From e737cba46aa46253a3185034c06d1c5d106ce55e Mon Sep 17 00:00:00 2001 From: liujuping Date: Mon, 20 Mar 2023 14:48:59 +0800 Subject: [PATCH] fix: fix workspace api ts defined --- .eslintrc.js | 2 +- .../bem-tools/border-selecting.tsx | 14 ++-- .../designer/src/builtin-simulator/host.ts | 65 +++++++------- .../builtin-simulator/node-selector/index.tsx | 30 ++++--- packages/designer/src/designer/designer.ts | 22 +++-- packages/designer/src/designer/dragon.ts | 14 ++-- .../designer/src/designer/offset-observer.ts | 14 ++-- .../designer/src/document/document-model.ts | 8 +- packages/designer/src/plugin/plugin-types.ts | 4 +- packages/designer/src/project/project.ts | 8 ++ packages/designer/src/simulator.ts | 7 +- packages/editor-core/src/hotkey.ts | 4 +- .../src/widgets/tip/tip-container.tsx | 5 +- packages/shell/src/api/plugins.ts | 8 +- packages/shell/src/api/workspace.ts | 6 +- packages/shell/src/model/resource.ts | 6 +- packages/shell/src/model/window.ts | 6 +- packages/types/src/shell/api/workspace.ts | 7 +- packages/types/src/shell/model/drag-object.ts | 9 +- packages/types/src/shell/model/resource.ts | 10 ++- packages/types/src/shell/model/window.ts | 6 +- .../src/shell/type/action-content-object.ts | 6 +- packages/types/src/shell/type/location.ts | 6 +- packages/types/src/shell/type/metadata.ts | 1 + .../types/src/shell/type/resource-list.ts | 9 +- .../check-types/is-action-content-object.ts | 3 +- .../utils/src/check-types/is-location-data.ts | 3 +- packages/utils/src/css-helper.ts | 48 +++++------ packages/utils/src/is-react.ts | 3 +- packages/utils/src/node-helper.ts | 9 +- .../workspace/src/context/base-context.ts | 84 +++++++++++++------ .../workspace/src/context/view-context.ts | 8 +- packages/workspace/src/index.ts | 4 +- packages/workspace/src/resource-type.ts | 10 ++- packages/workspace/src/resource.ts | 36 ++++++-- packages/workspace/src/window.ts | 15 +++- packages/workspace/src/workspace.ts | 67 +++++++++------ 37 files changed, 348 insertions(+), 219 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6c072c326..4d573688f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -52,6 +52,6 @@ module.exports = { 'error', { default: ['signature', 'field', 'constructor', 'method'] } ], - 'no-unused-vars': ['error', { "destructuredArrayIgnorePattern": "^_" }] + '@typescript-eslint/no-unused-vars': ['error'] }, }; diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx index da3c73ae5..75b4a3488 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx @@ -13,9 +13,9 @@ import { observer, computed, Tip, globalContext } from '@alilc/lowcode-editor-co import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils'; import { IPublicTypeActionContentObject } from '@alilc/lowcode-types'; import { BuiltinSimulatorHost } from '../host'; -import { OffsetObserver } from '../../designer'; -import { Node } from '../../document'; +import { INode, OffsetObserver } from '../../designer'; import NodeSelector from '../node-selector'; +import { ISimulatorHost } from '../../simulator'; @observer export class BorderSelectingInstance extends Component<{ @@ -116,8 +116,8 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { } } -function createAction(content: ReactNode | ComponentType | IPublicTypeActionContentObject, key: string, node: Node) { - if (isValidElement(content)) { +function createAction(content: ReactNode | ComponentType | IPublicTypeActionContentObject, key: string, node: INode) { + if (isValidElement<{ key: string; node: INode }>(content)) { return cloneElement(content, { key, node }); } if (isReactComponent(content)) { @@ -130,7 +130,7 @@ function createAction(content: ReactNode | ComponentType | IPublicTypeActio key={key} className="lc-borders-action" onClick={() => { - action && action(node); + action && action(node.internalToShellNode()!); const workspace = globalContext.get('workspace'); const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor'); const npm = node?.componentMeta?.npm; @@ -153,8 +153,8 @@ function createAction(content: ReactNode | ComponentType | IPublicTypeActio } @observer -export class BorderSelectingForNode extends Component<{ host: BuiltinSimulatorHost; node: Node }> { - get host(): BuiltinSimulatorHost { +export class BorderSelectingForNode extends Component<{ host: ISimulatorHost; node: INode }> { + get host(): ISimulatorHost { return this.props.host; } diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 6415a1b4c..b2a41b831 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -47,26 +47,26 @@ import { getRectTarget, CanvasPoint, Designer, + IDesigner, } from '../designer'; import { parseMetadata } from './utils/parse-metadata'; import { getClosestClickableNode } from './utils/clickable'; import { IPublicTypeComponentMetadata, - IPublicTypeComponentSchema, IPublicTypePackage, IPublicEnumTransitionType, IPublicEnumDragObjectType, - IPublicTypeDragNodeObject, IPublicTypeNodeInstance, IPublicTypeComponentInstance, IPublicTypeLocationChildrenDetail, IPublicTypeLocationDetailType, IPublicTypeRect, + IPublicModelNode, } from '@alilc/lowcode-types'; import { BuiltinSimulatorRenderer } from './renderer'; import { clipboard } from '../designer/clipboard'; import { LiveEditing } from './live-editing/live-editing'; -import { Project } from '../project'; +import { IProject, Project } from '../project'; import { IScroller } from '../designer/scroller'; import { isElementNode, isDOMNodeVisible } from '../utils/misc'; import { debounce } from 'lodash'; @@ -164,9 +164,9 @@ const defaultRaxEnvironment = [ export class BuiltinSimulatorHost implements ISimulatorHost { readonly isSimulator = true; - readonly project: Project; + readonly project: IProject; - readonly designer: Designer; + readonly designer: IDesigner; readonly viewport = new Viewport(); @@ -217,7 +217,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost { - this.project.currentDocument && detecting.leave(this.project.currentDocument) + this.project.currentDocument && detecting.leave(this.project.currentDocument); }; doc.addEventListener('mouseover', hover, true); @@ -812,7 +812,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost { const onMoveHook = node.componentMeta?.advanced.callbacks?.onMoveHook; const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook(node.internalToShellNode()) : true; - let parentContainerNode: Node | null = null; + let parentContainerNode: INode | null = null; let parentNode = node.parent; while (parentNode) { @@ -1254,7 +1255,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost, - e: ILocateEvent, ) { const { children } = container; - const document = this.project.currentDocument!; if (!children || children.isEmpty()) { return null; } - const nearDistance: any = null; const nearBy: any = null; for (let i = 0, l = children.size; i < l; i++) { let child = children.get(i); diff --git a/packages/designer/src/builtin-simulator/node-selector/index.tsx b/packages/designer/src/builtin-simulator/node-selector/index.tsx index 27211f224..09c8f1262 100644 --- a/packages/designer/src/builtin-simulator/node-selector/index.tsx +++ b/packages/designer/src/builtin-simulator/node-selector/index.tsx @@ -1,19 +1,19 @@ import { Overlay } from '@alifd/next'; -import React from 'react'; +import React, { MouseEvent } from 'react'; import { Title, globalContext } from '@alilc/lowcode-editor-core'; import { canClickNode } from '@alilc/lowcode-utils'; import './index.less'; -import { Node, INode } from '@alilc/lowcode-designer'; +import { INode } from '@alilc/lowcode-designer'; const { Popup } = Overlay; export interface IProps { - node: Node; + node: INode; } export interface IState { - parentNodes: Node[]; + parentNodes: INode[]; } type UnionNode = INode | null; @@ -26,14 +26,18 @@ export default class InstanceNodeSelector extends React.Component { + getParentNodes = (node: INode) => { const parentNodes: any[] = []; - const { focusNode } = node.document; + const focusNode = node.document?.focusNode; + + if (!focusNode) { + return null; + } if (node.contains(focusNode) || !focusNode.contains(node)) { return parentNodes; @@ -53,12 +57,12 @@ export default class InstanceNodeSelector extends React.Component (e: unknown) => { + onSelect = (node: INode) => (event: MouseEvent) => { if (!node) { return; } - const canClick = canClickNode(node, e as MouseEvent); + const canClick = canClickNode(node.internalToShellNode()!, event); if (canClick && typeof node.select === 'function') { node.select(); @@ -76,19 +80,19 @@ export default class InstanceNodeSelector extends React.Component (_: any, flag = true) => { + onMouseOver = (node: INode) => (_: any, flag = true) => { if (node && typeof node.hover === 'function') { node.hover(flag); } }; - onMouseOut = (node: Node) => (_: any, flag = false) => { + onMouseOut = (node: INode) => (_: any, flag = false) => { if (node && typeof node.hover === 'function') { node.hover(flag); } }; - renderNodes = (/* node: Node */) => { + renderNodes = () => { const nodes = this.state.parentNodes; if (!nodes || nodes.length < 1) { return null; @@ -136,7 +140,7 @@ export default class InstanceNodeSelector extends React.Component -
{this.renderNodes(node)}
+
{this.renderNodes()}
); diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index a1d05a8dd..74c1f51b2 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -16,17 +16,15 @@ import { IPublicModelScroller, IPublicTypeLocationData, IPublicEnumTransformStage, - IPublicModelDragon, - IPublicModelDropLocation, IPublicModelLocateEvent, } from '@alilc/lowcode-types'; 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 { ComponentMeta, IComponentMeta } from '../component-meta'; import { INodeSelector, Component } from '../simulator'; import { Scroller } from './scroller'; -import { Dragon, IDragon, ILocateEvent } from './dragon'; +import { Dragon, IDragon } from './dragon'; import { ActiveTracker, IActiveTracker } from './active-tracker'; import { Detecting } from './detecting'; import { DropLocation } from './location'; @@ -64,7 +62,11 @@ export interface DesignerProps { export interface IDesigner { readonly shellModelFactory: IShellModelFactory; - get dragon(): IPublicModelDragon; + viewName: string | undefined; + + readonly project: IProject; + + get dragon(): IDragon; get activeTracker(): IActiveTracker; @@ -78,6 +80,10 @@ export interface IDesigner { createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller; + refreshComponentMetasMap(): void; + + createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null; + /** * 创建插入位置,考虑放到 dragon 中 */ @@ -92,6 +98,8 @@ export interface IDesigner { generateMetadata?: () => IPublicTypeComponentMetadata | null, ): IComponentMeta; + clearLocation(): void; + createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null; getComponentMetasMap(): Map; @@ -118,7 +126,7 @@ export class Designer implements IDesigner { readonly detecting = new Detecting(); - readonly project: Project; + readonly project: IProject; readonly editor: IPublicModelEditor; @@ -140,7 +148,7 @@ export class Designer implements IDesigner { @obx.ref private _simulatorComponent?: ComponentType; - @obx.ref private _simulatorProps?: Record | ((project: Project) => object); + @obx.ref private _simulatorProps?: Record | ((project: IProject) => object); @obx.ref private _suspensed = false; diff --git a/packages/designer/src/designer/dragon.ts b/packages/designer/src/designer/dragon.ts index 2fc0ca3e5..a96c1eec2 100644 --- a/packages/designer/src/designer/dragon.ts +++ b/packages/designer/src/designer/dragon.ts @@ -11,9 +11,9 @@ import { IPublicModelSensor, } from '@alilc/lowcode-types'; import { setNativeSelection, cursor } from '@alilc/lowcode-utils'; -import { Node } from '../document'; +import { INode, Node } from '../document'; import { ISimulatorHost, isSimulatorHost } from '../simulator'; -import { Designer } from './designer'; +import { IDesigner } from './designer'; import { makeEventsHandler } from '../utils/misc'; export interface ILocateEvent extends IPublicModelLocateEvent { @@ -88,14 +88,14 @@ function getSourceSensor(dragObject: IPublicModelDragObject): ISimulatorHost | n if (!isDragNodeObject(dragObject)) { return null; } - return dragObject.nodes[0]?.document.simulator || null; + return dragObject.nodes[0]?.document?.simulator || null; } function isDragEvent(e: any): e is DragEvent { return e?.type?.startsWith('drag'); } -export interface IDragon extends IPublicModelDragon { +export interface IDragon extends IPublicModelDragon { emitter: IEventBus; } @@ -130,7 +130,7 @@ export class Dragon implements IDragon { emitter: IEventBus = createModuleEventBus('Dragon'); - constructor(readonly designer: Designer) { + constructor(readonly designer: IDesigner) { makeObservable(this); this.viewName = designer.viewName; } @@ -167,7 +167,7 @@ export class Dragon implements IDragon { * @param dragObject 拖拽对象 * @param boostEvent 拖拽初始时事件 */ - boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | IPublicModelNode) { + boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: INode | IPublicModelNode) { const { designer } = this; const masterSensors = this.getMasterSensors(); const handleEvents = makeEventsHandler(boostEvent, masterSensors); @@ -264,7 +264,7 @@ export class Dragon implements IDragon { this.emitter.emit('rgl.add.placeholder', { rglNode, fromRglNode, - node: locateEvent.dragObject.nodes[0], + node: locateEvent.dragObject?.nodes[0], event: e, }); designer.clearLocation(); diff --git a/packages/designer/src/designer/offset-observer.ts b/packages/designer/src/designer/offset-observer.ts index d9dd07dba..2cf5bfee2 100644 --- a/packages/designer/src/designer/offset-observer.ts +++ b/packages/designer/src/designer/offset-observer.ts @@ -2,7 +2,7 @@ import requestIdleCallback, { cancelIdleCallback } from 'ric-shim'; import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core'; import { uniqueId } from '@alilc/lowcode-utils'; import { INodeSelector, IViewport } from '../simulator'; -import { Node } from '../document'; +import { INode } from '../document'; export class OffsetObserver { readonly id = uniqueId('oobx'); @@ -93,11 +93,11 @@ export class OffsetObserver { private pid: number | undefined; - readonly viewport: IViewport; + readonly viewport: IViewport | undefined; private isRoot: boolean; - readonly node: Node; + readonly node: INode; readonly compute: () => void; @@ -105,10 +105,10 @@ export class OffsetObserver { const { node, instance } = nodeInstance; this.node = node; const doc = node.document; - const host = doc.simulator!; - const focusNode = doc.focusNode; + const host = doc?.simulator; + const focusNode = doc?.focusNode; this.isRoot = node.contains(focusNode!); - this.viewport = host.viewport; + this.viewport = host?.viewport; makeObservable(this); if (this.isRoot) { this.hasOffset = true; @@ -118,7 +118,7 @@ export class OffsetObserver { return; } - let pid: number; + let pid: number | undefined; const compute = () => { if (pid !== this.pid) { return; diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts index e44e21d35..2731aa5e6 100644 --- a/packages/designer/src/document/document-model.ts +++ b/packages/designer/src/document/document-model.ts @@ -35,7 +35,7 @@ import { isDragNodeDataObject, isNode, } from '@alilc/lowcode-utils'; -import { IProject, Project } from '../project'; +import { IProject } from '../project'; import { ISimulatorHost } from '../simulator'; import { IComponentMeta } from '../component-meta'; import { IDesigner, IHistory } from '../designer'; @@ -56,7 +56,7 @@ export type GetDataType = T extends undefined export interface IDocumentModel extends Omit< IPublicModelDocumentModel< ISelection, IHistory, - INode | IRootNode, + INode, IDropLocation, IModalNodesManager, IProject @@ -81,6 +81,8 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel< readonly designer: IDesigner; + selection: ISelection; + get rootNode(): INode | null; get simulator(): ISimulatorHost | null; @@ -98,8 +100,6 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel< get currentRoot(): INode | null; - selection: ISelection; - isBlank(): boolean; /** diff --git a/packages/designer/src/plugin/plugin-types.ts b/packages/designer/src/plugin/plugin-types.ts index 837fae4b1..61855020e 100644 --- a/packages/designer/src/plugin/plugin-types.ts +++ b/packages/designer/src/plugin/plugin-types.ts @@ -6,7 +6,6 @@ import { IPublicApiMaterial, IPublicApiEvent, IPublicApiCommon, - IPublicTypeCompositeObject, IPublicApiPlugins, IPublicTypePluginConfig, IPublicApiLogger, @@ -16,6 +15,7 @@ import { IPublicApiCanvas, IPublicApiWorkspace, IPublicTypePluginMeta, + IPublicTypePluginRegisterOptions, } from '@alilc/lowcode-types'; export type PluginPreference = Map>; @@ -72,7 +72,7 @@ export interface ILowCodePluginManagerCore { register( pluginModel: IPublicTypePlugin, pluginOptions?: any, - options?: IPublicTypeCompositeObject, + options?: IPublicTypePluginRegisterOptions, ): Promise; init(pluginPreference?: Map>): Promise; get(pluginName: string): ILowCodePluginRuntime | undefined; diff --git a/packages/designer/src/project/project.ts b/packages/designer/src/project/project.ts index 51db678ad..3204e5c8b 100644 --- a/packages/designer/src/project/project.ts +++ b/packages/designer/src/project/project.ts @@ -41,6 +41,14 @@ export interface IProject extends Omit< IBaseApiProject< get documents(): IDocumentModel[]; + get i18n(): { + [local: string]: { + [key: string]: any; + }; + }; + + mountSimulator(simulator: ISimulatorHost): void; + open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null; getDocumentByFileName(fileName: string): IDocumentModel | null; diff --git a/packages/designer/src/simulator.ts b/packages/designer/src/simulator.ts index 99586fb81..3a63a685b 100644 --- a/packages/designer/src/simulator.ts +++ b/packages/designer/src/simulator.ts @@ -1,8 +1,9 @@ import { ComponentType } from 'react'; 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 { INode } from './document'; +import { IProject } from './project'; export type AutoFit = '100%'; // eslint-disable-next-line no-redeclare @@ -89,6 +90,10 @@ export interface ISimulatorHost

extends IPublicModelSensor { readonly contentDocument?: Document; readonly renderer?: BuiltinSimulatorRenderer; + readonly project: IProject; + + readonly designer: IDesigner; + // dependsAsset // like react jQuery lodash // themesAsset // componentsAsset diff --git a/packages/editor-core/src/hotkey.ts b/packages/editor-core/src/hotkey.ts index 30390daca..adc74262a 100644 --- a/packages/editor-core/src/hotkey.ts +++ b/packages/editor-core/src/hotkey.ts @@ -339,8 +339,8 @@ function fireCallback(callback: IPublicTypeHotkeyCallback, e: KeyboardEvent, com } } -export interface IHotKey extends IPublicApiHotkey { - +export interface IHotKey extends Omit { + activate(activate: boolean): void; } export class Hotkey implements IHotKey { diff --git a/packages/editor-core/src/widgets/tip/tip-container.tsx b/packages/editor-core/src/widgets/tip/tip-container.tsx index ae494d540..619c10423 100644 --- a/packages/editor-core/src/widgets/tip/tip-container.tsx +++ b/packages/editor-core/src/widgets/tip/tip-container.tsx @@ -1,4 +1,5 @@ import { Component } from 'react'; +import ReactDOM from 'react-dom'; import { TipItem } from './tip-item'; import { tipHandler } from './tip-handler'; @@ -25,11 +26,13 @@ export class TipContainer extends Component { } render() { - return window.ReactDOM.createPortal( + ReactDOM.createPortal(

, document.querySelector('body')!, ); + + return null; } } diff --git a/packages/shell/src/api/plugins.ts b/packages/shell/src/api/plugins.ts index 6e2b9c6b7..e5a79edbd 100644 --- a/packages/shell/src/api/plugins.ts +++ b/packages/shell/src/api/plugins.ts @@ -1,5 +1,5 @@ import { - LowCodePluginManager, + ILowCodePluginManager, } from '@alilc/lowcode-designer'; import { globalContext } from '@alilc/lowcode-editor-core'; import { @@ -14,8 +14,8 @@ import { pluginsSymbol } from '../symbols'; const innerPluginsSymbol = Symbol('plugin'); export class Plugins implements IPublicApiPlugins { - private readonly [innerPluginsSymbol]: LowCodePluginManager; - get [pluginsSymbol](): LowCodePluginManager { + private readonly [innerPluginsSymbol]: ILowCodePluginManager; + get [pluginsSymbol](): ILowCodePluginManager { if (this.workspaceMode) { return this[innerPluginsSymbol]; } @@ -27,7 +27,7 @@ export class Plugins implements IPublicApiPlugins { return this[innerPluginsSymbol]; } - constructor(plugins: LowCodePluginManager, public workspaceMode: boolean = false) { + constructor(plugins: ILowCodePluginManager, public workspaceMode: boolean = false) { this[innerPluginsSymbol] = plugins; } diff --git a/packages/shell/src/api/workspace.ts b/packages/shell/src/api/workspace.ts index 54fccf426..ae4bc65aa 100644 --- a/packages/shell/src/api/workspace.ts +++ b/packages/shell/src/api/workspace.ts @@ -1,13 +1,13 @@ 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 { workspaceSymbol } from '../symbols'; import { Resource as ShellResource, Window as ShellWindow } from '../model'; export class Workspace implements IPublicApiWorkspace { - readonly [workspaceSymbol]: InnerWorkSpace; + readonly [workspaceSymbol]: IWorkspace; - constructor(innerWorkspace: InnerWorkSpace) { + constructor(innerWorkspace: IWorkspace) { this[workspaceSymbol] = innerWorkspace; } diff --git a/packages/shell/src/model/resource.ts b/packages/shell/src/model/resource.ts index 63435cdea..b2b065398 100644 --- a/packages/shell/src/model/resource.ts +++ b/packages/shell/src/model/resource.ts @@ -1,11 +1,11 @@ import { IPublicModelResource } from '@alilc/lowcode-types'; -import { Resource as InnerResource } from '@alilc/lowcode-workspace'; +import { IResource } from '@alilc/lowcode-workspace'; import { resourceSymbol } from '../symbols'; export class Resource implements IPublicModelResource { - readonly [resourceSymbol]: InnerResource; + readonly [resourceSymbol]: IResource; - constructor(resource: InnerResource) { + constructor(resource: IResource) { this[resourceSymbol] = resource; } diff --git a/packages/shell/src/model/window.ts b/packages/shell/src/model/window.ts index e2f17b889..b1263d541 100644 --- a/packages/shell/src/model/window.ts +++ b/packages/shell/src/model/window.ts @@ -1,10 +1,10 @@ import { windowSymbol } from '../symbols'; 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'; export class Window implements IPublicModelWindow { - private readonly [windowSymbol]: EditorWindow; + private readonly [windowSymbol]: IEditorWindow; get id() { return this[windowSymbol]?.id; @@ -22,7 +22,7 @@ export class Window implements IPublicModelWindow { return new ShellResource(this[windowSymbol].resource); } - constructor(editorWindow: EditorWindow) { + constructor(editorWindow: IEditorWindow) { this[windowSymbol] = editorWindow; } diff --git a/packages/types/src/shell/api/workspace.ts b/packages/types/src/shell/api/workspace.ts index c1be4cb7e..8c19846f7 100644 --- a/packages/types/src/shell/api/workspace.ts +++ b/packages/types/src/shell/api/workspace.ts @@ -2,19 +2,20 @@ import { IPublicModelWindow } from '../model'; import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types'; export interface IPublicApiWorkspace< - Plugins = IPublicApiPlugins + Plugins = IPublicApiPlugins, + ModelWindow = IPublicModelWindow > { /** 是否启用 workspace 模式 */ isActive: boolean; /** 当前设计器窗口 */ - window: IPublicModelWindow; + window: ModelWindow; plugins: Plugins; /** 当前设计器的编辑窗口 */ - windows: IPublicModelWindow[]; + windows: ModelWindow[]; /** 获取资源树列表 */ get resourceList(): IPublicModelResource[]; diff --git a/packages/types/src/shell/model/drag-object.ts b/packages/types/src/shell/model/drag-object.ts index 9169ea853..af404a2f0 100644 --- a/packages/types/src/shell/model/drag-object.ts +++ b/packages/types/src/shell/model/drag-object.ts @@ -1,8 +1,3 @@ -export interface IPublicModelDragObject { +import { IPublicTypeDragNodeDataObject, IPublicTypeDragNodeObject } from '../type'; - get type(): any; - - get nodes(): any; - - get data(): any; -} +export type IPublicModelDragObject = Readonly | Readonly; diff --git a/packages/types/src/shell/model/resource.ts b/packages/types/src/shell/model/resource.ts index c81776659..e18f3d503 100644 --- a/packages/types/src/shell/model/resource.ts +++ b/packages/types/src/shell/model/resource.ts @@ -1,6 +1,8 @@ import { ReactElement } from 'react'; -export interface IPublicModelResource { +export interface IBaseModelResource< + Resource +> { get title(): string | undefined; get icon(): ReactElement | undefined; @@ -13,7 +15,9 @@ export interface IPublicModelResource { get category(): string | undefined; - get children(): IPublicModelResource[]; + get children(): Resource[]; get viewName(): string | undefined; -} \ No newline at end of file +} + +export type IPublicModelResource = IBaseModelResource; diff --git a/packages/types/src/shell/model/window.ts b/packages/types/src/shell/model/window.ts index f772dc9f4..bb27ce317 100644 --- a/packages/types/src/shell/model/window.ts +++ b/packages/types/src/shell/model/window.ts @@ -2,7 +2,9 @@ import { ReactElement } from 'react'; import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type'; import { IPublicModelResource } from './resource'; -export interface IPublicModelWindow { +export interface IPublicModelWindow< + Resource = IPublicModelResource +> { /** 窗口 id */ id: string; @@ -14,7 +16,7 @@ export interface IPublicModelWindow { icon?: ReactElement; /** 窗口资源类型 */ - resource?: IPublicModelResource; + resource?: Resource; /** 当前窗口导入 schema */ importSchema(schema: IPublicTypeNodeSchema): void; diff --git a/packages/types/src/shell/type/action-content-object.ts b/packages/types/src/shell/type/action-content-object.ts index 25e913f02..cf3e0c048 100644 --- a/packages/types/src/shell/type/action-content-object.ts +++ b/packages/types/src/shell/type/action-content-object.ts @@ -1,19 +1,23 @@ +import { IPublicModelNode } from '../model'; import { IPublicTypeIconType, TipContent } from './'; /** * 动作描述 */ export interface IPublicTypeActionContentObject { + /** * 图标 */ icon?: IPublicTypeIconType; + /** * 描述 */ title?: TipContent; + /** * 执行动作 */ - action?: (currentNode: any) => void; + action?: (currentNode: IPublicModelNode) => void; } diff --git a/packages/types/src/shell/type/location.ts b/packages/types/src/shell/type/location.ts index c9e2df67f..4f8b59a7c 100644 --- a/packages/types/src/shell/type/location.ts +++ b/packages/types/src/shell/type/location.ts @@ -15,13 +15,14 @@ export enum LocationDetailType { } export type IPublicTypeRect = DOMRect & { - elements: Array; + elements?: Array; computed?: boolean; }; export interface IPublicTypeLocationChildrenDetail { type: IPublicTypeLocationDetailType.Children; index?: number | null; + /** * 是否有效位置 */ @@ -43,8 +44,7 @@ export interface IPublicTypeLocationPropDetail { domNode?: HTMLElement; } -// eslint-disable-next-line max-len -export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { type: string; [key: string]: any }; +export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { [key: string]: any; type: string }; export interface IPublicTypeLocationData< Node = IPublicModelNode diff --git a/packages/types/src/shell/type/metadata.ts b/packages/types/src/shell/type/metadata.ts index 7f972622b..7ed9dc6be 100644 --- a/packages/types/src/shell/type/metadata.ts +++ b/packages/types/src/shell/type/metadata.ts @@ -1,3 +1,4 @@ +import { MouseEvent } from 'react'; import { IPublicTypePropType, IPublicTypeComponentAction } from './'; import { IPublicModelNode, IPublicModelProp, IPublicModelSettingField } from '../model'; diff --git a/packages/types/src/shell/type/resource-list.ts b/packages/types/src/shell/type/resource-list.ts index db5e33dc8..5831d7b50 100644 --- a/packages/types/src/shell/type/resource-list.ts +++ b/packages/types/src/shell/type/resource-list.ts @@ -1,20 +1,27 @@ import { ReactElement } from 'react'; export interface IPublicResourceData { + /** 资源名字 */ resourceName: string; + /** 资源标题 */ - title: string; + title?: string; + /** 分类 */ category?: string; + /** 资源视图 */ viewName?: string; + /** 资源 icon */ icon?: ReactElement; + /** 资源其他配置 */ options: { [key: string]: any; }; + /** 资源子元素 */ children?: IPublicResourceData[]; } diff --git a/packages/utils/src/check-types/is-action-content-object.ts b/packages/utils/src/check-types/is-action-content-object.ts index 20c817177..4e9a6545a 100644 --- a/packages/utils/src/check-types/is-action-content-object.ts +++ b/packages/utils/src/check-types/is-action-content-object.ts @@ -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'; } diff --git a/packages/utils/src/check-types/is-location-data.ts b/packages/utils/src/check-types/is-location-data.ts index 3fa3a4204..8bb310346 100644 --- a/packages/utils/src/check-types/is-location-data.ts +++ b/packages/utils/src/check-types/is-location-data.ts @@ -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; } \ No newline at end of file diff --git a/packages/utils/src/css-helper.ts b/packages/utils/src/css-helper.ts index 9858d0d54..98bf1bbf0 100644 --- a/packages/utils/src/css-helper.ts +++ b/packages/utils/src/css-helper.ts @@ -10,14 +10,13 @@ const pseudoMap = ['hover', 'focus', 'active', 'visited']; const RE_CAMEL = /[A-Z]/g; const RE_HYPHEN = /[-\s]+(.)?/g; -const CSS_REG = /:root(.*)\{.*/i; const PROPS_REG = /([^:]*):\s?(.*)/i; // 给 css 分组 -function groupingCss(css) { +function groupingCss(css: string) { let stackLength = 0; let startIndex = 0; - const group = []; + const group: string[] = []; css.split('').forEach((char, index) => { if (char === '{') { stackLength++; @@ -33,38 +32,38 @@ function groupingCss(css) { return group; } - -function isString(str) { +function isString(str: any): str is string { return {}.toString.call(str) === '[object String]'; } -function hyphenate(str) { +function hyphenate(str: string): string { 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() : '')); } + /** * convert * {background-color: "red"} * to * background-color: red; */ -function runtimeToCss(runtime) { - const css = []; +function runtimeToCss(runtime: Record) { + const css: string[] = []; Object.keys(runtime).forEach((key) => { css.push(` ${key}: ${runtime[key]};`); }); return css.join('\n'); } -function toNativeStyle(runtime) { +function toNativeStyle(runtime: Record | undefined) { if (!runtime) { return {}; } if (runtime.default) { - const normalized = {}; + const normalized: Record = {}; Object.keys(runtime).forEach((pseudo) => { if (pseudo === 'extra') { normalized[pseudo] = runtime[pseudo]; @@ -98,14 +97,13 @@ function normalizeStyle(style) { return normalized; } - const normalized = {}; + const normalized: Record> = {}; Object.keys(style).forEach((key) => { normalized[hyphenate(key)] = style[key]; }); return normalized; } - function toCss(runtime) { if (!runtime) { return ( @@ -115,7 +113,7 @@ function toCss(runtime) { } if (runtime.default) { - const css = []; + const css: string[] = []; Object.keys(runtime).forEach((pseudo) => { if (pseudo === 'extra') { 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) { return {}; } - const runtime = {}; + const runtime: { + extra?: string[]; + default?: Record; + } = {}; const groups = groupingCss(css); groups.forEach((cssItem) => { if (!cssItem.startsWith(':root')) { @@ -153,7 +154,7 @@ function cssToRuntime(css) { } else { const res = /:root:?(.*)?{(.*)/ig.exec(cssItem.replace(/[\r\n]+/ig, '').trim()); if (res) { - let pseudo; + let pseudo: string | undefined; if (res[1] && res[1].trim() && some(pseudoMap, pse => res[1].indexOf(pse) === 0)) { pseudo = res[1].trim(); @@ -161,8 +162,8 @@ function cssToRuntime(css) { pseudo = res[1]; } - const s = {}; - res[2].split(';').reduce((prev, next) => { + const s: Record = {}; + res[2].split(';').reduce((prev, next) => { if (next.indexOf('base64') > -1) { prev[prev.length - 1] += `;${next}`; } else { @@ -173,8 +174,8 @@ function cssToRuntime(css) { if (item) { if (PROPS_REG.test(item)) { const props = item.match(PROPS_REG); - const key = props[1]; - const value = props[2]; + const key = props?.[1]; + const value = props?.[2]; if (key && value) { s[key.trim()] = value.trim(); } @@ -182,10 +183,7 @@ function cssToRuntime(css) { } }); - if (!pseudo) { - pseudo = 'default'; - } - runtime[pseudo] = s; + runtime[pseudo || 'default'] = s; } } }); diff --git a/packages/utils/src/is-react.ts b/packages/utils/src/is-react.ts index 02ef50fa6..1f17f9afc 100644 --- a/packages/utils/src/is-react.ts +++ b/packages/utils/src/is-react.ts @@ -23,7 +23,8 @@ export function isReactComponent(obj: any): obj is ComponentType { export function wrapReactClass(view: FunctionComponent) { let ViewComponentClass = class extends Component { render() { - return createElement(view, this.props); + const { children, ...other } = this.props; + return createElement(view, other, children); } } as any; ViewComponentClass = cloneEnumerableProperty(ViewComponentClass, view); diff --git a/packages/utils/src/node-helper.ts b/packages/utils/src/node-helper.ts index 55d42be4e..60102d679 100644 --- a/packages/utils/src/node-helper.ts +++ b/packages/utils/src/node-helper.ts @@ -1,5 +1,6 @@ // 仅使用类型 import { IPublicModelNode } from '@alilc/lowcode-types'; +import { MouseEvent } from 'react'; export const getClosestNode = ( node: Node, @@ -12,7 +13,7 @@ export const getClosestNode = return node; } else { // @ts-ignore - return getClosestNode(node.getParent(), until); + return getClosestNode(node.parent, until); } }; @@ -22,8 +23,8 @@ export const getClosestNode = * @param {unknown} e 点击事件 * @returns {boolean} 是否可点击,true表示可点击 */ -export function canClickNode(node: Node, e: unknown): boolean { +export function canClickNode(node: Node, e: MouseEvent): boolean { 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; -}; +} diff --git a/packages/workspace/src/context/base-context.ts b/packages/workspace/src/context/base-context.ts index b67842fe8..b82e25872 100644 --- a/packages/workspace/src/context/base-context.ts +++ b/packages/workspace/src/context/base-context.ts @@ -3,13 +3,17 @@ import { engineConfig, Setters as InnerSetters, Hotkey as InnerHotkey, commonEvent, + IEngineConfig, + IHotKey, } from '@alilc/lowcode-editor-core'; import { Designer, ILowCodePluginContextApiAssembler, LowCodePluginManager, ILowCodePluginContextPrivate, - Project as InnerProject, + IProject, + IDesigner, + ILowCodePluginManager, } from '@alilc/lowcode-designer'; import { Skeleton as InnerSkeleton, @@ -29,40 +33,72 @@ import { } from '@alilc/lowcode-shell'; import { IPluginPreferenceMananger, + IPublicApiCanvas, + IPublicApiCommon, IPublicApiEvent, - IPublicApiWorkspace, + IPublicApiHotkey, + IPublicApiMaterial, + IPublicApiPlugins, + IPublicApiProject, + IPublicApiSetters, + IPublicApiSkeleton, IPublicModelPluginContext, IPublicTypePluginMeta, } from '@alilc/lowcode-types'; -import { getLogger } from '@alilc/lowcode-utils'; -import { Workspace as InnerWorkspace } from '../workspace'; -import { EditorWindow } from '../window'; +import { getLogger, Logger as InnerLogger } from '@alilc/lowcode-utils'; +import { IWorkspace } from '../workspace'; +import { IEditorWindow } from '../window'; -export class BasicContext implements IPublicModelPluginContext { - skeleton: Skeleton; - plugins: Plugins; - project: Project; - setters: Setters; - material: Material; - common: Common; - config; - event; - logger; - hotkey: Hotkey; - innerProject: InnerProject; +export interface IBasicContext extends Omit { + 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: Designer; + designer: IDesigner; registerInnerPlugins: () => Promise; innerSetters: InnerSetters; innerSkeleton: InnerSkeleton; - innerHotkey: InnerHotkey; - innerPlugins: LowCodePluginManager; - canvas: Canvas; + innerHotkey: IHotKey; + innerPlugins: ILowCodePluginManager; + canvas: IPublicApiCanvas; pluginEvent: IPublicApiEvent; 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; + 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 innerSkeleton = new InnerSkeleton(editor, viewName); @@ -110,7 +146,7 @@ export class BasicContext implements IPublicModelPluginContext { this.canvas = canvas; const common = new Common(editor, innerSkeleton); this.common = common; - let plugins: any; + let plugins: IPublicApiPlugins; const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = { assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => { diff --git a/packages/workspace/src/context/view-context.ts b/packages/workspace/src/context/view-context.ts index d14549667..38a9e570f 100644 --- a/packages/workspace/src/context/view-context.ts +++ b/packages/workspace/src/context/view-context.ts @@ -1,9 +1,9 @@ import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types'; import { flow } from 'mobx'; -import { Workspace as InnerWorkspace } from '../workspace'; +import { IWorkspace } from '../workspace'; import { BasicContext } from './base-context'; -import { EditorWindow } from '../window'; +import { IEditorWindow } from '../window'; import { getWebviewPlugin } from '../inner-plugins/webview'; export class Context extends BasicContext { @@ -21,7 +21,7 @@ export class Context extends BasicContext { return this._activate; } - init = flow(function* (this: any) { + init = flow(function* (this: Context) { if (this.viewType === 'webview') { const url = yield this.instance?.url?.(); yield this.plugins.register(getWebviewPlugin(url, this.viewName)); @@ -33,7 +33,7 @@ export class Context extends BasicContext { 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); this.viewType = editorView.viewType || 'editor'; this.viewName = editorView.viewName; diff --git a/packages/workspace/src/index.ts b/packages/workspace/src/index.ts index 9442266bb..157219e9f 100644 --- a/packages/workspace/src/index.ts +++ b/packages/workspace/src/index.ts @@ -1,4 +1,4 @@ -export { Workspace } from './workspace'; +export { Workspace, IWorkspace } from './workspace'; export * from './window'; export * from './layouts/workbench'; -export { Resource } from './resource'; +export { Resource, IResource } from './resource'; diff --git a/packages/workspace/src/resource-type.ts b/packages/workspace/src/resource-type.ts index b52183068..28d54e56b 100644 --- a/packages/workspace/src/resource-type.ts +++ b/packages/workspace/src/resource-type.ts @@ -1,6 +1,14 @@ import { IPublicTypeResourceType } from '@alilc/lowcode-types'; -export class ResourceType { +export interface IResourceType extends Omit { + name: string; + + type: 'editor' | 'webview'; + + resourceTypeModel: IPublicTypeResourceType; +} + +export class ResourceType implements IResourceType { constructor(readonly resourceTypeModel: IPublicTypeResourceType) { } diff --git a/packages/workspace/src/resource.ts b/packages/workspace/src/resource.ts index ffb60ff6a..e9033cca7 100644 --- a/packages/workspace/src/resource.ts +++ b/packages/workspace/src/resource.ts @@ -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 { BasicContext } from './context/base-context'; -import { ResourceType } from './resource-type'; -import { Workspace as InnerWorkSpace } from './workspace'; +import { BasicContext, IBasicContext } from './context/base-context'; +import { ResourceType, IResourceType } from './resource-type'; +import { IWorkspace } from './workspace'; const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' }); -export class Resource implements IPublicModelResource { - private context: BasicContext; +export interface IBaseResource extends IBaseModelResource { + readonly resourceType: ResourceType; + + get editorViews(): IPublicTypeEditorView[]; + + get defaultViewType(): string; + + getEditorView(name: string): IPublicTypeEditorView | undefined; + + import(schema: any): Promise; + + save(value: any): Promise; + + url(): Promise; +} + +export type IResource = IBaseResource; + +export class Resource implements IResource { + private context: IBasicContext; resourceTypeInstance: IPublicResourceTypeConfig; @@ -49,13 +67,13 @@ export class Resource implements IPublicModelResource { return this.context.innerSkeleton; } - get children(): Resource[] { + get children(): IResource[] { 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.resourceTypeInstance = resourceType.resourceTypeModel(this.context, this.options); + this.resourceTypeInstance = resourceType.resourceTypeModel(this.context.innerPlugins._getLowCodePluginContext(), this.options); this.init(); if (this.resourceTypeInstance.editorViews) { this.resourceTypeInstance.editorViews.forEach((d: any) => { diff --git a/packages/workspace/src/window.ts b/packages/workspace/src/window.ts index e7e08757f..1fa426524 100644 --- a/packages/workspace/src/window.ts +++ b/packages/workspace/src/window.ts @@ -1,9 +1,10 @@ import { uniqueId } from '@alilc/lowcode-utils'; import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { Context } from './context/view-context'; -import { Workspace } from './workspace'; -import { Resource } from './resource'; +import { IWorkspace } from './workspace'; +import { IResource } from './resource'; import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable'; +import { IPublicModelWindow } from '@alilc/lowcode-types'; interface IWindowCOnfig { title: string | undefined; @@ -11,7 +12,13 @@ interface IWindowCOnfig { viewType?: string | undefined; } -export class EditorWindow { +export interface IEditorWindow extends Omit, 'changeViewType'> { + readonly resource: IResource; + + changeViewType: (name: string, ignoreEmit?: boolean) => void; +} + +export class EditorWindow implements IEditorWindow { id: string = uniqueId('window'); icon: React.ReactElement | undefined; @@ -27,7 +34,7 @@ export class EditorWindow { @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); this.init(); this.title = config.title; diff --git a/packages/workspace/src/workspace.ts b/packages/workspace/src/workspace.ts index f7d49ed49..526e1f2ca 100644 --- a/packages/workspace/src/workspace.ts +++ b/packages/workspace/src/workspace.ts @@ -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 { Plugins } from '@alilc/lowcode-shell'; -import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType } from '@alilc/lowcode-types'; +import { IPublicApiPlugins, IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType, IShellModelFactory } from '@alilc/lowcode-types'; import { BasicContext } from './context/base-context'; -import { EditorWindow } from './window'; -import { Resource } from './resource'; -import { ResourceType } from './resource-type'; +import { EditorWindow, IEditorWindow } from './window'; +import { IResource, Resource } from './resource'; +import { IResourceType, ResourceType } from './resource-type'; -enum event { - ChangeWindow = 'change_window', +enum EVENT { + CHANGE_WINDOW = 'change_window', - ChangeActiveWindow = 'change_active_window', + CHANGE_ACTIVE_WINDOW = 'change_active_window', } const CHANGE_EVENT = 'resource.list.change'; -interface IWorkspace extends Omit, 'resourceList'> {} +export interface IWorkspace extends Omit, 'resourceList' | 'plugins'> { + readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise; + + readonly shellModelFactory: IShellModelFactory; + + window: IEditorWindow; + + plugins: ILowCodePluginManager; + + getResourceList(): IResource[]; +} export class Workspace implements IWorkspace { context: BasicContext; @@ -28,7 +38,7 @@ export class Workspace implements IWorkspace { private resourceTypeMap: Map = new Map(); - private resourceList: Resource[] = []; + private resourceList: IResource[] = []; get skeleton() { return this.context.innerSkeleton; @@ -50,14 +60,14 @@ export class Workspace implements IWorkspace { return null; } - @obx.ref windows: EditorWindow[] = []; + @obx.ref windows: IEditorWindow[] = []; - editorWindowMap: Map = new Map(); + editorWindowMap: Map = new Map(); - @obx.ref window: EditorWindow; + @obx.ref window: IEditorWindow; constructor( - readonly registryInnerPlugin: (designer: Designer, editor: Editor, plugins: Plugins) => Promise, + readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise, readonly shellModelFactory: any, ) { this.init(); @@ -74,7 +84,10 @@ export class Workspace implements IWorkspace { return; } 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, { title, }); @@ -113,7 +126,7 @@ export class Workspace implements IWorkspace { }; } - getResourceType(resourceName: string): ResourceType { + getResourceType(resourceName: string): IResourceType { return this.resourceTypeMap.get(resourceName)!; } @@ -139,7 +152,7 @@ export class Workspace implements IWorkspace { } 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); } @@ -157,7 +170,7 @@ export class Workspace implements IWorkspace { console.error(`${name} resourceType is not available`); 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) { this.window = filterWindows[0]; this.emitChangeActiveWindow(); @@ -180,24 +193,24 @@ export class Workspace implements IWorkspace { } onChangeWindows(fn: () => void) { - this.emitter.on(event.ChangeWindow, fn); + this.emitter.on(EVENT.CHANGE_WINDOW, fn); return () => { - this.emitter.removeListener(event.ChangeWindow, fn); + this.emitter.removeListener(EVENT.CHANGE_WINDOW, fn); }; } emitChangeWindow() { - this.emitter.emit(event.ChangeWindow); + this.emitter.emit(EVENT.CHANGE_WINDOW); } emitChangeActiveWindow() { - this.emitter.emit(event.ChangeActiveWindow); + this.emitter.emit(EVENT.CHANGE_ACTIVE_WINDOW); } onChangeActiveWindow(fn: () => void) { - this.emitter.on(event.ChangeActiveWindow, fn); + this.emitter.on(EVENT.CHANGE_ACTIVE_WINDOW, fn); return () => { - this.emitter.removeListener(event.ChangeActiveWindow, fn); + this.emitter.removeListener(EVENT.CHANGE_ACTIVE_WINDOW, fn); }; } }