mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-02-28 12:50:38 +00:00
add onceGot
This commit is contained in:
parent
0e877e64d5
commit
5dc04152d5
@ -31,6 +31,15 @@ export interface GetOptions {
|
|||||||
forceNew?: boolean;
|
forceNew?: boolean;
|
||||||
sourceCls?: ClassType;
|
sourceCls?: ClassType;
|
||||||
}
|
}
|
||||||
|
export type GetReturnType<T, ClsType> = T extends undefined
|
||||||
|
? ClsType extends {
|
||||||
|
prototype: infer R;
|
||||||
|
}
|
||||||
|
? R
|
||||||
|
: any
|
||||||
|
: T;
|
||||||
|
|
||||||
|
const NOT_FOUND = Symbol.for('not_found');
|
||||||
|
|
||||||
export default class Editor extends EventEmitter {
|
export default class Editor extends EventEmitter {
|
||||||
static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => {
|
static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => {
|
||||||
@ -55,7 +64,9 @@ export default class Editor extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Ioc Container
|
* Ioc Container
|
||||||
*/
|
*/
|
||||||
readonly context = new IocContext();
|
private context = new IocContext({
|
||||||
|
notFoundHandler: (type: KeyType) => NOT_FOUND,
|
||||||
|
});
|
||||||
|
|
||||||
pluginStatus?: PluginStatusSet;
|
pluginStatus?: PluginStatusSet;
|
||||||
|
|
||||||
@ -86,8 +97,7 @@ export default class Editor extends EventEmitter {
|
|||||||
registShortCuts(shortCuts, this);
|
registShortCuts(shortCuts, this);
|
||||||
this.emit('editor.afterInit');
|
this.emit('editor.afterInit');
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,8 +115,12 @@ export default class Editor extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get<T = undefined, KeyOrType = any>(keyOrType: KeyOrType, opt?: GetOptions) {
|
get<T = undefined, KeyOrType = any>(keyOrType: KeyOrType, opt?: GetOptions): GetReturnType<T, KeyOrType> | undefined {
|
||||||
return this.context.get<T, KeyOrType>(keyOrType, opt);
|
const x = this.context.get<T, KeyOrType>(keyOrType, opt);
|
||||||
|
if (x === NOT_FOUND) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
has(keyOrType: KeyType): boolean {
|
has(keyOrType: KeyType): boolean {
|
||||||
@ -114,11 +128,79 @@ export default class Editor extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set(key: KeyType, data: any): void {
|
set(key: KeyType, data: any): void {
|
||||||
this.context.register(data, key);
|
if (this.context.has(key)) {
|
||||||
|
this.context.replace(key, data, undefined, true);
|
||||||
|
} else {
|
||||||
|
this.context.register(data, key);
|
||||||
|
}
|
||||||
|
this.notifyGot(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private waits = new Map<
|
||||||
|
KeyType,
|
||||||
|
Array<{
|
||||||
|
once?: boolean;
|
||||||
|
resolve: (data: any) => void;
|
||||||
|
}>
|
||||||
|
>();
|
||||||
|
private notifyGot(key: KeyType) {
|
||||||
|
let waits = this.waits.get(key);
|
||||||
|
if (!waits) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
waits = waits.slice().reverse();
|
||||||
|
let i = waits.length;
|
||||||
|
while (i--) {
|
||||||
|
waits[i].resolve(this.get(key));
|
||||||
|
if (waits[i].once) {
|
||||||
|
waits.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (waits.length > 0) {
|
||||||
|
this.waits.set(key, waits);
|
||||||
|
} else {
|
||||||
|
this.waits.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setWait(key: KeyType, resolve: (data: any) => void, once?: boolean) {
|
||||||
|
const waits = this.waits.get(key);
|
||||||
|
if (waits) {
|
||||||
|
waits.push({ resolve, once });
|
||||||
|
} else {
|
||||||
|
this.waits.set(key, [{ resolve, once }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onceGot<T = undefined, KeyOrType extends KeyType = any>(keyOrType: KeyOrType): Promise<GetReturnType<T, KeyOrType>> {
|
||||||
|
const x = this.context.get<T, KeyOrType>(keyOrType);
|
||||||
|
if (x !== NOT_FOUND) {
|
||||||
|
return Promise.resolve(x);
|
||||||
|
}
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.setWait(keyOrType, resolve, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onGot<T = undefined, KeyOrType extends KeyType = any>(
|
||||||
|
keyOrType: KeyOrType,
|
||||||
|
fn: (data: GetReturnType<T, KeyOrType>) => void,
|
||||||
|
): () => void {
|
||||||
|
const x = this.context.get<T, KeyOrType>(keyOrType);
|
||||||
|
if (x !== NOT_FOUND) {
|
||||||
|
fn(x);
|
||||||
|
return () => {};
|
||||||
|
} else {
|
||||||
|
this.setWait(keyOrType, fn);
|
||||||
|
return () => {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
register(data: any, key?: KeyType, options?: RegisterOptions): void {
|
register(data: any, key?: KeyType, options?: RegisterOptions): void {
|
||||||
this.context.register(data, key, options);
|
this.context.register(data, key, options);
|
||||||
|
this.notifyGot(key || data);
|
||||||
}
|
}
|
||||||
|
|
||||||
batchOn(events: string[], lisenter: (...args: any[]) => void): void {
|
batchOn(events: string[], lisenter: (...args: any[]) => void): void {
|
||||||
|
|||||||
@ -144,8 +144,8 @@ export default class Mixin extends PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let TargetNode = this.typeMap[this.state.type]['component'] || 'div';
|
let TargetNode = this.typeMap[this.state.type]?.component || 'div';
|
||||||
let targetProps = this.typeMap[this.state.type]['props'] || {};
|
let targetProps = this.typeMap[this.state.type]?.props || {};
|
||||||
let tarStyle = { position: 'relative', ...style };
|
let tarStyle = { position: 'relative', ...style };
|
||||||
let classes = classNames(className, 'lowcode-setter-mixin');
|
let classes = classNames(className, 'lowcode-setter-mixin');
|
||||||
|
|
||||||
|
|||||||
@ -14,11 +14,11 @@
|
|||||||
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
|
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
|
||||||
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
||||||
<!-- lowcode engine globals -->
|
<!-- lowcode engine globals -->
|
||||||
<link rel="stylesheet" href="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.8.0/globals.css" />
|
<link rel="stylesheet" href="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- lowcode engine globals -->
|
<!-- lowcode engine globals -->
|
||||||
<script src="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.8.0/globals.js"></script>
|
<script src="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,3 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* 拒绝
|
||||||
|
*/
|
||||||
|
export type REJECTED = 0 | false;
|
||||||
|
/**
|
||||||
|
* 限制性的
|
||||||
|
*/
|
||||||
|
export type LIMITED = 2;
|
||||||
|
/**
|
||||||
|
* 允许
|
||||||
|
*/
|
||||||
|
export type ALLOWED = true | 4;
|
||||||
|
|
||||||
|
export type HandleState = REJECTED | ALLOWED | LIMITED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* model.editing:(dbclick) 父级优先(捕获过程)
|
||||||
|
* asCode(gotocode) 默认行为 select - option
|
||||||
|
* asRichText (运行值)
|
||||||
|
* asPlainText (运行值) 仅包含
|
||||||
|
* null|undefined 不响应(默认值)
|
||||||
|
* false 禁用 阻止继续捕获
|
||||||
|
* handle-function
|
||||||
|
*
|
||||||
|
* ## 检查与控制 handle
|
||||||
|
*
|
||||||
|
* model.shouldRemoveChild: HandleState | (my, child) => HandleState 移除子节点时(触发时),return false,拒绝移除
|
||||||
|
* model.shouldMoveChild: HandleState | (my, child) => HandleState 移动子节点, return false: 拒绝移动; return 0: 不得改变嵌套关系
|
||||||
|
* model.shouldRemove: HandleState | (my) => HandleState
|
||||||
|
* model.shouldMove: HandleState | (my) => HandleState return false, 拒绝移动 return 0; 不得改变嵌套关系
|
||||||
|
*
|
||||||
|
* ## 类型嵌套检查 (白名单机制)
|
||||||
|
*
|
||||||
|
* 自定义 locate
|
||||||
|
* model.locate: (my, transferData, mouseEvent?) => Location | null, 用于非 node 节点任意数据的定位
|
||||||
|
*
|
||||||
|
* test-RegExp: /^tagName./
|
||||||
|
* test-Pattern: 'tagName,tagName2,Field-*'
|
||||||
|
* test-Func: (target, my) => boolean
|
||||||
|
* Tester: RegExp | Pattern | Func | { exclude: Tester, include: Tester }
|
||||||
|
*
|
||||||
|
* model.accept
|
||||||
|
* accept: '@CHILD',从子节点寻找一个容器,针对 slot,比如 TabsLayout,ColumnsLayout, 大纲树误定位则错误信息透出,拒绝投入
|
||||||
|
* accept: false|null 表示不是一个容器,是一个端点,比如input,option
|
||||||
|
* accept: true 表示ok,无任何限制,比如 div,
|
||||||
|
* accept: Tester, 表示限定接受,作为filter条件,比如 select,不接受的主视图跳过定位,大纲树定位进去后红线提示
|
||||||
|
* model.nesting 多级过滤,错误信息透出 (nextTick异步检查),拒绝投入
|
||||||
|
* null | undefined | false | true 未设置 | 无意义值,不作拦截
|
||||||
|
* Tester
|
||||||
|
* model.dropTarget
|
||||||
|
* Tester // 实时约束
|
||||||
|
* {
|
||||||
|
* highlight?: Tester | boolean, // 高亮,默认false,设为true时根据 parent | ancestor 取值
|
||||||
|
* parent?: Tester, // 实时约束,主视图限制定位,大纲树定位进去时红线提示
|
||||||
|
* ancestor?: Tester, // 异步检查,上文检查, 设置此值时,parent 可不设置
|
||||||
|
* }
|
||||||
|
* '@ROOT' 只能放根节点,不高亮,异步检查
|
||||||
|
* null | undefined | boolean 未设置|无意义值,不作拦截,不高亮
|
||||||
|
*
|
||||||
|
* 所有拒绝投放的,在结束时均会检查,并抖动提示原因
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 1. 分栏容器嵌套栏/UL 嵌套 li 子嵌套约束
|
||||||
|
* 2. Form 嵌套 Button, Input 后裔嵌套约束
|
||||||
|
* 3. 数据实体 拖入 可接受目标,比如变量拖入富文本编辑器(@千緖)
|
||||||
|
* 4. Li 拖拽时高亮所有 UL,根据Li设置的 dropTargetRules 目标规则筛选节点,取并集区域
|
||||||
|
* 5. 能弹出提示
|
||||||
|
*
|
||||||
|
* 父级接受 & 定位:默认值
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export interface BehaviorControl {
|
||||||
|
handleMove?: HandleState | ((my: ElementNode) => HandleState);
|
||||||
|
handleRemove?: HandleState | ((my: ElementNode) => HandleState);
|
||||||
|
handleChildMove?: HandleState | ((my: ElementNode, child: INode) => HandleState);
|
||||||
|
handleChildRemove?: HandleState | ((my: ElementNode, child: INode) => HandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AT_CHILD = Symbol.for('@CHILD');
|
||||||
|
export const AT_ROOT = Symbol.for('@ROOT');
|
||||||
|
export type AT_ROOT = typeof AT_ROOT;
|
||||||
|
export type AT_CHILD = typeof AT_CHILD;
|
||||||
|
|
||||||
|
export type AcceptFunc = (
|
||||||
|
my: ElementNode,
|
||||||
|
e: LocateEvent | KeyboardEvent | MouseEvent,
|
||||||
|
) => LocationData | INodeParent | AT_CHILD | null;
|
||||||
|
|
||||||
|
// should appear couple
|
||||||
|
export interface AcceptControl {
|
||||||
|
/**
|
||||||
|
* MouseEvent: drag a entiy from browser out
|
||||||
|
* KeyboardEvent: paste a entiy
|
||||||
|
* LocateEvent: drag a entiy from pane
|
||||||
|
*/
|
||||||
|
accept?: AcceptFunc | AT_CHILD;
|
||||||
|
handleAccept?: (my: ElementNode, locationData: LocationData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentEditable {
|
||||||
|
propTarget: string;
|
||||||
|
selector?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export enum DISPLAY_TYPE {
|
export enum DISPLAY_TYPE {
|
||||||
NONE = 'none',
|
NONE = 'none',
|
||||||
PLAIN = 'plain',
|
PLAIN = 'plain',
|
||||||
|
|||||||
@ -12,12 +12,10 @@ registerSetters();
|
|||||||
export const editor = new Editor();
|
export const editor = new Editor();
|
||||||
globalContext.register(editor, Editor);
|
globalContext.register(editor, Editor);
|
||||||
|
|
||||||
export const skeleton = new Skeleton();
|
export const skeleton = new Skeleton(editor);
|
||||||
|
editor.set(Skeleton, skeleton);
|
||||||
console.info(skeleton.editor);
|
|
||||||
|
|
||||||
export const designer = new Designer({ eventPipe: editor });
|
export const designer = new Designer({ eventPipe: editor });
|
||||||
|
|
||||||
editor.set(Designer, designer);
|
editor.set(Designer, designer);
|
||||||
|
|
||||||
skeleton.mainArea.add({
|
skeleton.mainArea.add({
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Editor } from '@ali/lowcode-editor-core';
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
import { inject } from '@ali/lowcode-globals';
|
|
||||||
import {
|
import {
|
||||||
DockConfig,
|
DockConfig,
|
||||||
PanelConfig,
|
PanelConfig,
|
||||||
@ -29,8 +28,6 @@ export enum SkeletonEvents {
|
|||||||
WIDGET_HIDE = 'skeleton.widget.hide',
|
WIDGET_HIDE = 'skeleton.widget.hide',
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(inject);
|
|
||||||
|
|
||||||
export class Skeleton {
|
export class Skeleton {
|
||||||
private panels = new Map<string, Panel>();
|
private panels = new Map<string, Panel>();
|
||||||
private containers = new Map<string, WidgetContainer<any>>();
|
private containers = new Map<string, WidgetContainer<any>>();
|
||||||
@ -44,9 +41,7 @@ export class Skeleton {
|
|||||||
readonly bottomArea: Area<PanelConfig, Panel>;
|
readonly bottomArea: Area<PanelConfig, Panel>;
|
||||||
readonly stages: Area<StageConfig, Stage>;
|
readonly stages: Area<StageConfig, Stage>;
|
||||||
|
|
||||||
@inject() public editor: Editor;
|
constructor(readonly editor: Editor) {
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.leftArea = new Area(
|
this.leftArea = new Area(
|
||||||
this,
|
this,
|
||||||
'leftArea',
|
'leftArea',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user