mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-20 07:14:23 +00:00
Merge branch 'release/0.9.2' into 'release/0.9.2'
主设置面板 entry display 使用 stagebox 的切换模式 RT See merge request !915532
This commit is contained in:
commit
0e65b1ff51
@ -102,8 +102,8 @@ context.use(HOOKS.VE_SETTING_FIELD_VARIABLE_SETTER, VariableSetter);
|
|||||||
const externals = ['react', 'react-dom', 'prop-types', 'react-router', 'react-router-dom', '@ali/recore'];
|
const externals = ['react', 'react-dom', 'prop-types', 'react-router', 'react-router-dom', '@ali/recore'];
|
||||||
|
|
||||||
async function loadAssets() {
|
async function loadAssets() {
|
||||||
const legaoAssets = await editor.utils.get('./raxAssets.json');
|
// const legaoAssets = await editor.utils.get('./raxAssets.json');
|
||||||
// const legaoAssets = await editor.utils.get('./legao-assets.json');
|
const legaoAssets = await editor.utils.get('./legao-assets.json');
|
||||||
|
|
||||||
const assets = upgradeAssetsBundle(legaoAssets);
|
const assets = upgradeAssetsBundle(legaoAssets);
|
||||||
|
|
||||||
@ -145,11 +145,11 @@ async function loadAssets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadSchema() {
|
async function loadSchema() {
|
||||||
const schema = await editor.utils.get('./rax.json');
|
// const schema = await editor.utils.get('./rax.json');
|
||||||
// const schema = await editor.utils.get('./schema.json');
|
const schema = await editor.utils.get('./schema.json');
|
||||||
editor.set('schema', schema);
|
editor.set('schema', schema);
|
||||||
editor.set('renderEnv', 'rax');
|
// editor.set('renderEnv', 'rax');
|
||||||
editor.set('clientTypes', ['mobile']);
|
// editor.set('clientTypes', ['mobile']);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,10 @@
|
|||||||
"@alifd/next": "^1.20.12",
|
"@alifd/next": "^1.20.12",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1",
|
||||||
|
"events": "^3.2.0",
|
||||||
|
"@ali/ve-icons": "latest",
|
||||||
|
"@ali/ve-less-variables": "^2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alib/build-scripts": "^0.1.3",
|
"@alib/build-scripts": "^0.1.3",
|
||||||
|
|||||||
@ -147,8 +147,13 @@ export function createSettingFieldView(item: SettingField | CustomView, field: S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SettingsPaneProps = {
|
||||||
|
target: SettingTopEntry | SettingField;
|
||||||
|
usePopup?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class SettingsPane extends Component<{ target: SettingTopEntry | SettingField }> {
|
export class SettingsPane extends Component<SettingsPaneProps> {
|
||||||
static contextType = SkeletonContext;
|
static contextType = SkeletonContext;
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
@ -160,6 +165,8 @@ export class SettingsPane extends Component<{ target: SettingTopEntry | SettingF
|
|||||||
private handleClick = (e: MouseEvent) => {
|
private handleClick = (e: MouseEvent) => {
|
||||||
// compatiable vision stageBox
|
// compatiable vision stageBox
|
||||||
// TODO: optimize these codes
|
// TODO: optimize these codes
|
||||||
|
const { usePopup = true } = this.props;
|
||||||
|
if (!usePopup) return;
|
||||||
const pane = e.currentTarget as HTMLDivElement;
|
const pane = e.currentTarget as HTMLDivElement;
|
||||||
let entry: any;
|
let entry: any;
|
||||||
function getTarget(node: any): any {
|
function getTarget(node: any): any {
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { Title, observer, Editor, obx, globalContext } from '@ali/lowcode-editor
|
|||||||
import { Node, isSettingField, SettingField, Designer } from '@ali/lowcode-designer';
|
import { Node, isSettingField, SettingField, Designer } from '@ali/lowcode-designer';
|
||||||
import { SettingsMain } from './main';
|
import { SettingsMain } from './main';
|
||||||
import { SettingsPane } from './settings-pane';
|
import { SettingsPane } from './settings-pane';
|
||||||
|
import { StageBox } from '../stage-box';
|
||||||
|
import { SkeletonContext } from '../../context';
|
||||||
import { createIcon } from '@ali/lowcode-utils';
|
import { createIcon } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -114,7 +116,18 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
|
|||||||
<div className="lc-settings-main">
|
<div className="lc-settings-main">
|
||||||
{this.renderBreadcrumb()}
|
{this.renderBreadcrumb()}
|
||||||
<div className="lc-settings-body">
|
<div className="lc-settings-body">
|
||||||
<SettingsPane target={settings} />
|
<SkeletonContext.Consumer>
|
||||||
|
{(skeleton) => {
|
||||||
|
if (skeleton) {
|
||||||
|
return (
|
||||||
|
<StageBox skeleton={skeleton} target={settings}>
|
||||||
|
<SettingsPane target={settings} usePopup={false} />
|
||||||
|
</StageBox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
</SkeletonContext.Consumer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -127,7 +140,18 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
|
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
|
||||||
<SettingsPane target={field} key={field.id} />
|
<SkeletonContext.Consumer>
|
||||||
|
{(skeleton) => {
|
||||||
|
if (skeleton) {
|
||||||
|
return (
|
||||||
|
<StageBox skeleton={skeleton} target={field} key={field.id}>
|
||||||
|
<SettingsPane target={field} key={field.id} usePopup={false} />
|
||||||
|
</StageBox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
</SkeletonContext.Consumer>
|
||||||
</Tab.Item>
|
</Tab.Item>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
74
packages/editor-skeleton/src/components/stage-box/index.less
Normal file
74
packages/editor-skeleton/src/components/stage-box/index.less
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
@import "~@ali/ve-less-variables/index.less";
|
||||||
|
|
||||||
|
.skeleton-stagebox {
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
min-height: 50px;
|
||||||
|
.skeleton-stagebox-stage {
|
||||||
|
height: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
transition: transform 0.2s;
|
||||||
|
|
||||||
|
&.skeleton-stagebox-refer {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.skeleton-stagebox-stageout-left, &.skeleton-stagebox-stagein-right {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.skeleton-stagebox-stageout-right, &.skeleton-stagebox-stagein-left {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-stagebox-stagebacker {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: var(--color-block-background-light, @normal-alpha-9);
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.skeleton-stagebox-stage-arrow {
|
||||||
|
position: absolute;
|
||||||
|
left: 3px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%) rotate(90deg);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.skeleton-stagebox-stage-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-block-background-dark, @normal-alpha-7);
|
||||||
|
.skeleton-stagebox-stage-arrow {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.skeleton-stagebox-stage-exit {
|
||||||
|
position: absolute;
|
||||||
|
right: 3px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-stagebox-stage-content {
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.skeleton-stagebox-has-backer {
|
||||||
|
.skeleton-stagebox-stage-content {
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
import StageBox from './stage-box';
|
||||||
|
import './index.less';
|
||||||
|
|
||||||
|
export { StageBox };
|
||||||
118
packages/editor-skeleton/src/components/stage-box/stage-box.tsx
Normal file
118
packages/editor-skeleton/src/components/stage-box/stage-box.tsx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
|
import { SettingTopEntry, SettingField } from '@ali/lowcode-designer';
|
||||||
|
import StageChain from './stage-chain';
|
||||||
|
import Stage from './stage';
|
||||||
|
import { Skeleton } from '../../skeleton';
|
||||||
|
import { Stage as StageWidget } from '../../widget/stage';
|
||||||
|
|
||||||
|
export const StageBoxDefaultProps = {};
|
||||||
|
|
||||||
|
export type StageBoxProps = typeof StageBoxDefaultProps & {
|
||||||
|
stageChain?: StageChain;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
skeleton: Skeleton;
|
||||||
|
// @todo to remove
|
||||||
|
target?: SettingTopEntry | SettingField;
|
||||||
|
};
|
||||||
|
|
||||||
|
type WillDetachMember = () => void;
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class StageBox extends Component<StageBoxProps> {
|
||||||
|
static defaultProps = StageBoxDefaultProps;
|
||||||
|
|
||||||
|
static displayName = 'StageBox';
|
||||||
|
|
||||||
|
private stageChain: StageChain;
|
||||||
|
private willDetach: WillDetachMember[] = [];
|
||||||
|
private shell: HTMLElement | null;
|
||||||
|
|
||||||
|
constructor(props: StageBoxProps) {
|
||||||
|
super(props);
|
||||||
|
const { stageChain, children, skeleton } = this.props;
|
||||||
|
if (stageChain) {
|
||||||
|
this.stageChain = stageChain;
|
||||||
|
} else {
|
||||||
|
const stateName = skeleton.createStage({
|
||||||
|
content: children,
|
||||||
|
});
|
||||||
|
this.stageChain = new StageChain(skeleton.getStage(stateName as string) as StageWidget);
|
||||||
|
}
|
||||||
|
this.willDetach.push(this.stageChain.onStageChange(() => this.forceUpdate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const shell = this.shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向上层递归寻找 target
|
||||||
|
* @param node 节点
|
||||||
|
* @returns 节点的 dataset.stageTarget 信息
|
||||||
|
*/
|
||||||
|
const getTarget = (node: HTMLElement | null): null | string => {
|
||||||
|
if (!node || !shell?.contains(node) || (node.nodeName === 'A' && node.getAttribute('href'))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = node.dataset ? node.dataset.stageTarget : null;
|
||||||
|
if (target) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
return getTarget(node.parentNode as HTMLElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
const click = (e: MouseEvent) => {
|
||||||
|
const target = getTarget(e.target as HTMLElement);
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target === 'stageback') {
|
||||||
|
this.stageChain.stageBack();
|
||||||
|
} else {
|
||||||
|
const { skeleton } = this.props;
|
||||||
|
this.stageChain.stagePush(skeleton.getStage(target));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
shell?.addEventListener('click', click, false);
|
||||||
|
this.willDetach.push(() => shell?.removeEventListener('click', click, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.willDetach) {
|
||||||
|
this.willDetach.forEach((off: () => void) => off());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const className = classNames('skeleton-stagebox', this.props.className);
|
||||||
|
const stage = this.stageChain.getCurrentStage();
|
||||||
|
const refer = stage?.getRefer();
|
||||||
|
|
||||||
|
let contentCurrent = null;
|
||||||
|
let contentRefer = null;
|
||||||
|
|
||||||
|
if (refer) {
|
||||||
|
contentCurrent = <Stage key={stage.getId()} stage={stage} direction={refer.direction} current />;
|
||||||
|
contentRefer = <Stage key={refer?.stage?.getId()} stage={refer?.stage} direction={refer.direction} />;
|
||||||
|
} else {
|
||||||
|
contentCurrent = <Stage key={stage.getId()} stage={stage} current />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={(ref) => {
|
||||||
|
this.shell = ref;
|
||||||
|
}}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{contentRefer}
|
||||||
|
{contentCurrent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { Stage as StageWidget } from '../../widget/stage';
|
||||||
|
|
||||||
|
export default class StageChain {
|
||||||
|
private emitter: EventEmitter;
|
||||||
|
private stage: StageWidget;
|
||||||
|
|
||||||
|
constructor(stage: StageWidget) {
|
||||||
|
this.emitter = new EventEmitter();
|
||||||
|
this.stage = stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
stagePush(stage: StageWidget | null) {
|
||||||
|
if (!stage) return;
|
||||||
|
stage.setPrevious(this.stage);
|
||||||
|
stage.setReferLeft(this.stage);
|
||||||
|
this.stage = stage;
|
||||||
|
this.emitter.emit('stagechange');
|
||||||
|
}
|
||||||
|
|
||||||
|
stageBack() {
|
||||||
|
const stage = this.stage.getPrevious();
|
||||||
|
if (!stage) return;
|
||||||
|
stage.setReferRight(this.stage);
|
||||||
|
this.stage = stage;
|
||||||
|
this.emitter.emit('stagechange');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回到最开始
|
||||||
|
*/
|
||||||
|
stageBackToRoot() {
|
||||||
|
while (!this.stage.isRoot) {
|
||||||
|
const stage = this.stage.getPrevious();
|
||||||
|
if (!stage) return;
|
||||||
|
stage.setReferRight(this.stage);
|
||||||
|
this.stage = stage;
|
||||||
|
}
|
||||||
|
this.emitter.emit('stagechange');
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentStage() {
|
||||||
|
return this.stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
onStageChange(func: () => void) {
|
||||||
|
this.emitter.on('stagechange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('stagechange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
93
packages/editor-skeleton/src/components/stage-box/stage.tsx
Normal file
93
packages/editor-skeleton/src/components/stage-box/stage.tsx
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// @todo 改成 hooks
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Icons from '@ali/ve-icons';
|
||||||
|
import { Stage as StageWidget } from '../../widget/stage';
|
||||||
|
|
||||||
|
export const StageDefaultProps = {
|
||||||
|
current: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StageProps = typeof StageDefaultProps & {
|
||||||
|
stage?: StageWidget;
|
||||||
|
current: boolean;
|
||||||
|
direction?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Stage extends Component<StageProps> {
|
||||||
|
static defaultProps = StageDefaultProps;
|
||||||
|
|
||||||
|
private timer: number;
|
||||||
|
private additionClassName: string | null;
|
||||||
|
private shell: any;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.doSkate();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.doSkate();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
doSkate() {
|
||||||
|
window.clearTimeout(this.timer);
|
||||||
|
if (this.additionClassName) {
|
||||||
|
this.timer = window.setTimeout(() => {
|
||||||
|
const elem = this.shell;
|
||||||
|
if (elem) {
|
||||||
|
if (this.props.current) {
|
||||||
|
elem.classList.remove(this.additionClassName);
|
||||||
|
} else {
|
||||||
|
elem.classList.add(this.additionClassName);
|
||||||
|
}
|
||||||
|
this.additionClassName = null;
|
||||||
|
}
|
||||||
|
}, 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { stage, current, direction } = this.props;
|
||||||
|
const content = stage?.getContent();
|
||||||
|
|
||||||
|
if (current) {
|
||||||
|
if (direction) {
|
||||||
|
this.additionClassName = `skeleton-stagebox-stagein-${direction}`;
|
||||||
|
}
|
||||||
|
} else if (direction) {
|
||||||
|
this.additionClassName = `skeleton-stagebox-stageout-${direction}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const className = classNames(
|
||||||
|
'skeleton-stagebox-stage',
|
||||||
|
{
|
||||||
|
'skeleton-stagebox-refer': !current,
|
||||||
|
},
|
||||||
|
this.additionClassName,
|
||||||
|
);
|
||||||
|
|
||||||
|
const stageBacker = stage?.hasBack() ? (
|
||||||
|
<div className="skeleton-stagebox-stagebacker" data-stage-target="stageback">
|
||||||
|
<Icons name="arrow" className="skeleton-stagebox-stage-arrow" size="medium" />
|
||||||
|
<span className="skeleton-stagebox-stage-title">{stage.title}</span>
|
||||||
|
<Icons name="exit" className="skeleton-stagebox-stage-exit" size="medium" />
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={(ref) => {
|
||||||
|
this.shell = ref;
|
||||||
|
}}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{stageBacker}
|
||||||
|
<div className="skeleton-stagebox-stage-content">{content}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,7 +20,7 @@ import PanelDock from './widget/panel-dock';
|
|||||||
import Dock from './widget/dock';
|
import Dock from './widget/dock';
|
||||||
import { Stage, StageConfig } from './widget/stage';
|
import { Stage, StageConfig } from './widget/stage';
|
||||||
import { isValidElement } from 'react';
|
import { isValidElement } from 'react';
|
||||||
import { isPlainObject } from '@ali/lowcode-utils';
|
import { isPlainObject, uniqueId } from '@ali/lowcode-utils';
|
||||||
import { Divider } from '@alifd/next';
|
import { Divider } from '@alifd/next';
|
||||||
import { EditorConfig, PluginClassSet } from '@ali/lowcode-types';
|
import { EditorConfig, PluginClassSet } from '@ali/lowcode-types';
|
||||||
|
|
||||||
@ -248,6 +248,19 @@ export class Skeleton {
|
|||||||
return this.panels.get(name);
|
return this.panels.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStage(name: string) {
|
||||||
|
return this.stages.container.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
createStage(config: any) {
|
||||||
|
const stage = this.add({
|
||||||
|
name: uniqueId('stage'),
|
||||||
|
area: 'stages',
|
||||||
|
...config,
|
||||||
|
});
|
||||||
|
return stage?.getName();
|
||||||
|
}
|
||||||
|
|
||||||
createContainer(
|
createContainer(
|
||||||
name: string,
|
name: string,
|
||||||
handle: (item: any) => any,
|
handle: (item: any) => any,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { uniqueId } from '@ali/lowcode-utils';
|
||||||
import Widget from './widget';
|
import Widget from './widget';
|
||||||
import { Skeleton } from '../skeleton';
|
import { Skeleton } from '../skeleton';
|
||||||
import { WidgetConfig } from '../types';
|
import { WidgetConfig } from '../types';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user