mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-07 10:57:19 +00:00
chore: 移除内置 setters
This commit is contained in:
parent
00300cbe8c
commit
32e235fcb1
@ -1,314 +0,0 @@
|
||||
import { Component, Fragment } from 'react';
|
||||
import { Icon, Button, Message } from '@alifd/next';
|
||||
import { Title, runInAction } from '@ali/lowcode-editor-core';
|
||||
import { SetterType, FieldConfig, SetterConfig } from '@ali/lowcode-types';
|
||||
import { SettingField } from '@ali/lowcode-designer';
|
||||
import { createSettingFieldView } from '../settings/settings-pane';
|
||||
import { PopupContext, PopupPipe } from '../popup';
|
||||
import Sortable from './sortable';
|
||||
import './style.less';
|
||||
|
||||
interface ArraySetterState {
|
||||
items: SettingField[];
|
||||
itemsMap: Map<string | number, SettingField>;
|
||||
}
|
||||
|
||||
interface ArraySetterProps {
|
||||
value: any[];
|
||||
field: SettingField;
|
||||
itemSetter?: SetterType;
|
||||
columns?: FieldConfig[];
|
||||
multiValue?: boolean;
|
||||
onChange?: Function;
|
||||
}
|
||||
|
||||
export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
|
||||
state: ArraySetterState = {
|
||||
items: [],
|
||||
itemsMap: new Map<string | number, SettingField>(),
|
||||
};
|
||||
|
||||
onItemChange = async () => {
|
||||
const { onChange } = this.props;
|
||||
const { items } = this.state;
|
||||
// setValue 的props数据合并会有一些延时,这里延时100毫秒来等待数据合并完成获取到最新数据
|
||||
await this.delay(100);
|
||||
onChange && onChange(items.map(item => {
|
||||
return item && item.getValue();
|
||||
}));
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { value, field, onChange } = this.props;
|
||||
const itemsMap = new Map<string | number, SettingField>();
|
||||
const items = [];
|
||||
const valueLength = value && Array.isArray(value) ? value.length : 0;
|
||||
|
||||
for (let i = 0; i < valueLength; i++) {
|
||||
const item = field.createField({
|
||||
name: i,
|
||||
setter: this.props.itemSetter,
|
||||
forceInline: 1,
|
||||
setValue: this.onItemChange,
|
||||
});
|
||||
items[i] = item;
|
||||
itemsMap.set(item.id, item);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
items,
|
||||
itemsMap,
|
||||
}, () => {
|
||||
// setValue 会触发onItemChange,需要在items被设值之后才能调用
|
||||
runInAction(() => {
|
||||
value && value.map((item, index) => {
|
||||
items[index].setValue(item);
|
||||
return item;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
onSort(sortedIds: Array<string | number>) {
|
||||
const { itemsMap } = this.state;
|
||||
const { onChange, itemSetter, field } = this.props;
|
||||
const sortValues = sortedIds.map((id) => {
|
||||
const value = itemsMap.get(id)!.getValue();
|
||||
return value;
|
||||
});
|
||||
|
||||
// 对itemsMap重新生成并刷新当前setter数据
|
||||
const newItems: SettingField[] = [];
|
||||
// const newItemsMap = {};
|
||||
itemsMap.clear();
|
||||
for (let i = 0; i < sortValues.length; i++) {
|
||||
const newItem = field.createField({
|
||||
name: i,
|
||||
setter: itemSetter,
|
||||
// FIXME:
|
||||
forceInline: 1,
|
||||
setValue: this.onItemChange,
|
||||
});
|
||||
newItems[i] = newItem;
|
||||
|
||||
itemsMap.set(newItem.id, newItem);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
items: newItems,
|
||||
itemsMap,
|
||||
}, () => {
|
||||
sortValues && sortValues.map((value, index) => {
|
||||
newItems[index].setValue(value);
|
||||
return newItems;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private scrollToLast = false;
|
||||
|
||||
onAdd() {
|
||||
const { items, itemsMap } = this.state;
|
||||
const { itemSetter, onChange } = this.props;
|
||||
const initialValue = typeof itemSetter === 'object' ? (itemSetter as any).initialValue : null;
|
||||
const item = this.props.field.createField({
|
||||
name: items.length,
|
||||
setter: itemSetter,
|
||||
// FIXME:
|
||||
forceInline: 1,
|
||||
setValue: this.onItemChange,
|
||||
});
|
||||
items.push(item);
|
||||
itemsMap.set(item.id, item);
|
||||
this.scrollToLast = true;
|
||||
this.setState({
|
||||
items: items.slice(),
|
||||
}, () => {
|
||||
item.setValue(typeof initialValue === 'function' ? initialValue(item) : initialValue);
|
||||
});
|
||||
}
|
||||
|
||||
onRemove(field: SettingField) {
|
||||
const { onChange } = this.props;
|
||||
const { items, itemsMap } = this.state;
|
||||
let i = items.indexOf(field);
|
||||
const values = items.map((item) => {
|
||||
return item.getValue();
|
||||
});
|
||||
if (i < 0) {
|
||||
return;
|
||||
}
|
||||
items.splice(i, 1);
|
||||
values.splice(i, 1);
|
||||
const l = items.length;
|
||||
while (i < l) {
|
||||
items[i].setKey(i);
|
||||
i++;
|
||||
}
|
||||
itemsMap.delete(field.id);
|
||||
field.remove();
|
||||
onChange && onChange(values);
|
||||
this.setState({ items: items.slice() });
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.state.items.forEach((field) => {
|
||||
field.purge();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let columns: any = null;
|
||||
if (this.props.columns) {
|
||||
columns = this.props.columns.map((column) => (
|
||||
<Title key={column.name} title={column.title || (column.name as string)} />
|
||||
));
|
||||
}
|
||||
|
||||
const { items } = this.state;
|
||||
const { scrollToLast } = this;
|
||||
this.scrollToLast = false;
|
||||
const lastIndex = items.length - 1;
|
||||
|
||||
const content =
|
||||
items.length > 0 ? (
|
||||
<div className="lc-setter-list-scroll-body">
|
||||
<Sortable itemClassName="lc-setter-list-card" onSort={this.onSort.bind(this)}>
|
||||
{items.map((field, index) => (
|
||||
<ArrayItem
|
||||
key={field.id}
|
||||
scrollIntoView={scrollToLast && index === lastIndex}
|
||||
field={field}
|
||||
onRemove={this.onRemove.bind(this, field)}
|
||||
/>
|
||||
))}
|
||||
</Sortable>
|
||||
</div>
|
||||
) : this.props.multiValue ? (<Message type="warning">当前选择了多个节点,且值不一致,修改会覆盖所有值</Message>) : (<Message type="notice">当前项目为空</Message>);
|
||||
|
||||
return (
|
||||
<div className="lc-setter-list lc-block-setter">
|
||||
{/* <div className="lc-block-setter-actions">
|
||||
<Button size="medium" onClick={this.onAdd.bind(this)}>
|
||||
<Icon type="add" />
|
||||
<span>添加</span>
|
||||
</Button>
|
||||
</div> */}
|
||||
{columns && <div className="lc-setter-list-columns">{columns}</div>}
|
||||
{content}
|
||||
<Button className="lc-setter-list-add" type="primary" onClick={this.onAdd.bind(this)}>
|
||||
<Icon type="add" />
|
||||
<span>添加一项</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayItem extends Component<{
|
||||
field: SettingField;
|
||||
onRemove: () => void;
|
||||
scrollIntoView: boolean;
|
||||
}> {
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private shell?: HTMLDivElement | null;
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.scrollIntoView && this.shell) {
|
||||
this.shell.parentElement!.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { onRemove, field } = this.props;
|
||||
return (
|
||||
<div className="lc-listitem" ref={(ref) => { this.shell = ref; }}>
|
||||
<div draggable className="lc-listitem-handler">
|
||||
<Icon type="ellipsis" size="small" />
|
||||
</div>
|
||||
<div className="lc-listitem-body">{createSettingFieldView(field, field.parent)}</div>
|
||||
<div className="lc-listitem-actions">
|
||||
<div className="lc-listitem-action" onClick={onRemove}>
|
||||
<Icon type="ashbin" size="small" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TableSetter extends ListSetter {
|
||||
// todo:
|
||||
// forceInline = 1
|
||||
// has more actions
|
||||
}
|
||||
|
||||
export default class ArraySetter extends Component<{
|
||||
value: any[];
|
||||
field: SettingField;
|
||||
itemSetter?: SetterType;
|
||||
mode?: 'popup' | 'list';
|
||||
forceInline?: boolean;
|
||||
multiValue?: boolean;
|
||||
}> {
|
||||
static contextType = PopupContext;
|
||||
|
||||
private pipe: any;
|
||||
|
||||
render() {
|
||||
const { mode, forceInline, ...props } = this.props;
|
||||
const { field, itemSetter } = props;
|
||||
let columns: FieldConfig[] | undefined;
|
||||
if ((itemSetter as SetterConfig)?.componentName === 'ObjectSetter') {
|
||||
const items: FieldConfig[] = (itemSetter as any).props?.config?.items;
|
||||
if (items && Array.isArray(items)) {
|
||||
columns = items.filter((item) => item.isRequired || item.important || (item.setter as any)?.isRequired);
|
||||
if (columns.length > 4) {
|
||||
columns = columns.slice(0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode === 'popup' || forceInline) {
|
||||
const title = (
|
||||
<Fragment>
|
||||
编辑:
|
||||
<Title title={field.title} />
|
||||
</Fragment>
|
||||
);
|
||||
if (!this.pipe) {
|
||||
let width = 360;
|
||||
if (columns) {
|
||||
if (columns.length === 3) {
|
||||
width = 480;
|
||||
} else if (columns.length > 3) {
|
||||
width = 600;
|
||||
}
|
||||
}
|
||||
this.pipe = (this.context as PopupPipe).create({ width });
|
||||
}
|
||||
|
||||
this.pipe.send(<TableSetter key={field.id} {...props} columns={columns} />, title);
|
||||
return (
|
||||
<Button
|
||||
type={forceInline ? 'normal' : 'primary'}
|
||||
onClick={(e) => {
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon type="edit" />
|
||||
{forceInline ? title : '编辑数组'}
|
||||
</Button>
|
||||
);
|
||||
} else {
|
||||
return <ListSetter {...props} columns={columns?.slice(0, 2)} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
.lc-sortable {
|
||||
position: relative;
|
||||
|
||||
.lc-sortable-card {
|
||||
box-sizing: border-box;
|
||||
&:after, &:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
&.lc-dragging {
|
||||
outline: 2px dashed var(--color-brand);
|
||||
outline-offset: -2px;
|
||||
> * {
|
||||
visibility: hidden;
|
||||
}
|
||||
border-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
[draggable] {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
}
|
||||
@ -1,223 +0,0 @@
|
||||
import { Component, Children, ReactElement } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './sortable.less';
|
||||
|
||||
class Sortable extends Component<{
|
||||
className?: string;
|
||||
itemClassName?: string;
|
||||
onSort?: (sortedIds: Array<string | number>) => void;
|
||||
dragImageSourceHandler?: (elem: Element) => Element;
|
||||
children: ReactElement[];
|
||||
}> {
|
||||
private shell?: HTMLDivElement | null;
|
||||
|
||||
private items?: Array<string | number>;
|
||||
|
||||
private willDetach?: () => void;
|
||||
|
||||
componentDidMount() {
|
||||
const box = this.shell!;
|
||||
|
||||
let isDragEnd = false;
|
||||
|
||||
/**
|
||||
* target node to be dragged
|
||||
*/
|
||||
let source: Element | null;
|
||||
|
||||
/**
|
||||
* node to be placed
|
||||
*/
|
||||
let ref: Element | null;
|
||||
|
||||
/**
|
||||
* next sibling of the source node
|
||||
*/
|
||||
let origRef: Element | null;
|
||||
|
||||
/**
|
||||
* accurately locate the node from event
|
||||
*/
|
||||
const locate = (e: DragEvent) => {
|
||||
let y = e.clientY;
|
||||
if (e.view !== window && e.view!.frameElement) {
|
||||
y += e.view!.frameElement.getBoundingClientRect().top;
|
||||
}
|
||||
let node = box.firstElementChild as HTMLDivElement;
|
||||
while (node) {
|
||||
if (node !== source && node.dataset.id) {
|
||||
const rect = node.getBoundingClientRect();
|
||||
|
||||
if (rect.height <= 0) continue;
|
||||
if (y < rect.top + rect.height / 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node.nextElementSibling as HTMLDivElement;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* find the source node
|
||||
*/
|
||||
const getSource = (e: DragEvent) => {
|
||||
const target = e.target as Element;
|
||||
if (!target || !box.contains(target) || target === box) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let node = box.firstElementChild;
|
||||
while (node) {
|
||||
if (node.contains(target)) {
|
||||
return node;
|
||||
}
|
||||
node = node.nextElementSibling;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const sort = (beforeId: string | number | null | undefined) => {
|
||||
if (!source) return;
|
||||
|
||||
const sourceId = (source as HTMLDivElement).dataset.id;
|
||||
const items = this.items!;
|
||||
const origIndex = items.findIndex(id => id == sourceId);
|
||||
|
||||
let newIndex = beforeId ? items.findIndex(id => id == beforeId) : items.length;
|
||||
|
||||
if (origIndex < 0 || newIndex < 0) return;
|
||||
if (this.props.onSort) {
|
||||
if (newIndex > origIndex) {
|
||||
newIndex -= 1;
|
||||
}
|
||||
if (origIndex === newIndex) return;
|
||||
const item = items.splice(origIndex, 1);
|
||||
items.splice(newIndex, 0, item[0]);
|
||||
|
||||
this.props.onSort(items);
|
||||
}
|
||||
};
|
||||
|
||||
const dragstart = (e: DragEvent) => {
|
||||
isDragEnd = false;
|
||||
source = getSource(e);
|
||||
if (!source) {
|
||||
return false;
|
||||
}
|
||||
origRef = source.nextElementSibling;
|
||||
const rect = source.getBoundingClientRect();
|
||||
let dragSource = source;
|
||||
if (this.props.dragImageSourceHandler) {
|
||||
dragSource = this.props.dragImageSourceHandler(source);
|
||||
}
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.setDragImage(dragSource, e.clientX - rect.left, e.clientY - rect.top);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
try {
|
||||
e.dataTransfer.setData('application/json', {} as any);
|
||||
} catch (ex) {
|
||||
// eslint-disable-line
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
source!.classList.add('lc-dragging');
|
||||
}, 0);
|
||||
return true;
|
||||
};
|
||||
|
||||
const placeAt = (beforeRef: Element | null) => {
|
||||
if (beforeRef) {
|
||||
if (beforeRef !== source) {
|
||||
box.insertBefore(source!, beforeRef);
|
||||
}
|
||||
} else {
|
||||
box.appendChild(source!);
|
||||
}
|
||||
};
|
||||
|
||||
const adjust = (e: DragEvent) => {
|
||||
if (isDragEnd) return;
|
||||
ref = locate(e);
|
||||
placeAt(ref);
|
||||
};
|
||||
|
||||
let lastDragEvent: DragEvent | null;
|
||||
const drag = (e: DragEvent) => {
|
||||
if (!source) return;
|
||||
e.preventDefault();
|
||||
if (lastDragEvent) {
|
||||
if (lastDragEvent.clientX === e.clientX && lastDragEvent.clientY === e.clientY) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastDragEvent = e;
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
adjust(e);
|
||||
};
|
||||
|
||||
const dragend = (e: DragEvent) => {
|
||||
isDragEnd = true;
|
||||
if (!source) return;
|
||||
e.preventDefault();
|
||||
source.classList.remove('lc-dragging');
|
||||
placeAt(origRef);
|
||||
sort(ref ? (ref as HTMLDivElement).dataset.id : null);
|
||||
source = null;
|
||||
ref = null;
|
||||
origRef = null;
|
||||
lastDragEvent = null;
|
||||
};
|
||||
|
||||
box.addEventListener('dragstart', dragstart);
|
||||
document.addEventListener('dragover', drag);
|
||||
document.addEventListener('drag', drag);
|
||||
document.addEventListener('dragend', dragend);
|
||||
|
||||
this.willDetach = () => {
|
||||
box.removeEventListener('dragstart', dragstart);
|
||||
document.removeEventListener('dragover', drag);
|
||||
document.removeEventListener('drag', drag);
|
||||
document.removeEventListener('dragend', dragend);
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.willDetach) {
|
||||
this.willDetach();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, itemClassName, children } = this.props;
|
||||
const items: Array<string | number> = [];
|
||||
const cards = Children.map(children, child => {
|
||||
const id = child.key!;
|
||||
items.push(id);
|
||||
return (
|
||||
<div key={id} data-id={id} className={classNames('lc-sortable-card', itemClassName)}>
|
||||
{child}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
this.items = items;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('lc-sortable', className)}
|
||||
ref={ref => {
|
||||
this.shell = ref;
|
||||
}}
|
||||
>
|
||||
{cards}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Sortable;
|
||||
@ -1,103 +0,0 @@
|
||||
.lc-setter-list {
|
||||
[draggable] {
|
||||
cursor: move;
|
||||
}
|
||||
color: var(--color-text);
|
||||
|
||||
.next-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 1 !important;
|
||||
max-width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.lc-setter-list-add {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
|
||||
.lc-setter-list-columns {
|
||||
display: flex;
|
||||
> .lc-title {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
margin-left: 47px;
|
||||
margin-right: 28px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.lc-setter-list-scroll-body {
|
||||
margin: -8px -5px;
|
||||
padding: 8px 10px;
|
||||
overflow-y: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.lc-setter-list-card {
|
||||
border: 1px solid rgba(31,56,88,.2);
|
||||
background-color: var(--color-block-background-light);
|
||||
border-radius: 3px;
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.lc-listitem {
|
||||
position: relative;
|
||||
outline: none;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
height: 34px;
|
||||
|
||||
.lc-listitem-actions {
|
||||
margin: 0 3px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
.lc-listitem-action {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.lc-listitem-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
text-overflow: ellipsis;
|
||||
.lc-field {
|
||||
padding: 0 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
>.lc-field-body {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
> * {
|
||||
width: 100%;
|
||||
}
|
||||
.next-btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.lc-listitem-handler {
|
||||
margin-left: 2px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
.next-icon-ellipsis {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,368 +0,0 @@
|
||||
import React, { Component, ComponentClass, ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Dropdown, Menu } from '@alifd/next';
|
||||
import {
|
||||
SetterConfig,
|
||||
CustomView,
|
||||
DynamicProps,
|
||||
DynamicSetter,
|
||||
TitleContent,
|
||||
isSetterConfig,
|
||||
isDynamicSetter,
|
||||
} from '@ali/lowcode-types';
|
||||
import {
|
||||
getSetter,
|
||||
getSettersMap,
|
||||
computed,
|
||||
obx,
|
||||
Title,
|
||||
createSetterContent,
|
||||
observer,
|
||||
shallowIntl,
|
||||
} from '@ali/lowcode-editor-core';
|
||||
|
||||
import { IconConvert } from '../../icons/convert';
|
||||
import { intlNode } from '../../locale';
|
||||
|
||||
import './style.less';
|
||||
import { SettingField } from '@ali/lowcode-designer';
|
||||
import { IconVariable } from '../../icons/variable';
|
||||
|
||||
export interface SetterItem {
|
||||
name: string;
|
||||
title: TitleContent;
|
||||
setter: string | DynamicSetter | CustomView;
|
||||
props?: object | DynamicProps;
|
||||
condition?: (field: SettingField) => boolean;
|
||||
initialValue?: any | ((field: SettingField) => any);
|
||||
list: boolean;
|
||||
}
|
||||
|
||||
function nomalizeSetters(setters?: Array<string | SetterConfig | CustomView | DynamicSetter>): SetterItem[] {
|
||||
if (!setters) {
|
||||
const normalized: SetterItem[] = [];
|
||||
getSettersMap().forEach((setter, name) => {
|
||||
if (name === 'MixedSetter') {
|
||||
return;
|
||||
}
|
||||
normalized.push({
|
||||
name,
|
||||
title: setter.title || name,
|
||||
setter: name,
|
||||
condition: setter.condition,
|
||||
initialValue: setter.initialValue,
|
||||
list: setter.recommend || false,
|
||||
});
|
||||
});
|
||||
return normalized;
|
||||
}
|
||||
const names: string[] = [];
|
||||
function generateName(n: string) {
|
||||
let idx = 1;
|
||||
let got = n;
|
||||
while (names.indexOf(got) > -1) {
|
||||
got = `${n}:${idx++}`;
|
||||
}
|
||||
names.push(got);
|
||||
return got;
|
||||
}
|
||||
return setters.map((setter) => {
|
||||
const config: any = {
|
||||
setter,
|
||||
list: true,
|
||||
};
|
||||
if (isSetterConfig(setter)) {
|
||||
config.setter = setter.componentName;
|
||||
config.props = setter.props;
|
||||
config.condition = setter.condition;
|
||||
config.initialValue = setter.initialValue;
|
||||
config.title = setter.title;
|
||||
}
|
||||
if (typeof config.setter === 'string') {
|
||||
config.name = config.setter;
|
||||
names.push(config.name);
|
||||
const info = getSetter(config.setter);
|
||||
if (!config.title) {
|
||||
config.title = info?.title || config.setter;
|
||||
}
|
||||
if (!config.condition) {
|
||||
config.condition = info?.condition;
|
||||
}
|
||||
if (!config.initialValue) {
|
||||
config.initialValue = info?.initialValue;
|
||||
}
|
||||
} else {
|
||||
config.name = generateName((config.setter as any)?.displayName || (config.setter as any)?.name || 'CustomSetter');
|
||||
if (!config.title) {
|
||||
config.title = config.name;
|
||||
}
|
||||
}
|
||||
return config;
|
||||
});
|
||||
}
|
||||
|
||||
interface VariableSetter extends ComponentClass {
|
||||
show(params: object): void;
|
||||
}
|
||||
|
||||
@observer
|
||||
export default class MixedSetter extends Component<{
|
||||
field: SettingField;
|
||||
setters?: Array<string | SetterConfig | CustomView | DynamicSetter>;
|
||||
onSetterChange?: (field: SettingField, name: string) => void;
|
||||
onChange?: (val: any) => void;
|
||||
value?: any;
|
||||
className?: string;
|
||||
}> {
|
||||
private setters = nomalizeSetters(this.props.setters);
|
||||
|
||||
// set name ,used in setting Transducer
|
||||
static displayName = 'MixedSetter';
|
||||
|
||||
@obx.ref private used?: string;
|
||||
|
||||
@computed private getCurrentSetter() {
|
||||
const { field } = this.props;
|
||||
let firstMatched: SetterItem | undefined;
|
||||
let firstDefault: SetterItem | undefined;
|
||||
for (const setter of this.setters) {
|
||||
if (setter.name === this.used) {
|
||||
return setter;
|
||||
}
|
||||
if (!setter.condition) {
|
||||
if (!firstDefault) {
|
||||
firstDefault = setter;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!firstMatched && setter.condition(field)) {
|
||||
firstMatched = setter;
|
||||
}
|
||||
}
|
||||
return firstMatched || firstDefault || this.setters[0];
|
||||
}
|
||||
|
||||
// dirty fix vision variable setter logic
|
||||
private hasVariableSetter = this.setters.some((item) => item.name === 'VariableSetter');
|
||||
|
||||
private useSetter = (name: string) => {
|
||||
const { field } = this.props;
|
||||
if (name === 'VariableSetter') {
|
||||
const setterComponent = getSetter('VariableSetter')?.component as any;
|
||||
if (setterComponent && setterComponent.isPopup) {
|
||||
setterComponent.show({ prop: field });
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (name === this.used) {
|
||||
return;
|
||||
}
|
||||
const setter = this.setters.find((item) => item.name === name);
|
||||
// reset hotValue
|
||||
field.setHotValue(undefined);
|
||||
this.used = name;
|
||||
if (setter) {
|
||||
this.handleInitial(setter);
|
||||
}
|
||||
};
|
||||
|
||||
private handleInitial({ initialValue }: SetterItem) {
|
||||
const { field, onChange } = this.props;
|
||||
let newValue: any = initialValue;
|
||||
if (newValue && typeof newValue === 'function') {
|
||||
newValue = newValue(field);
|
||||
}
|
||||
onChange && onChange(newValue);
|
||||
}
|
||||
|
||||
private shell: HTMLDivElement | null = null;
|
||||
|
||||
private checkIsBlockField() {
|
||||
if (this.shell) {
|
||||
const setter = this.shell.firstElementChild;
|
||||
if (setter && setter.classList.contains('lc-block-setter')) {
|
||||
this.shell.classList.add('lc-block-setter');
|
||||
} else {
|
||||
this.shell.classList.remove('lc-block-setter');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.checkIsBlockField();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.checkIsBlockField();
|
||||
}
|
||||
|
||||
private renderCurrentSetter(currentSetter?: SetterItem, extraProps?: object) {
|
||||
const { className, field, setters, onSetterChange, ...restProps } = this.props;
|
||||
if (!currentSetter) {
|
||||
// TODO: use intl
|
||||
if (restProps.value == null) {
|
||||
return <span>NullValue</span>;
|
||||
} else {
|
||||
return <span>InvalidValue</span>;
|
||||
}
|
||||
}
|
||||
const { setter, props } = currentSetter;
|
||||
let setterProps: any = {};
|
||||
let setterType: any;
|
||||
let dynamicProps: any = {};
|
||||
if (isDynamicSetter(setter)) {
|
||||
setterType = setter.call(field, field);
|
||||
// { componentName: string; props: object }
|
||||
if (typeof setterType === 'object' && typeof setterType.componentName === 'string') {
|
||||
dynamicProps = setterType.props || {};
|
||||
setterType = setterType.componentName;
|
||||
}
|
||||
} else {
|
||||
setterType = setter;
|
||||
}
|
||||
if (props) {
|
||||
setterProps = props;
|
||||
if (typeof setterProps === 'function') {
|
||||
setterProps = setterProps(field);
|
||||
}
|
||||
}
|
||||
|
||||
return createSetterContent(setterType, {
|
||||
...shallowIntl(setterProps),
|
||||
field,
|
||||
...restProps,
|
||||
...extraProps,
|
||||
...dynamicProps,
|
||||
onInitial: () => {
|
||||
this.handleInitial(currentSetter);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private contentsFromPolyfill(setterComponent: VariableSetter) {
|
||||
const { field } = this.props;
|
||||
|
||||
const n = this.setters.length;
|
||||
|
||||
let setterContent: any;
|
||||
let actions: any;
|
||||
if (n < 3) {
|
||||
const tipContent = field.isUseVariable()
|
||||
? intlNode('Binded: {expr}', { expr: field.getVariableValue() })
|
||||
: intlNode('Variable Binding');
|
||||
if (n === 1) {
|
||||
// =1: 原地展示<当前绑定的值,点击调用 VariableSetter.show>,icon 高亮是否->isUseVaiable,点击 VariableSetter.show
|
||||
setterContent = (
|
||||
<a
|
||||
onClick={() => {
|
||||
setterComponent.show({ prop: field });
|
||||
}}
|
||||
>
|
||||
{tipContent}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
// =2: 另外一个 Setter 原地展示,icon 高亮,点击弹出调用 VariableSetter.show
|
||||
// FIXME! use variable placeholder setter
|
||||
const otherSetter = this.setters.find((item) => item.name !== 'VariableSetter')!;
|
||||
setterContent = this.renderCurrentSetter(otherSetter, {
|
||||
value: field.getMockOrValue(),
|
||||
});
|
||||
}
|
||||
actions = (
|
||||
<Title
|
||||
className={field.isUseVariable() ? 'variable-binded' : ''}
|
||||
title={{
|
||||
icon: <IconVariable size={24} />,
|
||||
tip: tipContent,
|
||||
}}
|
||||
onClick={() => {
|
||||
setterComponent.show({ prop: field });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
// >=3: 原地展示当前 setter<当前绑定的值,点击调用 VariableSetter.show>,icon tip 提示绑定的值,点击展示切换 Setter,点击其它 setter 直接切换,点击 Variable Setter-> VariableSetter.show
|
||||
const currentSetter = field.isUseVariable()
|
||||
? this.setters.find((item) => item.name === 'VariableSetter')
|
||||
: this.getCurrentSetter();
|
||||
if (currentSetter?.name === 'VariableSetter') {
|
||||
setterContent = (
|
||||
<a
|
||||
onClick={() => {
|
||||
setterComponent.show({ prop: field });
|
||||
}}
|
||||
>
|
||||
{intlNode('Binded: {expr}', { expr: field.getVariableValue() })}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
setterContent = this.renderCurrentSetter(currentSetter);
|
||||
}
|
||||
actions = this.renderSwitchAction(currentSetter);
|
||||
}
|
||||
|
||||
return {
|
||||
setterContent,
|
||||
actions,
|
||||
};
|
||||
}
|
||||
|
||||
private renderSwitchAction(currentSetter?: SetterItem) {
|
||||
const usedName = currentSetter?.name || this.used;
|
||||
const triggerNode = (
|
||||
<Title
|
||||
title={{
|
||||
tip: intlNode('Switch Setter'),
|
||||
// FIXME: got a beautiful icon
|
||||
icon: <IconConvert size={24} />,
|
||||
}}
|
||||
className="lc-switch-trigger"
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Dropdown trigger={triggerNode} triggerType="click" align="tr br">
|
||||
<Menu selectMode="single" hasSelectedIcon selectedKeys={usedName} onItemClick={this.useSetter}>
|
||||
{this.setters
|
||||
.filter((setter) => setter.list || setter.name === usedName)
|
||||
.map((setter) => {
|
||||
return (
|
||||
<Menu.Item key={setter.name}>
|
||||
<Title title={setter.title} />
|
||||
</Menu.Item>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className } = this.props;
|
||||
let contents: {
|
||||
setterContent: ReactNode,
|
||||
actions: ReactNode,
|
||||
} | undefined;
|
||||
if (this.hasVariableSetter) {
|
||||
// polyfill vision variable setter logic
|
||||
const setterComponent = getSetter('VariableSetter')?.component as any;
|
||||
if (setterComponent && setterComponent.isPopup) {
|
||||
contents = this.contentsFromPolyfill(setterComponent);
|
||||
}
|
||||
}
|
||||
if (!contents) {
|
||||
const currentSetter = this.getCurrentSetter();
|
||||
contents = {
|
||||
setterContent: this.renderCurrentSetter(currentSetter),
|
||||
actions: this.renderSwitchAction(currentSetter),
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={(shell) => { this.shell = shell; }} className={classNames('lc-setter-mixed', className)}>
|
||||
{contents.setterContent}
|
||||
<div className="lc-setter-actions">{contents.actions}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
.lc-setter-mixed {
|
||||
min-width: 0;
|
||||
margin-right: 26px;
|
||||
display: block;
|
||||
position: relative;
|
||||
>.lc-setter-actions {
|
||||
position: absolute;
|
||||
right: -4px;
|
||||
top: 50%;
|
||||
transform: translate(100%, -50%);
|
||||
.lc-switch-trigger {
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.lc-title {
|
||||
cursor: pointer;
|
||||
|
||||
.lc-title-icon svg {
|
||||
fill: #8f9bb3;
|
||||
}
|
||||
}
|
||||
.variable-binded {
|
||||
background: var(--color-brand, #006cff);
|
||||
color: #fff!important;
|
||||
border-radius: 3px;
|
||||
|
||||
.lc-title-icon svg {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.next-input,.next-date-picker,.next-month-picker {
|
||||
width: 100%;
|
||||
}
|
||||
&.lc-block-setter {
|
||||
position: static;
|
||||
margin-right: 0;
|
||||
>.lc-setter-actions {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lc-block-field > .lc-field-body > .lc-setter-mixed {
|
||||
position: static;
|
||||
margin-right: 0;
|
||||
>.lc-setter-actions {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 0;
|
||||
height: 32px;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.lc-block-field > .lc-field-body > .lc-setter-mixed{
|
||||
|
||||
}
|
||||
.lc-accordion-field > .lc-field-body > .lc-setter-mixed {
|
||||
position: static;
|
||||
margin-right: 0;
|
||||
> .lc-setter-actions {
|
||||
right: 36px;
|
||||
top: 4px;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@ -1,203 +0,0 @@
|
||||
import { Component, Fragment } from 'react';
|
||||
import { Icon, Button } from '@alifd/next';
|
||||
import { SetterType, FieldConfig, CustomView } from '@ali/lowcode-types';
|
||||
import { createSettingFieldView } from '../settings/settings-pane';
|
||||
import { PopupContext, PopupPipe } from '../popup';
|
||||
import { isSettingField, SettingField } from '@ali/lowcode-designer';
|
||||
import './style.less';
|
||||
import { Title } from '@ali/lowcode-editor-core';
|
||||
|
||||
export default class ObjectSetter extends Component<{
|
||||
field: SettingField;
|
||||
descriptor?: string | ((rowField: SettingField) => string);
|
||||
config: ObjectSetterConfig;
|
||||
mode?: 'popup' | 'form';
|
||||
// 1: in tablerow 2: in listrow 3: in column-cell
|
||||
forceInline?: number;
|
||||
}> {
|
||||
render() {
|
||||
const { mode, forceInline = 0, ...props } = this.props;
|
||||
if (forceInline || mode === 'popup') {
|
||||
if (forceInline > 2 || mode === 'popup') {
|
||||
// popup
|
||||
return <RowSetter {...props} primaryButton={!forceInline} />;
|
||||
} else {
|
||||
return <RowSetter columns={forceInline > 1 ? 2 : 4} {...props} />;
|
||||
}
|
||||
} else {
|
||||
// form
|
||||
return <FormSetter {...props} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ObjectSetterConfig {
|
||||
items?: FieldConfig[];
|
||||
extraSetter?: SetterType;
|
||||
}
|
||||
|
||||
interface RowSetterProps {
|
||||
field: SettingField;
|
||||
descriptor?: string | ((rowField: SettingField) => string);
|
||||
config: ObjectSetterConfig;
|
||||
columns?: number;
|
||||
primaryButton?: boolean;
|
||||
}
|
||||
|
||||
class RowSetter extends Component<RowSetterProps> {
|
||||
static contextType = PopupContext;
|
||||
|
||||
state: any = {
|
||||
descriptor: '',
|
||||
};
|
||||
|
||||
private items?: SettingField[];
|
||||
|
||||
constructor(props: RowSetterProps) {
|
||||
super(props);
|
||||
const { config, descriptor, field, columns } = props;
|
||||
const items: SettingField[] = [];
|
||||
if (columns && config?.items) {
|
||||
const l = Math.min(config.items.length, columns);
|
||||
for (let i = 0; i < l; i++) {
|
||||
const conf = config.items[i];
|
||||
if (conf.isRequired || conf.important || (conf.setter as any)?.isRequired) {
|
||||
const item = field.createField({
|
||||
...conf,
|
||||
// in column-cell
|
||||
forceInline: 3,
|
||||
});
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (items.length > 0) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
let firstRun = true;
|
||||
field.onEffect(() => {
|
||||
const state: any = {};
|
||||
if (descriptor) {
|
||||
if (typeof descriptor === 'function') {
|
||||
state.descriptor = descriptor(field);
|
||||
} else {
|
||||
state.descriptor = field.getPropValue(descriptor);
|
||||
}
|
||||
} else {
|
||||
state.descriptor = field.title;
|
||||
}
|
||||
|
||||
if (firstRun) {
|
||||
firstRun = false;
|
||||
this.state = state;
|
||||
} else {
|
||||
this.setState(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
shouldComponentUpdate(_: any, nextState: any) {
|
||||
if (this.state.decriptor !== nextState.decriptor) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private pipe: any;
|
||||
|
||||
render() {
|
||||
const { items } = this;
|
||||
const { field, primaryButton, config } = this.props;
|
||||
|
||||
if (!this.pipe) {
|
||||
this.pipe = (this.context as PopupPipe).create({ width: 320 });
|
||||
}
|
||||
|
||||
const title = (
|
||||
<Fragment>
|
||||
编辑:
|
||||
<Title title={this.state.descriptor} />
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
this.pipe.send(<FormSetter key={field.id} field={field} config={config} />, title);
|
||||
|
||||
if (items) {
|
||||
return (
|
||||
<div className="lc-setter-object-row">
|
||||
<div
|
||||
className="lc-setter-object-row-edit"
|
||||
onClick={(e) => {
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon size="small" type="edit" />
|
||||
</div>
|
||||
<div className="lc-setter-object-row-body">{items.map((item) => createSettingFieldView(item, field))}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type={primaryButton === false ? 'normal' : 'primary'}
|
||||
onClick={(e) => {
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon type="edit" />
|
||||
{title}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface FormSetterProps {
|
||||
field: SettingField;
|
||||
config: ObjectSetterConfig;
|
||||
}
|
||||
class FormSetter extends Component<FormSetterProps> {
|
||||
private items: (SettingField | CustomView)[];
|
||||
|
||||
constructor(props: RowSetterProps) {
|
||||
super(props);
|
||||
const { config, field } = props;
|
||||
const { extraProps } = field;
|
||||
|
||||
if (Array.isArray(field.items) && field.items.length > 0) {
|
||||
field.items.forEach((item: SettingField | CustomView) => {
|
||||
if (isSettingField(item)) {
|
||||
const originalSetValue = item.extraProps.setValue;
|
||||
item.extraProps.setValue = (...args) => {
|
||||
// 调用子字段本身的 setValue
|
||||
originalSetValue?.apply(null, args);
|
||||
// 调用父字段本身的 setValue
|
||||
extraProps.setValue?.apply(null, args);
|
||||
};
|
||||
}
|
||||
});
|
||||
this.items = field.items;
|
||||
} else {
|
||||
this.items = (config?.items || []).map((conf) => field.createField({
|
||||
...conf,
|
||||
setValue: extraProps?.setValue,
|
||||
}));
|
||||
}
|
||||
// TODO: extraConfig for custom fields
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { field } = this.props;
|
||||
return (
|
||||
<div className="lc-setter-object lc-block-setter">
|
||||
{this.items.map((item, index) => createSettingFieldView(item, field, index))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
.lc-setter-object-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
.lc-setter-object-row-edit {
|
||||
width: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lc-setter-object-row-body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
.lc-field {
|
||||
padding: 0 !important;
|
||||
.lc-field-body {
|
||||
padding: 0 !important; margin: 0 !important;
|
||||
}
|
||||
}
|
||||
> * {
|
||||
flex: 1;
|
||||
flex-shrink: 1;
|
||||
margin-left: 2px;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
.lc-setter-slot {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
.lc-slot-params {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.lc-setter-slot-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
import { Component } from 'react';
|
||||
import { isJSSlot } from '@ali/lowcode-types';
|
||||
import { Button, Input, Icon } from '@alifd/next';
|
||||
import './index.less';
|
||||
|
||||
export default class SlotSetter extends Component<{
|
||||
value: any;
|
||||
onChange?: (value: any) => void;
|
||||
onInitial?: () => void;
|
||||
// 是否支持设置入参
|
||||
supportParams?: boolean;
|
||||
}> {
|
||||
private handleInitial = () => {
|
||||
const { onChange, onInitial } = this.props;
|
||||
if (onInitial) {
|
||||
onInitial();
|
||||
return;
|
||||
}
|
||||
if (!onChange) {
|
||||
return;
|
||||
}
|
||||
onChange({
|
||||
type: 'JSSlot',
|
||||
value: null,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { value, onChange, supportParams } = this.props;
|
||||
if (!isJSSlot(value)) {
|
||||
return (
|
||||
<Button type="primary" onClick={this.handleInitial}>
|
||||
开启插槽
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const hasParams = value.params && Array.isArray(value.params);
|
||||
return (
|
||||
<div className="lc-setter-slot lc-setter-slot-column">
|
||||
<Button
|
||||
onClick={() => {
|
||||
// TODO: use slot first child literal value pad
|
||||
onChange && onChange(null);
|
||||
}}
|
||||
type="secondary"
|
||||
>
|
||||
关闭插槽
|
||||
</Button>
|
||||
{hasParams ? (
|
||||
<Input
|
||||
className="lc-slot-params"
|
||||
addonTextBefore="入参"
|
||||
placeholder="插槽入参,以逗号风格"
|
||||
value={value.params!.join(',')}
|
||||
autoFocus
|
||||
onChange={(val) => {
|
||||
val = val.trim();
|
||||
const params = val ? val.split(/ *, */) : [];
|
||||
onChange &&
|
||||
onChange({
|
||||
...value,
|
||||
params: params.length == 0 ? [''] : params,
|
||||
});
|
||||
}}
|
||||
addonAfter={
|
||||
<Button
|
||||
type="secondary"
|
||||
onClick={() => {
|
||||
onChange &&
|
||||
onChange({
|
||||
...value,
|
||||
params: [''],
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon type="close" />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
) : supportParams ? (
|
||||
<Button
|
||||
className="lc-slot-params"
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
onChange &&
|
||||
onChange({
|
||||
...value,
|
||||
params: [],
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加入参
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,62 +1,9 @@
|
||||
import { registerSetter } from '@ali/lowcode-editor-core';
|
||||
import { registerMetadataTransducer } from '@ali/lowcode-designer';
|
||||
import ArraySetter from './components/array-setter';
|
||||
import ObjectSetter from './components/object-setter';
|
||||
import MixedSetter from './components/mixed-setter';
|
||||
import { isPlainObject } from '@ali/lowcode-utils';
|
||||
import parseJSFunc from './transducers/parse-func';
|
||||
import parseProps from './transducers/parse-props';
|
||||
import addonCombine from './transducers/addon-combine';
|
||||
import SlotSetter from './components/slot-setter';
|
||||
import { isJSSlot } from '@ali/lowcode-types';
|
||||
|
||||
export const registerDefaults = () => {
|
||||
registerSetter('ArraySetter', {
|
||||
component: ArraySetter,
|
||||
defaultProps: {},
|
||||
title: 'ArraySetter', // TODO
|
||||
condition: (field: any) => {
|
||||
const v = field.getValue();
|
||||
return v == null || Array.isArray(v);
|
||||
},
|
||||
initialValue: [],
|
||||
recommend: true,
|
||||
});
|
||||
registerSetter('ObjectSetter', {
|
||||
component: ObjectSetter,
|
||||
// todo: defaultProps
|
||||
defaultProps: {},
|
||||
title: 'ObjectSetter', // TODO
|
||||
condition: (field: any) => {
|
||||
const v = field.getValue();
|
||||
return v == null || isPlainObject(v);
|
||||
},
|
||||
initialValue: {},
|
||||
recommend: true,
|
||||
});
|
||||
registerSetter('SlotSetter', {
|
||||
component: SlotSetter,
|
||||
title: {
|
||||
type: 'i18n',
|
||||
'zh-CN': '插槽输入',
|
||||
'en-US': 'Slot Setter',
|
||||
},
|
||||
condition: (field: any) => {
|
||||
return isJSSlot(field.getValue());
|
||||
},
|
||||
initialValue: (field: any, value: any) => {
|
||||
if (isJSSlot(value)) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
type: 'JSSlot',
|
||||
value,
|
||||
};
|
||||
},
|
||||
recommend: true,
|
||||
});
|
||||
registerSetter('MixedSetter', MixedSetter);
|
||||
|
||||
// parseFunc
|
||||
registerMetadataTransducer(parseJSFunc, 1, 'parse-func');
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user