Merge branch 'develop' into patch-3

This commit is contained in:
林熠 2023-07-13 09:20:55 +08:00 committed by GitHub
commit ce7e766b86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 89 additions and 45 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@alilc/lowcode-engine-docs", "name": "@alilc/lowcode-engine-docs",
"version": "1.0.32", "version": "1.0.33",
"description": "低代码引擎版本化文档", "description": "低代码引擎版本化文档",
"license": "MIT", "license": "MIT",
"files": [ "files": [

View File

@ -635,18 +635,20 @@ export default function createHelloWorldProjectBuilder() {
template: CodeGen.solutionParts.icejs.template, template: CodeGen.solutionParts.icejs.template,
plugins: { plugins: {
components: [ components: [
CodeGen.plugins.react.reactCommonDeps(), CodeGen.plugins.icejs.reactCommonDeps(),
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }), CodeGen.plugins.common.esModule({ fileType: 'jsx' }),
CodeGen.plugins.react.containerClass(), CodeGen.plugins.common.styleImport(),
CodeGen.plugins.react.containerInjectContext(), CodeGen.plugins.icejs.containerClass(),
CodeGen.plugins.react.containerInjectUtils(), CodeGen.plugins.icejs.containerInjectContext(),
CodeGen.plugins.react.containerInjectDataSourceEngine(), CodeGen.plugins.icejs.containerInjectUtils(),
CodeGen.plugins.react.containerInjectI18n(), CodeGen.plugins.icejs.containerInjectDataSourceEngine(),
CodeGen.plugins.react.containerInitState(), CodeGen.plugins.icejs.containerInjectI18n(),
CodeGen.plugins.react.containerLifeCycle(), CodeGen.plugins.icejs.containerInjectConstants(),
CodeGen.plugins.react.containerMethod(), CodeGen.plugins.icejs.containerInitState(),
CodeGen.plugins.icejs.containerLifeCycle(),
CodeGen.plugins.icejs.containerMethod(),
examplePlugin(), examplePlugin(),
CodeGen.plugins.react.jsx({ CodeGen.plugins.icejs.jsx({
nodeTypeMapping: { nodeTypeMapping: {
Div: 'div', Div: 'div',
Component: 'div', Component: 'div',
@ -657,18 +659,20 @@ export default function createHelloWorldProjectBuilder() {
CodeGen.plugins.style.css(), CodeGen.plugins.style.css(),
], ],
pages: [ pages: [
CodeGen.plugins.react.reactCommonDeps(), CodeGen.plugins.icejs.reactCommonDeps(),
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }), CodeGen.plugins.common.esModule({ fileType: 'jsx' }),
CodeGen.plugins.react.containerClass(), CodeGen.plugins.common.styleImport(),
CodeGen.plugins.react.containerInjectContext(), CodeGen.plugins.icejs.containerClass(),
CodeGen.plugins.react.containerInjectUtils(), CodeGen.plugins.icejs.containerInjectContext(),
CodeGen.plugins.react.containerInjectDataSourceEngine(), CodeGen.plugins.icejs.containerInjectUtils(),
CodeGen.plugins.react.containerInjectI18n(), CodeGen.plugins.icejs.containerInjectDataSourceEngine(),
CodeGen.plugins.react.containerInitState(), CodeGen.plugins.icejs.containerInjectI18n(),
CodeGen.plugins.react.containerLifeCycle(), CodeGen.plugins.icejs.containerInjectConstants(),
CodeGen.plugins.react.containerMethod(), CodeGen.plugins.icejs.containerInitState(),
CodeGen.plugins.icejs.containerLifeCycle(),
CodeGen.plugins.icejs.containerMethod(),
examplePlugin(), examplePlugin(),
CodeGen.plugins.react.jsx({ CodeGen.plugins.icejs.jsx({
nodeTypeMapping: { nodeTypeMapping: {
Div: 'div', Div: 'div',
Component: 'div', Component: 'div',
@ -679,13 +683,13 @@ export default function createHelloWorldProjectBuilder() {
CodeGen.plugins.style.css(), CodeGen.plugins.style.css(),
], ],
router: [ router: [
CodeGen.plugins.common.esmodule(), CodeGen.plugins.common.esModule(),
CodeGen.solutionParts.icejs.plugins.router(), CodeGen.solutionParts.icejs.plugins.router(),
], ],
entry: [CodeGen.solutionParts.icejs.plugins.entry()], entry: [CodeGen.solutionParts.icejs.plugins.entry()],
constants: [CodeGen.plugins.project.constants()], constants: [CodeGen.plugins.project.constants()],
utils: [ utils: [
CodeGen.plugins.common.esmodule(), CodeGen.plugins.common.esModule(),
CodeGen.plugins.project.utils('react'), CodeGen.plugins.project.utils('react'),
], ],
i18n: [CodeGen.plugins.project.i18n()], i18n: [CodeGen.plugins.project.i18n()],

View File

@ -45,6 +45,7 @@ export default function createIceJsProjectBuilder(
containerInjectUtils(), containerInjectUtils(),
containerInjectDataSourceEngine(), containerInjectDataSourceEngine(),
containerInjectI18n(), containerInjectI18n(),
containerInjectConstants(),
containerInitState(), containerInitState(),
containerLifeCycle(), containerLifeCycle(),
containerMethod(), containerMethod(),

View File

@ -45,6 +45,7 @@ export default function createIceJsProjectBuilder(
containerInjectUtils(), containerInjectUtils(),
containerInjectDataSourceEngine(), containerInjectDataSourceEngine(),
containerInjectI18n(), containerInjectI18n(),
containerInjectConstants(),
containerInitState(), containerInitState(),
containerLifeCycle(), containerLifeCycle(),
containerMethod(), containerMethod(),

View File

@ -4,7 +4,6 @@ import {
reaction, reaction,
computed, computed,
getPublicPath, getPublicPath,
focusTracker,
engineConfig, engineConfig,
globalLocale, globalLocale,
IReactionPublic, IReactionPublic,
@ -519,7 +518,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// bind hotkey & clipboard // bind hotkey & clipboard
const hotkey = this.designer.editor.get('innerHotkey'); const hotkey = this.designer.editor.get('innerHotkey');
hotkey.mount(this._contentWindow); hotkey.mount(this._contentWindow);
focusTracker.mount(this._contentWindow); const innerSkeleton = this.designer.editor.get('skeleton');
innerSkeleton.focusTracker.mount(this._contentWindow);
clipboard.injectCopyPaster(this._contentDocument); clipboard.injectCopyPaster(this._contentDocument);
// TODO: dispose the bindings // TODO: dispose the bindings

View File

@ -24,6 +24,9 @@ import { fireEvent } from '@testing-library/react';
import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory';
import { Setters, Workspace } from '@alilc/lowcode-shell'; import { Setters, Workspace } from '@alilc/lowcode-shell';
import { ILowCodePluginContextApiAssembler, ILowCodePluginContextPrivate, LowCodePluginManager } from '@alilc/lowcode-designer'; import { ILowCodePluginContextApiAssembler, ILowCodePluginContextPrivate, LowCodePluginManager } from '@alilc/lowcode-designer';
import {
Skeleton as InnerSkeleton,
} from '@alilc/lowcode-editor-skeleton';
describe('Host 测试', () => { describe('Host 测试', () => {
let editor: Editor; let editor: Editor;
@ -45,6 +48,8 @@ describe('Host 测试', () => {
const innerPlugins = new LowCodePluginManager(pluginContextApiAssembler); const innerPlugins = new LowCodePluginManager(pluginContextApiAssembler);
const innerWorkspace = new InnerWorkspace(() => {}, {}); const innerWorkspace = new InnerWorkspace(() => {}, {});
const workspace = new Workspace(innerWorkspace); const workspace = new Workspace(innerWorkspace);
const innerSkeleton = new InnerSkeleton(editor);
editor.set('skeleton' as any, innerSkeleton);
editor.set('innerHotkey', new InnerHotkey()) editor.set('innerHotkey', new InnerHotkey())
editor.set('setters', new Setters(new InnerSetters())); editor.set('setters', new Setters(new InnerSetters()));
editor.set('innerPlugins' as any, innerPlugins); editor.set('innerPlugins' as any, innerPlugins);

View File

@ -155,6 +155,10 @@ const VALID_ENGINE_OPTIONS = {
description: '是否开启应用级设计模式', description: '是否开启应用级设计模式',
default: false, default: false,
}, },
workspaceEmptyComponent: {
type: 'function',
description: '应用级设计模式下,窗口为空时展示的占位组件',
},
}; };
const getStrictModeValue = (engineOptions: IPublicTypeEngineOptions, defaultValue: boolean): boolean => { const getStrictModeValue = (engineOptions: IPublicTypeEngineOptions, defaultValue: boolean): boolean => {

View File

@ -1,4 +1,8 @@
export class FocusTracker { export class FocusTracker {
private actives: Focusable[] = [];
private modals: Array<{ checkDown: (e: MouseEvent) => boolean; checkOpen: () => boolean }> = [];
mount(win: Window) { mount(win: Window) {
const checkDown = (e: MouseEvent) => { const checkDown = (e: MouseEvent) => {
if (this.checkModalDown(e)) { if (this.checkModalDown(e)) {
@ -16,14 +20,10 @@ export class FocusTracker {
}; };
} }
private actives: Focusable[] = [];
get first() { get first() {
return this.actives[0]; return this.actives[0];
} }
private modals: Array<{ checkDown: (e: MouseEvent) => boolean; checkOpen: () => boolean }> = [];
addModal(checkDown: (e: MouseEvent) => boolean, checkOpen: () => boolean) { addModal(checkDown: (e: MouseEvent) => boolean, checkOpen: () => boolean) {
this.modals.push({ this.modals.push({
checkDown, checkDown,
@ -154,7 +154,3 @@ export class Focusable {
} }
} }
} }
export const focusTracker = new FocusTracker();
focusTracker.mount(window);

View File

@ -1,6 +1,6 @@
import { Component, Fragment } from 'react'; import { Component, Fragment } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { observer, Focusable, focusTracker } from '@alilc/lowcode-editor-core'; import { observer, Focusable } from '@alilc/lowcode-editor-core';
import { Area } from '../area'; import { Area } from '../area';
import { Panel } from '../widget/panel'; import { Panel } from '../widget/panel';
import { PanelConfig } from '../types'; import { PanelConfig } from '../types';
@ -31,7 +31,7 @@ export default class LeftFloatPane extends Component<{ area: Area<PanelConfig, P
area.skeleton.editor.removeListener('designer.drag', triggerClose); area.skeleton.editor.removeListener('designer.drag', triggerClose);
}; };
this.focusing = focusTracker.create({ this.focusing = area.skeleton.focusTracker.create({
range: (e) => { range: (e) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
if (!target) { if (!target) {

View File

@ -1,4 +1,4 @@
import { action, makeObservable, obx, engineConfig, IEditor } from '@alilc/lowcode-editor-core'; import { action, makeObservable, obx, engineConfig, IEditor, FocusTracker } from '@alilc/lowcode-editor-core';
import { import {
DockConfig, DockConfig,
PanelConfig, PanelConfig,
@ -83,6 +83,8 @@ export interface ISkeleton extends Omit<IPublicApiSkeleton,
readonly widgets: IWidget[]; readonly widgets: IWidget[];
readonly focusTracker: FocusTracker;
getPanel(name: string): Panel | undefined; getPanel(name: string): Panel | undefined;
getWidget(name: string): IWidget | undefined; getWidget(name: string): IWidget | undefined;
@ -133,6 +135,8 @@ export class Skeleton {
readonly widgets: IWidget[] = []; readonly widgets: IWidget[] = [];
readonly focusTracker = new FocusTracker();
constructor(readonly editor: IEditor, readonly viewName: string = 'global') { constructor(readonly editor: IEditor, readonly viewName: string = 'global') {
makeObservable(this); makeObservable(this);
this.leftArea = new Area( this.leftArea = new Area(
@ -245,6 +249,7 @@ export class Skeleton {
this.setupPlugins(); this.setupPlugins();
this.setupEvents(); this.setupEvents();
this.focusTracker.mount(window);
} }
/** /**

View File

@ -67,6 +67,11 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
locale, locale,
}); });
}); });
engineConfig.onGot('requestHandlersMap', (requestHandlersMap) => {
this.setState({
requestHandlersMap,
});
});
const { components, packages, extraEnvironment, utils } = assets; const { components, packages, extraEnvironment, utils } = assets;
const state = { const state = {
componentMetadatas: components || [], componentMetadatas: components || [],

View File

@ -30,6 +30,10 @@ export class Tree {
treeNode?.notifyExpandableChanged(); treeNode?.notifyExpandableChanged();
}); });
doc?.history.onChangeCursor(() => {
this.root?.notifyExpandableChanged();
});
doc?.onChangeNodeProp((info: IPublicTypePropChangeOptions) => { doc?.onChangeNodeProp((info: IPublicTypePropChangeOptions) => {
const { node, key } = info; const { node, key } = info;
if (key === '___title___') { if (key === '___title___') {

View File

@ -193,8 +193,8 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
getNode, getNode,
}); });
if (curDocumentId && cache.component.has(componentCacheId)) { if (curDocumentId && cache.component.has(componentCacheId) && (cache.component.get(componentCacheId).Comp === Comp)) {
return cache.component.get(componentCacheId); return cache.component.get(componentCacheId).LeafWrapper;
} }
class LeafHoc extends Component { class LeafHoc extends Component {
@ -590,7 +590,10 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
LeafWrapper.displayName = (Comp as any).displayName; LeafWrapper.displayName = (Comp as any).displayName;
cache.component.set(componentCacheId, LeafWrapper); cache.component.set(componentCacheId, {
LeafWrapper,
Comp,
});
return LeafWrapper; return LeafWrapper;
} }

View File

@ -1,6 +1,6 @@
import { Component, Fragment } from 'react'; import { Component, Fragment } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { observer, Focusable, focusTracker } from '@alilc/lowcode-editor-core'; import { observer, Focusable } from '@alilc/lowcode-editor-core';
import { Area, Panel } from '@alilc/lowcode-editor-skeleton'; import { Area, Panel } from '@alilc/lowcode-editor-skeleton';
@observer @observer
@ -29,7 +29,7 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
area.skeleton.editor.removeListener('designer.drag', triggerClose); area.skeleton.editor.removeListener('designer.drag', triggerClose);
}; };
this.focusing = focusTracker.create({ this.focusing = area.skeleton.focusTracker.create({
range: (e) => { range: (e) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
if (!target) { if (!target) {

View File

@ -1,5 +1,5 @@
import { Component } from 'react'; import { Component } from 'react';
import { TipContainer, observer } from '@alilc/lowcode-editor-core'; import { TipContainer, engineConfig, observer } from '@alilc/lowcode-editor-core';
import { WindowView } from '../view/window-view'; import { WindowView } from '../view/window-view';
import classNames from 'classnames'; import classNames from 'classnames';
import TopArea from './top-area'; import TopArea from './top-area';
@ -21,17 +21,29 @@ export class Workbench extends Component<{
components?: PluginClassSet; components?: PluginClassSet;
className?: string; className?: string;
topAreaItemClassName?: string; topAreaItemClassName?: string;
}, {
workspaceEmptyComponent: any;
}> { }> {
constructor(props: any) { constructor(props: any) {
super(props); super(props);
const { config, components, workspace } = this.props; const { config, components, workspace } = this.props;
const { skeleton } = workspace; const { skeleton } = workspace;
skeleton.buildFromConfig(config, components); skeleton.buildFromConfig(config, components);
engineConfig.onGot('workspaceEmptyComponent', (workspaceEmptyComponent) => {
this.setState({
workspaceEmptyComponent,
});
});
this.state = {
workspaceEmptyComponent: engineConfig.get('workspaceEmptyComponent'),
};
} }
render() { render() {
const { workspace, className, topAreaItemClassName } = this.props; const { workspace, className, topAreaItemClassName } = this.props;
const { skeleton } = workspace; const { skeleton } = workspace;
const WorkspaceEmptyComponent = this.state.workspaceEmptyComponent;
return ( return (
<div className={classNames('lc-workspace-workbench', className)}> <div className={classNames('lc-workspace-workbench', className)}>
<SkeletonContext.Provider value={skeleton}> <SkeletonContext.Provider value={skeleton}>
@ -53,6 +65,10 @@ export class Workbench extends Component<{
/> />
)) ))
} }
{
!workspace.windows.length && WorkspaceEmptyComponent ? <WorkspaceEmptyComponent /> : null
}
</div> </div>
</div> </div>
<MainArea area={skeleton.mainArea} /> <MainArea area={skeleton.mainArea} />

View File

@ -199,7 +199,7 @@ export class Workspace implements IWorkspace {
this.windows.splice(index, 1); this.windows.splice(index, 1);
if (this.window === window) { if (this.window === window) {
this.window = this.windows[index] || this.windows[index + 1] || this.windows[index - 1]; this.window = this.windows[index] || this.windows[index + 1] || this.windows[index - 1];
if (this.window.sleep) { if (this.window?.sleep) {
this.window.init(); this.window.init();
} }
this.emitChangeActiveWindow(); this.emitChangeActiveWindow();