Merge branch 'feat/done-v2' into 'release/0.9.35'

Feat/done v2



See merge request !1049746
This commit is contained in:
力皓 2020-11-18 10:07:12 +08:00
commit 017a1dd48f
34 changed files with 256 additions and 181 deletions

View File

@ -17,7 +17,9 @@
"@alifd/next": "var window.Next",
"@ali/visualengine": "var window.VisualEngine",
"@ali/visualengine-utils": "var window.VisualEngineUtils",
"rax": "var window.Rax"
"rax": "var window.Rax",
"monaco-editor/esm/vs/editor/editor.api":"var window.monaco",
"monaco-editor/esm/vs/editor/editor.main.js":"var window.monaco"
},
"plugins": [
[

View File

@ -1,5 +1,4 @@
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = ({ context, onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
@ -8,19 +7,6 @@ module.exports = ({ context, onGetWebpackConfig }) => {
configFile: './tsconfig.json',
},
]);
config
// 定义插件名称
.plugin('MonacoWebpackPlugin')
// 第一项为具体插件,第二项为插件参数
.use(
new MonacoWebpackPlugin({
languages: ['typescript', 'css', 'json'],
features: ['!gotoSymbol'],
}),
[],
);
config.plugins.delete('hot');
config.devServer.hot(false);
if (context.command === 'start') {

View File

@ -53,7 +53,6 @@
"build-plugin-fusion": "^0.1.0",
"build-plugin-moment-locales": "^0.1.0",
"build-plugin-react-app": "^1.1.2",
"monaco-editor-webpack-plugin": "^1.9.0",
"tsconfig-paths-webpack-plugin": "^3.2.0"
}
}

View File

@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width" />
<title>LowCodeEngine Editor DEMO</title>
<link rel="shortcut icon" href="./favicon.png" />
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.0/min/vs/editor/editor.main.css"/>
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
@ -17,6 +18,12 @@
<link rel="stylesheet" href="https://unpkg.alibaba-inc.com/@alifd/next@1.20.25/dist/next.min.css" />
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.20.25/dist/next.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rax@1.1.3/dist/rax.js"></script>
<script>
var require = { paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.0/min/vs' } };
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.0/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.0/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.0/min/vs/editor/editor.main.js"></script>
<link rel="stylesheet" href="/css/editor-preset-vision.css" />
<script>
window.pageConfig = {

View File

@ -122,6 +122,11 @@ export class InsertionView extends Component<{ host: BuiltinSimulatorHost }> {
if (!loc) {
return null;
}
// 如果是个绝对定位容器,不需要渲染插入标记
if (loc.target.componentMeta.getMetadata().experimental?.isAbsoluteLayoutContainer) {
return null;
}
const { scale, scrollX, scrollY } = host.viewport;
const { edge, insertType, coverRect, nearRect, vertical } = processDetail(loc);

View File

@ -1,5 +1,5 @@
import { obx, autorun, computed, getPublicPath, hotkey, focusTracker } from '@ali/lowcode-editor-core';
import { ISimulatorHost, Component, NodeInstance, ComponentInstance } from '../simulator';
import { ISimulatorHost, Component, NodeInstance, ComponentInstance, DropContainer } from '../simulator';
import Viewport from './viewport';
import { createSimulator } from './create-simulator';
import { Node, ParentalNode, isNode, contains, isRootNode } from '../document';
@ -975,12 +975,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
event: e,
};
// if (e.dragObject.type === 'node' && e.dragObject.nodes[0]?.getPrototype()?.isModal()) {
if (
e.dragObject &&
e.dragObject.nodes &&
e.dragObject.nodes.length &&
e.dragObject.nodes[0].getPrototype()?.isModal()
e.dragObject.nodes[0].componentMeta.isModal
) {
return this.designer.createLocation({
target: document.rootNode,
@ -1086,7 +1085,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
*
*/
getDropContainer(e: LocateEvent): DropContainer | LocationData | null {
getDropContainer(e: LocateEvent): DropContainer | null {
const { target, dragObject } = e;
const isAny = isDragAnyObject(dragObject);
const document = this.project.currentDocument!;
@ -1157,9 +1156,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
let upward: DropContainer | null = null;
while (container) {
res = this.handleAccept(dropContainer, e);
if (isLocationData(res)) {
return res;
}
// if (isLocationData(res)) {
// return res;
// }
if (res === true) {
return dropContainer;
}
@ -1215,7 +1214,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
*
*/
handleAccept({ container, instance }: DropContainer, e: LocateEvent) {
handleAccept({ container, instance }: DropContainer, e: LocateEvent): boolean {
const { dragObject } = e;
const document = this.currentDocument!;
if (isRootNode(container)) {
@ -1393,8 +1392,3 @@ function getMatched(elements: Array<Element | Text>, selector: string): Element
}
return firstQueried;
}
interface DropContainer {
container: ParentalNode;
instance: ComponentInstance;
}

View File

@ -22,7 +22,7 @@
fill: var(--color-icon-white, @title-bgcolor);
}
}
&-current {
.instance-node-selector-current {
background: var(--color-brand, @brand-color-1);
padding: 0 6px;
display: flex;
@ -37,14 +37,14 @@
color: var(--color-icon-white, @title-bgcolor);
}
}
&-list {
.instance-node-selector-list {
position: absolute;
left: 0;
right: 0;
opacity: 0;
visibility: hidden;
}
&-node {
.instance-node-selector-node {
margin: 2px 0;
&-content {
padding-left: 6px;
@ -68,15 +68,15 @@
opacity: 0.8;
}
}
}
&:hover {
.instance-node-selector-current {
color: ar(--color-text-reverse, @white-alpha-2);
}
.instance-node-selector-popup {
visibility: visible;
opacity: 1;
transition: 0.2s all ease-in;
&:hover {
.instance-node-selector-current {
color: ar(--color-text-reverse, @white-alpha-2);
}
.instance-node-selector-popup {
visibility: visible;
opacity: 1;
transition: 0.2s all ease-in;
}
}
}

View File

@ -13,7 +13,7 @@ import {
FieldConfig,
} from '@ali/lowcode-types';
import { computed } from '@ali/lowcode-editor-core';
import { Node, ParentalNode } from './document';
import { isNode, Node, ParentalNode } from './document';
import { Designer } from './designer';
import { intlNode } from './locale';
import { IconContainer } from './icons/container';
@ -264,6 +264,9 @@ export class ComponentMeta {
checkNestingDown(my: Node, target: Node | NodeSchema) {
// 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器
if (this.childWhitelist) {
if (!isNode(target)) {
target = new Node(my.document, target);
}
return this.childWhitelist(target, my);
}
return true;

View File

@ -9,6 +9,7 @@ import {
CompositeObject,
PropsList,
isNodeSchema,
NodeSchema,
} from '@ali/lowcode-types';
import { Project } from '../project';
import { Node, DocumentModel, insertChildren, isRootNode, ParentalNode, TransformStage } from '../document';
@ -294,7 +295,7 @@ export class Designer {
/**
*
*/
getSuitableInsertion(): { target: ParentalNode; index?: number } | null {
getSuitableInsertion(insertNode?: Node | NodeSchema): { target: ParentalNode; index?: number } | null {
const activedDoc = this.project.currentDocument;
if (!activedDoc) {
return null;
@ -306,7 +307,7 @@ export class Designer {
target = activedDoc.rootNode;
} else {
const node = nodes[0];
if (isRootNode(node)) {
if (isRootNode(node) || node.componentMeta.isContainer) {
target = node;
} else {
// FIXME!!, parent maybe null
@ -314,6 +315,11 @@ export class Designer {
index = node.index + 1;
}
}
if (target && insertNode && !target.componentMeta.checkNestingDown(target, insertNode)) {
return null;
}
return { target, index };
}
@ -464,7 +470,7 @@ export class Designer {
const view = metaData.experimental?.view;
if (view) {
maps[key] = view;
} else if (config.npm) {
} else {
maps[key] = config.npm;
}
}

View File

@ -2,6 +2,7 @@ import { Component } from 'react';
import { observer, obx, Title } from '@ali/lowcode-editor-core';
import { Designer } from '../designer';
import { DragObject, isDragNodeObject, isDragNodeDataObject } from '../dragon';
import { isSimulatorHost } from '../../simulator';
import './ghost.less';
type offBinding = () => any;
@ -16,6 +17,8 @@ export default class DragGhost extends Component<{ designer: Designer }> {
@obx.ref private y = 0;
@obx private isAbsoluteLayoutContainer = false;
private dragon = this.props.designer.dragon;
constructor(props: any) {
@ -32,6 +35,14 @@ export default class DragGhost extends Component<{ designer: Designer }> {
this.dragon.onDrag(e => {
this.x = e.globalX;
this.y = e.globalY;
if (isSimulatorHost(e.sensor)) {
const container = e.sensor.getDropContainer(e);
if (container.container.componentMeta.getMetadata().experimental?.isAbsoluteLayoutContainer) {
this.isAbsoluteLayoutContainer = true;
return;
}
}
this.isAbsoluteLayoutContainer = false;
}),
this.dragon.onDragend(() => {
this.dragObject = null;
@ -84,6 +95,10 @@ export default class DragGhost extends Component<{ designer: Designer }> {
return null;
}
if (this.isAbsoluteLayoutContainer) {
return null;
}
return (
<div
className="lc-ghost-group"

View File

@ -4,8 +4,7 @@ import { DocumentModel } from '../document-model';
function getModalNodes(node: Node) {
let nodes: any = [];
const prototype = node.getPrototype();
if (prototype && prototype.isModal()) {
if (node.componentMeta.isModal) {
nodes.push(node);
}
const children = node.getChildren();
@ -85,8 +84,7 @@ export class ModalNodesManager {
}
private addNode(node: Node) {
const prototype = node.getPrototype();
if (prototype && prototype.isModal()) {
if (node.componentMeta.isModal) {
this.hideModalNodes();
this.modalNodes.push(node);
this.addNodeEvent(node);
@ -96,8 +94,7 @@ export class ModalNodesManager {
}
private removeNode(node: Node) {
const prototype = node.getPrototype();
if (prototype && prototype.isModal()) {
if (node.componentMeta.isModal) {
const index = this.modalNodes.indexOf(node);
if (index >= 0) {
this.modalNodes.splice(index, 1);

View File

@ -1,7 +1,7 @@
import { Component as ReactComponent, ComponentType } from 'react';
import { ComponentMetadata, NodeSchema } from '@ali/lowcode-types';
import { ISensor, Point, ScrollTarget, IScrollable } from './designer';
import { Node } from './document';
import { ISensor, Point, ScrollTarget, IScrollable, LocateEvent, LocationData } from './designer';
import { Node, ParentalNode } from './document';
export type AutoFit = '100%';
export const AutoFit = '100%';
@ -60,6 +60,11 @@ export interface IViewport extends IScrollable {
toGlobalPoint(point: Point): Point;
}
export interface DropContainer {
container: ParentalNode;
instance: ComponentInstance;
}
/**
*
*/
@ -143,6 +148,8 @@ export interface ISimulatorHost<P = object> extends ISensor {
findDOMNodes(instance: ComponentInstance, selector?: string): Array<Element | Text> | null;
getDropContainer(e: LocateEvent): DropContainer | null;
/**
*
*/

View File

@ -10,7 +10,11 @@
"react": "var window.React",
"react-dom": "var window.ReactDOM",
"prop-types": "var window.PropTypes",
"rax": "var window.Rax"
"@ali/visualengine": "var window.VisualEngine",
"@ali/visualengine-utils": "var window.VisualEngineUtils",
"rax": "var window.Rax",
"monaco-editor/esm/vs/editor/editor.api":"var window.monaco",
"monaco-editor/esm/vs/editor/editor.main.js":"var window.monaco"
}
}
],

View File

@ -16,6 +16,8 @@
},
"license": "MIT",
"dependencies": {
"@ali/lowcode-editor-setters": "^0.13.1-11",
"@ali/lowcode-utils": "^0.13.1-11",
"@ali/lowcode-designer": "^0.13.1-11",
"@ali/lowcode-editor-core": "^0.13.1-11",
"@ali/lowcode-editor-skeleton": "^0.13.1-11",

View File

@ -16,6 +16,7 @@ import {
upgradePropConfig,
upgradeConfigure,
} from './upgrade-metadata';
import { accessLibrary } from '@ali/lowcode-utils';
import { designer } from '../editor';
@ -166,15 +167,6 @@ export interface OldGlobalPropConfig extends OldPropConfig {
const packageMaps: any = {};
function accessLibrary(library: string | object) {
if (typeof library !== 'string') {
return library;
}
// TODO: enhance logic
return (window as any)[library];
}
export function setPackages(packages: Array<{ package: string; library: object | string }>) {
packages.forEach((item) => {
let lib: any;

View File

@ -136,6 +136,7 @@ export interface OldPrototypeConfig {
};
isContainer?: boolean; // => configure.component.isContainer
isAbsoluteLayoutContainer?: boolean; // => meta.experimental.isAbsoluteLayoutContainer 是否是绝对定位容器
isModal?: boolean; // => configure.component.isModal
isFloating?: boolean; // => configure.component.isFloating
descriptor?: string; // => configure.component.descriptor
@ -592,6 +593,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
configure,
transducers,
isContainer,
isAbsoluteLayoutContainer,
rectSelector,
isModal,
isFloating,
@ -678,7 +680,9 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
component.nestingRule = nestingRule;
// 未考虑清楚的,放在实验性段落
const experimental: any = {};
const experimental: any = {
isAbsoluteLayoutContainer,
};
if (context) {
// for prototype.getContextInfo
experimental.context = context;

View File

@ -27,8 +27,8 @@ import DragEngine from './drag-engine';
// import Flags from './base/flags';
import Viewport from './viewport';
import Project from './project';
import Symbols from './symbols';
import '@ali/lowcode-editor-setters';
import './vision.less';

View File

@ -103,9 +103,9 @@ html.engine-blur #engine {
height: 16px!important;
}
.lc-left-float-pane {
font-size: 14px;
}
// .lc-left-float-pane {
// font-size: 14px;
// }
html.engine-preview-mode {
.lc-left-area, .lc-right-area {
@ -125,4 +125,4 @@ html.engine-preview-mode {
.lc-setter-mixed {
flex: 1
}
}

View File

@ -17,7 +17,6 @@
"@ali/iceluna-comp-expression": "^1.0.6",
"@ali/iceluna-comp-form": "^1.0.20",
"@ali/iceluna-comp-list": "^1.0.26",
"@ali/iceluna-comp-monaco-editor": "^1.0.31",
"@ali/iceluna-comp-object-button": "^1.0.23",
"@ali/iceluna-comp-react-node": "^1.0.5",
"@ali/iceluna-sdk": "^1.0.5-beta.24",
@ -27,11 +26,11 @@
"acorn": "^6.4.1",
"classnames": "^2.2.6",
"intl-messageformat": "^9.3.1",
"monaco-editor": "^0.20.0",
"js-beautify": "^1.13.0",
"qs": "^6.9.1",
"react": "^16",
"react-dom": "^16.7.0",
"react-monaco-editor": "^0.34.0"
"react-monaco-editor": "0.40.0"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.18",

View File

@ -0,0 +1,90 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Select } from '@alife/next';
interface Color {
rgb: any;
onChange: () => void;
}
export interface PluginProps {
value: string;
onChange: any;
}
export default class ClassNameView extends PureComponent<PluginProps> {
static display = 'ClassName';
static propTypes = {
onChange: PropTypes.func,
value: PropTypes.string,
};
static defaultProps = {
onChange: () => {},
value: '',
};
getClassNameList = () => {
const { editor } = this.props.field;
const schema = editor.get('designer').project.getSchema();
const css = schema.componentsTree[0].css;
const classNameList = [];
const re = /\.?\w+[^{]+\{[^}]*\}/g;
const list = css.match(re);
list.map((item) => {
if (item[0] === '.') {
const className = item.substring(1, item.indexOf('{'));
classNameList.push(className);
}
return item;
});
return classNameList;
};
handleChange = (value) => {
const { onChange } = this.props;
onChange(value.join(' '));
this.setState({
selectValue: value,
});
};
// eslint-disable-next-line react/no-deprecated
componentWillMount() {
const { value } = this.props;
const classnameList = this.getClassNameList();
const dataSource = [];
classnameList.map((item) => {
dataSource.push({
value: item,
label: item,
});
return item;
});
let selectValue = [];
if (value && value !== '') {
selectValue = value.split(' ');
}
this.setState({
dataSource,
selectValue,
});
}
render() {
const { dataSource, selectValue } = this.state;
return (
<Select aria-label="tag mode" mode="tag" dataSource={dataSource} onChange={this.handleChange} value={selectValue} />
);
}
}

View File

@ -68,13 +68,12 @@ export default class ExpressionView extends PureComponent {
return val;
}
constructor(props: Readonly<{}>) {
constructor(props: any) {
super(props);
this.expression = React.createRef();
this.i18n = generateI18n(props.locale, props.messages);
this.state = {
value: ExpressionView.getInitValue(props.value),
context: props.context || {},
dataSource: props.dataSource || [],
};
}
@ -126,31 +125,15 @@ export default class ExpressionView extends PureComponent {
* @param {String}
* @return {Array}
*/
getDataSource(tempStr: string): any[] {
const {editor} = this.props.field;
getDataSource(): any[] {
const { editor } = this.props.field;
const schema = editor.get('designer').project.getSchema();
const stateMap = schema.componentsTree[0].state;
let dataSource = [];
const dataSource = [];
for (let key in stateMap){
for (const key in stateMap) {
dataSource.push(`this.state.${key}`);
}
// if (/[^\w\.]$/.test(tempStr)) {
// return [];
// } else if (tempStr === null || tempStr === '') {
// return this.getContextKeys([]);
// } else if (/\w\.$/.test(tempStr)) {
// const currentField = this.getCurrentFiled(tempStr);
// if (!currentField) return null;
// let tempKeys = this.getObjectKeys(currentField.str);
// tempKeys = this.getContextKeys(tempKeys);
// if (!tempKeys) return null;
// return tempKeys;
// } else if (/\.$/.test(tempStr)) {
// return [];
// } else {
// return null;
// }
return dataSource;
}
@ -283,11 +266,12 @@ export default class ExpressionView extends PureComponent {
innerBefore={<span style={{ color: '#999', marginLeft: 4 }}>{'{{'}</span>}
innerAfter={<span style={{ color: '#999', marginRight: 4 }}>{'}}'}</span>}
popupClassName="expression-setter-item-inner"
itemRender={({ itemValue }) => {
// eslint-disable-next-line no-shadow
itemRender={({ value }) => {
return (
<Option key={itemValue} text={itemValue} value={itemValue}>
<div className="code-input-value">{itemValue}</div>
<div className="code-input-help">{helpMap[itemValue]}</div>
<Option key={value} text={value} value={value}>
<div className="code-input-value">{value}</div>
<div className="code-input-help">{helpMap[value]}</div>
</Option>
);
}}

View File

@ -9,6 +9,7 @@ import EventsSetter from './events-setter';
import StyleSetter from './style-setter';
import IconSetter from './icon-setter';
import FunctionSetter from './function-setter';
import ClassNameSetter from './classname-setter';
// import MixedSetter from './mixed-setter';
export const StringSetter = {
@ -87,7 +88,7 @@ const VariableSetter = {
component: ExpressionSetter,
condition: (field: any) => {
const v = field.getValue();
return v == null || isJSExpression(v);
return isJSExpression(v);
},
defaultProps: { placeholder: '请输入表达式' },
title: '表达式输入',
@ -123,6 +124,7 @@ const builtinSetters: any = {
JsonSetter,
StyleSetter,
IconSetter,
ClassNameSetter,
FunctionSetter: FunctionBindSetter,
};

View File

@ -463,30 +463,30 @@ class MonacoEditorDefaultView extends PureComponent {
});
}
}
const prefix = 'data:text/javascript;charset=utf-8,';
const baseUrl = 'https://g.alicdn.com/iceluna/iceluna-vendor/0.0.1/';
window.MonacoEnvironment = {
getWorkerUrl(label: string) {
if (label === 'json') {
return `${prefix}${encodeURIComponent(`
importScripts('${baseUrl}json.worker.js');`)}`;
}
if (['css', 'less', 'scss'].includes(label)) {
return `${prefix}${encodeURIComponent(`
importScripts('${baseUrl}css.worker.js');`)}`;
}
if (label === 'html') {
return `${prefix}${encodeURIComponent(`
importScripts('${baseUrl}html.worker.js');`)}`;
}
if (['typescript', 'javascript'].includes(label)) {
return `${prefix}${encodeURIComponent(`
importScripts('${baseUrl}typescript.worker.js');`)}`;
}
return `${prefix}${encodeURIComponent(`
importScripts('${baseUrl}editor.worker.js');`)}`;
},
};
// const prefix = 'data:text/javascript;charset=utf-8,';
// const baseUrl = 'https://g.alicdn.com/iceluna/iceluna-vendor/0.0.1/';
// window.MonacoEnvironment = {
// getWorkerUrl(label: string) {
// if (label === 'json') {
// return `${prefix}${encodeURIComponent(`
// importScripts('${baseUrl}json.worker.js');`)}`;
// }
// if (['css', 'less', 'scss'].includes(label)) {
// return `${prefix}${encodeURIComponent(`
// importScripts('${baseUrl}css.worker.js');`)}`;
// }
// if (label === 'html') {
// return `${prefix}${encodeURIComponent(`
// importScripts('${baseUrl}html.worker.js');`)}`;
// }
// if (['typescript', 'javascript'].includes(label)) {
// return `${prefix}${encodeURIComponent(`
// importScripts('${baseUrl}typescript.worker.js');`)}`;
// }
// return `${prefix}${encodeURIComponent(`
// importScripts('${baseUrl}editor.worker.js');`)}`;
// },
// };
// eslint-disable-next-line react/no-multi-comp
export default class MonacoEditorButtonView extends PureComponent {

View File

@ -41,10 +41,11 @@
.skeleton-stagebox-stage-arrow {
position: absolute;
left: 3px;
left: 8px;
top: 50%;
transform: translateY(-50%) rotate(90deg);
opacity: 0.6;
width: 12px;
}
.skeleton-stagebox-stage-title {
font-weight: bold;
@ -57,7 +58,7 @@
}
.skeleton-stagebox-stage-exit {
position: absolute;
right: 3px;
right: 8px;
top: 50%;
transform: translateY(-50%);
opacity: 0.6;

View File

@ -16,8 +16,8 @@
--right-area-width: 300px;
--top-area-height: 48px;
--toolbar-height: 36px;
--dock-pane-width: 280px;
--dock-fixed-pane-width: 280px;
--dock-pane-width: 300px;
--dock-fixed-pane-width: 300px;
}
@media (min-width: 1860px) {

View File

@ -26,6 +26,10 @@ export class Workbench extends Component<{ skeleton: Skeleton; config?: EditorCo
return false;
}
// componentDidCatch(error: any) {
// globalContext.get(Editor).emit('editor.skeleton.workbench.error', error);
// }
render() {
const { skeleton, className, topAreaItemClassName } = this.props;
return (

View File

@ -158,8 +158,8 @@ export class OutlineMain implements ISensor, ITreeBoard, IScrollable {
const irect = this.getInsertionRect();
const originLoc = document.dropLocation;
const prop = e.dragObject.nodes ? e.dragObject.nodes[0].getPrototype() : null;
if (e.dragObject.type === 'node' && prop && prop.isModal()) {
const componentMeta = e.dragObject.nodes ? e.dragObject.nodes[0].componentMeta : null;
if (e.dragObject.type === 'node' && componentMeta && componentMeta.isModal) {
return designer.createLocation({
target: document.rootNode,
detail: {

View File

@ -29,7 +29,7 @@ class ModalTreeNodeView extends Component<{ treeNode: TreeNode }> {
render() {
const { treeNode } = this.props;
const modalNodes = treeNode.children?.filter((item) => {
return item.node.getPrototype()?.isModal();
return item.node.componentMeta.isModal;
});
if (!modalNodes || modalNodes.length === 0) {
return null;

View File

@ -72,7 +72,7 @@ class TreeNodeChildren extends Component<{
/>
);
treeNode.children?.forEach((child, index) => {
const childIsModal = child.node.getPrototype()?.isModal() || false;
const childIsModal = child.node.componentMeta.isModal || false;
if (isModal != childIsModal) {
return;
}

View File

@ -151,18 +151,18 @@ class Renderer extends Component<{
viewProps._leaf = leaf;
viewProps._componentName = leaf?.componentName;
// 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动
// if (
// !viewProps.dataSource &&
// leaf?.isContainer() &&
// (children == null || (Array.isArray(children) && !children.length)) &&
// (!viewProps.style || Object.keys(viewProps.style).length === 0)
// ) {
// children = (
// <div className="lc-container-placeholder" style={viewProps.placeholderStyle}>
// {viewProps.placeholder || '拖拽组件或模板到这里'}
// </div>
// );
// }
if (
!viewProps.dataSource &&
leaf?.isContainer() &&
(children == null || (Array.isArray(children) && !children.length)) &&
(!viewProps.style || Object.keys(viewProps.style).length === 0)
) {
children = (
<div className="lc-container-placeholder" style={viewProps.placeholderStyle}>
{viewProps.placeholder || '拖拽组件或模板到这里'}
</div>
);
}
if (viewProps._componentName === 'a') {
delete viewProps.href;
}
@ -189,7 +189,7 @@ class Renderer extends Component<{
return createElement(
getDeviceView(Component, device, designMode),
viewProps,
leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : null,
leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children,
);
}}
onCompGetRef={(schema: any, ref: ReactInstance | null) => {

View File

@ -54,35 +54,16 @@ html.engine-cursor-ew-resize, html.engine-cursor-ew-resize * {
}
.lc-container-placeholder {
height: 44px;
line-height: 44px;
background-color: #f0f0f0;
border-color: #a7b1bd;
min-height: 60px;
height: 100%;
width: 100%;
background-color: rgb(240, 240, 240);
border: 1px dotted;
color: #a7b1bd;
text-align: center;
}
.engine-empty {
background: #f2f3f5;
color: #a7b1bd;
outline: 1px dashed rgba(31, 56, 88, 0.2);
outline-offset: -1px !important;
height: 66px;
max-height: 100%;
min-width: 140px;
text-align: center;
overflow: hidden;
color: rgb(167, 177, 189);
display: flex;
align-items: center;
}
.engine-empty:before {
content: '\62D6\62FD\7EC4\4EF6\6216\6A21\677F\5230\8FD9\91CC';
justify-content: center;
font-size: 14px;
z-index: 1;
width: 100%;
white-space: nowrap;
}
body.engine-document {
@ -93,16 +74,6 @@ body.engine-document {
&:after {
clear: both;
}
/*
.next-input-group,
.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,
.next-number-picker,.next-radio-group,.next-range,.next-range-picker,
.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,
.next-year-picker,
.next-breadcrumb-item,.next-calendar-header,.next-calendar-table {
pointer-events: none !important;
}*/
}
.engine-live-editing {

View File

@ -509,7 +509,7 @@ class ComponentCreator extends React.Component<{ schema: any; propsMap: any, com
constructor(props: any) {
super(props);
const componentMeta = host.currentDocument?.getComponentMeta(props.schema.componentName);
if (componentMeta?.prototype?.isModal()) {
if (componentMeta?.isModal) {
this.isModal = true;
}
}

View File

@ -65,6 +65,7 @@ export interface Experimental {
autoruns?: AutorunItem[];
callbacks?: Callbacks;
initialChildren?: NodeData[] | ((target: SettingTarget) => NodeData[]);
isAbsoluteLayoutContainer: boolean;
// 样式 及 位置handle上必须有明确的标识以便事件路由判断或者主动设置事件独占模式
// NWSE 是交给引擎计算放置位置ReactElement 必须自己控制初始位置

View File

@ -9,7 +9,7 @@ interface LibraryMap {
[key: string]: string;
}
function accessLibrary(library: string | Record<string, unknown>) {
export function accessLibrary(library: string | Record<string, unknown>) {
if (typeof library !== 'string') {
return library;
}