feat: Divider支持带文字配置 (#8358)

* feat:divider支持带文字配置

* feat: divider支持带文字配置

* feat: divider支持带文字配置

---------

Co-authored-by: zhaowenli <zhaowenli@baidu.com>
This commit is contained in:
xiangwaner 2023-10-17 10:24:54 +08:00 committed by GitHub
parent 034d18e36c
commit 0ba4f50f70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 384 additions and 127 deletions

View File

@ -21,22 +21,51 @@ order: 42
```schema: scope="body"
[
{
"type": "divider"
"type": "divider",
"lineStyle": "solid"
},
{
"type": "divider",
"lineStyle": "solid"
"lineStyle": "dashed"
}
]
```
## 带标题的分割线
> `3.5.0`及以上版本
```schema: scope="body"
[
{
"type": "divider",
"title": "Text",
"titlePosition": "left"
},
{
"type": "divider",
"title": "Text",
"titlePosition": "center"
},
{
"type": "divider",
"title": "Text",
"titlePosition": "right"
}
]
```
## 属性表
| 属性名 | 类型 | 默认值 | 说明 |
| --------- | -------- | ------------ | ------------------------------------------ |
| 属性名 | 类型 | 默认值 | 说明 | 版本 |
| --------- | -------- | ------------ | --------------------------------------- |---------- |
| type | `string` | | `"divider"` 指定为 分割线 渲染器 |
| className | `string` | | 外层 Dom 的类名 |
| lineStyle | `string` | `solid` | 分割线的样式,支持`dashed`和`solid` |
| direction | `string` | `horizontal` | 分割线的方向,支持`horizontal`和`vertical` |
| color | `string` | | 分割线的颜色 |
| rotate | `number` | | 分割线的旋转角度 |
| direction | `string` | `horizontal` | 分割线的方向,支持`horizontal`和`vertical` | `3.5.0` |
| color | `string` | | 分割线的颜色 | `3.5.0` |
| rotate | `number` | | 分割线的旋转角度 | `3.5.0` |
| title | [SchemaNode](../../docs/types/schemanode) | | 分割线的标题 | `3.5.0` |
| titleClassName | `string` | | 分割线的标题类名 | `3.5.0` |
| titlePosition | `string` | `center`| 分割线的标题位置,支持`left`、`center`和`right` | `3.5.0` |

View File

@ -1,6 +1,13 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin} from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {
BasePlugin,
BaseEventContext,
defaultValue,
getI18nEnabled,
getSchemaTpl,
registerEditorPlugin,
tipedLabel,
valuePipeOut
} from 'amis-editor-core';
export class DividerPlugin extends BasePlugin {
static id = 'DividerPlugin';
@ -27,103 +34,203 @@ export class DividerPlugin extends BasePlugin {
panelJustify = true;
tags = ['展示'];
panelBody = getSchemaTpl('tabs', [
{
title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本样式',
body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}),
getSchemaTpl('layout:width:v2', {
visibleOn:
'data.style && data.style.position && (data.style.position === "fixed" || data.style.position === "absolute")'
}),
{
mode: 'horizontal',
type: 'button-group-select',
label: '类型',
name: 'lineStyle',
value: 'dashed',
options: [
{
value: 'dashed',
label: '虚线'
},
{
value: 'solid',
label: '实线'
panelBodyCreator = (context: BaseEventContext) => {
const i18nEnabled = getI18nEnabled();
return getSchemaTpl('tabs', [
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
i18nEnabled
? {
type: 'input-text-i18n',
name: 'title',
label: '标题',
placeholder: '请输入标题'
}
: getSchemaTpl('valueFormula', {
name: 'title',
label: '标题',
placeholder: '请输入标题',
rendererSchema: {
type: 'input-text'
}
})
]
},
getSchemaTpl('status')
])
},
{
title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本样式',
body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}),
getSchemaTpl('layout:width:v2', {
visibleOn:
'data.style && data.style.position && (data.style.position === "fixed" || data.style.position === "absolute")'
}),
{
mode: 'horizontal',
type: 'select',
label: '类型',
name: 'lineStyle',
value: 'solid',
options: [
{
value: 'solid',
label: '实线'
},
{
value: 'dashed',
label: '虚线'
}
]
},
{
mode: 'horizontal',
type: 'select',
label: '方向',
name: 'direction',
value: 'horizontal',
options: [
{
value: 'horizontal',
label: '水平'
},
{
value: 'vertical',
label: '垂直'
}
]
},
{
mode: 'horizontal',
type: 'input-number',
label: '角度',
name: 'rotate',
value: 0,
min: -360,
max: 360
},
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '线长',
name: 'style.width',
placeholder: '100%',
visibleOn: 'data.direction !== "vertical"',
clearValueOnHidden: true
}),
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '线长',
name: 'style.height',
placeholder: 'var(--sizes-base-15)',
visibleOn: 'data.direction === "vertical"',
clearValueOnHidden: true
}),
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '线宽',
name: 'style.borderWidth',
placeholder: '1px',
visibleOn: '!data.title || data.direction === "vertical"'
}),
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '线宽',
name: 'themeCss.titleWrapperControlClassName.border-bottom-width',
placeholder: '1px',
visibleOn: '!!data.title && data.direction !== "vertical"',
clearValueOnHidden: true,
pipeIn: (value: any, form: any) => {
if (
value === undefined &&
form.data?.style?.borderWidth !== undefined
) {
const bwidth = form.data.style.borderWidth;
setTimeout(() =>
form.setValueByName(
'themeCss.titleWrapperControlClassName.border-bottom-width',
bwidth
)
);
return bwidth;
}
return value;
}
]
},
{
mode: 'horizontal',
type: 'button-group-select',
label: '方向',
name: 'direction',
value: 'horizontal',
options: [
{
value: 'horizontal',
label: '水平'
},
{
value: 'vertical',
label: '垂直'
}
]
},
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '长度',
name: 'style.width',
placeholder: '100%',
visibleOn: 'direction !== "vertical"',
clearValueOnHidden: true
}),
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '长度',
name: 'style.height',
placeholder: 'var(--sizes-base-15)',
visibleOn: 'direction === "vertical"',
clearValueOnHidden: true
}),
getSchemaTpl('theme:select', {
mode: 'horizontal',
label: '宽度',
name: 'style.borderWidth',
placeholder: '1px'
}),
getSchemaTpl('theme:colorPicker', {
mode: 'horizontal',
label: '颜色',
name: 'color',
placeholder: 'var(--colors-neutral-line-8)',
labelMode: 'input',
needGradient: true
}),
getSchemaTpl('theme:paddingAndMargin', {
name: 'style',
hidePadding: true
}),
{
mode: 'horizontal',
type: 'input-number',
label: '角度',
name: 'rotate',
value: 0
}
]
}
])
},
{
title: '显隐',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
}
]);
}),
getSchemaTpl('theme:colorPicker', {
mode: 'horizontal',
label: '颜色',
name: 'color',
placeholder: 'var(--colors-neutral-line-8)',
labelMode: 'input',
needGradient: true
}),
getSchemaTpl('theme:paddingAndMargin', {
name: 'style',
hidePadding: true
})
]
},
{
title: '标题样式',
visibleOn: '!!data.title && data.direction !== "vertical"',
body: [
{
type: 'select',
name: 'titlePosition',
label: '位置',
pipeIn: defaultValue('center'),
options: [
{
value: 'left',
label: '居左'
},
{
value: 'center',
label: '居中'
},
{
value: 'right',
label: '居右'
}
],
clearValueOnHidden: true
},
getSchemaTpl('theme:select', {
label: tipedLabel(
'距离',
'标题和最近左、右边框之间的距离默认值5%'
),
name: 'themeCss.titleWrapperControlClassName.flex-basis',
placeholder: '5%',
visibleOn:
'data.titlePosition === "left" || data.titlePosition === "right"',
clearValueOnHidden: true
}),
getSchemaTpl('theme:font', {
title: '文字',
name: 'themeCss.titleControlClassName.font',
textAlign: false,
clearValueOnHidden: true
}),
getSchemaTpl('theme:paddingAndMargin', {
name: 'themeCss.titleControlClassName.padding-and-margin',
hidePadding: true,
clearValueOnHidden: true
})
]
}
])
}
]);
};
}
registerEditorPlugin(DividerPlugin);

View File

@ -2545,6 +2545,14 @@
--Divider-marginLeft: var(--sizes-size-0);
--Divider-marginRight: var(--sizes-size-0);
--Divider-marginBottom: var(--sizes-size-7);
--Divider-text-width: 5%;
--Divider-text-fontSize: var(--fonts-size-7);
--Divider-text-fontWeight: var(--fonts-weight-6);
--Divider-text-color: var(--colors-neutral-text-2);
--Divider-text-marginTop: var(--sizes-size-0);
--Divider-text-marginLeft: var(--sizes-size-9);
--Divider-text-marginRight: var(--sizes-size-9);
--Divider-text-marginBottom: var(--sizes-size-0);
--inputFile-base-des-color: var(--colors-neutral-text-2);
--inputFile-base-des-fontSize: var(--fonts-size-7);

View File

@ -23,18 +23,53 @@
}
&--horizontal {
border-bottom: var(--Divider-width) var(--Divider-style)
var(--Divider-color);
position: relative;
height: px2rem(2px);
border-bottom: var(--Divider-width) var(--Divider-style) var(--Divider-color);
transform-origin: 0 center;
clear: both;
}
&--vertical {
border-left: var(--Divider-width) var(--Divider-style) var(--Divider-color);
height: var(--sizes-base-15);
transform-origin: center bottom;
display: inline-block;
}
}
.#{$ns}Divider--with-text {
display: flex;
align-items: center;
height: unset;
border-bottom-width: 0 !important;
&::before,
&::after {
content: '';
height: 0;
flex: 1;
border-bottom: inherit;
border-bottom-width: var(--Divider-width);
}
&.#{$ns}Divider--with-text-left:before,
&.#{$ns}Divider--with-text-right:after {
flex-basis: var(--Divider-text-width);
flex-grow: 0;
}
}
.#{$ns}Divider-text {
margin: var(--Divider-text-marginTop) var(--Divider-text-marginRight)
var(--Divider-text-marginBottom) var(--Divider-text-marginLeft);
font-size: var(--Divider-text-fontSize);
font-weight: var(--Divider-text-fontWeight);
line-height: 1;
color: var(--Divider-text-color);
box-sizing: border-box;
}
/* 移动端样式调整 */
@include media-breakpoint-down(sm) {
.#{$ns}Divider {

View File

@ -1,6 +1,13 @@
import React from 'react';
import {Renderer, RendererProps} from 'amis-core';
import {BaseSchema} from '../Schema';
import {
Renderer,
RendererProps,
CustomStyle,
setThemeClassName,
isPureVariable,
resolveVariableAndFilter
} from 'amis-core';
import {BaseSchema, SchemaCollection} from '../Schema';
/**
* Divider 线
@ -12,6 +19,9 @@ export interface DividerSchema extends BaseSchema {
direction?: 'horizontal' | 'vertical';
color?: string;
rotate?: number;
title?: SchemaCollection;
titleClassName?: string;
titlePosition?: 'left' | 'center' | 'right';
[propName: string]: any;
}
@ -20,20 +30,33 @@ export interface DividerProps
Omit<DividerSchema, 'type' | 'className'> {}
export default class Divider extends React.Component<DividerProps, object> {
static defaultProps: Pick<DividerProps, 'className' | 'lineStyle'> = {
static defaultProps: Pick<
DividerProps,
'className' | 'lineStyle' | 'titleClassName' | 'titlePosition'
> = {
className: '',
lineStyle: 'solid'
lineStyle: 'solid',
titleClassName: '',
titlePosition: 'center'
};
render() {
const {
let {
render,
classnames: cx,
className,
style = {},
lineStyle,
direction,
color,
rotate
rotate,
title,
titleClassName,
titlePosition,
id,
themeCss,
env,
data
} = this.props;
const borderColor: any = {};
@ -46,22 +69,77 @@ export default class Divider extends React.Component<DividerProps, object> {
}
}
let transform;
let transform = style?.transform || '';
if (rotate) {
transform = `${style?.transform || ''} rotate(${rotate}deg)`;
transform += ` rotate(${rotate}deg)`;
}
if (isPureVariable(title)) {
title = resolveVariableAndFilter(title, data);
}
const classNames = cx(
'Divider',
lineStyle ? `Divider--${lineStyle}` : '',
direction === 'vertical' ? 'Divider--vertical' : 'Divider--horizontal',
title && direction !== 'vertical' ? 'Divider--with-text' : '',
title && direction !== 'vertical' && titlePosition
? `Divider--with-text-${titlePosition}`
: '',
title && direction !== 'vertical'
? setThemeClassName('titleWrapperControlClassName', id, themeCss)
: '',
className
);
return (
<div
className={cx(
'Divider',
lineStyle ? `Divider--${lineStyle}` : '',
direction === 'vertical'
? 'Divider--vertical'
: 'Divider--horizontal',
className
)}
style={{...style, ...borderColor, transform}}
/>
<div className={classNames} style={{...style, ...borderColor, transform}}>
{title && direction !== 'vertical' ? (
<span
className={cx(
`Divider-text Divider-text-${titlePosition} ${titleClassName}`,
setThemeClassName('titleControlClassName', id, themeCss)
)}
>
{render('title', title)}
</span>
) : null}
<CustomStyle
config={{
themeCss: themeCss,
classNames: [
{
key: 'titleWrapperControlClassName',
weights: {
default: {
suf: '::before',
important: true
}
}
},
{
key: 'titleWrapperControlClassName',
weights: {
default: {
suf: '::after',
important: true
}
}
},
{
key: 'titleControlClassName',
weights: {
default: {
important: true
}
}
}
],
id
}}
env={env}
/>
</div>
);
}
}