fix: fix workspace api ts defined

This commit is contained in:
liujuping 2023-03-20 14:48:59 +08:00 committed by 林熠
parent 12a22de169
commit 6d4ca29466
37 changed files with 348 additions and 219 deletions

View File

@ -52,6 +52,6 @@ module.exports = {
'error', 'error',
{ default: ['signature', 'field', 'constructor', 'method'] } { default: ['signature', 'field', 'constructor', 'method'] }
], ],
'no-unused-vars': ['error', { "destructuredArrayIgnorePattern": "^_" }] '@typescript-eslint/no-unused-vars': ['error']
}, },
}; };

View File

@ -13,9 +13,9 @@ import { observer, computed, Tip, globalContext } from '@alilc/lowcode-editor-co
import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils'; import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils';
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types'; import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
import { BuiltinSimulatorHost } from '../host'; import { BuiltinSimulatorHost } from '../host';
import { OffsetObserver } from '../../designer'; import { INode, OffsetObserver } from '../../designer';
import { Node } from '../../document';
import NodeSelector from '../node-selector'; import NodeSelector from '../node-selector';
import { ISimulatorHost } from '../../simulator';
@observer @observer
export class BorderSelectingInstance extends Component<{ export class BorderSelectingInstance extends Component<{
@ -116,8 +116,8 @@ class Toolbar extends Component<{ observed: OffsetObserver }> {
} }
} }
function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject, key: string, node: Node) { function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject, key: string, node: INode) {
if (isValidElement(content)) { if (isValidElement<{ key: string; node: INode }>(content)) {
return cloneElement(content, { key, node }); return cloneElement(content, { key, node });
} }
if (isReactComponent(content)) { if (isReactComponent(content)) {
@ -130,7 +130,7 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
key={key} key={key}
className="lc-borders-action" className="lc-borders-action"
onClick={() => { onClick={() => {
action && action(node); action && action(node.internalToShellNode()!);
const workspace = globalContext.get('workspace'); const workspace = globalContext.get('workspace');
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor'); const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
const npm = node?.componentMeta?.npm; const npm = node?.componentMeta?.npm;
@ -153,8 +153,8 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
} }
@observer @observer
export class BorderSelectingForNode extends Component<{ host: BuiltinSimulatorHost; node: Node }> { export class BorderSelectingForNode extends Component<{ host: ISimulatorHost; node: INode }> {
get host(): BuiltinSimulatorHost { get host(): ISimulatorHost {
return this.props.host; return this.props.host;
} }

View File

@ -47,26 +47,26 @@ import {
getRectTarget, getRectTarget,
CanvasPoint, CanvasPoint,
Designer, Designer,
IDesigner,
} from '../designer'; } from '../designer';
import { parseMetadata } from './utils/parse-metadata'; import { parseMetadata } from './utils/parse-metadata';
import { getClosestClickableNode } from './utils/clickable'; import { getClosestClickableNode } from './utils/clickable';
import { import {
IPublicTypeComponentMetadata, IPublicTypeComponentMetadata,
IPublicTypeComponentSchema,
IPublicTypePackage, IPublicTypePackage,
IPublicEnumTransitionType, IPublicEnumTransitionType,
IPublicEnumDragObjectType, IPublicEnumDragObjectType,
IPublicTypeDragNodeObject,
IPublicTypeNodeInstance, IPublicTypeNodeInstance,
IPublicTypeComponentInstance, IPublicTypeComponentInstance,
IPublicTypeLocationChildrenDetail, IPublicTypeLocationChildrenDetail,
IPublicTypeLocationDetailType, IPublicTypeLocationDetailType,
IPublicTypeRect, IPublicTypeRect,
IPublicModelNode,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import { BuiltinSimulatorRenderer } from './renderer'; import { BuiltinSimulatorRenderer } from './renderer';
import { clipboard } from '../designer/clipboard'; import { clipboard } from '../designer/clipboard';
import { LiveEditing } from './live-editing/live-editing'; import { LiveEditing } from './live-editing/live-editing';
import { 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';
@ -164,9 +164,9 @@ const defaultRaxEnvironment = [
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> { export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
readonly isSimulator = true; readonly isSimulator = true;
readonly project: Project; readonly project: IProject;
readonly designer: Designer; readonly designer: IDesigner;
readonly viewport = new Viewport(); readonly viewport = new Viewport();
@ -217,7 +217,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return this.get('requestHandlersMap') || null; return this.get('requestHandlersMap') || null;
} }
get thisRequiredInJSE(): any { get thisRequiredInJSE(): boolean {
return engineConfig.get('thisRequiredInJSE') ?? true; return engineConfig.get('thisRequiredInJSE') ?? true;
} }
@ -559,8 +559,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 as HTMLElement).removeAttribute('for'); downEvent.target?.removeAttribute('for');
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element); const nodeInst = this.getNodeInstanceFromElement(downEvent.target);
const { focusNode } = documentModel; const { focusNode } = documentModel;
const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent); const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent);
// 如果找不到可点击的节点,直接返回 // 如果找不到可点击的节点,直接返回
@ -675,11 +675,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const x = new Event('click'); const x = new Event('click');
x.initEvent('click', true); x.initEvent('click', true);
this._iframe?.dispatchEvent(x); this._iframe?.dispatchEvent(x);
const target = e.target as HTMLElement; const target = e.target;
const customizeIgnoreSelectors = engineConfig.get('customizeIgnoreSelectors'); const customizeIgnoreSelectors = engineConfig.get('customizeIgnoreSelectors');
// TODO: need more elegant solution to ignore click events of components in designer // TODO: need more elegant solution to ignore click events of components in designer
const defaultIgnoreSelectors: any = [ const defaultIgnoreSelectors: string[] = [
'.next-input-group', '.next-input-group',
'.next-checkbox-group', '.next-checkbox-group',
'.next-checkbox-wrapper', '.next-checkbox-wrapper',
@ -741,7 +741,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} }
}; };
const leave = () => { const leave = () => {
this.project.currentDocument && detecting.leave(this.project.currentDocument) this.project.currentDocument && detecting.leave(this.project.currentDocument);
}; };
doc.addEventListener('mouseover', hover, true); doc.addEventListener('mouseover', hover, true);
@ -812,7 +812,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* @see ISimulator * @see ISimulator
*/ */
setSuspense(suspended: boolean) { setSuspense(/** _suspended: boolean */) {
return false; return false;
// if (suspended) { // if (suspended) {
// /* // /*
@ -897,7 +897,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return this.renderer?.getComponent(componentName) || null; return this.renderer?.getComponent(componentName) || null;
} }
createComponent(schema: IPublicTypeComponentSchema): Component | null { createComponent(/** _schema: IPublicTypeComponentSchema */): Component | null {
return null; return null;
// return this.renderer?.createComponent(schema) || null; // return this.renderer?.createComponent(schema) || null;
} }
@ -1018,7 +1018,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} }
if (last) { if (last) {
const r: any = new DOMRect(last.x, last.y, last.r - last.x, last.b - last.y); const r: IPublicTypeRect = new DOMRect(last.x, last.y, last.r - last.x, last.b - last.y);
r.elements = elements; r.elements = elements;
r.computed = _computed; r.computed = _computed;
return r; return r;
@ -1186,13 +1186,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
*/ */
locate(e: ILocateEvent): any { locate(e: ILocateEvent): any {
const { dragObject } = e; const { dragObject } = e;
const { nodes } = dragObject as IPublicTypeDragNodeObject;
const nodes = dragObject?.nodes;
const operationalNodes = nodes?.filter((node) => { const operationalNodes = nodes?.filter((node) => {
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: Node | null = null; let parentContainerNode: INode | null = null;
let parentNode = node.parent; let parentNode = node.parent;
while (parentNode) { while (parentNode) {
@ -1254,7 +1255,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}; };
const locationData = { const locationData = {
target: container as INode, target: container,
detail, detail,
source: `simulator${document.id}`, source: `simulator${document.id}`,
event: e, event: e,
@ -1279,12 +1280,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return this.designer.createLocation(locationData); return this.designer.createLocation(locationData);
} }
let nearRect = null; let nearRect: IPublicTypeRect | null = null;
let nearIndex = 0; let nearIndex: number = 0;
let nearNode = null; let nearNode: INode | null = null;
let nearDistance = null; let nearDistance: number | null = null;
let minTop = null; let minTop: number | null = null;
let maxBottom = null; let maxBottom: number | null = null;
for (let i = 0, l = children.size; i < l; i++) { for (let i = 0, l = children.size; i < l; i++) {
const node = children.get(i)!; const node = children.get(i)!;
@ -1341,8 +1342,13 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const vertical = inline || row; const vertical = inline || row;
// TODO: fix type // TODO: fix type
const near: any = { const near: {
node: nearNode, node: IPublicModelNode;
pos: 'before' | 'after' | 'replace';
rect?: IPublicTypeRect;
align?: 'V' | 'H';
} = {
node: nearNode.internalToShellNode()!,
pos: 'before', pos: 'before',
align: vertical ? 'V' : 'H', align: vertical ? 'V' : 'H',
}; };
@ -1465,7 +1471,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
container = container.parent; container = container.parent;
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance; instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
dropContainer = { dropContainer = {
container: container, container,
instance, instance,
}; };
} else { } else {
@ -1483,12 +1489,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/** /**
* *
*/ */
handleAccept({ container, instance }: DropContainer, e: ILocateEvent): boolean { handleAccept({ container }: DropContainer, e: ILocateEvent): boolean {
const { dragObject } = e; const { dragObject } = e;
const document = this.currentDocument!; const document = this.currentDocument!;
const focusNode = document.focusNode; const focusNode = document.focusNode;
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;
@ -1509,15 +1515,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
getNearByContainer( getNearByContainer(
{ container, instance }: DropContainer, { container, instance }: DropContainer,
drillDownExcludes: Set<INode>, drillDownExcludes: Set<INode>,
e: ILocateEvent,
) { ) {
const { children } = container; const { children } = container;
const document = this.project.currentDocument!;
if (!children || children.isEmpty()) { if (!children || children.isEmpty()) {
return null; return null;
} }
const nearDistance: any = null;
const nearBy: any = null; const nearBy: any = null;
for (let i = 0, l = children.size; i < l; i++) { for (let i = 0, l = children.size; i < l; i++) {
let child = children.get(i); let child = children.get(i);

View File

@ -1,19 +1,19 @@
import { Overlay } from '@alifd/next'; import { Overlay } from '@alifd/next';
import React from 'react'; import React, { MouseEvent } from 'react';
import { Title, globalContext } from '@alilc/lowcode-editor-core'; import { Title, globalContext } from '@alilc/lowcode-editor-core';
import { canClickNode } from '@alilc/lowcode-utils'; import { canClickNode } from '@alilc/lowcode-utils';
import './index.less'; import './index.less';
import { Node, INode } from '@alilc/lowcode-designer'; import { INode } from '@alilc/lowcode-designer';
const { Popup } = Overlay; const { Popup } = Overlay;
export interface IProps { export interface IProps {
node: Node; node: INode;
} }
export interface IState { export interface IState {
parentNodes: Node[]; parentNodes: INode[];
} }
type UnionNode = INode | null; type UnionNode = INode | null;
@ -26,14 +26,18 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
componentDidMount() { componentDidMount() {
const parentNodes = this.getParentNodes(this.props.node); const parentNodes = this.getParentNodes(this.props.node);
this.setState({ this.setState({
parentNodes, parentNodes: parentNodes ?? [],
}); });
} }
// 获取节点的父级节点(最多获取 5 层) // 获取节点的父级节点(最多获取 5 层)
getParentNodes = (node: Node) => { getParentNodes = (node: INode) => {
const parentNodes: any[] = []; const parentNodes: any[] = [];
const { focusNode } = node.document; const focusNode = node.document?.focusNode;
if (!focusNode) {
return null;
}
if (node.contains(focusNode) || !focusNode.contains(node)) { if (node.contains(focusNode) || !focusNode.contains(node)) {
return parentNodes; return parentNodes;
@ -53,12 +57,12 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
return parentNodes; return parentNodes;
}; };
onSelect = (node: Node) => (e: unknown) => { onSelect = (node: INode) => (event: MouseEvent) => {
if (!node) { if (!node) {
return; return;
} }
const canClick = canClickNode(node, e as MouseEvent); const canClick = canClickNode(node.internalToShellNode()!, event);
if (canClick && typeof node.select === 'function') { if (canClick && typeof node.select === 'function') {
node.select(); node.select();
@ -76,19 +80,19 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
} }
}; };
onMouseOver = (node: Node) => (_: any, flag = true) => { onMouseOver = (node: INode) => (_: any, flag = true) => {
if (node && typeof node.hover === 'function') { if (node && typeof node.hover === 'function') {
node.hover(flag); node.hover(flag);
} }
}; };
onMouseOut = (node: Node) => (_: any, flag = false) => { onMouseOut = (node: INode) => (_: any, flag = false) => {
if (node && typeof node.hover === 'function') { if (node && typeof node.hover === 'function') {
node.hover(flag); node.hover(flag);
} }
}; };
renderNodes = (/* node: Node */) => { renderNodes = () => {
const nodes = this.state.parentNodes; const nodes = this.state.parentNodes;
if (!nodes || nodes.length < 1) { if (!nodes || nodes.length < 1) {
return null; return null;
@ -136,7 +140,7 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
triggerType="hover" triggerType="hover"
offset={[0, 0]} offset={[0, 0]}
> >
<div className="instance-node-selector">{this.renderNodes(node)}</div> <div className="instance-node-selector">{this.renderNodes()}</div>
</Popup> </Popup>
</div> </div>
); );

View File

@ -16,17 +16,15 @@ import {
IPublicModelScroller, IPublicModelScroller,
IPublicTypeLocationData, IPublicTypeLocationData,
IPublicEnumTransformStage, IPublicEnumTransformStage,
IPublicModelDragon,
IPublicModelDropLocation,
IPublicModelLocateEvent, IPublicModelLocateEvent,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils'; import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
import { Project } from '../project'; import { IProject, Project } from '../project';
import { Node, DocumentModel, insertChildren, INode } from '../document'; import { Node, DocumentModel, insertChildren, INode } from '../document';
import { ComponentMeta, IComponentMeta } from '../component-meta'; import { ComponentMeta, IComponentMeta } from '../component-meta';
import { INodeSelector, Component } from '../simulator'; import { INodeSelector, Component } from '../simulator';
import { Scroller } from './scroller'; import { Scroller } from './scroller';
import { Dragon, IDragon, ILocateEvent } from './dragon'; import { Dragon, IDragon } from './dragon';
import { ActiveTracker, IActiveTracker } from './active-tracker'; import { ActiveTracker, IActiveTracker } from './active-tracker';
import { Detecting } from './detecting'; import { Detecting } from './detecting';
import { DropLocation } from './location'; import { DropLocation } from './location';
@ -64,7 +62,11 @@ export interface DesignerProps {
export interface IDesigner { export interface IDesigner {
readonly shellModelFactory: IShellModelFactory; readonly shellModelFactory: IShellModelFactory;
get dragon(): IPublicModelDragon; viewName: string | undefined;
readonly project: IProject;
get dragon(): IDragon;
get activeTracker(): IActiveTracker; get activeTracker(): IActiveTracker;
@ -78,6 +80,10 @@ export interface IDesigner {
createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller; createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller;
refreshComponentMetasMap(): void;
createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null;
/** /**
* dragon * dragon
*/ */
@ -92,6 +98,8 @@ export interface IDesigner {
generateMetadata?: () => IPublicTypeComponentMetadata | null, generateMetadata?: () => IPublicTypeComponentMetadata | null,
): IComponentMeta; ): IComponentMeta;
clearLocation(): void;
createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null; createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null;
getComponentMetasMap(): Map<string, IComponentMeta>; getComponentMetasMap(): Map<string, IComponentMeta>;
@ -118,7 +126,7 @@ export class Designer implements IDesigner {
readonly detecting = new Detecting(); readonly detecting = new Detecting();
readonly project: Project; readonly project: IProject;
readonly editor: IPublicModelEditor; readonly editor: IPublicModelEditor;
@ -140,7 +148,7 @@ export class Designer implements IDesigner {
@obx.ref private _simulatorComponent?: ComponentType<any>; @obx.ref private _simulatorComponent?: ComponentType<any>;
@obx.ref private _simulatorProps?: Record<string, any> | ((project: Project) => object); @obx.ref private _simulatorProps?: Record<string, any> | ((project: IProject) => object);
@obx.ref private _suspensed = false; @obx.ref private _suspensed = false;

View File

@ -11,9 +11,9 @@ import {
IPublicModelSensor, IPublicModelSensor,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import { setNativeSelection, cursor } from '@alilc/lowcode-utils'; import { setNativeSelection, cursor } from '@alilc/lowcode-utils';
import { Node } from '../document'; import { INode, Node } from '../document';
import { ISimulatorHost, isSimulatorHost } from '../simulator'; import { ISimulatorHost, isSimulatorHost } from '../simulator';
import { Designer } from './designer'; import { IDesigner } from './designer';
import { makeEventsHandler } from '../utils/misc'; import { makeEventsHandler } from '../utils/misc';
export interface ILocateEvent extends IPublicModelLocateEvent { export interface ILocateEvent extends IPublicModelLocateEvent {
@ -88,14 +88,14 @@ 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?.simulator || null;
} }
function isDragEvent(e: any): e is DragEvent { function isDragEvent(e: any): e is DragEvent {
return e?.type?.startsWith('drag'); return e?.type?.startsWith('drag');
} }
export interface IDragon extends IPublicModelDragon { export interface IDragon extends IPublicModelDragon<INode> {
emitter: IEventBus; emitter: IEventBus;
} }
@ -130,7 +130,7 @@ export class Dragon implements IDragon {
emitter: IEventBus = createModuleEventBus('Dragon'); emitter: IEventBus = createModuleEventBus('Dragon');
constructor(readonly designer: Designer) { constructor(readonly designer: IDesigner) {
makeObservable(this); makeObservable(this);
this.viewName = designer.viewName; this.viewName = designer.viewName;
} }
@ -167,7 +167,7 @@ export class Dragon implements IDragon {
* @param dragObject * @param dragObject
* @param boostEvent * @param boostEvent
*/ */
boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | 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);
@ -264,7 +264,7 @@ export class Dragon implements IDragon {
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();

View File

@ -2,7 +2,7 @@ import requestIdleCallback, { cancelIdleCallback } from 'ric-shim';
import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core'; import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core';
import { uniqueId } from '@alilc/lowcode-utils'; import { uniqueId } from '@alilc/lowcode-utils';
import { INodeSelector, IViewport } from '../simulator'; import { INodeSelector, IViewport } from '../simulator';
import { Node } from '../document'; import { INode } from '../document';
export class OffsetObserver { export class OffsetObserver {
readonly id = uniqueId('oobx'); readonly id = uniqueId('oobx');
@ -93,11 +93,11 @@ export class OffsetObserver {
private pid: number | undefined; private pid: number | undefined;
readonly viewport: IViewport; readonly viewport: IViewport | undefined;
private isRoot: boolean; private isRoot: boolean;
readonly node: Node; readonly node: INode;
readonly compute: () => void; readonly compute: () => void;
@ -105,10 +105,10 @@ export class OffsetObserver {
const { node, instance } = nodeInstance; const { node, instance } = nodeInstance;
this.node = node; this.node = node;
const doc = node.document; const doc = node.document;
const host = doc.simulator!; const host = doc?.simulator;
const focusNode = doc.focusNode; const focusNode = doc?.focusNode;
this.isRoot = node.contains(focusNode!); this.isRoot = node.contains(focusNode!);
this.viewport = host.viewport; this.viewport = host?.viewport;
makeObservable(this); makeObservable(this);
if (this.isRoot) { if (this.isRoot) {
this.hasOffset = true; this.hasOffset = true;
@ -118,7 +118,7 @@ export class OffsetObserver {
return; return;
} }
let pid: number; let pid: number | undefined;
const compute = () => { const compute = () => {
if (pid !== this.pid) { if (pid !== this.pid) {
return; return;

View File

@ -35,7 +35,7 @@ import {
isDragNodeDataObject, isDragNodeDataObject,
isNode, isNode,
} from '@alilc/lowcode-utils'; } from '@alilc/lowcode-utils';
import { IProject, Project } from '../project'; import { IProject } from '../project';
import { ISimulatorHost } from '../simulator'; import { ISimulatorHost } from '../simulator';
import { IComponentMeta } from '../component-meta'; import { IComponentMeta } from '../component-meta';
import { IDesigner, IHistory } from '../designer'; import { IDesigner, IHistory } from '../designer';
@ -56,7 +56,7 @@ export type GetDataType<T, NodeType> = T extends undefined
export interface IDocumentModel extends Omit< IPublicModelDocumentModel< export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
ISelection, ISelection,
IHistory, IHistory,
INode | IRootNode, INode,
IDropLocation, IDropLocation,
IModalNodesManager, IModalNodesManager,
IProject IProject
@ -81,6 +81,8 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
readonly designer: IDesigner; readonly designer: IDesigner;
selection: ISelection;
get rootNode(): INode | null; get rootNode(): INode | null;
get simulator(): ISimulatorHost | null; get simulator(): ISimulatorHost | null;
@ -98,8 +100,6 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
get currentRoot(): INode | null; get currentRoot(): INode | null;
selection: ISelection;
isBlank(): boolean; isBlank(): boolean;
/** /**

View File

@ -6,7 +6,6 @@ import {
IPublicApiMaterial, IPublicApiMaterial,
IPublicApiEvent, IPublicApiEvent,
IPublicApiCommon, IPublicApiCommon,
IPublicTypeCompositeObject,
IPublicApiPlugins, IPublicApiPlugins,
IPublicTypePluginConfig, IPublicTypePluginConfig,
IPublicApiLogger, IPublicApiLogger,
@ -16,6 +15,7 @@ import {
IPublicApiCanvas, IPublicApiCanvas,
IPublicApiWorkspace, IPublicApiWorkspace,
IPublicTypePluginMeta, IPublicTypePluginMeta,
IPublicTypePluginRegisterOptions,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
export type PluginPreference = Map<string, Record<string, IPublicTypePreferenceValueType>>; export type PluginPreference = Map<string, Record<string, IPublicTypePreferenceValueType>>;
@ -72,7 +72,7 @@ export interface ILowCodePluginManagerCore {
register( register(
pluginModel: IPublicTypePlugin, pluginModel: IPublicTypePlugin,
pluginOptions?: any, pluginOptions?: any,
options?: IPublicTypeCompositeObject, options?: IPublicTypePluginRegisterOptions,
): Promise<void>; ): Promise<void>;
init(pluginPreference?: Map<string, Record<string, IPublicTypePreferenceValueType>>): Promise<void>; init(pluginPreference?: Map<string, Record<string, IPublicTypePreferenceValueType>>): Promise<void>;
get(pluginName: string): ILowCodePluginRuntime | undefined; get(pluginName: string): ILowCodePluginRuntime | undefined;

View File

@ -41,6 +41,14 @@ export interface IProject extends Omit< IBaseApiProject<
get documents(): IDocumentModel[]; get documents(): IDocumentModel[];
get i18n(): {
[local: string]: {
[key: string]: any;
};
};
mountSimulator(simulator: ISimulatorHost): void;
open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null; open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null;
getDocumentByFileName(fileName: string): IDocumentModel | null; getDocumentByFileName(fileName: string): IDocumentModel | null;

View File

@ -1,8 +1,9 @@
import { ComponentType } from 'react'; import { ComponentType } from 'react';
import { IPublicTypeComponentMetadata, IPublicTypeNodeSchema, IPublicTypeScrollable, IPublicTypeComponentInstance, IPublicModelSensor, IPublicTypeNodeInstance, IPublicTypePackage } from '@alilc/lowcode-types'; import { IPublicTypeComponentMetadata, IPublicTypeNodeSchema, IPublicTypeScrollable, IPublicTypeComponentInstance, IPublicModelSensor, IPublicTypeNodeInstance, IPublicTypePackage } from '@alilc/lowcode-types';
import { Point, ScrollTarget, ILocateEvent } from './designer'; import { Point, ScrollTarget, ILocateEvent, IDesigner } from './designer';
import { BuiltinSimulatorRenderer } from './builtin-simulator/renderer'; import { BuiltinSimulatorRenderer } from './builtin-simulator/renderer';
import { INode } from './document'; import { INode } from './document';
import { IProject } from './project';
export type AutoFit = '100%'; export type AutoFit = '100%';
// eslint-disable-next-line no-redeclare // eslint-disable-next-line no-redeclare
@ -89,6 +90,10 @@ export interface ISimulatorHost<P = object> extends IPublicModelSensor<INode> {
readonly contentDocument?: Document; readonly contentDocument?: Document;
readonly renderer?: BuiltinSimulatorRenderer; readonly renderer?: BuiltinSimulatorRenderer;
readonly project: IProject;
readonly designer: IDesigner;
// dependsAsset // like react jQuery lodash // dependsAsset // like react jQuery lodash
// themesAsset // themesAsset
// componentsAsset // componentsAsset

View File

@ -339,8 +339,8 @@ function fireCallback(callback: IPublicTypeHotkeyCallback, e: KeyboardEvent, com
} }
} }
export interface IHotKey extends IPublicApiHotkey { export interface IHotKey extends Omit<IPublicApiHotkey, 'bind' | 'callbacks'> {
activate(activate: boolean): void;
} }
export class Hotkey implements IHotKey { export class Hotkey implements IHotKey {

View File

@ -1,4 +1,5 @@
import { Component } from 'react'; import { Component } from 'react';
import ReactDOM from 'react-dom';
import { TipItem } from './tip-item'; import { TipItem } from './tip-item';
import { tipHandler } from './tip-handler'; import { tipHandler } from './tip-handler';
@ -25,11 +26,13 @@ export class TipContainer extends Component {
} }
render() { render() {
return window.ReactDOM.createPortal( ReactDOM.createPortal(
<div className="lc-tips-container"> <div className="lc-tips-container">
<TipItem /> <TipItem />
</div>, </div>,
document.querySelector('body')!, document.querySelector('body')!,
); );
return null;
} }
} }

View File

@ -1,5 +1,5 @@
import { import {
LowCodePluginManager, ILowCodePluginManager,
} from '@alilc/lowcode-designer'; } from '@alilc/lowcode-designer';
import { globalContext } from '@alilc/lowcode-editor-core'; import { globalContext } from '@alilc/lowcode-editor-core';
import { import {
@ -14,8 +14,8 @@ import { pluginsSymbol } from '../symbols';
const innerPluginsSymbol = Symbol('plugin'); const innerPluginsSymbol = Symbol('plugin');
export class Plugins implements IPublicApiPlugins { export class Plugins implements IPublicApiPlugins {
private readonly [innerPluginsSymbol]: LowCodePluginManager; private readonly [innerPluginsSymbol]: ILowCodePluginManager;
get [pluginsSymbol](): LowCodePluginManager { get [pluginsSymbol](): ILowCodePluginManager {
if (this.workspaceMode) { if (this.workspaceMode) {
return this[innerPluginsSymbol]; return this[innerPluginsSymbol];
} }
@ -27,7 +27,7 @@ export class Plugins implements IPublicApiPlugins {
return this[innerPluginsSymbol]; return this[innerPluginsSymbol];
} }
constructor(plugins: LowCodePluginManager, public workspaceMode: boolean = false) { constructor(plugins: ILowCodePluginManager, public workspaceMode: boolean = false) {
this[innerPluginsSymbol] = plugins; this[innerPluginsSymbol] = plugins;
} }

View File

@ -1,13 +1,13 @@
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types'; import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
import { Workspace as InnerWorkSpace } from '@alilc/lowcode-workspace'; import { IWorkspace } from '@alilc/lowcode-workspace';
import { Plugins } from '@alilc/lowcode-shell'; import { Plugins } from '@alilc/lowcode-shell';
import { workspaceSymbol } from '../symbols'; import { workspaceSymbol } from '../symbols';
import { Resource as ShellResource, Window as ShellWindow } from '../model'; import { Resource as ShellResource, Window as ShellWindow } from '../model';
export class Workspace implements IPublicApiWorkspace { export class Workspace implements IPublicApiWorkspace {
readonly [workspaceSymbol]: InnerWorkSpace; readonly [workspaceSymbol]: IWorkspace;
constructor(innerWorkspace: InnerWorkSpace) { constructor(innerWorkspace: IWorkspace) {
this[workspaceSymbol] = innerWorkspace; this[workspaceSymbol] = innerWorkspace;
} }

View File

@ -1,11 +1,11 @@
import { IPublicModelResource } from '@alilc/lowcode-types'; import { IPublicModelResource } from '@alilc/lowcode-types';
import { Resource as InnerResource } from '@alilc/lowcode-workspace'; import { IResource } from '@alilc/lowcode-workspace';
import { resourceSymbol } from '../symbols'; import { resourceSymbol } from '../symbols';
export class Resource implements IPublicModelResource { export class Resource implements IPublicModelResource {
readonly [resourceSymbol]: InnerResource; readonly [resourceSymbol]: IResource;
constructor(resource: InnerResource) { constructor(resource: IResource) {
this[resourceSymbol] = resource; this[resourceSymbol] = resource;
} }

View File

@ -1,10 +1,10 @@
import { windowSymbol } from '../symbols'; import { windowSymbol } from '../symbols';
import { IPublicModelResource, IPublicModelWindow, IPublicTypeDisposable } from '@alilc/lowcode-types'; import { IPublicModelResource, IPublicModelWindow, IPublicTypeDisposable } from '@alilc/lowcode-types';
import { EditorWindow } from '@alilc/lowcode-workspace'; import { IEditorWindow } from '@alilc/lowcode-workspace';
import { Resource as ShellResource } from './resource'; import { Resource as ShellResource } from './resource';
export class Window implements IPublicModelWindow { export class Window implements IPublicModelWindow {
private readonly [windowSymbol]: EditorWindow; private readonly [windowSymbol]: IEditorWindow;
get id() { get id() {
return this[windowSymbol]?.id; return this[windowSymbol]?.id;
@ -22,7 +22,7 @@ export class Window implements IPublicModelWindow {
return new ShellResource(this[windowSymbol].resource); return new ShellResource(this[windowSymbol].resource);
} }
constructor(editorWindow: EditorWindow) { constructor(editorWindow: IEditorWindow) {
this[windowSymbol] = editorWindow; this[windowSymbol] = editorWindow;
} }

View File

@ -2,19 +2,20 @@ import { IPublicModelWindow } from '../model';
import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types'; import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
export interface IPublicApiWorkspace< export interface IPublicApiWorkspace<
Plugins = IPublicApiPlugins Plugins = IPublicApiPlugins,
ModelWindow = IPublicModelWindow
> { > {
/** 是否启用 workspace 模式 */ /** 是否启用 workspace 模式 */
isActive: boolean; isActive: boolean;
/** 当前设计器窗口 */ /** 当前设计器窗口 */
window: IPublicModelWindow; window: ModelWindow;
plugins: Plugins; plugins: Plugins;
/** 当前设计器的编辑窗口 */ /** 当前设计器的编辑窗口 */
windows: IPublicModelWindow[]; windows: ModelWindow[];
/** 获取资源树列表 */ /** 获取资源树列表 */
get resourceList(): IPublicModelResource[]; get resourceList(): IPublicModelResource[];

View File

@ -1,8 +1,3 @@
export interface IPublicModelDragObject { import { IPublicTypeDragNodeDataObject, IPublicTypeDragNodeObject } from '../type';
get type(): any; export type IPublicModelDragObject = Readonly<IPublicTypeDragNodeObject> | Readonly<IPublicTypeDragNodeDataObject>;
get nodes(): any;
get data(): any;
}

View File

@ -1,6 +1,8 @@
import { ReactElement } from 'react'; import { ReactElement } from 'react';
export interface IPublicModelResource { export interface IBaseModelResource<
Resource
> {
get title(): string | undefined; get title(): string | undefined;
get icon(): ReactElement | undefined; get icon(): ReactElement | undefined;
@ -13,7 +15,9 @@ export interface IPublicModelResource {
get category(): string | undefined; get category(): string | undefined;
get children(): IPublicModelResource[]; get children(): Resource[];
get viewName(): string | undefined; get viewName(): string | undefined;
} }
export type IPublicModelResource = IBaseModelResource<IPublicModelResource>;

View File

@ -2,7 +2,9 @@ import { ReactElement } from 'react';
import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type'; import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type';
import { IPublicModelResource } from './resource'; import { IPublicModelResource } from './resource';
export interface IPublicModelWindow { export interface IPublicModelWindow<
Resource = IPublicModelResource
> {
/** 窗口 id */ /** 窗口 id */
id: string; id: string;
@ -14,7 +16,7 @@ export interface IPublicModelWindow {
icon?: ReactElement; icon?: ReactElement;
/** 窗口资源类型 */ /** 窗口资源类型 */
resource?: IPublicModelResource; resource?: Resource;
/** 当前窗口导入 schema */ /** 当前窗口导入 schema */
importSchema(schema: IPublicTypeNodeSchema): void; importSchema(schema: IPublicTypeNodeSchema): void;

View File

@ -1,19 +1,23 @@
import { IPublicModelNode } from '../model';
import { IPublicTypeIconType, TipContent } from './'; import { IPublicTypeIconType, TipContent } from './';
/** /**
* *
*/ */
export interface IPublicTypeActionContentObject { export interface IPublicTypeActionContentObject {
/** /**
* *
*/ */
icon?: IPublicTypeIconType; icon?: IPublicTypeIconType;
/** /**
* *
*/ */
title?: TipContent; title?: TipContent;
/** /**
* *
*/ */
action?: (currentNode: any) => void; action?: (currentNode: IPublicModelNode) => void;
} }

View File

@ -15,13 +15,14 @@ export enum LocationDetailType {
} }
export type IPublicTypeRect = DOMRect & { export type IPublicTypeRect = DOMRect & {
elements: Array<Element | Text>; elements?: Array<Element | Text>;
computed?: boolean; computed?: boolean;
}; };
export interface IPublicTypeLocationChildrenDetail { export interface IPublicTypeLocationChildrenDetail {
type: IPublicTypeLocationDetailType.Children; type: IPublicTypeLocationDetailType.Children;
index?: number | null; index?: number | null;
/** /**
* *
*/ */
@ -43,8 +44,7 @@ export interface IPublicTypeLocationPropDetail {
domNode?: HTMLElement; domNode?: HTMLElement;
} }
// eslint-disable-next-line max-len export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { [key: string]: any; type: string };
export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { type: string; [key: string]: any };
export interface IPublicTypeLocationData< export interface IPublicTypeLocationData<
Node = IPublicModelNode Node = IPublicModelNode

View File

@ -1,3 +1,4 @@
import { MouseEvent } from 'react';
import { IPublicTypePropType, IPublicTypeComponentAction } from './'; import { IPublicTypePropType, IPublicTypeComponentAction } from './';
import { IPublicModelNode, IPublicModelProp, IPublicModelSettingField } from '../model'; import { IPublicModelNode, IPublicModelProp, IPublicModelSettingField } from '../model';

View File

@ -1,20 +1,27 @@
import { ReactElement } from 'react'; import { ReactElement } from 'react';
export interface IPublicResourceData { export interface IPublicResourceData {
/** 资源名字 */ /** 资源名字 */
resourceName: string; resourceName: string;
/** 资源标题 */ /** 资源标题 */
title: string; title?: string;
/** 分类 */ /** 分类 */
category?: string; category?: string;
/** 资源视图 */ /** 资源视图 */
viewName?: string; viewName?: string;
/** 资源 icon */ /** 资源 icon */
icon?: ReactElement; icon?: ReactElement;
/** 资源其他配置 */ /** 资源其他配置 */
options: { options: {
[key: string]: any; [key: string]: any;
}; };
/** 资源子元素 */ /** 资源子元素 */
children?: IPublicResourceData[]; children?: IPublicResourceData[];
} }

View File

@ -1,4 +1,5 @@
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
export function isActionContentObject(obj: any): boolean { export function isActionContentObject(obj: any): obj is IPublicTypeActionContentObject {
return obj && typeof obj === 'object'; return obj && typeof obj === 'object';
} }

View File

@ -1,4 +1,5 @@
import { IPublicTypeLocationData } from '@alilc/lowcode-types';
export function isLocationData(obj: any): boolean { export function isLocationData(obj: any): obj is IPublicTypeLocationData {
return obj && obj.target && obj.detail; return obj && obj.target && obj.detail;
} }

View File

@ -10,14 +10,13 @@ const pseudoMap = ['hover', 'focus', 'active', 'visited'];
const RE_CAMEL = /[A-Z]/g; const RE_CAMEL = /[A-Z]/g;
const RE_HYPHEN = /[-\s]+(.)?/g; const RE_HYPHEN = /[-\s]+(.)?/g;
const CSS_REG = /:root(.*)\{.*/i;
const PROPS_REG = /([^:]*):\s?(.*)/i; const PROPS_REG = /([^:]*):\s?(.*)/i;
// 给 css 分组 // 给 css 分组
function groupingCss(css) { function groupingCss(css: string) {
let stackLength = 0; let stackLength = 0;
let startIndex = 0; let startIndex = 0;
const group = []; const group: string[] = [];
css.split('').forEach((char, index) => { css.split('').forEach((char, index) => {
if (char === '{') { if (char === '{') {
stackLength++; stackLength++;
@ -33,38 +32,38 @@ function groupingCss(css) {
return group; return group;
} }
function isString(str: any): str is string {
function isString(str) {
return {}.toString.call(str) === '[object String]'; return {}.toString.call(str) === '[object String]';
} }
function hyphenate(str) { function hyphenate(str: string): string {
return str.replace(RE_CAMEL, w => `-${w}`).toLowerCase(); return str.replace(RE_CAMEL, w => `-${w}`).toLowerCase();
} }
function camelize(str) { function camelize(str: string): string {
return str.replace(RE_HYPHEN, (m, w) => (w ? w.toUpperCase() : '')); return str.replace(RE_HYPHEN, (m, w) => (w ? w.toUpperCase() : ''));
} }
/** /**
* convert * convert
* {background-color: "red"} * {background-color: "red"}
* to * to
* background-color: red; * background-color: red;
*/ */
function runtimeToCss(runtime) { function runtimeToCss(runtime: Record<string, string>) {
const css = []; const css: string[] = [];
Object.keys(runtime).forEach((key) => { Object.keys(runtime).forEach((key) => {
css.push(` ${key}: ${runtime[key]};`); css.push(` ${key}: ${runtime[key]};`);
}); });
return css.join('\n'); return css.join('\n');
} }
function toNativeStyle(runtime) { function toNativeStyle(runtime: Record<string, string> | undefined) {
if (!runtime) { if (!runtime) {
return {}; return {};
} }
if (runtime.default) { if (runtime.default) {
const normalized = {}; const normalized: Record<string, string> = {};
Object.keys(runtime).forEach((pseudo) => { Object.keys(runtime).forEach((pseudo) => {
if (pseudo === 'extra') { if (pseudo === 'extra') {
normalized[pseudo] = runtime[pseudo]; normalized[pseudo] = runtime[pseudo];
@ -98,14 +97,13 @@ function normalizeStyle(style) {
return normalized; return normalized;
} }
const normalized = {}; const normalized: Record<string, string | Record<string, string>> = {};
Object.keys(style).forEach((key) => { Object.keys(style).forEach((key) => {
normalized[hyphenate(key)] = style[key]; normalized[hyphenate(key)] = style[key];
}); });
return normalized; return normalized;
} }
function toCss(runtime) { function toCss(runtime) {
if (!runtime) { if (!runtime) {
return ( return (
@ -115,7 +113,7 @@ function toCss(runtime) {
} }
if (runtime.default) { if (runtime.default) {
const css = []; const css: string[] = [];
Object.keys(runtime).forEach((pseudo) => { Object.keys(runtime).forEach((pseudo) => {
if (pseudo === 'extra') { if (pseudo === 'extra') {
Array.isArray(runtime.extra) && css.push(runtime.extra.join('\n')); Array.isArray(runtime.extra) && css.push(runtime.extra.join('\n'));
@ -140,11 +138,14 @@ ${runtimeToCss(normalizeStyle(runtime))}
); );
} }
function cssToRuntime(css) { function cssToRuntime(css: string) {
if (!css) { if (!css) {
return {}; return {};
} }
const runtime = {}; const runtime: {
extra?: string[];
default?: Record<string, string>;
} = {};
const groups = groupingCss(css); const groups = groupingCss(css);
groups.forEach((cssItem) => { groups.forEach((cssItem) => {
if (!cssItem.startsWith(':root')) { if (!cssItem.startsWith(':root')) {
@ -153,7 +154,7 @@ function cssToRuntime(css) {
} else { } else {
const res = /:root:?(.*)?{(.*)/ig.exec(cssItem.replace(/[\r\n]+/ig, '').trim()); const res = /:root:?(.*)?{(.*)/ig.exec(cssItem.replace(/[\r\n]+/ig, '').trim());
if (res) { if (res) {
let pseudo; let pseudo: string | undefined;
if (res[1] && res[1].trim() && some(pseudoMap, pse => res[1].indexOf(pse) === 0)) { if (res[1] && res[1].trim() && some(pseudoMap, pse => res[1].indexOf(pse) === 0)) {
pseudo = res[1].trim(); pseudo = res[1].trim();
@ -161,8 +162,8 @@ function cssToRuntime(css) {
pseudo = res[1]; pseudo = res[1];
} }
const s = {}; const s: Record<string, string> = {};
res[2].split(';').reduce((prev, next) => { res[2].split(';').reduce<string[]>((prev, next) => {
if (next.indexOf('base64') > -1) { if (next.indexOf('base64') > -1) {
prev[prev.length - 1] += `;${next}`; prev[prev.length - 1] += `;${next}`;
} else { } else {
@ -173,8 +174,8 @@ function cssToRuntime(css) {
if (item) { if (item) {
if (PROPS_REG.test(item)) { if (PROPS_REG.test(item)) {
const props = item.match(PROPS_REG); const props = item.match(PROPS_REG);
const key = props[1]; const key = props?.[1];
const value = props[2]; const value = props?.[2];
if (key && value) { if (key && value) {
s[key.trim()] = value.trim(); s[key.trim()] = value.trim();
} }
@ -182,10 +183,7 @@ function cssToRuntime(css) {
} }
}); });
if (!pseudo) { runtime[pseudo || 'default'] = s;
pseudo = 'default';
}
runtime[pseudo] = s;
} }
} }
}); });

View File

@ -23,7 +23,8 @@ export function isReactComponent(obj: any): obj is ComponentType<any> {
export function wrapReactClass(view: FunctionComponent) { export function wrapReactClass(view: FunctionComponent) {
let ViewComponentClass = class extends Component { let ViewComponentClass = class extends Component {
render() { render() {
return createElement(view, this.props); const { children, ...other } = this.props;
return createElement(view, other, children);
} }
} as any; } as any;
ViewComponentClass = cloneEnumerableProperty(ViewComponentClass, view); ViewComponentClass = cloneEnumerableProperty(ViewComponentClass, view);

View File

@ -1,5 +1,6 @@
// 仅使用类型 // 仅使用类型
import { IPublicModelNode } from '@alilc/lowcode-types'; import { IPublicModelNode } from '@alilc/lowcode-types';
import { MouseEvent } from 'react';
export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>( export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>(
node: Node, node: Node,
@ -12,7 +13,7 @@ export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>
return node; return node;
} else { } else {
// @ts-ignore // @ts-ignore
return getClosestNode(node.getParent(), until); return getClosestNode(node.parent, until);
} }
}; };
@ -22,8 +23,8 @@ export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>
* @param {unknown} e * @param {unknown} e
* @returns {boolean} true表示可点击 * @returns {boolean} true表示可点击
*/ */
export function canClickNode<Node extends IPublicModelNode = IPublicModelNode>(node: Node, e: unknown): boolean { export function canClickNode<Node extends IPublicModelNode = IPublicModelNode>(node: Node, e: MouseEvent): boolean {
const onClickHook = node.componentMeta?.advanced?.callbacks?.onClickHook; const onClickHook = node.componentMeta?.advanced?.callbacks?.onClickHook;
const canClick = typeof onClickHook === 'function' ? onClickHook(e as MouseEvent, node) : true; const canClick = typeof onClickHook === 'function' ? onClickHook(e, node) : true;
return canClick; return canClick;
}; }

View File

@ -3,13 +3,17 @@ import {
engineConfig, Setters as InnerSetters, engineConfig, Setters as InnerSetters,
Hotkey as InnerHotkey, Hotkey as InnerHotkey,
commonEvent, commonEvent,
IEngineConfig,
IHotKey,
} from '@alilc/lowcode-editor-core'; } from '@alilc/lowcode-editor-core';
import { import {
Designer, Designer,
ILowCodePluginContextApiAssembler, ILowCodePluginContextApiAssembler,
LowCodePluginManager, LowCodePluginManager,
ILowCodePluginContextPrivate, ILowCodePluginContextPrivate,
Project as InnerProject, IProject,
IDesigner,
ILowCodePluginManager,
} from '@alilc/lowcode-designer'; } from '@alilc/lowcode-designer';
import { import {
Skeleton as InnerSkeleton, Skeleton as InnerSkeleton,
@ -29,40 +33,72 @@ import {
} from '@alilc/lowcode-shell'; } from '@alilc/lowcode-shell';
import { import {
IPluginPreferenceMananger, IPluginPreferenceMananger,
IPublicApiCanvas,
IPublicApiCommon,
IPublicApiEvent, IPublicApiEvent,
IPublicApiWorkspace, IPublicApiHotkey,
IPublicApiMaterial,
IPublicApiPlugins,
IPublicApiProject,
IPublicApiSetters,
IPublicApiSkeleton,
IPublicModelPluginContext, IPublicModelPluginContext,
IPublicTypePluginMeta, IPublicTypePluginMeta,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
import { getLogger } from '@alilc/lowcode-utils'; import { getLogger, Logger as InnerLogger } from '@alilc/lowcode-utils';
import { Workspace as InnerWorkspace } from '../workspace'; import { IWorkspace } from '../workspace';
import { EditorWindow } from '../window'; import { IEditorWindow } from '../window';
export class BasicContext implements IPublicModelPluginContext { export interface IBasicContext extends Omit<IPublicModelPluginContext, 'workspace'> {
skeleton: Skeleton; skeleton: IPublicApiSkeleton;
plugins: Plugins; plugins: IPublicApiPlugins;
project: Project; project: IPublicApiProject;
setters: Setters; setters: IPublicApiSetters;
material: Material; material: IPublicApiMaterial;
common: Common; common: IPublicApiCommon;
config; config: IEngineConfig;
event; event: IPublicApiEvent;
logger; logger: InnerLogger;
hotkey: Hotkey; hotkey: IPublicApiHotkey;
innerProject: InnerProject; innerProject: IProject;
editor: Editor; editor: Editor;
designer: Designer; designer: IDesigner;
registerInnerPlugins: () => Promise<void>; registerInnerPlugins: () => Promise<void>;
innerSetters: InnerSetters; innerSetters: InnerSetters;
innerSkeleton: InnerSkeleton; innerSkeleton: InnerSkeleton;
innerHotkey: InnerHotkey; innerHotkey: IHotKey;
innerPlugins: LowCodePluginManager; innerPlugins: ILowCodePluginManager;
canvas: Canvas; canvas: IPublicApiCanvas;
pluginEvent: IPublicApiEvent; pluginEvent: IPublicApiEvent;
preference: IPluginPreferenceMananger; preference: IPluginPreferenceMananger;
workspace: IPublicApiWorkspace; workspace: IWorkspace;
}
constructor(innerWorkspace: InnerWorkspace, viewName: string, public editorWindow?: EditorWindow) { export class BasicContext implements IBasicContext {
skeleton: IPublicApiSkeleton;
plugins: IPublicApiPlugins;
project: IPublicApiProject;
setters: IPublicApiSetters;
material: IPublicApiMaterial;
common: IPublicApiCommon;
config: IEngineConfig;
event: IPublicApiEvent;
logger: InnerLogger;
hotkey: IPublicApiHotkey;
innerProject: IProject;
editor: Editor;
designer: IDesigner;
registerInnerPlugins: () => Promise<void>;
innerSetters: InnerSetters;
innerSkeleton: InnerSkeleton;
innerHotkey: IHotKey;
innerPlugins: ILowCodePluginManager;
canvas: IPublicApiCanvas;
pluginEvent: IPublicApiEvent;
preference: IPluginPreferenceMananger;
workspace: IWorkspace;
constructor(innerWorkspace: IWorkspace, viewName: string, public editorWindow?: IEditorWindow) {
const editor = new Editor(viewName, true); const editor = new Editor(viewName, true);
const innerSkeleton = new InnerSkeleton(editor, viewName); const innerSkeleton = new InnerSkeleton(editor, viewName);
@ -110,7 +146,7 @@ export class BasicContext implements IPublicModelPluginContext {
this.canvas = canvas; this.canvas = canvas;
const common = new Common(editor, innerSkeleton); const common = new Common(editor, innerSkeleton);
this.common = common; this.common = common;
let plugins: any; let plugins: IPublicApiPlugins;
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = { const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => { assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => {

View File

@ -1,9 +1,9 @@
import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core';
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types'; import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
import { flow } from 'mobx'; import { flow } from 'mobx';
import { Workspace as InnerWorkspace } from '../workspace'; import { IWorkspace } from '../workspace';
import { BasicContext } from './base-context'; import { BasicContext } from './base-context';
import { EditorWindow } from '../window'; import { IEditorWindow } from '../window';
import { getWebviewPlugin } from '../inner-plugins/webview'; import { getWebviewPlugin } from '../inner-plugins/webview';
export class Context extends BasicContext { export class Context extends BasicContext {
@ -21,7 +21,7 @@ export class Context extends BasicContext {
return this._activate; return this._activate;
} }
init = flow(function* (this: any) { init = flow(function* (this: Context) {
if (this.viewType === 'webview') { if (this.viewType === 'webview') {
const url = yield this.instance?.url?.(); const url = yield this.instance?.url?.();
yield this.plugins.register(getWebviewPlugin(url, this.viewName)); yield this.plugins.register(getWebviewPlugin(url, this.viewName));
@ -33,7 +33,7 @@ export class Context extends BasicContext {
this.isInit = true; this.isInit = true;
}); });
constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) { constructor(public workspace: IWorkspace, public editorWindow: IEditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) {
super(workspace, editorView.viewName, editorWindow); super(workspace, editorView.viewName, editorWindow);
this.viewType = editorView.viewType || 'editor'; this.viewType = editorView.viewType || 'editor';
this.viewName = editorView.viewName; this.viewName = editorView.viewName;

View File

@ -1,4 +1,4 @@
export { Workspace } from './workspace'; export { Workspace, IWorkspace } from './workspace';
export * from './window'; export * from './window';
export * from './layouts/workbench'; export * from './layouts/workbench';
export { Resource } from './resource'; export { Resource, IResource } from './resource';

View File

@ -1,6 +1,14 @@
import { IPublicTypeResourceType } from '@alilc/lowcode-types'; import { IPublicTypeResourceType } from '@alilc/lowcode-types';
export class ResourceType { export interface IResourceType extends Omit<IPublicTypeResourceType, 'resourceName' | 'resourceType'> {
name: string;
type: 'editor' | 'webview';
resourceTypeModel: IPublicTypeResourceType;
}
export class ResourceType implements IResourceType {
constructor(readonly resourceTypeModel: IPublicTypeResourceType) { constructor(readonly resourceTypeModel: IPublicTypeResourceType) {
} }

View File

@ -1,13 +1,31 @@
import { IPublicTypeEditorView, IPublicModelResource, IPublicResourceData, IPublicResourceTypeConfig } from '@alilc/lowcode-types'; import { IPublicTypeEditorView, IPublicResourceData, IPublicResourceTypeConfig, IBaseModelResource } from '@alilc/lowcode-types';
import { Logger } from '@alilc/lowcode-utils'; import { Logger } from '@alilc/lowcode-utils';
import { BasicContext } from './context/base-context'; import { BasicContext, IBasicContext } from './context/base-context';
import { ResourceType } from './resource-type'; import { ResourceType, IResourceType } from './resource-type';
import { Workspace as InnerWorkSpace } from './workspace'; import { IWorkspace } from './workspace';
const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' }); const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' });
export class Resource implements IPublicModelResource { export interface IBaseResource<T> extends IBaseModelResource<T> {
private context: BasicContext; readonly resourceType: ResourceType;
get editorViews(): IPublicTypeEditorView[];
get defaultViewType(): string;
getEditorView(name: string): IPublicTypeEditorView | undefined;
import(schema: any): Promise<any>;
save(value: any): Promise<any>;
url(): Promise<string | undefined>;
}
export type IResource = IBaseResource<IResource>;
export class Resource implements IResource {
private context: IBasicContext;
resourceTypeInstance: IPublicResourceTypeConfig; resourceTypeInstance: IPublicResourceTypeConfig;
@ -49,13 +67,13 @@ export class Resource implements IPublicModelResource {
return this.context.innerSkeleton; return this.context.innerSkeleton;
} }
get children(): Resource[] { get children(): IResource[] {
return this.resourceData?.children?.map(d => new Resource(d, this.resourceType, this.workspace)) || []; return this.resourceData?.children?.map(d => new Resource(d, this.resourceType, this.workspace)) || [];
} }
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, readonly workspace: InnerWorkSpace) { constructor(readonly resourceData: IPublicResourceData, readonly resourceType: IResourceType, readonly workspace: IWorkspace) {
this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`); this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, this.options); this.resourceTypeInstance = resourceType.resourceTypeModel(this.context.innerPlugins._getLowCodePluginContext(), this.options);
this.init(); this.init();
if (this.resourceTypeInstance.editorViews) { if (this.resourceTypeInstance.editorViews) {
this.resourceTypeInstance.editorViews.forEach((d: any) => { this.resourceTypeInstance.editorViews.forEach((d: any) => {

View File

@ -1,9 +1,10 @@
import { uniqueId } from '@alilc/lowcode-utils'; import { uniqueId } from '@alilc/lowcode-utils';
import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
import { Context } from './context/view-context'; import { Context } from './context/view-context';
import { Workspace } from './workspace'; import { IWorkspace } from './workspace';
import { Resource } from './resource'; import { IResource } from './resource';
import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable'; import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable';
import { IPublicModelWindow } from '@alilc/lowcode-types';
interface IWindowCOnfig { interface IWindowCOnfig {
title: string | undefined; title: string | undefined;
@ -11,7 +12,13 @@ interface IWindowCOnfig {
viewType?: string | undefined; viewType?: string | undefined;
} }
export class EditorWindow { export interface IEditorWindow extends Omit<IPublicModelWindow<IResource>, 'changeViewType'> {
readonly resource: IResource;
changeViewType: (name: string, ignoreEmit?: boolean) => void;
}
export class EditorWindow implements IEditorWindow {
id: string = uniqueId('window'); id: string = uniqueId('window');
icon: React.ReactElement | undefined; icon: React.ReactElement | undefined;
@ -27,7 +34,7 @@ export class EditorWindow {
@obx initReady = false; @obx initReady = false;
constructor(readonly resource: Resource, readonly workspace: Workspace, private config: IWindowCOnfig) { constructor(readonly resource: IResource, readonly workspace: IWorkspace, private config: IWindowCOnfig) {
makeObservable(this); makeObservable(this);
this.init(); this.init();
this.title = config.title; this.title = config.title;

View File

@ -1,23 +1,33 @@
import { Designer, LowCodePluginManager } from '@alilc/lowcode-designer'; import { IDesigner, ILowCodePluginManager, LowCodePluginManager } from '@alilc/lowcode-designer';
import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
import { Plugins } from '@alilc/lowcode-shell'; import { IPublicApiPlugins, IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType, IShellModelFactory } from '@alilc/lowcode-types';
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType } from '@alilc/lowcode-types';
import { BasicContext } from './context/base-context'; import { BasicContext } from './context/base-context';
import { EditorWindow } from './window'; import { EditorWindow, IEditorWindow } from './window';
import { Resource } from './resource'; import { IResource, Resource } from './resource';
import { ResourceType } from './resource-type'; import { IResourceType, ResourceType } from './resource-type';
enum event { enum EVENT {
ChangeWindow = 'change_window', CHANGE_WINDOW = 'change_window',
ChangeActiveWindow = 'change_active_window', CHANGE_ACTIVE_WINDOW = 'change_active_window',
} }
const CHANGE_EVENT = 'resource.list.change'; const CHANGE_EVENT = 'resource.list.change';
interface IWorkspace extends Omit<IPublicApiWorkspace< export interface IWorkspace extends Omit<IPublicApiWorkspace<
LowCodePluginManager LowCodePluginManager,
>, 'resourceList'> {} IEditorWindow
>, 'resourceList' | 'plugins'> {
readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise<void>;
readonly shellModelFactory: IShellModelFactory;
window: IEditorWindow;
plugins: ILowCodePluginManager;
getResourceList(): IResource[];
}
export class Workspace implements IWorkspace { export class Workspace implements IWorkspace {
context: BasicContext; context: BasicContext;
@ -28,7 +38,7 @@ export class Workspace implements IWorkspace {
private resourceTypeMap: Map<string, ResourceType> = new Map(); private resourceTypeMap: Map<string, ResourceType> = new Map();
private resourceList: Resource[] = []; private resourceList: IResource[] = [];
get skeleton() { get skeleton() {
return this.context.innerSkeleton; return this.context.innerSkeleton;
@ -50,14 +60,14 @@ export class Workspace implements IWorkspace {
return null; return null;
} }
@obx.ref windows: EditorWindow[] = []; @obx.ref windows: IEditorWindow[] = [];
editorWindowMap: Map<string, EditorWindow> = new Map<string, EditorWindow>(); editorWindowMap: Map<string, IEditorWindow> = new Map<string, IEditorWindow>();
@obx.ref window: EditorWindow; @obx.ref window: IEditorWindow;
constructor( constructor(
readonly registryInnerPlugin: (designer: Designer, editor: Editor, plugins: Plugins) => Promise<void>, readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise<void>,
readonly shellModelFactory: any, readonly shellModelFactory: any,
) { ) {
this.init(); this.init();
@ -74,7 +84,10 @@ export class Workspace implements IWorkspace {
return; return;
} }
const title = this.defaultResourceType.name; const title = this.defaultResourceType.name;
const resource = new Resource({}, this.defaultResourceType, this); const resource = new Resource({
resourceName: title,
options: {},
}, this.defaultResourceType, this);
this.window = new EditorWindow(resource, this, { this.window = new EditorWindow(resource, this, {
title, title,
}); });
@ -113,7 +126,7 @@ export class Workspace implements IWorkspace {
}; };
} }
getResourceType(resourceName: string): ResourceType { getResourceType(resourceName: string): IResourceType {
return this.resourceTypeMap.get(resourceName)!; return this.resourceTypeMap.get(resourceName)!;
} }
@ -139,7 +152,7 @@ export class Workspace implements IWorkspace {
} }
removeEditorWindow(resourceName: string) { removeEditorWindow(resourceName: string) {
const index = this.windows.findIndex(d => (d.resource.name === resourceName && d.title)); const index = this.windows.findIndex(d => (d.resource?.name === resourceName && d.title));
this.remove(index); this.remove(index);
} }
@ -157,7 +170,7 @@ export class Workspace implements IWorkspace {
console.error(`${name} resourceType is not available`); console.error(`${name} resourceType is not available`);
return; return;
} }
const filterWindows = this.windows.filter(d => (d.resource.name === name && d.resource.title == title)); const filterWindows = this.windows.filter(d => (d.resource?.name === name && d.resource.title == title));
if (filterWindows && filterWindows.length) { if (filterWindows && filterWindows.length) {
this.window = filterWindows[0]; this.window = filterWindows[0];
this.emitChangeActiveWindow(); this.emitChangeActiveWindow();
@ -180,24 +193,24 @@ export class Workspace implements IWorkspace {
} }
onChangeWindows(fn: () => void) { onChangeWindows(fn: () => void) {
this.emitter.on(event.ChangeWindow, fn); this.emitter.on(EVENT.CHANGE_WINDOW, fn);
return () => { return () => {
this.emitter.removeListener(event.ChangeWindow, fn); this.emitter.removeListener(EVENT.CHANGE_WINDOW, fn);
}; };
} }
emitChangeWindow() { emitChangeWindow() {
this.emitter.emit(event.ChangeWindow); this.emitter.emit(EVENT.CHANGE_WINDOW);
} }
emitChangeActiveWindow() { emitChangeActiveWindow() {
this.emitter.emit(event.ChangeActiveWindow); this.emitter.emit(EVENT.CHANGE_ACTIVE_WINDOW);
} }
onChangeActiveWindow(fn: () => void) { onChangeActiveWindow(fn: () => void) {
this.emitter.on(event.ChangeActiveWindow, fn); this.emitter.on(EVENT.CHANGE_ACTIVE_WINDOW, fn);
return () => { return () => {
this.emitter.removeListener(event.ChangeActiveWindow, fn); this.emitter.removeListener(EVENT.CHANGE_ACTIVE_WINDOW, fn);
}; };
} }
} }