mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
feat: form、crud、textarea、selecth支持外观配置 (#10649)
* feat(editor): 表单支持外观配置 * bugfix * 优化获取cssVar逻辑 * 优化外观默认值 * 删除外观继承相关逻辑 * 更新快照 * 表单布局 * 表单默认mode优化为flex * 优化colorpicker交互 * 优化编辑器表单布局配置 * 表单静态展示外观配置 * bugfix * feat: crud2支持外观配置 * crud 外观默认值 * bugfix * 多行文本支持外观配置 * 下拉框支持外观配置 * 修复table表头无法居中对齐问题 * style: 优化表格样式 * bugfix --------- Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
This commit is contained in:
parent
8e93124781
commit
d43922db81
@ -49,10 +49,15 @@ import LazyComponent from '../components/LazyComponent';
|
||||
import {isAlive} from 'mobx-state-tree';
|
||||
|
||||
import type {LabelAlign} from './Item';
|
||||
import {injectObjectChain} from '../utils';
|
||||
import {
|
||||
CustomStyleClassName,
|
||||
injectObjectChain,
|
||||
setThemeClassName
|
||||
} from '../utils';
|
||||
import {reaction} from 'mobx';
|
||||
import groupBy from 'lodash/groupBy';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import CustomStyle from '../components/CustomStyle';
|
||||
|
||||
export interface FormHorizontal {
|
||||
left?: number;
|
||||
@ -1958,6 +1963,11 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
staticClassName,
|
||||
static: isStatic = false,
|
||||
loadingConfig,
|
||||
themeCss,
|
||||
id,
|
||||
wrapperCustomStyle,
|
||||
env,
|
||||
wrapWithPanel,
|
||||
testid
|
||||
} = this.props;
|
||||
|
||||
@ -1986,7 +1996,25 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
`Form--${mode || 'normal'}`,
|
||||
columnCount ? `Form--column Form--column-${columnCount}` : null,
|
||||
staticClassName && isStatic ? staticClassName : className,
|
||||
isStatic ? 'Form--isStatic' : null
|
||||
isStatic ? 'Form--isStatic' : null,
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: [
|
||||
'formControlClassName',
|
||||
'itemClassName',
|
||||
'staticClassName',
|
||||
'itemLabelClassName'
|
||||
],
|
||||
id,
|
||||
themeCss
|
||||
}),
|
||||
!wrapWithPanel &&
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'wrapperCustomStyle',
|
||||
id,
|
||||
themeCss: wrapperCustomStyle
|
||||
})
|
||||
)}
|
||||
onSubmit={this.handleFormSubmit}
|
||||
noValidate
|
||||
@ -2060,6 +2088,69 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
show: store.drawerOpen
|
||||
}
|
||||
)}
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss,
|
||||
classNames: [
|
||||
wrapWithPanel && {
|
||||
key: 'panelClassName'
|
||||
},
|
||||
!wrapWithPanel && {
|
||||
key: 'formControlClassName'
|
||||
},
|
||||
{
|
||||
key: 'headerControlClassName',
|
||||
weights: {
|
||||
default: {
|
||||
parent: `.${cx('Panel')}`
|
||||
}
|
||||
}
|
||||
},
|
||||
wrapWithPanel && {
|
||||
key: 'headerTitleControlClassName'
|
||||
},
|
||||
wrapWithPanel && {
|
||||
key: 'bodyControlClassName'
|
||||
},
|
||||
wrapWithPanel && {
|
||||
key: 'actionsControlClassName',
|
||||
weights: {
|
||||
default: {
|
||||
parent: `.${cx('Panel--form')}`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'itemClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${cx('Form-item')}`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'staticClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${cx('Form-static')}`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'itemLabelClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${cx('Form-label')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
].filter(n => n) as CustomStyleClassName[],
|
||||
wrapperCustomStyle,
|
||||
id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</WrapperComponent>
|
||||
);
|
||||
}
|
||||
@ -2083,7 +2174,10 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
affixFooter,
|
||||
lazyLoad,
|
||||
translate: __,
|
||||
footer
|
||||
footer,
|
||||
id,
|
||||
wrapperCustomStyle,
|
||||
themeCss
|
||||
} = this.props;
|
||||
|
||||
let body: JSX.Element = this.renderBody();
|
||||
@ -2096,7 +2190,22 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
title: __(title)
|
||||
},
|
||||
{
|
||||
className: cx(panelClassName, 'Panel--form'),
|
||||
className: cx(
|
||||
panelClassName,
|
||||
'Panel--form',
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'wrapperCustomStyle',
|
||||
id,
|
||||
themeCss: wrapperCustomStyle
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'panelClassName',
|
||||
id,
|
||||
themeCss
|
||||
})
|
||||
),
|
||||
style: style,
|
||||
formStore: this.props.store,
|
||||
children: body,
|
||||
@ -2106,11 +2215,35 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
disabled: store.loading,
|
||||
btnDisabled: store.loading || store.validating,
|
||||
headerClassName,
|
||||
headerControlClassName: setThemeClassName({
|
||||
...this.props,
|
||||
name: 'headerControlClassName',
|
||||
id,
|
||||
themeCss
|
||||
}),
|
||||
headerTitleControlClassName: setThemeClassName({
|
||||
...this.props,
|
||||
name: 'headerTitleControlClassName',
|
||||
id,
|
||||
themeCss
|
||||
}),
|
||||
footer,
|
||||
footerClassName,
|
||||
footerWrapClassName,
|
||||
actionsClassName,
|
||||
actionsControlClassName: setThemeClassName({
|
||||
...this.props,
|
||||
name: 'actionsControlClassName',
|
||||
id,
|
||||
themeCss
|
||||
}),
|
||||
bodyClassName,
|
||||
bodyControlClassName: setThemeClassName({
|
||||
...this.props,
|
||||
name: 'bodyControlClassName',
|
||||
id,
|
||||
themeCss
|
||||
}),
|
||||
affixFooter
|
||||
}
|
||||
) as JSX.Element;
|
||||
|
@ -1224,7 +1224,9 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
const horizontal = props.horizontal || props.formHorizontal || {};
|
||||
const left = getWidthRate(horizontal.left);
|
||||
const right = getWidthRate(horizontal.right);
|
||||
const labelAlign = props.labelAlign || props.formLabelAlign;
|
||||
const labelAlign =
|
||||
(props.labelAlign !== 'inherit' && props.labelAlign) ||
|
||||
props.formLabelAlign;
|
||||
const labelWidth = props.labelWidth || props.formLabelWidth;
|
||||
|
||||
return (
|
||||
@ -1966,7 +1968,8 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
themeCss,
|
||||
id,
|
||||
wrapperCustomStyle,
|
||||
env
|
||||
env,
|
||||
classnames: cx
|
||||
} = this.props;
|
||||
const mode = this.props.mode || formMode;
|
||||
|
||||
@ -2004,7 +2007,13 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
themeCss: themeCss || css,
|
||||
classNames: [
|
||||
{
|
||||
key: 'labelClassName'
|
||||
key: 'labelClassName',
|
||||
weights: {
|
||||
default: {
|
||||
suf: `.${cx('Form-label')}`,
|
||||
parent: `.${cx('Form-item')}`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'descriptionClassName'
|
||||
@ -2222,10 +2231,10 @@ export function asFormItem(config: Omit<FormItemConfig, 'component'>) {
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const controlSize =
|
||||
size && ['xs', 'sm', 'md', 'lg', 'full'].includes(size)
|
||||
? size
|
||||
: defaultSize;
|
||||
const isRuleSize =
|
||||
size && ['xs', 'sm', 'md', 'lg', 'full'].includes(size);
|
||||
|
||||
const controlSize = isRuleSize ? size : defaultSize;
|
||||
|
||||
//@ts-ignore
|
||||
const isOpened = this.state.isOpened;
|
||||
@ -2246,6 +2255,9 @@ export function asFormItem(config: Omit<FormItemConfig, 'component'>) {
|
||||
ref={supportRef ? this.refFn : undefined}
|
||||
forwardedRef={supportRef ? undefined : this.refFn}
|
||||
formItem={model}
|
||||
style={{
|
||||
width: !isRuleSize && size ? size : undefined
|
||||
}}
|
||||
className={cx(
|
||||
`Form-control`,
|
||||
{
|
||||
|
@ -40,6 +40,7 @@ export const inheritValueMap: PlainObject = {
|
||||
|
||||
interface extra {
|
||||
important?: boolean;
|
||||
parent?: string;
|
||||
inner?: string;
|
||||
pre?: string;
|
||||
suf?: string;
|
||||
@ -179,7 +180,8 @@ export function formatStyle(
|
||||
default: '',
|
||||
hover: ':hover',
|
||||
active: ':hover:active',
|
||||
disabled: '.is-disabled'
|
||||
focused: '',
|
||||
disabled: ''
|
||||
};
|
||||
|
||||
for (let item of classNames) {
|
||||
@ -200,6 +202,7 @@ export function formatStyle(
|
||||
default: {},
|
||||
hover: {},
|
||||
active: {},
|
||||
focused: {},
|
||||
disabled: {}
|
||||
};
|
||||
Object.keys(body).forEach(key => {
|
||||
@ -210,6 +213,8 @@ export function formatStyle(
|
||||
statusMap.hover[key.replace(':hover', '')] = body[key];
|
||||
} else if (!!~key.indexOf(':active')) {
|
||||
statusMap.active[key.replace(':active', '')] = body[key];
|
||||
} else if (!!~key.indexOf(':focused')) {
|
||||
statusMap.focused[key.replace(':focused', '')] = body[key];
|
||||
} else if (!!~key.indexOf(':disabled')) {
|
||||
statusMap.disabled[key.replace(':disabled', '')] = body[key];
|
||||
} else {
|
||||
@ -269,11 +274,13 @@ export function formatStyle(
|
||||
if (styles.length > 0) {
|
||||
const cx = (weights?.pre || '') + className + (weights?.suf || '');
|
||||
const inner = weights?.inner || '';
|
||||
const parent = weights?.parent || '';
|
||||
|
||||
res.push({
|
||||
className: cx + status2string[status] + inner,
|
||||
content: `.${cx + status2string[status]} ${inner}{\n ${styles.join(
|
||||
'\n '
|
||||
)}\n}`
|
||||
className: parent + cx + status2string[status] + inner,
|
||||
content: `${parent} .${
|
||||
cx + status2string[status]
|
||||
} ${inner}{\n ${styles.join('\n ')}\n}`
|
||||
});
|
||||
// TODO:切换状态暂时先不改变组件的样式
|
||||
// if (['hover', 'active', 'disabled'].includes(status)) {
|
||||
@ -297,11 +304,12 @@ export interface CustomStyleClassName {
|
||||
default?: extra;
|
||||
hover?: extra;
|
||||
active?: extra;
|
||||
focused?: extra;
|
||||
disabled?: extra;
|
||||
};
|
||||
}
|
||||
|
||||
export function insertCustomStyle(prams: {
|
||||
export function insertCustomStyle(params: {
|
||||
themeCss: any;
|
||||
classNames: CustomStyleClassName[];
|
||||
id: string;
|
||||
@ -318,7 +326,7 @@ export function insertCustomStyle(prams: {
|
||||
customStyleClassPrefix,
|
||||
doc,
|
||||
data
|
||||
} = prams;
|
||||
} = params;
|
||||
if (!themeCss) {
|
||||
return;
|
||||
}
|
||||
@ -503,7 +511,7 @@ export function formatInputThemeCss(themeCss: any) {
|
||||
}
|
||||
|
||||
export function setThemeClassName(params: {
|
||||
name: string;
|
||||
name: string | string[];
|
||||
id?: string;
|
||||
themeCss: any;
|
||||
extra?: string;
|
||||
@ -514,17 +522,25 @@ export function setThemeClassName(params: {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (name !== 'wrapperCustomStyle' && !themeCss[name]) {
|
||||
return '';
|
||||
}
|
||||
let index = '';
|
||||
if (typeof data?.index === 'number') {
|
||||
index = `-${data.index}`;
|
||||
}
|
||||
|
||||
return (
|
||||
`${name}-${id.replace?.('u:', '') || id}` +
|
||||
(extra ? `-${extra}` : '') +
|
||||
index
|
||||
);
|
||||
function setClassName(name: string, id: string) {
|
||||
if (name !== 'wrapperCustomStyle' && !themeCss[name]) {
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
`${name}-${id.replace?.('u:', '') || id}` +
|
||||
(extra ? `-${extra}` : '') +
|
||||
index
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof name === 'string') {
|
||||
return setClassName(name, id);
|
||||
} else {
|
||||
return name.map(n => setClassName(n, id)).join(' ');
|
||||
}
|
||||
}
|
||||
|
@ -382,7 +382,7 @@
|
||||
}
|
||||
.action-desc {
|
||||
margin-left: 16px;
|
||||
color: var(--Form-item-fontColor);
|
||||
color: var(--Form-item-color);
|
||||
}
|
||||
|
||||
.cmpt-action-select,
|
||||
|
@ -54,6 +54,8 @@
|
||||
@import './style-control/style-common';
|
||||
@import './style-control/theme-css-code';
|
||||
@import './style-control/flex-layout';
|
||||
@import './style-control/col-count';
|
||||
@import './style-control/col-size';
|
||||
|
||||
/* 组件样式 */
|
||||
@import './components/button';
|
||||
|
@ -81,7 +81,7 @@
|
||||
label {
|
||||
flex-shrink: 0;
|
||||
margin-right: 8px;
|
||||
color: var(--Form-item-fontColor);
|
||||
color: var(--Form-item-color);
|
||||
}
|
||||
|
||||
.flex {
|
||||
|
30
packages/amis-editor-core/scss/style-control/_col-count.scss
Normal file
30
packages/amis-editor-core/scss/style-control/_col-count.scss
Normal file
@ -0,0 +1,30 @@
|
||||
.ColCount {
|
||||
display: flex;
|
||||
background-color: #f7f7f9;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
&-item {
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
&:not(.is-disabled):hover {
|
||||
background: #fff;
|
||||
color: #2468f2;
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
background: #fff;
|
||||
color: #2468f2;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.is-disabled {
|
||||
cursor: not-allowed;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
.LabelAlign {
|
||||
width: 100%;
|
||||
}
|
28
packages/amis-editor-core/scss/style-control/_col-size.scss
Normal file
28
packages/amis-editor-core/scss/style-control/_col-size.scss
Normal file
@ -0,0 +1,28 @@
|
||||
.ColSize {
|
||||
display: flex;
|
||||
background-color: #f7f7f9;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
&-item {
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
width: 32px;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
&:not(.is-disabled):hover {
|
||||
background: #fff;
|
||||
color: #2468f2;
|
||||
}
|
||||
}
|
||||
.is-active {
|
||||
background: #fff;
|
||||
color: #2468f2;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.is-disabled {
|
||||
cursor: not-allowed;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
@ -54,6 +54,7 @@ export {
|
||||
|
||||
export let themeConfig: any = {};
|
||||
export let themeOptionsData: any = {};
|
||||
export let cssVars: any = {};
|
||||
|
||||
export function __uri(id: string) {
|
||||
return id;
|
||||
@ -1180,11 +1181,52 @@ export function setThemeConfig(config: any) {
|
||||
themeConfig = config;
|
||||
themeOptionsData = getGlobalData(themeConfig);
|
||||
themeUselessPropKeys = Object.keys(getThemeConfig());
|
||||
cssVars = getAllCssVar();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件的css变量
|
||||
* @param id 组件id
|
||||
* @param selectorText 选择器
|
||||
* @returns css变量
|
||||
*/
|
||||
export function getCssVarById(id: string, selectorText: string) {
|
||||
const styleSheets = document.styleSheets;
|
||||
let cssVars: PlainObject = {};
|
||||
for (const styleSheet of styleSheets) {
|
||||
if ((styleSheet.ownerNode as Element)?.id === id) {
|
||||
for (let i = 0; i < styleSheet.cssRules.length; i++) {
|
||||
const cssRule = styleSheet.cssRules[i] as any;
|
||||
if ((cssRule as any).selectorText?.includes(selectorText)) {
|
||||
const cssText = cssRule.style.cssText;
|
||||
const cssArr = cssText.split('; ');
|
||||
cssArr.forEach((item: string) => {
|
||||
if (item) {
|
||||
const [key, value] = item.split(': ');
|
||||
cssVars[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cssVars;
|
||||
}
|
||||
|
||||
export function getAllCssVar() {
|
||||
const cssVars = getCssVarById('baseStyle', ':root, .AMISCSSWrapper');
|
||||
const themeCssVars = getCssVarById(
|
||||
'themeCss',
|
||||
'.app-popover, #editor-preview-body'
|
||||
);
|
||||
|
||||
return Object.assign({}, cssVars, themeCssVars);
|
||||
}
|
||||
|
||||
// 获取主题数据和样式选择器数据
|
||||
export function getThemeConfig() {
|
||||
return {themeConfig, ...themeOptionsData};
|
||||
return {themeConfig, ...themeOptionsData, cssVars};
|
||||
}
|
||||
|
||||
const backgroundMap: PlainObject = {
|
||||
|
@ -26,7 +26,12 @@
|
||||
rel="stylesheet"
|
||||
href="../../../node_modules/@fortawesome/fontawesome-free/css/v4-shims.css"
|
||||
/>
|
||||
<link rel="stylesheet" title="cxd" href="../amis-ui/scss/themes/cxd.scss" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
title="cxd"
|
||||
id="baseStyle"
|
||||
href="../amis-ui/scss/themes/cxd.scss"
|
||||
/>
|
||||
<link rel="stylesheet" title="cxd" href="../amis-ui/scss/helper.scss" />
|
||||
<link rel="stylesheet" href="../amis-editor-core/scss/editor.scss" />
|
||||
<link rel="stylesheet" href="../../../examples/doc.css" />
|
||||
|
@ -614,16 +614,18 @@ export class ApiDSBuilder extends DSBuilder<
|
||||
id,
|
||||
type: 'form',
|
||||
title: '表单',
|
||||
mode: 'horizontal',
|
||||
mode: 'flex',
|
||||
labelAlign: 'top',
|
||||
dsType: this.key,
|
||||
feat: feat,
|
||||
body: fields.map(f => {
|
||||
body: fields.map((f, index) => {
|
||||
const type = f.inputType
|
||||
? displayType2inputType(f.inputType) ?? 'input-text'
|
||||
: 'input-text';
|
||||
|
||||
return {
|
||||
...pick(f, ['name', 'label']),
|
||||
row: index,
|
||||
type,
|
||||
...this.appendSchema2InputControl(type)
|
||||
};
|
||||
|
@ -45,6 +45,9 @@ import './renderer/event-control/index';
|
||||
import './renderer/TreeOptionControl';
|
||||
import './renderer/TransferTableControl';
|
||||
import './renderer/style-control/ThemeCssCode';
|
||||
import './renderer/style-control/ColCount';
|
||||
import './renderer/style-control/ColSize';
|
||||
import './renderer/style-control/LabelAlign';
|
||||
import './renderer/ButtonGroupControl';
|
||||
import './renderer/FlexSettingControl';
|
||||
import './renderer/FieldSetting';
|
||||
|
@ -139,10 +139,11 @@ export class ButtonPlugin extends BasePlugin {
|
||||
label: '文字',
|
||||
name: `themeCss.className.font:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: [
|
||||
`button1.type.\${level}.${state}.body.font-color`,
|
||||
`button1.size.\${size}.body.font`
|
||||
]
|
||||
editorValueToken: {
|
||||
'color': `--button-\${level || "default"}-${state}-font-color`,
|
||||
'*': '--button-size-${size || "default"}'
|
||||
},
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
@ -151,28 +152,33 @@ export class ButtonPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `button1.type.\${level}.${state}.body.bg-color`
|
||||
editorValueToken: `--button-\${level || "default"}-${state}-bg-color`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `themeCss.className.border:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `button1.type.\${level}.${state}.body.border`
|
||||
editorValueToken: `--button-\${level || "default"}-${state}`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: `themeCss.className.padding-and-margin:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `button1.size.\${size}.body.padding-and-margin`
|
||||
editorValueToken: '--button-size-${size || "default"}',
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:radius', {
|
||||
name: `themeCss.className.radius:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `button1.size.\${size}.body.border`
|
||||
editorValueToken: '--button-size-${size || "default"}',
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:select', {
|
||||
label: '图标尺寸',
|
||||
name: `themeCss.iconClassName.iconSize:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `button1.size.\${size}.body.icon-size`
|
||||
editorValueToken: '--button-size-${size || "default"}-icon-size',
|
||||
state
|
||||
})
|
||||
];
|
||||
};
|
||||
|
@ -483,7 +483,7 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
baseCRUDPanelBody = (context: BuildPanelEventContext) => {
|
||||
return getSchemaTpl('tabs', [
|
||||
this.renderPropsTab(context),
|
||||
this.renderStylesTab(context),
|
||||
// this.renderStylesTab(context),
|
||||
this.renderEventTab(context)
|
||||
]);
|
||||
};
|
||||
|
@ -123,7 +123,13 @@ export class FormPlugin extends BasePlugin {
|
||||
label: '表单集合',
|
||||
matchRegion: (elem: JSX.Element) => !!elem?.props.noValidate,
|
||||
renderMethod: 'renderBody',
|
||||
preferTag: '表单项'
|
||||
preferTag: '表单项',
|
||||
dndMode: (schema: any) => {
|
||||
if (schema.mode === 'flex') {
|
||||
return 'flex';
|
||||
}
|
||||
return 'default';
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@ -1091,12 +1097,66 @@ export class FormPlugin extends BasePlugin {
|
||||
{
|
||||
title: '布局',
|
||||
body: [
|
||||
getSchemaTpl('formItemMode', {
|
||||
isForm: true,
|
||||
/** Form组件默认为normal模式 */
|
||||
defaultValue: 'normal'
|
||||
}),
|
||||
getSchemaTpl('horizontal'),
|
||||
{
|
||||
label: '布局',
|
||||
name: 'mode',
|
||||
type: 'select',
|
||||
pipeIn: defaultValue('flex'),
|
||||
options: [
|
||||
{
|
||||
label: '网格',
|
||||
value: 'flex'
|
||||
},
|
||||
{
|
||||
label: '内联',
|
||||
value: 'inline'
|
||||
},
|
||||
{
|
||||
label: '水平',
|
||||
value: 'horizontal'
|
||||
},
|
||||
{
|
||||
label: '垂直',
|
||||
value: 'normal'
|
||||
}
|
||||
],
|
||||
pipeOut: (v: string) => (v ? v : undefined),
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: string,
|
||||
model: any,
|
||||
form: any
|
||||
) => {
|
||||
const body = [...form.data.body];
|
||||
let temp = body;
|
||||
if (value === 'flex') {
|
||||
temp = body?.map((item: any, index: number) => {
|
||||
return {
|
||||
...item,
|
||||
row: index,
|
||||
mode: undefined
|
||||
};
|
||||
});
|
||||
} else {
|
||||
temp = body?.map((item: any, index: number) => {
|
||||
return {
|
||||
...item,
|
||||
row: undefined,
|
||||
colSize: undefined,
|
||||
labelAlign: undefined,
|
||||
mode: undefined
|
||||
};
|
||||
});
|
||||
}
|
||||
form.setValueByName('body', temp);
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'col-count',
|
||||
name: '__rolCount',
|
||||
label: tipedLabel('列数', '仅对PC页面生效'),
|
||||
visibleOn: 'this.mode === "flex"'
|
||||
},
|
||||
{
|
||||
label: '列数',
|
||||
name: 'columnCount',
|
||||
@ -1106,6 +1166,7 @@ export class FormPlugin extends BasePlugin {
|
||||
precision: 0,
|
||||
resetValue: '',
|
||||
unitOptions: ['列'],
|
||||
hiddenOn: 'this.mode === "flex"',
|
||||
pipeOut: (value: string) => {
|
||||
if (value && typeof value === 'string') {
|
||||
const count = Number.parseInt(
|
||||
@ -1120,12 +1181,7 @@ export class FormPlugin extends BasePlugin {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
body: [
|
||||
},
|
||||
getSchemaTpl('switch', {
|
||||
name: 'wrapWithPanel',
|
||||
label: tipedLabel(
|
||||
@ -1144,6 +1200,142 @@ export class FormPlugin extends BasePlugin {
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:base', {
|
||||
classname: 'formControlClassName',
|
||||
title: '表单样式',
|
||||
needState: false,
|
||||
hiddenOn: isWrapped
|
||||
}),
|
||||
getSchemaTpl('theme:base', {
|
||||
classname: 'panelClassName',
|
||||
title: 'Panel样式',
|
||||
editorValueToken: '--Panel',
|
||||
hidePadding: true,
|
||||
needState: false,
|
||||
visibleOn: isWrapped
|
||||
}),
|
||||
getSchemaTpl('theme:base', {
|
||||
classname: 'headerControlClassName',
|
||||
title: '标题区样式',
|
||||
visibleOn: isWrapped,
|
||||
editorValueToken: '--Panel-heading',
|
||||
hideRadius: true,
|
||||
hideShadow: true,
|
||||
hideMargin: true,
|
||||
needState: false,
|
||||
extra: [
|
||||
getSchemaTpl('theme:font', {
|
||||
name: 'themeCss.headerTitleControlClassName.font',
|
||||
editorValueToken: '--Panel-heading'
|
||||
})
|
||||
]
|
||||
}),
|
||||
|
||||
getSchemaTpl('theme:base', {
|
||||
classname: 'bodyControlClassName',
|
||||
title: '内容区样式',
|
||||
editorValueToken: '--Panel-body',
|
||||
hideRadius: true,
|
||||
hideShadow: true,
|
||||
hideBorder: true,
|
||||
hideMargin: true,
|
||||
hideBackground: true,
|
||||
needState: false,
|
||||
visibleOn: isWrapped
|
||||
}),
|
||||
{
|
||||
title: '表单项样式',
|
||||
body: [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'labelAlign',
|
||||
label: '标题位置',
|
||||
selectFirst: true,
|
||||
hiddenOn:
|
||||
'this.mode === "normal" || this.mode === "inline" || this.mode === "horizontal"',
|
||||
options: [
|
||||
{
|
||||
label: '上下布局',
|
||||
value: 'top'
|
||||
},
|
||||
{
|
||||
label: '水平居左',
|
||||
value: 'left'
|
||||
},
|
||||
{
|
||||
label: '水平居右',
|
||||
value: 'right'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
name: 'labelAlign',
|
||||
label: '标题位置',
|
||||
selectFirst: true,
|
||||
hiddenOn:
|
||||
'this.mode === "normal" || this.mode === "inline" || this.mode === "flex"',
|
||||
options: [
|
||||
{
|
||||
label: '水平居左',
|
||||
value: 'left'
|
||||
},
|
||||
{
|
||||
label: '水平居右',
|
||||
value: 'right'
|
||||
}
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:select', {
|
||||
label: '标题宽度',
|
||||
name: 'labelWidth',
|
||||
hiddenOn:
|
||||
'this.mode === "normal" || this.labelAlign === "top"'
|
||||
}),
|
||||
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '标题文字',
|
||||
editorValueToken: '--Form-item',
|
||||
hasSenior: false,
|
||||
name: 'themeCss.itemLabelClassName.font'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '标题边距',
|
||||
hidePadding: true,
|
||||
name: 'themeCss.itemLabelClassName.padding-and-margin'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '表单项边距',
|
||||
hidePadding: true,
|
||||
name: 'themeCss.itemClassName.padding-and-margin'
|
||||
}),
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '静态展示文字',
|
||||
editorValueToken: '--Form-static',
|
||||
name: 'themeCss.staticClassName.font',
|
||||
visibleOn: '!!this.static || !!this.staticOn'
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:base', {
|
||||
classname: 'actionsControlClassName',
|
||||
title: '操作区样式',
|
||||
editorValueToken: '--Panel-footer',
|
||||
hideRadius: true,
|
||||
hideShadow: true,
|
||||
hideMargin: true,
|
||||
needState: false,
|
||||
visibleOn: isWrapped
|
||||
}),
|
||||
{
|
||||
title: '自定义样式',
|
||||
body: [
|
||||
{
|
||||
type: 'theme-cssCode',
|
||||
label: false
|
||||
}
|
||||
]
|
||||
},
|
||||
/** */
|
||||
getSchemaTpl('style:classNames', {
|
||||
isFormItem: false,
|
||||
|
@ -13,20 +13,20 @@ import {ValidatorTag} from '../../validator';
|
||||
|
||||
const addBtnCssClassName = 'themeCss.addBtnControlClassName';
|
||||
const IconCssClassName = 'themeCss.iconControlClassName';
|
||||
const editorPath = 'inputImage.base';
|
||||
const editorPath = '--inputImage-base';
|
||||
const inputStateFunc = (visibleOn: string, state: string) => {
|
||||
return [
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `${addBtnCssClassName}.border:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${editorPath}.${state}.body.border`
|
||||
editorValueToken: `${editorPath}-${state}`
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '文字',
|
||||
name: `${addBtnCssClassName}.color:${state}`,
|
||||
labelMode: 'input',
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${editorPath}.${state}.body.color`
|
||||
editorValueToken: `${editorPath}-${state}-color`
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
@ -35,14 +35,14 @@ const inputStateFunc = (visibleOn: string, state: string) => {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${editorPath}.${state}.body.bg-color`
|
||||
editorValueToken: `${editorPath}-${state}-bg-color`
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '图标',
|
||||
name: `${addBtnCssClassName}.icon-color:${state}`,
|
||||
labelMode: 'input',
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${editorPath}.${state}.body.icon-color`
|
||||
editorValueToken: `${editorPath}-${state}-icon-color`
|
||||
})
|
||||
];
|
||||
};
|
||||
@ -506,7 +506,7 @@ export class ImageControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('theme:radius', {
|
||||
name: `${addBtnCssClassName}.border-radius`,
|
||||
label: '圆角',
|
||||
editorThemePath: `${editorPath}.default.body.border`
|
||||
editorValueToken: `${editorPath}-default`
|
||||
}),
|
||||
{
|
||||
name: `${addBtnCssClassName}.--inputImage-base-default-icon`,
|
||||
@ -517,12 +517,12 @@ export class ImageControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('theme:select', {
|
||||
name: `${IconCssClassName}.iconSize`,
|
||||
label: '图标大小',
|
||||
editorThemePath: `${editorPath}.default.body.icon-size`
|
||||
editorValueToken: `${editorPath}-default-icon-size`
|
||||
}),
|
||||
getSchemaTpl('theme:select', {
|
||||
name: `${IconCssClassName}.margin-bottom`,
|
||||
label: '图标底边距',
|
||||
editorThemePath: `${editorPath}.default.body.icon-margin`
|
||||
editorValueToken: `${editorPath}-default-icon-margin`
|
||||
})
|
||||
]
|
||||
},
|
||||
|
@ -289,8 +289,7 @@ export class NumberControlPlugin extends BasePlugin {
|
||||
getSchemaTpl(
|
||||
'collapseGroup',
|
||||
[
|
||||
getSchemaTpl('style:formItem', {
|
||||
renderer: context.info.renderer,
|
||||
getSchemaTpl('theme:formItem', {
|
||||
schema: [
|
||||
{
|
||||
label: '快捷编辑',
|
||||
@ -317,7 +316,7 @@ export class NumberControlPlugin extends BasePlugin {
|
||||
body: [
|
||||
...inputStateTpl(
|
||||
'themeCss.inputControlClassName',
|
||||
'inputNumber.base.base'
|
||||
'--inputNumber-${displayMode || "base"}'
|
||||
)
|
||||
]
|
||||
},
|
||||
|
@ -416,7 +416,7 @@ export class TextControlPlugin extends BasePlugin {
|
||||
body: getSchemaTpl(
|
||||
'collapseGroup',
|
||||
[
|
||||
getSchemaTpl('style:formItem', {renderer}),
|
||||
getSchemaTpl('theme:formItem'),
|
||||
getSchemaTpl('theme:form-label'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
{
|
||||
@ -424,7 +424,7 @@ export class TextControlPlugin extends BasePlugin {
|
||||
body: [
|
||||
...inputStateTpl(
|
||||
'themeCss.inputControlClassName',
|
||||
'input.base.default'
|
||||
'--input-default'
|
||||
)
|
||||
]
|
||||
},
|
||||
|
@ -134,10 +134,14 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
panelTitle = '列表选取';
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
const pickStyleStateFunc = (visibleOn: string, state: string) => {
|
||||
const cssToken =
|
||||
state === 'default'
|
||||
? 'base'
|
||||
: `status-${state === 'focused' ? 'focus' : state}`;
|
||||
return [
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `themeCss.pickControlClassName.border:${state}`,
|
||||
editorThemePath: `pick.status.body.${state}-border`,
|
||||
editorValueToken: `--Pick-${cssToken}`,
|
||||
visibleOn: visibleOn
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
@ -146,43 +150,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: `themeCss.pickControlClassName.background:${state}`,
|
||||
editorThemePath: `pick.status.body.${state}-bgColor`,
|
||||
visibleOn: visibleOn
|
||||
})
|
||||
];
|
||||
};
|
||||
const pickDisabledSateFunc = (visibleOn: string, state: string) => {
|
||||
return [
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `themeCss.pickControlDisabledClassName.border`,
|
||||
editorThemePath: `pick.status.body.${state}-border`,
|
||||
visibleOn: visibleOn
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
labelMode: 'input',
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: `themeCss.pickControlDisabledClassName.background`,
|
||||
editorThemePath: `pick.status.body.${state}-bgColor`,
|
||||
visibleOn: visibleOn
|
||||
})
|
||||
];
|
||||
};
|
||||
const pickStyleFunc = (visibleOn: string, state: string) => {
|
||||
return [
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `themeCss.pickControlClassName.border:${state}`,
|
||||
editorThemePath: `pick.base.body.border`,
|
||||
visibleOn: visibleOn
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
labelMode: 'input',
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: `themeCss.pickControlClassName.background:${state}`,
|
||||
editorThemePath: `pick.base.body.bgColor`,
|
||||
editorValueToken: `--Pick-${cssToken}-bgColor`,
|
||||
visibleOn: visibleOn
|
||||
})
|
||||
];
|
||||
@ -494,7 +462,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
},
|
||||
{
|
||||
label: '聚焦',
|
||||
value: 'focus'
|
||||
value: 'focused'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
@ -502,13 +470,16 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
}
|
||||
]
|
||||
},
|
||||
...pickStyleFunc(
|
||||
...pickStyleStateFunc(
|
||||
"${__editorState == 'default' || !__editorState}",
|
||||
'default'
|
||||
),
|
||||
...pickStyleStateFunc("${__editorState == 'hover'}", 'hover'),
|
||||
...pickStyleStateFunc("${__editorState == 'focus'}", 'active'),
|
||||
...pickDisabledSateFunc(
|
||||
...pickStyleStateFunc(
|
||||
"${__editorState == 'focused'}",
|
||||
'focused'
|
||||
),
|
||||
...pickStyleStateFunc(
|
||||
"${__editorState == 'disabled'}",
|
||||
'disabled'
|
||||
)
|
||||
@ -519,7 +490,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
body: [
|
||||
getSchemaTpl('theme:font', {
|
||||
name: 'themeCss.pickFontClassName.font:default',
|
||||
editorThemePath: 'pick.base.body.value-font'
|
||||
editorValueToken: '--Pick-base-value'
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
@ -527,15 +498,15 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: 'themeCss.pickValueWrapClassName.background',
|
||||
editorThemePath: 'pick.base.body.value-bgColor'
|
||||
editorValueToken: '--Pick-base-value-bgColor'
|
||||
}),
|
||||
getSchemaTpl('theme:border', {
|
||||
name: 'themeCss.pickValueWrapClassName.border:default',
|
||||
editorThemePath: 'pick.base.body.value-border'
|
||||
editorValueToken: '--Pick-base-value'
|
||||
}),
|
||||
getSchemaTpl('theme:radius', {
|
||||
name: 'themeCss.pickValueWrapClassName.radius',
|
||||
editorThemePath: 'pick.base.body.value-radius'
|
||||
editorValueToken: '--Pick-base'
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '图标颜色',
|
||||
@ -543,7 +514,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: 'themeCss.pickValueIconClassName.color',
|
||||
editorThemePath: 'pick.base.body.value-icon-color'
|
||||
editorValueToken: '--Pick-base-value-icon-color'
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '图标hover颜色',
|
||||
@ -551,7 +522,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: 'themeCss.pickValueIconClassName.color:hover',
|
||||
editorThemePath: 'pick.base.body.value-hover-icon-color'
|
||||
editorValueToken: '--Pick-base-value-hover-icon-color'
|
||||
})
|
||||
]
|
||||
},
|
||||
@ -568,7 +539,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
// getSchemaTpl('theme:size', {
|
||||
// name: 'themeCss.pickControlClassName.--Pick-base-icon-size',
|
||||
// label: '图标大小',
|
||||
// editorThemePath: `default.body.icon-size`
|
||||
// editorValueToken: `default.body.icon-size`
|
||||
// }),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '颜色',
|
||||
@ -576,7 +547,7 @@ export class PickerControlPlugin extends BasePlugin {
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
name: 'themeCss.pickIconClassName.color',
|
||||
editorThemePath: 'pick.base.body.icon-color'
|
||||
editorValueToken: '--Pick-base-icon-color'
|
||||
})
|
||||
]
|
||||
},
|
||||
|
@ -28,6 +28,7 @@ import type {
|
||||
BaseEventContext,
|
||||
EditorManager
|
||||
} from 'amis-editor-core';
|
||||
import {inputStateTpl} from '../../renderer/style-control/helper';
|
||||
|
||||
export class SelectControlPlugin extends BasePlugin {
|
||||
static id = 'SelectControlPlugin';
|
||||
@ -301,7 +302,29 @@ export class SelectControlPlugin extends BasePlugin {
|
||||
title: '外观',
|
||||
body: [
|
||||
getSchemaTpl('collapseGroup', [
|
||||
getSchemaTpl('style:formItem', {renderer: context.info.renderer}),
|
||||
getSchemaTpl('theme:formItem'),
|
||||
getSchemaTpl('theme:form-label'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
{
|
||||
title: '选择框样式',
|
||||
body: [
|
||||
...inputStateTpl('themeCss.selectControlClassName', '--select')
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '下拉框样式',
|
||||
body: [
|
||||
...inputStateTpl(
|
||||
'themeCss.selectPopoverClassName',
|
||||
'--select',
|
||||
{
|
||||
state: ['default', 'hover', 'focused']
|
||||
}
|
||||
)
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:cssCode'),
|
||||
getSchemaTpl('style:classNames')
|
||||
])
|
||||
]
|
||||
|
@ -6,6 +6,7 @@ import type {BaseEventContext} from 'amis-editor-core';
|
||||
import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {inputStateTpl} from '../../renderer/style-control/helper';
|
||||
|
||||
export class TextareaControlPlugin extends BasePlugin {
|
||||
static id = 'TextareaControlPlugin';
|
||||
@ -183,8 +184,7 @@ export class TextareaControlPlugin extends BasePlugin {
|
||||
title: '外观',
|
||||
body: [
|
||||
getSchemaTpl('collapseGroup', [
|
||||
getSchemaTpl('style:formItem', {
|
||||
renderer: context.info.renderer,
|
||||
getSchemaTpl('theme:formItem', {
|
||||
schema: [
|
||||
{
|
||||
type: 'input-number',
|
||||
@ -200,6 +200,18 @@ export class TextareaControlPlugin extends BasePlugin {
|
||||
}
|
||||
]
|
||||
}),
|
||||
getSchemaTpl('theme:form-label'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
{
|
||||
title: '多行文本样式',
|
||||
body: [
|
||||
...inputStateTpl(
|
||||
'themeCss.inputControlClassName',
|
||||
'--input-textarea'
|
||||
)
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:cssCode'),
|
||||
getSchemaTpl('style:classNames')
|
||||
])
|
||||
]
|
||||
|
@ -355,20 +355,22 @@ export class ImagePlugin extends BasePlugin {
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '标题文字',
|
||||
name: 'themeCss.titleControlClassName.font',
|
||||
editorThemePath: 'image.image.default.normal.body.font'
|
||||
editorValueToken: '--image-image-normal'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '标题边距',
|
||||
name: 'themeCss.titleControlClassName.padding-and-margin'
|
||||
name: 'themeCss.titleControlClassName.padding-and-margin',
|
||||
editorValueToken: '--image-image-normal-title'
|
||||
}),
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '描述文字',
|
||||
name: 'themeCss.desControlClassName.font',
|
||||
editorThemePath: 'image.image.default.description.body.font'
|
||||
editorValueToken: '--image-image-description'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '描述边距',
|
||||
name: 'themeCss.desControlClassName.padding-and-margin'
|
||||
name: 'themeCss.desControlClassName.padding-and-margin',
|
||||
editorValueToken: '--image-image-description'
|
||||
}),
|
||||
{
|
||||
name: 'themeCss.iconControlClassName.--image-image-normal-icon',
|
||||
|
@ -1000,19 +1000,6 @@ export class Table2Plugin extends BasePlugin {
|
||||
{
|
||||
title: '行设置',
|
||||
body: [
|
||||
{
|
||||
name: 'lineHeight',
|
||||
label: '行高度',
|
||||
type: 'select',
|
||||
placeholder: '请选择高度',
|
||||
options: [
|
||||
{label: '跟随内容', value: ''},
|
||||
{label: '高', value: 'large'},
|
||||
{label: '中', value: 'middle'}
|
||||
],
|
||||
clearable: false,
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
type: 'ae-Switch-More',
|
||||
mode: 'normal',
|
||||
@ -1337,31 +1324,31 @@ export class Table2Plugin extends BasePlugin {
|
||||
{
|
||||
title: '基本',
|
||||
body: [
|
||||
getSchemaTpl('switch', {
|
||||
name: 'bordered',
|
||||
label: '边框',
|
||||
pipeIn: defaultValue(false)
|
||||
}),
|
||||
{
|
||||
name: 'size',
|
||||
label: '控件尺寸',
|
||||
type: 'select',
|
||||
pipeIn: defaultValue('default'),
|
||||
options: [
|
||||
{
|
||||
label: '小',
|
||||
value: 'small'
|
||||
},
|
||||
{
|
||||
label: '默认',
|
||||
value: 'default'
|
||||
},
|
||||
{
|
||||
label: '大',
|
||||
value: 'large'
|
||||
}
|
||||
]
|
||||
},
|
||||
// getSchemaTpl('switch', {
|
||||
// name: 'bordered',
|
||||
// label: '边框',
|
||||
// pipeIn: defaultValue(false)
|
||||
// }),
|
||||
// {
|
||||
// name: 'size',
|
||||
// label: '控件尺寸',
|
||||
// type: 'select',
|
||||
// pipeIn: defaultValue('default'),
|
||||
// options: [
|
||||
// {
|
||||
// label: '小',
|
||||
// value: 'small'
|
||||
// },
|
||||
// {
|
||||
// label: '默认',
|
||||
// value: 'default'
|
||||
// },
|
||||
// {
|
||||
// label: '大',
|
||||
// value: 'large'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
getSchemaTpl('switch', {
|
||||
name: 'autoFillHeight',
|
||||
label: '高度自适应'
|
||||
@ -1384,20 +1371,10 @@ export class Table2Plugin extends BasePlugin {
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'input-group',
|
||||
type: 'amis-theme-select',
|
||||
name: 'scroll.y',
|
||||
visibleOn: 'this.scroll && this.scroll.y !== null',
|
||||
label: '高度值',
|
||||
body: [
|
||||
{
|
||||
type: 'input-number',
|
||||
name: 'scroll.y'
|
||||
},
|
||||
{
|
||||
type: 'tpl',
|
||||
addOnclassName: 'border-0 bg-none',
|
||||
tpl: 'px'
|
||||
}
|
||||
]
|
||||
label: '高度值'
|
||||
},
|
||||
|
||||
{
|
||||
@ -1422,21 +1399,10 @@ export class Table2Plugin extends BasePlugin {
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'input-group',
|
||||
visibleOn: 'this.scroll && this.scroll.x !== null',
|
||||
type: 'amis-theme-select',
|
||||
name: 'scroll.x',
|
||||
label: '宽度值',
|
||||
body: [
|
||||
{
|
||||
type: 'input-number',
|
||||
name: 'scroll.x'
|
||||
},
|
||||
{
|
||||
type: 'tpl',
|
||||
addOnclassName: 'border-0 bg-none',
|
||||
tpl: 'px'
|
||||
}
|
||||
]
|
||||
visibleOn: 'this.scroll && this.scroll.x !== null',
|
||||
label: '宽度值'
|
||||
},
|
||||
{
|
||||
name: 'indentSize',
|
||||
@ -1464,7 +1430,84 @@ export class Table2Plugin extends BasePlugin {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '表头',
|
||||
body: [
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
name: 'themeCss.tableHeadClassname.background',
|
||||
needCustom: true,
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
labelMode: 'input',
|
||||
label: '背景',
|
||||
editorValueToken: '--table-header-bg-color'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: 'themeCss.tableHeadClassname.paddingAndMargin',
|
||||
hideMargin: true,
|
||||
editorValueToken: '--table'
|
||||
}),
|
||||
getSchemaTpl('theme:border', {
|
||||
name: 'themeCss.tableHeadClassname.border',
|
||||
label: '边框',
|
||||
editorValueToken: {
|
||||
'rightBorderColor': '--Table-thead-borderColor',
|
||||
'rightBorderWidth': '--Table-thead-borderWidth',
|
||||
'*': '--table-header'
|
||||
}
|
||||
}),
|
||||
getSchemaTpl('theme:font', {
|
||||
name: 'themeCss.tableHeadClassname.font',
|
||||
editorValueToken: '--table-header'
|
||||
})
|
||||
]
|
||||
},
|
||||
|
||||
getSchemaTpl('theme:base', {
|
||||
title: '单元格',
|
||||
classname: 'tableBodyClassname',
|
||||
editorValueToken: '--table-body',
|
||||
hideShadow: true,
|
||||
hideRadius: true,
|
||||
hideBorder: true,
|
||||
hidePaddingAndMargin: true,
|
||||
state: ['default', 'hover'],
|
||||
extra: [
|
||||
{
|
||||
type: 'amis-theme-select',
|
||||
label: '行高',
|
||||
name: 'themeCss.tableBodyClassname.height',
|
||||
editorValueToken: '--table-body-line-height',
|
||||
mode: 'default'
|
||||
},
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: 'themeCss.tableRowClassname.paddingAndMargin',
|
||||
hideMargin: true,
|
||||
editorValueToken: '--table'
|
||||
}),
|
||||
getSchemaTpl('theme:border', {
|
||||
name: 'themeCss.tableRowClassname.border',
|
||||
editorValueToken: {
|
||||
'bottomBorderColor': '--Table-borderColor',
|
||||
'bottomBorderWidth': '--Table-borderWidth',
|
||||
'*': '--table'
|
||||
}
|
||||
}),
|
||||
getSchemaTpl('theme:font', {
|
||||
name: 'themeCss.tableBodyClassname.font',
|
||||
editorValueToken: '--table-body'
|
||||
})
|
||||
]
|
||||
}),
|
||||
{
|
||||
title: '自定义样式',
|
||||
body: [
|
||||
{
|
||||
type: 'theme-cssCode',
|
||||
label: false
|
||||
}
|
||||
]
|
||||
},
|
||||
getSchemaTpl('style:classNames', {
|
||||
isFormItem: false,
|
||||
schema: [
|
||||
|
@ -722,17 +722,17 @@ export class TableCell2Plugin extends BasePlugin {
|
||||
}
|
||||
].filter(Boolean)
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '外观',
|
||||
body: [
|
||||
getSchemaTpl('className'),
|
||||
getSchemaTpl('className', {
|
||||
name: 'innerClassName',
|
||||
label: '内部 CSS 类名'
|
||||
})
|
||||
]
|
||||
}
|
||||
// {
|
||||
// title: '外观',
|
||||
// body: [
|
||||
// getSchemaTpl('className'),
|
||||
// getSchemaTpl('className', {
|
||||
// name: 'innerClassName',
|
||||
// label: '内部 CSS 类名'
|
||||
// })
|
||||
// ]
|
||||
// }
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
61
packages/amis-editor/src/renderer/style-control/ColCount.tsx
Normal file
61
packages/amis-editor/src/renderer/style-control/ColCount.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import {FormControlProps, FormItem} from 'amis-core';
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
const colCount = [1, 2, 3, 4];
|
||||
|
||||
const ColCount: React.FC<FormControlProps> = props => {
|
||||
const [value, setValue] = React.useState(props.value);
|
||||
|
||||
function handleClick(value: number) {
|
||||
const store = props.manager.store;
|
||||
const body = [...(props.data.body || [])];
|
||||
let row = 0;
|
||||
let count = value;
|
||||
for (let i = 0; i < body.length; i++) {
|
||||
// 需要独占一行的组件
|
||||
if (body[i].$$dragMode === 'hv') {
|
||||
count = value;
|
||||
body[i] = {
|
||||
...body[i],
|
||||
row: ++row
|
||||
};
|
||||
row++;
|
||||
} else {
|
||||
count--;
|
||||
body[i] = {
|
||||
...body[i],
|
||||
row,
|
||||
colSize: value > 1 ? `1/${value}` : '1'
|
||||
};
|
||||
if (count === 0) {
|
||||
row++;
|
||||
count = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
props.setValue(body, 'body');
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ColCount">
|
||||
{colCount.map(n => (
|
||||
<div
|
||||
key={n}
|
||||
className={cx('ColCount-item', value === n && 'is-active')}
|
||||
onClick={() => handleClick(n)}
|
||||
>
|
||||
{n}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@FormItem({type: 'col-count', strictMode: false})
|
||||
export class ColCountRenderer extends React.Component<FormControlProps> {
|
||||
render() {
|
||||
return <ColCount {...this.props} />;
|
||||
}
|
||||
}
|
154
packages/amis-editor/src/renderer/style-control/ColSize.tsx
Normal file
154
packages/amis-editor/src/renderer/style-control/ColSize.tsx
Normal file
@ -0,0 +1,154 @@
|
||||
import {FormControlProps, FormItem} from 'amis-core';
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
import {JSONUpdate} from 'amis-editor-core';
|
||||
|
||||
const baseColSize = ['1/4', '1/3', '1/2', '2/3', '3/4', '1'];
|
||||
|
||||
const colSizeMap: {
|
||||
[key: number]: string[];
|
||||
} = {
|
||||
1: baseColSize,
|
||||
2: baseColSize,
|
||||
3: ['1/3', '1/2', '1'],
|
||||
4: ['1/4', '1']
|
||||
};
|
||||
|
||||
function getColSize(value: string, count: number) {
|
||||
if (!value.includes('/')) {
|
||||
return value;
|
||||
}
|
||||
const [a, b] = value.split('/').map(n => parseInt(n, 10));
|
||||
const c = b - a;
|
||||
if (c % count === 0) {
|
||||
return `${c / count}/${b}`;
|
||||
} else {
|
||||
return `${c}/${b * count}`;
|
||||
}
|
||||
}
|
||||
|
||||
const ColSize: React.FC<FormControlProps> = props => {
|
||||
const store = props.manager.store;
|
||||
const body = [...store.getSchemaParentById(store.activeId)];
|
||||
const node = store.getNodeById(store.activeId);
|
||||
const row = props.data.row;
|
||||
const rowItem = body.filter((item: any) => item.row === row);
|
||||
const length = rowItem.length;
|
||||
const parent = store.getNodeById(node.parentId);
|
||||
const isFlex = parent?.schema?.mode === 'flex';
|
||||
|
||||
const value = isFlex ? props.data.colSize : props.data.size;
|
||||
|
||||
function handleColSizeChange(value: string) {
|
||||
if (
|
||||
!colSizeMap[length].includes(value) ||
|
||||
node?.schema?.$$dragMode === 'hv'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let list = [...body];
|
||||
if (length > 1) {
|
||||
if (value === '1') {
|
||||
// 如果设置为占整行,需要调整自身和后面的元素的row
|
||||
let nodeIndex = list.findIndex((item: any) => item.$$id === node.id);
|
||||
let hasBefore = false;
|
||||
list = list.map((item, index) => {
|
||||
if (item.row === row) {
|
||||
if (index < nodeIndex) {
|
||||
hasBefore = true;
|
||||
}
|
||||
if (index === nodeIndex && hasBefore) {
|
||||
item.row += 1;
|
||||
}
|
||||
}
|
||||
if (index > nodeIndex) {
|
||||
item.row += hasBefore ? 2 : 1;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
// 非整行,需要调整同行元素的colSize
|
||||
const colSize = getColSize(value, length - 1);
|
||||
list = list.map((item: any) => {
|
||||
if (item.row === row && item.$$id !== node.id) {
|
||||
item.colSize = colSize;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const schema = JSONUpdate(store.schema, node.parentId, {
|
||||
[node.parentRegion]: list
|
||||
});
|
||||
|
||||
store.setSchema(schema);
|
||||
props.setValue(value, 'colSize');
|
||||
}
|
||||
|
||||
function handleSizeChange(value: string) {
|
||||
props.setValue(value, 'size');
|
||||
}
|
||||
|
||||
return isFlex ? (
|
||||
<div className="ColSize">
|
||||
{baseColSize.map(n => (
|
||||
<div
|
||||
className={cx(
|
||||
'ColSize-item',
|
||||
value === n && 'is-active',
|
||||
!colSizeMap[length]?.includes(n) && 'is-disabled',
|
||||
node.schema.$$dragMode === 'hv' && 'is-disabled'
|
||||
)}
|
||||
key={n}
|
||||
onClick={() => handleColSizeChange(n)}
|
||||
>
|
||||
{n}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
props.render('size', {
|
||||
label: false,
|
||||
type: 'amis-theme-select',
|
||||
name: 'size',
|
||||
value,
|
||||
options: [
|
||||
{
|
||||
label: '占满',
|
||||
value: 'full'
|
||||
},
|
||||
{
|
||||
label: '极小',
|
||||
value: 'xs'
|
||||
},
|
||||
{
|
||||
label: '小',
|
||||
value: 'sm'
|
||||
},
|
||||
{
|
||||
label: '中',
|
||||
value: 'md'
|
||||
},
|
||||
{
|
||||
label: '大',
|
||||
value: 'lg'
|
||||
},
|
||||
...(props.data?.sizesOptions?.filter((item: any) => {
|
||||
return !['var(--sizes-size-0)', 'var(--sizes-size-1)'].includes(
|
||||
item.value
|
||||
);
|
||||
}) || [])
|
||||
],
|
||||
onChange: handleSizeChange
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
@FormItem({type: 'col-size', strictMode: false})
|
||||
export class ColSizeRenderer extends React.Component<FormControlProps> {
|
||||
render() {
|
||||
return <ColSize {...this.props} />;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import {FormControlProps, FormItem} from 'amis-core';
|
||||
import {Select} from 'amis-ui';
|
||||
import React from 'react';
|
||||
|
||||
const LabelAlign: React.FC<FormControlProps> = props => {
|
||||
const store = props.manager.store;
|
||||
const node = store.getNodeById(store.activeId);
|
||||
const parent = store.getNodeById(node.parentId);
|
||||
const parentMode = parent?.schema?.mode;
|
||||
|
||||
function handleSizeChange(res: any) {
|
||||
const value = res.value;
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
props.onChange(value);
|
||||
if (parentMode !== 'flex') {
|
||||
// 历史包袱,只能改变mode
|
||||
if (value === 'inherit') {
|
||||
props.setValue(undefined, 'mode');
|
||||
} else if (value !== 'top') {
|
||||
props.setValue('horizontal', 'mode');
|
||||
} else {
|
||||
props.setValue('normal', 'mode');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
className=":LabelAlign"
|
||||
value={props.value || 'inherit'}
|
||||
onChange={handleSizeChange}
|
||||
clearable={false}
|
||||
options={[
|
||||
{
|
||||
label: '继承',
|
||||
value: 'inherit'
|
||||
},
|
||||
{
|
||||
label: '上下布局',
|
||||
value: 'top'
|
||||
},
|
||||
{
|
||||
label: '水平居左',
|
||||
value: 'left'
|
||||
},
|
||||
{
|
||||
label: '水平居右',
|
||||
value: 'right'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@FormItem({type: 'label-align', strictMode: false})
|
||||
export class LabelAlignRenderer extends React.Component<FormControlProps> {
|
||||
render() {
|
||||
return <LabelAlign {...this.props} />;
|
||||
}
|
||||
}
|
@ -1,10 +1,18 @@
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export const inputStateTpl = (className: string, path: string = '') => {
|
||||
export const inputStateTpl = (
|
||||
className: string,
|
||||
token: string = '',
|
||||
options: {
|
||||
state: string[];
|
||||
} = {
|
||||
state: ['default', 'hover', 'focused', 'disabled']
|
||||
}
|
||||
) => {
|
||||
return [
|
||||
{
|
||||
type: 'select',
|
||||
name: '__editorState',
|
||||
name: `__editorState${className}`,
|
||||
label: '状态',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
@ -17,19 +25,39 @@ export const inputStateTpl = (className: string, path: string = '') => {
|
||||
value: 'hover'
|
||||
},
|
||||
{
|
||||
label: '点击',
|
||||
value: 'active'
|
||||
label: '选中',
|
||||
value: 'focused'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'disabled'
|
||||
}
|
||||
]
|
||||
].filter(item => options.state.includes(item.value))
|
||||
},
|
||||
...inputStateFunc(
|
||||
"${__editorState == 'default' || !__editorState}",
|
||||
`\${__editorState${className} == 'default' || !__editorState${className}}`,
|
||||
'default',
|
||||
className,
|
||||
path
|
||||
token
|
||||
),
|
||||
...inputStateFunc("${__editorState == 'hover'}", 'hover', className, path),
|
||||
...inputStateFunc("${__editorState == 'active'}", 'active', className, path)
|
||||
...inputStateFunc(
|
||||
`\${__editorState${className} == 'hover'}`,
|
||||
'hover',
|
||||
className,
|
||||
token
|
||||
),
|
||||
...inputStateFunc(
|
||||
`\${__editorState${className} == 'focused'}`,
|
||||
'focused',
|
||||
className,
|
||||
token
|
||||
),
|
||||
...inputStateFunc(
|
||||
`\${__editorState${className} == 'disabled'}`,
|
||||
'disabled',
|
||||
className,
|
||||
token
|
||||
)
|
||||
];
|
||||
};
|
||||
|
||||
@ -37,15 +65,17 @@ export const inputStateFunc = (
|
||||
visibleOn: string,
|
||||
state: string,
|
||||
className: string,
|
||||
path: string,
|
||||
token: string,
|
||||
options: any = []
|
||||
) => {
|
||||
const cssToken = state === 'focused' ? 'active' : state;
|
||||
return [
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '文字',
|
||||
name: `${className}.font:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${path}.${state}.body.font`
|
||||
editorValueToken: `${token}-${cssToken}`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '背景',
|
||||
@ -54,22 +84,26 @@ export const inputStateFunc = (
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${path}.${state}.body.bg-color`
|
||||
editorValueToken: `${token}-${cssToken}-bg-color`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:border', {
|
||||
name: `${className}.border:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${path}.${state}.body.border`
|
||||
editorValueToken: `${token}-${cssToken}`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: `${className}.padding-and-margin:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${path}.${state}.body.padding-and-margin`
|
||||
editorValueToken: `${token}-${cssToken}`,
|
||||
state
|
||||
}),
|
||||
getSchemaTpl('theme:radius', {
|
||||
name: `${className}.radius:${state}`,
|
||||
visibleOn: visibleOn,
|
||||
editorThemePath: `${path}.${state}.body.border`
|
||||
editorValueToken: `${token}-${cssToken}`,
|
||||
state
|
||||
}),
|
||||
...options
|
||||
];
|
||||
|
@ -118,12 +118,14 @@ setSchemaTpl(
|
||||
label: '垂直',
|
||||
value: 'normal'
|
||||
},
|
||||
config?.isForm
|
||||
? null
|
||||
: {
|
||||
label: '继承',
|
||||
value: ''
|
||||
}
|
||||
!config?.isForm && {
|
||||
label: '继承',
|
||||
value: ''
|
||||
},
|
||||
config?.isForm && {
|
||||
label: '网格',
|
||||
value: 'flex'
|
||||
}
|
||||
].filter(i => i),
|
||||
pipeOut: (v: string) => (v ? v : undefined)
|
||||
})
|
||||
@ -261,6 +263,27 @@ setSchemaTpl('labelHide', () =>
|
||||
})
|
||||
);
|
||||
|
||||
setSchemaTpl('theme:labelHide', () =>
|
||||
getSchemaTpl('switch', {
|
||||
name: '__label',
|
||||
label: '隐藏标题',
|
||||
onChange: (value: any, origin: any, item: any, form: any) => {
|
||||
if (value) {
|
||||
form.setValueByName(
|
||||
'$$tempLabel',
|
||||
form.getValueByName('label') || item.label
|
||||
);
|
||||
form.setValueByName('label', false);
|
||||
} else {
|
||||
form.setValueByName(
|
||||
'label',
|
||||
form.getValueByName('$$tempLabel') || item['$$tempLabel'] || ''
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
setSchemaTpl('placeholder', {
|
||||
label: '占位提示',
|
||||
name: 'placeholder',
|
||||
|
@ -16,28 +16,46 @@ setSchemaTpl('style:formItem', ({renderer, schema}: any) => {
|
||||
};
|
||||
});
|
||||
|
||||
setSchemaTpl('theme:formItem', ({schema}: any = {}) => {
|
||||
return {
|
||||
title: '表单项',
|
||||
key: 'formItem',
|
||||
body: [
|
||||
getSchemaTpl('theme:labelHide'),
|
||||
{
|
||||
type: 'col-size',
|
||||
name: '__size',
|
||||
label: '宽度'
|
||||
}
|
||||
].concat(schema)
|
||||
};
|
||||
});
|
||||
|
||||
setSchemaTpl(
|
||||
'style:classNames',
|
||||
(config: {
|
||||
schema: SchemaCollection;
|
||||
isFormItem: boolean;
|
||||
unsupportStatic?: boolean;
|
||||
collapsed?: boolean;
|
||||
}) => {
|
||||
const {
|
||||
isFormItem = true,
|
||||
unsupportStatic = false,
|
||||
schema = []
|
||||
schema = [],
|
||||
collapsed = true
|
||||
} = config || {};
|
||||
|
||||
return {
|
||||
title: 'CSS 类名',
|
||||
collapsed,
|
||||
body: (isFormItem
|
||||
? [
|
||||
getSchemaTpl('className', {
|
||||
label: '表单项'
|
||||
}),
|
||||
getSchemaTpl('className', {
|
||||
label: '标签',
|
||||
label: '标题',
|
||||
name: 'labelClassName'
|
||||
}),
|
||||
getSchemaTpl('className', {
|
||||
@ -441,16 +459,25 @@ setSchemaTpl('theme:cssCode', () => {
|
||||
// form label
|
||||
setSchemaTpl('theme:form-label', () => {
|
||||
return {
|
||||
title: 'Label样式',
|
||||
title: '标题样式',
|
||||
visibleOn: 'this.label !== false',
|
||||
body: [
|
||||
{
|
||||
type: 'label-align',
|
||||
name: 'labelAlign',
|
||||
label: '位置'
|
||||
},
|
||||
getSchemaTpl('theme:select', {
|
||||
label: '宽度',
|
||||
name: 'labelWidth'
|
||||
name: 'labelWidth',
|
||||
hiddenOn: 'this.labelAlign == "top"'
|
||||
}),
|
||||
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '文字',
|
||||
name: 'themeCss.labelClassName.font:default',
|
||||
editorThemePath: 'form.item.default.label.body.font'
|
||||
hasSenior: false,
|
||||
editorValueToken: '--Form-item'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: 'themeCss.labelClassName.padding-and-margin:default'
|
||||
@ -468,11 +495,15 @@ setSchemaTpl('theme:form-description', () => {
|
||||
getSchemaTpl('theme:font', {
|
||||
label: '文字',
|
||||
name: 'themeCss.descriptionClassName.font:default',
|
||||
editorThemePath: 'form.item.default.description.body.font'
|
||||
editorValueToken: '--Form-description'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
name: 'themeCss.descriptionClassName.padding-and-margin:default'
|
||||
})
|
||||
{
|
||||
label: '上间距',
|
||||
type: 'amis-theme-select',
|
||||
name: 'themeCss.descriptionClassName.margin-top:default',
|
||||
options: '${sizesOptions}',
|
||||
editorValueToken: '--Form-description-gap'
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
@ -481,6 +512,7 @@ setSchemaTpl('theme:form-description', () => {
|
||||
setSchemaTpl('theme:select', (option: any = {}) => {
|
||||
return {
|
||||
mode: 'horizontal',
|
||||
labelAlign: 'left',
|
||||
type: 'amis-theme-select',
|
||||
label: '大小',
|
||||
name: `themeCss.className.select:default`,
|
||||
@ -579,7 +611,17 @@ setSchemaTpl(
|
||||
classname?: string;
|
||||
title?: string;
|
||||
hiddenOn?: string;
|
||||
visibleOn?: string;
|
||||
hidePaddingAndMargin?: boolean;
|
||||
hideBorder?: boolean;
|
||||
hideRadius?: boolean;
|
||||
hideBackground?: boolean;
|
||||
hideShadow?: boolean;
|
||||
hideMargin?: boolean;
|
||||
hidePadding?: boolean;
|
||||
needState?: boolean;
|
||||
editorValueToken?: string;
|
||||
state?: string[];
|
||||
}) => {
|
||||
const {
|
||||
collapsed = false,
|
||||
@ -587,38 +629,64 @@ setSchemaTpl(
|
||||
classname = 'baseControlClassName',
|
||||
title = '基本样式',
|
||||
hiddenOn,
|
||||
hidePaddingAndMargin
|
||||
visibleOn,
|
||||
hidePaddingAndMargin,
|
||||
hideBorder,
|
||||
hideRadius,
|
||||
hideBackground,
|
||||
hideShadow,
|
||||
hideMargin,
|
||||
hidePadding,
|
||||
needState = true,
|
||||
editorValueToken,
|
||||
state = ['default', 'hover', 'active']
|
||||
} = option;
|
||||
const curHidePaddingAndMargin = hidePaddingAndMargin ?? false;
|
||||
const styleStateFunc = (visibleOn: string, state: string) => {
|
||||
return [
|
||||
!curHidePaddingAndMargin
|
||||
? getSchemaTpl('theme:paddingAndMargin', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.padding-and-margin:${state}`
|
||||
})
|
||||
: null,
|
||||
getSchemaTpl('theme:border', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.border:${state}`
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.background:${state}`,
|
||||
label: '背景',
|
||||
needCustom: true,
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
labelMode: 'input'
|
||||
}),
|
||||
getSchemaTpl('theme:radius', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.radius:${state}`
|
||||
}),
|
||||
getSchemaTpl('theme:shadow', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.boxShadow:${state}`
|
||||
})
|
||||
!hideBorder &&
|
||||
getSchemaTpl('theme:border', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.border:${state}`,
|
||||
state,
|
||||
editorValueToken
|
||||
}),
|
||||
!hideRadius &&
|
||||
getSchemaTpl('theme:radius', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.radius:${state}`,
|
||||
state,
|
||||
editorValueToken
|
||||
}),
|
||||
!hidePaddingAndMargin &&
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.padding-and-margin:${state}`,
|
||||
hideMargin,
|
||||
hidePadding,
|
||||
state,
|
||||
editorValueToken
|
||||
}),
|
||||
!hideBackground &&
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.background:${state}`,
|
||||
label: '背景',
|
||||
needCustom: true,
|
||||
needGradient: true,
|
||||
needImage: true,
|
||||
labelMode: 'input',
|
||||
state,
|
||||
editorValueToken: editorValueToken
|
||||
? `${editorValueToken}-\${__editorState${classname} || 'default'}-bg-color`
|
||||
: undefined
|
||||
}),
|
||||
!hideShadow &&
|
||||
getSchemaTpl('theme:shadow', {
|
||||
visibleOn: visibleOn,
|
||||
name: `themeCss.${classname}.boxShadow:${state}`,
|
||||
state,
|
||||
editorValueToken
|
||||
})
|
||||
]
|
||||
.filter(item => item)
|
||||
.concat(
|
||||
@ -626,15 +694,19 @@ setSchemaTpl(
|
||||
return {
|
||||
...item,
|
||||
visibleOn: visibleOn,
|
||||
name: `${item.name}:${state}`
|
||||
name: `${item.name}:${state}`,
|
||||
state
|
||||
};
|
||||
})
|
||||
);
|
||||
};
|
||||
const styles = [
|
||||
{
|
||||
needState && {
|
||||
type: 'select',
|
||||
name: '__editorState',
|
||||
mode: 'horizontal',
|
||||
labelAlign: 'left',
|
||||
labelWidth: 80,
|
||||
name: `__editorState${classname}`,
|
||||
label: '状态',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
@ -650,21 +722,22 @@ setSchemaTpl(
|
||||
label: '点击',
|
||||
value: 'active'
|
||||
}
|
||||
]
|
||||
].filter(item => state.includes(item.value))
|
||||
},
|
||||
...styleStateFunc(
|
||||
"${__editorState == 'default' || !__editorState}",
|
||||
`\${__editorState${classname} == 'default' || !__editorState${classname}}`,
|
||||
'default'
|
||||
),
|
||||
...styleStateFunc("${__editorState == 'hover'}", 'hover'),
|
||||
...styleStateFunc("${__editorState == 'active'}", 'active')
|
||||
];
|
||||
...styleStateFunc(`\${__editorState${classname} == 'hover'}`, 'hover'),
|
||||
...styleStateFunc(`\${__editorState${classname} == 'active'}`, 'active')
|
||||
].filter(Boolean);
|
||||
|
||||
return {
|
||||
title,
|
||||
collapsed,
|
||||
body: styles,
|
||||
hiddenOn
|
||||
hiddenOn,
|
||||
visibleOn
|
||||
};
|
||||
}
|
||||
);
|
||||
@ -734,3 +807,35 @@ setSchemaTpl(
|
||||
].filter(item => !~exclude.indexOf(item.key || ''));
|
||||
}
|
||||
);
|
||||
|
||||
setSchemaTpl(
|
||||
'theme:icon',
|
||||
(option: {classname?: string; visibleOn?: string; title?: string}) => {
|
||||
const {
|
||||
classname = 'iconControlClassName',
|
||||
visibleOn,
|
||||
title = '图标样式'
|
||||
} = option;
|
||||
return {
|
||||
title,
|
||||
visibleOn,
|
||||
body: [
|
||||
getSchemaTpl('theme:select', {
|
||||
label: '图标尺寸',
|
||||
name: `themeCss.${classname}.iconSize`
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
name: `themeCss.${classname}.color`,
|
||||
label: '图标颜色',
|
||||
needCustom: true,
|
||||
needGradient: true,
|
||||
labelMode: 'input'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '图标边距',
|
||||
name: `themeCss.${classname}.padding-and-margin`
|
||||
})
|
||||
]
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -1,18 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图标" transform="translate(-141.000000, -40.000000)">
|
||||
<g id="自定义设置" transform="translate(142.000000, 41.000000)">
|
||||
<g id="编组-28备份">
|
||||
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
|
||||
</g>
|
||||
<rect id="矩形" fill="#84868C" x="7.11577461" y="2.95100764" width="6.91305466" height="1" rx="0.5"></rect>
|
||||
<rect id="矩形备份-49" fill="#84868C" x="7.11577461" y="5.98938234" width="5.18768508" height="1" rx="0.5"></rect>
|
||||
<rect id="矩形备份-51" fill="#84868C" x="7.11577461" y="9.02775704" width="6.91305466" height="1" rx="0.5"></rect>
|
||||
<rect id="矩形备份-50" fill="#84868C" x="7.11577461" y="12.0661317" width="5.18768508" height="1" rx="0.5"></rect>
|
||||
<path d="M4.28402126,2.5 L4.28402126,3.98813377 M4.28402126,6.73009787 L4.28402126,8.87389474 M4.28402126,11.9388703 L4.28402126,13.5" id="形状" stroke="#84868C" stroke-linecap="round" stroke-linejoin="bevel"></path>
|
||||
<path d="M4.25,9.19464196 C4.98767176,9.19464196 5.58567287,9.79264308 5.58567287,10.5303148 C5.58567287,11.2679866 4.98767176,11.8659877 4.25,11.8659877 C3.51232824,11.8659877 2.91432713,11.2679866 2.91432713,10.5303148 C2.91432713,9.79264308 3.51232824,9.19464196 4.25,9.19464196 Z M4.25,4.04216118 C4.98767176,4.04216118 5.58567287,4.6401623 5.58567287,5.37783405 C5.58567287,6.11550581 4.98767176,6.71350693 4.25,6.71350693 C3.51232824,6.71350693 2.91432713,6.11550581 2.91432713,5.37783405 C2.91432713,4.6401623 3.51232824,4.04216118 4.25,4.04216118 Z" id="形状结合" stroke="#84868C" stroke-linejoin="round"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect x="7.11577461" y="2.95100764" width="6.91305466" height="1"
|
||||
rx="0.5" fill="currentColor"> </rect>
|
||||
<rect x="7.11577461" y="5.98938234" width="5.18768508"
|
||||
height="1" rx="0.5" fill="currentColor"></rect>
|
||||
<rect x="7.11577461" y="9.02775704" width="6.91305466"
|
||||
height="1" rx="0.5" fill="currentColor"></rect>
|
||||
<rect x="7.11577461" y="12.0661317" width="5.18768508"
|
||||
fill="currentColor"
|
||||
height="1" rx="0.5"></rect>
|
||||
<path
|
||||
d="M4.28402126,2.5 L4.28402126,3.98813377 M4.28402126,6.73009787 L4.28402126,8.87389474 M4.28402126,11.9388703 L4.28402126,13.5"
|
||||
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="bevel"></path>
|
||||
<path
|
||||
d="M4.25,9.19464196 C4.98767176,9.19464196 5.58567287,9.79264308 5.58567287,10.5303148 C5.58567287,11.2679866 4.98767176,11.8659877 4.25,11.8659877 C3.51232824,11.8659877 2.91432713,11.2679866 2.91432713,10.5303148 C2.91432713,9.79264308 3.51232824,9.19464196 4.25,9.19464196 Z M4.25,4.04216118 C4.98767176,4.04216118 5.58567287,4.6401623 5.58567287,5.37783405 C5.58567287,6.11550581 4.98767176,6.71350693 4.25,6.71350693 C3.51232824,6.71350693 2.91432713,6.11550581 2.91432713,5.37783405 C2.91432713,4.6401623 3.51232824,4.04216118 4.25,4.04216118 Z"
|
||||
stroke="currentColor" fill="none" stroke-linejoin="round"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.5 KiB |
@ -12,12 +12,7 @@ import {Select} from 'amis-ui';
|
||||
import ColorPicker from './ColorPicker';
|
||||
import ThemeSelect from './ThemeSelect';
|
||||
import {i18n as _i18n} from 'i18n-runtime';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface BorderProps {
|
||||
custom?: boolean;
|
||||
@ -104,7 +99,7 @@ function BoxBorder(props: BorderProps & FormControlProps) {
|
||||
label,
|
||||
needColorCustom,
|
||||
state,
|
||||
editorThemePath
|
||||
editorValueToken
|
||||
} = props;
|
||||
const [borderWidthOptions, setBorderWidthOptions] = useState(
|
||||
cloneDeep(
|
||||
@ -122,39 +117,44 @@ function BoxBorder(props: BorderProps & FormControlProps) {
|
||||
cloneDeep(props.colorOptions || data.colorOptions)
|
||||
);
|
||||
const [borderType, setBorderType] = useState<string>('all');
|
||||
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
const borderData = formatData(value || {});
|
||||
|
||||
useEffect(() => {
|
||||
if (state && state !== 'default') {
|
||||
const type = borderType === 'all' ? 'top' : borderType;
|
||||
const styleOptions = cloneDeep(borderStyleOptions);
|
||||
if (styleOptions[0].parent) {
|
||||
styleOptions[0].value = editorThemePath
|
||||
? 'inherit'
|
||||
: `var(${data.default.token}${type}-border-style)`;
|
||||
styleOptions[0].realValue = '继承常规';
|
||||
} else {
|
||||
styleOptions.unshift({
|
||||
label: '继承常规',
|
||||
value: editorThemePath
|
||||
? 'inherit'
|
||||
: `var(${data?.default?.token}${type}-border-style)`,
|
||||
parent: true,
|
||||
realValue: '继承常规'
|
||||
let borderToken: any;
|
||||
|
||||
if (editorValueToken) {
|
||||
borderToken = {
|
||||
'top-border-color': `${editorValueToken}-top-border-color`,
|
||||
'top-border-width': `${editorValueToken}-top-border-width`,
|
||||
'top-border-style': `${editorValueToken}-top-border-style`,
|
||||
'right-border-color': `${editorValueToken}-right-border-color`,
|
||||
'right-border-width': `${editorValueToken}-right-border-width`,
|
||||
'right-border-style': `${editorValueToken}-right-border-style`,
|
||||
'bottom-border-color': `${editorValueToken}-bottom-border-color`,
|
||||
'bottom-border-width': `${editorValueToken}-bottom-border-width`,
|
||||
'bottom-border-style': `${editorValueToken}-bottom-border-style`,
|
||||
'left-border-color': `${editorValueToken}-left-border-color`,
|
||||
'left-border-width': `${editorValueToken}-left-border-width`,
|
||||
'left-border-style': `${editorValueToken}-left-border-style`
|
||||
};
|
||||
if (typeof editorValueToken === 'object') {
|
||||
Object.keys(borderToken).forEach(key => {
|
||||
// 短横线转驼峰
|
||||
const tokenKey = key.replace(/-([a-z])/g, function (all, letter) {
|
||||
return letter.toUpperCase();
|
||||
});
|
||||
}
|
||||
setBorderStyleOptions(styleOptions);
|
||||
borderToken[key] =
|
||||
editorValueToken[tokenKey] || `${editorValueToken['*']}-${key}`;
|
||||
});
|
||||
}
|
||||
}, [borderType]);
|
||||
}
|
||||
const editorDefaultValue = formatData(getDefaultValue(borderToken, data));
|
||||
const borderData = formatData(value || {});
|
||||
|
||||
function formatData(sourceData: any) {
|
||||
if (!sourceData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = formatInheritData(cloneDeep(sourceData));
|
||||
const data = cloneDeep(sourceData);
|
||||
|
||||
const fn = (type: string) => {
|
||||
if (
|
||||
@ -174,9 +174,6 @@ function BoxBorder(props: BorderProps & FormControlProps) {
|
||||
}
|
||||
|
||||
function getLabel(value?: string, option?: any) {
|
||||
if (value === 'inherit') {
|
||||
return '继承常规';
|
||||
}
|
||||
const res = option?.find((item: any) => item.value === value);
|
||||
if (res) {
|
||||
return res.label;
|
||||
@ -222,7 +219,7 @@ function BoxBorder(props: BorderProps & FormControlProps) {
|
||||
};
|
||||
}
|
||||
|
||||
onChange(setInheritData(changeValue, editorInheritValue));
|
||||
onChange(changeValue);
|
||||
};
|
||||
}
|
||||
|
||||
@ -269,7 +266,6 @@ function BoxBorder(props: BorderProps & FormControlProps) {
|
||||
borderType === 'all' ? 'top' : borderType
|
||||
}-border-width`}
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.[getKey('width')] || '边框粗细'}
|
||||
/>
|
||||
<div className="Theme-Border-settings-style-color">
|
||||
|
@ -28,12 +28,7 @@ import type {GlobalData} from '../helper/getGlobalData';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import debounce from 'lodash/debounce';
|
||||
import {i18n as _i18n} from 'i18n-runtime';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
import {Icon as ThemeIcon} from '../icons/index';
|
||||
|
||||
interface ColorPickerProps {
|
||||
@ -53,7 +48,6 @@ interface ColorPickerProps {
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
editorInheritValue?: string;
|
||||
}
|
||||
|
||||
interface ColorPickerControlProps extends FormControlProps {
|
||||
@ -62,7 +56,7 @@ interface ColorPickerControlProps extends FormControlProps {
|
||||
needImage?: boolean; // 图片
|
||||
needTheme?: boolean; // 主题色
|
||||
needCustom?: boolean; // 自定义颜色
|
||||
editorThemePath?: string;
|
||||
editorValueToken?: string;
|
||||
}
|
||||
|
||||
interface ColorSelectProps {
|
||||
@ -112,33 +106,23 @@ function findColor(value: string | undefined, tree: any) {
|
||||
res = {label: '继承常规', value: value};
|
||||
}
|
||||
}
|
||||
if (value === 'transparent') {
|
||||
if (value === 'transparent' || value?.includes('none')) {
|
||||
res = {label: '透明', value: 'transparent'};
|
||||
}
|
||||
if (value === 'custom') {
|
||||
res = {label: '分别配置', value: 'transparent'};
|
||||
}
|
||||
if (value === 'inherit') {
|
||||
res = {label: '继承常规', value: value};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function ThemeColorList(props: ThemeColorProps) {
|
||||
const {themeList, onChange, value, data, itemName, state, editorThemePath} =
|
||||
props;
|
||||
const editorInheritValue =
|
||||
props.editorInheritValue || getInheritValue(editorThemePath, data);
|
||||
const defaultVar =
|
||||
state && state !== 'default'
|
||||
? 'inherit'
|
||||
: `var(${data?.default?.token}${itemName})`;
|
||||
const {themeList, onChange, value, data, itemName, state} = props;
|
||||
|
||||
const [colorList, setColorList] = useState(cloneDeep(themeList || []));
|
||||
const [showFlag, setShowFlag] = useState(true);
|
||||
|
||||
function setColor(value: string | undefined) {
|
||||
onChange(setInheritData(value, editorInheritValue));
|
||||
onChange(value);
|
||||
}
|
||||
|
||||
function searchColor(value: string) {
|
||||
@ -213,36 +197,6 @@ function ThemeColorList(props: ThemeColorProps) {
|
||||
</div>
|
||||
</div>
|
||||
</TooltipWrapper>
|
||||
{(data?.state && data.state !== 'default') ||
|
||||
(state && state !== 'default') ? (
|
||||
<TooltipWrapper
|
||||
trigger="hover"
|
||||
placement="top"
|
||||
tooltip={{
|
||||
children: () => <div>继承常规</div>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={cx(
|
||||
'ThemeColorList-content-label',
|
||||
value === defaultVar && 'ThemeColorList-content-label--active'
|
||||
)}
|
||||
onClick={() => setColor(defaultVar)}
|
||||
>
|
||||
<div
|
||||
className={cx(
|
||||
'ThemeColorList-content-label-inner',
|
||||
'ThemeColor--transparent'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="ThemeColorList-content-label-inner"
|
||||
style={{background: defaultVar}}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</TooltipWrapper>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="ThemeColorList-content--search">
|
||||
<SearchBox placeholder="输入色值或名称搜索" onChange={searchColor} />
|
||||
@ -1472,11 +1426,9 @@ function ColorPicker(props: ColorPickerProps) {
|
||||
}
|
||||
|
||||
function ColorPickerControl(props: ColorPickerControlProps) {
|
||||
const editorDefaultValue = getValueByPath(
|
||||
props.editorThemePath || '',
|
||||
props.data
|
||||
);
|
||||
const value = formatInheritData(props.value) || editorDefaultValue;
|
||||
let editorDefaultValue = getDefaultValue(props.editorValueToken, props.data);
|
||||
|
||||
const value = props.value || editorDefaultValue;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -14,16 +14,11 @@ import cloneDeep from 'lodash/cloneDeep';
|
||||
import assign from 'lodash/assign';
|
||||
import {ThemeWrapperHeader} from './ThemeWrapper';
|
||||
import ThemeSelect from './ThemeSelect';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface FontEditorProps extends FormControlProps {}
|
||||
|
||||
interface SizeDataProps {
|
||||
interface FontDataProps {
|
||||
'font-family'?: string;
|
||||
'fontSize'?: string;
|
||||
'fontWeight'?: string;
|
||||
@ -37,7 +32,7 @@ interface SizeDataProps {
|
||||
|
||||
interface OptionProps {
|
||||
label: string;
|
||||
type: keyof SizeDataProps;
|
||||
type: keyof FontDataProps;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@ -921,7 +916,7 @@ function FontEditor(props: FontEditorProps) {
|
||||
fontWeightOptions = data.fontWeightOptions || defaultFontWeight,
|
||||
lineHeightOptions = data.lineHeightOptions || defaultlineHeight,
|
||||
fontFamilyOptions = data.fontFamilyOptions || SYSTEM_FONT_FAMILY,
|
||||
editorThemePath
|
||||
editorValueToken
|
||||
} = props;
|
||||
|
||||
const alignOptions = hasVertical
|
||||
@ -930,24 +925,54 @@ function FontEditor(props: FontEditorProps) {
|
||||
|
||||
const [open, toggleOpen] = React.useState(true);
|
||||
const [senior, toggleSenior] = React.useState(false);
|
||||
const editorDefaultValue = getValueByPath(editorThemePath, data);
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
|
||||
const [sizeData, setSizeData] = React.useState<SizeDataProps>(
|
||||
assign({}, formatInheritData(value))
|
||||
let fontToken;
|
||||
if (editorValueToken) {
|
||||
let color = `${editorValueToken}-color`;
|
||||
let fontSize = `${editorValueToken}-fontSize`;
|
||||
let fontWeight = `${editorValueToken}-fontWeight`;
|
||||
let lineHeight = `${editorValueToken}-lineHeight`;
|
||||
if (typeof editorValueToken === 'object') {
|
||||
color = editorValueToken.color || `${editorValueToken['*']}-color`;
|
||||
fontSize =
|
||||
editorValueToken.fontSize || `${editorValueToken['*']}-fontSize`;
|
||||
fontWeight =
|
||||
editorValueToken.fontWeight || `${editorValueToken['*']}-fontWeight`;
|
||||
lineHeight =
|
||||
editorValueToken.lineHeight || `${editorValueToken['*']}-lineHeight`;
|
||||
}
|
||||
fontToken = {
|
||||
color,
|
||||
fontSize,
|
||||
fontWeight,
|
||||
lineHeight
|
||||
};
|
||||
}
|
||||
const editorDefaultValue = getDefaultValue(fontToken, data);
|
||||
|
||||
const [fontData, setFontData] = React.useState<FontDataProps>(
|
||||
assign({}, value)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (value) {
|
||||
setSizeData(assign({}, formatInheritData(value)));
|
||||
setFontData(assign({}, value));
|
||||
if (
|
||||
value['font-style'] ||
|
||||
value['text-decoration'] ||
|
||||
value['text-align'] ||
|
||||
value['vertical-align']
|
||||
) {
|
||||
toggleSenior(true);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}, [value]);
|
||||
|
||||
function handleEdit(value: string | undefined, type: keyof SizeDataProps) {
|
||||
const data = cloneDeep(sizeData);
|
||||
function handleEdit(value: string | undefined, type: keyof FontDataProps) {
|
||||
const data = cloneDeep(fontData);
|
||||
if (
|
||||
[
|
||||
'font-style',
|
||||
@ -961,14 +986,11 @@ function FontEditor(props: FontEditorProps) {
|
||||
} else {
|
||||
data[type] = value;
|
||||
}
|
||||
setSizeData(data);
|
||||
onChange(setInheritData(data, editorInheritValue));
|
||||
setFontData(data);
|
||||
onChange(data);
|
||||
}
|
||||
|
||||
function getLabel(value?: string, option?: any) {
|
||||
if (value === 'inherit') {
|
||||
return '继承常规';
|
||||
}
|
||||
const res = option?.find((item: any) => item.value === value);
|
||||
if (res) {
|
||||
return res.label;
|
||||
@ -994,7 +1016,7 @@ function FontEditor(props: FontEditorProps) {
|
||||
<ColorPicker
|
||||
{...props}
|
||||
needCustom={needColorCustom ?? false}
|
||||
value={sizeData.color}
|
||||
value={fontData.color}
|
||||
options={colorOptions}
|
||||
onChange={(value: string) => {
|
||||
handleEdit(value, 'color');
|
||||
@ -1002,7 +1024,6 @@ function FontEditor(props: FontEditorProps) {
|
||||
itemName="color"
|
||||
state={state}
|
||||
placeholder={editorDefaultValue?.color || '字体颜色'}
|
||||
editorInheritValue={editorInheritValue?.color}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -1011,14 +1032,13 @@ function FontEditor(props: FontEditorProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={fontSizeOptions}
|
||||
value={sizeData['fontSize']}
|
||||
value={fontData['fontSize']}
|
||||
onChange={(value: string) => {
|
||||
handleEdit(value, 'fontSize');
|
||||
}}
|
||||
itemName="fontSize"
|
||||
menuTpl="label"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.fontSize || '字体大小'}
|
||||
/>
|
||||
</div>
|
||||
@ -1030,14 +1050,13 @@ function FontEditor(props: FontEditorProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={fontWeightOptions}
|
||||
value={sizeData['fontWeight']}
|
||||
value={fontData['fontWeight']}
|
||||
onChange={(value: string) => {
|
||||
handleEdit(value, 'fontWeight');
|
||||
}}
|
||||
itemName="fontWeight"
|
||||
menuTpl="label"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.fontWeight || '字体字重'}
|
||||
/>
|
||||
{(!hideLineHeight || !hideFontFamily) && (
|
||||
@ -1050,14 +1069,13 @@ function FontEditor(props: FontEditorProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={lineHeightOptions}
|
||||
value={sizeData['lineHeight']}
|
||||
value={fontData['lineHeight']}
|
||||
onChange={(value: string) => {
|
||||
handleEdit(value, 'lineHeight');
|
||||
}}
|
||||
itemName="lineHeight"
|
||||
menuTpl="label"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.lineHeight || '字体行高'}
|
||||
/>
|
||||
<div className="Theme-FontEditor-item-label">行高</div>
|
||||
@ -1068,14 +1086,14 @@ function FontEditor(props: FontEditorProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={fontFamilyOptions}
|
||||
value={sizeData['font-family']}
|
||||
value={fontData['font-family']}
|
||||
onChange={(value: string) => {
|
||||
handleEdit(value, 'font-family');
|
||||
}}
|
||||
itemName="fontFamily"
|
||||
menuTpl="label"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.fontFamily || '字体'}
|
||||
/>
|
||||
<div className="Theme-FontEditor-item-label">字体</div>
|
||||
</div>
|
||||
@ -1092,7 +1110,7 @@ function FontEditor(props: FontEditorProps) {
|
||||
<div
|
||||
className={cx(
|
||||
'Theme-FontEditor-font-style-icon',
|
||||
sizeData[item.type] === item.value &&
|
||||
fontData[item.type] === item.value &&
|
||||
'Theme-FontEditor-font-style-selected'
|
||||
)}
|
||||
>
|
||||
@ -1118,7 +1136,7 @@ function FontEditor(props: FontEditorProps) {
|
||||
className={cx(
|
||||
'Theme-FontEditor-font-style-icon',
|
||||
hasVertical && index === 3 && 'right-line',
|
||||
sizeData[item.type] === item.value &&
|
||||
fontData[item.type] === item.value &&
|
||||
'Theme-FontEditor-font-style-selected'
|
||||
)}
|
||||
>
|
||||
|
@ -9,12 +9,7 @@ import React, {useEffect, useState} from 'react';
|
||||
import cx from 'classnames';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import ThemeSelect from './ThemeSelect';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface PaddingAndMarginProps extends FormControlProps {
|
||||
custom: boolean;
|
||||
@ -31,15 +26,13 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
hideMargin,
|
||||
hidePadding,
|
||||
state,
|
||||
editorThemePath
|
||||
editorValueToken
|
||||
} = props;
|
||||
const [type, setType] = useState('all');
|
||||
const [customRef, setCustomRef] = useState<Element | null>(null);
|
||||
const [customShow, setCustomShow] = useState(false);
|
||||
const [customIndex, setCustomIndex] = useState(0);
|
||||
const [customKey, setCustomKey] = useState('marginTop');
|
||||
const [isPaddingInherit, setIsPaddingInherit] = useState<boolean>(false);
|
||||
const [isMarginInherit, setIsMarginInherit] = useState<boolean>(false);
|
||||
|
||||
const LABELS = [
|
||||
{value: 'marginTop'},
|
||||
@ -60,8 +53,23 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
}
|
||||
});
|
||||
|
||||
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
let paddingAndMarginToken;
|
||||
if (editorValueToken) {
|
||||
paddingAndMarginToken = {
|
||||
paddingTop: `${editorValueToken}-paddingTop`,
|
||||
paddingBottom: `${editorValueToken}-paddingBottom`,
|
||||
paddingLeft: `${editorValueToken}-paddingLeft`,
|
||||
paddingRight: `${editorValueToken}-paddingRight`,
|
||||
marginTop: `${editorValueToken}-marginTop`,
|
||||
marginBottom: `${editorValueToken}-marginBottom`,
|
||||
marginLeft: `${editorValueToken}-marginLeft`,
|
||||
marginRight: `${editorValueToken}-marginRight`
|
||||
};
|
||||
}
|
||||
|
||||
const editorDefaultValue = formatData(
|
||||
getDefaultValue(paddingAndMarginToken, data)
|
||||
);
|
||||
const spaceData = formatData(value || {});
|
||||
const optionsData = options || data.sizesOptions || [];
|
||||
|
||||
@ -70,7 +78,7 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = formatInheritData(cloneDeep(sourceData));
|
||||
const data = cloneDeep(sourceData);
|
||||
if (
|
||||
data?.marginTop === data?.marginRight &&
|
||||
data?.marginRight === data?.marginBottom &&
|
||||
@ -102,43 +110,20 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
}
|
||||
|
||||
if (position === 'margin-all') {
|
||||
if (value?.includes('all')) {
|
||||
const defaultToken = (key: string) =>
|
||||
`var(${data.default.token}${key})`;
|
||||
res.marginTop = defaultToken('marginTop');
|
||||
res.marginRight = defaultToken('marginRight');
|
||||
res.marginBottom = defaultToken('marginBottom');
|
||||
res.marginLeft = defaultToken('marginLeft');
|
||||
} else {
|
||||
res.marginTop = value;
|
||||
res.marginRight = value;
|
||||
res.marginBottom = value;
|
||||
res.marginLeft = value;
|
||||
}
|
||||
res.marginTop = value;
|
||||
res.marginRight = value;
|
||||
res.marginBottom = value;
|
||||
res.marginLeft = value;
|
||||
} else if (position === 'padding-all') {
|
||||
if (value?.includes('all')) {
|
||||
const defaultToken = (key: string) =>
|
||||
`var(${data.default.token}${key})`;
|
||||
res.paddingTop = defaultToken('paddingTop');
|
||||
res.paddingRight = defaultToken('paddingRight');
|
||||
res.paddingBottom = defaultToken('paddingBottom');
|
||||
res.paddingLeft = defaultToken('paddingLeft');
|
||||
} else {
|
||||
res.paddingTop = value;
|
||||
res.paddingRight = value;
|
||||
res.paddingBottom = value;
|
||||
res.paddingLeft = value;
|
||||
}
|
||||
res.paddingTop = value;
|
||||
res.paddingRight = value;
|
||||
res.paddingBottom = value;
|
||||
res.paddingLeft = value;
|
||||
} else if (typeof position === 'number') {
|
||||
const label = LABELS[position].value;
|
||||
res[label] = value;
|
||||
if (label.includes('padding')) {
|
||||
setIsPaddingInherit(false);
|
||||
} else {
|
||||
setIsMarginInherit(false);
|
||||
}
|
||||
}
|
||||
onChange(setInheritData(res, editorInheritValue));
|
||||
onChange(res);
|
||||
};
|
||||
}
|
||||
|
||||
@ -155,27 +140,6 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
setCustomKey(key);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (state && state !== 'default' && value) {
|
||||
if (
|
||||
value['paddingTop']?.includes('default-paddingTop') &&
|
||||
value['paddingBottom']?.includes('default-paddingBottom') &&
|
||||
value['paddingRight']?.includes('default-paddingRight') &&
|
||||
value['paddingLeft']?.includes('default-paddingLeft')
|
||||
) {
|
||||
setIsPaddingInherit(true);
|
||||
}
|
||||
if (
|
||||
value['marginTop']?.includes('default-marginTop') &&
|
||||
value['marginBottom']?.includes('default-marginBottom') &&
|
||||
value['marginRight']?.includes('default-marginRight') &&
|
||||
value['marginLeft']?.includes('default-marginLeft')
|
||||
) {
|
||||
setIsMarginInherit(true);
|
||||
}
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (spaceData.margin === 'custom' || spaceData.padding === 'custom') {
|
||||
setType('custom');
|
||||
@ -222,15 +186,10 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={optionsData}
|
||||
value={
|
||||
isMarginInherit
|
||||
? `var(${data.default.token}margin-all)`
|
||||
: spaceData.margin
|
||||
}
|
||||
value={spaceData.margin}
|
||||
onChange={onSpaceChange('margin-all')}
|
||||
itemName="margin-all"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.margin || '外边距'}
|
||||
/>
|
||||
<div className="Theme-PaddingAndMargin-input-label">外边距</div>
|
||||
@ -241,15 +200,10 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={optionsData}
|
||||
value={
|
||||
isPaddingInherit
|
||||
? `var(${data.default.token}padding-all)`
|
||||
: spaceData.padding
|
||||
}
|
||||
value={spaceData.padding}
|
||||
onChange={onSpaceChange('padding-all')}
|
||||
itemName="padding-all"
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.padding || '内边距'}
|
||||
/>
|
||||
<div className="Theme-PaddingAndMargin-input-label">内边距</div>
|
||||
@ -298,7 +252,6 @@ function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
|
||||
onChange={onSpaceChange(customIndex)}
|
||||
itemName={customKey}
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.[customKey]}
|
||||
/>
|
||||
</div>
|
||||
|
@ -9,12 +9,7 @@ import {FormItem, RendererProps, resolveVariableAndFilter} from 'amis-core';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import ThemeSelect from './ThemeSelect';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface RadiusProps {
|
||||
custom: boolean;
|
||||
@ -48,7 +43,7 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
label,
|
||||
borderRadiusOptions,
|
||||
state,
|
||||
editorThemePath
|
||||
editorValueToken
|
||||
} = props;
|
||||
|
||||
let options = cloneDeep(borderRadiusOptions || data.borderRadiusOptions);
|
||||
@ -57,10 +52,19 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
options = resolveVariableAndFilter(borderRadiusOptions, data, '| raw');
|
||||
}
|
||||
const [radiusType, setRadiusType] = useState<string>('all');
|
||||
const [isInherit, setIsInherit] = useState<boolean>(false);
|
||||
|
||||
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
let radiusToken;
|
||||
|
||||
if (editorValueToken) {
|
||||
radiusToken = {
|
||||
'top-right-border-radius': `${editorValueToken}-top-right-border-radius`,
|
||||
'top-left-border-radius': `${editorValueToken}-top-left-border-radius`,
|
||||
'bottom-right-border-radius': `${editorValueToken}-bottom-right-border-radius`,
|
||||
'bottom-left-border-radius': `${editorValueToken}-bottom-left-border-radius`
|
||||
};
|
||||
}
|
||||
|
||||
const editorDefaultValue = formatData(getDefaultValue(radiusToken, data));
|
||||
const borderData = formatData(value || {});
|
||||
|
||||
function formatData(sourceData: any) {
|
||||
@ -68,7 +72,7 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = formatInheritData(cloneDeep(sourceData));
|
||||
const data = cloneDeep(sourceData);
|
||||
if (
|
||||
data[`top-right-border-radius`] === data[`top-left-border-radius`] &&
|
||||
data[`top-left-border-radius`] === data[`bottom-right-border-radius`] &&
|
||||
@ -99,17 +103,7 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
const items = radiusItems;
|
||||
items.forEach(item => {
|
||||
let itemKey = `${item.item}-border-radius`;
|
||||
if (
|
||||
state &&
|
||||
state !== 'default' &&
|
||||
val?.includes('all-border-radius')
|
||||
) {
|
||||
const defaultToken = (key: string) =>
|
||||
`var(${data.default.token}${key})`;
|
||||
newValue[itemKey] = defaultToken(itemKey);
|
||||
} else {
|
||||
newValue[itemKey] = val;
|
||||
}
|
||||
newValue[itemKey] = val;
|
||||
});
|
||||
changeValue = {
|
||||
...value,
|
||||
@ -121,32 +115,10 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
[field]: val
|
||||
};
|
||||
}
|
||||
onChange(setInheritData(changeValue, editorInheritValue));
|
||||
setIsInherit(false);
|
||||
onChange(changeValue);
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (state && state !== 'default') {
|
||||
if (
|
||||
value['top-left-border-radius']?.includes(
|
||||
'default-top-left-border-radius'
|
||||
) &&
|
||||
value['top-right-border-radius']?.includes(
|
||||
'default-top-right-border-radius'
|
||||
) &&
|
||||
value['bottom-left-border-radius']?.includes(
|
||||
'default-bottom-left-border-radius'
|
||||
) &&
|
||||
value['bottom-right-border-radius']?.includes(
|
||||
'default-bottom-right-border-radius'
|
||||
)
|
||||
) {
|
||||
setIsInherit(true);
|
||||
}
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (borderData['all-border-radius'] === 'custom') {
|
||||
setRadiusType('custom');
|
||||
@ -185,17 +157,12 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
<ThemeSelect
|
||||
{...props}
|
||||
options={options}
|
||||
value={
|
||||
isInherit
|
||||
? `var(${data.default.token}all-border-radius)`
|
||||
: borderData[getKey('all')]
|
||||
}
|
||||
value={borderData[getKey('all')]}
|
||||
onChange={changeItem('all')}
|
||||
extraUnit={['px']}
|
||||
disabled={radiusType === 'custom'}
|
||||
itemName={'all-border-radius'}
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.[getKey('all')] || '圆角'}
|
||||
/>
|
||||
</div>
|
||||
@ -217,7 +184,6 @@ function BoxRadius(props: RadiusProps & RendererProps) {
|
||||
extraUnit={['px']}
|
||||
itemName={position + '-border-radius'}
|
||||
state={state}
|
||||
inheritValue={editorThemePath ? 'inherit' : ''}
|
||||
placeholder={editorDefaultValue?.[getKey(position)]}
|
||||
menuTpl="realValue"
|
||||
/>
|
||||
|
@ -16,7 +16,7 @@ import isEqual from 'lodash/isEqual';
|
||||
import {ThemeWrapperHeader} from './ThemeWrapper';
|
||||
import ColorPicker from './ColorPicker';
|
||||
import {Icon as ThemeIcon} from '../icons/index';
|
||||
import {getValueByPath, getInheritValue, setInheritData} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface ShadowEditorProps extends FormControlProps {}
|
||||
|
||||
@ -81,7 +81,7 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
colorOptions,
|
||||
state,
|
||||
itemName,
|
||||
editorThemePath
|
||||
editorValueToken
|
||||
} = props;
|
||||
const target = React.useRef<HTMLDivElement>(null);
|
||||
const [open, toggleOpen] = React.useState(true);
|
||||
@ -107,20 +107,13 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
? [...options, customShadow]
|
||||
: [...cloneDeep(data.shadowOptions || []), customShadow];
|
||||
|
||||
if (state && state !== 'default') {
|
||||
shadowOptions.unshift({
|
||||
value: editorThemePath ? 'inherit' : `var(${data.default.token}shadow)`,
|
||||
label: '继承常规',
|
||||
realValue: editorThemePath
|
||||
? ['继承常规']
|
||||
: [`var(${data.default.token}${itemName})`]
|
||||
});
|
||||
let shadowToken;
|
||||
if (editorValueToken) {
|
||||
shadowToken = `${editorValueToken}-shadow`;
|
||||
}
|
||||
const editorDefaultValue = getValueByPath(editorThemePath, data);
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
const editorDefaultValue = getDefaultValue(shadowToken, data);
|
||||
const defaultValue = value
|
||||
? (value.indexOf('inherit:') > -1 && 'inherit') ||
|
||||
find(cloneDeep(shadowOptions), item => item.value === value) ||
|
||||
? find(cloneDeep(shadowOptions), item => item.value === value) ||
|
||||
formateCustomValue(value)
|
||||
: null;
|
||||
|
||||
@ -137,6 +130,20 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
}
|
||||
}, [defaultValue]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (shadowData?.value === 'custom') {
|
||||
toggleSenior(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
function getLabel(value?: string, option?: any) {
|
||||
const res = option?.find((item: any) => item.value === value);
|
||||
if (res) {
|
||||
return res.label;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function formateCustomValue(value: string) {
|
||||
const color: PlainObject = {};
|
||||
let colorIndex = 0;
|
||||
@ -192,7 +199,7 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
const findItem = find(shadowOptions, item => item.value === value);
|
||||
if (findItem?.value) {
|
||||
setShadowData(findItem);
|
||||
onChange(setInheritData(findItem.value, editorInheritValue));
|
||||
onChange(findItem.value);
|
||||
}
|
||||
} else {
|
||||
setShadowData(undefined);
|
||||
@ -303,8 +310,19 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
close={() => {
|
||||
toggleViewShow(false);
|
||||
}}
|
||||
name={shadowData?.label || '无阴影'}
|
||||
value={formatRealValue(shadowData?.realValue).source}
|
||||
name={
|
||||
shadowData?.label ||
|
||||
getLabel(editorDefaultValue, shadowOptions) ||
|
||||
'无阴影'
|
||||
}
|
||||
value={
|
||||
formatRealValue(
|
||||
shadowData?.realValue ||
|
||||
shadowOptions.find(
|
||||
item => item.value === editorDefaultValue
|
||||
)?.realValue
|
||||
).source
|
||||
}
|
||||
/>
|
||||
<div className="Theme-ShadowEditor-item">
|
||||
<Select
|
||||
@ -314,11 +332,13 @@ function ShadowEditor(props: ShadowEditorProps) {
|
||||
onChange={(res: any) => {
|
||||
onShadowSelect(res.value);
|
||||
}}
|
||||
placeholder={editorDefaultValue || '无阴影'}
|
||||
placeholder={
|
||||
getLabel(editorDefaultValue, shadowOptions) || '无阴影'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{senior || shadowData?.value === 'custom' ? (
|
||||
{senior ? (
|
||||
<div className="Theme-ShadowEditor-customContent">
|
||||
<div className="Theme-Wrapper-header Theme-ShadowEditor-sub-header">
|
||||
<div className="Theme-Wrapper-header-left">阴影层</div>
|
||||
|
@ -12,12 +12,7 @@ import cx from 'classnames';
|
||||
import {Button} from 'amis-ui';
|
||||
import ThemeSelect from './ThemeSelect';
|
||||
import {find} from 'lodash';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface SizeEditorProps extends FormControlProps {
|
||||
hideWidth?: boolean;
|
||||
@ -34,7 +29,7 @@ function SizeEditor(props: SizeEditorProps) {
|
||||
hideWidth,
|
||||
hideHeight,
|
||||
hideMinWidth,
|
||||
editorThemePath,
|
||||
editorValue,
|
||||
label
|
||||
} = props;
|
||||
const [lock, setLockValue] = React.useState(0);
|
||||
@ -48,13 +43,12 @@ function SizeEditor(props: SizeEditorProps) {
|
||||
minWidth: ''
|
||||
});
|
||||
const RULE = /[0-9\.]*/;
|
||||
const editorDefaultValue = getValueByPath(editorThemePath, data);
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
const editorDefaultValue = getDefaultValue(editorValue, data);
|
||||
|
||||
React.useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (defaultValue) {
|
||||
setValue(formatInheritData(defaultValue));
|
||||
setValue(defaultValue);
|
||||
}
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
@ -76,7 +70,7 @@ function SizeEditor(props: SizeEditorProps) {
|
||||
value[key] = sizeFind ? sizeFind.value : valueTemp[key];
|
||||
}
|
||||
);
|
||||
onChange(setInheritData(value, editorInheritValue));
|
||||
onChange(value);
|
||||
return;
|
||||
}
|
||||
onChange(valueTemp);
|
||||
|
@ -10,12 +10,7 @@ import debounce from 'lodash/debounce';
|
||||
import {FormItem, resolveVariableAndFilter, highlight} from 'amis-core';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import cx from 'classnames';
|
||||
import {
|
||||
getValueByPath,
|
||||
getInheritValue,
|
||||
formatInheritData,
|
||||
setInheritData
|
||||
} from '../util';
|
||||
import {getDefaultValue} from '../util';
|
||||
|
||||
interface Option {
|
||||
label: any;
|
||||
@ -34,10 +29,8 @@ interface ThemeSelectProps {
|
||||
state?: string;
|
||||
itemName?: string;
|
||||
menuTpl?: string;
|
||||
inheritValue?: string;
|
||||
placeholder?: string;
|
||||
editorThemePath?: any;
|
||||
isEditorTpl?: boolean;
|
||||
editorValueToken?: string | {[key: string]: string};
|
||||
}
|
||||
|
||||
interface ThemeSelectContentProps extends ThemeSelectProps {
|
||||
@ -59,19 +52,17 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
disabled,
|
||||
menuTpl,
|
||||
placeholder,
|
||||
editorThemePath,
|
||||
data,
|
||||
isEditorTpl
|
||||
editorValueToken,
|
||||
data
|
||||
} = props;
|
||||
// 期望value是string类型
|
||||
const value = String(formatInheritData(props.value));
|
||||
const value = props.value + '';
|
||||
const input = useRef<HTMLInputElement>(null);
|
||||
const [currentItem, setCurrentItem] = useState<Option | undefined>(undefined);
|
||||
const [options, setOptions] = useState<Option[] | undefined>(originalOptions);
|
||||
const [showOptions, setShowOptions] = useState(false);
|
||||
|
||||
const editorDefaultValue = getValueByPath(editorThemePath, data);
|
||||
const editorInheritValue = getInheritValue(editorThemePath, data);
|
||||
const editorDefaultValue = getDefaultValue(editorValueToken, data);
|
||||
|
||||
useEffect(() => {
|
||||
const res = originalOptions?.find(item => item.value === value);
|
||||
@ -83,9 +74,6 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
}, [value]);
|
||||
|
||||
function getRealValue(value?: string) {
|
||||
if (value === 'inherit') {
|
||||
return '继承常规';
|
||||
}
|
||||
const res = originalOptions?.find(item => item.value === value);
|
||||
if (res) {
|
||||
return res.label;
|
||||
@ -149,9 +137,7 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
function valueOnChange(value: string) {
|
||||
return debounce(() => {
|
||||
if (value) {
|
||||
onChange(
|
||||
isEditorTpl ? setInheritData(value, editorInheritValue) : value
|
||||
);
|
||||
onChange(value);
|
||||
} else {
|
||||
onChange(undefined);
|
||||
}
|
||||
@ -165,9 +151,7 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
}
|
||||
|
||||
function onSelectValue(item: Option) {
|
||||
onChange(
|
||||
isEditorTpl ? setInheritData(item.value, editorInheritValue) : item.value
|
||||
);
|
||||
onChange(item.value);
|
||||
setShowOptions(false);
|
||||
input.current && (input.current.value = item.value);
|
||||
}
|
||||
@ -178,15 +162,11 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const tooltipLabel =
|
||||
value === 'inherit' ? '继承常规' : currentItem?.label || '分别配置';
|
||||
const tooltipLabel = currentItem?.label || '分别配置';
|
||||
|
||||
return (
|
||||
<>
|
||||
{currentItem ||
|
||||
value === 'custom' ||
|
||||
value?.includes('var') ||
|
||||
value === 'inherit' ? (
|
||||
{currentItem || value === 'custom' || value?.includes('var') ? (
|
||||
<div
|
||||
onClick={openOptions}
|
||||
className={cx(
|
||||
@ -233,9 +213,7 @@ function ThemeSelectContent(props: ThemeSelectContentProps) {
|
||||
onFocus={openOptions}
|
||||
ref={input}
|
||||
disabled={disabled}
|
||||
placeholder={getRealValue(
|
||||
isEditorTpl ? editorDefaultValue : placeholder
|
||||
)}
|
||||
placeholder={getRealValue(placeholder || editorDefaultValue)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -279,11 +257,7 @@ function ThemeSelect(props: ThemeSelectProps) {
|
||||
value: originValue,
|
||||
options: originOptions,
|
||||
extraUnit = ['px', 'rem', '%'],
|
||||
disabled,
|
||||
state,
|
||||
itemName,
|
||||
inheritValue,
|
||||
isEditorTpl
|
||||
disabled
|
||||
} = props;
|
||||
const themeSelect = useRef<HTMLDivElement>(null);
|
||||
const [options, setOptions] = React.useState<Option[]>(getOptions());
|
||||
@ -291,26 +265,10 @@ function ThemeSelect(props: ThemeSelectProps) {
|
||||
const list = cloneDeep(
|
||||
typeof originOptions === 'string'
|
||||
? resolveVariableAndFilter(originOptions, data, '| raw')
|
||||
: isEditorTpl && !originOptions
|
||||
: !originOptions
|
||||
? data?.sizesOptions || []
|
||||
: originOptions || []
|
||||
);
|
||||
|
||||
if (
|
||||
state &&
|
||||
state !== 'default' &&
|
||||
list[0] &&
|
||||
list[0].value !== `var(${data?.default?.token}${itemName})`
|
||||
) {
|
||||
const name = isEditorTpl
|
||||
? 'inherit'
|
||||
: `var(${data?.default?.token}${itemName})`;
|
||||
list.unshift({
|
||||
label: '继承常规',
|
||||
value: inheritValue || name,
|
||||
realValue: '继承常规'
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
useEffect(() => {
|
||||
|
@ -45,7 +45,10 @@ export function ThemeWrapperHeader(props: ThemeWrapperProps) {
|
||||
>
|
||||
<ThemeIcon
|
||||
icon="custom"
|
||||
className="common-icon"
|
||||
className={cx(
|
||||
'common-icon',
|
||||
senior ? 'common-icon--active' : ''
|
||||
)}
|
||||
onClick={() => toggleSenior && toggleSenior(!senior)}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
|
@ -9,6 +9,7 @@ $ns: cxd-;
|
||||
padding: 0 px2rem(8px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
.ThemeSelectContent-theme {
|
||||
background-color: #f7f8fa;
|
||||
border-radius: 2px;
|
||||
|
@ -7,6 +7,9 @@ $ns: cxd-;
|
||||
cursor: pointer;
|
||||
color: #5c5f66;
|
||||
}
|
||||
.common-icon--active {
|
||||
color: #2468f2;
|
||||
}
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
|
@ -3912,7 +3912,7 @@ const component: ThemeDefinition['component'] = {
|
||||
paddingLeft: 'var(--sizes-size-7)',
|
||||
paddingRight: 'var(--sizes-size-7)'
|
||||
},
|
||||
bg: 'var(--colors-neutral-fill-11)',
|
||||
bg: 'var(--colors-neutral-fill-none)',
|
||||
border: {
|
||||
'top-border-color': 'var(--colors-neutral-line-8)',
|
||||
'top-border-width': 'var(--borders-width-2)',
|
||||
@ -6006,11 +6006,12 @@ const component: ThemeDefinition['component'] = {
|
||||
'border-width': 'var(--borders-width-2)',
|
||||
'border-color': 'var(--colors-neutral-line-8)',
|
||||
'padding-and-margin': {
|
||||
paddingTop: 'var(--sizes-size-6)',
|
||||
paddingTop: 'var(--sizes-size-3)',
|
||||
paddingRight: 'var(--sizes-size-6)',
|
||||
paddingBottom: 'var(--sizes-size-6)',
|
||||
paddingBottom: 'var(--sizes-size-3)',
|
||||
paddingLeft: 'var(--sizes-size-6)'
|
||||
},
|
||||
'line-height': 'var(--sizes-base-20)',
|
||||
'paddingX': 'var(--sizes-size-7)',
|
||||
'header-font': {
|
||||
color: 'var(--colors-neutral-text-2)',
|
||||
|
@ -1,64 +1,57 @@
|
||||
import {PlainObject, filter} from 'amis-core';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
const THEME_CSS_VAR = [
|
||||
'--colors',
|
||||
'--sizes',
|
||||
'--borders',
|
||||
'--fonts',
|
||||
'--shadows'
|
||||
];
|
||||
|
||||
function getCssKey(key: string) {
|
||||
return key?.replace('var(', '').replace(')', '');
|
||||
}
|
||||
|
||||
function isThemeCssVar(key: string) {
|
||||
// 是否以主题变量开头
|
||||
return THEME_CSS_VAR.some(item => getCssKey(key)?.startsWith(item));
|
||||
}
|
||||
/**
|
||||
* 根据路径获取默认值
|
||||
*/
|
||||
export function getValueByPath(path: string | string[], data: any): any {
|
||||
try {
|
||||
if (!path || !data) {
|
||||
return null;
|
||||
}
|
||||
let res = {};
|
||||
const getValue = (p: string) => {
|
||||
const keys = p.split('.');
|
||||
let value = cloneDeep(data.themeConfig.component);
|
||||
let defaultToken = '';
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let key = keys[i];
|
||||
const isVar = /\$\{(.*)\}/.exec(key) || [];
|
||||
if (isVar[1]) {
|
||||
key = data[isVar[1]] || 'default';
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
value = value.find(n => n.type === key);
|
||||
} else {
|
||||
if (key === 'hover' || key === 'active' || key === 'disabled') {
|
||||
defaultToken = value['default'].token;
|
||||
}
|
||||
value = value[key];
|
||||
}
|
||||
export function getDefaultValue(
|
||||
editorValue?: string | {[key: string]: string},
|
||||
data?: any
|
||||
): any {
|
||||
if (editorValue) {
|
||||
if (typeof editorValue === 'string') {
|
||||
const key = filter(editorValue, data);
|
||||
const value = data.cssVars[key];
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (defaultToken && value) {
|
||||
// 继承default
|
||||
if (typeof value === 'object') {
|
||||
for (let key in value) {
|
||||
if (value[key] === `var(${defaultToken}${key})`) {
|
||||
value[key] = 'inherit';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (value === `var(${defaultToken}${keys[keys.length - 1]})`) {
|
||||
value = 'inherit';
|
||||
}
|
||||
}
|
||||
if (isThemeCssVar(value)) {
|
||||
return value;
|
||||
} else {
|
||||
return getDefaultValue(getCssKey(value), data);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
if (Array.isArray(path)) {
|
||||
path.forEach(p => {
|
||||
let value = getValue(p);
|
||||
if (typeof value === 'string') {
|
||||
value = {color: value};
|
||||
}
|
||||
res = Object.assign(res, value);
|
||||
});
|
||||
} else {
|
||||
res = getValue(path);
|
||||
const res: PlainObject = {};
|
||||
Object.keys(editorValue).forEach(k => {
|
||||
const key = filter(editorValue[k], data);
|
||||
const value = data.cssVars[key];
|
||||
if (!value) {
|
||||
res[k] = value;
|
||||
}
|
||||
if (isThemeCssVar(value)) {
|
||||
res[k] = value;
|
||||
} else {
|
||||
res[k] = getDefaultValue(getCssKey(value), data);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1634,7 +1634,6 @@
|
||||
--Form-item-gap: var(--sizes-base-12);
|
||||
--Form-item-mobile-gap: var(--sizes-base-4);
|
||||
--Form-item-color: var(--colors-neutral-text-4);
|
||||
--Form-item-fontColor: var(--Form-item-color);
|
||||
--Form-item-fontSize: var(--fonts-size-7);
|
||||
--Form-item-fontWeight: var(--fonts-weight-6);
|
||||
--Form-item-lineHeight: var(--fonts-lineHeight-1);
|
||||
@ -2449,7 +2448,7 @@
|
||||
--Tabs--chrome-right-border-color: var(--colors-neutral-line-5);
|
||||
|
||||
// 面板 Panel
|
||||
--Panel-bg: var(--colors-neutral-fill-11);
|
||||
--Panel-bg-color: var(--colors-neutral-fill-11);
|
||||
--Panel-marginTop: var(--sizes-size-0);
|
||||
--Panel-marginBottom: var(--sizes-base-10);
|
||||
--Panel-marginLeft: var(--sizes-size-0);
|
||||
@ -2476,12 +2475,12 @@
|
||||
--Panel-borderWidth: var(--Panel-top-border-width)
|
||||
var(--Panel-right-border-width) var(--Panel-bottom-border-width)
|
||||
var(--Panel-left-border-width);
|
||||
--Panel-boxShadow: var(--shadows-shadow-sm);
|
||||
--Panel-shadow: var(--shadows-shadow-sm);
|
||||
--Panel-heading-paddingTop: var(--sizes-size-5);
|
||||
--Panel-heading-paddingBottom: var(--sizes-size-5);
|
||||
--Panel-heading-paddingLeft: var(--sizes-size-7);
|
||||
--Panel-heading-paddingRight: var(--sizes-size-7);
|
||||
--Panel-heading-bg: var(--colors-neutral-fill-10);
|
||||
--Panel-heading-bg-color: var(--colors-neutral-fill-10);
|
||||
--Panel-heading-color: var(--colors-neutral-text-3);
|
||||
--Panel-heading-fontSize: var(--fonts-size-8);
|
||||
--Panel-heading-fontWeight: var(--fonts-weight-6);
|
||||
@ -2514,7 +2513,7 @@
|
||||
--Panel-footer-paddingBottom: var(--sizes-size-5);
|
||||
--Panel-footer-paddingLeft: var(--sizes-size-7);
|
||||
--Panel-footer-paddingRight: var(--sizes-size-7);
|
||||
--Panel-footer-bg: var(--colors-neutral-fill-11);
|
||||
--Panel-footer-bg-color: var(--colors-neutral-fill-none);
|
||||
--Panel-footer-top-border-color: var(--colors-neutral-line-8);
|
||||
--Panel-footer-top-border-width: var(--borders-width-2);
|
||||
--Panel-footer-top-border-style: var(--borders-style-2);
|
||||
@ -2529,7 +2528,7 @@
|
||||
--Panel-footer-left-border-style: var(--borders-style-2);
|
||||
--Panel-footerBorderRadius: 0 0 var(--Panel-bottom-right-border-radius)
|
||||
var(--Panel-bottom-left-border-radius);
|
||||
--Panel-footerBg: var(--Panel-footer-bg);
|
||||
--Panel-footerBg: var(--Panel-footer-bg-color);
|
||||
--Panel-footerPadding: var(--Panel-footer-paddingTop)
|
||||
var(--Panel-footer-paddingRight) var(--Panel-footer-paddingBottom)
|
||||
var(--Panel-footer-paddingLeft);
|
||||
@ -3327,7 +3326,7 @@
|
||||
--image-image-normal-title-marginTop: var(--sizes-size-0);
|
||||
--image-image-description-color: var(--colors-neutral-text-2);
|
||||
--image-image-description-fontSize: var(--fonts-size-8);
|
||||
--image-image-description-marginTop: var(--fonts-size-0);
|
||||
--image-image-description-marginTop: var(--sizes-size-0);
|
||||
--image-image-normal-icon: '<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd"><g><rect opacity="0" x="0.5" y="0.5" width="15" height="15"></rect><path d="M7.9999,3.0001 C11.9889,3.0001 14.9999,6.8731 14.9999,8.0001 C14.9999,8.8831 11.9889,13.0001 7.9999,13.0001 C3.9609,13.0001 0.9999,8.8831 0.9999,8.0001 C0.9999,6.8731 3.9609,3.0001 7.9999,3.0001 Z M7.9999,4.0001 C4.7329,4.0001 2.2179,7.0861 2.0089,7.9731 C2.2749,8.7711 4.7189,12.0001 7.9999,12.0001 C11.2099,12.0001 13.7339,8.7311 13.9929,7.9631 C13.8069,7.1261 11.2709,4.0001 7.9999,4.0001 Z M7.975,5.879 C9.08,5.879 9.975,6.775 9.975,7.879 C9.975,8.983 9.08,9.879 7.975,9.879 C6.871,9.879 5.975,8.983 5.975,7.879 C5.975,6.775 6.871,5.879 7.975,5.879 Z M7.975,6.879 C7.424,6.879 6.975,7.327 6.975,7.879 C6.975,8.43 7.424,8.879 7.975,8.879 C8.527,8.879 8.975,8.43 8.975,7.879 C8.975,7.327 8.527,6.879 7.975,6.879 Z" ></path></g></g></svg>';
|
||||
|
||||
--image-images-item-marginTop: var(--sizes-size-3);
|
||||
@ -3643,7 +3642,6 @@
|
||||
--Pick-base-icon-color: #84878c;
|
||||
--Pick-base-value-hover-icon-color: #b3d7ff;
|
||||
--Pick-base-value-icon-color: var(--colors-other-5);
|
||||
--Picker-iconColor: var(--Pick-base-icon-color);
|
||||
--Picker-onHover-iconColor: var(--icon-onHover-color);
|
||||
--Picker-tag-height: #{px2rem(24px)};
|
||||
--Picker-tag-marginBottom: var(--select-multiple-marginBottom);
|
||||
@ -3659,7 +3657,7 @@
|
||||
--Pick-status-hover-left-border-color: var(--colors-other-5);
|
||||
--Pick-status-hover-left-border-width: var(--borders-width-2);
|
||||
--Pick-status-hover-left-border-style: var(--borders-style-2);
|
||||
--Pick-status-hover-bgColor: var(--colors-neutral-line-11);
|
||||
--Pick-status-hover-bgColor: var(--colors-neutral-fill-11);
|
||||
--Pick-status-focus-top-border-color: var(--colors-other-7);
|
||||
--Pick-status-focus-top-border-width: var(--borders-width-2);
|
||||
--Pick-status-focus-top-border-style: var(--borders-style-2);
|
||||
@ -3673,7 +3671,7 @@
|
||||
--Pick-status-focus-left-border-width: var(--borders-width-2);
|
||||
--Pick-status-focus-left-border-style: var(--borders-style-2);
|
||||
--Pick-status-focus-shadow: var(--shadows-shadow-none);
|
||||
--Pick-status-focus-bgColor: var(--colors-neutral-line-11);
|
||||
--Pick-status-focus-bgColor: var(--colors-neutral-fill-11);
|
||||
--Pick-status-disabled-color: var(--colors-neutral-text-2);
|
||||
--Pick-status-disabled-fontSize: var(--fonts-size-7);
|
||||
--Pick-status-disabled-fontWeight: var(--fonts-weight-6);
|
||||
@ -3689,7 +3687,7 @@
|
||||
--Pick-status-disabled-left-border-color: var(--colors-neutral-line-8);
|
||||
--Pick-status-disabled-left-border-width: var(--borders-width-2);
|
||||
--Pick-status-disabled-left-border-style: var(--borders-style-2);
|
||||
--Pick-status-disabled-bgColor: var(--colors-neutral-text-10);
|
||||
--Pick-status-disabled-bgColor: var(--colors-neutral-fill-10);
|
||||
--Pick-status-disabled-color: var(--colors-neutral-line-6);
|
||||
--Pick-status-disabled-fontSize: var(--fonts-size-7);
|
||||
--Pick-status-disabled-fontWeight: var(--fonts-weight-6);
|
||||
@ -3934,9 +3932,9 @@
|
||||
|
||||
--table-border-width: var(--borders-width-2);
|
||||
--table-border-color: var(--colors-neutral-line-8);
|
||||
--table-paddingTop: var(--sizes-size-6);
|
||||
--table-paddingTop: var(--sizes-size-3);
|
||||
--table-paddingRight: var(--sizes-size-6);
|
||||
--table-paddingBottom: var(--sizes-size-6);
|
||||
--table-paddingBottom: var(--sizes-size-3);
|
||||
--table-paddingLeft: var(--sizes-size-6);
|
||||
--table-paddingX: var(--sizes-size-7);
|
||||
--table-header-color: var(--colors-neutral-text-2);
|
||||
@ -3949,8 +3947,10 @@
|
||||
--table-body-color: var(--colors-neutral-text-2);
|
||||
--table-body-fontSize: var(--fonts-size-8);
|
||||
--table-body-fontWeight: var(--fonts-weight-6);
|
||||
--table-body-line-height: var(--sizes-base-20);
|
||||
--table-body-lineHeight: var(--fonts-lineHeight-2);
|
||||
--table-body-bg-color: var(--colors-neutral-fill-11);
|
||||
--table-body-default-bg-color: var(--table-body-bg-color);
|
||||
--table-body-hover-color: var(--colors-neutral-text-2);
|
||||
--table-body-hover-bg-color: var(--colors-brand-10);
|
||||
--table-body-hover-border-color: var(--colors-neutral-line-8);
|
||||
@ -4260,4 +4260,9 @@
|
||||
|
||||
--common-popover-border: var(--borders-width-2) solid
|
||||
var(--colors-neutral-fill-9);
|
||||
|
||||
--Form-static-fontSize: var(--fonts-size-7);
|
||||
--Form-static-color: var(--colors-neutral-text-2);
|
||||
--Form-static-lineHeight: var(--fonts-lineHeight-2);
|
||||
--Form-static-fontWeight: var(--fonts-weight-6);
|
||||
}
|
||||
|
@ -611,7 +611,6 @@ $Table-strip-bg: transparent;
|
||||
--Panel--default-badgeBg: var(--colors-neutral-fill-3);
|
||||
--Panel--default-badgeColor: var(--colors-neutral-fill-10);
|
||||
|
||||
--Picker-iconColor: var(--icon-color);
|
||||
--Picker-onHover-iconColor: var(--icon-onHover-color);
|
||||
|
||||
--PickerColumns-bg: white;
|
||||
@ -837,7 +836,7 @@ $Table-strip-bg: transparent;
|
||||
--IconSelect-sm-padding: #{px2rem(6px)};
|
||||
--IconSelect-base-border-radius: var(--borderRadiusMd);
|
||||
--IconSelect-border-color: var(--menu-border-color);
|
||||
--IconSelect-preivew-icon-size: #{px2rem(16px)};
|
||||
--IconSelect-preview-icon-size: #{px2rem(16px)};
|
||||
--IconSelect-list-icon-size: #{px2rem(24px)};
|
||||
--IconSelect-type-font-size: var(--fontSizeSm);
|
||||
--IconSelect-active-badge-color: var(--colors-neutral-fill-11);
|
||||
|
@ -1,7 +1,7 @@
|
||||
.#{$ns}Panel {
|
||||
margin: var(--Panel-marginTop) var(--Panel-marginRight)
|
||||
var(--Panel-marginBottom) var(--Panel-marginLeft);
|
||||
background: var(--Panel-bg);
|
||||
background: var(--Panel-bg-color);
|
||||
border-color: var(--Panel-top-border-color) var(--Panel-right-border-color)
|
||||
var(--Panel-bottom-border-color) var(--Panel-left-border-color);
|
||||
border-style: var(--Panel-top-border-style) var(--Panel-right-border-style)
|
||||
@ -9,7 +9,7 @@
|
||||
border-width: var(--Panel-borderWidth);
|
||||
border-radius: var(--Panel-borderRadius);
|
||||
-webkit-box-shadow: var(--Panel-boxShadow);
|
||||
box-shadow: var(--Panel-boxShadow);
|
||||
box-shadow: var(--Panel-shadow);
|
||||
|
||||
&-fixedBottom {
|
||||
position: sticky;
|
||||
@ -24,7 +24,7 @@
|
||||
var(--Panel-bottom-border-color) var(--Panel-left-border-color);
|
||||
|
||||
> .#{$ns}Panel-heading {
|
||||
background: var(--Panel-heading-bg);
|
||||
background: var(--Panel-heading-bg-color);
|
||||
color: var(--Panel-heading-color);
|
||||
|
||||
.badge {
|
||||
|
@ -224,6 +224,7 @@
|
||||
& th,
|
||||
& td {
|
||||
text-align: left;
|
||||
border-color: transparent;
|
||||
border-bottom: var(--Table-borderWidth) solid var(--Table-borderColor);
|
||||
|
||||
&.is-sticky {
|
||||
|
@ -193,6 +193,8 @@
|
||||
|
||||
> thead > tr {
|
||||
> th {
|
||||
height: var(--table-body-line-height);
|
||||
vertical-align: middle;
|
||||
background: var(--Table-thead-bg);
|
||||
padding: var(--table-paddingTop) var(--table-paddingRight)
|
||||
var(--table-paddingBottom) var(--table-paddingLeft);
|
||||
@ -259,6 +261,8 @@
|
||||
|
||||
> td,
|
||||
> th {
|
||||
height: px2rem(40px);
|
||||
vertical-align: middle;
|
||||
padding: var(--table-paddingTop) var(--table-paddingRight)
|
||||
var(--table-paddingBottom) var(--table-paddingLeft);
|
||||
|
||||
@ -283,6 +287,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}Form-static {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-height: inherit;
|
||||
line-height: inherit;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.#{$ns}Table-cell-height-large {
|
||||
height: var(--TableCell-line-height-large);
|
||||
line-height: var(--TableCell-line-height-large);
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
.#{$ns}Form-static {
|
||||
min-height: var(--Form-input-height);
|
||||
font-size: var(--Form-static-fontSize);
|
||||
color: var(--Form-static-color);
|
||||
line-height: var(--Form-static-lineHeight);
|
||||
font-weight: var(--Form-static-fontWeight);
|
||||
&:not(.is-noPaddingY-static) {
|
||||
padding-top: var(--Form-label-paddingTop);
|
||||
padding-bottom: var(--Form-label-paddingTop);
|
||||
@ -57,7 +61,7 @@
|
||||
margin-bottom: var(--Form-mode-default-labelGap);
|
||||
position: relative;
|
||||
font-size: var(--Form-item-fontSize);
|
||||
color: var(--Form-item-fontColor);
|
||||
color: var(--Form-item-color);
|
||||
|
||||
> span {
|
||||
position: relative;
|
||||
|
@ -51,9 +51,10 @@
|
||||
|
||||
&-input {
|
||||
overflow: hidden;
|
||||
height: px2rem(32px);
|
||||
|
||||
&-area {
|
||||
min-height: var(--IconSelect-preivew-icon-size);
|
||||
min-height: var(--IconSelect-preview-icon-size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
@ -83,8 +84,8 @@
|
||||
&-icon {
|
||||
&-show {
|
||||
& > svg {
|
||||
width: var(--IconSelect-preivew-icon-size);
|
||||
height: var(--IconSelect-preivew-icon-size);
|
||||
width: var(--IconSelect-preview-icon-size);
|
||||
height: var(--IconSelect-preview-icon-size);
|
||||
margin-right: var(--IconSelect-xs-margin);
|
||||
top: px2rem(3px);
|
||||
}
|
||||
@ -97,6 +98,7 @@
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
|
@ -319,7 +319,7 @@
|
||||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
> a {
|
||||
color: var(--Form-item-fontColor);
|
||||
color: var(--Form-item-color);
|
||||
padding: 2px 5px;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
|
@ -120,7 +120,7 @@
|
||||
|
||||
&-btn {
|
||||
cursor: pointer;
|
||||
color: var(--Picker-iconColor);
|
||||
color: var(--Pick-base-icon-color);
|
||||
flex: 30px 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -185,7 +185,8 @@ export class Textarea extends React.Component<TextAreaProps, TextAreaState> {
|
||||
maxLength,
|
||||
showCounter,
|
||||
clearable,
|
||||
testIdBuilder
|
||||
testIdBuilder,
|
||||
style
|
||||
} = this.props;
|
||||
const counter = showCounter ? this.valueToString(value).length : 0;
|
||||
|
||||
@ -200,6 +201,7 @@ export class Textarea extends React.Component<TextAreaProps, TextAreaState> {
|
||||
},
|
||||
className
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
<BaseTextArea
|
||||
className={cx(`TextareaControl-input`, {
|
||||
|
@ -133,7 +133,8 @@ export default class Head extends React.PureComponent<Props> {
|
||||
onSelectAll,
|
||||
onFilter,
|
||||
onResizeMouseDown,
|
||||
testIdBuilder
|
||||
testIdBuilder,
|
||||
className
|
||||
} = this.props;
|
||||
|
||||
const {thColumns, tdColumns} = getBuildColumns(columns);
|
||||
@ -142,7 +143,7 @@ export default class Head extends React.PureComponent<Props> {
|
||||
|
||||
// 获取一行最多th个数
|
||||
let maxCount = 0;
|
||||
columns.forEach(cols => {
|
||||
this.thColumns.forEach(cols => {
|
||||
if (cols.length > maxCount) {
|
||||
maxCount = cols.length;
|
||||
}
|
||||
@ -174,9 +175,9 @@ export default class Head extends React.PureComponent<Props> {
|
||||
const selectedKeys = selectedRowKeys.filter((key: number | string) =>
|
||||
rowKeys.includes(key)
|
||||
);
|
||||
|
||||
let thIndex = 0;
|
||||
return (
|
||||
<thead ref={this.domRef} className={cx('Table-thead')}>
|
||||
<thead ref={this.domRef} className={cx('Table-thead', className)}>
|
||||
{this.thColumns.map((data, index) => {
|
||||
return (
|
||||
<tr key={'th-cell-' + index}>
|
||||
@ -239,6 +240,7 @@ export default class Head extends React.PureComponent<Props> {
|
||||
) : null}
|
||||
{isLeftExpandable && index === 0 ? expandableCell : null}
|
||||
{data.map((item: any, colIndex: number) => {
|
||||
thIndex++;
|
||||
let sort = null;
|
||||
if (item.sorter) {
|
||||
sort = (
|
||||
@ -315,9 +317,7 @@ export default class Head extends React.PureComponent<Props> {
|
||||
classPrefix={classPrefix}
|
||||
fixed={item.fixed === true ? 'left' : item.fixed}
|
||||
className={cx({
|
||||
'Table-cell-last':
|
||||
colIndex === maxCount - 1 &&
|
||||
colIndex === data.length - 1
|
||||
'Table-cell-last': thIndex === maxCount
|
||||
})}
|
||||
depth={item.depth}
|
||||
col={String(colIndex)}
|
||||
|
@ -139,6 +139,9 @@ export interface TableProps extends ThemeProps, LocaleProps, SpinnerExtraProps {
|
||||
className?: string;
|
||||
dataSource: Array<any>;
|
||||
classnames: ClassNamesFn;
|
||||
headerClassName?: string;
|
||||
bodyClassname?: string;
|
||||
rowClassname?: string;
|
||||
columns: Array<ColumnProps>;
|
||||
scroll?: ScrollProps;
|
||||
rowSelection?: RowSelectionProps;
|
||||
@ -686,7 +689,8 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
onSort,
|
||||
onSelectAll,
|
||||
onFilter,
|
||||
testIdBuilder
|
||||
testIdBuilder,
|
||||
headerClassName
|
||||
} = this.props;
|
||||
|
||||
const rowSelectionKeyField = this.getRowSelectionKeyField();
|
||||
@ -721,6 +725,7 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
orderBy={this.state.sort?.orderBy}
|
||||
popOverContainer={this.getPopOverContainer}
|
||||
classnames={cx}
|
||||
className={headerClassName}
|
||||
classPrefix={classPrefix}
|
||||
onSort={(payload: SortProps, column: ColumnProps) => {
|
||||
this.setState({
|
||||
@ -1296,7 +1301,8 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
showHeader,
|
||||
itemActions,
|
||||
tableLayout,
|
||||
classnames: cx
|
||||
classnames: cx,
|
||||
bodyClassname
|
||||
} = this.props;
|
||||
|
||||
const hasScrollX = scroll && scroll.x;
|
||||
@ -1326,7 +1332,7 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
...tableStyle,
|
||||
tableLayout: tableLayout === 'fixed' ? 'fixed' : 'auto'
|
||||
}}
|
||||
className={cx('Table-table')}
|
||||
className={cx('Table-table', bodyClassname)}
|
||||
>
|
||||
{this.renderColGroup()}
|
||||
{showHeader ? this.renderHead() : null}
|
||||
@ -1343,7 +1349,8 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
headSummary,
|
||||
sticky,
|
||||
showHeader,
|
||||
classnames: cx
|
||||
classnames: cx,
|
||||
headerClassName
|
||||
} = this.props;
|
||||
|
||||
const style = {overflow: 'hidden'};
|
||||
@ -1354,16 +1361,25 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
const tableStyle = {};
|
||||
if (scroll && (scroll.y || scroll.x)) {
|
||||
Object.assign(tableStyle, {
|
||||
width: scroll && scroll.x ? scroll.x + 'px' : '100%'
|
||||
width:
|
||||
scroll && scroll.x
|
||||
? typeof scroll.x === 'number'
|
||||
? scroll.x + 'px'
|
||||
: scroll.x
|
||||
: '100%'
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.headerDom}
|
||||
className={cx('Table-header', {
|
||||
[cx('Table-sticky-holder')]: !!sticky
|
||||
})}
|
||||
className={cx(
|
||||
'Table-header',
|
||||
{
|
||||
[cx('Table-sticky-holder')]: !!sticky
|
||||
},
|
||||
headerClassName
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
<table
|
||||
@ -1381,7 +1397,7 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
}
|
||||
|
||||
renderScrollTableBody() {
|
||||
const {scroll, itemActions, classnames: cx} = this.props;
|
||||
const {scroll, itemActions, classnames: cx, bodyClassname} = this.props;
|
||||
|
||||
const style = {};
|
||||
const tableStyle = {};
|
||||
@ -1392,7 +1408,12 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
});
|
||||
|
||||
Object.assign(tableStyle, {
|
||||
width: scroll && scroll.x ? scroll.x + 'px' : '100%'
|
||||
width:
|
||||
scroll && scroll.x
|
||||
? typeof scroll.x === 'number'
|
||||
? scroll.x + 'px'
|
||||
: scroll.x
|
||||
: '100%'
|
||||
});
|
||||
}
|
||||
|
||||
@ -1414,7 +1435,7 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
</ItemActionsWrapper>
|
||||
) : null}
|
||||
<table
|
||||
className={cx('Table-table')}
|
||||
className={cx('Table-table', bodyClassname)}
|
||||
style={{...tableStyle, tableLayout: 'fixed'}}
|
||||
>
|
||||
{this.renderColGroup()}
|
||||
|
@ -30,7 +30,7 @@ exports[`1. Renderer:Picker base 1`] = `
|
||||
class="cxd-Picker cxd-Picker--single is-focused"
|
||||
>
|
||||
<div
|
||||
class="cxd-Picker-input"
|
||||
class="cxd-Picker-input is-focused"
|
||||
>
|
||||
<div
|
||||
class="cxd-Picker-placeholder"
|
||||
@ -247,7 +247,7 @@ exports[`1. Renderer:Picker base 2`] = `
|
||||
class="cxd-Picker cxd-Picker--single is-focused"
|
||||
>
|
||||
<div
|
||||
class="cxd-Picker-input"
|
||||
class="cxd-Picker-input is-focused"
|
||||
>
|
||||
<div
|
||||
class="cxd-Picker-valueWrap"
|
||||
|
@ -1379,7 +1379,8 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
|
||||
type: mode,
|
||||
columns: mode.startsWith('table')
|
||||
? store.columns || columns
|
||||
: undefined
|
||||
: undefined,
|
||||
id
|
||||
},
|
||||
{
|
||||
key: 'body',
|
||||
|
@ -79,23 +79,36 @@ export default class IconSelectControl extends React.PureComponent<
|
||||
);
|
||||
}
|
||||
|
||||
getValueBySvg(svg: string | undefined): IconSelectStore.SvgIcon | null {
|
||||
if (!svg || typeof svg !== 'string') {
|
||||
getSvgName(value: IconChecked | string) {
|
||||
if (typeof value === 'string') {
|
||||
return /data-name="(.*?)"/.exec(value)?.[1] || '';
|
||||
} else {
|
||||
return value?.name || value?.id || '';
|
||||
}
|
||||
}
|
||||
|
||||
getSvgId(value: IconChecked | string) {
|
||||
if (typeof value === 'string') {
|
||||
return /data-id="(.*?)"/.exec(value)?.[1] || '';
|
||||
} else {
|
||||
return value?.id || '';
|
||||
}
|
||||
}
|
||||
|
||||
getValueBySvg(
|
||||
svg: string | IconSelectStore.SvgIcon
|
||||
): IconSelectStore.SvgIcon | null {
|
||||
if (!svg) {
|
||||
return null;
|
||||
}
|
||||
let findItem: IconSelectStore.SvgIcon | undefined = undefined;
|
||||
if (IconSelectStore.svgIcons && IconSelectStore.svgIcons.length) {
|
||||
for (let i = 0; i < IconSelectStore.svgIcons.length; i++) {
|
||||
findItem = find(
|
||||
IconSelectStore.svgIcons[i].children,
|
||||
i => i.svg === svg
|
||||
);
|
||||
if (findItem) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof svg !== 'string') {
|
||||
return svg;
|
||||
}
|
||||
return findItem || {name: svg, id: '', svg: ''};
|
||||
|
||||
const svgName = this.getSvgName(svg);
|
||||
const svgId = this.getSvgId(svg);
|
||||
return {name: svgName, id: svgId, svg: svg.replace(/'/g, '')};
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -124,18 +137,18 @@ export default class IconSelectControl extends React.PureComponent<
|
||||
clearable
|
||||
} = this.props;
|
||||
|
||||
const iconName = value?.name || value;
|
||||
const svg = this.getValueBySvg(value);
|
||||
|
||||
return (
|
||||
<div className={cx(`${ns}IconSelectControl-input-area`)}>
|
||||
<div className={cx(`${ns}IconSelectControl-input-icon-show`)}>
|
||||
<Icon icon={value} className="icon" />
|
||||
<Icon icon={svg?.svg} className="icon" />
|
||||
</div>
|
||||
<span className={cx(`${ns}IconSelectControl-input-icon-id`)}>
|
||||
{iconName}
|
||||
{svg?.name}
|
||||
</span>
|
||||
|
||||
{clearable && !disabled && value ? (
|
||||
{clearable && !disabled && svg ? (
|
||||
<a
|
||||
onClick={this.handleClear}
|
||||
className={cx(`${ns}IconSelectControl-clear`)}
|
||||
@ -144,7 +157,7 @@ export default class IconSelectControl extends React.PureComponent<
|
||||
</a>
|
||||
) : null}
|
||||
|
||||
{(!value && placeholder && (
|
||||
{(!svg && placeholder && (
|
||||
<span className={cx(`${ns}IconSelectControl-input-icon-placeholder`)}>
|
||||
{placeholder}
|
||||
</span>
|
||||
@ -191,8 +204,12 @@ export default class IconSelectControl extends React.PureComponent<
|
||||
handleConfirm() {
|
||||
const checkedIcon = this.state.tmpCheckIconId;
|
||||
if (this.props.returnSvg) {
|
||||
this.props.onChange &&
|
||||
this.props.onChange((checkedIcon && checkedIcon.svg) || '');
|
||||
let svg = (checkedIcon && checkedIcon.svg) || '';
|
||||
svg = svg.replace(
|
||||
/<svg/,
|
||||
`<svg data-name="${checkedIcon?.name}" data-id="${checkedIcon?.id}"`
|
||||
);
|
||||
this.props.onChange && this.props.onChange(svg);
|
||||
} else {
|
||||
this.props.onChange &&
|
||||
this.props.onChange(
|
||||
|
@ -520,6 +520,7 @@ export default class NumberControl extends React.Component<
|
||||
},
|
||||
className
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
<NumberInput
|
||||
name={name}
|
||||
@ -594,11 +595,15 @@ export default class NumberControl extends React.Component<
|
||||
{
|
||||
key: 'inputControlClassName',
|
||||
weights: {
|
||||
active: {
|
||||
pre: `inputControlClassName-${id?.replace(
|
||||
'u:',
|
||||
''
|
||||
)}.focused, `
|
||||
focused: {
|
||||
pre: `${ns}Number-${
|
||||
displayMode ? displayMode + '-' : ''
|
||||
}focused.`
|
||||
},
|
||||
disabled: {
|
||||
pre: `${ns}Number-${
|
||||
displayMode ? displayMode + '-' : ''
|
||||
}disabled.`
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -621,11 +626,16 @@ export default class NumberControl extends React.Component<
|
||||
hover: {
|
||||
inner: 'input'
|
||||
},
|
||||
active: {
|
||||
pre: `inputControlClassName-${id?.replace(
|
||||
'u:',
|
||||
''
|
||||
)}.focused, `,
|
||||
focused: {
|
||||
pre: `${ns}Number-${
|
||||
displayMode ? displayMode + '-' : ''
|
||||
}focused.`,
|
||||
inner: 'input'
|
||||
},
|
||||
disabled: {
|
||||
pre: `${ns}Number-${
|
||||
displayMode ? displayMode + '-' : ''
|
||||
}disabled.`,
|
||||
inner: 'input'
|
||||
}
|
||||
}
|
||||
|
@ -1211,7 +1211,7 @@ export default class TextControl extends React.PureComponent<
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={classNames}>
|
||||
<div className={classNames} style={style}>
|
||||
{addOn && addOn.position === 'left' ? addOnDom : null}
|
||||
{body}
|
||||
{addOn && addOn.position !== 'left' ? addOnDom : null}
|
||||
@ -1251,11 +1251,11 @@ export default class TextControl extends React.PureComponent<
|
||||
{
|
||||
key: 'inputControlClassName',
|
||||
weights: {
|
||||
active: {
|
||||
pre: `${ns}TextControl.is-focused > .inputControlClassName-${id?.replace(
|
||||
'u:',
|
||||
''
|
||||
)}, `
|
||||
focused: {
|
||||
parent: `.${ns}TextControl.is-focused`
|
||||
},
|
||||
disabled: {
|
||||
parent: `.${ns}TextControl.is-disabled`
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1278,11 +1278,12 @@ export default class TextControl extends React.PureComponent<
|
||||
hover: {
|
||||
inner: 'input'
|
||||
},
|
||||
active: {
|
||||
pre: `${ns}TextControl.is-focused > .inputControlClassName-${id?.replace(
|
||||
'u:',
|
||||
''
|
||||
)}, `,
|
||||
focused: {
|
||||
parent: `.${ns}TextControl.is-focused`,
|
||||
inner: 'input'
|
||||
},
|
||||
disabled: {
|
||||
parent: `.${ns}TextControl.is-disabled`,
|
||||
inner: 'input'
|
||||
}
|
||||
}
|
||||
|
@ -770,17 +770,13 @@ export default class PickerControl extends React.PureComponent<
|
||||
onClick={this.handleClick}
|
||||
className={cx(
|
||||
'Picker-input',
|
||||
disabled && 'is-disabled',
|
||||
this.state.isFocused && 'is-focused',
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'pickControlClassName',
|
||||
id,
|
||||
themeCss: themeCss || css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'pickControlDisabledClassName',
|
||||
id,
|
||||
themeCss: themeCss || css
|
||||
})
|
||||
)}
|
||||
>
|
||||
@ -873,24 +869,13 @@ export default class PickerControl extends React.PureComponent<
|
||||
hover: {
|
||||
important: true
|
||||
},
|
||||
active: {
|
||||
important: true
|
||||
focused: {
|
||||
important: true,
|
||||
parent: `.${ns}Picker.is-focused >`
|
||||
},
|
||||
disabled: {
|
||||
important: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'pickControlDisabledClassName',
|
||||
weights: {
|
||||
default: {
|
||||
pre: `${ns}Picker.is-disabled> .${setThemeClassName({
|
||||
...this.props,
|
||||
name: 'pickControlDisabledClassName',
|
||||
id,
|
||||
themeCss: themeCss || css
|
||||
})}, `
|
||||
important: true,
|
||||
parent: `.${ns}Picker.is-disabled >`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -16,7 +16,9 @@ import {
|
||||
createObject,
|
||||
autobind,
|
||||
TestIdBuilder,
|
||||
getVariable
|
||||
getVariable,
|
||||
CustomStyle,
|
||||
setThemeClassName
|
||||
} from 'amis-core';
|
||||
import {TransferDropDown, Spinner, Select, SpinnerExtraProps} from 'amis-ui';
|
||||
import {FormOptionsSchema, SchemaApi} from '../../Schema';
|
||||
@ -466,6 +468,7 @@ export default class SelectControl extends React.Component<SelectProps, any> {
|
||||
showInvalidMatch,
|
||||
options,
|
||||
className,
|
||||
popoverClassName,
|
||||
style,
|
||||
loading,
|
||||
value,
|
||||
@ -489,13 +492,17 @@ export default class SelectControl extends React.Component<SelectProps, any> {
|
||||
filterOption,
|
||||
...rest
|
||||
} = this.props;
|
||||
const {classPrefix: ns, themeCss} = this.props;
|
||||
|
||||
if (noResultsText) {
|
||||
noResultsText = render('noResultText', noResultsText);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cx(`${classPrefix}SelectControl`, className)}>
|
||||
<div
|
||||
className={cx(`${classPrefix}SelectControl`, className)}
|
||||
style={style}
|
||||
>
|
||||
{['table', 'list', 'group', 'tree', 'chained', 'associated'].includes(
|
||||
selectMode
|
||||
) ? (
|
||||
@ -503,6 +510,23 @@ export default class SelectControl extends React.Component<SelectProps, any> {
|
||||
) : (
|
||||
<Select
|
||||
{...rest}
|
||||
className={cx(
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'selectControlClassName',
|
||||
id,
|
||||
themeCss: themeCss
|
||||
})
|
||||
)}
|
||||
popoverClassName={cx(
|
||||
popoverClassName,
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'selectPopoverClassName',
|
||||
id,
|
||||
themeCss: themeCss
|
||||
})
|
||||
)}
|
||||
mobileUI={mobileUI}
|
||||
popOverContainer={
|
||||
mobileUI
|
||||
@ -535,6 +559,38 @@ export default class SelectControl extends React.Component<SelectProps, any> {
|
||||
overlay={overlay}
|
||||
/>
|
||||
)}
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss: themeCss,
|
||||
classNames: [
|
||||
{
|
||||
key: 'selectControlClassName',
|
||||
weights: {
|
||||
focused: {
|
||||
suf: '.is-opened:not(.is-mobile)'
|
||||
},
|
||||
disabled: {
|
||||
suf: '.is-disabled'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'selectPopoverClassName',
|
||||
weights: {
|
||||
hover: {
|
||||
suf: ` .${ns}Select-option.is-highlight`
|
||||
},
|
||||
focused: {
|
||||
inner: `.${ns}Select-option.is-active`
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
id: id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -4,12 +4,15 @@ import {
|
||||
FormControlProps,
|
||||
resolveEventData,
|
||||
autobind,
|
||||
getVariable
|
||||
getVariable,
|
||||
CustomStyle,
|
||||
setThemeClassName
|
||||
} from 'amis-core';
|
||||
import {Textarea} from 'amis-ui';
|
||||
import type {ListenerAction} from 'amis-core';
|
||||
import {FormBaseControlSchema} from '../../Schema';
|
||||
import {supportStatic} from './StaticHoc';
|
||||
import cx from 'classnames';
|
||||
|
||||
/**
|
||||
* TextArea 多行文本输入框。
|
||||
@ -193,14 +196,55 @@ export default class TextAreaControl extends React.Component<
|
||||
@supportStatic()
|
||||
render() {
|
||||
const {...rest} = this.props;
|
||||
const {id, themeCss, env, className, classPrefix: ns} = this.props;
|
||||
return (
|
||||
<Textarea
|
||||
{...rest}
|
||||
forwardRef={this.inputRef}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<>
|
||||
<Textarea
|
||||
{...rest}
|
||||
forwardRef={this.inputRef}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
onChange={this.handleChange}
|
||||
className={cx(
|
||||
className,
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'inputControlClassName',
|
||||
id,
|
||||
themeCss: themeCss
|
||||
})
|
||||
)}
|
||||
/>
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss: themeCss,
|
||||
classNames: [
|
||||
{
|
||||
key: 'inputControlClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${ns}TextareaControl-input`
|
||||
},
|
||||
hover: {
|
||||
inner: `.${ns}TextareaControl-input`
|
||||
},
|
||||
focused: {
|
||||
suf: '.is-focused',
|
||||
inner: `.${ns}TextareaControl-input`
|
||||
},
|
||||
disabled: {
|
||||
suf: '.is-disabled',
|
||||
inner: `.${ns}TextareaControl-input`
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
id: id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
CustomStyle,
|
||||
RENDERER_TRANSMISSION_OMIT_PROPS,
|
||||
Renderer,
|
||||
RendererProps
|
||||
@ -87,6 +88,13 @@ export interface PanelSchema extends BaseSchema {
|
||||
* 如果是水平排版,这个属性可以细化水平排版的左右宽度占比。
|
||||
*/
|
||||
subFormHorizontal?: FormHorizontal;
|
||||
|
||||
/**
|
||||
* 外观配置的classname
|
||||
*/
|
||||
headerControlClassName: string;
|
||||
bodyControlClassName: string;
|
||||
actionsControlClassName: string;
|
||||
}
|
||||
|
||||
export interface PanelProps
|
||||
@ -186,6 +194,10 @@ export default class Panel extends React.Component<PanelProps> {
|
||||
actionsClassName,
|
||||
footerClassName,
|
||||
footerWrapClassName,
|
||||
headerControlClassName,
|
||||
headerTitleControlClassName,
|
||||
bodyControlClassName,
|
||||
actionsControlClassName,
|
||||
children,
|
||||
title,
|
||||
footer,
|
||||
@ -207,7 +219,11 @@ export default class Panel extends React.Component<PanelProps> {
|
||||
footerDoms.push(
|
||||
<div
|
||||
key="actions"
|
||||
className={cx(`Panel-btnToolbar`, actionsClassName || `Panel-footer`)}
|
||||
className={cx(
|
||||
`Panel-btnToolbar`,
|
||||
actionsClassName || `Panel-footer`,
|
||||
actionsControlClassName
|
||||
)}
|
||||
>
|
||||
{actions}
|
||||
</div>
|
||||
@ -215,7 +231,13 @@ export default class Panel extends React.Component<PanelProps> {
|
||||
|
||||
footer &&
|
||||
footerDoms.push(
|
||||
<div key="footer" className={cx(footerClassName || `Panel-footer`)}>
|
||||
<div
|
||||
key="footer"
|
||||
className={cx(
|
||||
footerClassName || `Panel-footer`,
|
||||
actionsControlClassName
|
||||
)}
|
||||
>
|
||||
{render('footer', footer, subProps)}
|
||||
</div>
|
||||
);
|
||||
@ -235,18 +257,30 @@ export default class Panel extends React.Component<PanelProps> {
|
||||
return (
|
||||
<div className={cx(`Panel`, className || `Panel--default`)} style={style}>
|
||||
{header ? (
|
||||
<div className={cx(headerClassName || `Panel-heading`)}>
|
||||
<div
|
||||
className={cx(
|
||||
headerClassName || `Panel-heading`,
|
||||
headerControlClassName
|
||||
)}
|
||||
>
|
||||
{render('header', header, subProps)}
|
||||
</div>
|
||||
) : title ? (
|
||||
<div className={cx(headerClassName || `Panel-heading`)}>
|
||||
<h3 className={cx(`Panel-title`)}>
|
||||
<div
|
||||
className={cx(
|
||||
headerClassName || `Panel-heading`,
|
||||
headerControlClassName
|
||||
)}
|
||||
>
|
||||
<h3 className={cx(`Panel-title`, headerTitleControlClassName)}>
|
||||
{render('title', title, subProps)}
|
||||
</h3>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className={bodyClassName || `${ns}Panel-body`}>
|
||||
<div
|
||||
className={cx(bodyClassName || `Panel-body`, bodyControlClassName)}
|
||||
>
|
||||
{this.renderBody()}
|
||||
</div>
|
||||
|
||||
|
@ -32,7 +32,9 @@ import {
|
||||
changedEffect,
|
||||
evalExpressionWithConditionBuilderAsync,
|
||||
normalizeApi,
|
||||
getPropValue
|
||||
getPropValue,
|
||||
CustomStyle,
|
||||
setThemeClassName
|
||||
} from 'amis-core';
|
||||
import {Icon, Table, BadgeObject, SpinnerExtraProps} from 'amis-ui';
|
||||
import type {
|
||||
@ -929,6 +931,15 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
[`${column.className}`]: !!column.className,
|
||||
[`${column.titleClassName}`]: !!column.titleClassName
|
||||
})}
|
||||
style={{
|
||||
justifyContent:
|
||||
(
|
||||
{
|
||||
right: 'flex-end',
|
||||
center: 'center'
|
||||
} as any
|
||||
)[column.align] || 'flex-start'
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
{remark}
|
||||
@ -1161,7 +1172,7 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
|
||||
@autobind
|
||||
rowClassName(record: any, rowIndex: number) {
|
||||
const {rowClassNameExpr, store} = this.props;
|
||||
const {rowClassNameExpr, store, themeCss, id} = this.props;
|
||||
|
||||
const classnames = [];
|
||||
if (rowClassNameExpr) {
|
||||
@ -1176,6 +1187,14 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
if (row?.moved) {
|
||||
classnames.push('is-moved');
|
||||
}
|
||||
classnames.push(
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'tableRowClassname',
|
||||
id,
|
||||
themeCss
|
||||
})
|
||||
);
|
||||
return classnames.join(' ');
|
||||
}
|
||||
|
||||
@ -1942,6 +1961,8 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
maxKeepItemSelectionLength,
|
||||
onRow,
|
||||
store,
|
||||
id,
|
||||
themeCss,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
@ -1983,6 +2004,18 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
return (
|
||||
<Table
|
||||
{...rest}
|
||||
headerClassName={setThemeClassName({
|
||||
...this.props,
|
||||
name: 'tableHeadClassname',
|
||||
id,
|
||||
themeCss
|
||||
})}
|
||||
bodyClassname={setThemeClassName({
|
||||
...this.props,
|
||||
name: 'tableBodyClassname',
|
||||
id,
|
||||
themeCss
|
||||
})}
|
||||
onRef={this.getRef}
|
||||
title={this.renderSchema('title', title, schemaProps)}
|
||||
footer={this.renderSchema('footer', footer, schemaProps)}
|
||||
@ -2110,7 +2143,15 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx, style, store} = this.props;
|
||||
const {
|
||||
classnames: cx,
|
||||
style,
|
||||
store,
|
||||
themeCss,
|
||||
wrapperCustomStyle,
|
||||
id,
|
||||
env
|
||||
} = this.props;
|
||||
|
||||
this.renderedToolbars = []; // 用来记录哪些 toolbar 已经渲染了
|
||||
|
||||
@ -2118,14 +2159,82 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx('Table-render-wrapper', {
|
||||
'Table--unsaved': !!store.modified || !!store.moved
|
||||
})}
|
||||
className={cx(
|
||||
'Table-render-wrapper',
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'wrapperCustomStyle',
|
||||
id,
|
||||
themeCss: wrapperCustomStyle
|
||||
}),
|
||||
{
|
||||
'Table--unsaved': !!store.modified || !!store.moved
|
||||
}
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
{this.renderActions('header')}
|
||||
{heading}
|
||||
{this.renderTable()}
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss,
|
||||
classNames: [
|
||||
{
|
||||
key: 'tableHeadClassname',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${cx('Table-table')} > thead > tr > th`,
|
||||
important: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'tableHeadClassname',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `> tr > th`,
|
||||
important: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'tableBodyClassname',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `> tbody.${cx('Table-tbody')} > tr td`
|
||||
},
|
||||
hover: {
|
||||
suf: '> tbody > tr',
|
||||
inner: `td`,
|
||||
important: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'tableRowClassname',
|
||||
weights: {
|
||||
default: {
|
||||
parent: `.${cx('Table-table')} > tbody.${cx(
|
||||
'Table-tbody'
|
||||
)}`,
|
||||
inner: `td.${cx('Table-cell')}`
|
||||
},
|
||||
hover: {
|
||||
parent: `.${cx('Table-table')} > tbody.${cx(
|
||||
'Table-tbody'
|
||||
)}`,
|
||||
inner: `td.${cx('Table-cell')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
wrapperCustomStyle,
|
||||
id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user