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", "name": "label",
"propType": "string", "propType": "string",
"title":"标签文案",
"description": "label" "description": "label"
}, },
{ {
"name": "hasClear", "name": "hasClear",
"propType": "bool", "propType": "bool",
"description": "是否出现clear按钮" "description": "是否出现清除按钮"
}, },
{ {
"name": "state", "name": "state",
@ -5806,6 +5807,47 @@
"description": "尺寸\n@enumdesc 小, 中, 大", "description": "尺寸\n@enumdesc 小, 中, 大",
"defaultValue": "medium" "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", "name": "onPressEnter",
"propType": "func", "propType": "func",
@ -5854,13 +5896,7 @@
{ {
"name": "autoFocus", "name": "autoFocus",
"propType": "bool", "propType": "bool",
"description": "自动聚焦(原生input支持)" "description": "自动聚焦"
},
{
"name": "isPreview",
"propType": "bool",
"description": "是否为预览态",
"defaultValue": false
}, },
{ {
"name": "style", "name": "style",
@ -9776,7 +9812,7 @@
}, },
{ {
"name": "icon", "name": "icon",
"propType": "string", "propType": "icon",
"description": "图标" "description": "图标"
}, },
{ {
@ -9870,19 +9906,6 @@
"subName": "" "subName": ""
}, },
"props": [ "props": [
{
"name": "prefix",
"propType": "string",
"defaultValue": "next-"
},
{
"name": "rtl",
"propType": "bool"
},
{
"name": "pure",
"propType": "bool"
},
{ {
"name": "className", "name": "className",
"propType": "string", "propType": "string",
@ -9893,36 +9916,15 @@
"propType": "object", "propType": "object",
"description": "自定义内敛样式" "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", "name": "checked",
"propType": "bool", "propType": "bool",
"description": "开关当前的值(针对受控组件)" "description": "当前状态"
},
{
"name": "defaultChecked",
"propType": "bool",
"description": "开关默认值 (针对非受控组件)",
"defaultValue": false
}, },
{ {
"name": "disabled", "name": "disabled",
"propType": "bool", "propType": "bool",
"description": "表示开关被禁用", "description": "是否禁用",
"defaultValue": false "defaultValue": false
}, },
{ {
@ -9934,9 +9936,25 @@
"small" "small"
] ]
}, },
"description": "switch的尺寸\n@enumdesc 正常大小, 缩小版大小", "description": "尺寸",
"defaultValue": "medium" "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", "name": "onClick",
"propType": "func", "propType": "func",
@ -9946,26 +9964,6 @@
"name": "onKeyDown", "name": "onKeyDown",
"propType": "func", "propType": "func",
"description": "键盘按键事件\n@param {Event} e DOM事件对象" "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", "name": "icon",
"propType": "string", "propType": "icon",
"description": "图标" "description": "图标"
}, },
{ {

View File

@ -18,23 +18,23 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
static display = 'ColorPicker'; static display = 'ColorPicker';
static propTypes = { static propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
value: PropTypes.string value: PropTypes.string,
}; };
static defaultProps = { static defaultProps = {
onChange: () => {}, onChange: () => {},
value: '' value: '',
}; };
constructor(props: Readonly<{value: string; defaultValue: string}>) { constructor(props: Readonly<{ value: string; defaultValue: string }>) {
super(props); super(props);
this.state = { 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) { if (props.value != state.preValue) {
return { return {
preValue: props.value, preValue: props.value,
value: props.value value: props.value,
}; };
} }
return null; return null;
@ -42,35 +42,35 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
onChangeComplete = (color: Color): void => { onChangeComplete = (color: Color): void => {
let value; let value;
if (color.rgb.a < 1) { if (color.rgb.a < 1) {
let rgb = color.rgb; const rgb = color.rgb;
let rgba = [rgb.r, rgb.g, rgb.b, rgb.a]; const rgba = [rgb.r, rgb.g, rgb.b, rgb.a];
value = `rgba(${rgba.join(',')})`; value = `rgba(${rgba.join(',')})`;
} else { } else {
value = color.hex; value = color.hex;
} }
this.setState({ this.setState({
value value,
}); });
this.props.onChange && this.props.onChange(value); this.props.onChange && this.props.onChange(value);
} };
onInputChange = (value: string): void => { onInputChange = (value: string): void => {
if (/^[0-9a-zA-Z]{6}$/.test(value)) value = '#' + value; if (/^[0-9a-zA-Z]{6}$/.test(value)) value = '#' + value;
this.setState({ this.setState({
value value,
}); });
this.props.onChange && this.props.onChange(value); this.props.onChange && this.props.onChange(value);
} };
render(): React.ReactNode { render(): React.ReactNode {
const { value, onChange, ...restProps } = this.props; const { value, onChange, ...restProps } = this.props;
let boxStyle = { const boxStyle = {
backgroundColor: this.state.value backgroundColor: this.state.value,
}; };
let triggerNode = ( const triggerNode = (
<div className="lowcode-color-box"> <div className="lowcode-color-box">
<div style={boxStyle} /> <div style={boxStyle} />
</div> </div>
); );
let InnerBeforeNode = ( const InnerBeforeNode = (
<Balloon <Balloon
className={'lowcode-color-content'} className={'lowcode-color-content'}
trigger={triggerNode} trigger={triggerNode}
@ -80,20 +80,11 @@ export default class ColorPickerView extends PureComponent<PluginProps> {
alignEdge="edge" alignEdge="edge"
offset={[-3, -6]} offset={[-3, -6]}
> >
<SketchPicker <SketchPicker onChangeComplete={this.onChangeComplete} color={this.state.value} arrowPointAtCenter={true} />
onChangeComplete={this.onChangeComplete}
color={this.state.value}
arrowPointAtCenter={true}
/>
</Balloon> </Balloon>
); );
return ( return (
<Input <Input {...restProps} innerBefore={InnerBeforeNode} onChange={this.onInputChange} value={this.state.value} />
{...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 { registerSetter } from '@ali/lowcode-editor-core';
import { isJSExpression } from '@ali/lowcode-types'; import { isJSExpression } from '@ali/lowcode-types';
import { DatePicker, TimePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next'; 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 JsonSetter from './json-setter';
import EventsSetter from './events-setter'; import EventsSetter from './events-setter';
import StyleSetter from './style-setter'; import StyleSetter from './style-setter';
import React, { Component } from 'react'; import IconSetter from './icon-setter';
export const StringSetter = { export const StringSetter = {
component: Input, component: Input,
defaultProps: { placeholder: '请输入', style: { maxWidth: 180 } }, defaultProps: { placeholder: '请输入', style: { maxWidth: 180 } },
@ -15,14 +17,16 @@ export const StringSetter = {
}; };
export const NumberSetter = NumberPicker; export const NumberSetter = NumberPicker;
export class BoolSetter extends Component { export class BoolSetter extends Component {
render() { render() {
const { onChange, value, defaultValue } = this.props; const { onChange, value, defaultValue } = this.props;
return <Switch checked={value || defaultValue} onChange={ return (
val => { <Switch
onChange(val) checked={value || defaultValue}
} onChange={(val) => {
}/>; onChange(val);
}}
/>
);
} }
} }
export const SelectSetter = Select; export const SelectSetter = Select;
@ -49,25 +53,27 @@ export const DateRangeSetter = DatePicker.RangePicker;
export { ExpressionSetter, EventsSetter }; export { ExpressionSetter, EventsSetter };
class StringDateSetter extends Component { class StringDateSetter extends Component {
render() { render() {
const { onChange, editor } = this.props; const { onChange, editor } = this.props;
return <DatePicker onChange={ return (
val => { <DatePicker
onChange(val.format()) onChange={(val) => {
} onChange(val.format());
}/>; }}
/>
);
} }
} }
class StringTimePicker extends Component { class StringTimePicker extends Component {
render() { render() {
const { onChange, editor } = this.props; const { onChange, editor } = this.props;
return <TimePicker onChange={ return (
val => { <TimePicker
onChange(val.format('HH:mm:ss')) onChange={(val) => {
} onChange(val.format('HH:mm:ss'));
}/>; }}
/>
);
} }
} }
@ -97,6 +103,7 @@ const builtinSetters: any = {
ColorSetter, ColorSetter,
JsonSetter, JsonSetter,
StyleSetter, StyleSetter,
IconSetter,
}; };
registerSetter(builtinSetters); registerSetter(builtinSetters);

View File

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

View File

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

View File

@ -57,6 +57,7 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
itemsMap.delete(item.id); itemsMap.delete(item.id);
}); });
} }
return { return {
items, items,
itemsMap, itemsMap,
@ -72,7 +73,7 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
onSort(sortedIds: Array<string | number>) { onSort(sortedIds: Array<string | number>) {
const { itemsMap } = this.state; const { itemsMap } = this.state;
const { onChange } = this.props; const { onChange ,itemSetter,field} = this.props;
const items = sortedIds.map((id, index) => { const items = sortedIds.map((id, index) => {
const item = itemsMap.get(id)!; const item = itemsMap.get(id)!;
// item.setKey(index); // item.setKey(index);
@ -82,10 +83,26 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
const values = items.map((item) => { const values = items.map((item) => {
return item.getValue(); 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); onChange(values);
this.setState({ this.setState({
items, items:newItems,
itemsMap
}); });
} }

View File

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