mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
refactor: 💡 处理引用冲突
This commit is contained in:
commit
8421aef510
@ -7,6 +7,8 @@ import {
|
||||
TitleContent,
|
||||
TransformedComponentMetadata,
|
||||
NestingFilter,
|
||||
isTitleConfig,
|
||||
I18nData,
|
||||
} from '@ali/lowcode-types';
|
||||
import { computed } from '@ali/lowcode-editor-core';
|
||||
import { Node, ParentalNode } from './document';
|
||||
@ -17,6 +19,7 @@ import { IconPage } from './icons/page';
|
||||
import { IconComponent } from './icons/component';
|
||||
import { IconRemove } from './icons/remove';
|
||||
import { IconClone } from './icons/clone';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
function ensureAList(list?: string | string[]): string[] | null {
|
||||
if (!list) {
|
||||
@ -91,12 +94,20 @@ export class ComponentMeta {
|
||||
private childWhitelist?: NestingFilter | null;
|
||||
|
||||
private _title?: TitleContent;
|
||||
get title() {
|
||||
get title(): string | I18nData | ReactElement {
|
||||
// TODO: 标记下。这块需要康师傅加一下API,页面正常渲染。
|
||||
// string | i18nData | ReactElement
|
||||
// TitleConfig title.label
|
||||
if (isTitleConfig(this._title)) {
|
||||
return (this._title.label as any) || this.componentName;
|
||||
}
|
||||
return this._title || this.componentName;
|
||||
}
|
||||
|
||||
@computed get icon() {
|
||||
// TODO: 标记下。这块需要康师傅加一下API,页面正常渲染。
|
||||
// give Slot default icon
|
||||
// if _title is TitleConfig get _title.icon
|
||||
return (
|
||||
this._transformedMetadata?.icon ||
|
||||
(this.componentName === 'Page' ? IconPage : this.isContainer ? IconContainer : IconComponent)
|
||||
@ -131,10 +142,10 @@ export class ComponentMeta {
|
||||
this._title =
|
||||
typeof title === 'string'
|
||||
? {
|
||||
type: 'i18n',
|
||||
'en-US': this.componentName,
|
||||
'zh-CN': title,
|
||||
}
|
||||
type: 'i18n',
|
||||
'en-US': this.componentName,
|
||||
'zh-CN': title,
|
||||
}
|
||||
: title;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
PropsList,
|
||||
NodeData,
|
||||
TitleContent,
|
||||
I18nData,
|
||||
SlotSchema,
|
||||
PageSchema,
|
||||
ComponentSchema,
|
||||
@ -19,6 +20,7 @@ import { Prop } from './props/prop';
|
||||
import { ComponentMeta } from '../../component-meta';
|
||||
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
||||
import { TransformStage } from './transform-stage';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
/**
|
||||
* 基础节点
|
||||
@ -122,7 +124,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@computed get title(): TitleContent {
|
||||
@computed get title(): string | I18nData | ReactElement {
|
||||
let t = this.getExtraProp('title');
|
||||
if (!t && this.componentMeta.descriptor) {
|
||||
t = this.getProp(this.componentMeta.descriptor, false);
|
||||
@ -136,6 +138,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
return this.componentMeta.title;
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this.componentMeta.icon;
|
||||
}
|
||||
|
||||
constructor(readonly document: DocumentModel, nodeSchema: Schema) {
|
||||
const { componentName, id, children, props, ...extras } = nodeSchema;
|
||||
this.id = id || `node$${document.nextId()}`;
|
||||
|
||||
@ -13,3 +13,6 @@ export interface TitleConfig {
|
||||
|
||||
export type TitleContent = string | I18nData | ReactElement | TitleConfig;
|
||||
|
||||
export function isTitleConfig(obj: any): obj is TitleConfig {
|
||||
return obj && (obj.label || obj.tip || obj.icon);
|
||||
}
|
||||
|
||||
82
packages/vision-preset/src/components/index.less
Normal file
82
packages/vision-preset/src/components/index.less
Normal file
@ -0,0 +1,82 @@
|
||||
@import '~@ali/ve-less-variables/index.less';
|
||||
|
||||
// 样式直接沿用之前的样式,优化了下命名
|
||||
.instance-node-selector {
|
||||
position: relative;
|
||||
margin-right: 2px;
|
||||
color: var(--color-icon-white, @title-bgcolor);
|
||||
border-radius: @global-border-radius;
|
||||
margin-right: 2px;
|
||||
pointer-events: auto;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
max-width: inherit;
|
||||
path {
|
||||
fill: var(--color-icon-white, @title-bgcolor);
|
||||
}
|
||||
}
|
||||
&-current {
|
||||
background: var(--color-brand, @brand-color-1);
|
||||
padding: 0 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
color: var(--color-icon-white, @title-bgcolor);
|
||||
border-radius: 3px;
|
||||
|
||||
&-title {
|
||||
padding-right: 6px;
|
||||
color: var(--color-icon-white, @title-bgcolor);
|
||||
}
|
||||
}
|
||||
&-list {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
&-node {
|
||||
margin: 2px 0;
|
||||
&-content {
|
||||
padding-left: 6px;
|
||||
background: #78869a;
|
||||
display: inline-flex;
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
color: var(--color-icon-white, @title-bgcolor);
|
||||
cursor: pointer;
|
||||
overflow: visible;
|
||||
}
|
||||
&-title {
|
||||
padding-right: 6px;
|
||||
// margin-left: 5px;
|
||||
color: var(--color-icon-white, @title-bgcolor);
|
||||
cursor: pointer;
|
||||
overflow: visible;
|
||||
}
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.instance-node-selector-current {
|
||||
color: ar(--color-text-reverse, @white-alpha-2);
|
||||
}
|
||||
.instance-node-selector-popup {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: 0.2s all ease-in;
|
||||
}
|
||||
}
|
||||
95
packages/vision-preset/src/components/index.tsx
Normal file
95
packages/vision-preset/src/components/index.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import { Overlay } from '@alifd/next';
|
||||
import React from 'react';
|
||||
import './index.less';
|
||||
import { Title } from '@ali/lowcode-editor-core';
|
||||
|
||||
import { Node, ParentalNode } from '@ali/lowcode-designer';
|
||||
|
||||
const { Popup } = Overlay;
|
||||
|
||||
export interface IProps {
|
||||
node: Node;
|
||||
}
|
||||
|
||||
export interface IState {
|
||||
parentNodes: Node[];
|
||||
}
|
||||
|
||||
type UnionNode = Node | ParentalNode | null;
|
||||
|
||||
export class InstanceNodeSelector extends React.Component<IProps, IState> {
|
||||
state: IState = {
|
||||
parentNodes: [],
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const parentNodes = this.getParentNodes(this.props.node);
|
||||
this.setState({
|
||||
parentNodes,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取节点的父级节点(最多获取5层)
|
||||
getParentNodes = (node: Node) => {
|
||||
const parentNodes = [];
|
||||
let currentNode: UnionNode = node;
|
||||
|
||||
while (currentNode && parentNodes.length < 5) {
|
||||
currentNode = currentNode.getParent();
|
||||
if (currentNode) {
|
||||
parentNodes.push(currentNode);
|
||||
}
|
||||
}
|
||||
return parentNodes;
|
||||
};
|
||||
|
||||
onSelect = (node: Node) => () => {
|
||||
if (node && typeof node.select === 'function') {
|
||||
node.select();
|
||||
}
|
||||
};
|
||||
|
||||
renderNodes = (node: Node) => {
|
||||
const nodes = this.state.parentNodes || [];
|
||||
const children = nodes.map((node, key) => {
|
||||
return (
|
||||
<div key={key} onClick={this.onSelect(node)} className="instance-node-selector-node">
|
||||
<div className="instance-node-selector-node-content">
|
||||
<Title
|
||||
className="instance-node-selector-node-title"
|
||||
title={{
|
||||
label: node.title,
|
||||
icon: node.icon,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return children;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { node } = this.props;
|
||||
return (
|
||||
<div className="instance-node-selector">
|
||||
<Popup
|
||||
trigger={
|
||||
<div className="instance-node-selector-current">
|
||||
<Title
|
||||
className="instance-node-selector-node-title"
|
||||
title={{
|
||||
label: node.title,
|
||||
icon: node.icon,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
triggerType="hover"
|
||||
>
|
||||
<div className="instance-node-selector">{this.renderNodes(node)}</div>
|
||||
</Popup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,18 @@
|
||||
import { isJSBlock, isJSSlot } from '@ali/lowcode-types';
|
||||
import { isPlainObject } from '@ali/lowcode-utils';
|
||||
import { globalContext, Editor, registerSetter } from '@ali/lowcode-editor-core';
|
||||
import { Designer, TransformStage } from '@ali/lowcode-designer';
|
||||
// import { registerSetters } from '@ali/lowcode-setters';
|
||||
import Outline from '@ali/lowcode-plugin-outline-pane';
|
||||
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||
import { Designer, TransformStage, addBuiltinComponentAction } from '@ali/lowcode-designer';
|
||||
import { registerSetters } from '@ali/lowcode-setters';
|
||||
// import Outline from '@ali/lowcode-plugin-outline-pane';
|
||||
|
||||
import DesignerPlugin from '@ali/lowcode-plugin-designer';
|
||||
import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton';
|
||||
|
||||
import Preview from '@ali/lowcode-plugin-sample-preview';
|
||||
// import SourceEditor from '@ali/lowcode-plugin-source-editor';
|
||||
import { i18nReducer } from './i18n-reducer';
|
||||
import { InstanceNodeSelector } from './components';
|
||||
import { Divider } from '@alifd/next';
|
||||
|
||||
export const editor = new Editor();
|
||||
globalContext.register(editor, Editor);
|
||||
@ -112,3 +115,10 @@ skeleton.add({
|
||||
// },
|
||||
// content: SourceEditor,
|
||||
// });
|
||||
|
||||
// 实例节点选择器,线框高亮
|
||||
addBuiltinComponentAction({
|
||||
name: 'instance-node-selector',
|
||||
content: InstanceNodeSelector,
|
||||
important: true,
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user