mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-16 15:01:15 +00:00
joint editor & designer
This commit is contained in:
parent
fa1062ace9
commit
901e06ac01
@ -45,7 +45,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-device-legao {
|
&-device-default {
|
||||||
top: 15px;
|
top: 15px;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
bottom: 15px;
|
bottom: 15px;
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
@computed get device(): string | undefined {
|
@computed get device(): string | undefined {
|
||||||
// 根据 device 不同来做画布外框样式变化 渲染时可选择不同组件
|
// 根据 device 不同来做画布外框样式变化 渲染时可选择不同组件
|
||||||
// renderer 依赖
|
// renderer 依赖
|
||||||
return this.get('device');
|
return this.get('device') || 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get deviceClassName(): string | undefined {
|
@computed get deviceClassName(): string | undefined {
|
||||||
|
|||||||
@ -86,7 +86,7 @@ function npmToURI(npm: {
|
|||||||
main?: string;
|
main?: string;
|
||||||
version: string;
|
version: string;
|
||||||
}): string {
|
}): string {
|
||||||
let pkg = [];
|
const pkg = [];
|
||||||
if (npm.package) {
|
if (npm.package) {
|
||||||
pkg.push(npm.package);
|
pkg.push(npm.package);
|
||||||
}
|
}
|
||||||
@ -143,14 +143,17 @@ export class ComponentType {
|
|||||||
}
|
}
|
||||||
private _configure?: Configure;
|
private _configure?: Configure;
|
||||||
get configure() {
|
get configure() {
|
||||||
return [{
|
return [
|
||||||
|
{
|
||||||
name: '#props',
|
name: '#props',
|
||||||
title: "属性",
|
title: '属性',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
name: 'label',
|
name: 'label',
|
||||||
title: '标签',
|
title: '标签',
|
||||||
setter: 'StringSetter'
|
setter: 'StringSetter',
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
title: '名称',
|
title: '名称',
|
||||||
setter: {
|
setter: {
|
||||||
@ -158,48 +161,73 @@ export class ComponentType {
|
|||||||
props: {
|
props: {
|
||||||
itemConfig: {
|
itemConfig: {
|
||||||
setter: 'StringSetter',
|
setter: 'StringSetter',
|
||||||
defaultValue: ''
|
defaultValue: '',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
title: '大小',
|
title: '大小',
|
||||||
setter: 'StringSetter'
|
setter: 'StringSetter',
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'age',
|
name: 'age',
|
||||||
title: '年龄',
|
title: '年龄',
|
||||||
setter: 'NumberSetter'
|
setter: 'NumberSetter',
|
||||||
}]
|
},
|
||||||
}, {
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
name: '#styles',
|
name: '#styles',
|
||||||
title: "样式",
|
title: '样式',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
name: 'className',
|
name: 'className',
|
||||||
title: '类名绑定',
|
title: '类名绑定',
|
||||||
setter: 'ClassNameSetter'
|
setter: 'ClassNameSetter',
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'className2',
|
name: 'className2',
|
||||||
title: '类名绑定',
|
title: '类名绑定',
|
||||||
setter: 'StringSetter'
|
setter: 'StringSetter',
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: '#inlineStyles',
|
name: '#inlineStyles',
|
||||||
title: '行内样式',
|
title: '行内样式',
|
||||||
items: []
|
items: [],
|
||||||
}]
|
},
|
||||||
}, {
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
name: '#events',
|
name: '#events',
|
||||||
title: "事件",
|
title: '事件',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
name: '!events',
|
name: '!events',
|
||||||
title: '事件绑定',
|
title: '事件绑定',
|
||||||
setter: 'EventsSetter'
|
setter: {
|
||||||
}]
|
componentName: 'EventsSetter',
|
||||||
}, {
|
},
|
||||||
|
extraProps: {
|
||||||
|
getValue(field: any) {
|
||||||
|
console.info('lifeCycles', field.getExtraPropValue('lifeCycles'));
|
||||||
|
return field.getPropValue('xxx');
|
||||||
|
},
|
||||||
|
setValue(field: any, val: any) {
|
||||||
|
field.setExtraPropValue('lifeCycles', val);
|
||||||
|
field.setPropValue('xxx', val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
name: '#data',
|
name: '#data',
|
||||||
title: "数据",
|
title: '数据',
|
||||||
items: []
|
items: [],
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private parentWhitelist?: string[] | null;
|
private parentWhitelist?: string[] | null;
|
||||||
|
|||||||
@ -17,9 +17,9 @@ import Props from './props/props';
|
|||||||
* meta
|
* meta
|
||||||
* state
|
* state
|
||||||
* defaultProps
|
* defaultProps
|
||||||
|
* dataSource
|
||||||
* lifeCycles
|
* lifeCycles
|
||||||
* methods
|
* methods
|
||||||
* dataSource
|
|
||||||
* css
|
* css
|
||||||
*
|
*
|
||||||
* [Directives **not used**]
|
* [Directives **not used**]
|
||||||
@ -42,16 +42,16 @@ export default class RootNode extends Node implements NodeParent {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
get nextSibling() {
|
get nextSibling() {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
get prevSibling() {
|
get prevSibling() {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
get zLevel() {
|
get zLevel() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
get parent() {
|
get parent() {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
get children(): NodeChildren {
|
get children(): NodeChildren {
|
||||||
return this._children as NodeChildren;
|
return this._children as NodeChildren;
|
||||||
@ -59,7 +59,9 @@ export default class RootNode extends Node implements NodeParent {
|
|||||||
get props(): Props {
|
get props(): Props {
|
||||||
return this._props as any;
|
return this._props as any;
|
||||||
}
|
}
|
||||||
internalSetParent(parent: null) {}
|
internalSetParent(parent: null) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
constructor(readonly document: DocumentModel, rootSchema: RootSchema) {
|
constructor(readonly document: DocumentModel, rootSchema: RootSchema) {
|
||||||
super(document, rootSchema);
|
super(document, rootSchema);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import logo from '../plugins/logo';
|
import logo from '../plugins/logo';
|
||||||
import designer from '../plugins/designer';
|
import Designer from '../plugins/designer';
|
||||||
import undoRedo from '../plugins/undoRedo';
|
import undoRedo from '../plugins/undoRedo';
|
||||||
|
import Settings from '../../../plugin-settings';
|
||||||
import topBalloonIcon from '@ali/iceluna-addon-2';
|
import topBalloonIcon from '@ali/iceluna-addon-2';
|
||||||
import topDialogIcon from '@ali/iceluna-addon-2';
|
import topDialogIcon from '@ali/iceluna-addon-2';
|
||||||
import leftPanelIcon from '@ali/iceluna-addon-2';
|
import leftPanelIcon from '@ali/iceluna-addon-2';
|
||||||
@ -16,7 +17,8 @@ import PluginFactory from '../framework/pluginFactory';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
logo: PluginFactory(logo),
|
logo: PluginFactory(logo),
|
||||||
designer: PluginFactory(designer),
|
designer: PluginFactory(Designer),
|
||||||
|
settings: PluginFactory(Settings),
|
||||||
undoRedo: PluginFactory(undoRedo),
|
undoRedo: PluginFactory(undoRedo),
|
||||||
topBalloonIcon: PluginFactory(topBalloonIcon),
|
topBalloonIcon: PluginFactory(topBalloonIcon),
|
||||||
topDialogIcon: PluginFactory(topDialogIcon),
|
topDialogIcon: PluginFactory(topDialogIcon),
|
||||||
|
|||||||
16
packages/editor/src/config/setters.ts
Normal file
16
packages/editor/src/config/setters.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Input } from '@alifd/next';
|
||||||
|
import NumberSetter from '../../../plugin-setters/number-setter';
|
||||||
|
import { registerSetter } from '../../../plugin-settings/src';
|
||||||
|
import { createElement } from 'react';
|
||||||
|
|
||||||
|
registerSetter('ClassNameSetter', () => {
|
||||||
|
return createElement('div', {
|
||||||
|
className: 'lc-block-setter'
|
||||||
|
}, '这里是类名绑定');
|
||||||
|
});
|
||||||
|
|
||||||
|
registerSetter('EventsSetter', Input);
|
||||||
|
|
||||||
|
registerSetter('StringSetter', { component: Input, props: { placeholder: "请输入" } });
|
||||||
|
|
||||||
|
registerSetter('NumberSetter', NumberSetter as any);
|
||||||
@ -204,54 +204,14 @@ export default {
|
|||||||
],
|
],
|
||||||
rightArea: [
|
rightArea: [
|
||||||
{
|
{
|
||||||
pluginKey: 'rightPanel1',
|
pluginKey: 'settings',
|
||||||
type: 'Panel',
|
type: 'Panel',
|
||||||
props: {
|
props: {},
|
||||||
title: '样式'
|
|
||||||
},
|
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/iceluna-addon-2',
|
|
||||||
version: '^1.0.0'
|
version: '^1.0.0'
|
||||||
},
|
},
|
||||||
pluginProps: {}
|
pluginProps: {}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
pluginKey: 'rightPanel2',
|
|
||||||
type: 'Panel',
|
|
||||||
props: {
|
|
||||||
title: '属性',
|
|
||||||
icon: 'dengpao'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
package: '@ali/iceluna-addon-2',
|
|
||||||
version: '^1.0.0'
|
|
||||||
},
|
|
||||||
pluginProps: {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pluginKey: 'rightPanel3',
|
|
||||||
type: 'Panel',
|
|
||||||
props: {
|
|
||||||
title: '事件'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
package: '@ali/iceluna-addon-2',
|
|
||||||
version: '^1.0.0'
|
|
||||||
},
|
|
||||||
pluginProps: {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pluginKey: 'rightPanel4',
|
|
||||||
type: 'Panel',
|
|
||||||
props: {
|
|
||||||
title: '数据'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
package: '@ali/iceluna-addon-2',
|
|
||||||
version: '^1.0.0'
|
|
||||||
},
|
|
||||||
pluginProps: {}
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
centerArea: [{
|
centerArea: [{
|
||||||
pluginKey: 'designer',
|
pluginKey: 'designer',
|
||||||
|
|||||||
@ -112,7 +112,10 @@ export interface Utils {
|
|||||||
[propName: string]: (...args) => any;
|
[propName: string]: (...args) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginClass extends React.Component {
|
export interface PluginClass extends React.ComponentClass<{
|
||||||
|
editor: Editor;
|
||||||
|
[key: string]: any
|
||||||
|
}> {
|
||||||
init?: (editor: Editor) => void;
|
init?: (editor: Editor) => void;
|
||||||
open?: () => any;
|
open?: () => any;
|
||||||
close?: () => any;
|
close?: () => any;
|
||||||
|
|||||||
@ -7,13 +7,14 @@ import config from './config/skeleton';
|
|||||||
import components from './config/components';
|
import components from './config/components';
|
||||||
import utils from './config/utils';
|
import utils from './config/utils';
|
||||||
import constants from './config/constants';
|
import constants from './config/constants';
|
||||||
import messages from './config/locale';
|
import './config/locale';
|
||||||
|
import './config/setters';
|
||||||
|
|
||||||
import pkg from '../package.json';
|
import pkg from '../package.json';
|
||||||
import './global.scss';
|
import './global.scss';
|
||||||
import './config/theme.scss';
|
import './config/theme.scss';
|
||||||
|
|
||||||
window.__pkg = pkg;
|
(window as any).__pkg = pkg;
|
||||||
|
|
||||||
const ICE_CONTAINER = document.getElementById('ice-container');
|
const ICE_CONTAINER = document.getElementById('ice-container');
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
.lowcode-plugin-designer {
|
.lowcode-plugin-designer {
|
||||||
background-color: #ffffff;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@ -172,8 +172,8 @@ export default class DesignerPlugin extends PureComponent<PluginProps> {
|
|||||||
render() {
|
render() {
|
||||||
const { editor } = this.props;
|
const { editor } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="lowcode-plugin-designer">
|
|
||||||
<Designer
|
<Designer
|
||||||
|
className="lowcode-plugin-designer"
|
||||||
defaultSchema={SCHEMA as any}
|
defaultSchema={SCHEMA as any}
|
||||||
eventPipe={editor as any}
|
eventPipe={editor as any}
|
||||||
simulatorProps={{
|
simulatorProps={{
|
||||||
@ -190,11 +190,9 @@ export default class DesignerPlugin extends PureComponent<PluginProps> {
|
|||||||
id: 'next',
|
id: 'next',
|
||||||
level: 2
|
level: 2
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
// simulatorUrl: ['/statics/simulator-renderer.css', '/statics/simulator-renderer.js']
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,13 +20,12 @@ body {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #d8d8d8;
|
background-color: rgba(31, 56, 88, 0.06);
|
||||||
}
|
}
|
||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
padding: 12px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,6 +128,18 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
if (visiblePluginList.length < 2) {
|
||||||
|
const pane = visiblePluginList[0];
|
||||||
|
if (!pane) {
|
||||||
|
return <div className="lowcode-right-area"></div>;
|
||||||
|
}
|
||||||
|
const Comp = this.editor.components[pane.pluginKey];
|
||||||
|
return (
|
||||||
|
<div className="lowcode-right-area">
|
||||||
|
<Comp editor={this.editor} config={pane} {...pane.pluginProps} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="lowcode-right-area">
|
<div className="lowcode-right-area">
|
||||||
<Tab
|
<Tab
|
||||||
|
|||||||
@ -66,7 +66,6 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
|
|||||||
this.editor.destroy();
|
this.editor.destroy();
|
||||||
}
|
}
|
||||||
const { utils, config, components } = this.props;
|
const { utils, config, components } = this.props;
|
||||||
debugger;
|
|
||||||
const editor = (this.editor = new Editor(comboEditorConfig(defaultConfig, config), components, {
|
const editor = (this.editor = new Editor(comboEditorConfig(defaultConfig, config), components, {
|
||||||
...skeletonUtils,
|
...skeletonUtils,
|
||||||
...utils
|
...utils
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-settings-pane",
|
"name": "@ali/lowcode-plugin-settings",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"description": "xxx for Ali lowCode engine",
|
"description": "xxx for Ali lowCode engine",
|
||||||
"main": "src/index.tsx",
|
"main": "src/index.tsx",
|
||||||
@ -10,20 +10,20 @@ interface ArraySetterState {
|
|||||||
itemsMap: Map<string | number, SettingField>;
|
itemsMap: Map<string | number, SettingField>;
|
||||||
prevLength: number;
|
prevLength: number;
|
||||||
}
|
}
|
||||||
export class ListSetter extends Component<
|
|
||||||
{
|
interface ArraySetterProps {
|
||||||
value: any[];
|
value: any[];
|
||||||
field: SettingField;
|
field: SettingField;
|
||||||
itemConfig?: {
|
itemConfig?: {
|
||||||
setter?: SetterType;
|
setter?: SetterType;
|
||||||
defaultValue?: any | ((field: SettingField, editor: any) => any);
|
defaultValue?: any | ((field: SettingField) => any);
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
};
|
};
|
||||||
multiValue?: boolean;
|
multiValue?: boolean;
|
||||||
},
|
}
|
||||||
ArraySetterState
|
|
||||||
> {
|
export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
|
||||||
static getDerivedStateFromProps(props: any, state: ArraySetterState) {
|
static getDerivedStateFromProps(props: ArraySetterProps, state: ArraySetterState) {
|
||||||
const { value, field } = props;
|
const { value, field } = props;
|
||||||
const newLength = value && Array.isArray(value) ? value.length : 0;
|
const newLength = value && Array.isArray(value) ? value.length : 0;
|
||||||
if (state && state.prevLength === newLength) {
|
if (state && state.prevLength === newLength) {
|
||||||
@ -63,6 +63,12 @@ export class ListSetter extends Component<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state: ArraySetterState = {
|
||||||
|
items: [],
|
||||||
|
itemsMap: new Map<string | number, SettingField>(),
|
||||||
|
prevLength: 0,
|
||||||
|
};
|
||||||
|
|
||||||
onSort(sortedIds: Array<string | number>) {
|
onSort(sortedIds: Array<string | number>) {
|
||||||
const { itemsMap } = this.state;
|
const { itemsMap } = this.state;
|
||||||
const items = sortedIds.map((id, index) => {
|
const items = sortedIds.map((id, index) => {
|
||||||
@ -87,7 +93,7 @@ export class ListSetter extends Component<
|
|||||||
});
|
});
|
||||||
items.push(item);
|
items.push(item);
|
||||||
itemsMap.set(item.id, item);
|
itemsMap.set(item.id, item);
|
||||||
item.setValue(typeof defaultValue === 'function' ? defaultValue(item, item.editor) : defaultValue);
|
item.setValue(typeof defaultValue === 'function' ? defaultValue(item) : defaultValue);
|
||||||
this.scrollToLast = true;
|
this.scrollToLast = true;
|
||||||
this.setState({
|
this.setState({
|
||||||
items: items.slice(),
|
items: items.slice(),
|
||||||
@ -202,17 +208,14 @@ class ArrayItem extends Component<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TableSetter extends ListSetter {
|
class TableSetter extends ListSetter {}
|
||||||
|
|
||||||
}
|
export default class ArraySetter extends Component<{
|
||||||
|
|
||||||
export default class ArraySetter extends Component<
|
|
||||||
{
|
|
||||||
value: any[];
|
value: any[];
|
||||||
field: SettingField;
|
field: SettingField;
|
||||||
itemConfig?: {
|
itemConfig?: {
|
||||||
setter?: SetterType;
|
setter?: SetterType;
|
||||||
defaultValue?: any | ((field: SettingField, editor: any) => any);
|
defaultValue?: any | ((field: SettingField) => any);
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
};
|
};
|
||||||
mode?: 'popup' | 'list' | 'table';
|
mode?: 'popup' | 'list' | 'table';
|
||||||
@ -3,7 +3,7 @@ import { Tab, Breadcrumb, Icon } from '@alifd/next';
|
|||||||
import { SettingsMain, SettingField, isSettingField } from './main';
|
import { SettingsMain, SettingField, isSettingField } from './main';
|
||||||
import './style.less';
|
import './style.less';
|
||||||
import Title from './title';
|
import Title from './title';
|
||||||
import SettingsTab, { registerSetter, createSetterContent, getSetter, createSettingFieldView } from './settings-pane';
|
import SettingsPane, { registerSetter, createSetterContent, getSetter, createSettingFieldView } from './settings-pane';
|
||||||
import Node from '../../designer/src/designer/document/node/node';
|
import Node from '../../designer/src/designer/document/node/node';
|
||||||
import ArraySetter from './builtin-setters/array-setter';
|
import ArraySetter from './builtin-setters/array-setter';
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ export default class SettingsMainView extends Component {
|
|||||||
onMouseOut: hoverNode.bind(null, node, false),
|
onMouseOut: hoverNode.bind(null, node, false),
|
||||||
onClick: selectNode.bind(null, node),
|
onClick: selectNode.bind(null, node),
|
||||||
};
|
};
|
||||||
items.unshift(<Breadcrumb.Item {...props}>{node.title}</Breadcrumb.Item>);
|
items.unshift(<Breadcrumb.Item {...props} key={node.id}>{node.title}</Breadcrumb.Item>);
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ export default class SettingsMainView extends Component {
|
|||||||
<div className="lc-settings-main">
|
<div className="lc-settings-main">
|
||||||
{this.renderBreadcrumb()}
|
{this.renderBreadcrumb()}
|
||||||
<div className="lc-settings-body">
|
<div className="lc-settings-body">
|
||||||
<SettingsTab target={this.main} />
|
<SettingsPane target={this.main} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -107,7 +107,7 @@ export default class SettingsMainView extends Component {
|
|||||||
>
|
>
|
||||||
{(items as SettingField[]).map(field => (
|
{(items as SettingField[]).map(field => (
|
||||||
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
|
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
|
||||||
<SettingsTab target={field} key={field.id} />
|
<SettingsPane target={field} key={field.id} />
|
||||||
</Tab.Item>
|
</Tab.Item>
|
||||||
))}
|
))}
|
||||||
</Tab>
|
</Tab>
|
||||||
@ -45,9 +45,9 @@ export interface SettingTarget {
|
|||||||
|
|
||||||
readonly path: string[];
|
readonly path: string[];
|
||||||
|
|
||||||
/**
|
readonly top: SettingTarget;
|
||||||
* 响应式自动运行
|
|
||||||
*/
|
// 响应式自动运行
|
||||||
onEffect(action: () => void): () => void;
|
onEffect(action: () => void): () => void;
|
||||||
|
|
||||||
// 获取属性值
|
// 获取属性值
|
||||||
@ -56,6 +56,12 @@ export interface SettingTarget {
|
|||||||
// 设置属性值
|
// 设置属性值
|
||||||
setPropValue(propName: string | number, value: any): void;
|
setPropValue(propName: string | number, value: any): void;
|
||||||
|
|
||||||
|
// 获取附属属性值
|
||||||
|
getExtraPropValue(propName: string): any;
|
||||||
|
|
||||||
|
// 设置附属属性值
|
||||||
|
setExtraPropValue(propName: string, value: any): void;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// 所有属性值数据
|
// 所有属性值数据
|
||||||
readonly props: object;
|
readonly props: object;
|
||||||
@ -74,7 +80,7 @@ export function isCustomView(obj: any): obj is CustomView {
|
|||||||
return obj && (isValidElement(obj) || isReactComponent(obj));
|
return obj && (isValidElement(obj) || isReactComponent(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DynamicProps = (field: SettingField, editor: any) => object;
|
export type DynamicProps = (field: SettingField) => object;
|
||||||
|
|
||||||
export interface SetterConfig {
|
export interface SetterConfig {
|
||||||
/**
|
/**
|
||||||
@ -102,13 +108,13 @@ export interface FieldExtraProps {
|
|||||||
* default value of target prop for setter use
|
* default value of target prop for setter use
|
||||||
*/
|
*/
|
||||||
defaultValue?: any;
|
defaultValue?: any;
|
||||||
onChange?: (val: any, field: SettingField, editor: any) => void;
|
getValue?: (field: SettingField, fieldValue: any) => any;
|
||||||
getValue?: (field: SettingField, editor: any) => any;
|
setValue?: (field: SettingField, value: any) => void;
|
||||||
/**
|
/**
|
||||||
* the field conditional show, is not set always true
|
* the field conditional show, is not set always true
|
||||||
* @default undefined
|
* @default undefined
|
||||||
*/
|
*/
|
||||||
condition?: (field: SettingField, editor: any) => boolean;
|
condition?: (field: SettingField) => boolean;
|
||||||
/**
|
/**
|
||||||
* default collapsed when display accordion
|
* default collapsed when display accordion
|
||||||
*/
|
*/
|
||||||
@ -168,6 +174,7 @@ export class SettingField implements SettingTarget {
|
|||||||
readonly nodes: Node[];
|
readonly nodes: Node[];
|
||||||
readonly componentType: ComponentType | null;
|
readonly componentType: ComponentType | null;
|
||||||
readonly designer: Designer;
|
readonly designer: Designer;
|
||||||
|
readonly top: SettingTarget;
|
||||||
get path() {
|
get path() {
|
||||||
const path = this.parent.path.slice();
|
const path = this.parent.path.slice();
|
||||||
if (this.type === 'field') {
|
if (this.type === 'field') {
|
||||||
@ -210,6 +217,7 @@ export class SettingField implements SettingTarget {
|
|||||||
this.isOne = parent.isOne;
|
this.isOne = parent.isOne;
|
||||||
this.isNone = parent.isNone;
|
this.isNone = parent.isNone;
|
||||||
this.designer = parent.designer!;
|
this.designer = parent.designer!;
|
||||||
|
this.top = parent.top;
|
||||||
|
|
||||||
// initial items
|
// initial items
|
||||||
if (this.type === 'group' && items) {
|
if (this.type === 'group' && items) {
|
||||||
@ -277,27 +285,26 @@ export class SettingField implements SettingTarget {
|
|||||||
* 获取当前属性值
|
* 获取当前属性值
|
||||||
*/
|
*/
|
||||||
getValue(): any {
|
getValue(): any {
|
||||||
if (this.type !== 'field') {
|
let val: any = null;
|
||||||
return null;
|
if (this.type === 'field') {
|
||||||
|
val = this.parent.getPropValue(this.name);
|
||||||
}
|
}
|
||||||
// todo: use getValue
|
|
||||||
const { getValue } = this.extraProps;
|
const { getValue } = this.extraProps;
|
||||||
if (getValue) {
|
return getValue ? getValue(this, val) : val;
|
||||||
return getValue(this, this.editor);
|
|
||||||
}
|
|
||||||
return this.parent.getPropValue(this.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置当前属性值
|
* 设置当前属性值
|
||||||
*/
|
*/
|
||||||
setValue(val: any) {
|
setValue(val: any) {
|
||||||
if (this.type !== 'field') {
|
if (this.type === 'field') {
|
||||||
return;
|
|
||||||
}
|
|
||||||
// todo: use onChange
|
|
||||||
this.parent.setPropValue(this.name, val);
|
this.parent.setPropValue(this.name, val);
|
||||||
}
|
}
|
||||||
|
const { setValue } = this.extraProps;
|
||||||
|
if (setValue) {
|
||||||
|
setValue(this, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setKey(key: string | number) {
|
setKey(key: string | number) {
|
||||||
if (this.type !== 'field') {
|
if (this.type !== 'field') {
|
||||||
@ -338,6 +345,14 @@ export class SettingField implements SettingTarget {
|
|||||||
return this.parent.getPropValue(path);
|
return this.parent.getPropValue(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getExtraPropValue(propName: string) {
|
||||||
|
return this.top.getExtraPropValue(propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
setExtraPropValue(propName: string, value: any) {
|
||||||
|
this.top.setExtraPropValue(propName, value);
|
||||||
|
}
|
||||||
|
|
||||||
purge() {
|
purge() {
|
||||||
this.disposeItems();
|
this.disposeItems();
|
||||||
}
|
}
|
||||||
@ -356,6 +371,7 @@ export class SettingsMain implements SettingTarget {
|
|||||||
private _componentType: ComponentType | null = null;
|
private _componentType: ComponentType | null = null;
|
||||||
private _isSame: boolean = true;
|
private _isSame: boolean = true;
|
||||||
readonly path = [];
|
readonly path = [];
|
||||||
|
readonly top: SettingTarget = this;
|
||||||
|
|
||||||
get nodes(): Node[] {
|
get nodes(): Node[] {
|
||||||
return this._nodes;
|
return this._nodes;
|
||||||
@ -433,6 +449,9 @@ export class SettingsMain implements SettingTarget {
|
|||||||
* 获取属性值
|
* 获取属性值
|
||||||
*/
|
*/
|
||||||
getPropValue(propName: string): any {
|
getPropValue(propName: string): any {
|
||||||
|
if (this.nodes.length < 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return this.nodes[0].getProp(propName, false)?.value;
|
return this.nodes[0].getProp(propName, false)?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +464,19 @@ export class SettingsMain implements SettingTarget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getExtraPropValue(propName: string) {
|
||||||
|
if (this.nodes.length < 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.nodes[0].getExtraProp(propName, false)?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setExtraPropValue(propName: string, value: any) {
|
||||||
|
this.nodes.forEach(node => {
|
||||||
|
node.getExtraProp(propName, true)?.setValue(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 设置多个属性值,替换原有值
|
// 设置多个属性值,替换原有值
|
||||||
setProps(data: object) {
|
setProps(data: object) {
|
||||||
this.nodes.forEach(node => {
|
this.nodes.forEach(node => {
|
||||||
@ -11,14 +11,22 @@ import {
|
|||||||
DynamicProps,
|
DynamicProps,
|
||||||
} from './main';
|
} from './main';
|
||||||
import { Field, FieldGroup } from './field';
|
import { Field, FieldGroup } from './field';
|
||||||
|
import { TitleContent } from './title';
|
||||||
|
|
||||||
export type RegisteredSetter = CustomView | {
|
export type RegisteredSetter = {
|
||||||
component: CustomView;
|
component: CustomView;
|
||||||
props?: object;
|
defaultProps?: object;
|
||||||
|
title?: TitleContent;
|
||||||
};
|
};
|
||||||
|
|
||||||
const settersMap = new Map<string, RegisteredSetter>();
|
const settersMap = new Map<string, RegisteredSetter>();
|
||||||
export function registerSetter(type: string, setter: RegisteredSetter) {
|
export function registerSetter(type: string, setter: CustomView | RegisteredSetter) {
|
||||||
|
if (isCustomView(setter)) {
|
||||||
|
setter = {
|
||||||
|
component: setter,
|
||||||
|
title: (setter as any).displayName || (setter as any).name || 'CustomSetter'
|
||||||
|
};
|
||||||
|
}
|
||||||
settersMap.set(type, setter);
|
settersMap.set(type, setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,16 +37,17 @@ export function getSetter(type: string): RegisteredSetter | null {
|
|||||||
export function createSetterContent(setter: any, props: object): ReactNode {
|
export function createSetterContent(setter: any, props: object): ReactNode {
|
||||||
if (typeof setter === 'string') {
|
if (typeof setter === 'string') {
|
||||||
setter = getSetter(setter);
|
setter = getSetter(setter);
|
||||||
if (!isCustomView(setter)) {
|
if (!setter) {
|
||||||
if (setter.props) {
|
return null;
|
||||||
|
}
|
||||||
|
if (setter.defaultProps) {
|
||||||
props = {
|
props = {
|
||||||
...setter.props,
|
...setter.defaultProps,
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
setter = setter.component;
|
setter = setter.component;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return createContent(setter, props);
|
return createContent(setter, props);
|
||||||
}
|
}
|
||||||
@ -71,12 +80,12 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
|||||||
let firstRun: boolean = true;
|
let firstRun: boolean = true;
|
||||||
this.dispose = field.onEffect(() => {
|
this.dispose = field.onEffect(() => {
|
||||||
const state: any = {};
|
const state: any = {};
|
||||||
const { extraProps, editor } = field;
|
const { extraProps } = field;
|
||||||
const { condition, defaultValue } = extraProps;
|
const { condition, defaultValue } = extraProps;
|
||||||
state.visible = field.isOne && typeof condition === 'function' ? !condition(field, editor) : true;
|
state.visible = field.isOne && typeof condition === 'function' ? !condition(field) : true;
|
||||||
if (state.visible) {
|
if (state.visible) {
|
||||||
state.setterProps = {
|
state.setterProps = {
|
||||||
...(typeof setterProps === 'function' ? setterProps(field, editor) : setterProps),
|
...(typeof setterProps === 'function' ? setterProps(field) : setterProps),
|
||||||
};
|
};
|
||||||
if (field.type === 'field') {
|
if (field.type === 'field') {
|
||||||
if (defaultValue != null && !('defaultValue' in state.setterProps)) {
|
if (defaultValue != null && !('defaultValue' in state.setterProps)) {
|
||||||
@ -136,7 +145,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
|||||||
forceInline: extraProps.forceInline,
|
forceInline: extraProps.forceInline,
|
||||||
key: field.id,
|
key: field.id,
|
||||||
// === injection
|
// === injection
|
||||||
prop: field,
|
prop: field, // for compatible
|
||||||
field,
|
field,
|
||||||
// === IO
|
// === IO
|
||||||
value, // reaction point
|
value, // reaction point
|
||||||
@ -165,7 +174,7 @@ class SettingGroupView extends Component<{ field: SettingField }> {
|
|||||||
let firstRun: boolean = true;
|
let firstRun: boolean = true;
|
||||||
this.dispose = field.onEffect(() => {
|
this.dispose = field.onEffect(() => {
|
||||||
const state: any = {};
|
const state: any = {};
|
||||||
state.visible = field.isOne && typeof condition === 'function' ? !condition(field, field.editor) : true;
|
state.visible = field.isOne && typeof condition === 'function' ? !condition(field) : true;
|
||||||
if (state.visible) {
|
if (state.visible) {
|
||||||
state.items = field.items.slice();
|
state.items = field.items.slice();
|
||||||
}
|
}
|
||||||
@ -216,7 +225,7 @@ export function createSettingFieldView(item: SettingField | CustomView, field: S
|
|||||||
return <SettingFieldView field={item} key={item.id} />;
|
return <SettingFieldView field={item} key={item.id} />;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return createContent(item, { key: index, field, editor: field.editor });
|
return createContent(item, { key: index, field });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
.lc-settings-main {
|
.lc-settings-main {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.lc-settings-notice {
|
.lc-settings-notice {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -64,6 +65,9 @@
|
|||||||
&:not(:last-child):hover {
|
&:not(:last-child):hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.next-breadcrumb-text {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user