Merge branch 'components-panel' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into components-panel

This commit is contained in:
春希 2020-08-10 22:03:44 +08:00
commit b79fc93d6c
9 changed files with 335 additions and 157 deletions

View File

@ -5771,12 +5771,13 @@
{
"name": "label",
"propType": "string",
"title":"标签文案",
"description": "label"
},
{
"name": "hasClear",
"propType": "bool",
"description": "是否出现clear按钮"
"description": "是否出现清除按钮"
},
{
"name": "state",
@ -5806,6 +5807,47 @@
"description": "尺寸\n@enumdesc 小, 中, 大",
"defaultValue": "medium"
},
{
"name": "disabled",
"propType": "bool",
"description": "是否禁用"
},
{
"name": "maxLength",
"propType": "number",
"description": "最大长度"
},
{
"name": "hasLimitHint",
"propType": "bool",
"description": "是否展现最大长度样式"
},
{
"name": "cutString",
"propType": "bool",
"description": "是否截断超出字符串"
},
{
"name": "readOnly",
"propType": "bool",
"description": "是否只读"
},
{
"name": "trim",
"propType": "bool",
"description": "onChange返回会自动去除头尾空字符"
},
{
"name": "placeholder",
"propType": "string",
"description": "输入提示"
},
{
"name": "hasBorder",
"propType": "bool",
"description": "是否有边框"
},
{
"name": "onPressEnter",
"propType": "func",
@ -5854,13 +5896,7 @@
{
"name": "autoFocus",
"propType": "bool",
"description": "自动聚焦(原生input支持)"
},
{
"name": "isPreview",
"propType": "bool",
"description": "是否为预览态",
"defaultValue": false
"description": "自动聚焦"
},
{
"name": "style",
@ -9776,7 +9812,7 @@
},
{
"name": "icon",
"propType": "string",
"propType": "icon",
"description": "图标"
},
{
@ -9870,19 +9906,6 @@
"subName": ""
},
"props": [
{
"name": "prefix",
"propType": "string",
"defaultValue": "next-"
},
{
"name": "rtl",
"propType": "bool"
},
{
"name": "pure",
"propType": "bool"
},
{
"name": "className",
"propType": "string",
@ -9893,36 +9916,15 @@
"propType": "object",
"description": "自定义内敛样式"
},
{
"name": "checkedChildren",
"propType": "any",
"description": "打开时的内容"
},
{
"name": "unCheckedChildren",
"propType": "any",
"description": "关闭时的内容"
},
{
"name": "onChange",
"propType": "func",
"description": "开关状态改变是触发此事件\n@param {Boolean} checked 是否为打开状态\n@param {Event} e DOM事件对象"
},
{
"name": "checked",
"propType": "bool",
"description": "开关当前的值(针对受控组件)"
},
{
"name": "defaultChecked",
"propType": "bool",
"description": "开关默认值 (针对非受控组件)",
"defaultValue": false
"description": "当前状态"
},
{
"name": "disabled",
"propType": "bool",
"description": "表示开关被禁用",
"description": "是否禁用",
"defaultValue": false
},
{
@ -9934,9 +9936,25 @@
"small"
]
},
"description": "switch的尺寸\n@enumdesc 正常大小, 缩小版大小",
"description": "尺寸",
"defaultValue": "medium"
},
{
"name": "checkedChildren",
"propType": "string",
"description": "打开时的内容"
},
{
"name": "unCheckedChildren",
"propType": "string",
"description": "关闭时的内容"
},
{
"name": "onChange",
"propType": "func",
"description": "开关状态改变是触发此事件\n@param {Boolean} checked 是否为打开状态\n@param {Event} e DOM事件对象"
},
{
"name": "onClick",
"propType": "func",
@ -9946,26 +9964,6 @@
"name": "onKeyDown",
"propType": "func",
"description": "键盘按键事件\n@param {Event} e DOM事件对象"
},
{
"name": "isPreview",
"propType": "bool",
"description": "是否为预览态",
"defaultValue": false
},
{
"name": "renderPreview",
"propType": "func",
"description": "预览态模式下渲染的内容\n@param {number} value 评分值"
},
{
"name": "locale",
"propType": "object",
"description": "国际化配置"
},
{
"name": "readOnly",
"defaultValue": false
}
]
},
@ -10857,7 +10855,7 @@
},
{
"name": "icon",
"propType": "string",
"propType": "icon",
"description": "图标"
},
{

View File

@ -18,23 +18,23 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
static display = 'ColorPicker';
static propTypes = {
onChange: PropTypes.func,
value: PropTypes.string
value: PropTypes.string,
};
static defaultProps = {
onChange: () => {},
value: ''
value: '',
};
constructor(props: Readonly<{value: string; defaultValue: string}>) {
constructor(props: Readonly<{ value: string; defaultValue: string }>) {
super(props);
this.state = {
value: props.value || props.defaultValue
value: props.value || props.defaultValue,
};
}
static getDerivedStateFromProps(props: { value: string; }, state: { preValue: string; }) {
static getDerivedStateFromProps(props: { value: string }, state: { preValue: string }) {
if (props.value != state.preValue) {
return {
preValue: props.value,
value: props.value
value: props.value,
};
}
return null;
@ -42,35 +42,35 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
onChangeComplete = (color: Color): void => {
let value;
if (color.rgb.a < 1) {
let rgb = color.rgb;
let rgba = [rgb.r, rgb.g, rgb.b, rgb.a];
const rgb = color.rgb;
const rgba = [rgb.r, rgb.g, rgb.b, rgb.a];
value = `rgba(${rgba.join(',')})`;
} else {
value = color.hex;
}
this.setState({
value
value,
});
this.props.onChange && this.props.onChange(value);
}
};
onInputChange = (value: string): void => {
if (/^[0-9a-zA-Z]{6}$/.test(value)) value = '#' + value;
this.setState({
value
value,
});
this.props.onChange && this.props.onChange(value);
}
render(): React.ReactNode {
};
render(): React.ReactNode {
const { value, onChange, ...restProps } = this.props;
let boxStyle = {
backgroundColor: this.state.value
const boxStyle = {
backgroundColor: this.state.value,
};
let triggerNode = (
const triggerNode = (
<div className="lowcode-color-box">
<div style={boxStyle} />
</div>
);
let InnerBeforeNode = (
const InnerBeforeNode = (
<Balloon
className={'lowcode-color-content'}
trigger={triggerNode}
@ -80,20 +80,11 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
alignEdge="edge"
offset={[-3, -6]}
>
<SketchPicker
onChangeComplete={this.onChangeComplete}
color={this.state.value}
arrowPointAtCenter={true}
/>
<SketchPicker onChangeComplete={this.onChangeComplete} color={this.state.value} arrowPointAtCenter={true} />
</Balloon>
);
return (
<Input
{...restProps}
innerBefore={InnerBeforeNode}
onChange={this.onInputChange}
value={this.state.value}
/>
<Input {...restProps} innerBefore={InnerBeforeNode} onChange={this.onInputChange} value={this.state.value} />
);
}
}

View File

@ -0,0 +1,44 @@
.lowcode-icon-box {
display: inline-block;
margin-right: -5px;
padding: 3px 0 3px 0;
width: 26px;
height: 26px;
text-align: center;
line-height: 20px;
background: #f2f2f2;
div {
width: 20px;
height: 20px;
border: 1px solid #ddd;
}
}
.lc-icon-setter{
.next-input{
width: auto !important;
}
}
.lowcode-icon-setter-popup{
max-width: 354px;
.lowcode-icon-list{
overflow: auto;
li{
float: left;
margin-bottom: 10px;
width: 40px;
color: #666;
cursor: pointer;
text-align: center;
&:hover{
color: #000;
}
}
}
}

View File

@ -0,0 +1,121 @@
import React, { PureComponent } from 'react';
// import PropTypes from 'prop-types';
import { Input, Icon, Balloon } from '@alifd/next';
import './index.scss';
const icons = [
'smile',
'cry',
'success',
'warning',
'prompt',
'error',
'help',
'clock',
'success-filling',
'delete-filling',
'favorites-filling',
'add',
'minus',
'arrow-up',
'arrow-down',
'arrow-left',
'arrow-right',
'arrow-double-left',
'arrow-double-right',
'switch',
'sorting',
'descending',
'ascending',
'select',
'semi-select',
'loading',
'search',
'close',
'ellipsis',
'picture',
'calendar',
'ashbin',
'upload',
'download',
'set',
'edit',
'refresh',
'filter',
'attachment',
'account',
'email',
'atm',
'copy',
'exit',
'eye',
'eye-close',
'toggle-left',
'toggle-right',
'lock',
'unlock',
'chart-pie',
'chart-bar',
'form',
'detail',
'list',
'dashboard',
];
interface IconSetterProps {
value: string;
onChange: (icon: string) => undefined;
icons: string[];
}
export default class IconSetter extends PureComponent<IconSetterProps, {}> {
static defaultProps = {
value: '',
icons: icons,
onChange: (icon: string) => undefined,
};
onInputChange() {
console.log(this);
}
onSelectIcon(icon: string) {
const { onChange } = this.props;
onChange(icon);
}
render() {
const { icons, value } = this.props;
const triggerNode = (
<div className="lowcode-icon-box">
<Icon type={value} />
</div>
);
const InnerBeforeNode = (
<Balloon
className={'lowcode-icon-content'}
trigger={triggerNode}
needAdjust={true}
triggerType="click"
closable={false}
alignEdge
align="l"
popupClassName="lowcode-icon-setter-popup"
>
<ul className="lowcode-icon-list">
{icons.map((icon) => (
<li onClick={() => this.onSelectIcon(icon)}>
<Icon type={icon} size="large" />
</li>
))}
</ul>
</Balloon>
);
return (
<div className="lc-icon-setter">
<Input innerBefore={InnerBeforeNode} onChange={this.onInputChange} value={value} />
</div>
);
}
}

View File

@ -1,3 +1,4 @@
import React, { Component } from 'react';
import { registerSetter } from '@ali/lowcode-editor-core';
import { isJSExpression } from '@ali/lowcode-types';
import { DatePicker, TimePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next';
@ -6,7 +7,8 @@ import ColorSetter from './color-setter';
import JsonSetter from './json-setter';
import EventsSetter from './events-setter';
import StyleSetter from './style-setter';
import React, { Component } from 'react';
import IconSetter from './icon-setter';
export const StringSetter = {
component: Input,
defaultProps: { placeholder: '请输入', style: { maxWidth: 180 } },
@ -15,14 +17,16 @@ export const StringSetter = {
};
export const NumberSetter = NumberPicker;
export class BoolSetter extends Component {
render() {
const { onChange, value, defaultValue } = this.props;
return <Switch checked={value || defaultValue} onChange={
val => {
onChange(val)
}
}/>;
return (
<Switch
checked={value || defaultValue}
onChange={(val) => {
onChange(val);
}}
/>
);
}
}
export const SelectSetter = Select;
@ -49,25 +53,27 @@ export const DateRangeSetter = DatePicker.RangePicker;
export { ExpressionSetter, EventsSetter };
class StringDateSetter extends Component {
render() {
const { onChange, editor } = this.props;
return <DatePicker onChange={
val => {
onChange(val.format())
}
}/>;
return (
<DatePicker
onChange={(val) => {
onChange(val.format());
}}
/>
);
}
}
class StringTimePicker extends Component {
render() {
const { onChange, editor } = this.props;
return <TimePicker onChange={
val => {
onChange(val.format('HH:mm:ss'))
}
}/>;
return (
<TimePicker
onChange={(val) => {
onChange(val.format('HH:mm:ss'));
}}
/>
);
}
}
@ -97,6 +103,7 @@ const builtinSetters: any = {
ColorSetter,
JsonSetter,
StyleSetter,
IconSetter,
};
registerSetter(builtinSetters);

View File

@ -25,25 +25,27 @@ export default class Mixin extends PureComponent {
static defaultProps = {
locale: 'zh-CN',
messages: zhCN,
types: [{
"name": "StringSetter",
"props": {}
}],
types: [
{
name: 'StringSetter',
props: {},
},
],
};
typeMap: any;
i18n: (key: any, values?: {}) => string | void | (string | void)[];
i18n: (key: any, values?: {}) => string | void | Array<string | void>;
constructor(props: Readonly<{}>) {
super(props);
let type = props.defaultType;// judgeTypeHandler(props, {});
const type = props.defaultType; // judgeTypeHandler(props, {});
this.i18n = generateI18n(props.locale, props.messages);
this.state = {
preType: type,
type
type,
};
}
changeType(type: string) {
if (typeof type === 'object' || type === this.state.type) return;
let { onChange } = this.props;
const { onChange } = this.props;
let newValue = undefined;
const setterProps = this.typeMap[type]['props'];
if (setterProps) {
@ -60,18 +62,10 @@ export default class Mixin extends PureComponent {
onChange && onChange(newValue);
}
render() {
const {
style = {},
className,
locale,
messages,
types = [],
defaultType,
...restProps
} = this.props;
const { style = {}, className, locale, messages, types = [], defaultType, ...restProps } = this.props;
this.typeMap = {};
let realTypes: any[] = [];
types.forEach( (el: { name: any; props: any; }) => {
const realTypes: any[] = [];
types.forEach((el: { name: any; props: any }) => {
const { name, props } = el;
const Setter = getSetter(name);
if (Setter) {
@ -79,15 +73,15 @@ export default class Mixin extends PureComponent {
label: name,
component: Setter.component,
props,
}
};
}
realTypes.push(name);
})
});
let moreBtnNode = null;
//如果只有2种且有变量表达式则直接展示变量按钮
if (realTypes.length > 1) {
let isTwoType = !!(realTypes.length === 2 && ~realTypes.indexOf('ExpressionSetter'));
let btnProps = {
const isTwoType = !!(realTypes.length === 2 && ~realTypes.indexOf('ExpressionSetter'));
const btnProps = {
size: 'small',
text: true,
style: {
@ -100,13 +94,13 @@ export default class Mixin extends PureComponent {
width: 16,
height: 16,
lineHeight: '16px',
textAlign: 'center'
}
textAlign: 'center',
},
};
if (isTwoType) {
btnProps.onClick = this.changeType.bind(this, realTypes.indexOf(this.state.type) ? realTypes[0] : realTypes[1]);
}
let triggerNode = (
const triggerNode = (
<Button {...btnProps} size={isTwoType ? 'large' : 'small'}>
<Icon type={isTwoType ? 'edit' : 'ellipsis'} />
</Button>
@ -114,19 +108,19 @@ export default class Mixin extends PureComponent {
if (isTwoType) {
moreBtnNode = triggerNode;
} else {
let MenuItems: {} | null | undefined = [];
realTypes.map(type => {
const MenuItems: {} | null | undefined = [];
realTypes.map((type) => {
if (this.typeMap[type]) {
MenuItems.push(<Menu.Item key={type}>{this.typeMap[type]['label']}</Menu.Item>);
} else {
console.error(
this.i18n('typeError', {
type
})
type,
}),
);
}
});
let MenuNode = (
const MenuNode = (
<Menu
selectMode="single"
hasSelectedIcon={false}
@ -144,13 +138,13 @@ export default class Mixin extends PureComponent {
);
}
}
let TargetNode = this.typeMap[this.state.type]?.component || 'div';
let targetProps = this.typeMap[this.state.type]?.props || {};
let tarStyle = { position: 'relative', ...style };
let classes = classNames(className, 'lowcode-setter-mixin');
const TargetNode = this.typeMap[this.state.type]?.component || 'div';
const targetProps = this.typeMap[this.state.type]?.props || {};
const tarStyle = { position: 'relative', ...style };
const classes = classNames(className, 'lowcode-setter-mixin');
return (
<div style={tarStyle} className={classes} >
<div style={tarStyle} className={classes}>
<TargetNode {...restProps} {...targetProps} />
{moreBtnNode}
</div>

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import LowStyleSetter from '@ali/lc-style-setter';
import { globalLocale } from '@ali/lowcode-editor-core';
export default class StyleSetter extends Component{
export default class StyleSetter extends Component {
static displayName = 'StyleSetter';
static propTypes = {
@ -15,7 +15,7 @@ export default class StyleSetter extends Component{
};
static defaultProps = {
value: {},
onChange: () => {},
onChange: () => { },
placeholder: '',
locale: globalLocale.getLocale() || 'en-US'
};
@ -25,7 +25,7 @@ export default class StyleSetter extends Component{
onChange(val.native);
}
render () {
render() {
const { value } = this.props;
return (
<div className="lc-block-setter">

View File

@ -57,6 +57,7 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
itemsMap.delete(item.id);
});
}
return {
items,
itemsMap,
@ -72,7 +73,7 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
onSort(sortedIds: Array<string | number>) {
const { itemsMap } = this.state;
const { onChange } = this.props;
const { onChange ,itemSetter,field} = this.props;
const items = sortedIds.map((id, index) => {
const item = itemsMap.get(id)!;
// item.setKey(index);
@ -82,10 +83,26 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
const values = items.map((item) => {
return item.getValue();
});
console.log('values',values);
// 对itemsMap重新生成并刷新当前setter数据
let newItems = [],newItemsMap = {}
itemsMap.clear();
for (let i = 0; i < items.length; i++) {
const newItem = field.createField({
name: i,
setter: itemSetter,
// FIXME:
forceInline: 1,
});
newItems[i] = newItem;
itemsMap.set(newItem.id, newItem);
}
onChange(values);
this.setState({
items,
items:newItems,
itemsMap
});
}

View File

@ -54,6 +54,12 @@ function propTypeToSetter(propType: PropType): SetterType {
initialValue: '',
};
case 'icon':
return {
componentName: 'IconSetter',
isRequired,
initialValue: '',
};
case 'number':
return {
componentName: 'NumberSetter',
@ -164,7 +170,7 @@ function propTypeToSetter(propType: PropType): SetterType {
componentName: 'MixedSetter',
props: {
// TODO:
setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)),
setters: (propType as OneOfType).value.map((item) => propTypeToSetter(item)),
},
isRequired,
};