build: change build-scripts to vite

This commit is contained in:
1ncounter 2024-03-27 10:39:41 +08:00
parent 50465d6499
commit 17f736b130
146 changed files with 2026 additions and 1695 deletions

View File

@ -4,7 +4,10 @@
"mainEntryPointFilePath": "<projectFolder>/temp/index.d.ts", "mainEntryPointFilePath": "<projectFolder>/temp/index.d.ts",
"compiler": { "compiler": {
"tsconfigFilePath": "<projectFolder>/tsconfig.declaration.json" "tsconfigFilePath": "<projectFolder>/tsconfig.declaration.json",
"overrideTsconfig": {
"baseUrl": "<projectFolder>/temp"
}
}, },
"dtsRollup": { "dtsRollup": {

View File

@ -1 +0,0 @@
module.exports = require('../../babel.config');

View File

@ -1,5 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce"
]
}

View File

@ -1,9 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce",
"@alilc/lowcode-test-mate/plugin/index.ts"
],
"babelPlugins": [
["@babel/plugin-proposal-private-property-in-object", { "loose": true }]
]
}

View File

@ -1,54 +0,0 @@
const fs = require('fs');
const { join } = require('path');
const esModules = [].join('|');
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
const jestConfig = {
// transform: {
// '^.+\\.[jt]sx?$': 'babel-jest',
// // '^.+\\.(ts|tsx)$': 'ts-jest',
// // '^.+\\.(js|jsx)$': 'babel-jest',
// },
// testMatch: ['**/node-children.test.ts'],
// testMatch: ['**/plugin-manager.test.ts'],
// testMatch: ['**/history/history.test.ts'],
// testMatch: ['**/document-model.test.ts'],
// testMatch: ['**/prop.test.ts'],
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
// testMatch: ['**/document/node/node.add.test.ts'],
// testMatch: ['**/setting-field.test.ts'],
// testMatch: ['**/node.test.ts'],
// testMatch: ['**/builtin-hotkey.test.ts'],
// testMatch: ['**/selection.test.ts'],
// testMatch: ['**/plugin/sequencify.test.ts'],
// testMatch: ['**/builtin-simulator/utils/parse-metadata.test.ts'],
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],
setupFiles: ['./tests/fixtures/unhandled-rejection.ts'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
collectCoverage: false,
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/icons/**',
'!src/locale/**',
'!src/builtin-simulator/utils/**',
'!src/plugin/sequencify.ts',
'!src/document/node/exclusive-group.ts',
'!src/document/node/props/value-to-source.ts',
'!src/builtin-simulator/live-editing/live-editing.ts',
'!src/designer/offset-observer.ts',
'!src/designer/clipboard.ts',
'!src/designer/scroller.ts',
'!src/builtin-simulator/host.ts',
'!**/node_modules/**',
'!**/vendor/**',
],
};
// 只对本仓库内的 pkg 做 mapping
jestConfig.moduleNameMapper = {};
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
module.exports = jestConfig;

View File

@ -2,47 +2,56 @@
"name": "@alilc/lowcode-designer", "name": "@alilc/lowcode-designer",
"version": "2.0.0-beta.0", "version": "2.0.0-beta.0",
"description": "Designer for Ali LowCode Engine", "description": "Designer for Ali LowCode Engine",
"main": "lib/index.js", "type": "module",
"module": "es/index.js", "main": "dist/designer.cjs",
"module": "dist/designer.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/designer.js",
"require": "./dist/designer.cjs",
"types": "./dist/index.d.ts"
}
},
"files": [ "files": [
"lib", "dist",
"es" "src",
"package.json"
], ],
"scripts": { "scripts": {
"build": "build-scripts build", "build": "vite build",
"test": "build-scripts test --config build.test.json", "build-dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
"test:cov": "build-scripts test --config build.test.json --jest-coverage" "test": "vitest",
"test:cov": ""
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@alilc/lowcode-editor-core": "1.3.2", "@alilc/lowcode-editor-core": "workspace:*",
"@alilc/lowcode-types": "1.3.2", "@alilc/lowcode-types": "workspace:*",
"@alilc/lowcode-utils": "1.3.2", "@alilc/lowcode-utils": "workspace:*",
"classnames": "^2.2.6", "@alifd/next": "^1.27.8",
"react": "^16", "classnames": "^2.5.1",
"react-dom": "^16.7.0", "lodash-es": "^4.17.20",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ric-shim": "^1.0.1", "ric-shim": "^1.0.1",
"semver": "^7.3.5" "semver": "^7.6.0",
"events": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.29", "@testing-library/react": "^14.2.2",
"@testing-library/react": "^11.2.2", "@types/lodash-es": "^4.14.165",
"@types/classnames": "^2.2.7", "@types/prop-types": "^15.7.12",
"@types/enzyme": "^3.10.12", "@types/react": "^18.2.0",
"@types/enzyme-adapter-react-16": "^1.0.6", "@types/react-dom": "^18.2.0",
"@types/jest": "^26.0.16", "@types/semver": "7.5.8",
"@types/lodash": "^4.14.165", "less": "^4.2.0"
"@types/medium-editor": "^5.0.3", },
"@types/node": "^13.7.1", "peerDependencies": {
"@types/react": "^16", "@alifd/next": "^1.27.8",
"@types/react-dom": "^16", "react": "^18.2.0",
"@types/semver": "7.3.9", "react-dom": "^18.2.0"
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"jest": "^26.6.3",
"lodash": "^4.17.20",
"moment": "^2.29.1",
"typescript": "^4.0.3"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

@ -35,9 +35,7 @@ export class BorderDetectingInstance extends PureComponent<{
return ( return (
<div className={className} style={style}> <div className={className} style={style}>
<Title title={title} className="lc-borders-title" /> <Title title={title} className="lc-borders-title" />
{ {isLocked ? <Title title={intl('locked')} className="lc-borders-status" /> : null}
isLocked ? (<Title title={intl('locked')} className="lc-borders-status" />) : null
}
</div> </div>
); );
} }
@ -77,7 +75,10 @@ export class BorderDetecting extends Component<{ host: BuiltinSimulatorHost }> {
const { current } = this; const { current } = this;
const canHoverHook = current?.componentMeta.advanced.callbacks?.onHoverHook; const canHoverHook = current?.componentMeta.advanced.callbacks?.onHoverHook;
const canHover = (canHoverHook && typeof canHoverHook === 'function') ? canHoverHook(current.internalToShellNode()) : true; const canHover =
canHoverHook && typeof canHoverHook === 'function'
? canHoverHook(current.internalToShellNode()!)
: true;
if (!canHover || !current || host.viewport.scrolling || host.liveEditing.editing) { if (!canHover || !current || host.viewport.scrolling || host.liveEditing.editing) {
return null; return null;
@ -104,7 +105,7 @@ export class BorderDetecting extends Component<{ host: BuiltinSimulatorHost }> {
); );
} }
const lockedNode = getClosestNode(current, (n) => { const lockedNode = getClosestNode(current as any, (n) => {
// 假如当前节点就是 locked 状态,要从当前节点的父节点开始查找 // 假如当前节点就是 locked 状态,要从当前节点的父节点开始查找
return !!(current?.isLocked ? n.parent?.isLocked : n.isLocked); return !!(current?.isLocked ? n.parent?.isLocked : n.isLocked);
}); });
@ -118,7 +119,10 @@ export class BorderDetecting extends Component<{ host: BuiltinSimulatorHost }> {
scrollX={this.scrollX} scrollX={this.scrollX}
scrollY={this.scrollY} scrollY={this.scrollY}
// @ts-ignore // @ts-ignore
rect={host.computeComponentInstanceRect(host.getComponentInstances(lockedNode)[0], lockedNode.componentMeta.rootSelector)} rect={host.computeComponentInstanceRect(
host.getComponentInstances(lockedNode)![0],
lockedNode.componentMeta.rootSelector,
)}
isLocked={lockedNode?.getId() !== current.getId()} isLocked={lockedNode?.getId() !== current.getId()}
/> />
); );

View File

@ -89,7 +89,12 @@ export class BoxResizingForNode extends Component<{ host: BuiltinSimulatorHost;
return null; return null;
} }
return ( return (
<BoxResizingInstance key={observed.id} dragging={this.dragging} designer={designer} observed={observed} /> <BoxResizingInstance
key={observed.id}
dragging={this.dragging}
designer={designer}
observed={observed}
/>
); );
})} })}
</Fragment> </Fragment>
@ -135,41 +140,38 @@ export class BoxResizingInstance extends Component<{
// this.hoveringCapture.setBoundary(this.outline); // this.hoveringCapture.setBoundary(this.outline);
this.willBind(); this.willBind();
const resize = (e: MouseEvent, direction: string, node: INode, moveX: number, moveY: number) => { const resize = (
e: MouseEvent,
direction: string,
node: INode,
moveX: number,
moveY: number,
) => {
const { advanced } = node.componentMeta; const { advanced } = node.componentMeta;
if ( if (advanced.callbacks && typeof advanced.callbacks.onResize === 'function') {
advanced.callbacks &&
typeof advanced.callbacks.onResize === 'function'
) {
(e as any).trigger = direction; (e as any).trigger = direction;
(e as any).deltaX = moveX; (e as any).deltaX = moveX;
(e as any).deltaY = moveY; (e as any).deltaY = moveY;
const cbNode = node?.isNode ? node.internalToShellNode() : node; const cbNode = node?.isNode ? node.internalToShellNode() : node;
advanced.callbacks.onResize(e, cbNode); advanced.callbacks.onResize(e as any, cbNode);
} }
}; };
const resizeStart = (e: MouseEvent, direction: string, node: INode) => { const resizeStart = (e: MouseEvent, direction: string, node: INode) => {
const { advanced } = node.componentMeta; const { advanced } = node.componentMeta;
if ( if (advanced.callbacks && typeof advanced.callbacks.onResizeStart === 'function') {
advanced.callbacks &&
typeof advanced.callbacks.onResizeStart === 'function'
) {
(e as any).trigger = direction; (e as any).trigger = direction;
const cbNode = node?.isNode ? node.internalToShellNode() : node; const cbNode = node?.isNode ? node.internalToShellNode() : node;
advanced.callbacks.onResizeStart(e, cbNode); advanced.callbacks.onResizeStart(e as any, cbNode);
} }
}; };
const resizeEnd = (e: MouseEvent, direction: string, node: INode) => { const resizeEnd = (e: MouseEvent, direction: string, node: INode) => {
const { advanced } = node.componentMeta; const { advanced } = node.componentMeta;
if ( if (advanced.callbacks && typeof advanced.callbacks.onResizeEnd === 'function') {
advanced.callbacks &&
typeof advanced.callbacks.onResizeEnd === 'function'
) {
(e as any).trigger = direction; (e as any).trigger = direction;
const cbNode = node?.isNode ? node.internalToShellNode() : node; const cbNode = node?.isNode ? node.internalToShellNode() : node;
advanced.callbacks.onResizeEnd(e, cbNode); advanced.callbacks.onResizeEnd(e as any, cbNode as any);
} }
const editor = node.document?.designer.editor; const editor = node.document?.designer.editor;
@ -241,14 +243,16 @@ export class BoxResizingInstance extends Component<{
let offsetTop = 0; let offsetTop = 0;
let offsetLeft = 0; let offsetLeft = 0;
if (observed.hasOffset) { if (observed.hasOffset) {
offsetWidth = observed.offsetWidth; offsetWidth = observed.offsetWidth!;
offsetHeight = observed.offsetHeight; offsetHeight = observed.offsetHeight!;
offsetTop = observed.offsetTop; offsetTop = observed.offsetTop;
offsetLeft = observed.offsetLeft; offsetLeft = observed.offsetLeft;
const { node } = observed; const { node } = observed;
const metadata = node.componentMeta.getMetadata(); const metadata = node.componentMeta.getMetadata();
if (metadata.configure?.advanced?.getResizingHandlers) { if (metadata.configure?.advanced?.getResizingHandlers) {
triggerVisible = metadata.configure.advanced.getResizingHandlers(node.internalToShellNode()); triggerVisible = metadata.configure.advanced.getResizingHandlers(
node.internalToShellNode(),
);
} }
} }
triggerVisible = normalizeTriggers(triggerVisible); triggerVisible = normalizeTriggers(triggerVisible);

View File

@ -1,7 +1,6 @@
import { import {
Component, Component,
Fragment, Fragment,
ReactNodeArray,
isValidElement, isValidElement,
cloneElement, cloneElement,
createElement, createElement,
@ -54,11 +53,8 @@ export class BorderSelectingInstance extends Component<{
} }
return ( return (
<div <div className={className} style={style}>
className={className} {!dragging && !hideComponentAction ? <Toolbar observed={observed} /> : null}
style={style}
>
{(!dragging && !hideComponentAction) ? <Toolbar observed={observed} /> : null}
</div> </div>
); );
} }
@ -68,7 +64,7 @@ export class BorderSelectingInstance extends Component<{
class Toolbar extends Component<{ observed: OffsetObserver }> { class Toolbar extends Component<{ observed: OffsetObserver }> {
render() { render() {
const { observed } = this.props; const { observed } = this.props;
const { height, width } = observed.viewport; const { height, width } = observed.viewport!;
const BAR_HEIGHT = 20; const BAR_HEIGHT = 20;
const MARGIN = 1; const MARGIN = 1;
const BORDER = 2; const BORDER = 2;
@ -81,7 +77,7 @@ class Toolbar extends Component<{ observed: OffsetObserver }> {
top: -SPACE_HEIGHT, top: -SPACE_HEIGHT,
height: BAR_HEIGHT, height: BAR_HEIGHT,
}; };
} else if (observed.bottom + SPACE_HEIGHT < height) { } else if (observed.bottom! + SPACE_HEIGHT < height) {
style = { style = {
bottom: -SPACE_HEIGHT, bottom: -SPACE_HEIGHT,
height: BAR_HEIGHT, height: BAR_HEIGHT,
@ -93,21 +89,24 @@ class Toolbar extends Component<{ observed: OffsetObserver }> {
}; };
} }
// 计算 toolbar 的左/右位置 // 计算 toolbar 的左/右位置
if (SPACE_MINIMUM_WIDTH > observed.left + observed.width) { if (SPACE_MINIMUM_WIDTH > observed.left + observed.width!) {
style.left = Math.max(-BORDER, observed.left - width - BORDER); style.left = Math.max(-BORDER, observed.left - width - BORDER);
} else { } else {
style.right = Math.max(-BORDER, observed.right - width - BORDER); style.right = Math.max(-BORDER, observed.right! - width - BORDER);
style.justifyContent = 'flex-start'; style.justifyContent = 'flex-start';
} }
const { node } = observed; const { node } = observed;
const actions: ReactNodeArray = []; const actions: ReactNode[] = [];
node.componentMeta.availableActions.forEach((action) => { node.componentMeta.availableActions.forEach((action) => {
const { important = true, condition, content, name } = action; const { important = true, condition, content, name } = action;
if (node.isSlot() && (name === 'copy' || name === 'remove')) { if (node.isSlot() && (name === 'copy' || name === 'remove')) {
// FIXME: need this? // FIXME: need this?
return; return;
} }
if (important && (typeof condition === 'function' ? condition(node) !== false : condition !== false)) { if (
important &&
(typeof condition === 'function' ? condition(node) !== false : condition !== false)
) {
actions.push(createAction(content, name, node)); actions.push(createAction(content, name, node));
} }
}); });
@ -120,7 +119,11 @@ class Toolbar extends Component<{ observed: OffsetObserver }> {
} }
} }
function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject, key: string, node: INode) { function createAction(
content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject,
key: string,
node: INode,
) {
if (isValidElement<{ key: string; node: INode }>(content)) { if (isValidElement<{ key: string; node: INode }>(content)) {
return cloneElement(content, { key, node }); return cloneElement(content, { key, node });
} }
@ -148,7 +151,7 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
}} }}
> >
{icon && createIcon(icon, { key, node: node.internalToShellNode() })} {icon && createIcon(icon, { key, node: node.internalToShellNode() })}
<Tip>{title}</Tip> <Tip>{title as any}</Tip>
</div> </div>
); );
} }
@ -187,7 +190,13 @@ export class BorderSelectingForNode extends Component<{ host: ISimulatorHost; no
if (!observed) { if (!observed) {
return null; return null;
} }
return <BorderSelectingInstance key={observed.id} dragging={this.dragging} observed={observed} />; return (
<BorderSelectingInstance
key={observed.id}
dragging={this.dragging}
observed={observed}
/>
);
})} })}
</Fragment> </Fragment>
); );

View File

@ -52,7 +52,7 @@ export default class DragResizeEngine {
if (!sourceDocument || sourceDocument === document) { if (!sourceDocument || sourceDocument === document) {
return e; return e;
} }
const srcSim = masterSensors.find(sim => sim.contentDocument === sourceDocument); const srcSim = masterSensors.find((sim) => sim.contentDocument === sourceDocument);
if (srcSim) { if (srcSim) {
return srcSim.viewport.toGlobalPoint(e); return srcSim.viewport.toGlobalPoint(e);
} }
@ -61,7 +61,7 @@ export default class DragResizeEngine {
const over = (e: MouseEvent) => { const over = (e: MouseEvent) => {
const handleEvents = makeEventsHandler(e, masterSensors); const handleEvents = makeEventsHandler(e, masterSensors);
handleEvents(doc => { handleEvents((doc) => {
doc.removeEventListener('mousemove', move, true); doc.removeEventListener('mousemove', move, true);
doc.removeEventListener('mouseup', over, true); doc.removeEventListener('mouseup', over, true);
}); });
@ -77,7 +77,7 @@ export default class DragResizeEngine {
node = boost(e); node = boost(e);
startEvent = createResizeEvent(e); startEvent = createResizeEvent(e);
const handleEvents = makeEventsHandler(e, masterSensors); const handleEvents = makeEventsHandler(e, masterSensors);
handleEvents(doc => { handleEvents((doc) => {
doc.addEventListener('mousemove', move, true); doc.addEventListener('mousemove', move, true);
doc.addEventListener('mouseup', over, true); doc.addEventListener('mouseup', over, true);
}); });
@ -87,9 +87,9 @@ export default class DragResizeEngine {
this.designer.detecting.enable = false; this.designer.detecting.enable = false;
cursor.addState('ew-resize'); cursor.addState('ew-resize');
}; };
shell.addEventListener('mousedown', mousedown); shell.addEventListener('mousedown', mousedown as any);
return () => { return () => {
shell.removeEventListener('mousedown', mousedown); shell.removeEventListener('mousedown', mousedown as any);
}; };
} }
@ -118,7 +118,7 @@ export default class DragResizeEngine {
private getMasterSensors(): ISimulatorHost[] { private getMasterSensors(): ISimulatorHost[] {
return this.designer.project.documents return this.designer.project.documents
.map(doc => { .map((doc) => {
if (doc.active && doc.simulator?.sensorAvailable) { if (doc.active && doc.simulator?.sensorAvailable) {
return doc.simulator; return doc.simulator;
} }

View File

@ -1,14 +1,15 @@
import { Component } from 'react'; import { Component } from 'react';
import { observer } from '@alilc/lowcode-editor-core'; import { observer } from '@alilc/lowcode-editor-core';
import { BuiltinSimulatorHost } from '../host'; import { BuiltinSimulatorHost } from '../host';
import { import { DropLocation, isVertical } from '../../designer';
DropLocation,
isVertical,
} from '../../designer';
import { ISimulatorHost } from '../../simulator'; import { ISimulatorHost } from '../../simulator';
import { INode } from '../../document'; import { INode } from '../../document';
import './insertion.less'; import './insertion.less';
import { IPublicTypeNodeData, IPublicTypeNodeSchema, IPublicTypeLocationChildrenDetail, IPublicTypeRect } from '@alilc/lowcode-types'; import {
IPublicTypeNodeData,
IPublicTypeLocationChildrenDetail,
IPublicTypeRect,
} from '@alilc/lowcode-types';
import { isLocationChildrenDetail } from '@alilc/lowcode-utils'; import { isLocationChildrenDetail } from '@alilc/lowcode-utils';
interface InsertionData { interface InsertionData {
@ -23,7 +24,11 @@ interface InsertionData {
/** /**
* (INode) * (INode)
*/ */
function processChildrenDetail(sim: ISimulatorHost, container: INode, detail: IPublicTypeLocationChildrenDetail): InsertionData { function processChildrenDetail(
sim: ISimulatorHost,
container: INode,
detail: IPublicTypeLocationChildrenDetail,
): InsertionData {
let edge = detail.edge || null; let edge = detail.edge || null;
if (!edge) { if (!edge) {
@ -40,7 +45,7 @@ function processChildrenDetail(sim: ISimulatorHost, container: INode, detail: IP
if (detail.near) { if (detail.near) {
const { node, pos, rect, align } = detail.near; const { node, pos, rect, align } = detail.near;
ret.nearRect = rect || sim.computeRect(node); ret.nearRect = rect || sim.computeRect(node as any);
ret.nearNode = node; ret.nearNode = node;
if (pos === 'replace') { if (pos === 'replace') {
// FIXME: ret.nearRect mybe null // FIXME: ret.nearRect mybe null
@ -65,10 +70,10 @@ function processChildrenDetail(sim: ISimulatorHost, container: INode, detail: IP
ret.insertType = 'cover'; ret.insertType = 'cover';
return ret; return ret;
} }
let nearNode = container.children.get(index); let nearNode = container.children?.get(index);
if (!nearNode) { if (!nearNode) {
// index = 0, eg. nochild, // index = 0, eg. nochild,
nearNode = container.children.get(index > 0 ? index - 1 : 0); nearNode = container.children?.get(index > 0 ? index - 1 : 0);
if (!nearNode) { if (!nearNode) {
ret.insertType = 'cover'; ret.insertType = 'cover';
ret.coverRect = edge; ret.coverRect = edge;
@ -95,7 +100,7 @@ function processChildrenDetail(sim: ISimulatorHost, container: INode, detail: IP
* detail "坐标" * detail "坐标"
*/ */
function processDetail({ target, detail, document }: DropLocation): InsertionData { function processDetail({ target, detail, document }: DropLocation): InsertionData {
const sim = document.simulator; const sim = document!.simulator;
if (!sim) { if (!sim) {
return {}; return {};
} }
@ -126,7 +131,7 @@ export class InsertionView extends Component<{ host: BuiltinSimulatorHost }> {
} }
const { scale, scrollX, scrollY } = host.viewport; const { scale, scrollX, scrollY } = host.viewport;
const { edge, insertType, coverRect, nearRect, vertical, nearNode } = processDetail(loc); const { edge, insertType, coverRect, nearRect, vertical, nearNode } = processDetail(loc as any);
if (!edge) { if (!edge) {
return null; return null;
@ -159,7 +164,7 @@ export class InsertionView extends Component<{ host: BuiltinSimulatorHost }> {
y = ((insertType === 'before' ? nearRect.top : nearRect.bottom) + scrollY) * scale; y = ((insertType === 'before' ? nearRect.top : nearRect.bottom) + scrollY) * scale;
style.width = nearRect.width * scale; style.width = nearRect.width * scale;
} }
if (y === 0 && (nearNode as IPublicTypeNodeSchema)?.componentMeta?.isTopFixed) { if (y === 0 && (nearNode as any)?.componentMeta?.isTopFixed) {
return null; return null;
} }
} }

View File

@ -14,11 +14,7 @@ import {
IEventBus, IEventBus,
} from '@alilc/lowcode-editor-core'; } from '@alilc/lowcode-editor-core';
import { import { ISimulatorHost, Component, DropContainer } from '../simulator';
ISimulatorHost,
Component,
DropContainer,
} from '../simulator';
import Viewport from './viewport'; import Viewport from './viewport';
import { createSimulator } from './create-simulator'; import { createSimulator } from './create-simulator';
import { Node, INode, contains, isRootNode, isLowCodeComponent } from '../document'; import { Node, INode, contains, isRootNode, isLowCodeComponent } from '../document';
@ -71,7 +67,7 @@ import { LiveEditing } from './live-editing/live-editing';
import { IProject, Project } from '../project'; import { IProject, Project } from '../project';
import { IScroller } from '../designer/scroller'; import { IScroller } from '../designer/scroller';
import { isElementNode, isDOMNodeVisible } from '../utils/misc'; import { isElementNode, isDOMNodeVisible } from '../utils/misc';
import { debounce } from 'lodash'; import { debounce } from 'lodash-es';
const logger = new Logger({ level: 'warn', bizName: 'designer' }); const logger = new Logger({ level: 'warn', bizName: 'designer' });
@ -352,24 +348,30 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
*/ */
connect( connect(
renderer: BuiltinSimulatorRenderer, renderer: BuiltinSimulatorRenderer,
effect: (reaction: IReactionPublic) => void, options?: IReactionOptions, effect: (reaction: IReactionPublic) => void,
options?: IReactionOptions<any, boolean>,
) { ) {
this._renderer = renderer; this._renderer = renderer;
return autorun(effect, options); return autorun(effect, options);
} }
reaction(expression: (reaction: IReactionPublic) => unknown, effect: (value: unknown, prev: unknown, reaction: IReactionPublic) => void, reaction(
opts?: IReactionOptions | undefined): IReactionDisposer { expression: (reaction: IReactionPublic) => unknown,
effect: (value: unknown, prev: unknown, reaction: IReactionPublic) => void,
opts?: IReactionOptions<any, boolean> | undefined,
): IReactionDisposer {
return reaction(expression, effect, opts); return reaction(expression, effect, opts);
} }
autorun(effect: (reaction: IReactionPublic) => void, options?: IReactionOptions): IReactionDisposer { autorun(
effect: (reaction: IReactionPublic) => void,
options?: IReactionOptions<any, boolean>,
): IReactionDisposer {
return autorun(effect, options); return autorun(effect, options);
} }
purge(): void { purge(): void {
// todo // todo
} }
mountViewport(viewport: HTMLElement | null) { mountViewport(viewport: HTMLElement | null) {
@ -450,11 +452,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const vendors = [ const vendors = [
// required & use once // required & use once
assetBundle( assetBundle(this.get('environment') || defaultEnvironment, AssetLevel.Environment),
this.get('environment') ||
defaultEnvironment,
AssetLevel.Environment,
),
// required & use once // required & use once
assetBundle(this.get('extraEnvironment'), AssetLevel.Environment), assetBundle(this.get('extraEnvironment'), AssetLevel.Environment),
@ -463,11 +461,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// required & TODO: think of update // required & TODO: think of update
assetBundle(this.theme, AssetLevel.Theme), assetBundle(this.theme, AssetLevel.Theme),
// required & use once // required & use once
assetBundle( assetBundle(this.get('simulatorUrl') || defaultSimulatorUrl, AssetLevel.Runtime),
this.get('simulatorUrl') ||
defaultSimulatorUrl,
AssetLevel.Runtime,
),
]; ];
// wait 准备 iframe 内容、依赖库注入 // wait 准备 iframe 内容、依赖库注入
@ -555,8 +549,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return; return;
} }
// FIXME: dirty fix remove label-for fro liveEditing // FIXME: dirty fix remove label-for fro liveEditing
downEvent.target?.removeAttribute('for'); (downEvent.target as any)?.removeAttribute('for');
const nodeInst = this.getNodeInstanceFromElement(downEvent.target); const nodeInst = this.getNodeInstanceFromElement(downEvent.target as any);
const { focusNode } = documentModel; const { focusNode } = documentModel;
const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent); const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent);
// 如果找不到可点击的节点,直接返回 // 如果找不到可点击的节点,直接返回
@ -572,7 +566,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const isRGLNode = rglNode?.isRGLContainer; const isRGLNode = rglNode?.isRGLContainer;
if (isRGLNode) { if (isRGLNode) {
// 如果拖拽的是磁铁块的右下角 handle则直接跳过 // 如果拖拽的是磁铁块的右下角 handle则直接跳过
if (downEvent.target?.classList.contains('react-resizable-handle')) return; if ((downEvent.target as any)?.classList.contains('react-resizable-handle')) return;
// 禁止多选 // 禁止多选
isMulti = false; isMulti = false;
designer.dragon.emitter.emit('rgl.switch', { designer.dragon.emitter.emit('rgl.switch', {
@ -649,7 +643,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
{ {
type: IPublicEnumDragObjectType.Node, type: IPublicEnumDragObjectType.Node,
nodes, nodes,
}, } as any,
downEvent, downEvent,
isRGLNode ? rglNode : undefined, isRGLNode ? rglNode : undefined,
); );
@ -697,10 +691,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
'.next-calendar-table', '.next-calendar-table',
'.editor-container', // 富文本组件 '.editor-container', // 富文本组件
]; ];
const ignoreSelectors = customizeIgnoreSelectors?.(defaultIgnoreSelectors, e) || defaultIgnoreSelectors; const ignoreSelectors =
customizeIgnoreSelectors?.(defaultIgnoreSelectors, e) || defaultIgnoreSelectors;
const ignoreSelectorsString = ignoreSelectors.join(','); const ignoreSelectorsString = ignoreSelectors.join(',');
// 提供了 customizeIgnoreSelectors 的情况下,忽略 isFormEvent() 判断 // 提供了 customizeIgnoreSelectors 的情况下,忽略 isFormEvent() 判断
if ((!customizeIgnoreSelectors && isFormEvent(e)) || target?.closest(ignoreSelectorsString)) { if (
(!customizeIgnoreSelectors && isFormEvent(e)) ||
(target as any)?.closest(ignoreSelectorsString)
) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -918,7 +916,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* @see ISimulator * @see ISimulator
*/ */
getComponentInstances(node: INode, context?: IPublicTypeNodeInstance): IPublicTypeComponentInstance[] | null { getComponentInstances(
node: INode,
context?: IPublicTypeNodeInstance,
): IPublicTypeComponentInstance[] | null {
const docId = node.document?.id; const docId = node.document?.id;
if (!docId) { if (!docId) {
return null; return null;
@ -966,7 +967,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* @see ISimulator * @see ISimulator
*/ */
computeComponentInstanceRect(instance: IPublicTypeComponentInstance, selector?: string): IPublicTypeRect | null { computeComponentInstanceRect(
instance: IPublicTypeComponentInstance,
selector?: string,
): IPublicTypeRect | null {
const renderer = this.renderer!; const renderer = this.renderer!;
const elements = this.findDOMNodes(instance, selector); const elements = this.findDOMNodes(instance, selector);
if (!elements) { if (!elements) {
@ -1032,7 +1036,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* @see ISimulator * @see ISimulator
*/ */
findDOMNodes(instance: IPublicTypeComponentInstance, selector?: string): Array<Element | Text> | null { findDOMNodes(
instance: IPublicTypeComponentInstance,
selector?: string,
): Array<Element | Text> | null {
const elements = this._renderer?.findDOMNodes(instance); const elements = this._renderer?.findDOMNodes(instance);
if (!elements) { if (!elements) {
return null; return null;
@ -1051,7 +1058,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* DOM simulator * DOM simulator
*/ */
getNodeInstanceFromElement(target: Element | null): IPublicTypeNodeInstance<IPublicTypeComponentInstance, INode> | null { getNodeInstanceFromElement(
target: Element | null,
): IPublicTypeNodeInstance<IPublicTypeComponentInstance, INode> | null {
if (!target) { if (!target) {
return null; return null;
} }
@ -1191,9 +1200,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const nodes = dragObject?.nodes; const nodes = dragObject?.nodes;
const operationalNodes = nodes?.filter((node) => { const operationalNodes = nodes?.filter((node: any) => {
const onMoveHook = node.componentMeta?.advanced.callbacks?.onMoveHook; const onMoveHook = node.componentMeta?.advanced.callbacks?.onMoveHook;
const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook(node.internalToShellNode()) : true; const canMove =
onMoveHook && typeof onMoveHook === 'function'
? onMoveHook(node.internalToShellNode())
: true;
let parentContainerNode: INode | null = null; let parentContainerNode: INode | null = null;
let parentNode = node.parent; let parentNode = node.parent;
@ -1207,9 +1219,16 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
parentNode = parentNode.parent; parentNode = parentNode.parent;
} }
const onChildMoveHook = parentContainerNode?.componentMeta?.advanced.callbacks?.onChildMoveHook; const onChildMoveHook =
parentContainerNode?.componentMeta?.advanced.callbacks?.onChildMoveHook;
const childrenCanMove = onChildMoveHook && parentContainerNode && typeof onChildMoveHook === 'function' ? onChildMoveHook(node.internalToShellNode(), parentContainerNode.internalToShellNode()) : true; const childrenCanMove =
onChildMoveHook && parentContainerNode && typeof onChildMoveHook === 'function'
? onChildMoveHook(
node!.internalToShellNode(),
(parentContainerNode as any).internalToShellNode(),
)
: true;
return canMove && childrenCanMove; return canMove && childrenCanMove;
}); });
@ -1225,16 +1244,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return null; return null;
} }
const dropContainer = this.getDropContainer(e); const dropContainer = this.getDropContainer(e);
const lockedNode = getClosestNode(dropContainer?.container, (node) => node.isLocked); const lockedNode = getClosestNode(dropContainer?.container as any, (node) => node.isLocked);
if (lockedNode) return null; if (lockedNode) return null;
if ( if (!dropContainer) {
!dropContainer
) {
return null; return null;
} }
if (isLocationData(dropContainer)) { if (isLocationData(dropContainer)) {
return this.designer.createLocation(dropContainer); return this.designer.createLocation(dropContainer as any);
} }
const { container, instance: containerInstance } = dropContainer; const { container, instance: containerInstance } = dropContainer;
@ -1267,7 +1284,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
e.dragObject && e.dragObject &&
e.dragObject.nodes && e.dragObject.nodes &&
e.dragObject.nodes.length && e.dragObject.nodes.length &&
e.dragObject.nodes[0].componentMeta.isModal && e.dragObject.nodes[0]?.componentMeta?.isModal &&
document.focusNode document.focusNode
) { ) {
return this.designer.createLocation({ return this.designer.createLocation({
@ -1296,8 +1313,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const inst = instances const inst = instances
? instances.length > 1 ? instances.length > 1
? instances.find( ? instances.find(
(_inst) => this.getClosestNodeInstance(_inst, container.id)?.instance === containerInstance, (_inst) =>
) this.getClosestNodeInstance(_inst, container.id)?.instance === containerInstance,
)
: instances[0] : instances[0]
: null; : null;
const rect = inst const rect = inst
@ -1420,7 +1438,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// get common parent, avoid drop container contains by dragObject // get common parent, avoid drop container contains by dragObject
const drillDownExcludes = new Set<INode>(); const drillDownExcludes = new Set<INode>();
if (isDragNodeObject(dragObject)) { if (isDragNodeObject(dragObject)) {
const { nodes } = dragObject; const { nodes } = dragObject as any;
let i = nodes.length; let i = nodes.length;
let p: any = container; let p: any = container;
while (i-- > 0) { while (i-- > 0) {
@ -1495,14 +1513,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const { dragObject } = e; const { dragObject } = e;
const document = this.currentDocument!; const document = this.currentDocument!;
const { focusNode } = document; const { focusNode } = document;
if (isRootNode(container) || container.contains(focusNode)) { if (isRootNode(container) || container.contains(focusNode!)) {
return document.checkNesting(focusNode!, dragObject as any); return document.checkNesting(focusNode!, dragObject as any);
} }
const meta = (container as Node).componentMeta; const meta = (container as Node).componentMeta;
// FIXME: get containerInstance for accept logic use // FIXME: get containerInstance for accept logic use
const acceptable: boolean = this.isAcceptable(container); const acceptable: boolean = this.isAcceptable();
if (!meta.isContainer && !acceptable) { if (!meta.isContainer && !acceptable) {
return false; return false;
} }
@ -1514,10 +1532,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* *
*/ */
getNearByContainer( getNearByContainer({ container, instance }: DropContainer, drillDownExcludes: Set<INode>) {
{ container, instance }: DropContainer,
drillDownExcludes: Set<INode>,
) {
const { children } = container; const { children } = container;
if (!children || children.isEmpty()) { if (!children || children.isEmpty()) {
return null; return null;

View File

@ -59,21 +59,23 @@ export class LiveEditing {
const editor = node.document?.designer.editor; const editor = node.document?.designer.editor;
const npm = node?.componentMeta?.npm; const npm = node?.componentMeta?.npm;
const selected = const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || node?.componentMeta?.componentName || ''; [npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.eventBus.emit('designer.builtinSimulator.liveEditing', { editor?.eventBus.emit('designer.builtinSimulator.liveEditing', {
selected, selected,
}); });
let setterPropElement = getSetterPropElement(targetElement, rootElement); let setterPropElement = getSetterPropElement(targetElement, rootElement);
let propTarget = setterPropElement?.dataset.setterProp; let propTarget = setterPropElement?.dataset.setterProp;
let matched: (IPublicTypePluginConfig & { propElement?: HTMLElement }) | undefined | null; let matched: (IPublicTypePluginConfig & { propElement?: HTMLElement }) | undefined | null | any;
if (liveTextEditing) { if (liveTextEditing) {
if (propTarget) { if (propTarget) {
// 已埋点命中 data-setter-prop="proptarget", 从 liveTextEditing 读取配置mode|onSaveContent // 已埋点命中 data-setter-prop="proptarget", 从 liveTextEditing 读取配置mode|onSaveContent
matched = liveTextEditing.find(config => config.propTarget == propTarget); matched = liveTextEditing.find((config) => config.propTarget == propTarget);
} else { } else {
// 执行 embedTextEditing selector 规则,获得第一个节点 是否 contains e.target若匹配读取配置 // 执行 embedTextEditing selector 规则,获得第一个节点 是否 contains e.target若匹配读取配置
matched = liveTextEditing.find(config => { matched = liveTextEditing.find((config) => {
if (!config.selector) { if (!config.selector) {
return false; return false;
} }
@ -89,7 +91,8 @@ export class LiveEditing {
}); });
if (matched) { if (matched) {
propTarget = matched.propTarget; propTarget = matched.propTarget;
setterPropElement = matched.propElement || queryPropElement(rootElement, targetElement, matched.selector); setterPropElement =
matched.propElement || queryPropElement(rootElement, targetElement, matched.selector);
} }
} }
@ -117,9 +120,15 @@ export class LiveEditing {
// 4. 监听 blur 事件 // 4. 监听 blur 事件
// 5. 设置编辑锁定disable hover | disable select | disable canvas drag // 5. 设置编辑锁定disable hover | disable select | disable canvas drag
const onSaveContent = matched?.onSaveContent || saveHandlers.find(item => item.condition(prop))?.onSaveContent || defaultSaveContent; const onSaveContent =
matched?.onSaveContent ||
saveHandlers.find((item) => item.condition(prop as any))?.onSaveContent ||
defaultSaveContent;
setterPropElement.setAttribute('contenteditable', matched?.mode && matched.mode !== 'plaintext' ? 'true' : 'plaintext-only'); setterPropElement.setAttribute(
'contenteditable',
matched?.mode && matched.mode !== 'plaintext' ? 'true' : 'plaintext-only',
);
setterPropElement.classList.add('engine-live-editing'); setterPropElement.classList.add('engine-live-editing');
// be sure // be sure
setterPropElement.focus(); setterPropElement.focus();
@ -134,7 +143,7 @@ export class LiveEditing {
switch (e.code) { switch (e.code) {
case 'Enter': case 'Enter':
break; break;
// TODO: check is richtext? // TODO: check is richtext?
case 'Escape': case 'Escape':
break; break;
case 'Tab': case 'Tab':
@ -157,7 +166,7 @@ export class LiveEditing {
setterPropElement!.removeEventListener('keydown', keydown, true); setterPropElement!.removeEventListener('keydown', keydown, true);
}; };
this._editing = prop; this._editing = prop as any;
} }
// TODO: process enter | esc events & joint the FocusTracker // TODO: process enter | esc events & joint the FocusTracker
@ -186,9 +195,11 @@ export class LiveEditing {
} }
} }
export type SpecificRule = (target: EditingTarget) => (IPublicTypeLiveTextEditingConfig & { export type SpecificRule = (target: EditingTarget) =>
propElement?: HTMLElement; | (IPublicTypeLiveTextEditingConfig & {
}) | null; propElement?: HTMLElement;
})
| null;
export interface SaveHandler { export interface SaveHandler {
condition: (prop: Prop) => boolean; condition: (prop: Prop) => boolean;
@ -223,7 +234,9 @@ function queryPropElement(rootElement: HTMLElement, targetElement: HTMLElement,
} }
if (!propElement.contains(targetElement)) { if (!propElement.contains(targetElement)) {
// try selectorAll // try selectorAll
propElement = Array.from(rootElement.querySelectorAll(selector)).find(item => item.contains(targetElement)) as HTMLElement; propElement = Array.from(rootElement.querySelectorAll(selector)).find((item) =>
item.contains(targetElement),
) as HTMLElement;
if (!propElement) { if (!propElement) {
return null; return null;
} }

View File

@ -2,10 +2,9 @@ import { Overlay } from '@alifd/next';
import React, { MouseEvent } from 'react'; import React, { MouseEvent } from 'react';
import { Title, observer } from '@alilc/lowcode-editor-core'; import { Title, observer } from '@alilc/lowcode-editor-core';
import { canClickNode } from '@alilc/lowcode-utils'; import { canClickNode } from '@alilc/lowcode-utils';
import { INode } from '../../document';
import './index.less'; import './index.less';
import { INode } from '@alilc/lowcode-designer';
const { Popup } = Overlay; const { Popup } = Overlay;
export interface IProps { export interface IProps {
@ -80,17 +79,21 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
} }
}; };
onMouseOver = (node: INode) => (_: any, flag = true) => { onMouseOver =
if (node && typeof node.hover === 'function') { (node: INode) =>
node.hover(flag); (_: any, flag = true) => {
} if (node && typeof node.hover === 'function') {
}; node.hover(flag);
}
};
onMouseOut = (node: INode) => (_: any, flag = false) => { onMouseOut =
if (node && typeof node.hover === 'function') { (node: INode) =>
node.hover(flag); (_: any, flag = false) => {
} if (node && typeof node.hover === 'function') {
}; node.hover(flag);
}
};
renderNodes = () => { renderNodes = () => {
const nodes = this.state.parentNodes; const nodes = this.state.parentNodes;

View File

@ -10,12 +10,12 @@ export const getClosestClickableNode = (
currentNode: INode | undefined | null, currentNode: INode | undefined | null,
event: MouseEvent, event: MouseEvent,
) => { ) => {
let node = currentNode; let node = currentNode as any;
while (node) { while (node) {
// 判断当前节点是否可点击 // 判断当前节点是否可点击
let canClick = canClickNode(node, event); let canClick = canClickNode(node, event as any);
// eslint-disable-next-line no-loop-func // eslint-disable-next-line no-loop-func
const lockedNode = getClosestNode(node!, (n) => { const lockedNode: any = getClosestNode(node, (n) => {
// 假如当前节点就是 locked 状态,要从当前节点的父节点开始查找 // 假如当前节点就是 locked 状态,要从当前节点的父节点开始查找
return !!(node?.isLocked ? n.parent?.isLocked : n.isLocked); return !!(node?.isLocked ? n.parent?.isLocked : n.isLocked);
}); });

View File

@ -18,11 +18,7 @@ import { deprecate, isRegExp, isTitleConfig, isNode } from '@alilc/lowcode-utils
import { computed, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core'; import { computed, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core';
import { Node, INode } from './document'; import { Node, INode } from './document';
import { Designer } from './designer'; import { Designer } from './designer';
import { import { IconContainer, IconPage, IconComponent } from './icons';
IconContainer,
IconPage,
IconComponent,
} from './icons';
export function ensureAList(list?: string | string[]): string[] | null { export function ensureAList(list?: string | string[]): string[] | null {
if (!list) { if (!list) {
@ -138,7 +134,7 @@ export class ComponentMeta implements IComponentMeta {
private _isTopFixed?: boolean; private _isTopFixed?: boolean;
get isTopFixed(): boolean { get isTopFixed(): boolean {
return !!(this._isTopFixed); return !!this._isTopFixed;
} }
private parentWhitelist?: IPublicTypeNestingFilter | null; private parentWhitelist?: IPublicTypeNestingFilter | null;
@ -155,7 +151,7 @@ export class ComponentMeta implements IComponentMeta {
if (isTitleConfig(this._title)) { if (isTitleConfig(this._title)) {
return (this._title?.label as any) || this.componentName; return (this._title?.label as any) || this.componentName;
} }
return this._title || this.componentName; return (this._title as any) || this.componentName;
} }
@computed get icon() { @computed get icon() {
@ -184,7 +180,10 @@ export class ComponentMeta implements IComponentMeta {
*/ */
prototype?: any; prototype?: any;
constructor(readonly designer: Designer, metadata: IPublicTypeComponentMetadata) { constructor(
readonly designer: Designer,
metadata: IPublicTypeComponentMetadata,
) {
this.parseMetadata(metadata); this.parseMetadata(metadata);
} }
@ -287,8 +286,8 @@ export class ComponentMeta implements IComponentMeta {
} }
private transformMetadata( private transformMetadata(
metadta: IPublicTypeComponentMetadata, metadta: IPublicTypeComponentMetadata,
): IPublicTypeTransformedComponentMetadata { ): IPublicTypeTransformedComponentMetadata {
const registeredTransducers = this.designer.componentActions.getRegisteredMetadataTransducers(); const registeredTransducers = this.designer.componentActions.getRegisteredMetadataTransducers();
const result = registeredTransducers.reduce((prevMetadata, current) => { const result = registeredTransducers.reduce((prevMetadata, current) => {
return current(prevMetadata); return current(prevMetadata);
@ -351,7 +350,10 @@ export class ComponentMeta implements IComponentMeta {
return true; return true;
} }
checkNestingDown(my: INode, target: INode | IPublicTypeNodeSchema | IPublicTypeNodeSchema[]): boolean { checkNestingDown(
my: INode,
target: INode | IPublicTypeNodeSchema | IPublicTypeNodeSchema[],
): boolean {
// 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器 // 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器
if (this.childWhitelist) { if (this.childWhitelist) {
const _target: any = !Array.isArray(target) ? [target] : target; const _target: any = !Array.isArray(target) ? [target] : target;
@ -372,14 +374,15 @@ export class ComponentMeta implements IComponentMeta {
this.emitter.removeListener('metadata_change', fn); this.emitter.removeListener('metadata_change', fn);
}; };
} }
} }
export function isComponentMeta(obj: any): obj is ComponentMeta { export function isComponentMeta(obj: any): obj is ComponentMeta {
return obj && obj.isComponentMeta; return obj && obj.isComponentMeta;
} }
function preprocessMetadata(metadata: IPublicTypeComponentMetadata): IPublicTypeTransformedComponentMetadata { function preprocessMetadata(
metadata: IPublicTypeComponentMetadata,
): IPublicTypeTransformedComponentMetadata {
if (metadata.configure) { if (metadata.configure) {
if (Array.isArray(metadata.configure)) { if (Array.isArray(metadata.configure)) {
return { return {

View File

@ -1,6 +1,17 @@
import { IPublicTypeContextMenuAction, IPublicEnumContextMenuType, IPublicTypeContextMenuItem, IPublicApiMaterial, IPublicModelPluginContext } from '@alilc/lowcode-types'; import {
IPublicTypeContextMenuAction,
IPublicEnumContextMenuType,
IPublicTypeContextMenuItem,
IPublicApiMaterial,
IPublicModelPluginContext,
} from '@alilc/lowcode-types';
import { IDesigner, INode } from './designer'; import { IDesigner, INode } from './designer';
import { createContextMenu, parseContextMenuAsReactNode, parseContextMenuProperties, uniqueId } from '@alilc/lowcode-utils'; import {
createContextMenu,
parseContextMenuAsReactNode,
parseContextMenuProperties,
uniqueId,
} from '@alilc/lowcode-utils';
import { Menu } from '@alifd/next'; import { Menu } from '@alifd/next';
import { engineConfig } from '@alilc/lowcode-editor-core'; import { engineConfig } from '@alilc/lowcode-editor-core';
import './context-menu-actions.scss'; import './context-menu-actions.scss';
@ -22,16 +33,14 @@ export class GlobalContextMenuActions {
return; return;
} }
this.enableContextMenu = enable; this.enableContextMenu = enable;
this.dispose.forEach(d => d()); this.dispose.forEach((d) => d());
if (enable) { if (enable) {
this.initEvent(); this.initEvent();
} }
}); });
} }
handleContextMenu = ( handleContextMenu = (event: MouseEvent) => {
event: MouseEvent,
) => {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -46,7 +55,9 @@ export class GlobalContextMenuActions {
const destroy = () => { const destroy = () => {
destroyFn?.(); destroyFn?.();
}; };
const pluginContext: IPublicModelPluginContext = contextMenu.designer.editor.get('pluginContext') as IPublicModelPluginContext; const pluginContext: IPublicModelPluginContext = contextMenu.designer.editor.get(
'pluginContext',
) as IPublicModelPluginContext;
const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, { const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: [], nodes: [],
@ -69,7 +80,7 @@ export class GlobalContextMenuActions {
const target = event.target; const target = event.target;
const { top, left } = target?.getBoundingClientRect(); const { top, left } = (target as any)?.getBoundingClientRect();
const menuInstance = Menu.create({ const menuInstance = Menu.create({
target: event.target, target: event.target,
@ -113,7 +124,7 @@ export class ContextMenuActions {
enableContextMenu: boolean; enableContextMenu: boolean;
id: string = uniqueId('contextMenu');; id: string = uniqueId('contextMenu');
constructor(designer: IDesigner) { constructor(designer: IDesigner) {
this.designer = designer; this.designer = designer;
@ -124,7 +135,7 @@ export class ContextMenuActions {
return; return;
} }
this.enableContextMenu = enable; this.enableContextMenu = enable;
this.dispose.forEach(d => d()); this.dispose.forEach((d) => d());
if (enable) { if (enable) {
this.initEvent(); this.initEvent();
} }
@ -133,10 +144,7 @@ export class ContextMenuActions {
globalContextMenuActions.registerContextMenuActions(this); globalContextMenuActions.registerContextMenuActions(this);
} }
handleContextMenu = ( handleContextMenu = (nodes: INode[], event: MouseEvent) => {
nodes: INode[],
event: MouseEvent,
) => {
const designer = this.designer; const designer = this.designer;
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -152,10 +160,12 @@ export class ContextMenuActions {
destroyFn?.(); destroyFn?.();
}; };
const pluginContext: IPublicModelPluginContext = this.designer.editor.get('pluginContext') as IPublicModelPluginContext; const pluginContext: IPublicModelPluginContext = this.designer.editor.get(
'pluginContext',
) as IPublicModelPluginContext;
const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, { const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!), nodes: nodes.map((d) => designer.shellModelFactory.createNode(d)!),
destroy, destroy,
event, event,
pluginContext, pluginContext,
@ -169,7 +179,7 @@ export class ContextMenuActions {
const menuNode = parseContextMenuAsReactNode(layoutMenu, { const menuNode = parseContextMenuAsReactNode(layoutMenu, {
destroy, destroy,
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!), nodes: nodes.map((d) => designer.shellModelFactory.createNode(d)!),
pluginContext, pluginContext,
}); });
@ -182,26 +192,25 @@ export class ContextMenuActions {
initEvent() { initEvent() {
const designer = this.designer; const designer = this.designer;
this.dispose.push( this.dispose.push(
designer.editor.eventBus.on('designer.builtinSimulator.contextmenu', ({ designer.editor.eventBus.on(
node, 'designer.builtinSimulator.contextmenu',
originalEvent, ({ node, originalEvent }: { node: INode; originalEvent: MouseEvent }) => {
}: { originalEvent.stopPropagation();
node: INode; originalEvent.preventDefault();
originalEvent: MouseEvent; // 如果右键的节点不在 当前选中的节点中,选中该节点
}) => { if (!designer.currentSelection?.has(node.id)) {
originalEvent.stopPropagation(); designer.currentSelection?.select(node.id);
originalEvent.preventDefault(); }
// 如果右键的节点不在 当前选中的节点中,选中该节点 const nodes = designer.currentSelection?.getNodes() ?? [];
if (!designer.currentSelection?.has(node.id)) { this.handleContextMenu(nodes, originalEvent);
designer.currentSelection?.select(node.id); },
} ),
const nodes = designer.currentSelection?.getNodes();
this.handleContextMenu(nodes, originalEvent);
}),
); );
} }
addMenuAction: IPublicApiMaterial['addContextMenuOption'] = (action: IPublicTypeContextMenuAction) => { addMenuAction: IPublicApiMaterial['addContextMenuOption'] = (
action: IPublicTypeContextMenuAction,
) => {
this.actions.push({ this.actions.push({
type: IPublicEnumContextMenuType.MENU_ITEM, type: IPublicEnumContextMenuType.MENU_ITEM,
...action, ...action,
@ -215,9 +224,11 @@ export class ContextMenuActions {
} }
}; };
adjustMenuLayout: IPublicApiMaterial['adjustContextMenuLayout'] = (fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]) => { adjustMenuLayout: IPublicApiMaterial['adjustContextMenuLayout'] = (
fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[],
) => {
adjustMenuLayoutFn = fn; adjustMenuLayoutFn = fn;
}; };
} }
export interface IContextMenuActions extends ContextMenuActions {} export interface IContextMenuActions extends ContextMenuActions {}

View File

@ -1,23 +1,21 @@
import { INode } from '../document/node/node'; import { INode } from '../document/node/node';
import { obx, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import { obx, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
import { import { IPublicTypeActiveTarget, IPublicModelActiveTracker } from '@alilc/lowcode-types';
IPublicTypeActiveTarget,
IPublicModelActiveTracker,
} from '@alilc/lowcode-types';
import { isNode } from '@alilc/lowcode-utils'; import { isNode } from '@alilc/lowcode-utils';
export interface IActiveTracker extends Omit< IPublicModelActiveTracker, 'track' | 'onChange' > { export interface IActiveTracker extends Omit<IPublicModelActiveTracker, 'track' | 'onChange'> {
_target: ActiveTarget | INode; _target?: ActiveTarget | INode;
track(originalTarget: ActiveTarget | INode): void; track(originalTarget: ActiveTarget | INode): void;
onChange(fn: (target: ActiveTarget) => void): () => void; onChange(fn: (target: ActiveTarget) => void): () => void;
} }
export interface ActiveTarget extends Omit< IPublicTypeActiveTarget, 'node' > { export interface ActiveTarget extends Omit<IPublicTypeActiveTarget, 'node'> {
node: INode; node: INode;
} }
// @ts-ignore
export class ActiveTracker implements IActiveTracker { export class ActiveTracker implements IActiveTracker {
@obx.ref private _target?: ActiveTarget | INode; @obx.ref private _target?: ActiveTarget | INode;

View File

@ -4,7 +4,11 @@ import { Designer } from '../designer';
import { isDragNodeObject } from '../dragon'; import { isDragNodeObject } from '../dragon';
import { isSimulatorHost } from '../../simulator'; import { isSimulatorHost } from '../../simulator';
import './ghost.less'; import './ghost.less';
import { IPublicTypeI18nData, IPublicTypeNodeSchema, IPublicModelDragObject } from '@alilc/lowcode-types'; import {
IPublicTypeI18nData,
IPublicTypeNodeSchema,
IPublicModelDragObject,
} from '@alilc/lowcode-types';
type offBinding = () => any; type offBinding = () => any;
@ -26,15 +30,15 @@ export default class DragGhost extends Component<{ designer: Designer }> {
super(props); super(props);
makeObservable(this); makeObservable(this);
this.dispose = [ this.dispose = [
this.dragon.onDragstart(e => { this.dragon.onDragstart((e) => {
if (e.originalEvent.type.slice(0, 4) === 'drag') { if (e.originalEvent.type.slice(0, 4) === 'drag') {
return; return;
} }
this.titles = this.getTitles(e.dragObject); this.titles = this.getTitles(e.dragObject!) as any;
this.x = e.globalX; this.x = e.globalX;
this.y = e.globalY; this.y = e.globalY;
}), }),
this.dragon.onDrag(e => { this.dragon.onDrag((e) => {
this.x = e.globalX; this.x = e.globalX;
this.y = e.globalY; this.y = e.globalY;
if (isSimulatorHost(e.sensor)) { if (isSimulatorHost(e.sensor)) {
@ -56,17 +60,20 @@ export default class DragGhost extends Component<{ designer: Designer }> {
getTitles(dragObject: IPublicModelDragObject) { getTitles(dragObject: IPublicModelDragObject) {
if (isDragNodeObject(dragObject)) { if (isDragNodeObject(dragObject)) {
return dragObject.nodes.map((node) => node.title); return dragObject.nodes.map((node) => node?.title);
} }
const dataList = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data]; const dataList = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data!];
return dataList.map((item: IPublicTypeNodeSchema, i) => (this.props.designer.getComponentMeta(item.componentName).title)); return dataList.map(
(item: IPublicTypeNodeSchema) =>
this.props.designer.getComponentMeta(item.componentName).title,
);
} }
componentWillUnmount() { componentWillUnmount() {
if (this.dispose) { if (this.dispose) {
this.dispose.forEach(off => off()); this.dispose.forEach((off) => off());
} }
} }

View File

@ -43,7 +43,11 @@ export function isDragNodeDataObject(obj: any): obj is IPublicTypeDragNodeDataOb
* @deprecated use same function in @alilc/lowcode-utils * @deprecated use same function in @alilc/lowcode-utils
*/ */
export function isDragAnyObject(obj: any): obj is IPublicTypeDragAnyObject { export function isDragAnyObject(obj: any): obj is IPublicTypeDragAnyObject {
return obj && obj.type !== IPublicEnumDragObjectType.NodeData && obj.type !== IPublicEnumDragObjectType.Node; return (
obj &&
obj.type !== IPublicEnumDragObjectType.NodeData &&
obj.type !== IPublicEnumDragObjectType.Node
);
} }
export function isLocateEvent(e: any): e is ILocateEvent { export function isLocateEvent(e: any): e is ILocateEvent {
@ -88,7 +92,7 @@ function getSourceSensor(dragObject: IPublicModelDragObject): ISimulatorHost | n
if (!isDragNodeObject(dragObject)) { if (!isDragNodeObject(dragObject)) {
return null; return null;
} }
return dragObject.nodes[0]?.document?.simulator || null; return (dragObject.nodes[0]?.document as any)?.simulator || null;
} }
function isDragEvent(e: any): e is DragEvent { function isDragEvent(e: any): e is DragEvent {
@ -98,10 +102,7 @@ function isDragEvent(e: any): e is DragEvent {
/** /**
* Drag-on * Drag-on
*/ */
export class Dragon implements IPublicModelDragon< export class Dragon implements IPublicModelDragon<INode, ILocateEvent> {
INode,
ILocateEvent
> {
private sensors: IPublicModelSensor[] = []; private sensors: IPublicModelSensor[] = [];
private nodeInstPointerEvents: boolean; private nodeInstPointerEvents: boolean;
@ -139,6 +140,7 @@ export class Dragon implements IPublicModelDragon<
* @param shell container element * @param shell container element
* @param boost boost got a drag object * @param boost boost got a drag object
*/ */
// @ts-ignore
from(shell: Element, boost: (e: MouseEvent) => IPublicModelDragObject | null) { from(shell: Element, boost: (e: MouseEvent) => IPublicModelDragObject | null) {
const mousedown = (e: MouseEvent) => { const mousedown = (e: MouseEvent) => {
// ESC or RightClick // ESC or RightClick
@ -166,13 +168,20 @@ export class Dragon implements IPublicModelDragon<
* @param dragObject * @param dragObject
* @param boostEvent * @param boostEvent
*/ */
boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: INode | IPublicModelNode) { boost(
dragObject: IPublicModelDragObject,
boostEvent: MouseEvent | DragEvent,
fromRglNode?: INode | IPublicModelNode,
) {
const { designer } = this; const { designer } = this;
const masterSensors = this.getMasterSensors(); const masterSensors = this.getMasterSensors();
const handleEvents = makeEventsHandler(boostEvent, masterSensors); const handleEvents = makeEventsHandler(boostEvent, masterSensors);
const newBie = !isDragNodeObject(dragObject); const newBie = !isDragNodeObject(dragObject);
const forceCopyState = const forceCopyState =
isDragNodeObject(dragObject) && dragObject.nodes.some((node: Node | IPublicModelNode) => (typeof node.isSlot === 'function' ? node.isSlot() : node.isSlot)); isDragNodeObject(dragObject) &&
dragObject.nodes.some((node: Node | IPublicModelNode) =>
typeof node.isSlot === 'function' ? node.isSlot() : node.isSlot,
);
const isBoostFromDragAPI = isDragEvent(boostEvent); const isBoostFromDragAPI = isDragEvent(boostEvent);
let lastSensor: IPublicModelSensor | undefined; let lastSensor: IPublicModelSensor | undefined;
@ -238,14 +247,14 @@ export class Dragon implements IPublicModelDragon<
} }
lastArrive = e; lastArrive = e;
const { isRGL, rglNode } = getRGL(e); const { isRGL, rglNode } = getRGL(e) as any;
const locateEvent = createLocateEvent(e); const locateEvent = createLocateEvent(e);
const sensor = chooseSensor(locateEvent); const sensor = chooseSensor(locateEvent);
/* istanbul ignore next */ /* istanbul ignore next */
if (isRGL) { if (isRGL) {
// 禁止被拖拽元素的阻断 // 禁止被拖拽元素的阻断
const nodeInst = dragObject.nodes[0].getDOMNode(); const nodeInst = dragObject?.nodes?.[0]?.getDOMNode();
if (nodeInst && nodeInst.style) { if (nodeInst && nodeInst.style) {
this.nodeInstPointerEvents = true; this.nodeInstPointerEvents = true;
nodeInst.style.pointerEvents = 'none'; nodeInst.style.pointerEvents = 'none';
@ -263,7 +272,7 @@ export class Dragon implements IPublicModelDragon<
this.emitter.emit('rgl.add.placeholder', { this.emitter.emit('rgl.add.placeholder', {
rglNode, rglNode,
fromRglNode, fromRglNode,
node: locateEvent.dragObject?.nodes[0], node: locateEvent.dragObject?.nodes?.[0],
event: e, event: e,
}); });
designer.clearLocation(); designer.clearLocation();
@ -337,7 +346,7 @@ export class Dragon implements IPublicModelDragon<
const over = (e?: any) => { const over = (e?: any) => {
// 禁止被拖拽元素的阻断 // 禁止被拖拽元素的阻断
if (this.nodeInstPointerEvents) { if (this.nodeInstPointerEvents) {
const nodeInst = dragObject.nodes[0].getDOMNode(); const nodeInst = dragObject?.nodes?.[0]?.getDOMNode();
if (nodeInst && nodeInst.style) { if (nodeInst && nodeInst.style) {
nodeInst.style.pointerEvents = ''; nodeInst.style.pointerEvents = '';
} }
@ -346,18 +355,18 @@ export class Dragon implements IPublicModelDragon<
// 发送drop事件 // 发送drop事件
if (e) { if (e) {
const { isRGL, rglNode } = getRGL(e); const { isRGL, rglNode } = getRGL(e) as any;
/* istanbul ignore next */ /* istanbul ignore next */
if (isRGL && this._canDrop && this._dragging) { if (isRGL && this._canDrop && this._dragging) {
const tarNode = dragObject.nodes[0]; const tarNode = dragObject?.nodes?.[0];
if (rglNode.id !== tarNode.id) { if (rglNode.id !== tarNode?.id) {
// 避免死循环 // 避免死循环
this.emitter.emit('rgl.drop', { this.emitter.emit('rgl.drop', {
rglNode, rglNode,
node: tarNode, node: tarNode,
}); });
const selection = designer.project.currentDocument?.selection; const selection = designer.project.currentDocument?.selection;
selection?.select(tarNode.id); selection?.select(tarNode!.id);
} }
} }
} }
@ -429,7 +438,7 @@ export class Dragon implements IPublicModelDragon<
if (!sourceDocument || sourceDocument === document) { if (!sourceDocument || sourceDocument === document) {
evt.globalX = e.clientX; evt.globalX = e.clientX;
evt.globalY = e.clientY; evt.globalY = e.clientY;
} else /* istanbul ignore next */ { } /* istanbul ignore next */ else {
// event from simulator sandbox // event from simulator sandbox
let srcSim: ISimulatorHost | undefined; let srcSim: ISimulatorHost | undefined;
const lastSim = lastSensor && isSimulatorHost(lastSensor) ? lastSensor : null; const lastSim = lastSensor && isSimulatorHost(lastSensor) ? lastSensor : null;
@ -463,7 +472,9 @@ export class Dragon implements IPublicModelDragon<
/* istanbul ignore next */ /* istanbul ignore next */
const chooseSensor = (e: ILocateEvent) => { const chooseSensor = (e: ILocateEvent) => {
// this.sensors will change on dragstart // this.sensors will change on dragstart
const sensors: IPublicModelSensor[] = this.sensors.concat(masterSensors as IPublicModelSensor[]); const sensors: IPublicModelSensor[] = this.sensors.concat(
masterSensors as IPublicModelSensor[],
);
let sensor = let sensor =
e.sensor && e.sensor.isEnter(e) e.sensor && e.sensor.isEnter(e)
? e.sensor ? e.sensor
@ -475,7 +486,7 @@ export class Dragon implements IPublicModelDragon<
} else if (e.sensor) { } else if (e.sensor) {
sensor = e.sensor; sensor = e.sensor;
} else if (sourceSensor) { } else if (sourceSensor) {
sensor = sourceSensor; sensor = sourceSensor as any;
} }
} }
if (sensor !== lastSensor) { if (sensor !== lastSensor) {
@ -634,4 +645,4 @@ export class Dragon implements IPublicModelDragon<
} }
} }
export interface IDragon extends Dragon { } export interface IDragon extends Dragon {}

View File

@ -60,7 +60,10 @@ export function isChildInline(child: Element | Text, win?: Window) {
return true; return true;
} }
const style = (win || getWindow(child)).getComputedStyle(child); const style = (win || getWindow(child)).getComputedStyle(child);
return /^inline/.test(style.getPropertyValue('display')) || /^(left|right)$/.test(style.getPropertyValue('float')); return (
/^inline/.test(style.getPropertyValue('display')) ||
/^(left|right)$/.test(style.getPropertyValue('float'))
);
} }
export function getRectTarget(rect: IPublicTypeRect | null) { export function getRectTarget(rect: IPublicTypeRect | null) {
@ -99,7 +102,6 @@ export function getWindow(elem: Element | Document): Window {
return (isDocument(elem) ? elem : elem.ownerDocument!).defaultView!; return (isDocument(elem) ? elem : elem.ownerDocument!).defaultView!;
} }
export interface IDropLocation extends Omit<IPublicModelDropLocation, 'target' | 'clone'> { export interface IDropLocation extends Omit<IPublicModelDropLocation, 'target' | 'clone'> {
readonly source: string; readonly source: string;
get target(): INode; get target(): INode;
@ -126,7 +128,7 @@ export class DropLocation implements IDropLocation {
this.target = target; this.target = target;
this.detail = detail; this.detail = detail;
this.source = source; this.source = source;
this.event = event; this.event = event as any;
} }
clone(event: ILocateEvent): IDropLocation { clone(event: ILocateEvent): IDropLocation {

View File

@ -75,14 +75,14 @@ export class OffsetObserver {
@computed get offsetHeight() { @computed get offsetHeight() {
if (!this.viewport?.scrolling || this.lastOffsetHeight == null) { if (!this.viewport?.scrolling || this.lastOffsetHeight == null) {
this.lastOffsetHeight = this.isRoot ? (this.viewport?.height || 0) : this.height; this.lastOffsetHeight = this.isRoot ? this.viewport?.height || 0 : this.height;
} }
return this.lastOffsetHeight; return this.lastOffsetHeight;
} }
@computed get offsetWidth() { @computed get offsetWidth() {
if (!(this.viewport?.scrolling || 0) || this.lastOffsetWidth == null) { if (!(this.viewport?.scrolling || 0) || this.lastOffsetWidth == null) {
this.lastOffsetWidth = this.isRoot ? (this.viewport?.width || 0) : this.width; this.lastOffsetWidth = this.isRoot ? this.viewport?.width || 0 : this.width;
} }
return this.lastOffsetWidth; return this.lastOffsetWidth;
} }

View File

@ -10,17 +10,19 @@ import {
IPublicModelSettingField, IPublicModelSettingField,
IBaseModelSettingField, IBaseModelSettingField,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import type { import type { IPublicTypeSetValueOptions } from '@alilc/lowcode-types';
IPublicTypeSetValueOptions,
} from '@alilc/lowcode-types';
import { Transducer } from './utils'; import { Transducer } from './utils';
import { ISettingPropEntry, SettingPropEntry } from './setting-prop-entry'; import { ISettingPropEntry, SettingPropEntry } from './setting-prop-entry';
import { computed, obx, makeObservable, action, untracked, intl } from '@alilc/lowcode-editor-core'; import { computed, obx, makeObservable, action, untracked, intl } from '@alilc/lowcode-editor-core';
import { cloneDeep, isCustomView, isDynamicSetter, isJSExpression } from '@alilc/lowcode-utils'; import { cloneDeep, isCustomView, isDynamicSetter, isJSExpression } from '@alilc/lowcode-utils';
import { ISettingTopEntry } from './setting-top-entry'; import { ISettingTopEntry } from './setting-top-entry';
import { IComponentMeta, INode } from '@alilc/lowcode-designer'; import { IComponentMeta } from '../../component-meta';
import { INode } from '../../document';
function getSettingFieldCollectorKey(parent: ISettingTopEntry | ISettingField, config: IPublicTypeFieldConfig) { function getSettingFieldCollectorKey(
parent: ISettingTopEntry | ISettingField,
config: IPublicTypeFieldConfig,
) {
let cur = parent; let cur = parent;
const path = [config.name]; const path = [config.name];
while (cur !== parent.top) { while (cur !== parent.top) {
@ -32,12 +34,13 @@ function getSettingFieldCollectorKey(parent: ISettingTopEntry | ISettingField, c
return path.join('.'); return path.join('.');
} }
export interface ISettingField extends ISettingPropEntry, Omit<IBaseModelSettingField< // @ts-ignore
ISettingTopEntry, export interface ISettingField
ISettingField, extends ISettingPropEntry,
IComponentMeta, Omit<
INode IBaseModelSettingField<ISettingTopEntry, ISettingField, IComponentMeta, INode>,
>, 'setValue' | 'key' | 'node'> { 'setValue' | 'key' | 'node'
> {
readonly isSettingField: true; readonly isSettingField: true;
readonly isRequired: boolean; readonly isRequired: boolean;
@ -96,7 +99,7 @@ export class SettingField extends SettingPropEntry implements ISettingField {
// ==== dynamic properties ==== // ==== dynamic properties ====
private _title?: IPublicTypeTitleContent; private _title?: IPublicTypeTitleContent;
get title() { get title(): any {
return ( return (
this._title || (typeof this.name === 'number' ? `${intl('Item')} ${this.name}` : this.name) this._title || (typeof this.name === 'number' ? `${intl('Item')} ${this.name}` : this.name)
); );
@ -132,11 +135,11 @@ export class SettingField extends SettingPropEntry implements ISettingField {
this.initItems(items, settingFieldCollector); this.initItems(items, settingFieldCollector);
} }
if (this.type !== 'group' && settingFieldCollector && config.name) { if (this.type !== 'group' && settingFieldCollector && config.name) {
settingFieldCollector(getSettingFieldCollectorKey(parent, config), this); settingFieldCollector(getSettingFieldCollectorKey(parent, config), this as any);
} }
// compatiable old config // compatiable old config
this.transducer = new Transducer(this, { setter }); this.transducer = new Transducer(this as any, { setter });
} }
@computed get setter(): IPublicTypeSetterType | null { @computed get setter(): IPublicTypeSetterType | null {
@ -179,8 +182,8 @@ export class SettingField extends SettingPropEntry implements ISettingField {
if (isCustomView(item)) { if (isCustomView(item)) {
return item; return item;
} }
return new SettingField(this, item, settingFieldCollector); return new SettingField(this as any, item, settingFieldCollector);
}); }) as any;
} }
private disposeItems() { private disposeItems() {
@ -190,8 +193,8 @@ export class SettingField extends SettingPropEntry implements ISettingField {
// 创建子配置项,通常用于 object/array 类型数据 // 创建子配置项,通常用于 object/array 类型数据
createField(config: IPublicTypeFieldConfig): ISettingField { createField(config: IPublicTypeFieldConfig): ISettingField {
this.settingFieldCollector?.(getSettingFieldCollectorKey(this.parent, config), this); this.settingFieldCollector?.(getSettingFieldCollectorKey(this.parent, config), this as any);
return new SettingField(this, config, this.settingFieldCollector); return new SettingField(this as any, config, this.settingFieldCollector) as ISettingField;
} }
purge() { purge() {
@ -307,7 +310,7 @@ export class SettingField extends SettingPropEntry implements ISettingField {
} }
onEffect(action: () => void): IPublicTypeDisposable { onEffect(action: () => void): IPublicTypeDisposable {
return this.designer!.autorun(action, true); return this.designer!.autorun(action);
} }
internalToShellField() { internalToShellField() {

View File

@ -1,5 +1,19 @@
import { obx, computed, makeObservable, runInAction, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import {
import { GlobalEvent, IPublicApiSetters, IPublicModelEditor, IPublicModelSettingField, IPublicTypeFieldExtraProps, IPublicTypeSetValueOptions } from '@alilc/lowcode-types'; obx,
computed,
makeObservable,
runInAction,
IEventBus,
createModuleEventBus,
} from '@alilc/lowcode-editor-core';
import {
GlobalEvent,
IPublicApiSetters,
IPublicModelEditor,
IPublicModelSettingField,
IPublicTypeFieldExtraProps,
IPublicTypeSetValueOptions,
} from '@alilc/lowcode-types';
import { uniqueId, isJSExpression } from '@alilc/lowcode-utils'; import { uniqueId, isJSExpression } from '@alilc/lowcode-utils';
import { ISettingEntry } from './setting-entry-type'; import { ISettingEntry } from './setting-entry-type';
import { INode } from '../../document'; import { INode } from '../../document';
@ -33,7 +47,12 @@ export interface ISettingPropEntry extends ISettingEntry {
remove(): void; remove(): void;
setValue(val: any, isHotValue?: boolean, force?: boolean, extraOptions?: IPublicTypeSetValueOptions): void; setValue(
val: any,
isHotValue?: boolean,
force?: boolean,
extraOptions?: IPublicTypeSetValueOptions,
): void;
internalToShellField(): IPublicModelSettingField; internalToShellField(): IPublicModelSettingField;
} }
@ -83,7 +102,11 @@ export class SettingPropEntry implements ISettingPropEntry {
extraProps: IPublicTypeFieldExtraProps = {}; extraProps: IPublicTypeFieldExtraProps = {};
constructor(readonly parent: ISettingTopEntry | ISettingField, name: string | number | undefined, type?: 'field' | 'group') { constructor(
readonly parent: ISettingTopEntry | ISettingField,
name: string | number | undefined,
type?: 'field' | 'group',
) {
makeObservable(this); makeObservable(this);
if (type == null) { if (type == null) {
const c = typeof name === 'string' ? name.slice(0, 1) : ''; const c = typeof name === 'string' ? name.slice(0, 1) : '';
@ -206,7 +229,12 @@ export class SettingPropEntry implements ISettingPropEntry {
/** /**
* *
*/ */
setValue(val: any, isHotValue?: boolean, force?: boolean, extraOptions?: IPublicTypeSetValueOptions) { setValue(
val: any,
isHotValue?: boolean,
force?: boolean,
extraOptions?: IPublicTypeSetValueOptions,
) {
const oldValue = this.getValue(); const oldValue = this.getValue();
if (this.type === 'field') { if (this.type === 'field') {
this.name?.toString() && this.parent.setPropValue(this.name, val); this.name?.toString() && this.parent.setPropValue(this.name, val);
@ -329,7 +357,7 @@ export class SettingPropEntry implements ISettingPropEntry {
} }
notifyValueChange(oldValue: any, newValue: any) { notifyValueChange(oldValue: any, newValue: any) {
this.editor.eventBus.emit(GlobalEvent.Node.Prop.Change, { this.editor.eventBus.emit(GlobalEvent.Node.Prop.InnerChange, {
node: this.getNode(), node: this.getNode(),
prop: this, prop: this,
oldValue, oldValue,

View File

@ -1,4 +1,9 @@
import { IPublicTypeCustomView, IPublicModelEditor, IPublicModelSettingTopEntry, IPublicApiSetters } from '@alilc/lowcode-types'; import {
IPublicTypeCustomView,
IPublicModelEditor,
IPublicModelSettingTopEntry,
IPublicApiSetters,
} from '@alilc/lowcode-types';
import { isCustomView } from '@alilc/lowcode-utils'; import { isCustomView } from '@alilc/lowcode-utils';
import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
import { ISettingEntry } from './setting-entry-type'; import { ISettingEntry } from './setting-entry-type';
@ -14,10 +19,9 @@ function generateSessionId(nodes: INode[]) {
.join(','); .join(',');
} }
export interface ISettingTopEntry extends ISettingEntry, IPublicModelSettingTopEntry< export interface ISettingTopEntry
INode, extends ISettingEntry,
ISettingField IPublicModelSettingTopEntry<INode, ISettingField> {
> {
readonly top: ISettingTopEntry; readonly top: ISettingTopEntry;
readonly parent: ISettingTopEntry; readonly parent: ISettingTopEntry;
@ -48,16 +52,16 @@ export class SettingTopEntry implements ISettingTopEntry {
readonly path = []; readonly path = [];
readonly top = this; readonly top = this as ISettingTopEntry;
readonly parent = this; readonly parent = this as ISettingTopEntry;
get componentMeta() { get componentMeta() {
return this._componentMeta; return this._componentMeta;
} }
get items() { get items() {
return this._items; return this._items as any;
} }
/** /**
@ -95,7 +99,10 @@ export class SettingTopEntry implements ISettingTopEntry {
disposeFunctions: any[] = []; disposeFunctions: any[] = [];
constructor(readonly editor: IPublicModelEditor, readonly nodes: INode[]) { constructor(
readonly editor: IPublicModelEditor,
readonly nodes: INode[],
) {
if (!Array.isArray(nodes) || nodes.length < 1) { if (!Array.isArray(nodes) || nodes.length < 1) {
throw new ReferenceError('nodes should not be empty'); throw new ReferenceError('nodes should not be empty');
} }
@ -145,7 +152,7 @@ export class SettingTopEntry implements ISettingTopEntry {
if (isCustomView(item)) { if (isCustomView(item)) {
return item; return item;
} }
return new SettingField(this, item as any, settingFieldCollector); return new SettingField(this as ISettingTopEntry, item as any, settingFieldCollector);
}); });
this._settingFieldMap = settingFieldMap; this._settingFieldMap = settingFieldMap;
} }
@ -177,7 +184,10 @@ export class SettingTopEntry implements ISettingTopEntry {
*/ */
get(propName: string | number): ISettingField | null { get(propName: string | number): ISettingField | null {
if (!propName) return null; if (!propName) return null;
return this._settingFieldMap[propName] || (new SettingField(this, { name: propName })); return (
this._settingFieldMap[propName] ||
new SettingField(this as ISettingTopEntry, { name: propName })
);
} }
/** /**
@ -244,7 +254,7 @@ export class SettingTopEntry implements ISettingTopEntry {
this.disposeItems(); this.disposeItems();
this._settingFieldMap = {}; this._settingFieldMap = {};
this.emitter.removeAllListeners(); this.emitter.removeAllListeners();
this.disposeFunctions.forEach(f => f()); this.disposeFunctions.forEach((f) => f());
this.disposeFunctions = []; this.disposeFunctions = [];
} }
@ -253,21 +263,15 @@ export class SettingTopEntry implements ISettingTopEntry {
} }
// ==== copy some Node api ===== // ==== copy some Node api =====
getStatus() { getStatus() {}
} setStatus() {}
setStatus() {
}
getChildren() { getChildren() {
// this.nodes.map() // this.nodes.map()
} }
getDOMNode() { getDOMNode() {}
}
getId() { getId() {
return this.id; return this.id;

View File

@ -4,11 +4,11 @@ import { IPublicTypeFieldConfig, IPublicTypeSetterConfig } from '@alilc/lowcode-
import { isSetterConfig, isDynamicSetter } from '@alilc/lowcode-utils'; import { isSetterConfig, isDynamicSetter } from '@alilc/lowcode-utils';
import { ISettingField } from './setting-field'; import { ISettingField } from './setting-field';
function getHotterFromSetter(setter) { function getHotterFromSetter(setter: any) {
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line return (setter && (setter.Hotter || (setter.type && setter.type.Hotter))) || []; // eslint-disable-line
} }
function getTransducerFromSetter(setter) { function getTransducerFromSetter(setter: any) {
return ( return (
(setter && (setter &&
(setter.transducer || (setter.transducer ||
@ -18,15 +18,15 @@ function getTransducerFromSetter(setter) {
); // eslint-disable-line ); // eslint-disable-line
} }
function combineTransducer(transducer, arr, context) { function combineTransducer(transducer: any, arr: any, context: any) {
if (!transducer && Array.isArray(arr)) { if (!transducer && Array.isArray(arr)) {
const [toHot, toNative] = arr; const [toHot, toNative] = arr;
transducer = { toHot, toNative }; transducer = { toHot, toNative };
} }
return { return {
toHot: (transducer && transducer.toHot || (x => x)).bind(context), // eslint-disable-line toHot: ((transducer && transducer.toHot) || ((x: any) => x)).bind(context), // eslint-disable-line
toNative: (transducer && transducer.toNative || (x => x)).bind(context), // eslint-disable-line toNative: ((transducer && transducer.toNative) || ((x: any) => x)).bind(context), // eslint-disable-line
}; };
} }
@ -43,9 +43,9 @@ export class Transducer {
// 3. IPublicTypeSetterConfig[] // 3. IPublicTypeSetterConfig[]
if (Array.isArray(setter)) { if (Array.isArray(setter)) {
setter = setter[0]; setter = setter[0];
} else if (isValidElement(setter) && setter.type.displayName === 'MixedSetter') { } else if (isValidElement(setter) && (setter.type as any).displayName === 'MixedSetter') {
setter = setter.props?.setters?.[0]; setter = (setter.props as any)?.setters?.[0];
} else if (typeof setter === 'object' && setter.componentName === 'MixedSetter') { } else if (typeof setter === 'object' && (setter as any).componentName === 'MixedSetter') {
setter = Array.isArray(setter?.props?.setters) && setter.props.setters[0]; setter = Array.isArray(setter?.props?.setters) && setter.props.setters[0];
} }
@ -71,18 +71,24 @@ export class Transducer {
if (isDynamicSetter(setter) && isDynamic) { if (isDynamicSetter(setter) && isDynamic) {
try { try {
setter = setter.call(context.internalToShellField(), context.internalToShellField()); setter = setter.call(context.internalToShellField(), context.internalToShellField());
} catch (e) { console.error(e); } } catch (e) {
console.error(e);
}
} }
this.setterTransducer = combineTransducer(getTransducerFromSetter(setter), getHotterFromSetter(setter), context); this.setterTransducer = combineTransducer(
getTransducerFromSetter(setter),
getHotterFromSetter(setter),
context,
);
this.context = context; this.context = context;
} }
toHot(data) { toHot(data: any) {
return this.setterTransducer.toHot(data); return this.setterTransducer.toHot(data);
} }
toNative(data) { toNative(data: any) {
return this.setterTransducer.toNative(data); return this.setterTransducer.toNative(data);
} }
} }

View File

@ -20,12 +20,8 @@ import {
IPublicTypeOnChangeOptions, IPublicTypeOnChangeOptions,
IPublicTypeDisposable, IPublicTypeDisposable,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import type { import type { IPublicTypeRootSchema } from '@alilc/lowcode-types';
IPublicTypeRootSchema, import type { IDropLocation } from '../designer/location';
} from '@alilc/lowcode-types';
import type {
IDropLocation,
} from '@alilc/lowcode-designer';
import { import {
uniqueId, uniqueId,
isPlainObject, isPlainObject,
@ -50,36 +46,40 @@ import { EDITOR_EVENT } from '../types';
export type GetDataType<T, NodeType> = T extends undefined export type GetDataType<T, NodeType> = T extends undefined
? NodeType extends { ? NodeType extends {
schema: infer R; schema: infer R;
} }
? R ? R
: any : any
: T; : T;
export class DocumentModel implements Omit<IPublicModelDocumentModel< export class DocumentModel
ISelection, implements
IHistory, Omit<
INode, IPublicModelDocumentModel<
IDropLocation, ISelection,
IModalNodesManager, IHistory,
IProject INode,
>, IDropLocation,
'detecting' | IModalNodesManager,
'checkNesting' | IProject
'getNodeById' | >,
// 以下属性在内部的 document 中不存在 | 'detecting'
'exportSchema' | | 'checkNesting'
'importSchema' | | 'getNodeById'
'onAddNode' | // 以下属性在内部的 document 中不存在
'onRemoveNode' | | 'exportSchema'
'onChangeDetecting' | | 'importSchema'
'onChangeSelection' | | 'onAddNode'
'onChangeNodeProp' | | 'onRemoveNode'
'onImportSchema' | | 'onChangeDetecting'
'isDetectingNode' | | 'onChangeSelection'
'onFocusNodeChanged' | | 'onChangeNodeProp'
'onDropLocationChanged' | 'onImportSchema'
> { | 'isDetectingNode'
| 'onFocusNodeChanged'
| 'onDropLocationChanged'
>
{
/** /**
* Page/Component/Block * Page/Component/Block
*/ */
@ -179,10 +179,10 @@ IProject
set dropLocation(loc: IDropLocation | null) { set dropLocation(loc: IDropLocation | null) {
this._dropLocation = loc; this._dropLocation = loc;
// pub event // pub event
this.designer.editor.eventBus.emit( this.designer.editor.eventBus.emit('document.dropLocation.changed', {
'document.dropLocation.changed', document: this,
{ document: this, location: loc }, location: loc,
); });
} }
/** /**
@ -282,7 +282,9 @@ IProject
}; };
} }
onChangeNodeChildren(fn: (info: IPublicTypeOnChangeOptions<INode>) => void): IPublicTypeDisposable { onChangeNodeChildren(
fn: (info: IPublicTypeOnChangeOptions<INode>) => void,
): IPublicTypeDisposable {
this.designer.editor?.eventBus.on(EDITOR_EVENT.NODE_CHILDREN_CHANGE, fn); this.designer.editor?.eventBus.on(EDITOR_EVENT.NODE_CHILDREN_CHANGE, fn);
return () => { return () => {
@ -401,14 +403,24 @@ IProject
/** /**
* *
*/ */
insertNode(parent: INode, thing: INode | IPublicTypeNodeData, at?: number | null, copy?: boolean): INode | null { insertNode(
parent: INode,
thing: INode | IPublicTypeNodeData,
at?: number | null,
copy?: boolean,
): INode | null {
return insertChild(parent, thing, at, copy); return insertChild(parent, thing, at, copy);
} }
/** /**
* *
*/ */
insertNodes(parent: INode, thing: INode[] | IPublicTypeNodeData[], at?: number | null, copy?: boolean) { insertNodes(
parent: INode,
thing: INode[] | IPublicTypeNodeData[],
at?: number | null,
copy?: boolean,
) {
return insertChildren(parent, thing, at, copy); return insertChildren(parent, thing, at, copy);
} }
@ -473,7 +485,7 @@ IProject
const drillDownNodeId = this._drillDownNode?.id; const drillDownNodeId = this._drillDownNode?.id;
runWithGlobalEventOff(() => { runWithGlobalEventOff(() => {
// TODO: 暂时用饱和式删除,原因是 Slot 节点并不是树节点,无法正常递归删除 // TODO: 暂时用饱和式删除,原因是 Slot 节点并不是树节点,无法正常递归删除
this.nodes.forEach(node => { this.nodes.forEach((node) => {
if (node.isRoot()) return; if (node.isRoot()) return;
this.internalRemoveAndPurgeNode(node, true); this.internalRemoveAndPurgeNode(node, true);
}); });
@ -486,14 +498,20 @@ IProject
}); });
} }
export(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Serilize): IPublicTypeRootSchema | undefined { export(
stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Serilize,
): IPublicTypeRootSchema | undefined {
stage = compatStage(stage); stage = compatStage(stage);
// 置顶只作用于 Page 的第一级子节点,目前还用不到里层的置顶;如果后面有需要可以考虑将这段写到 node-children 中的 export // 置顶只作用于 Page 的第一级子节点,目前还用不到里层的置顶;如果后面有需要可以考虑将这段写到 node-children 中的 export
const currentSchema = this.rootNode?.export<IPublicTypeRootSchema>(stage); const currentSchema = this.rootNode?.export<IPublicTypeRootSchema>(stage);
if (Array.isArray(currentSchema?.children) && currentSchema?.children?.length && currentSchema?.children?.length > 0) { if (
Array.isArray(currentSchema?.children) &&
currentSchema?.children?.length &&
currentSchema?.children?.length > 0
) {
const FixedTopNodeIndex = currentSchema?.children const FixedTopNodeIndex = currentSchema?.children
.filter(i => isPlainObject(i)) .filter((i) => isPlainObject(i))
.findIndex((i => (i as IPublicTypeNodeSchema).props?.__isTopFixed__)); .findIndex((i) => (i as IPublicTypeNodeSchema).props?.__isTopFixed__);
if (FixedTopNodeIndex > 0) { if (FixedTopNodeIndex > 0) {
const FixedTopNode = currentSchema?.children.splice(FixedTopNodeIndex, 1); const FixedTopNode = currentSchema?.children.splice(FixedTopNodeIndex, 1);
currentSchema?.children.unshift(FixedTopNode[0]); currentSchema?.children.unshift(FixedTopNode[0]);
@ -598,7 +616,11 @@ IProject
checkNesting( checkNesting(
dropTarget: INode, dropTarget: INode,
dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject, dragObject:
| IPublicTypeDragNodeObject
| IPublicTypeNodeSchema
| INode
| IPublicTypeDragNodeDataObject,
): boolean { ): boolean {
let items: Array<INode | IPublicTypeNodeSchema>; let items: Array<INode | IPublicTypeNodeSchema>;
if (isDragNodeDataObject(dragObject)) { if (isDragNodeDataObject(dragObject)) {
@ -611,7 +633,9 @@ IProject
console.warn('the dragObject is not in the correct type, dragObject:', dragObject); console.warn('the dragObject is not in the correct type, dragObject:', dragObject);
return true; return true;
} }
return items.every((item) => this.checkNestingDown(dropTarget, item) && this.checkNestingUp(dropTarget, item)); return items.every(
(item) => this.checkNestingDown(dropTarget, item) && this.checkNestingUp(dropTarget, item),
);
} }
/** /**
@ -619,7 +643,10 @@ IProject
* Will be deleted in version 2.0.0. * Will be deleted in version 2.0.0.
* Use checkNesting method instead. * Use checkNesting method instead.
*/ */
checkDropTarget(dropTarget: INode, dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject): boolean { checkDropTarget(
dropTarget: INode,
dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject,
): boolean {
let items: Array<INode | IPublicTypeNodeSchema>; let items: Array<INode | IPublicTypeNodeSchema>;
if (isDragNodeDataObject(dragObject)) { if (isDragNodeDataObject(dragObject)) {
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data]; items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
@ -686,7 +713,7 @@ IProject
/** /**
* @deprecated * @deprecated
*/ */
/* istanbul ignore next */ /* istanbul ignore next */
exportAddonData() { exportAddonData() {
const addons: { const addons: {
@ -722,10 +749,7 @@ IProject
} }
/* istanbul ignore next */ /* istanbul ignore next */
acceptRootNodeVisitor( acceptRootNodeVisitor(visitorName = 'default', visitorFn: (node: IRootNode) => any) {
visitorName = 'default',
visitorFn: (node: IRootNode) => any,
) {
let visitorResult = {}; let visitorResult = {};
if (!visitorName) { if (!visitorName) {
/* eslint-disable-next-line no-console */ /* eslint-disable-next-line no-console */
@ -753,7 +777,7 @@ IProject
// 组件去重 // 组件去重
const exsitingMap: { [componentName: string]: boolean } = {}; const exsitingMap: { [componentName: string]: boolean } = {};
for (const node of this._nodesMap.values()) { for (const node of this._nodesMap.values()) {
const { componentName } = node || {}; const componentName: string = node.componentName;
if (componentName === 'Slot') continue; if (componentName === 'Slot') continue;
if (!exsitingMap[componentName]) { if (!exsitingMap[componentName]) {
exsitingMap[componentName] = true; exsitingMap[componentName] = true;
@ -855,4 +879,4 @@ export function isPageSchema(obj: any): obj is IPublicTypePageSchema {
return obj?.componentName === 'Page'; return obj?.componentName === 'Page';
} }
export interface IDocumentModel extends DocumentModel {} export interface IDocumentModel extends DocumentModel {}

View File

@ -8,7 +8,7 @@ import { BuiltinSimulatorHostView } from '../builtin-simulator';
export class DocumentView extends Component<{ document: IDocumentModel }> { export class DocumentView extends Component<{ document: IDocumentModel }> {
render() { render() {
const { document } = this.props; const { document } = this.props;
const { simulatorProps } = document; const { simulatorProps } = document as any;
const Simulator = document.designer.simulatorComponent || BuiltinSimulatorHostView; const Simulator = document.designer.simulatorComponent || BuiltinSimulatorHostView;
return ( return (
<div <div

View File

@ -1,5 +1,15 @@
import { ReactElement } from 'react'; import { ReactElement } from 'react';
import { obx, computed, autorun, makeObservable, runInAction, wrapWithEventSwitch, action, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core'; import {
obx,
computed,
autorun,
makeObservable,
runInAction,
wrapWithEventSwitch,
action,
createModuleEventBus,
IEventBus,
} from '@alilc/lowcode-editor-core';
import { import {
IPublicTypeNodeSchema, IPublicTypeNodeSchema,
IPublicTypePropsMap, IPublicTypePropsMap,
@ -18,7 +28,7 @@ import {
IBaseModelNode, IBaseModelNode,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import { compatStage, isDOMText, isJSExpression, isNode, isNodeSchema } from '@alilc/lowcode-utils'; import { compatStage, isDOMText, isJSExpression, isNode, isNodeSchema } from '@alilc/lowcode-utils';
import { ISettingTopEntry } from '@alilc/lowcode-designer'; import { ISettingTopEntry } from '../../designer/setting/setting-top-entry';
import { Props, getConvertedExtraKey, IProps } from './props/props'; import { Props, getConvertedExtraKey, IProps } from './props/props';
import type { IDocumentModel } from '../document-model'; import type { IDocumentModel } from '../document-model';
import { NodeChildren, INodeChildren } from './node-children'; import { NodeChildren, INodeChildren } from './node-children';
@ -86,34 +96,38 @@ export interface IBaseNode extends Node {}
* isLocked * isLocked
* hidden * hidden
*/ */
export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema> implements Omit<IBaseModelNode< export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
IDocumentModel, implements
IBaseNode, Omit<
INodeChildren, IBaseModelNode<
IComponentMeta, IDocumentModel,
ISettingTopEntry, IBaseNode,
IProps, INodeChildren,
IProp, IComponentMeta,
IExclusiveGroup ISettingTopEntry,
>, IProps,
'isRoot' | IProp,
'isPage' | IExclusiveGroup
'isComponent' | >,
'isModal' | | 'isRoot'
'isSlot' | | 'isPage'
'isParental' | | 'isComponent'
'isLeaf' | | 'isModal'
'settingEntry' | | 'isSlot'
// 在内部的 node 模型中不存在 | 'isParental'
'getExtraPropValue' | | 'isLeaf'
'setExtraPropValue' | | 'settingEntry'
'exportSchema' | // 在内部的 node 模型中不存在
'visible' | | 'getExtraPropValue'
'importSchema' | | 'setExtraPropValue'
// 内外实现有差异 | 'exportSchema'
'isContainer' | | 'visible'
'isEmpty' | 'importSchema'
> { // 内外实现有差异
| 'isContainer'
| 'isEmpty'
>
{
private emitter: IEventBus; private emitter: IEventBus;
/** /**
@ -269,7 +283,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
pseudo: false, pseudo: false,
}; };
constructor(readonly document: IDocumentModel, nodeSchema: Schema) { constructor(
readonly document: IDocumentModel,
nodeSchema: Schema,
) {
makeObservable(this); makeObservable(this);
const { componentName, id, children, props, ...extras } = nodeSchema; const { componentName, id, children, props, ...extras } = nodeSchema;
this.id = document.nextId(id); this.id = document.nextId(id);
@ -282,10 +299,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
this.props = new Props(this, props, extras); this.props = new Props(this, props, extras);
this._children = new NodeChildren(this as INode, this.initialChildren(children)); this._children = new NodeChildren(this as INode, this.initialChildren(children));
this._children.internalInitParent(); this._children.internalInitParent();
this.props.merge( this.props.merge(this.upgradeProps(this.initProps(props || {})), this.upgradeProps(extras));
this.upgradeProps(this.initProps(props || {})),
this.upgradeProps(extras),
);
this.setupAutoruns(); this.setupAutoruns();
} }
@ -310,12 +324,18 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
*/ */
@action @action
private initBuiltinProps() { private initBuiltinProps() {
this.props.has(getConvertedExtraKey('hidden')) || this.props.add(false, getConvertedExtraKey('hidden')); this.props.has(getConvertedExtraKey('hidden')) ||
this.props.has(getConvertedExtraKey('title')) || this.props.add('', getConvertedExtraKey('title')); this.props.add(false, getConvertedExtraKey('hidden'));
this.props.has(getConvertedExtraKey('isLocked')) || this.props.add(false, getConvertedExtraKey('isLocked')); this.props.has(getConvertedExtraKey('title')) ||
this.props.has(getConvertedExtraKey('condition')) || this.props.add(true, getConvertedExtraKey('condition')); this.props.add('', getConvertedExtraKey('title'));
this.props.has(getConvertedExtraKey('conditionGroup')) || this.props.add('', getConvertedExtraKey('conditionGroup')); this.props.has(getConvertedExtraKey('isLocked')) ||
this.props.has(getConvertedExtraKey('loop')) || this.props.add(undefined, getConvertedExtraKey('loop')); this.props.add(false, getConvertedExtraKey('isLocked'));
this.props.has(getConvertedExtraKey('condition')) ||
this.props.add(true, getConvertedExtraKey('condition'));
this.props.has(getConvertedExtraKey('conditionGroup')) ||
this.props.add('', getConvertedExtraKey('conditionGroup'));
this.props.has(getConvertedExtraKey('loop')) ||
this.props.add(undefined, getConvertedExtraKey('loop'));
} }
@action @action
@ -340,7 +360,9 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
}); });
} }
private initialChildren(children: IPublicTypeNodeData | IPublicTypeNodeData[] | undefined): IPublicTypeNodeData[] { private initialChildren(
children: IPublicTypeNodeData | IPublicTypeNodeData[] | undefined,
): IPublicTypeNodeData[] {
const { initialChildren } = this.componentMeta.advanced; const { initialChildren } = this.componentMeta.advanced;
if (children == null) { if (children == null) {
@ -527,9 +549,13 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
} }
if (this.isSlot()) { if (this.isSlot()) {
this.parent.removeSlot(this); this.parent.removeSlot(this);
this.parent.children?.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true }); this.parent.children?.internalDelete(this, purge, useMutator, {
suppressRemoveEvent: true,
});
} else { } else {
this.parent.children?.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true }); this.parent.children?.internalDelete(this, purge, useMutator, {
suppressRemoveEvent: true,
});
} }
} }
} }
@ -550,7 +576,8 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
canSelect(): boolean { canSelect(): boolean {
const onSelectHook = this.componentMeta?.advanced?.callbacks?.onSelectHook; const onSelectHook = this.componentMeta?.advanced?.callbacks?.onSelectHook;
const canSelect = typeof onSelectHook === 'function' ? onSelectHook(this.internalToShellNode()!) : true; const canSelect =
typeof onSelectHook === 'function' ? onSelectHook(this.internalToShellNode()!) : true;
return canSelect; return canSelect;
} }
@ -845,7 +872,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/** /**
* schema * schema
*/ */
export<T = IPublicTypeNodeSchema>(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save, options: any = {}): T { export<T = IPublicTypeNodeSchema>(
stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save,
options: any = {},
): T {
stage = compatStage(stage); stage = compatStage(stage);
const baseSchema: any = { const baseSchema: any = {
componentName: this.componentName, componentName: this.componentName,
@ -999,12 +1029,11 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
*/ */
canPerformAction(actionName: string): boolean { canPerformAction(actionName: string): boolean {
const availableActions = const availableActions =
this.componentMeta?.availableActions?.filter((action: IPublicTypeComponentAction) => { this.componentMeta?.availableActions
const { condition } = action; ?.filter((action: IPublicTypeComponentAction) => {
return typeof condition === 'function' ? const { condition } = action;
condition(this) !== false : return typeof condition === 'function' ? condition(this) !== false : condition !== false;
condition !== false; })
})
.map((action: IPublicTypeComponentAction) => action.name) || []; .map((action: IPublicTypeComponentAction) => action.name) || [];
return availableActions.indexOf(actionName) >= 0; return availableActions.indexOf(actionName) >= 0;
@ -1061,7 +1090,9 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
return this.props; return this.props;
} }
onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable | undefined { onChildrenChange(
fn: (param?: { type: string; node: INode }) => void,
): IPublicTypeDisposable | undefined {
const wrappedFunc = wrapWithEventSwitch(fn); const wrappedFunc = wrapWithEventSwitch(fn);
return this.children?.onChange(wrappedFunc); return this.children?.onChange(wrappedFunc);
} }
@ -1131,7 +1162,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
const isContainerNode = this.isContainer(); const isContainerNode = this.isContainer();
const isEmptyNode = this.isEmpty(); const isEmptyNode = this.isEmpty();
const isRGLContainerNode = this.isRGLContainer; const isRGLContainerNode = this.isRGLContainer;
const isRGLNode = (this.getParent()?.isRGLContainer) as boolean; const isRGLNode = this.getParent()?.isRGLContainer as boolean;
const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode)); const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode));
let rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : null; let rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : null;
return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode }; return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode };
@ -1294,7 +1325,13 @@ export interface ISlotNode extends Node<IPublicTypeSlotSchema> {}
export interface IPageNode extends Node<IPublicTypePageSchema> {} export interface IPageNode extends Node<IPublicTypePageSchema> {}
export interface IComponentNode extends Node<IPublicTypeComponentSchema> {} export interface IComponentNode extends Node<IPublicTypeComponentSchema> {}
export interface IRootNode extends Node<IPublicTypePageSchema | IPublicTypeComponentSchema> {} export interface IRootNode extends Node<IPublicTypePageSchema | IPublicTypeComponentSchema> {}
export interface INode extends Node<IPublicTypePageSchema | IPublicTypeSlotSchema | IPublicTypeComponentSchema | IPublicTypeNodeSchema> {} export interface INode
extends Node<
| IPublicTypePageSchema
| IPublicTypeSlotSchema
| IPublicTypeComponentSchema
| IPublicTypeNodeSchema
> {}
export function isRootNode(node: INode): node is IRootNode { export function isRootNode(node: INode): node is IRootNode {
return node && node.isRootNode; return node && node.isRootNode;

View File

@ -48,7 +48,7 @@ export class Selection implements ISelection {
selectAll(ids: string[]) { selectAll(ids: string[]) {
const selectIds: string[] = []; const selectIds: string[] = [];
ids.forEach(d => { ids.forEach((d) => {
const node = this.doc.getNode(d); const node = this.doc.getNode(d);
if (node?.canSelect()) { if (node?.canSelect()) {
@ -125,7 +125,7 @@ export class Selection implements ISelection {
containsNode(node: INode, excludeRoot = false) { containsNode(node: INode, excludeRoot = false) {
for (const id of this._selected) { for (const id of this._selected) {
const parent = this.doc.getNode(id); const parent = this.doc.getNode(id);
if (excludeRoot && parent?.contains(this.doc.focusNode)) { if (excludeRoot && parent?.contains(this.doc.focusNode!)) {
continue; continue;
} }
if (parent?.contains(node)) { if (parent?.contains(node)) {
@ -157,7 +157,7 @@ export class Selection implements ISelection {
for (const id of this._selected) { for (const id of this._selected) {
const node = this.doc.getNode(id); const node = this.doc.getNode(id);
// 排除根节点 // 排除根节点
if (!node || (!includeRoot && node.contains(this.doc.focusNode))) { if (!node || (!includeRoot && node.contains(this.doc.focusNode!))) {
continue; continue;
} }
let i = nodes.length; let i = nodes.length;

1
packages/designer/src/module.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'ric-shim';

View File

@ -23,7 +23,25 @@ import {
const logger = getLogger({ level: 'warn', bizName: 'designer:pluginManager' }); const logger = getLogger({ level: 'warn', bizName: 'designer:pluginManager' });
// 保留的事件前缀 // 保留的事件前缀
const RESERVED_EVENT_PREFIX = ['designer', 'editor', 'skeleton', 'renderer', 'render', 'utils', 'plugin', 'engine', 'editor-core', 'engine-core', 'plugins', 'event', 'events', 'log', 'logger', 'ctx', 'context']; const RESERVED_EVENT_PREFIX = [
'designer',
'editor',
'skeleton',
'renderer',
'render',
'utils',
'plugin',
'engine',
'editor-core',
'engine-core',
'plugins',
'event',
'events',
'log',
'logger',
'ctx',
'context',
];
export class LowCodePluginManager implements ILowCodePluginManager { export class LowCodePluginManager implements ILowCodePluginManager {
private plugins: ILowCodePluginRuntime[] = []; private plugins: ILowCodePluginRuntime[] = [];
@ -35,7 +53,10 @@ export class LowCodePluginManager implements ILowCodePluginManager {
contextApiAssembler: ILowCodePluginContextApiAssembler; contextApiAssembler: ILowCodePluginContextApiAssembler;
constructor(contextApiAssembler: ILowCodePluginContextApiAssembler, readonly viewName = 'global') { constructor(
contextApiAssembler: ILowCodePluginContextApiAssembler,
readonly viewName = 'global',
) {
this.contextApiAssembler = contextApiAssembler; this.contextApiAssembler = contextApiAssembler;
} }
@ -79,24 +100,30 @@ export class LowCodePluginManager implements ILowCodePluginManager {
const isReservedPrefix = RESERVED_EVENT_PREFIX.find((item) => item === eventPrefix); const isReservedPrefix = RESERVED_EVENT_PREFIX.find((item) => item === eventPrefix);
if (isReservedPrefix) { if (isReservedPrefix) {
meta.eventPrefix = undefined; meta.eventPrefix = undefined;
logger.warn(`plugin ${pluginName} is trying to use ${eventPrefix} as event prefix, which is a reserved event prefix, please use another one`); logger.warn(
`plugin ${pluginName} is trying to use ${eventPrefix} as event prefix, which is a reserved event prefix, please use another one`,
);
} }
const ctx = this._getLowCodePluginContext({ pluginName, meta }); const ctx = this._getLowCodePluginContext({ pluginName, meta });
const customFilterValidOptions = engineConfig.get('customPluginFilterOptions', filterValidOptions); const customFilterValidOptions = engineConfig.get(
'customPluginFilterOptions',
filterValidOptions,
);
const pluginTransducer = engineConfig.get('customPluginTransducer', null); const pluginTransducer = engineConfig.get('customPluginTransducer', null);
const newPluginModel = pluginTransducer ? await pluginTransducer(pluginModel, ctx, options) : pluginModel; const newPluginModel = pluginTransducer
const newOptions = customFilterValidOptions(options, newPluginModel.meta?.preferenceDeclaration); ? await pluginTransducer(pluginModel, ctx, options)
: pluginModel;
const newOptions = customFilterValidOptions(
options,
newPluginModel.meta?.preferenceDeclaration,
);
const config = newPluginModel(ctx, newOptions); const config = newPluginModel(ctx, newOptions);
// compat the legacy way to declare pluginName // compat the legacy way to declare pluginName
// @ts-ignore // @ts-ignore
pluginName = pluginName || config.name; pluginName = pluginName || config.name;
invariant( invariant(pluginName, 'pluginConfigCreator.pluginName required', config);
pluginName,
'pluginConfigCreator.pluginName required',
config,
);
ctx.setPreference(pluginName, preferenceDeclaration); ctx.setPreference(pluginName, preferenceDeclaration!);
const allowOverride = registerOptions?.override === true; const allowOverride = registerOptions?.override === true;
@ -119,7 +146,9 @@ export class LowCodePluginManager implements ILowCodePluginManager {
const engineVersionExp = engines && engines.lowcodeEngine; const engineVersionExp = engines && engines.lowcodeEngine;
if (engineVersionExp && !this.isEngineVersionMatched(engineVersionExp)) { if (engineVersionExp && !this.isEngineVersionMatched(engineVersionExp)) {
throw new Error(`plugin ${pluginName} skipped, engine check failed, current engine version is ${engineConfig.get('ENGINE_VERSION')}, meta.engines.lowcodeEngine is ${engineVersionExp}`); throw new Error(
`plugin ${pluginName} skipped, engine check failed, current engine version is ${engineConfig.get('ENGINE_VERSION')}, meta.engines.lowcodeEngine is ${engineVersionExp}`,
);
} }
const plugin = new LowCodePluginRuntime(pluginName, this, config, meta); const plugin = new LowCodePluginRuntime(pluginName, this, config, meta);
@ -188,7 +217,9 @@ export class LowCodePluginManager implements ILowCodePluginManager {
return this.pluginsMap.size; return this.pluginsMap.size;
} }
getPluginPreference(pluginName: string): Record<string, IPublicTypePreferenceValueType> | null | undefined { getPluginPreference(
pluginName: string,
): Record<string, IPublicTypePreferenceValueType> | null | undefined {
if (!this.pluginPreference) { if (!this.pluginPreference) {
return null; return null;
} }

View File

@ -1,5 +1,8 @@
import { isPlainObject } from 'lodash'; import { isPlainObject } from 'lodash-es';
import { IPublicTypePluginRegisterOptions, IPublicTypePluginDeclaration } from '@alilc/lowcode-types'; import {
IPublicTypePluginRegisterOptions,
IPublicTypePluginDeclaration,
} from '@alilc/lowcode-types';
export function isValidPreferenceKey( export function isValidPreferenceKey(
key: string, key: string,
@ -17,10 +20,7 @@ export function isLowCodeRegisterOptions(opts: any): opts is IPublicTypePluginRe
return opts && ('autoInit' in opts || 'override' in opts); return opts && ('autoInit' in opts || 'override' in opts);
} }
export function filterValidOptions( export function filterValidOptions(opts: any, preferenceDeclaration: IPublicTypePluginDeclaration) {
opts: any,
preferenceDeclaration: IPublicTypePluginDeclaration,
) {
if (!opts || !isPlainObject(opts)) return opts; if (!opts || !isPlainObject(opts)) return opts;
const filteredOpts = {} as any; const filteredOpts = {} as any;
Object.keys(opts).forEach((key) => { Object.keys(opts).forEach((key) => {
@ -32,4 +32,4 @@ export function filterValidOptions(
} }
}); });
return filteredOpts; return filteredOpts;
} }

View File

@ -28,7 +28,7 @@ export function sequence({
} }
const node = tasks[name]; const node = tasks[name];
if (!node) { if (!node) {
missing.push([parentName, name].filter((d => !!d)).join('.')); missing.push([parentName, name].filter((d) => !!d).join('.'));
} else if (nest.indexOf(name) > -1) { } else if (nest.indexOf(name) > -1) {
nest.push(name); nest.push(name);
recursive.push(nest.slice(0)); recursive.push(nest.slice(0));
@ -64,7 +64,7 @@ export default function (tasks: ITaks, names: string[]) {
missing, missing,
recursive, recursive,
nest: [], nest: [],
}); } as any);
if (missing.length || recursive.length) { if (missing.length || recursive.length) {
results = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion results = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion

View File

@ -1,19 +1,7 @@
import React from 'react';
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import '../fixtures/window'; import '../fixtures/window';
import { Editor } from '@alilc/lowcode-editor-core';
import { Project } from '../../src/project/project';
import { Node } from '../../src/document/node/node';
import TestRenderer from 'react-test-renderer';
import { configure, render, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { Designer } from '../../src/designer/designer';
import formSchema from '../fixtures/schema/form';
import { getMockRenderer } from '../utils'; import { getMockRenderer } from '../utils';
import { isSimulatorRenderer } from '../../src/builtin-simulator/renderer'; import { isSimulatorRenderer } from '../../src/builtin-simulator/renderer';
describe('renderer 测试', () => { describe('renderer 测试', () => {
it('renderer', () => { it('renderer', () => {
expect(isSimulatorRenderer(getMockRenderer())).toBeTruthy(); expect(isSimulatorRenderer(getMockRenderer())).toBeTruthy();

View File

@ -1,5 +1,4 @@
import set from 'lodash/set'; import { set, cloneDeep } from 'lodash-es';
import cloneDeep from 'lodash/cloneDeep';
import '../../fixtures/window'; import '../../fixtures/window';
import { Project, IProject } from '../../../src/project/project'; import { Project, IProject } from '../../../src/project/project';
import { Node, INode } from '../../../src/document/node/node'; import { Node, INode } from '../../../src/document/node/node';
@ -22,7 +21,9 @@ jest.mock('../../../src/designer/designer', () => {
}, },
}; };
}, },
transformProps(props) { return props; }, transformProps(props) {
return props;
},
createSettingEntry: mockCreateSettingEntry, createSettingEntry: mockCreateSettingEntry,
postEvent() {}, postEvent() {},
}; };
@ -40,9 +41,7 @@ describe('schema 生成节点模型测试', () => {
let project: IProject; let project: IProject;
beforeEach(() => { beforeEach(() => {
project = new Project(designer, { project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
}); });
@ -56,8 +55,10 @@ describe('schema 生成节点模型测试', () => {
const ids = getIdsFromSchema(formSchema); const ids = getIdsFromSchema(formSchema);
const expectedNodeCnt = ids.length; const expectedNodeCnt = ids.length;
expect(nodesMap?.size).toBe(expectedNodeCnt); expect(nodesMap?.size).toBe(expectedNodeCnt);
ids.forEach(id => { ids.forEach((id) => {
expect(nodesMap?.get(id)?.componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName); expect(nodesMap?.get(id)?.componentName).toBe(
getNodeFromSchemaById(formSchema, id).componentName,
);
}); });
const pageNode = currentDocument?.getNode('page'); const pageNode = currentDocument?.getNode('page');
@ -66,7 +67,7 @@ describe('schema 生成节点模型测试', () => {
const exportSchema = currentDocument?.export(1); const exportSchema = currentDocument?.export(1);
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt); expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
nodesMap.forEach(node => { nodesMap.forEach((node) => {
// 触发 getter // 触发 getter
node.settingEntry; node.settingEntry;
}); });
@ -245,16 +246,14 @@ describe('schema 生成节点模型测试', () => {
expect(pageNode?.isPage()).toBe(true); expect(pageNode?.isPage()).toBe(true);
expect(pageNode?.isComponent()).toBe(false); expect(pageNode?.isComponent()).toBe(false);
expect(pageNode?.isSlot()).toBe(false); expect(pageNode?.isSlot()).toBe(false);
expect(pageNode?.title).toBe('hey, i\' a page!'); expect(pageNode?.title).toBe("hey, i' a page!");
}); });
describe('节点新增insertNode', () => { describe('节点新增insertNode', () => {
let project: Project; let project: Project;
beforeEach(() => { beforeEach(() => {
project = new Project(designer, { project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
}); });
@ -292,14 +291,19 @@ describe('schema 生成节点模型测试', () => {
const { currentDocument } = project; const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap; const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form'); const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, { formNode &&
componentName: 'TextInput', currentDocument?.insertNode(
id: 'nodeschema-id1', formNode,
props: { {
propA: 'haha', componentName: 'TextInput',
propB: 3, id: 'nodeschema-id1',
}, props: {
}, 0); propA: 'haha',
propB: 3,
},
},
0,
);
expect(nodesMap?.size).toBe(ids.length + 1); expect(nodesMap?.size).toBe(ids.length + 1);
expect(formNode?.children?.length).toBe(4); expect(formNode?.children?.length).toBe(4);
const insertedNode = formNode?.children?.get(0); const insertedNode = formNode?.children?.get(0);
@ -318,14 +322,19 @@ describe('schema 生成节点模型测试', () => {
const { currentDocument } = project; const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap; const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form'); const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, { formNode &&
componentName: 'TextInput', currentDocument?.insertNode(
id: 'nodeschema-id1', formNode,
props: { {
propA: 'haha', componentName: 'TextInput',
propB: 3, id: 'nodeschema-id1',
}, props: {
}, 1); propA: 'haha',
propB: 3,
},
},
1,
);
expect(nodesMap?.size).toBe(ids.length + 1); expect(nodesMap?.size).toBe(ids.length + 1);
expect(formNode?.children?.length).toBe(4); expect(formNode?.children?.length).toBe(4);
const insertedNode = formNode?.children?.get(1); const insertedNode = formNode?.children?.get(1);
@ -380,14 +389,15 @@ describe('schema 生成节点模型测试', () => {
const { currentDocument } = project; const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap; const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form'); const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, { formNode &&
componentName: 'TextInput', currentDocument?.insertNode(formNode, {
id: 'nodeschema-id1', componentName: 'TextInput',
props: { id: 'nodeschema-id1',
propA: 'haha', props: {
propB: 3, propA: 'haha',
}, propB: 3,
}); },
});
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput'); expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
expect(nodesMap?.size).toBe(ids.length + 1); expect(nodesMap?.size).toBe(ids.length + 1);
}); });
@ -398,14 +408,15 @@ describe('schema 生成节点模型测试', () => {
const { currentDocument } = project; const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap; const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form'); const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, { formNode &&
componentName: 'TextInput', currentDocument?.insertNode(formNode, {
id: 'nodeschema-id1', componentName: 'TextInput',
props: { id: 'nodeschema-id1',
propA: 'haha', props: {
propB: 3, propA: 'haha',
}, propB: 3,
}); },
});
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput'); expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
expect(nodesMap?.size).toBe(ids.length + 1); expect(nodesMap?.size).toBe(ids.length + 1);
}); });
@ -463,9 +474,7 @@ describe('schema 生成节点模型测试', () => {
let project: Project; let project: Project;
beforeEach(() => { beforeEach(() => {
project = new Project(designer, { project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
}); });
@ -477,22 +486,26 @@ describe('schema 生成节点模型测试', () => {
const formNode = nodesMap?.get('form') as Node; const formNode = nodesMap?.get('form') as Node;
const formNode2 = currentDocument?.getNode('form'); const formNode2 = currentDocument?.getNode('form');
expect(formNode).toEqual(formNode2); expect(formNode).toEqual(formNode2);
currentDocument?.insertNodes(formNode, [ currentDocument?.insertNodes(
{ formNode,
componentName: 'TextInput', [
props: { {
propA: 'haha2', componentName: 'TextInput',
propB: 3, props: {
propA: 'haha2',
propB: 3,
},
}, },
}, {
{ componentName: 'TextInput2',
componentName: 'TextInput2', props: {
props: { propA: 'haha',
propA: 'haha', propB: 3,
propB: 3, },
}, },
}, ],
], 1); 1,
);
expect(nodesMap?.size).toBe(ids.length + 2); expect(nodesMap?.size).toBe(ids.length + 2);
expect(formNode.children?.length).toBe(5); expect(formNode.children?.length).toBe(5);
const insertedNode1 = formNode.children?.get(1); const insertedNode1 = formNode.children?.get(1);
@ -552,11 +565,13 @@ describe('schema 生成节点模型测试', () => {
describe('block ❌ | component ❌ | slot ✅', () => { describe('block ❌ | component ❌ | slot ✅', () => {
it('基本的 slot 创建', () => { it('基本的 slot 创建', () => {
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot'); const formSchemaWithSlot = set(
cloneDeep(formSchema),
'children[0].children[0].props.title.type',
'JSSlot',
);
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchemaWithSlot],
formSchemaWithSlot,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();

View File

@ -1,5 +1,4 @@
import set from 'lodash/set'; import { set, cloneDeep } from 'lodash-es';
import cloneDeep from 'lodash/cloneDeep';
import '../../fixtures/window'; import '../../fixtures/window';
import { Project } from '../../../src/project/project'; import { Project } from '../../../src/project/project';
import { Designer } from '../../../src/designer/designer'; import { Designer } from '../../../src/designer/designer';
@ -21,7 +20,9 @@ jest.mock('../../../src/designer/designer', () => {
}, },
}; };
}, },
transformProps(props) { return props; }, transformProps(props) {
return props;
},
createSettingEntry: mockCreateSettingEntry, createSettingEntry: mockCreateSettingEntry,
postEvent() {}, postEvent() {},
}; };
@ -37,9 +38,7 @@ beforeAll(() => {
describe('节点模型删除测试', () => { describe('节点模型删除测试', () => {
it('删除叶子节点', () => { it('删除叶子节点', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -62,12 +61,13 @@ describe('节点模型删除测试', () => {
}); });
it('删除叶子节点,带有 slot', () => { it('删除叶子节点,带有 slot', () => {
const formSchemaWithSlot = set(cloneDeep(formSchema), const formSchemaWithSlot = set(
'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot'); cloneDeep(formSchema),
'children[1].children[0].children[2].children[1].props.greeting.type',
'JSSlot',
);
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchemaWithSlot],
formSchemaWithSlot,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -84,9 +84,7 @@ describe('节点模型删除测试', () => {
it('删除分支节点', () => { it('删除分支节点', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -102,12 +100,13 @@ describe('节点模型删除测试', () => {
}); });
it('删除分支节点,带有 slot', () => { it('删除分支节点,带有 slot', () => {
const formSchemaWithSlot = set(cloneDeep(formSchema), const formSchemaWithSlot = set(
'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot'); cloneDeep(formSchema),
'children[1].children[0].children[2].children[1].props.greeting.type',
'JSSlot',
);
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchemaWithSlot],
formSchemaWithSlot,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();

View File

@ -1,11 +1,7 @@
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import '../fixtures/window'; import '../fixtures/window';
import { Project } from '../../src/project/project'; import { Project } from '../../src/project/project';
import { Node } from '../../src/document/node/node';
import { Designer } from '../../src/designer/designer'; import { Designer } from '../../src/designer/designer';
import formSchema from '../fixtures/schema/form'; import formSchema from '../fixtures/schema/form';
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
const mockCreateSettingEntry = jest.fn(); const mockCreateSettingEntry = jest.fn();
jest.mock('../../src/designer/designer', () => { jest.mock('../../src/designer/designer', () => {
@ -22,7 +18,9 @@ jest.mock('../../src/designer/designer', () => {
}, },
}; };
}, },
transformProps(props) { return props; }, transformProps(props) {
return props;
},
createSettingEntry: mockCreateSettingEntry, createSettingEntry: mockCreateSettingEntry,
postEvent() {}, postEvent() {},
}; };
@ -38,9 +36,7 @@ beforeAll(() => {
describe('选择区测试', () => { describe('选择区测试', () => {
it('常规方法', () => { it('常规方法', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -92,9 +88,7 @@ describe('选择区测试', () => {
it('add 方法', () => { it('add 方法', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -124,9 +118,7 @@ describe('选择区测试', () => {
it('selectAll 包含不存在的 id', () => { it('selectAll 包含不存在的 id', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -140,9 +132,7 @@ describe('选择区测试', () => {
it('dispose 方法 - 选中的节点没有被删除的', () => { it('dispose 方法 - 选中的节点没有被删除的', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -160,9 +150,7 @@ describe('选择区测试', () => {
it('containsNode 方法', () => { it('containsNode 方法', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -190,9 +178,7 @@ describe('选择区测试', () => {
it('containsNode 方法 - excludeRoot: true', () => { it('containsNode 方法 - excludeRoot: true', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -213,9 +199,7 @@ describe('选择区测试', () => {
it('containsNode 方法 - excludeRoot: true', () => { it('containsNode 方法 - excludeRoot: true', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -239,9 +223,7 @@ describe('选择区测试', () => {
it('getNodes', () => { it('getNodes', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
const { currentDocument } = project; const { currentDocument } = project;
@ -255,9 +237,7 @@ describe('选择区测试', () => {
it('getTopNodes - BeforeOrAfter', () => { it('getTopNodes - BeforeOrAfter', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
const { currentDocument } = project; const { currentDocument } = project;
@ -269,9 +249,7 @@ describe('选择区测试', () => {
}); });
it('getTopNodes', () => { it('getTopNodes', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
const { currentDocument } = project; const { currentDocument } = project;

View File

@ -1,5 +1,4 @@
import set from 'lodash/set'; import { set, cloneDeep } from 'lodash-es';
import cloneDeep from 'lodash/cloneDeep';
import '../fixtures/window'; import '../fixtures/window';
import { Editor } from '@alilc/lowcode-editor-core'; import { Editor } from '@alilc/lowcode-editor-core';
import { Project } from '../../src/project/project'; import { Project } from '../../src/project/project';
@ -22,7 +21,9 @@ jest.mock('../../src/designer/designer', () => {
}, },
}; };
}, },
transformProps(props) { return props; }, transformProps(props) {
return props;
},
createSettingEntry: mockCreateSettingEntry, createSettingEntry: mockCreateSettingEntry,
postEvent() {}, postEvent() {},
}; };
@ -44,9 +45,7 @@ describe('schema 生成节点模型测试', () => {
it('基本的节点模型初始化,模型导出,初始化传入 schema', () => { it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -55,13 +54,15 @@ describe('schema 生成节点模型测试', () => {
const ids = getIdsFromSchema(formSchema); const ids = getIdsFromSchema(formSchema);
const expectedNodeCnt = ids.length; const expectedNodeCnt = ids.length;
expect(nodesMap.size).toBe(expectedNodeCnt); expect(nodesMap.size).toBe(expectedNodeCnt);
ids.forEach(id => { ids.forEach((id) => {
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName); expect(nodesMap.get(id).componentName).toBe(
getNodeFromSchemaById(formSchema, id).componentName,
);
}); });
const exportSchema = currentDocument?.export(1); const exportSchema = currentDocument?.export(1);
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt); expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
nodesMap.forEach(node => { nodesMap.forEach((node) => {
// 触发 getter // 触发 getter
node.settingEntry; node.settingEntry;
}); });
@ -70,9 +71,7 @@ describe('schema 生成节点模型测试', () => {
it('onSimulatorReady works', () => { it('onSimulatorReady works', () => {
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchema],
formSchema,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -103,23 +102,26 @@ describe('schema 生成节点模型测试', () => {
const project = new Project(designer); const project = new Project(designer);
expect(project).toBeTruthy(); expect(project).toBeTruthy();
// trigger autoOpen case // trigger autoOpen case
project.load({ project.load(
componentsTree: [ {
formSchema, componentsTree: [formSchema],
], },
}, true); true,
);
const { currentDocument } = project; const { currentDocument } = project;
const { nodesMap } = currentDocument; const { nodesMap } = currentDocument;
const ids = getIdsFromSchema(formSchema); const ids = getIdsFromSchema(formSchema);
const expectedNodeCnt = ids.length; const expectedNodeCnt = ids.length;
expect(nodesMap.size).toBe(expectedNodeCnt); expect(nodesMap.size).toBe(expectedNodeCnt);
ids.forEach(id => { ids.forEach((id) => {
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName); expect(nodesMap.get(id).componentName).toBe(
getNodeFromSchemaById(formSchema, id).componentName,
);
}); });
const exportSchema = currentDocument?.export(1); const exportSchema = currentDocument?.export(1);
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt); expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
nodesMap.forEach(node => { nodesMap.forEach((node) => {
// 触发 getter // 触发 getter
node.settingEntry; node.settingEntry;
}); });
@ -129,31 +131,34 @@ describe('schema 生成节点模型测试', () => {
const project = new Project(designer); const project = new Project(designer);
expect(project).toBeTruthy(); expect(project).toBeTruthy();
// trigger autoOpen case // trigger autoOpen case
project.load({ project.load(
componentsTree: [ {
{ componentsTree: [
...formSchema, {
fileName: 'demoFile1', ...formSchema,
fileName: 'demoFile1',
},
{
...formSchema,
fileName: 'demoFile2',
},
],
config: {
layout: {
props: {
tabBar: {
items: [
{
path: '/demoFile2',
},
],
},
},
},
}, },
{ },
...formSchema, true,
fileName: 'demoFile2', );
}
],
config: {
layout: {
props: {
tabBar: {
items: [
{
path: '/demoFile2',
}
],
}
}
}
}
}, true);
const { currentDocument } = project; const { currentDocument } = project;
expect(currentDocument.fileName).toBe('demoFile2'); expect(currentDocument.fileName).toBe('demoFile2');
}); });
@ -162,23 +167,25 @@ describe('schema 生成节点模型测试', () => {
const project = new Project(designer); const project = new Project(designer);
expect(project).toBeTruthy(); expect(project).toBeTruthy();
// trigger autoOpen case // trigger autoOpen case
project.load({ project.load(
componentsTree: [ {
{ componentsTree: [
...formSchema, {
fileName: 'demoFile1', ...formSchema,
}, fileName: 'demoFile1',
{ },
...formSchema, {
fileName: 'demoFile2', ...formSchema,
} fileName: 'demoFile2',
], },
}, 'demoFile2'); ],
},
'demoFile2',
);
const { currentDocument } = project; const { currentDocument } = project;
expect(currentDocument.fileName).toBe('demoFile2'); expect(currentDocument.fileName).toBe('demoFile2');
}); });
it('setSchema works', () => { it('setSchema works', () => {
const project = new Project(designer); const project = new Project(designer);
project.open(); project.open();
@ -204,13 +211,15 @@ describe('schema 生成节点模型测试', () => {
const ids = getIdsFromSchema(formSchema); const ids = getIdsFromSchema(formSchema);
const expectedNodeCnt = ids.length; const expectedNodeCnt = ids.length;
expect(nodesMap.size).toBe(expectedNodeCnt); expect(nodesMap.size).toBe(expectedNodeCnt);
ids.forEach(id => { ids.forEach((id) => {
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName); expect(nodesMap.get(id).componentName).toBe(
getNodeFromSchemaById(formSchema, id).componentName,
);
}); });
const exportSchema = currentDocument?.export(1); const exportSchema = currentDocument?.export(1);
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt); expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
nodesMap.forEach(node => { nodesMap.forEach((node) => {
// 触发 getter // 触发 getter
node.settingEntry; node.settingEntry;
}); });
@ -271,11 +280,13 @@ describe('schema 生成节点模型测试', () => {
describe('block ❌ | component ❌ | slot ✅', () => { describe('block ❌ | component ❌ | slot ✅', () => {
it('基本的节点模型初始化,模型导出,初始化传入 schema', () => { it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot'); const formSchemaWithSlot = set(
cloneDeep(formSchema),
'children[0].children[0].props.title.type',
'JSSlot',
);
const project = new Project(designer, { const project = new Project(designer, {
componentsTree: [ componentsTree: [formSchemaWithSlot],
formSchemaWithSlot,
],
}); });
project.open(); project.open();
expect(project).toBeTruthy(); expect(project).toBeTruthy();
@ -290,7 +301,5 @@ describe('schema 生成节点模型测试', () => {
}); });
}); });
describe.skip('多 document 测试', () => { describe.skip('多 document 测试', () => {});
});
}); });

View File

@ -1,4 +1,4 @@
import lodashSet from 'lodash/set'; import { set as lodashSet } from 'lodash-es';
export function set(obj: any, path: any, val: any) { export function set(obj: any, path: any, val: any) {
if (typeof path === 'string' && path.startsWith('prototype')) { if (typeof path === 'string' && path.startsWith('prototype')) {
@ -17,7 +17,7 @@ export function set(obj: any, path: any, val: any) {
} }
export function delay(ms) { export function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
} }
export function delayObxTick() { export function delayObxTick() {

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "temp",
"stripInternal": true,
"paths": {}
}
}

View File

@ -1,12 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "dist"
"types": ["node","jest"]
}, },
"include": [ "include": ["src"]
"./src/",
"./tests/"
],
"exclude": ["**/lib", "**/es", "node_modules"]
} }

View File

@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import { resolve } from 'node:path';
import react from '@vitejs/plugin-react';
import { devDependencies, peerDependencies } from './package.json';
const externals = [...Object.keys(peerDependencies), ...Object.keys(devDependencies)];
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(import.meta.dirname, 'src/index.ts'),
name: 'LowCodeDesigner',
formats: ['es', 'cjs'],
// the proper extensions will be added
fileName: 'designer',
},
rollupOptions: {
external: externals,
},
},
plugins: [react()],
});

View File

View File

@ -3,18 +3,30 @@
"version": "2.0.0-beta.0", "version": "2.0.0-beta.0",
"description": "Core Api for Ali lowCode engine", "description": "Core Api for Ali lowCode engine",
"license": "MIT", "license": "MIT",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module", "type": "module",
"main": "dist/editorCore.js",
"module": "dist/editorCore.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/editorCore.js",
"types": "./dist/index.d.ts"
}
},
"sideEffects": [
"*.css",
"*.less"
],
"files": [ "files": [
"lib", "dist",
"es" "src",
"package.json"
], ],
"scripts": { "scripts": {
"build": "tsc", "build": "vite build",
"test": "build-scripts test --config build.test.json", "build-dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
"test:cov": "build-scripts test --config build.test.json --jest-coverage" "test": "vitest",
"test:cov": ""
}, },
"dependencies": { "dependencies": {
"@alifd/next": "^1.27.8", "@alifd/next": "^1.27.8",
@ -29,16 +41,18 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"store": "^2.0.12", "store": "^2.0.12",
"strict-event-emitter-types": "^2.0.0" "strict-event-emitter-types": "^2.0.0",
"events": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {
"@alilc/lowcode-datasource-types": "^1.0.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/react": "^18.2.0", "@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0", "@types/react-dom": "^18.2.0",
"@types/store": "^2.0.2" "@types/store": "^2.0.2",
"less": "^4.2.0"
}, },
"peerDependencies": { "peerDependencies": {
"@alifd/next": "^1.27.8",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },

View File

@ -1,5 +1,3 @@
/* eslint-disable no-console */
/* eslint-disable max-len */
import { StrictEventEmitter } from 'strict-event-emitter-types'; import { StrictEventEmitter } from 'strict-event-emitter-types';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { EventBus, IEventBus } from './event-bus'; import { EventBus, IEventBus } from './event-bus';
@ -39,6 +37,7 @@ const AssetsCache: {
[key: string]: IPublicTypeRemoteComponentDescription; [key: string]: IPublicTypeRemoteComponentDescription;
} = {}; } = {};
// @ts-ignore
export declare interface Editor extends StrictEventEmitter<EventEmitter, GlobalEvent.EventConfig> { export declare interface Editor extends StrictEventEmitter<EventEmitter, GlobalEvent.EventConfig> {
addListener(event: string | symbol, listener: (...args: any[]) => void): this; addListener(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this; once(event: string | symbol, listener: (...args: any[]) => void): this;

View File

@ -1,5 +1,6 @@
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { configure } from 'mobx'; import { configure } from 'mobx';
import * as mobx from 'mobx';
configure({ enforceActions: 'never' }); configure({ enforceActions: 'never' });
@ -19,5 +20,4 @@ export {
} from 'mobx'; } from 'mobx';
export type { IReactionDisposer, IReactionPublic, IReactionOptions } from 'mobx'; export type { IReactionDisposer, IReactionPublic, IReactionOptions } from 'mobx';
export * as mobx from 'mobx'; export { observer, mobx };
export { observer };

View File

@ -106,7 +106,11 @@ export class TipItem extends Component {
render() { render() {
const tip: IPublicTypeTipConfig = tipHandler.tip || ({} as any); const tip: IPublicTypeTipConfig = tipHandler.tip || ({} as any);
const className = classNames('lc-tip', tip.className, tip && tip.theme ? `lc-theme-${tip.theme}` : null); const className = classNames(
'lc-tip',
tip.className,
tip && tip.theme ? `lc-theme-${tip.theme}` : null,
);
this.originClassName = className; this.originClassName = className;
@ -118,7 +122,7 @@ export class TipItem extends Component {
}} }}
> >
<i className="lc-arrow" /> <i className="lc-arrow" />
<div className="lc-tip-content">{intl(tip.children)}</div> <div className="lc-tip-content">{intl((tip as any).children)}</div>
</div> </div>
); );
} }

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "temp",
"stripInternal": true,
"paths": {}
}
}

View File

@ -1,10 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist"
"paths": {
"@alilc/lowcode-*": ["packages/*"]
}
}, },
"include": ["src"] "include": ["src"]
} }

View File

@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import { resolve } from 'node:path';
import react from '@vitejs/plugin-react';
import { devDependencies, peerDependencies } from './package.json';
const externals = [...Object.keys(peerDependencies), ...Object.keys(devDependencies)];
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(import.meta.dirname, 'src/index.ts'),
name: 'LowCodeEditorCore',
formats: ['es'],
// the proper extensions will be added
fileName: 'editorCore',
},
rollupOptions: {
external: externals,
},
},
plugins: [react()],
});

View File

View File

@ -1,9 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce",
"build-plugin-fusion",
["build-plugin-moment-locales", {
"locales": ["zh-cn"]
}]
]
}

View File

@ -1,9 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce",
"@alilc/lowcode-test-mate/plugin/index.ts"
],
"babelPlugins": [
["@babel/plugin-proposal-private-property-in-object", { "loose": true }]
]
}

View File

@ -1,29 +0,0 @@
const fs = require('fs');
const { join } = require('path');
const esModules = [].join('|');
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
const jestConfig = {
// transform: {
// '^.+\\.[jt]sx?$': 'babel-jest',
// // '^.+\\.(ts|tsx)$': 'ts-jest',
// // '^.+\\.(js|jsx)$': 'babel-jest',
// },
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
collectCoverage: false,
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!**/node_modules/**',
'!**/vendor/**',
],
};
// 只对本仓库内的 pkg 做 mapping
jestConfig.moduleNameMapper = {};
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
module.exports = jestConfig;

View File

@ -1,38 +1,55 @@
{ {
"name": "@alilc/lowcode-editor-skeleton", "name": "@alilc/lowcode-editor-skeleton",
"version": "1.3.2", "version": "2.0.0-beta.0",
"description": "alibaba lowcode editor skeleton", "description": "alibaba lowcode editor skeleton",
"main": "lib/index.js", "type": "module",
"module": "es/index.js", "main": "dist/designer.cjs",
"stylePath": "style.js", "module": "dist/designer.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/designer.js",
"require": "./dist/designer.cjs",
"types": "./dist/index.d.ts"
}
},
"sideEffects": [
"*.css"
],
"files": [ "files": [
"lib", "dist",
"es" "src",
"package.json"
], ],
"scripts": { "scripts": {
"test": "build-scripts test --config build.test.json", "build": "vite build",
"build": "build-scripts build" "build-dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
"test": "vitest"
}, },
"keywords": [ "keywords": [
"lowcode", "lowcode",
"editor" "editor"
], ],
"dependencies": { "dependencies": {
"@alifd/next": "^1.20.12", "@alifd/next": "^1.27.8",
"@alilc/lowcode-designer": "1.3.2", "@alilc/lowcode-designer": "workspace:*",
"@alilc/lowcode-editor-core": "1.3.2", "@alilc/lowcode-editor-core": "workspace:*",
"@alilc/lowcode-types": "1.3.2", "@alilc/lowcode-types": "workspace:*",
"@alilc/lowcode-utils": "1.3.2", "@alilc/lowcode-utils": "workspace:*",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"react": "^16.8.1", "lodash-es": "^4.17.21",
"react-dom": "^16.8.1" "react": "^18.2.0",
"react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.3", "@types/lodash-es": "^4.17.12",
"@types/react": "^16.9.13", "@types/react": "^18.2.0",
"@types/react-dom": "^16.9.4", "@types/react-dom": "^18.2.0"
"build-plugin-fusion": "^0.1.0", },
"build-plugin-moment-locales": "^0.1.0" "peerDependencies": {
"@alifd/next": "^1.27.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

@ -1,6 +1,5 @@
/* eslint-disable react/no-unused-prop-types */ import { Component, ErrorInfo, MouseEvent, type ReactNode } from 'react';
import { Component, ErrorInfo, MouseEvent } from 'react'; import { isObject } from 'lodash-es';
import { isObject } from 'lodash';
import classNames from 'classnames'; import classNames from 'classnames';
import { Icon } from '@alifd/next'; import { Icon } from '@alifd/next';
import { Title } from '@alilc/lowcode-editor-core'; import { Title } from '@alilc/lowcode-editor-core';
@ -25,6 +24,7 @@ export interface FieldProps {
tip?: any; tip?: any;
onExpandChange?: (expandState: boolean) => void; onExpandChange?: (expandState: boolean) => void;
onClear?: () => void; onClear?: () => void;
children?: ReactNode;
} }
export class Field extends Component<FieldProps> { export class Field extends Component<FieldProps> {
@ -116,22 +116,37 @@ export class Field extends Component<FieldProps> {
getTipContent(propName: string, tip?: any): any { getTipContent(propName: string, tip?: any): any {
let tipContent = ( let tipContent = (
<div> <div>
<div>{intl('Attribute: ')}{propName}</div> <div>
{intl('Attribute: ')}
{propName}
</div>
</div> </div>
); );
if (isObject(tip)) { if (isObject(tip)) {
tipContent = ( tipContent = (
<div> <div>
<div>{intl('Attribute: ')}{propName}</div> <div>
<div>{intl('Description: ')}{(tip as any).content}</div> {intl('Attribute: ')}
{propName}
</div>
<div>
{intl('Description: ')}
{(tip as any).content}
</div>
</div> </div>
); );
} else if (tip) { } else if (tip) {
tipContent = ( tipContent = (
<div> <div>
<div>{intl('Attribute: ')}{propName}</div> <div>
<div>{intl('Description: ')}{tip}</div> {intl('Attribute: ')}
{propName}
</div>
<div>
{intl('Description: ')}
{tip}
</div>
</div> </div>
); );
} }
@ -149,7 +164,7 @@ export class Field extends Component<FieldProps> {
return null; return null;
} }
const { className, children, meta, title, valueState, name: propName, tip } = this.props; const { className, children, meta, title, name: propName, tip } = this.props;
const { display, collapsed } = this.state; const { display, collapsed } = this.state;
const isAccordion = display === 'accordion'; const isAccordion = display === 'accordion';
let hostName = ''; let hostName = '';
@ -167,22 +182,23 @@ export class Field extends Component<FieldProps> {
})} })}
id={id} id={id}
> >
{ {display !== 'plain' && (
display !== 'plain' && ( <div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}>
<div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}> <div className="lc-field-title">
<div className="lc-field-title"> {createValueState()}
{createValueState(valueState, this.handleClear)} <Title title={title || ''} onClick={this.clickHandler} />
<Title <InlineTip position="top">{tipContent}</InlineTip>
title={title || ''}
onClick={this.clickHandler}
/>
<InlineTip position="top">{tipContent}</InlineTip>
</div>
{isAccordion && <Icon className="lc-field-icon" type="arrow-up" size="xs" />}
</div> </div>
) {isAccordion && <Icon className="lc-field-icon" type="arrow-up" size="xs" />}
} </div>
<div key="body" ref={(shell) => { this.body = shell; }} className="lc-field-body"> )}
<div
key="body"
ref={(shell) => {
this.body = shell;
}}
className="lc-field-body"
>
{children} {children}
</div> </div>
</div> </div>

View File

@ -8,18 +8,17 @@ export interface PopupExtProps {
width?: number; width?: number;
hasMask?: boolean; hasMask?: boolean;
trigger?: ReactNode; trigger?: ReactNode;
canCloseByOutSideClick?: boolean canCloseByOutSideClick?: boolean;
className?: string; className?: string;
safeNode?: string[]; safeNode?: string[];
} }
interface PopupProps extends PopupExtProps{ interface PopupProps extends PopupExtProps {
content?: ReactNode, content?: ReactNode;
title?: ReactNode, title?: ReactNode;
actionKey?: string actionKey?: string;
} }
export const PopupContext = createContext<PopupPipe>({} as any); export const PopupContext = createContext<PopupPipe>({} as any);
export class PopupPipe { export class PopupPipe {
@ -84,6 +83,7 @@ export default class PopupService extends Component<{
actionKey?: string; actionKey?: string;
safeId?: string; safeId?: string;
popupContainer?: string; popupContainer?: string;
children?: ReactNode;
}> { }> {
private popupPipe = this.props.popupPipe || new PopupPipe(); private popupPipe = this.props.popupPipe || new PopupPipe();
@ -103,9 +103,9 @@ export default class PopupService extends Component<{
} }
interface StateType extends PopupProps { interface StateType extends PopupProps {
visible?: boolean, visible?: boolean;
offsetX?: number, offsetX?: number;
pos?: {top: number, height: number} pos?: { top: number; height: number };
} }
export class PopupContent extends PureComponent<{ safeId?: string; popupContainer?: string }> { export class PopupContent extends PureComponent<{ safeId?: string; popupContainer?: string }> {
static contextType = PopupContext; static contextType = PopupContext;
@ -153,7 +153,18 @@ export class PopupContent extends PureComponent<{ safeId?: string; popupContaine
}; };
render() { render() {
const { content, visible, title, actionKey, pos, offsetX, width = 360, hasMask = false, canCloseByOutSideClick = true, safeNode = [] } = this.state; const {
content,
visible,
title,
actionKey,
pos,
offsetX,
width = 360,
hasMask = false,
canCloseByOutSideClick = true,
safeNode = [],
} = this.state;
if (!visible) { if (!visible) {
return null; return null;
} }
@ -171,7 +182,7 @@ export class PopupContent extends PureComponent<{ safeId?: string; popupContaine
visible={visible} visible={visible}
offset={[offsetX, 0]} offset={[offsetX, 0]}
hasMask={hasMask} hasMask={hasMask}
onVisibleChange={(_visible, type) => { onVisibleChange={(_visible: boolean, type: string) => {
if (avoidLaterHidden) { if (avoidLaterHidden) {
return; return;
} }
@ -186,15 +197,12 @@ export class PopupContent extends PureComponent<{ safeId?: string; popupContaine
onClose={this.onClose} onClose={this.onClose}
id={this.props.safeId} id={this.props.safeId}
safeNode={[id, ...safeNode]} safeNode={[id, ...safeNode]}
closeable
container={this.props.popupContainer} container={this.props.popupContainer}
> >
<div className="lc-ballon-title">{title}</div> <div className="lc-ballon-title">{title}</div>
<div className="lc-ballon-content"> <div className="lc-ballon-content">
<PopupService actionKey={actionKey} safeId={id} popupContainer={this.popupContainerId}> <PopupService actionKey={actionKey} safeId={id} popupContainer={this.popupContainerId}>
<ConfigProvider popupContainer={this.popupContainerId}> <ConfigProvider popupContainer={this.popupContainerId}>{content}</ConfigProvider>
{content}
</ConfigProvider>
</PopupService> </PopupService>
</div> </div>
<div id={this.popupContainerId} /> <div id={this.popupContainerId} />

View File

@ -1,5 +1,13 @@
import { Node, Designer, Selection, SettingTopEntry } from '@alilc/lowcode-designer'; import { Node, Designer, Selection, SettingTopEntry } from '@alilc/lowcode-designer';
import { Editor, obx, computed, makeObservable, action, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import {
Editor,
obx,
computed,
makeObservable,
action,
IEventBus,
createModuleEventBus,
} from '@alilc/lowcode-editor-core';
function generateSessionId(nodes: Node[]) { function generateSessionId(nodes: Node[]) {
return nodes return nodes
@ -72,9 +80,9 @@ export class SettingsMain {
// 当节点只有一个时,复用 node 上挂载的 settingEntry不会产生平行的两个实例这样在整个系统中对 // 当节点只有一个时,复用 node 上挂载的 settingEntry不会产生平行的两个实例这样在整个系统中对
// 某个节点操作的 SettingTopEntry 只有一个实例,后续的 getProp() 也会拿到相同的 SettingField 实例 // 某个节点操作的 SettingTopEntry 只有一个实例,后续的 getProp() 也会拿到相同的 SettingField 实例
if (nodes.length === 1) { if (nodes.length === 1) {
this._settings = nodes[0].settingEntry; this._settings = nodes[0].settingEntry as any;
} else { } else {
this._settings = this.designer.createSettingEntry(nodes); this._settings = this.designer.createSettingEntry(nodes) as any;
} }
} }

View File

@ -1,9 +1,25 @@
import { Component, MouseEvent, Fragment, ReactNode } from 'react'; import { Component, MouseEvent, Fragment, ReactNode } from 'react';
import { shallowIntl, observer, obx, engineConfig, runInAction } from '@alilc/lowcode-editor-core'; import { shallowIntl, observer, obx, engineConfig, runInAction } from '@alilc/lowcode-editor-core';
import { createContent, isJSSlot, isSetterConfig, shouldUseVariableSetter } from '@alilc/lowcode-utils'; import {
import { Skeleton, Stage } from '@alilc/lowcode-editor-skeleton'; createContent,
import { IPublicApiSetters, IPublicTypeCustomView, IPublicTypeDynamicProps } from '@alilc/lowcode-types'; isJSSlot,
import { ISettingEntry, IComponentMeta, ISettingField, isSettingField, ISettingTopEntry } from '@alilc/lowcode-designer'; isSetterConfig,
shouldUseVariableSetter,
} from '@alilc/lowcode-utils';
import { Skeleton } from '../../skeleton';
import { Stage } from '../../widget/stage';
import {
IPublicApiSetters,
IPublicTypeCustomView,
IPublicTypeDynamicProps,
} from '@alilc/lowcode-types';
import {
ISettingEntry,
IComponentMeta,
ISettingField,
isSettingField,
ISettingTopEntry,
} from '@alilc/lowcode-designer';
import { createField } from '../field'; import { createField } from '../field';
import PopupService, { PopupPipe } from '../popup'; import PopupService, { PopupPipe } from '../popup';
import { SkeletonContext } from '../../context'; import { SkeletonContext } from '../../context';
@ -24,10 +40,14 @@ function isStandardComponent(componentMeta: IComponentMeta | null) {
*/ */
function isInitialValueNotEmpty(initialValue: any) { function isInitialValueNotEmpty(initialValue: any) {
if (isJSSlot(initialValue)) { if (isJSSlot(initialValue)) {
// @ts-ignore visible 为 false 代表默认不展示 return (
return initialValue.visible !== false && Array.isArray(initialValue.value) && initialValue.value.length > 0; // @ts-ignore visible 为 false 代表默认不展示
initialValue.visible !== false &&
Array.isArray(initialValue.value) &&
initialValue.value.length > 0
);
} }
return (initialValue !== undefined && initialValue !== null); return initialValue !== undefined && initialValue !== null;
} }
type SettingFieldViewProps = { field: ISettingField }; type SettingFieldViewProps = { field: ISettingField };
@ -61,7 +81,11 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
stages.add({ stages.add({
type: 'Widget', type: 'Widget',
name: stageName, name: stageName,
content: <Fragment>{field.items.map((item, index) => createSettingFieldView(item, field, index))}</Fragment>, content: (
<Fragment>
{field.items.map((item, index) => createSettingFieldView(item, field, index))}
</Fragment>
),
props: { props: {
title: field.title, title: field.title,
}, },
@ -79,7 +103,9 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
const { extraProps } = this.field; const { extraProps } = this.field;
const { condition } = extraProps; const { condition } = extraProps;
try { try {
return typeof condition === 'function' ? condition(this.field.internalToShellField()) !== false : true; return typeof condition === 'function'
? condition(this.field.internalToShellField()) !== false
: true;
} catch (error) { } catch (error) {
console.error('exception when condition (hidden) is excuted', error); console.error('exception when condition (hidden) is excuted', error);
} }
@ -111,16 +137,18 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
const { defaultValue } = extraProps; const { defaultValue } = extraProps;
const { setter } = this.field; const { setter } = this.field;
let setterProps: { let setterProps:
setters?: (ReactNode | string)[]; | ({
} & Record<string, unknown> | IPublicTypeDynamicProps = {}; setters?: (ReactNode | string)[];
} & Record<string, unknown>)
| IPublicTypeDynamicProps = {};
let setterType: any; let setterType: any;
let initialValue: any = null; let initialValue: any = null;
if (Array.isArray(setter)) { if (Array.isArray(setter)) {
setterType = 'MixedSetter'; setterType = 'MixedSetter';
setterProps = { setterProps = {
setters: setter, setters: setter as any,
}; };
} else if (isSetterConfig(setter)) { } else if (isSetterConfig(setter)) {
setterType = setter.componentName; setterType = setter.componentName;
@ -154,7 +182,8 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
// 根据是否支持变量配置做相应的更改 // 根据是否支持变量配置做相应的更改
const supportVariable = this.field.extraProps?.supportVariable; const supportVariable = this.field.extraProps?.supportVariable;
// supportVariableGlobally 只对标准组件生效vc 需要单独配置 // supportVariableGlobally 只对标准组件生效vc 需要单独配置
const supportVariableGlobally = engineConfig.get('supportVariableGlobally', false) && isStandardComponent(componentMeta); const supportVariableGlobally =
engineConfig.get('supportVariableGlobally', false) && isStandardComponent(componentMeta);
const isUseVariableSetter = shouldUseVariableSetter(supportVariable, supportVariableGlobally); const isUseVariableSetter = shouldUseVariableSetter(supportVariable, supportVariableGlobally);
if (isUseVariableSetter === false) { if (isUseVariableSetter === false) {
return { return {
@ -172,10 +201,7 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
} else { } else {
setterType = 'MixedSetter'; setterType = 'MixedSetter';
setterProps = { setterProps = {
setters: [ setters: [setter as any, 'VariableSetter'],
setter,
'VariableSetter',
],
}; };
} }
return { return {
@ -191,7 +217,8 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
initDefaultValue() { initDefaultValue() {
const { initialValue } = this.setterInfo; const { initialValue } = this.setterInfo;
if (this.state?.fromOnChange || if (
this.state?.fromOnChange ||
!isInitialValueNotEmpty(initialValue) || !isInitialValueNotEmpty(initialValue) ||
this.ignoreDefaultValue || this.ignoreDefaultValue ||
this.value !== undefined this.value !== undefined
@ -200,7 +227,10 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
} }
// 当前 field 没有 value 值时,将 initialValue 写入 field // 当前 field 没有 value 值时,将 initialValue 写入 field
// 之所以用 initialValue而不是 defaultValue 是为了保持跟 props.onInitial 的逻辑一致 // 之所以用 initialValue而不是 defaultValue 是为了保持跟 props.onInitial 的逻辑一致
const _initialValue = typeof initialValue === 'function' ? initialValue(this.field.internalToShellField()) : initialValue; const _initialValue =
typeof initialValue === 'function'
? initialValue(this.field.internalToShellField())
: initialValue;
this.field.setValue(_initialValue); this.field.setValue(_initialValue);
} }
@ -217,11 +247,7 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
return null; return null;
} }
const { const { setterProps = {}, setterType, initialValue = null } = this.setterInfo;
setterProps = {},
setterType,
initialValue = null,
} = this.setterInfo;
const value = this.value; const value = this.value;
@ -243,44 +269,47 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
...extraProps, ...extraProps,
}, },
!stageName && !stageName &&
this.setters?.createSetterContent(setterType, { this.setters?.createSetterContent(setterType, {
...shallowIntl(setterProps), ...shallowIntl(setterProps),
forceInline: extraProps.forceInline, forceInline: extraProps.forceInline,
key: field.id, key: field.id,
// === injection // === injection
prop: field.internalToShellField(), // for compatible vision prop: field.internalToShellField(), // for compatible vision
selected: field.top?.getNode()?.internalToShellNode(), selected: field.top?.getNode()?.internalToShellNode(),
field: field.internalToShellField(), field: field.internalToShellField(),
// === IO // === IO
value, // reaction point value, // reaction point
initialValue, initialValue,
onChange: (value: any) => { onChange: (value: any) => {
this.setState({ this.setState({
fromOnChange: true, fromOnChange: true,
// eslint-disable-next-line react/no-unused-state // eslint-disable-next-line react/no-unused-state
value, value,
}); });
field.setValue(value, true); field.setValue(value, true);
if (onChangeAPI) onChangeAPI(value, field.internalToShellField()); if (onChangeAPI) onChangeAPI(value, field.internalToShellField());
}, },
onInitial: () => { onInitial: () => {
if (initialValue == null) { if (initialValue == null) {
return; return;
} }
const value = typeof initialValue === 'function' ? initialValue(field.internalToShellField()) : initialValue; const value =
this.setState({ typeof initialValue === 'function'
// eslint-disable-next-line react/no-unused-state ? initialValue(field.internalToShellField())
value, : initialValue;
}); this.setState({
field.setValue(value, true); // eslint-disable-next-line react/no-unused-state
}, value,
});
field.setValue(value, true);
},
removeProp: () => { removeProp: () => {
if (field.name) { if (field.name) {
field.parent.clearPropValue(field.name); field.parent.clearPropValue(field.name);
} }
}, },
}), }),
extraProps.forceInline ? 'plain' : extraProps.display, extraProps.forceInline ? 'plain' : extraProps.display,
); );
} }
@ -311,7 +340,11 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
stages.add({ stages.add({
type: 'Widget', type: 'Widget',
name: stageName, name: stageName,
content: <Fragment>{field.items.map((item, index) => createSettingFieldView(item, field, index))}</Fragment>, content: (
<Fragment>
{field.items.map((item, index) => createSettingFieldView(item, field, index))}
</Fragment>
),
props: { props: {
title: field.title, title: field.title,
}, },
@ -325,7 +358,10 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
const { field } = this.props; const { field } = this.props;
const { extraProps } = field; const { extraProps } = field;
const { condition, display } = extraProps; const { condition, display } = extraProps;
const visible = field.isSingle && typeof condition === 'function' ? condition(field.internalToShellField()) !== false : true; const visible =
field.isSingle && typeof condition === 'function'
? condition(field.internalToShellField()) !== false
: true;
if (!visible) { if (!visible) {
return null; return null;
@ -349,7 +385,11 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
} }
} }
export function createSettingFieldView(field: ISettingField | IPublicTypeCustomView, fieldEntry: ISettingEntry, index?: number) { export function createSettingFieldView(
field: ISettingField | IPublicTypeCustomView,
fieldEntry: ISettingEntry,
index?: number,
) {
if (isSettingField(field)) { if (isSettingField(field)) {
if (field.isGroup) { if (field.isGroup) {
return <SettingGroupView field={field} key={field.id} />; return <SettingGroupView field={field} key={field.id} />;
@ -411,10 +451,6 @@ export class SettingsPane extends Component<SettingsPaneProps> {
} }
}; };
private popStage() {
this.currentStage = this.currentStage?.getPrevious();
}
render() { render() {
const { target } = this.props; const { target } = this.props;
const { items } = target; const { items } = target;

View File

@ -1,6 +1,14 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Tab, Breadcrumb } from '@alifd/next'; import { Tab, Breadcrumb } from '@alifd/next';
import { Title, observer, Editor, obx, globalContext, engineConfig, makeObservable } from '@alilc/lowcode-editor-core'; import {
Title,
observer,
Editor,
obx,
globalContext,
engineConfig,
makeObservable,
} from '@alilc/lowcode-editor-core';
import { Node, SettingField, isSettingField, INode } from '@alilc/lowcode-designer'; import { Node, SettingField, isSettingField, INode } from '@alilc/lowcode-designer';
import classNames from 'classnames'; import classNames from 'classnames';
import { SettingsMain } from './main'; import { SettingsMain } from './main';
@ -16,7 +24,10 @@ interface ISettingsPrimaryPaneProps {
} }
@observer @observer
export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, { shouldIgnoreRoot: boolean }> { export class SettingsPrimaryPane extends Component<
ISettingsPrimaryPaneProps,
{ shouldIgnoreRoot: boolean }
> {
state = { state = {
shouldIgnoreRoot: false, shouldIgnoreRoot: false,
}; };
@ -93,27 +104,29 @@ export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, {
l === 2 l === 2
? {} ? {}
: { : {
onMouseOver: hoverNode.bind(null, _node, true), onMouseOver: hoverNode.bind(null, _node, true),
onMouseOut: hoverNode.bind(null, _node, false), onMouseOut: hoverNode.bind(null, _node, false),
onClick: () => { onClick: () => {
if (!_node) { if (!_node) {
return; return;
} }
selectNode.call(null, _node); selectNode.call(null, _node);
const getName = (node: any) => { const getName = (node: any) => {
const npm = node?.componentMeta?.npm; const npm = node?.componentMeta?.npm;
return [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || return (
node?.componentMeta?.componentName || [npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
''; node?.componentMeta?.componentName ||
}; ''
const selected = getName(current); );
const target = getName(_node); };
editor?.eventBus.emit('skeleton.settingsPane.Breadcrumb', { const selected = getName(current);
selected, const target = getName(_node);
target, editor?.eventBus.emit('skeleton.settingsPane.Breadcrumb', {
}); selected,
}, target,
}; });
},
};
items.unshift( items.unshift(
<Breadcrumb.Item {...props} key={node.id}> <Breadcrumb.Item {...props} key={node.id}>
<Title title={node.title} /> <Title title={node.title} />
@ -179,7 +192,7 @@ export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, {
} }
const { items } = settings; const { items } = settings;
if (items.length > 5 || items.some((item) => !isSettingField(item) || !item.isGroup)) { if (items.length > 5 || items.some((item: any) => !isSettingField(item) || !item.isGroup)) {
return ( return (
<div className="lc-settings-main"> <div className="lc-settings-main">
{this.renderBreadcrumb()} {this.renderBreadcrumb()}
@ -188,6 +201,7 @@ export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, {
{(skeleton) => { {(skeleton) => {
if (skeleton) { if (skeleton) {
return ( return (
// @ts-ignore
<StageBox skeleton={skeleton} target={settings} key={settings.id}> <StageBox skeleton={skeleton} target={settings} key={settings.id}>
<SettingsPane target={settings} usePopup={false} /> <SettingsPane target={settings} usePopup={false} />
</StageBox> </StageBox>
@ -211,19 +225,18 @@ export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, {
className="lc-settings-tab-item" className="lc-settings-tab-item"
title={<Title title={field.title} />} title={<Title title={field.title} />}
key={field.name} key={field.name}
onClick={ onClick={() => {
() => { editor?.eventBus.emit('skeleton.settingsPane.change', {
editor?.eventBus.emit('skeleton.settingsPane.change', { name: field.name,
name: field.name, title: field.title,
title: field.title, });
}); }}
}
}
> >
<SkeletonContext.Consumer> <SkeletonContext.Consumer>
{(skeleton) => { {(skeleton) => {
if (skeleton) { if (skeleton) {
return ( return (
// @ts-ignore
<StageBox skeleton={skeleton} target={field} key={field.id}> <StageBox skeleton={skeleton} target={field} key={field.id}>
<SettingsPane target={field} key={field.id} usePopup={false} /> <SettingsPane target={field} key={field.id} usePopup={false} />
</StageBox> </StageBox>
@ -243,7 +256,7 @@ export class SettingsPrimaryPane extends Component<ISettingsPrimaryPaneProps, {
}); });
return ( return (
<div className={className}> <div className={className}>
{ this.renderBreadcrumb() } {this.renderBreadcrumb()}
<Tab <Tab
activeKey={activeKey} activeKey={activeKey}
onChange={(tabKey) => { onChange={(tabKey) => {

View File

@ -1,28 +1,34 @@
function getHotterFromSetter(setter) { function getHotterFromSetter(setter: any) {
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line return (setter && (setter.Hotter || (setter.type && setter.type.Hotter))) || []; // eslint-disable-line
} }
function getTransducerFromSetter(setter) { function getTransducerFromSetter(setter: any) {
return setter && ( return (
setter.transducer || setter.Transducer (setter &&
|| (setter.type && (setter.type.transducer || setter.type.Transducer)) (setter.transducer ||
) || null; // eslint-disable-line setter.Transducer ||
(setter.type && (setter.type.transducer || setter.type.Transducer)))) ||
null
); // eslint-disable-line
} }
function combineTransducer(transducer, arr, context) { function combineTransducer(transducer: any, arr: any, context: any) {
if (!transducer && Array.isArray(arr)) { if (!transducer && Array.isArray(arr)) {
const [toHot, toNative] = arr; const [toHot, toNative] = arr;
transducer = { toHot, toNative }; transducer = { toHot, toNative };
} }
return { return {
toHot: (transducer && transducer.toHot || (x => x)).bind(context), // eslint-disable-line toHot: ((transducer && transducer.toHot) || ((x: any) => x)).bind(context), // eslint-disable-line
toNative: (transducer && transducer.toNative || (x => x)).bind(context), // eslint-disable-line toNative: ((transducer && transducer.toNative) || ((x: any) => x)).bind(context), // eslint-disable-line
}; };
} }
export class Transducer { export class Transducer {
constructor(context, config) { context: any;
setterTransducer: any;
constructor(context: any, config: any) {
this.setterTransducer = combineTransducer( this.setterTransducer = combineTransducer(
getTransducerFromSetter(config.setter), getTransducerFromSetter(config.setter),
getHotterFromSetter(config.setter), getHotterFromSetter(config.setter),
@ -31,11 +37,11 @@ export class Transducer {
this.context = context; this.context = context;
} }
toHot(data) { toHot(data: any) {
return this.setterTransducer.toHot(data); return this.setterTransducer.toHot(data);
} }
toNative(data) { toNative(data: any) {
return this.setterTransducer.toNative(data); return this.setterTransducer.toNative(data);
} }
} }

View File

@ -104,8 +104,12 @@ export default class StageBox extends Component<StageBoxProps> {
let contentRefer = null; let contentRefer = null;
if (refer) { if (refer) {
contentCurrent = <Stage key={stage.getId()} stage={stage} direction={refer.direction} current />; contentCurrent = (
contentRefer = <Stage key={refer?.stage?.getId()} stage={refer?.stage} direction={refer.direction} />; <Stage key={stage.getId()} stage={stage} direction={refer.direction} current />
);
contentRefer = (
<Stage key={refer?.stage?.getId()} stage={refer?.stage} direction={refer.direction} />
);
} else { } else {
contentCurrent = <Stage key={stage.getId()} stage={stage} current />; contentCurrent = <Stage key={stage.getId()} stage={stage} current />;
} }
@ -117,12 +121,10 @@ export default class StageBox extends Component<StageBoxProps> {
}} }}
className={className} className={className}
> >
{/* @ts-ignore */}
<PopupService popupPipe={this.popupPipe}> <PopupService popupPipe={this.popupPipe}>
{contentRefer} {contentRefer}
{contentCurrent} {contentCurrent}
</PopupService> </PopupService>
</div> </div>
); );

View File

@ -78,9 +78,17 @@ export default class Stage extends Component<StageProps> {
const stageBacker = stage?.hasBack() ? ( const stageBacker = stage?.hasBack() ? (
<div className="skeleton-stagebox-stagebacker"> <div className="skeleton-stagebox-stagebacker">
<IconArrow className="skeleton-stagebox-stage-arrow" size="medium" data-stage-target="stageback" /> <IconArrow
<span className="skeleton-stagebox-stage-title">{newTitle}</span> className="skeleton-stagebox-stage-arrow"
<IconExit className="skeleton-stagebox-stage-exit" size="medium" data-stage-target="stageexit" /> size="medium"
data-stage-target="stageback"
/>
<span className="skeleton-stagebox-stage-title">{newTitle as any}</span>
<IconExit
className="skeleton-stagebox-stage-exit"
size="medium"
data-stage-target="stageexit"
/>
</div> </div>
) : null; ) : null;

View File

@ -6,7 +6,7 @@ import { IconFloat } from '../../icons/float';
import { Panel } from '../../widget/panel'; import { Panel } from '../../widget/panel';
export default class PanelOperationRow extends Component<{ panel: Panel }> { export default class PanelOperationRow extends Component<{ panel: Panel }> {
constructor(props) { constructor(props: any) {
super(props); super(props);
makeObservable(this); makeObservable(this);
} }
@ -36,8 +36,8 @@ export default class PanelOperationRow extends Component<{ panel: Panel }> {
const hideTitleBar = panel?.config.props?.hideTitleBar; const hideTitleBar = panel?.config.props?.hideTitleBar;
const areaName = panel?.parent?.name; const areaName = panel?.parent?.name ?? '';
const area = panel.skeleton[areaName]; const area = (panel.skeleton as any)[areaName];
return ( return (
<Fragment> <Fragment>

View File

@ -3,7 +3,7 @@ import { SVGIcon, IconProps } from '@alilc/lowcode-utils';
export function IconSlot(props: IconProps) { export function IconSlot(props: IconProps) {
return ( return (
<SVGIcon viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M682.325333 135.509333V204.8H819.2v613.376h-614.741333V204.8h136.874666v-69.290667h-206.165333v752.298667h754.346667V135.509333z" c="Q29weXJpZ2h0IChjKSAyMDIwLXByZXNlbnQgQWxpYmFiYSBJbmMu" /> <path d="M682.325333 135.509333V204.8H819.2v613.376h-614.741333V204.8h136.874666v-69.290667h-206.165333v752.298667h754.346667V135.509333z" />
<path d="M512 512m-170.325333 0a170.325333 170.325333 0 1 0 340.650666 0 170.325333 170.325333 0 1 0-340.650666 0Z" /> <path d="M512 512m-170.325333 0a170.325333 170.325333 0 1 0 340.650666 0 170.325333 170.325333 0 1 0-340.650666 0Z" />
</SVGIcon> </SVGIcon>
); );

View File

@ -9,3 +9,4 @@ export * from './context';
export * from './register-defaults'; export * from './register-defaults';
export * from './widget'; export * from './widget';
export * from './layouts'; export * from './layouts';
export * from './event';

View File

@ -1,7 +1,7 @@
import { Component, Fragment } from 'react'; import { Component, Fragment } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { observer } from '@alilc/lowcode-editor-core'; import { observer } from '@alilc/lowcode-editor-core';
import { Area } from '@alilc/lowcode-editor-skeleton'; import { Area } from '../area';
@observer @observer
export default class SubTopArea extends Component<{ area: Area; itemClassName?: string }> { export default class SubTopArea extends Component<{ area: Area; itemClassName?: string }> {
@ -13,9 +13,10 @@ export default class SubTopArea extends Component<{ area: Area; itemClassName?:
} }
return ( return (
<div className={classNames('lc-workspace-sub-top-area lc-sub-top-area engine-actionpane', { <div
'lc-area-visible': area.visible, className={classNames('lc-workspace-sub-top-area lc-sub-top-area engine-actionpane', {
})} 'lc-area-visible': area.visible,
})}
> >
<Contents area={area} itemClassName={itemClassName} /> <Contents area={area} itemClassName={itemClassName} />
</div> </div>
@ -30,38 +31,43 @@ class Contents extends Component<{ area: Area; itemClassName?: string }> {
const left: any[] = []; const left: any[] = [];
const center: any[] = []; const center: any[] = [];
const right: any[] = []; const right: any[] = [];
area.container.items.slice().sort((a, b) => { area.container.items
const index1 = a.config?.index || 0; .slice()
const index2 = b.config?.index || 0; .sort((a, b) => {
return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1); const index1 = a.config?.index || 0;
}).forEach(item => { const index2 = b.config?.index || 0;
const content = ( return index1 === index2 ? 0 : index1 > index2 ? 1 : -1;
<div className={itemClassName || ''} key={`top-area-${item.name}`}> })
{item.content} .forEach((item) => {
</div> const content = (
); <div className={itemClassName || ''} key={`top-area-${item.name}`}>
if (item.align === 'center') { {item.content}
center.push(content); </div>
} else if (item.align === 'left') { );
left.push(content); if (item.align === 'center') {
} else { center.push(content);
right.push(content); } else if (item.align === 'left') {
} left.push(content);
}); } else {
right.push(content);
}
});
let children = []; let children = [];
if (left && left.length) { if (left && left.length) {
children.push(<div className="lc-workspace-sub-top-area-left lc-sub-top-area-left">{left}</div>); children.push(
<div className="lc-workspace-sub-top-area-left lc-sub-top-area-left">{left}</div>,
);
} }
if (center && center.length) { if (center && center.length) {
children.push(<div className="lc-workspace-sub-top-area-center lc-sub-top-area-center">{center}</div>); children.push(
<div className="lc-workspace-sub-top-area-center lc-sub-top-area-center">{center}</div>,
);
} }
if (right && right.length) { if (right && right.length) {
children.push(<div className="lc-workspace-sub-top-area-right lc-sub-top-area-right">{right}</div>); children.push(
<div className="lc-workspace-sub-top-area-right lc-sub-top-area-right">{right}</div>,
);
} }
return ( return <Fragment>{children}</Fragment>;
<Fragment>
{children}
</Fragment>
);
} }
} }

View File

@ -0,0 +1 @@
declare module 'ric-shim';

View File

@ -36,27 +36,29 @@ function transformStringToFunction(str: string) {
fn = new Function(fnBody)(); fn = new Function(fnBody)();
} catch (e) { } catch (e) {
logger.error(str); logger.error(str);
logger.error(e.message); logger.error((e as Error).message);
} }
return fn; return fn;
} }
function parseJSFunc(obj: any, enableAllowedKeys = true) { function parseJSFunc(obj: any, enableAllowedKeys = true) {
if (!obj) return; if (!obj) return;
Object.keys(obj).forEach(key => { Object.keys(obj).forEach((key) => {
const item = obj[key]; const item = obj[key];
if (isJSFunction(item)) { if (isJSFunction(item)) {
obj[key] = transformStringToFunction(item.value); obj[key] = transformStringToFunction(item.value);
} else if (Array.isArray(item)) { } else if (Array.isArray(item)) {
item.forEach(o => parseJSFunc(o, enableAllowedKeys)); item.forEach((o) => parseJSFunc(o, enableAllowedKeys));
} else if (isPlainObject(item)) { } else if (isPlainObject(item)) {
parseJSFunc(item, enableAllowedKeys); parseJSFunc(item, enableAllowedKeys);
} }
}); });
} }
export default function (metadata: IPublicTypeTransformedComponentMetadata): IPublicTypeTransformedComponentMetadata { export default function (
metadata: IPublicTypeTransformedComponentMetadata,
): IPublicTypeTransformedComponentMetadata {
parseJSFunc(metadata, false); parseJSFunc(metadata, false);
return metadata; return metadata;
} }

View File

@ -21,7 +21,7 @@ function propConfigToFieldConfig(propConfig: IPublicTypePropConfig): IPublicType
'zh-CN': description?.slice(0, 10) || name, 'zh-CN': description?.slice(0, 10) || name,
}, },
tip: description ? `${name} | ${description}` : undefined, tip: description ? `${name} | ${description}` : undefined,
}; } as any;
return { return {
title, title,
...propConfig, ...propConfig,
@ -65,7 +65,8 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
const dataSource = ((propType as IPublicTypeOneOf).value || []).map((value, index) => { const dataSource = ((propType as IPublicTypeOneOf).value || []).map((value, index) => {
const t = typeof value; const t = typeof value;
return { return {
label: t === 'string' || t === 'number' || t === 'boolean' ? String(value) : `value ${index}`, label:
t === 'string' || t === 'number' || t === 'boolean' ? String(value) : `value ${index}`,
value, value,
}; };
}); });
@ -93,7 +94,9 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
}; };
case 'shape': case 'shape':
case 'exact': case 'exact':
const items = ((propType as any).value || []).map((item: any) => propConfigToFieldConfig(item)); const items = ((propType as any).value || []).map((item: any) =>
propConfigToFieldConfig(item),
);
return { return {
componentName: 'ObjectSetter', componentName: 'ObjectSetter',
props: { props: {
@ -110,7 +113,11 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
if (initial == null && item.setter && typeof item.setter === 'object') { if (initial == null && item.setter && typeof item.setter === 'object') {
initial = (item.setter as any).initialValue; initial = (item.setter as any).initialValue;
} }
data[item.name] = initial ? (typeof initial === 'function' ? initial(field) : initial) : null; data[item.name] = initial
? typeof initial === 'function'
? initial(field)
: initial
: null;
}); });
return data; return data;
}, },
@ -121,7 +128,9 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
componentName: 'ObjectSetter', componentName: 'ObjectSetter',
props: { props: {
config: { config: {
extraSetter: propTypeToSetter(typeName === 'objectOf' ? (propType as IPublicTypeObjectOf).value : 'any'), extraSetter: propTypeToSetter(
typeName === 'objectOf' ? (propType as IPublicTypeObjectOf).value : 'any',
),
}, },
}, },
isRequired, isRequired,
@ -132,7 +141,9 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
return { return {
componentName: 'ArraySetter', componentName: 'ArraySetter',
props: { props: {
itemSetter: propTypeToSetter(typeName === 'arrayOf' ? (propType as IPublicTypeArrayOf).value : 'any'), itemSetter: propTypeToSetter(
typeName === 'arrayOf' ? (propType as IPublicTypeArrayOf).value : 'any',
),
}, },
isRequired, isRequired,
initialValue: [], initialValue: [],
@ -157,7 +168,7 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
isRequired, isRequired,
}; };
default: default:
// do nothing // do nothing
} }
return { return {
componentName: 'MixedSetter', componentName: 'MixedSetter',
@ -168,7 +179,9 @@ function propTypeToSetter(propType: IPublicTypePropType): IPublicTypeSetterType
const EVENT_RE = /^on|after|before[A-Z][\w]*$/; const EVENT_RE = /^on|after|before[A-Z][\w]*$/;
export default function (metadata: IPublicTypeTransformedComponentMetadata): IPublicTypeTransformedComponentMetadata { export default function (
metadata: IPublicTypeTransformedComponentMetadata,
): IPublicTypeTransformedComponentMetadata {
const { configure = {} } = metadata; const { configure = {} } = metadata;
// TODO types后续补充 // TODO types后续补充
let extendsProps: any = null; let extendsProps: any = null;

View File

@ -1,7 +1,7 @@
import { ReactNode, createElement } from 'react'; import { ReactNode, createElement } from 'react';
import { makeObservable, obx } from '@alilc/lowcode-editor-core'; import { makeObservable, obx } from '@alilc/lowcode-editor-core';
import { uniqueId, createContent } from '@alilc/lowcode-utils'; import { uniqueId, createContent } from '@alilc/lowcode-utils';
import { getEvent } from '@alilc/lowcode-shell'; import { getEvent } from '../event';
import { DockConfig } from '../types'; import { DockConfig } from '../types';
import { ISkeleton } from '../skeleton'; import { ISkeleton } from '../skeleton';
import { DockView, WidgetView } from '../components/widget-views'; import { DockView, WidgetView } from '../components/widget-views';
@ -59,7 +59,10 @@ export class Dock implements IWidget {
return this._body; return this._body;
} }
constructor(readonly skeleton: ISkeleton, readonly config: DockConfig) { constructor(
readonly skeleton: ISkeleton,
readonly config: DockConfig,
) {
makeObservable(this); makeObservable(this);
const { props = {}, name } = config; const { props = {}, name } = config;
this.name = name; this.name = name;

View File

@ -1,9 +1,19 @@
import { createElement, ReactNode } from 'react'; import { createElement, ReactNode } from 'react';
import { obx, computed, makeObservable, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import {
obx,
computed,
makeObservable,
IEventBus,
createModuleEventBus,
} from '@alilc/lowcode-editor-core';
import { uniqueId, createContent } from '@alilc/lowcode-utils'; import { uniqueId, createContent } from '@alilc/lowcode-utils';
import { IPublicTypeHelpTipConfig, IPublicTypePanelConfig, IPublicTypeTitleContent } from '@alilc/lowcode-types'; import {
IPublicTypeHelpTipConfig,
IPublicTypePanelConfig,
IPublicTypeTitleContent,
} from '@alilc/lowcode-types';
import { WidgetContainer } from './widget-container'; import { WidgetContainer } from './widget-container';
import { getEvent } from '@alilc/lowcode-shell'; import { getEvent } from '../event';
import { TitledPanelView, TabsPanelView, PanelView } from '../components/widget-views'; import { TitledPanelView, TabsPanelView, PanelView } from '../components/widget-views';
import { ISkeleton } from '../skeleton'; import { ISkeleton } from '../skeleton';
import { composeTitle } from './utils'; import { composeTitle } from './utils';
@ -49,7 +59,7 @@ export class Panel implements IWidget {
} }
const { content, contentProps } = this.config; const { content, contentProps } = this.config;
return createContent(content, { return createContent(content as any, {
...contentProps, ...contentProps,
editor: getEvent(this.skeleton.editor), editor: getEvent(this.skeleton.editor),
config: this.config, config: this.config,
@ -80,7 +90,10 @@ export class Panel implements IWidget {
@obx.ref public parent?: WidgetContainer; @obx.ref public parent?: WidgetContainer;
constructor(readonly skeleton: ISkeleton, readonly config: IPublicTypePanelConfig) { constructor(
readonly skeleton: ISkeleton,
readonly config: IPublicTypePanelConfig,
) {
makeObservable(this); makeObservable(this);
const { name, content, props = {} } = config; const { name, content, props = {} } = config;
const { hideTitleBar, title, icon, description, help } = props; const { hideTitleBar, title, icon, description, help } = props;
@ -108,8 +121,8 @@ export class Panel implements IWidget {
props.onInit.call(this, this); props.onInit.call(this, this);
} }
if (typeof content !== 'string' && content && content.onInit) { if (typeof content !== 'string' && content && (content as any).onInit) {
content.onInit.call(this, this); (content as any).onInit.call(this, this);
} }
// todo: process shortcut // todo: process shortcut
} }
@ -217,7 +230,7 @@ export class Panel implements IWidget {
} }
getAssocDocks(): PanelDock[] { getAssocDocks(): PanelDock[] {
return this.skeleton.widgets.filter(item => { return this.skeleton.widgets.filter((item) => {
return isPanelDock(item) && item.panelName === this.name; return isPanelDock(item) && item.panelName === this.name;
}) as any; }) as any;
} }

View File

@ -2,13 +2,19 @@ import { IPublicTypeIconType, IPublicTypeTitleContent, TipContent } from '@alilc
import { isI18nData, isTitleConfig } from '@alilc/lowcode-utils'; import { isI18nData, isTitleConfig } from '@alilc/lowcode-utils';
import { isValidElement } from 'react'; import { isValidElement } from 'react';
export function composeTitle(title?: IPublicTypeTitleContent, icon?: IPublicTypeIconType, tip?: TipContent, tipAsTitle?: boolean, noIcon?: boolean) { export function composeTitle(
title?: IPublicTypeTitleContent,
icon?: IPublicTypeIconType,
tip?: TipContent,
tipAsTitle?: boolean,
noIcon?: boolean,
) {
let _title: IPublicTypeTitleContent | undefined; let _title: IPublicTypeTitleContent | undefined;
if (!title) { if (!title) {
_title = {}; _title = {};
if (!icon || tipAsTitle) { if (!icon || tipAsTitle) {
_title = { _title = {
label: tip, label: tip as any,
}; };
tip = undefined; tip = undefined;
} }
@ -19,7 +25,7 @@ export function composeTitle(title?: IPublicTypeTitleContent, icon?: IPublicType
if (icon || tip) { if (icon || tip) {
if (typeof _title !== 'object' || isValidElement(_title) || isI18nData(_title)) { if (typeof _title !== 'object' || isValidElement(_title) || isI18nData(_title)) {
if (isValidElement(_title)) { if (isValidElement(_title)) {
if (_title.type === 'svg' || _title.type.getIcon) { if (_title.type === 'svg' || (_title.type as any).getIcon) {
if (!icon) { if (!icon) {
icon = _title; icon = _title;
} }
@ -32,7 +38,7 @@ export function composeTitle(title?: IPublicTypeTitleContent, icon?: IPublicType
} }
} }
_title = { _title = {
label: _title, label: _title as any,
icon, icon,
tip, tip,
}; };
@ -41,7 +47,7 @@ export function composeTitle(title?: IPublicTypeTitleContent, icon?: IPublicType
..._title, ..._title,
icon, icon,
tip, tip,
}; } as any;
} }
} }
if (isTitleConfig(_title) && noIcon) { if (isTitleConfig(_title) && noIcon) {

View File

@ -1,7 +1,7 @@
import { ReactNode, createElement } from 'react'; import { ReactNode, createElement } from 'react';
import { makeObservable, obx } from '@alilc/lowcode-editor-core'; import { makeObservable, obx } from '@alilc/lowcode-editor-core';
import { createContent, uniqueId } from '@alilc/lowcode-utils'; import { createContent, uniqueId } from '@alilc/lowcode-utils';
import { getEvent } from '@alilc/lowcode-shell'; import { getEvent } from '../event';
import { WidgetConfig } from '../types'; import { WidgetConfig } from '../types';
import { ISkeleton } from '../skeleton'; import { ISkeleton } from '../skeleton';
import { WidgetView } from '../components/widget-views'; import { WidgetView } from '../components/widget-views';
@ -71,7 +71,10 @@ export class Widget implements IWidget {
readonly title: IPublicTypeTitleContent; readonly title: IPublicTypeTitleContent;
constructor(readonly skeleton: ISkeleton, readonly config: WidgetConfig) { constructor(
readonly skeleton: ISkeleton,
readonly config: WidgetConfig,
) {
makeObservable(this); makeObservable(this);
const { props = {}, name } = config; const { props = {}, name } = config;
this.name = name; this.name = name;

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "temp",
"stripInternal": true,
"paths": {}
}
}

View File

@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import { resolve } from 'node:path';
import react from '@vitejs/plugin-react';
import { devDependencies, peerDependencies } from './package.json';
const externals = [...Object.keys(peerDependencies), ...Object.keys(devDependencies)];
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(import.meta.dirname, 'src/index.ts'),
name: 'LowCodeEditorSkeleton',
formats: ['es', 'cjs'],
// the proper extensions will be added
fileName: 'editorSkeleton',
},
rollupOptions: {
external: externals,
},
},
plugins: [react()],
});

View File

@ -1 +0,0 @@
module.exports = require('../../babel.config');

View File

@ -1,19 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce",
[
"build-plugin-fusion",
{
"themePackage": "@alifd/theme-lowcode-light",
"externalNext": "umd"
}
],
[
"build-plugin-moment-locales",
{
"locales": ["zh-cn"]
}
],
"./build.plugin.js"
]
}

View File

@ -1,40 +0,0 @@
const { execSync } = require('child_process');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
// get version from git branch name,
// e.g. release/1.0.7 => 1.0.7
// release/1.0.7-beta => 1.0.7 (beta)
// release/1.0.7-beta.0 => 1.0.7 (beta)
function getVersion() {
const gitBranchName = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' });
const reBranchVersion = /^(?:[\w-]+\/)(\d+\.\d+\.\d+)(-?beta)?(?:\.\d+)?$/im;
const match = reBranchVersion.exec(gitBranchName);
if (!match) {
console.warn(`[engine] gitBranchName: ${gitBranchName}`);
return 'N/A';
}
const [_, version, beta] = match;
return beta && beta.endsWith('beta') ? `${version}-beta` : version;
}
const releaseVersion = getVersion();
module.exports = ({ context, onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [
{
configFile: './tsconfig.json',
},
]);
config.plugin('define').use(context.webpack.DefinePlugin, [
{
VERSION_PLACEHOLDER: JSON.stringify(releaseVersion),
},
]);
config.plugins.delete('hot');
config.devServer.hot(false);
});
};

View File

@ -1,19 +0,0 @@
{
"plugins": [
[
"@alilc/build-plugin-lce",
{
"filename": "editor-preset-vision",
"library": "LowcodeEditor",
"libraryTarget": "umd",
"externals": {
"react": "var window.React",
"react-dom": "var window.ReactDOM",
"prop-types": "var window.PropTypes",
"rax": "var window.Rax"
}
}
],
"@alilc/lowcode-test-mate/plugin/index.ts"
]
}

View File

@ -1,40 +0,0 @@
{
"entry": {
"engine-core": "src/index"
},
"sourceMap": true,
"library": "AliLowCodeEngine",
"libraryTarget": "umd",
"externals": {
"react": "var window.React",
"react-dom": "var window.ReactDOM",
"prop-types": "var window.PropTypes",
"@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",
"@alifd/next": "var Next",
"@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt",
"moment": "var moment",
"lodash": "var _"
},
"polyfill": false,
"outputDir": "dist",
"vendor": false,
"ignoreHtmlTemplate": true,
"plugins": [
"build-plugin-react-app",
[
"build-plugin-fusion",
{
"themePackage": "@alifd/theme-lowcode-light",
"externalNext": "umd"
}
],
["build-plugin-moment-locales", {
"locales": ["zh-cn"]
}],
"./build.plugin.js"
]
}

View File

@ -1,27 +0,0 @@
const esModules = [
'@recore/obx-react',
// '@ali/lowcode-editor-core',
].join('|');
module.exports = {
// transform: {
// '^.+\\.[jt]sx?$': 'babel-jest',
// // '^.+\\.(ts|tsx)$': 'ts-jest',
// // '^.+\\.(js|jsx)$': 'babel-jest',
// },
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
collectCoverage: false,
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.d.ts',
'!src/base/**',
'!src/fields/**',
'!src/prop.ts',
'!**/node_modules/**',
'!**/vendor/**',
],
};

View File

@ -29,16 +29,16 @@
"@alilc/lowcode-shell": "1.3.2", "@alilc/lowcode-shell": "1.3.2",
"@alilc/lowcode-utils": "1.3.2", "@alilc/lowcode-utils": "1.3.2",
"@alilc/lowcode-workspace": "1.3.2", "@alilc/lowcode-workspace": "1.3.2",
"react": "^16.8.1", "react": "^18.2.0",
"react-dom": "^16.8.1" "react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.18", "@alib/build-scripts": "^0.1.18",
"@alifd/theme-lowcode-dark": "^0.2.0", "@alifd/theme-lowcode-dark": "^0.2.0",
"@alifd/theme-lowcode-light": "^0.2.0", "@alifd/theme-lowcode-light": "^0.2.0",
"@types/domready": "^1.0.0", "@types/domready": "^1.0.0",
"@types/react": "^16.8.3", "@types/react": "^18.2.0",
"@types/react-dom": "^16.8.2", "@types/react-dom": "^18.2.0",
"build-plugin-fusion": "0.1.17-beta.0", "build-plugin-fusion": "0.1.17-beta.0",
"build-plugin-moment-locales": "^0.1.0", "build-plugin-moment-locales": "^0.1.0",
"build-plugin-react-app": "^1.8.0", "build-plugin-react-app": "^1.8.0",

View File

@ -1,9 +0,0 @@
{
"plugins": [
"@alilc/build-plugin-lce",
"build-plugin-fusion",
["build-plugin-moment-locales", {
"locales": ["zh-cn"]
}]
]
}

View File

@ -1,19 +0,0 @@
{
"plugins": [
[
"@alilc/build-plugin-lce",
{
"filename": "editor-preset-vision",
"library": "LowcodeEditor",
"libraryTarget": "umd",
"externals": {
"react": "var window.React",
"react-dom": "var window.ReactDOM",
"prop-types": "var window.PropTypes",
"rax": "var window.Rax"
}
}
],
"@alilc/lowcode-test-mate/plugin/index.ts"
]
}

View File

@ -1,22 +0,0 @@
const fs = require('fs');
const { join } = require('path');
const esModules = [].join('|');
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
const jestConfig = {
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
collectCoverage: true,
collectCoverageFrom: [
'src/**/*.ts',
'src/**/*.tsx',
],
};
// 只对本仓库内的 pkg 做 mapping
jestConfig.moduleNameMapper = {};
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
module.exports = jestConfig;

View File

@ -1,39 +1,46 @@
{ {
"name": "@alilc/lowcode-plugin-command", "name": "@alilc/lowcode-plugin-command",
"version": "1.3.2", "version": "2.0.0-beta.0",
"description": "> TODO: description", "description": "> TODO: description",
"author": "liujuping <liujup@foxmail.com>", "author": "liujuping <liujup@foxmail.com>",
"homepage": "https://github.com/alibaba/lowcode-engine#readme", "homepage": "https://github.com/alibaba/lowcode-engine#readme",
"license": "ISC", "license": "ISC",
"main": "lib/index.js", "type": "module",
"module": "es/index.js", "main": "dist/command.cjs",
"directories": { "module": "dist/command.js",
"lib": "lib", "types": "dist/index.d.ts",
"test": "__tests__" "exports": {
".": {
"import": "./dist/command.js",
"require": "./dist/command.cjs",
"types": "./dist/index.d.ts"
}
}, },
"files": [ "files": [
"lib", "dist",
"es" "src",
"package.json"
], ],
"sideEffects": [
"*.css"
],
"scripts": {
"build": "vite build",
"build-dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
"test": "vitest"
},
"bugs": {
"url": "https://github.com/alibaba/lowcode-engine/issues"
},
"dependencies": {
"@alilc/lowcode-types": "workspace:*",
"@alilc/lowcode-utils": "workspace:*"
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/alibaba/lowcode-engine.git" "url": "git+https://github.com/alibaba/lowcode-engine.git"
},
"scripts": {
"test": "build-scripts test --config build.test.json --jest-passWithNoTests",
"build": "build-scripts build"
},
"bugs": {
"url": "https://github.com/alibaba/lowcode-engine/issues"
},
"dependencies": {
"@alilc/lowcode-types": "1.3.2",
"@alilc/lowcode-utils": "1.3.2"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.18"
} }
} }

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "temp",
"stripInternal": true,
"paths": {}
}
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"]
}

View File

@ -0,0 +1,15 @@
import { defineConfig } from 'vite';
import { resolve } from 'node:path';
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(import.meta.dirname, 'src/index.ts'),
name: 'LowCodePluginCommand',
formats: ['es', 'cjs'],
// the proper extensions will be added
fileName: 'plugin-command',
},
},
});

View File

View File

@ -1,16 +1,27 @@
{ {
"name": "@alilc/lowcode-plugin-designer", "name": "@alilc/lowcode-plugin-designer",
"version": "1.3.2", "version": "2.0.0-beta.0",
"description": "alibaba lowcode editor designer plugin", "description": "alibaba lowcode editor designer plugin",
"type": "module",
"main": "dist/designer.cjs",
"module": "dist/designer.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/designer.js",
"require": "./dist/designer.cjs",
"types": "./dist/index.d.ts"
}
},
"files": [ "files": [
"es", "dist",
"lib" "src",
"package.json"
], ],
"main": "lib/index.js",
"module": "es/index.js",
"stylePath": "style.js",
"scripts": { "scripts": {
"build": "build-scripts build" "build": "vite build",
"build-dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
"test": "vitest"
}, },
"keywords": [ "keywords": [
"lowcode", "lowcode",
@ -18,16 +29,19 @@
], ],
"author": "xiayang.xy", "author": "xiayang.xy",
"dependencies": { "dependencies": {
"@alilc/lowcode-designer": "1.3.2", "@alilc/lowcode-designer": "workspace:*",
"@alilc/lowcode-editor-core": "1.3.2", "@alilc/lowcode-editor-core": "workspace:*",
"@alilc/lowcode-utils": "1.3.2", "@alilc/lowcode-utils": "workspace:*",
"react": "^16.8.1", "react": "^18.2.0",
"react-dom": "^16.8.1" "react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.3", "@types/react": "^18.2.0",
"@types/react": "^16.9.13", "@types/react-dom": "^18.2.0"
"@types/react-dom": "^16.9.4" },
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

@ -13,6 +13,7 @@ export interface PluginProps {
interface DesignerPluginState { interface DesignerPluginState {
componentMetadatas?: any[] | null; componentMetadatas?: any[] | null;
library?: any[] | null; library?: any[] | null;
utilsMetadata?: any[] | null;
extraEnvironment?: any[] | null; extraEnvironment?: any[] | null;
renderEnv?: string; renderEnv?: string;
device?: string; device?: string;
@ -29,6 +30,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
state: DesignerPluginState = { state: DesignerPluginState = {
componentMetadatas: null, componentMetadatas: null,
utilsMetadata: null,
library: null, library: null,
extraEnvironment: null, extraEnvironment: null,
renderEnv: 'default', renderEnv: 'default',
@ -58,7 +60,8 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
const deviceClassName = engineConfig.get('deviceClassName') || editor.get('deviceClassName'); const deviceClassName = engineConfig.get('deviceClassName') || editor.get('deviceClassName');
const simulatorUrl = engineConfig.get('simulatorUrl') || editor.get('simulatorUrl'); const simulatorUrl = engineConfig.get('simulatorUrl') || editor.get('simulatorUrl');
// @TODO setupAssets 里设置 requestHandlersMap 不太合适 // @TODO setupAssets 里设置 requestHandlersMap 不太合适
const requestHandlersMap = engineConfig.get('requestHandlersMap') || editor.get('requestHandlersMap'); const requestHandlersMap =
engineConfig.get('requestHandlersMap') || editor.get('requestHandlersMap');
if (!this._mounted) { if (!this._mounted) {
return; return;
} }
@ -139,6 +142,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
name={editor.viewName} name={editor.viewName}
designer={editor.get('designer')} designer={editor.get('designer')}
componentMetadatas={componentMetadatas} componentMetadatas={componentMetadatas}
shellModelFactory={{} as any}
simulatorProps={{ simulatorProps={{
library, library,
utilsMetadata, utilsMetadata,

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "temp",
"stripInternal": true,
"paths": {}
}
}

View File

@ -1,9 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "lib" "outDir": "dist"
}, },
"include": [ "include": ["src"]
"./src/"
]
} }

View File

@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import { resolve } from 'node:path';
import react from '@vitejs/plugin-react';
import { devDependencies, peerDependencies } from './package.json';
const externals = [...Object.keys(peerDependencies), ...Object.keys(devDependencies)];
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(import.meta.dirname, 'src/index.tsx'),
name: 'LowCodePluginDesigner',
formats: ['es', 'cjs'],
// the proper extensions will be added
fileName: 'plugin-designer',
},
rollupOptions: {
external: externals,
},
},
plugins: [react()],
});

Some files were not shown because too many files have changed in this diff Show More