mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-04-20 12:28:08 +00:00
merge
This commit is contained in:
commit
4ea1c775ec
@ -22,7 +22,7 @@ import {
|
|||||||
CanvasPoint,
|
CanvasPoint,
|
||||||
} from '../designer';
|
} from '../designer';
|
||||||
import { parseMetadata } from './utils/parse-metadata';
|
import { parseMetadata } from './utils/parse-metadata';
|
||||||
import { ComponentMetadata } from '@ali/lowcode-types';
|
import { ComponentMetadata, ComponentSchema } from '@ali/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';
|
||||||
@ -447,6 +447,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return this.renderer?.getComponent(componentName) || null;
|
return this.renderer?.getComponent(componentName) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createComponent(schema: ComponentSchema): Component | null {
|
||||||
|
return this.renderer?.createComponent(schema) || null;
|
||||||
|
}
|
||||||
|
|
||||||
@obx.val private instancesMap = new Map<string, ComponentInstance[]>();
|
@obx.val private instancesMap = new Map<string, ComponentInstance[]>();
|
||||||
setInstance(id: string, instances: ComponentInstance[] | null) {
|
setInstance(id: string, instances: ComponentInstance[] | null) {
|
||||||
if (instances == null) {
|
if (instances == null) {
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { ComponentInstance, NodeInstance, Component } from '../simulator';
|
import { ComponentInstance, NodeInstance, Component } from '../simulator';
|
||||||
|
import { ComponentSchema } from '@ali/lowcode-types';
|
||||||
|
|
||||||
export interface BuiltinSimulatorRenderer {
|
export interface BuiltinSimulatorRenderer {
|
||||||
readonly isSimulatorRenderer: true;
|
readonly isSimulatorRenderer: true;
|
||||||
|
createComponent(schema: ComponentSchema): Component | null;
|
||||||
getComponent(componentName: string): Component;
|
getComponent(componentName: string): Component;
|
||||||
getComponentInstances(id: string): ComponentInstance[] | null;
|
getComponentInstances(id: string): ComponentInstance[] | null;
|
||||||
getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null;
|
getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null;
|
||||||
|
|||||||
@ -228,7 +228,7 @@ export class Designer {
|
|||||||
|
|
||||||
touchOffsetObserver() {
|
touchOffsetObserver() {
|
||||||
this.clearOobxList(true);
|
this.clearOobxList(true);
|
||||||
this.oobxList.forEach(item => item.compute());
|
this.oobxList.forEach((item) => item.compute());
|
||||||
}
|
}
|
||||||
|
|
||||||
createSettingEntry(editor: IEditor, nodes: Node[]) {
|
createSettingEntry(editor: IEditor, nodes: Node[]) {
|
||||||
@ -392,12 +392,17 @@ export class Designer {
|
|||||||
@computed get componentsMap(): { [key: string]: NpmInfo | Component } {
|
@computed get componentsMap(): { [key: string]: NpmInfo | Component } {
|
||||||
const maps: any = {};
|
const maps: any = {};
|
||||||
this._componentMetasMap.forEach((config, key) => {
|
this._componentMetasMap.forEach((config, key) => {
|
||||||
const view = config.getMetadata().experimental?.view;
|
const metaData = config.getMetadata();
|
||||||
|
if (metaData.devMode === 'lowcode') {
|
||||||
|
maps[key] = this.currentDocument?.simulator?.createComponent(metaData.schema);
|
||||||
|
} else {
|
||||||
|
const view = metaData.experimental?.view;
|
||||||
if (view) {
|
if (view) {
|
||||||
maps[key] = view;
|
maps[key] = view;
|
||||||
} else if (config.npm) {
|
} else if (config.npm) {
|
||||||
maps[key] = config.npm;
|
maps[key] = config.npm;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { autorun, Reaction, untracked } from '@ali/lowcode-editor-core';
|
import { autorun, Reaction, untracked, globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
import { NodeSchema } from '@ali/lowcode-types';
|
import { NodeSchema } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// TODO: cache to localStorage
|
// TODO: cache to localStorage
|
||||||
@ -114,6 +114,11 @@ export class History {
|
|||||||
}
|
}
|
||||||
const cursor = this.session.cursor - 1;
|
const cursor = this.session.cursor - 1;
|
||||||
this.go(cursor);
|
this.go(cursor);
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
if (!editor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.emit('history.back', cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
forward() {
|
forward() {
|
||||||
@ -122,6 +127,11 @@ export class History {
|
|||||||
}
|
}
|
||||||
const cursor = this.session.cursor + 1;
|
const cursor = this.session.cursor + 1;
|
||||||
this.go(cursor);
|
this.go(cursor);
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
if (!editor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.emit('history.forward', cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
savePoint() {
|
savePoint() {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Component as ReactComponent, ComponentType } from 'react';
|
import { Component as ReactComponent, ComponentType } from 'react';
|
||||||
import { ComponentMetadata } from '@ali/lowcode-types';
|
import { ComponentMetadata, ComponentSchema } from '@ali/lowcode-types';
|
||||||
import { ISensor, Point, ScrollTarget, IScrollable } from './designer';
|
import { ISensor, Point, ScrollTarget, IScrollable } from './designer';
|
||||||
import { Node } from './document';
|
import { Node } from './document';
|
||||||
|
|
||||||
@ -126,6 +126,10 @@ export interface ISimulatorHost<P = object> extends ISensor {
|
|||||||
* 根据节点获取节点的组件实例
|
* 根据节点获取节点的组件实例
|
||||||
*/
|
*/
|
||||||
getComponentInstances(node: Node): ComponentInstance[] | null;
|
getComponentInstances(node: Node): ComponentInstance[] | null;
|
||||||
|
/**
|
||||||
|
* 根据低代码组件 schema 创建组件类
|
||||||
|
*/
|
||||||
|
createComponent(schema: ComponentSchema): Component | null;
|
||||||
/**
|
/**
|
||||||
* 根据节点获取节点的组件运行上下文
|
* 根据节点获取节点的组件运行上下文
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { globalContext } from './di';
|
||||||
|
import { Editor } from './editor';
|
||||||
|
|
||||||
interface KeyMap {
|
interface KeyMap {
|
||||||
[key: number]: string;
|
[key: number]: string;
|
||||||
}
|
}
|
||||||
@ -329,6 +332,16 @@ function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
if (!editor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.emit('hotkey.callback.call', {
|
||||||
|
callback,
|
||||||
|
e,
|
||||||
|
combo,
|
||||||
|
sequence,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Hotkey {
|
export class Hotkey {
|
||||||
|
|||||||
@ -7,8 +7,23 @@ import { Tip } from '../tip';
|
|||||||
import './title.less';
|
import './title.less';
|
||||||
|
|
||||||
export class Title extends Component<{ title: TitleContent; className?: string; onClick?: () => void }> {
|
export class Title extends Component<{ title: TitleContent; className?: string; onClick?: () => void }> {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
}
|
||||||
|
handleClick(e: React.MouseEvent) {
|
||||||
|
const { title, onClick } = this.props as any;
|
||||||
|
const url = title && (title.docUrl || title.url);
|
||||||
|
if (url) {
|
||||||
|
window.open(url);
|
||||||
|
// 防止触发行操作(如折叠面板)
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
// TODO: 操作交互冲突,目前 mixedSetter 仅有 2 个 setter 注册时用到了 onClick
|
||||||
|
onClick && onClick(e);
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
let { title, className, onClick } = this.props;
|
let { title, className } = this.props;
|
||||||
if (title == null) {
|
if (title == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -40,7 +55,7 @@ export class Title extends Component<{ title: TitleContent; className?: string;
|
|||||||
'has-tip': !!tip,
|
'has-tip': !!tip,
|
||||||
'only-icon': !title.label
|
'only-icon': !title.label
|
||||||
})}
|
})}
|
||||||
onClick={onClick}
|
onClick={this.handleClick}
|
||||||
>
|
>
|
||||||
{icon ? <b className="lc-title-icon">{icon}</b> : null}
|
{icon ? <b className="lc-title-icon">{icon}</b> : null}
|
||||||
{title.label ? intl(title.label) : null}
|
{title.label ? intl(title.label) : null}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
|
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
|
||||||
import { isPlainObject } from '@ali/lowcode-utils';
|
import { isPlainObject } from '@ali/lowcode-utils';
|
||||||
import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, isJSExpression, AutorunItem } from '@ali/lowcode-types';
|
import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, ProjectSchema, AutorunItem } from '@ali/lowcode-types';
|
||||||
import { untracked } from '@ali/lowcode-editor-core';
|
import { untracked } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
type Field = SettingTarget;
|
type Field = SettingTarget;
|
||||||
@ -167,6 +167,8 @@ export interface OldPrototypeConfig {
|
|||||||
onResizeStart?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
onResizeStart?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
||||||
onResize?: (e: MouseEvent, triggerDirection: string, dragment: Node, moveX: number, moveY: number) => void;
|
onResize?: (e: MouseEvent, triggerDirection: string, dragment: Node, moveX: number, moveY: number) => void;
|
||||||
onResizeEnd?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
onResizeEnd?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
||||||
|
devMode?: string;
|
||||||
|
schema?: ProjectSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISetterConfig {
|
export interface ISetterConfig {
|
||||||
@ -607,6 +609,8 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
|||||||
onResizeStart, // onResizeStart
|
onResizeStart, // onResizeStart
|
||||||
onResize, // onResize
|
onResize, // onResize
|
||||||
onResizeEnd, // onResizeEnd
|
onResizeEnd, // onResizeEnd
|
||||||
|
devMode,
|
||||||
|
schema,
|
||||||
} = oldConfig;
|
} = oldConfig;
|
||||||
|
|
||||||
const meta: any = {
|
const meta: any = {
|
||||||
@ -614,7 +618,8 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
|||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
docUrl,
|
docUrl,
|
||||||
devMode: 'procode',
|
devMode: devMode || 'procode',
|
||||||
|
schema: schema?.componentsTree[0],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (category) {
|
if (category) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import logger from '@ali/vu-logger';
|
import logger from '@ali/vu-logger';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
import { editor } from './editor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bus class as an EventEmitter
|
* Bus class as an EventEmitter
|
||||||
@ -19,7 +20,6 @@ export class Bus {
|
|||||||
// alias to unsub
|
// alias to unsub
|
||||||
off(event: string, func: (...args: any[]) => any) {
|
off(event: string, func: (...args: any[]) => any) {
|
||||||
this.unsub(event, func);
|
this.unsub(event, func);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// alias to pub
|
// alias to pub
|
||||||
@ -62,4 +62,18 @@ export class Bus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Bus();
|
const bus = new Bus();
|
||||||
|
|
||||||
|
editor.on('hotkey.callback.call', (data) => {
|
||||||
|
bus.emit('ve.hotkey.callback.call', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.on('history.back', (data) => {
|
||||||
|
bus.emit('ve.history.back', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.on('history.forward', (data) => {
|
||||||
|
bus.emit('ve.history.forward', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default bus;
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { skeleton, editor } from './editor';
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { IWidgetBaseConfig, Skeleton } from '@ali/lowcode-editor-skeleton';
|
import { IWidgetBaseConfig, Skeleton } from '@ali/lowcode-editor-skeleton';
|
||||||
import { uniqueId } from '@ali/lowcode-utils';
|
import { uniqueId } from '@ali/lowcode-utils';
|
||||||
|
import bus from './bus';
|
||||||
|
|
||||||
export interface IContentItemConfig {
|
export interface IContentItemConfig {
|
||||||
title: string;
|
title: string;
|
||||||
@ -175,6 +176,7 @@ const dockPane = Object.assign(skeleton.leftArea, {
|
|||||||
console.warn(`Could not find pane with name ${name}`);
|
console.warn(`Could not find pane with name ${name}`);
|
||||||
}
|
}
|
||||||
pane?.active();
|
pane?.active();
|
||||||
|
bus.emit('ve.dock_pane.active_doc', pane);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -28,6 +28,11 @@ export class Field extends Component<FieldProps> {
|
|||||||
display: this.props.defaultDisplay || 'inline',
|
display: this.props.defaultDisplay || 'inline',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.handleClear = this.handleClear.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
private toggleExpand = () => {
|
private toggleExpand = () => {
|
||||||
const { onExpandChange } = this.props;
|
const { onExpandChange } = this.props;
|
||||||
const collapsed = !this.state.collapsed;
|
const collapsed = !this.state.collapsed;
|
||||||
@ -68,6 +73,10 @@ export class Field extends Component<FieldProps> {
|
|||||||
});
|
});
|
||||||
this.dispose = () => observer.disconnect();
|
this.dispose = () => observer.disconnect();
|
||||||
}
|
}
|
||||||
|
private handleClear(e: React.MouseEvent) {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.props.onClear && this.props.onClear();
|
||||||
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { defaultDisplay } = this.props;
|
const { defaultDisplay } = this.props;
|
||||||
if (!defaultDisplay || defaultDisplay === 'inline') {
|
if (!defaultDisplay || defaultDisplay === 'inline') {
|
||||||
@ -118,7 +127,7 @@ export class Field extends Component<FieldProps> {
|
|||||||
>
|
>
|
||||||
<div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}>
|
<div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}>
|
||||||
<div className="lc-field-title">
|
<div className="lc-field-title">
|
||||||
{createValueState(valueState, onClear)}
|
{createValueState(valueState, this.handleClear)}
|
||||||
<Title title={title || ''} />
|
<Title title={title || ''} />
|
||||||
<InlineTip position="top">{tipContent}</InlineTip>
|
<InlineTip position="top">{tipContent}</InlineTip>
|
||||||
</div>
|
</div>
|
||||||
@ -143,7 +152,7 @@ export class Field extends Component<FieldProps> {
|
|||||||
*
|
*
|
||||||
* TODO: turn number to enum
|
* TODO: turn number to enum
|
||||||
*/
|
*/
|
||||||
function createValueState(valueState?: number, onClear?: () => void) {
|
function createValueState(valueState?: number, onClear?: (e: React.MouseEvent) => void) {
|
||||||
let tip: any = null;
|
let tip: any = null;
|
||||||
let className = 'lc-valuestate';
|
let className = 'lc-valuestate';
|
||||||
let icon: any = null;
|
let icon: any = null;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { createElement, ReactInstance, ComponentType } from 'react';
|
import React, { createElement, ReactInstance, ComponentType, ReactElement } from 'react';
|
||||||
import { render as reactRender } from 'react-dom';
|
import { render as reactRender } from 'react-dom';
|
||||||
import { host } from './host';
|
import { host } from './host';
|
||||||
import SimulatorRendererView from './renderer-view';
|
import SimulatorRendererView from './renderer-view';
|
||||||
@ -8,9 +8,9 @@ import { getClientRects } from './utils/get-client-rects';
|
|||||||
import loader from './utils/loader';
|
import loader from './utils/loader';
|
||||||
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
|
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
|
||||||
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
|
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
|
||||||
import { RootSchema, NpmInfo } from '@ali/lowcode-types';
|
import { RootSchema, NpmInfo, ComponentSchema } from '@ali/lowcode-types';
|
||||||
// just use types
|
// just use types
|
||||||
import { BuiltinSimulatorRenderer, NodeInstance } from '@ali/lowcode-designer';
|
import { BuiltinSimulatorRenderer, NodeInstance, Component, TransformStage } from '@ali/lowcode-designer';
|
||||||
import Slot from './builtin-components/slot';
|
import Slot from './builtin-components/slot';
|
||||||
import Leaf from './builtin-components/leaf';
|
import Leaf from './builtin-components/leaf';
|
||||||
|
|
||||||
@ -210,6 +210,39 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
return this.instancesMap.get(id) || null;
|
return this.instancesMap.get(id) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createComponent(schema: ComponentSchema): Component | null {
|
||||||
|
const _schema = {
|
||||||
|
...schema,
|
||||||
|
};
|
||||||
|
_schema.methods = {};
|
||||||
|
_schema.lifeCycles = {};
|
||||||
|
|
||||||
|
const getElement = (componentsMap: any, schema: any): ReactElement => {
|
||||||
|
const Com = componentsMap[schema.componentName];
|
||||||
|
let children = null;
|
||||||
|
if (schema.children && schema.children.length > 0) {
|
||||||
|
children = schema.children.map((item: any) => getElement(componentsMap, item));
|
||||||
|
}
|
||||||
|
const _leaf = host.document.designer.currentDocument?.createNode(schema);
|
||||||
|
const props = host.document.designer.transformProps(schema.props || {}, host.document.createNode(schema), TransformStage.Render);
|
||||||
|
return createElement(Com, {...props, _leaf}, children);
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = this;
|
||||||
|
class Com extends React.Component {
|
||||||
|
render() {
|
||||||
|
const componentsMap = renderer.componentsMap;
|
||||||
|
let children = null;
|
||||||
|
if (_schema.children && Array.isArray(_schema.children)) {
|
||||||
|
children = _schema.children?.map((item:any) => getElement(componentsMap, item));
|
||||||
|
}
|
||||||
|
return createElement(React.Fragment, {}, children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Com;
|
||||||
|
}
|
||||||
|
|
||||||
getClosestNodeInstance(from: ReactInstance, nodeId?: string): NodeInstance<ReactInstance> | null {
|
getClosestNodeInstance(from: ReactInstance, nodeId?: string): NodeInstance<ReactInstance> | null {
|
||||||
return getClosestNodeInstance(from, nodeId);
|
return getClosestNodeInstance(from, nodeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { TitleContent } from './title';
|
|||||||
import { PropConfig } from './prop-config';
|
import { PropConfig } from './prop-config';
|
||||||
import { NpmInfo } from './npm';
|
import { NpmInfo } from './npm';
|
||||||
import { FieldConfig } from './field-config';
|
import { FieldConfig } from './field-config';
|
||||||
import { NodeSchema, NodeData } from './schema';
|
import { NodeSchema, NodeData, ComponentSchema } from './schema';
|
||||||
import { SettingTarget } from './setting-target';
|
import { SettingTarget } from './setting-target';
|
||||||
|
|
||||||
export type NestingFilter = (testNode: any, currentNode: any) => boolean;
|
export type NestingFilter = (testNode: any, currentNode: any) => boolean;
|
||||||
@ -163,6 +163,7 @@ export interface ComponentMetadata {
|
|||||||
props?: PropConfig[];
|
props?: PropConfig[];
|
||||||
configure?: FieldConfig[] | Configure;
|
configure?: FieldConfig[] | Configure;
|
||||||
experimental?: Experimental;
|
experimental?: Experimental;
|
||||||
|
schema?: ComponentSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransformedComponentMetadata extends ComponentMetadata {
|
export interface TransformedComponentMetadata extends ComponentMetadata {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user