mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-16 03:18:11 +00:00
Merge branch 'polyfill/vision' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into polyfill/vision
This commit is contained in:
commit
38599fffa1
@ -41,7 +41,8 @@
|
|||||||
"@alife/theme-lowcode-light": "^0.1.0",
|
"@alife/theme-lowcode-light": "^0.1.0",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.8.1",
|
"react-dom": "^16.8.1",
|
||||||
"@ali/vu-function-parser": "^2.5.0-beta.0"
|
"@ali/vu-function-parser": "^2.5.0-beta.0",
|
||||||
|
"compare-versions": "^3.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ali/iceluna-cli": "^0.0.16",
|
"@ali/iceluna-cli": "^0.0.16",
|
||||||
|
|||||||
@ -18,8 +18,11 @@ import { upgradeAssetsBundle } from './upgrade-assets';
|
|||||||
import { isCSSUrl } from '@ali/lowcode-utils';
|
import { isCSSUrl } from '@ali/lowcode-utils';
|
||||||
import { I18nSetter } from '@ali/visualengine-utils';
|
import { I18nSetter } from '@ali/visualengine-utils';
|
||||||
import VariableSetter from '@ali/vs-variable-setter';
|
import VariableSetter from '@ali/vs-variable-setter';
|
||||||
import { isObject, isArray } from 'lodash';
|
import _isArray from "lodash/isArray";
|
||||||
|
import _isObject from "lodash/isObject";
|
||||||
|
import _get from 'lodash/get';
|
||||||
import funcParser from '@ali/vu-function-parser';
|
import funcParser from '@ali/vu-function-parser';
|
||||||
|
import cv from 'compare-versions';
|
||||||
|
|
||||||
|
|
||||||
const { editor, skeleton, context, HOOKS, Trunk } = Engine;
|
const { editor, skeleton, context, HOOKS, Trunk } = Engine;
|
||||||
@ -45,11 +48,7 @@ async function loadAssets() {
|
|||||||
|
|
||||||
if (assets.packages) {
|
if (assets.packages) {
|
||||||
assets.packages.forEach((item: any) => {
|
assets.packages.forEach((item: any) => {
|
||||||
if (item.package.indexOf('@ali/vc-') === 0 && item.urls) {
|
if (item.package && externals.indexOf(item.package) > -1) {
|
||||||
item.urls = item.urls.filter((url: string) => {
|
|
||||||
return url.indexOf('view.mobile') < 0;
|
|
||||||
});
|
|
||||||
} else if (item.package && externals.indexOf(item.package) > -1) {
|
|
||||||
item.urls = null;
|
item.urls = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -103,7 +102,7 @@ function initDemoPanes() {
|
|||||||
props: {
|
props: {
|
||||||
align: 'bottom',
|
align: 'bottom',
|
||||||
icon: 'set',
|
icon: 'set',
|
||||||
description: '设置',
|
description: '设置'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
skeleton.add({
|
skeleton.add({
|
||||||
@ -113,7 +112,7 @@ function initDemoPanes() {
|
|||||||
props: {
|
props: {
|
||||||
align: 'bottom',
|
align: 'bottom',
|
||||||
icon: 'help',
|
icon: 'help',
|
||||||
description: '帮助',
|
description: '帮助'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -336,9 +335,9 @@ function replaceFuncProp(props?: any){
|
|||||||
}
|
}
|
||||||
if ((prop.compiled && prop.source) || prop.type === 'actionRef' || prop.type === 'js') {
|
if ((prop.compiled && prop.source) || prop.type === 'actionRef' || prop.type === 'js') {
|
||||||
replaceProps[name] = funcParser(prop);
|
replaceProps[name] = funcParser(prop);
|
||||||
} else if (isObject(prop)) {
|
} else if (_isObject(prop)) {
|
||||||
replaceFuncProp(prop);
|
replaceFuncProp(prop);
|
||||||
} else if (isArray(prop)) {
|
} else if (_isArray(prop)) {
|
||||||
prop.map((propItem) => {
|
prop.map((propItem) => {
|
||||||
replaceFuncProp(propItem);
|
replaceFuncProp(propItem);
|
||||||
});
|
});
|
||||||
@ -348,7 +347,6 @@ function replaceFuncProp(props?: any){
|
|||||||
for (const name in replaceProps) {
|
for (const name in replaceProps) {
|
||||||
props[name] = replaceProps[name];
|
props[name] = replaceProps[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1
packages/demo/src/vision/module.d.ts
vendored
1
packages/demo/src/vision/module.d.ts
vendored
@ -10,3 +10,4 @@ declare module '@ali/ve-i18n-manage-pane';
|
|||||||
declare module '@ali/ve-action-pane';
|
declare module '@ali/ve-action-pane';
|
||||||
declare module '@ali/vu-legao-design-fetch-context';
|
declare module '@ali/vu-legao-design-fetch-context';
|
||||||
declare module "@ali/vu-function-parser";
|
declare module "@ali/vu-function-parser";
|
||||||
|
declare module "compare-versions";
|
||||||
|
|||||||
@ -39,27 +39,25 @@ export class BorderHoveringInstance extends PureComponent<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BorderHovering extends Component {
|
export class BorderHovering extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get scale() {
|
@computed get scale() {
|
||||||
return (this.context as BuiltinSimulatorHost).viewport.scale;
|
return this.props.host.viewport.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get scrollX() {
|
@computed get scrollX() {
|
||||||
return (this.context as BuiltinSimulatorHost).viewport.scrollX;
|
return this.props.host.viewport.scrollX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get scrollY() {
|
@computed get scrollY() {
|
||||||
return (this.context as BuiltinSimulatorHost).viewport.scrollY;
|
return this.props.host.viewport.scrollY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get current() {
|
@computed get current() {
|
||||||
const host = this.context as BuiltinSimulatorHost;
|
const host = this.props.host;
|
||||||
const doc = host.document;
|
const doc = host.document;
|
||||||
const selection = doc.selection;
|
const selection = doc.selection;
|
||||||
const current = host.designer.hovering.current;
|
const current = host.designer.hovering.current;
|
||||||
@ -70,7 +68,7 @@ export class BorderHovering extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const host = this.context as BuiltinSimulatorHost;
|
const host = this.props.host;
|
||||||
const current = this.current;
|
const current = this.current;
|
||||||
if (!current || host.viewport.scrolling) {
|
if (!current || host.viewport.scrolling) {
|
||||||
return <Fragment />;
|
return <Fragment />;
|
||||||
|
|||||||
@ -132,11 +132,9 @@ function createAction(content: ReactNode | ComponentType<any> | ActionContentObj
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BorderSelectingForNode extends Component<{ node: Node }> {
|
export class BorderSelectingForNode extends Component<{ host: BuiltinSimulatorHost; node: Node }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
|
|
||||||
get host(): BuiltinSimulatorHost {
|
get host(): BuiltinSimulatorHost {
|
||||||
return this.context;
|
return this.props.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
get dragging(): boolean {
|
get dragging(): boolean {
|
||||||
@ -177,11 +175,9 @@ export class BorderSelectingForNode extends Component<{ node: Node }> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BorderSelecting extends Component {
|
export class BorderSelecting extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
|
|
||||||
get host(): BuiltinSimulatorHost {
|
get host(): BuiltinSimulatorHost {
|
||||||
return this.context;
|
return this.props.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
get dragging(): boolean {
|
get dragging(): boolean {
|
||||||
@ -211,7 +207,7 @@ export class BorderSelecting extends Component {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{selecting.map((node) => (
|
{selecting.map((node) => (
|
||||||
<BorderSelectingForNode key={node.id} node={node} />
|
<BorderSelectingForNode key={node.id} host={this.props.host} node={node} />
|
||||||
))}
|
))}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
> * {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-action {
|
&-action {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
import { observer } from '@ali/lowcode-editor-core';
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
import { BorderHovering } from './border-hovering';
|
import { BorderHovering } from './border-hovering';
|
||||||
import { SimulatorContext } from '../context';
|
|
||||||
import { BuiltinSimulatorHost } from '../host';
|
import { BuiltinSimulatorHost } from '../host';
|
||||||
import { BorderSelecting } from './border-selecting';
|
import { BorderSelecting } from './border-selecting';
|
||||||
import BorderResizing from './border-resizing';
|
import BorderResizing from './border-resizing';
|
||||||
@ -10,15 +9,13 @@ import './bem-tools.less';
|
|||||||
import './borders.less';
|
import './borders.less';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BemTools extends Component {
|
export class BemTools extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const host = this.context as BuiltinSimulatorHost;
|
const host = this.props.host;
|
||||||
const { scrollX, scrollY, scale } = host.viewport;
|
const { scrollX, scrollY, scale } = host.viewport;
|
||||||
return (
|
return (
|
||||||
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
|
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
|
||||||
|
|||||||
@ -112,24 +112,19 @@ function processDetail({ target, detail, document }: DropLocation): InsertionDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class InsertionView extends Component {
|
export class InsertionView extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
|
|
||||||
@computed get host(): BuiltinSimulatorHost {
|
|
||||||
return this.context;
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const loc = this.host.document.dropLocation;
|
const { host } = this.props;
|
||||||
|
const loc = host.document.dropLocation;
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { scale, scrollX, scrollY } = this.host.viewport;
|
const { scale, scrollX, scrollY } = host.viewport;
|
||||||
const { edge, insertType, coverRect, nearRect, vertical } = processDetail(loc);
|
const { edge, insertType, coverRect, nearRect, vertical } = processDetail(loc);
|
||||||
|
|
||||||
if (!edge) {
|
if (!edge) {
|
||||||
|
|||||||
@ -41,20 +41,17 @@ export class BuiltinSimulatorHostView extends Component<SimulatorHostProps> {
|
|||||||
const { Provider } = SimulatorContext;
|
const { Provider } = SimulatorContext;
|
||||||
return (
|
return (
|
||||||
<div className="lc-simulator">
|
<div className="lc-simulator">
|
||||||
<Provider value={this.host}>
|
|
||||||
{/*progressing.visible ? <PreLoaderView /> : null*/}
|
{/*progressing.visible ? <PreLoaderView /> : null*/}
|
||||||
<Canvas />
|
<Canvas host={this.host} />
|
||||||
</Provider>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Canvas extends Component {
|
class Canvas extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
render() {
|
render() {
|
||||||
const sim = this.context as BuiltinSimulatorHost;
|
const sim = this.props.host;
|
||||||
let className = 'lc-simulator-canvas';
|
let className = 'lc-simulator-canvas';
|
||||||
if (sim.deviceClassName) {
|
if (sim.deviceClassName) {
|
||||||
className += ` ${sim.deviceClassName}`;
|
className += ` ${sim.deviceClassName}`;
|
||||||
@ -65,8 +62,8 @@ class Canvas extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<div ref={elmt => sim.mountViewport(elmt)} className="lc-simulator-canvas-viewport">
|
<div ref={elmt => sim.mountViewport(elmt)} className="lc-simulator-canvas-viewport">
|
||||||
<BemTools />
|
<BemTools host={sim} />
|
||||||
<Content />
|
<Content host={sim} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -74,10 +71,9 @@ class Canvas extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Content extends Component {
|
class Content extends Component<{ host: BuiltinSimulatorHost }> {
|
||||||
static contextType = SimulatorContext;
|
|
||||||
render() {
|
render() {
|
||||||
const sim = this.context as BuiltinSimulatorHost;
|
const sim = this.props.host;
|
||||||
const viewport = sim.viewport;
|
const viewport = sim.viewport;
|
||||||
let frameStyle = {};
|
let frameStyle = {};
|
||||||
if (viewport.scale < 1) {
|
if (viewport.scale < 1) {
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import {
|
|||||||
TitleContent,
|
TitleContent,
|
||||||
TransformedComponentMetadata,
|
TransformedComponentMetadata,
|
||||||
NestingFilter,
|
NestingFilter,
|
||||||
|
isTitleConfig,
|
||||||
|
I18nData,
|
||||||
} from '@ali/lowcode-types';
|
} from '@ali/lowcode-types';
|
||||||
import { computed } from '@ali/lowcode-editor-core';
|
import { computed } from '@ali/lowcode-editor-core';
|
||||||
import { Node, ParentalNode } from './document';
|
import { Node, ParentalNode } from './document';
|
||||||
@ -17,6 +19,8 @@ import { IconPage } from './icons/page';
|
|||||||
import { IconComponent } from './icons/component';
|
import { IconComponent } from './icons/component';
|
||||||
import { IconRemove } from './icons/remove';
|
import { IconRemove } from './icons/remove';
|
||||||
import { IconClone } from './icons/clone';
|
import { IconClone } from './icons/clone';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
import { IconHidden } from './icons/hidden';
|
||||||
|
|
||||||
function ensureAList(list?: string | string[]): string[] | null {
|
function ensureAList(list?: string | string[]): string[] | null {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
@ -91,12 +95,20 @@ export class ComponentMeta {
|
|||||||
private childWhitelist?: NestingFilter | null;
|
private childWhitelist?: NestingFilter | null;
|
||||||
|
|
||||||
private _title?: TitleContent;
|
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;
|
return this._title || this.componentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get icon() {
|
@computed get icon() {
|
||||||
|
// TODO: 标记下。这块需要康师傅加一下API,页面正常渲染。
|
||||||
// give Slot default icon
|
// give Slot default icon
|
||||||
|
// if _title is TitleConfig get _title.icon
|
||||||
return (
|
return (
|
||||||
this._transformedMetadata?.icon ||
|
this._transformedMetadata?.icon ||
|
||||||
(this.componentName === 'Page' ? IconPage : this.isContainer ? IconContainer : IconComponent)
|
(this.componentName === 'Page' ? IconPage : this.isContainer ? IconContainer : IconComponent)
|
||||||
@ -319,6 +331,20 @@ const builtinComponentActions: ComponentAction[] = [
|
|||||||
},
|
},
|
||||||
important: true,
|
important: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'hide',
|
||||||
|
content: {
|
||||||
|
icon: IconHidden,
|
||||||
|
title: intlNode('hide'),
|
||||||
|
action(node: Node) {
|
||||||
|
node.getExtraProp('hidden', true)?.setValue(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: (node: Node) => {
|
||||||
|
return node.componentMeta.isModal;
|
||||||
|
},
|
||||||
|
important: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'copy',
|
name: 'copy',
|
||||||
content: {
|
content: {
|
||||||
@ -326,6 +352,8 @@ const builtinComponentActions: ComponentAction[] = [
|
|||||||
title: intlNode('copy'),
|
title: intlNode('copy'),
|
||||||
action(node: Node) {
|
action(node: Node) {
|
||||||
// node.remove();
|
// node.remove();
|
||||||
|
const { document: doc, parent, schema, index } = node;
|
||||||
|
parent && doc.insertNode(parent, schema, index);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
important: true,
|
important: true,
|
||||||
|
|||||||
@ -4,6 +4,67 @@ import { focusing } from './focusing';
|
|||||||
import { insertChildren, TransformStage } from '../document';
|
import { insertChildren, TransformStage } from '../document';
|
||||||
import clipboard from './clipboard';
|
import clipboard from './clipboard';
|
||||||
|
|
||||||
|
function getNextForSelect(next: any, head?: any, parent?: any): any {
|
||||||
|
if (next) {
|
||||||
|
if (!head) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret;
|
||||||
|
if (next.isContainer()) {
|
||||||
|
const children = next.getChildren() || [];
|
||||||
|
if (children && !children.isEmpty()) {
|
||||||
|
ret = getNextForSelect(children.get(0));
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = getNextForSelect(next.nextSibling);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
return getNextForSelect(parent.nextSibling, false, parent.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrevForSelect(prev: any, head?: any, parent?: any): any {
|
||||||
|
if (prev) {
|
||||||
|
debugger;
|
||||||
|
let ret;
|
||||||
|
if (!head && prev.isContainer()) {
|
||||||
|
const children = prev.getChildren() || [];
|
||||||
|
const lastChild = children && !children.isEmpty() ? children.get(children.size - 1) : null;
|
||||||
|
|
||||||
|
ret = getPrevForSelect(lastChild);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!head) {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = getPrevForSelect(prev.prevSibling);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// hotkey binding
|
// hotkey binding
|
||||||
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
|
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
|
||||||
const doc = focusing.focusDesigner?.currentDocument;
|
const doc = focusing.focusDesigner?.currentDocument;
|
||||||
@ -58,14 +119,15 @@ hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], (e, action) => {
|
|||||||
const data = { type: 'nodeSchema', componentsMap, componentsTree };
|
const data = { type: 'nodeSchema', componentsMap, componentsTree };
|
||||||
|
|
||||||
clipboard.setData(data);
|
clipboard.setData(data);
|
||||||
/*
|
|
||||||
const cutMode = action.indexOf('x') > 0;
|
const cutMode = action.indexOf('x') > 0;
|
||||||
if (cutMode) {
|
if (cutMode) {
|
||||||
const parentNode = selected.getParent();
|
selected.forEach((node) => {
|
||||||
parentNode.select();
|
const parentNode = node.getParent();
|
||||||
selected.remove();
|
parentNode?.select();
|
||||||
|
node.remove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// command + v paste
|
// command + v paste
|
||||||
@ -111,3 +173,92 @@ hotkey.bind(['command+y', 'ctrl+y', 'command+shift+z'], (e) => {
|
|||||||
|
|
||||||
his.forward();
|
his.forward();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// sibling selection
|
||||||
|
hotkey.bind(['left', 'right'], (e, action) => {
|
||||||
|
const designer = focusing.focusDesigner;
|
||||||
|
const doc = designer?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
const selected = doc.selection.getTopNodes(true);
|
||||||
|
if (!selected || selected.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const firstNode = selected[0];
|
||||||
|
const silbing = action === 'left' ? firstNode?.prevSibling : firstNode?.nextSibling;
|
||||||
|
silbing?.select();
|
||||||
|
});
|
||||||
|
|
||||||
|
hotkey.bind(['up', 'down'], (e, action) => {
|
||||||
|
const designer = focusing.focusDesigner;
|
||||||
|
const doc = designer?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
const selected = doc.selection.getTopNodes(true);
|
||||||
|
if (!selected || selected.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const firstNode = selected[0];
|
||||||
|
|
||||||
|
if (action === 'down') {
|
||||||
|
const next = getNextForSelect(firstNode, true, firstNode.getParent());
|
||||||
|
next?.select();
|
||||||
|
} else if (action === 'up') {
|
||||||
|
const prev = getPrevForSelect(firstNode, true, firstNode.getParent());
|
||||||
|
prev?.select();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
hotkey.bind(['option+up', 'option+down', 'option+left', 'option+right'], (e, action) => {
|
||||||
|
const designer = focusing.focusDesigner;
|
||||||
|
const doc = designer?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
const selected = doc.selection.getTopNodes(true);
|
||||||
|
if (!selected || selected.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: 此处需要增加判断当前节点是否可被操作移动,原ve里是用 node.canOperating()来判断
|
||||||
|
|
||||||
|
const firstNode = selected[0];
|
||||||
|
const parent = firstNode.getParent();
|
||||||
|
if (!parent) return;
|
||||||
|
|
||||||
|
const isPrev = /(up|left)$/.test(action);
|
||||||
|
const isTravel = /(up|down)$/.test(action);
|
||||||
|
|
||||||
|
const silbing = isPrev ? firstNode.prevSibling : firstNode.nextSibling;
|
||||||
|
if (silbing) {
|
||||||
|
if (isTravel && silbing.isContainer()) {
|
||||||
|
const place = silbing.getSuitablePlace(firstNode, null);
|
||||||
|
if (isPrev) {
|
||||||
|
place.container.insertAfter(firstNode, place.ref);
|
||||||
|
} else {
|
||||||
|
place.container.insertBefore(firstNode, place.ref);
|
||||||
|
}
|
||||||
|
} else if (isPrev) {
|
||||||
|
parent.insertBefore(firstNode, silbing);
|
||||||
|
} else {
|
||||||
|
parent.insertAfter(firstNode, silbing);
|
||||||
|
}
|
||||||
|
firstNode?.select();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isTravel) {
|
||||||
|
const place = parent.getSuitablePlace(firstNode, null); // upwards
|
||||||
|
if (place) {
|
||||||
|
if (isPrev) {
|
||||||
|
place.container.insertBefore(firstNode, place.ref);
|
||||||
|
} else {
|
||||||
|
place.container.insertAfter(firstNode, place.ref);
|
||||||
|
}
|
||||||
|
firstNode?.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -180,6 +180,11 @@ export class SettingPropEntry implements SettingEntry {
|
|||||||
return this.top;
|
return this.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add settingfield props
|
||||||
|
get props() {
|
||||||
|
return this.top;
|
||||||
|
}
|
||||||
|
|
||||||
onValueChange(func: () => any) {
|
onValueChange(func: () => any) {
|
||||||
this.emitter.on('valuechange', func);
|
this.emitter.on('valuechange', func);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
// all this file for polyfill vision logic
|
// all this file for polyfill vision logic
|
||||||
|
|
||||||
import { isValidElement } from 'react';
|
import { isValidElement } from 'react';
|
||||||
|
import { isSetterConfig } from '@ali/lowcode-types';
|
||||||
|
import { getSetter } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
function getHotterFromSetter(setter) {
|
function getHotterFromSetter(setter) {
|
||||||
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line
|
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line
|
||||||
@ -40,6 +42,13 @@ export class Transducer {
|
|||||||
setter = setter.props.setters[0];
|
setter = setter.props.setters[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isSetterConfig(setter)) {
|
||||||
|
setter = setter.componentName;
|
||||||
|
}
|
||||||
|
if (typeof setter === 'string') {
|
||||||
|
setter = getSetter(setter);
|
||||||
|
}
|
||||||
|
|
||||||
this.setterTransducer = combineTransducer(
|
this.setterTransducer = combineTransducer(
|
||||||
getTransducerFromSetter(setter),
|
getTransducerFromSetter(setter),
|
||||||
getHotterFromSetter(setter),
|
getHotterFromSetter(setter),
|
||||||
|
|||||||
@ -41,6 +41,7 @@ export class DocumentModel {
|
|||||||
private seqId = 0;
|
private seqId = 0;
|
||||||
private _simulator?: ISimulatorHost;
|
private _simulator?: ISimulatorHost;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模拟器
|
* 模拟器
|
||||||
*/
|
*/
|
||||||
@ -110,6 +111,14 @@ export class DocumentModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readonly designer = this.project.designer;
|
readonly designer = this.project.designer;
|
||||||
|
// getAddonData(name: string) {
|
||||||
|
// const addon = this.addons.find((item) => item.name === name);
|
||||||
|
// if (addon) {
|
||||||
|
// return addon.exportData();
|
||||||
|
// }
|
||||||
|
// return this.addonsData[name];
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成唯一id
|
* 生成唯一id
|
||||||
@ -230,6 +239,14 @@ export class DocumentModel {
|
|||||||
this.selection.remove(node.id);
|
this.selection.remove(node.id);
|
||||||
node.remove();
|
node.remove();
|
||||||
}
|
}
|
||||||
|
getAddonData(name: string) {
|
||||||
|
const addon = this.getNode(name)
|
||||||
|
if (addon) {
|
||||||
|
// 无法确定是否有这个api
|
||||||
|
// return addon.exportData();
|
||||||
|
}
|
||||||
|
return addon
|
||||||
|
}
|
||||||
|
|
||||||
@obx.ref private _dropLocation: DropLocation | null = null;
|
@obx.ref private _dropLocation: DropLocation | null = null;
|
||||||
/**
|
/**
|
||||||
@ -461,14 +478,16 @@ export class DocumentModel {
|
|||||||
return config.checkNestingDown(parent, obj) && this.checkNestingUp(parent, obj);
|
return config.checkNestingDown(parent, obj) && this.checkNestingUp(parent, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======= compatibles
|
// ======= compatibles for vision
|
||||||
getRoot() {
|
getRoot() {
|
||||||
return this.rootNode;
|
return this.rootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// add toData
|
||||||
* 兼容vision
|
toData() {
|
||||||
*/
|
return { componentsTree: [this.project?.currentDocument?.export(TransformStage.Save)] };
|
||||||
|
}
|
||||||
|
|
||||||
getHistory(): History {
|
getHistory(): History {
|
||||||
return this.history;
|
return this.history;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,6 +174,10 @@ export class History {
|
|||||||
this.emitter.removeAllListeners();
|
this.emitter.removeAllListeners();
|
||||||
this.records = [];
|
this.records = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isModified() {
|
||||||
|
return this.point !== this.session.cursor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Session {
|
class Session {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
PropsList,
|
PropsList,
|
||||||
NodeData,
|
NodeData,
|
||||||
TitleContent,
|
TitleContent,
|
||||||
|
I18nData,
|
||||||
SlotSchema,
|
SlotSchema,
|
||||||
PageSchema,
|
PageSchema,
|
||||||
ComponentSchema,
|
ComponentSchema,
|
||||||
@ -19,6 +20,7 @@ import { Prop } from './props/prop';
|
|||||||
import { ComponentMeta } from '../../component-meta';
|
import { ComponentMeta } from '../../component-meta';
|
||||||
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
||||||
import { TransformStage } from './transform-stage';
|
import { TransformStage } from './transform-stage';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础节点
|
* 基础节点
|
||||||
@ -122,7 +124,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get title(): TitleContent {
|
@computed get title(): string | I18nData | ReactElement {
|
||||||
let t = this.getExtraProp('title');
|
let t = this.getExtraProp('title');
|
||||||
if (!t && this.componentMeta.descriptor) {
|
if (!t && this.componentMeta.descriptor) {
|
||||||
t = this.getProp(this.componentMeta.descriptor, false);
|
t = this.getProp(this.componentMeta.descriptor, false);
|
||||||
@ -136,6 +138,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return this.componentMeta.title;
|
return this.componentMeta.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get icon() {
|
||||||
|
return this.componentMeta.icon;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(readonly document: DocumentModel, nodeSchema: Schema) {
|
constructor(readonly document: DocumentModel, nodeSchema: Schema) {
|
||||||
const { componentName, id, children, props, ...extras } = nodeSchema;
|
const { componentName, id, children, props, ...extras } = nodeSchema;
|
||||||
this.id = id || `node$${document.nextId()}`;
|
this.id = id || `node$${document.nextId()}`;
|
||||||
@ -154,8 +160,9 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
|
|
||||||
private transformProps(props: any): any {
|
private transformProps(props: any): any {
|
||||||
// FIXME! support PropsList
|
// FIXME! support PropsList
|
||||||
return this.document.designer.transformProps(props, this, TransformStage.Init);
|
const x = this.document.designer.transformProps(props, this, TransformStage.Init);
|
||||||
|
|
||||||
|
return x;
|
||||||
// TODO: run transducers in metadata.experimental
|
// TODO: run transducers in metadata.experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,19 +184,19 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return this.isParental() && this.componentMeta.isContainer;
|
return this.isParental() && this.componentMeta.isContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRoot(): this is RootNode {
|
isRoot(): boolean {
|
||||||
return this.document.rootNode == (this as any);
|
return this.document.rootNode == (this as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
isPage(): this is PageNode {
|
isPage(): boolean {
|
||||||
return this.isRoot() && this.componentName === 'Page';
|
return this.isRoot() && this.componentName === 'Page';
|
||||||
}
|
}
|
||||||
|
|
||||||
isComponent(): this is ComponentNode {
|
isComponent(): boolean {
|
||||||
return this.isRoot() && this.componentName === 'Component';
|
return this.isRoot() && this.componentName === 'Component';
|
||||||
}
|
}
|
||||||
|
|
||||||
isSlot(): this is SlotNode {
|
isSlot(): boolean {
|
||||||
return this._slotFor != null && this.componentName === 'Slot';
|
return this._slotFor != null && this.componentName === 'Slot';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,9 +226,13 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isSlot() && this._parent) {
|
if (this._parent) {
|
||||||
|
if (this.isSlot()) {
|
||||||
|
this._parent.removeSlot(this, false);
|
||||||
|
} else {
|
||||||
this._parent.children.delete(this);
|
this._parent.children.delete(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
@ -252,10 +263,14 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
* 移除当前节点
|
* 移除当前节点
|
||||||
*/
|
*/
|
||||||
remove() {
|
remove() {
|
||||||
if (!this.isSlot() && this.parent) {
|
if (this.parent) {
|
||||||
|
if (this.isSlot()) {
|
||||||
|
this.parent.removeSlot(this, true);
|
||||||
|
} else {
|
||||||
this.parent.children.delete(this, true);
|
this.parent.children.delete(this, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 选择当前节点
|
* 选择当前节点
|
||||||
@ -289,24 +304,13 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return this.props.export(TransformStage.Serilize).props || null;
|
return this.props.export(TransformStage.Serilize).props || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@obx.val _slots: Node[] = [];
|
||||||
@computed hasSlots() {
|
@computed hasSlots() {
|
||||||
for (const item of this.props) {
|
return this._slots.length > 0;
|
||||||
if (item.type === 'slot') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get slots() {
|
get slots() {
|
||||||
// TODO: optimize recore/obx, array maked every time, donot as changed
|
return this._slots;
|
||||||
const slots: Node[] = [];
|
|
||||||
this.props.forEach((item) => {
|
|
||||||
if (item.type === 'slot') {
|
|
||||||
slots.push(item.slotNode!);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return slots;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref private _conditionGroup: ExclusiveGroup | null = null;
|
@obx.ref private _conditionGroup: ExclusiveGroup | null = null;
|
||||||
@ -352,7 +356,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
|
|
||||||
@computed hasCondition() {
|
@computed hasCondition() {
|
||||||
const v = this.getExtraProp('condition', false)?.getValue();
|
const v = this.getExtraProp('condition', false)?.getValue();
|
||||||
return v != null && v !== '';
|
return v != null && v !== '' && v !== true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed hasLoop() {
|
@computed hasLoop() {
|
||||||
@ -536,6 +540,28 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return comparePosition(this, otherNode);
|
return comparePosition(this, otherNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个Slot节点
|
||||||
|
*/
|
||||||
|
removeSlot(slotNode: Node, purge = false): boolean {
|
||||||
|
const i = this._slots.indexOf(slotNode);
|
||||||
|
if (i < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const deleted = this._slots.splice(i, 1)[0];
|
||||||
|
if (purge) {
|
||||||
|
// should set parent null
|
||||||
|
deleted.internalSetParent(null);
|
||||||
|
deleted.purge();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
addSlot(slotNode: Node) {
|
||||||
|
slotNode.internalSetParent(this as ParentalNode);
|
||||||
|
this._slots.push(slotNode);
|
||||||
|
}
|
||||||
|
|
||||||
private purged = false;
|
private purged = false;
|
||||||
/**
|
/**
|
||||||
* 是否已销毁
|
* 是否已销毁
|
||||||
@ -679,9 +705,20 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRect(): DOMRect | null {
|
getRect(): DOMRect | null {
|
||||||
|
if (this.isRoot()) {
|
||||||
|
return this.document.simulator?.viewport.contentBounds || null;
|
||||||
|
}
|
||||||
return this.document.simulator?.computeRect(this) || null;
|
return this.document.simulator?.computeRect(this) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPrototype() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIcon() {
|
||||||
|
return this.icon;
|
||||||
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -221,7 +221,7 @@ export class Prop implements IPropParent {
|
|||||||
} else {
|
} else {
|
||||||
const owner = this.props.owner;
|
const owner = this.props.owner;
|
||||||
this._slotNode = owner.document.createNode<SlotNode>(slotSchema);
|
this._slotNode = owner.document.createNode<SlotNode>(slotSchema);
|
||||||
this._slotNode.internalSetParent(owner as any);
|
owner.addSlot(this._slotNode);
|
||||||
this._slotNode.internalSetSlotFor(this);
|
this._slotNode.internalSetSlotFor(this);
|
||||||
}
|
}
|
||||||
this.dispose();
|
this.dispose();
|
||||||
|
|||||||
@ -309,4 +309,11 @@ export class Props implements IPropParent {
|
|||||||
getPropValue(path: string): any {
|
getPropValue(path: string): any {
|
||||||
return this.getProp(path, false)?.value;
|
return this.getProp(path, false)?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单个属性值
|
||||||
|
*/
|
||||||
|
setPropValue(path: string, value: any) {
|
||||||
|
this.getProp(path, true)!.setValue(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
|
"hide": "Hide",
|
||||||
"Condition Group": "Condition Group",
|
"Condition Group": "Condition Group",
|
||||||
"No opened document": "No opened document, open some document to editing"
|
"No opened document": "No opened document, open some document to editing"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"copy": "复制",
|
"copy": "复制",
|
||||||
"remove": "删除",
|
"remove": "删除",
|
||||||
|
"hide": "隐藏",
|
||||||
"Condition Group": "条件组",
|
"Condition Group": "条件组",
|
||||||
"No opened document": "没有打开的页面,请选择页面打开编辑"
|
"No opened document": "没有打开的页面,请选择页面打开编辑"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,13 +49,14 @@ class AliGlobalLocale {
|
|||||||
}
|
}
|
||||||
} else if (g_config) {
|
} else if (g_config) {
|
||||||
if (g_config.locale) {
|
if (g_config.locale) {
|
||||||
return languageMap[g_config.locale] || (g_config.locale || '').replace('_', '-');
|
return languageMap[g_config.locale] || g_config.locale.replace('_', '-');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let locale: string = '';
|
let locale: string = '';
|
||||||
if (navigator.language) {
|
if (navigator.language) {
|
||||||
locale = (navigator.language as string).replace('_', '-');
|
const lang = (navigator.language as string);
|
||||||
|
return languageMap[lang] || lang.replace('_', '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
// IE10 及更低版本使用 browserLanguage
|
// IE10 及更低版本使用 browserLanguage
|
||||||
|
|||||||
@ -37,10 +37,13 @@ function injectVars(msg: string, params: any, locale: string): string {
|
|||||||
});*/
|
});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
export function intl(data: any, params?: object): string {
|
export function intl(data: any, params?: object): ReactNode {
|
||||||
if (!isI18nData(data)) {
|
if (!isI18nData(data)) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
if (data.intl) {
|
||||||
|
return data.intl;
|
||||||
|
}
|
||||||
const locale = globalLocale.getLocale();
|
const locale = globalLocale.getLocale();
|
||||||
const tries = generateTryLocales(locale);
|
const tries = generateTryLocales(locale);
|
||||||
let msg: string | undefined;
|
let msg: string | undefined;
|
||||||
|
|||||||
48
packages/editor-core/src/utils/focusing-track.ts
Normal file
48
packages/editor-core/src/utils/focusing-track.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
class FocusingManager {
|
||||||
|
deploy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
send(e: MouseEvent | KeyboardEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
addModalCheck() {
|
||||||
|
|
||||||
|
}
|
||||||
|
create(config: FocusableConfig) {
|
||||||
|
|
||||||
|
}
|
||||||
|
activeItem() {
|
||||||
|
|
||||||
|
}
|
||||||
|
suspenceItem() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FocusableConfig {
|
||||||
|
range: HTMLElement | ((e: MouseEvent) => boolean);
|
||||||
|
modal?: boolean;
|
||||||
|
onEsc?: () => void;
|
||||||
|
onBlur?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Focusable {
|
||||||
|
readonly isModal: boolean;
|
||||||
|
constructor(private manager: FocusingManager, { range, modal }: FocusableConfig) {
|
||||||
|
this.isModal = modal == null ? false : modal;
|
||||||
|
|
||||||
|
}
|
||||||
|
checkRange(e: MouseEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
active() {
|
||||||
|
this.manager.activeItem(this);
|
||||||
|
}
|
||||||
|
suspence() {
|
||||||
|
this.manager.suspenceItem(this);
|
||||||
|
}
|
||||||
|
purge() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.lc-field-icon {
|
.lc-field-icon {
|
||||||
margin-right: @x-gap;
|
// margin-right: @x-gap;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
transition: transform 0.1s;
|
transition: transform 0.1s;
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
&.lc-plain-field {
|
&.lc-plain-field {
|
||||||
// for top-level style
|
// for top-level style
|
||||||
padding: 8px 10px;
|
// padding: 8px 10px;
|
||||||
> .lc-field-body {
|
> .lc-field-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -34,7 +34,16 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
// for top-level style
|
// for top-level style
|
||||||
padding: 8px 10px;
|
padding: 16px;
|
||||||
|
&:first-child{
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
&:last-child{
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
&+.lc-inline-field{
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
> .lc-field-head {
|
> .lc-field-head {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
@ -58,19 +67,29 @@
|
|||||||
border-top: 1px solid var(--color-line-normal);
|
border-top: 1px solid var(--color-line-normal);
|
||||||
}
|
}
|
||||||
> .lc-field-head {
|
> .lc-field-head {
|
||||||
padding-left: @x-gap;
|
// padding-left: @x-gap;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
background: var(--color-block-background-shallow, rgba(31,56,88,.06));
|
// background: var(--color-block-background-shallow, rgba(31,56,88,.06));
|
||||||
border-bottom: 1px solid var(--color-line-normal);
|
// border-bottom: 1px solid var(--color-line-normal);
|
||||||
color: var(--color-title);
|
// color: var(--color-title);
|
||||||
|
padding: 0 16px;
|
||||||
|
background-color: #F7F9FC;
|
||||||
|
color: #8F9BB3;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .lc-field-body {
|
> .lc-field-body {
|
||||||
padding: @y-gap @x-gap/2;
|
// padding: @y-gap @x-gap/2;
|
||||||
|
padding: 16px;
|
||||||
|
.lc-inline-field{
|
||||||
|
margin-bottom: 16px;
|
||||||
|
&:last-child{
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ .lc-inline-field {
|
+ .lc-inline-field {
|
||||||
@ -94,7 +113,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.lc-accordion-field {
|
&.lc-accordion-field {
|
||||||
|
position: relative;
|
||||||
// collapsed
|
// collapsed
|
||||||
|
&:last-child.lc-field-is-collapsed{
|
||||||
|
border-bottom: 1px solid var(--color-line-normal);
|
||||||
|
}
|
||||||
&.lc-field-is-collapsed {
|
&.lc-field-is-collapsed {
|
||||||
> .lc-field-head .lc-field-icon {
|
> .lc-field-head .lc-field-icon {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
@ -106,14 +129,15 @@
|
|||||||
|
|
||||||
// 邻近的保持上下距离
|
// 邻近的保持上下距离
|
||||||
+ .lc-field {
|
+ .lc-field {
|
||||||
margin-top: @y-gap;
|
// margin-top: @y-gap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2rd level reset
|
// 2rd level reset
|
||||||
.lc-field-body {
|
.lc-field-body {
|
||||||
.lc-inline-field {
|
.lc-inline-field {
|
||||||
padding: @y-gap @x-gap/2 0 @x-gap/2;
|
// padding: @y-gap @x-gap/2 0 @x-gap/2;
|
||||||
|
padding: 0;
|
||||||
&:first-child {
|
&:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
@ -130,9 +154,10 @@
|
|||||||
> .lc-field-head {
|
> .lc-field-head {
|
||||||
padding-left: @x-gap/2;
|
padding-left: @x-gap/2;
|
||||||
background: var(--color-block-background-light);
|
background: var(--color-block-background-light);
|
||||||
border-bottom-color: var(--color-line-light);
|
border-bottom-color: var(--color-line-light, rgba(31, 56, 88, .1));
|
||||||
> .lc-field-icon {
|
> .lc-field-icon {
|
||||||
margin-right: @x-gap/2;
|
// margin-right: @x-gap/2;
|
||||||
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,5 +171,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
>.lc-block-setter {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,9 +42,22 @@
|
|||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
>.lc-setter-actions {
|
>.lc-setter-actions {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 16px;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lc-block-field > .lc-field-body > .lc-setter-mixed{
|
||||||
|
|
||||||
|
}
|
||||||
|
.lc-accordion-field > .lc-field-body > .lc-setter-mixed{
|
||||||
|
position: static;
|
||||||
|
margin-right: 0;
|
||||||
|
> .lc-setter-actions{
|
||||||
|
right: 32px;
|
||||||
|
top: 6px;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -70,13 +70,6 @@ export class SettingsMain {
|
|||||||
this._settings = this.designer.createSettingEntry(this.editor, nodes);
|
this._settings = this.designer.createSettingEntry(this.editor, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
onceOutlineVisible(fn: () => void): () => void {
|
|
||||||
this.emitter.on('outline-visible', fn);
|
|
||||||
return () => {
|
|
||||||
this.emitter.removeListener('outline-visible', fn);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
purge() {
|
purge() {
|
||||||
this.disposeListener();
|
this.disposeListener();
|
||||||
this.emitter.removeAllListeners();
|
this.emitter.removeAllListeners();
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 5px;
|
padding: 0 16px;
|
||||||
border-bottom: 1px solid var(--color-line-normal);
|
border-bottom: 1px solid var(--color-line-normal);
|
||||||
.lc-settings-navigator-icon {
|
.lc-settings-navigator-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
|||||||
@ -12,6 +12,8 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private dispose?: () => void;
|
private dispose?: () => void;
|
||||||
|
// private focusing?: FocusingItem;
|
||||||
|
private shell: HTMLElement | null = null;
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { area } = this.props;
|
const { area } = this.props;
|
||||||
const triggerClose = () => area.setVisible(false);
|
const triggerClose = () => area.setVisible(false);
|
||||||
@ -19,18 +21,44 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
|
|||||||
this.dispose = () => {
|
this.dispose = () => {
|
||||||
area.skeleton.editor.removeListener('designer.dragstart', triggerClose);
|
area.skeleton.editor.removeListener('designer.dragstart', triggerClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.focusing = focusingTrack.create(this.shell!, {
|
||||||
|
onEsc: () => {
|
||||||
|
this.props.area.setVisible(false);
|
||||||
|
},
|
||||||
|
onBlur: () => {
|
||||||
|
this.props.area.setVisible(false);
|
||||||
|
},
|
||||||
|
// modal: boolean
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.onEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEffect() {
|
||||||
|
/*
|
||||||
|
const { area } = this.props;
|
||||||
|
if (area.visible) {
|
||||||
|
this.focusing?.active();
|
||||||
|
} else {
|
||||||
|
this.focusing?.suspense();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.onEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
// this.focusing?.purge();
|
||||||
this.dispose?.();
|
this.dispose?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { area } = this.props;
|
const { area } = this.props;
|
||||||
// TODO: add focusingManager
|
|
||||||
// focusin set focus (push|replace)
|
|
||||||
// focusout remove focus
|
|
||||||
// onEsc
|
|
||||||
const width = area.current?.config.props?.width;
|
const width = area.current?.config.props?.width;
|
||||||
const hideTitleBar = area.current?.config.props?.hideTitleBar;
|
const hideTitleBar = area.current?.config.props?.hideTitleBar;
|
||||||
const style = width ? {
|
const style = width ? {
|
||||||
@ -38,6 +66,7 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
|
|||||||
} : undefined;
|
} : undefined;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={(ref) => { this.shell = ref }}
|
||||||
className={classNames('lc-left-float-pane', {
|
className={classNames('lc-left-float-pane', {
|
||||||
'lc-area-visible': area.visible,
|
'lc-area-visible': area.visible,
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export default class MainArea extends Component<{ area: Area<any, Panel | Widget
|
|||||||
render() {
|
render() {
|
||||||
const { area } = this.props;
|
const { area } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={classNames('lc-main-area')}>
|
<div className={classNames('lc-main-area engine-workspacepane')}>
|
||||||
{area.container.items.map((item) => item.content)}
|
{area.container.items.map((item) => item.content)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export default class RightArea extends Component<{ area: Area<any, Panel> }> {
|
|||||||
render() {
|
render() {
|
||||||
const { area } = this.props;
|
const { area } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={classNames('lc-right-area', {
|
<div className={classNames('lc-right-area engine-tabpane', {
|
||||||
'lc-area-visible': area.visible,
|
'lc-area-visible': area.visible,
|
||||||
})}>
|
})}>
|
||||||
<Contents area={area} />
|
<Contents area={area} />
|
||||||
|
|||||||
@ -4,23 +4,23 @@ import { observer } from '@ali/lowcode-editor-core';
|
|||||||
import Area from '../area';
|
import Area from '../area';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class TopArea extends Component<{ area: Area }> {
|
export default class TopArea extends Component<{ area: Area, itemClassName?: string }> {
|
||||||
render() {
|
render() {
|
||||||
const { area } = this.props;
|
const { area, itemClassName } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={classNames("lc-top-area", {
|
<div className={classNames("lc-top-area engine-actionpane", {
|
||||||
'lc-area-visible': area.visible
|
'lc-area-visible': area.visible
|
||||||
})}>
|
})}>
|
||||||
<Contents area={area} />
|
<Contents area={area} itemClassName={itemClassName} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Contents extends Component<{ area: Area }> {
|
class Contents extends Component<{ area: Area, itemClassName?: string }> {
|
||||||
render() {
|
render() {
|
||||||
const { area } = this.props;
|
const { area, itemClassName } = this.props;
|
||||||
const left: any[] = [];
|
const left: any[] = [];
|
||||||
const center: any[] = [];
|
const center: any[] = [];
|
||||||
const right: any[] = [];
|
const right: any[] = [];
|
||||||
@ -29,12 +29,17 @@ class Contents extends Component<{ area: Area }> {
|
|||||||
const index2 = b.config?.index || 0;
|
const index2 = b.config?.index || 0;
|
||||||
return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1);
|
return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1);
|
||||||
}).forEach(item => {
|
}).forEach(item => {
|
||||||
|
const content = (
|
||||||
|
<div className={itemClassName || ''}>
|
||||||
|
{item.content}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
if (item.align === 'center') {
|
if (item.align === 'center') {
|
||||||
center.push(item.content);
|
center.push(content);
|
||||||
} else if (item.align === 'left') {
|
} else if (item.align === 'left') {
|
||||||
left.push(item.content);
|
left.push(content);
|
||||||
} else {
|
} else {
|
||||||
right.push(item.content);
|
right.push(content);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -54,14 +54,11 @@ body {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.lc-panel-title {
|
.lc-panel-title {
|
||||||
height: 38px;
|
// background-color: var(--pane-title-bg-color,rgba(31,56,88,.04));
|
||||||
font-size: 14px;
|
|
||||||
background-color: var(--pane-title-bg-color,rgba(31,56,88,.04));
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
border-bottom: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
|
|
||||||
|
|
||||||
.lc-help-tip {
|
.lc-help-tip {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
@ -69,10 +66,18 @@ body {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
> .lc-panel-title {
|
||||||
|
height: 48px;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 0 15px;
|
||||||
|
// border-bottom: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
|
||||||
|
color: #0F1726;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.lc-panel-body {
|
.lc-panel-body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 38px;
|
top: 48px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -111,6 +116,9 @@ body {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
.lc-outline-pane{
|
||||||
|
border-top: 1px solid var(--color-line-normal,rgba(31,56,88,.1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.lc-panel {
|
.lc-panel {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -153,23 +161,88 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
/*覆盖旧面板*/
|
||||||
|
/*组件面板*/
|
||||||
|
// .ve-component-list {
|
||||||
|
// .ve-component-list-body{
|
||||||
|
// .ve-component-list-sidebar{
|
||||||
|
// .ve-component-list-navigator{
|
||||||
|
// .navigator-group{
|
||||||
|
// &:last-child{
|
||||||
|
// &::after{
|
||||||
|
// display: none;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &::after{
|
||||||
|
// content: '';
|
||||||
|
// display: block;
|
||||||
|
// height: 1px;
|
||||||
|
// background-color: #EDEFF3;
|
||||||
|
// line-height: 0;
|
||||||
|
// margin: 4px 12px 0;
|
||||||
|
// }
|
||||||
|
// .navigator-group-head{
|
||||||
|
// .navigator-group-title{
|
||||||
|
// border-bottom: none;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .navigator-group-item{
|
||||||
|
// border-left: 2px solid transparent;
|
||||||
|
// &.active{
|
||||||
|
// border-left-color: #0079f2;
|
||||||
|
// border-right: none;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
/*数据源*/
|
||||||
|
// .engine-datapool{
|
||||||
|
// .engine-datapool-view-group{
|
||||||
|
// padding-top: 48px;
|
||||||
|
// .engine-datapool-view-group-title{
|
||||||
|
// height: 48px;
|
||||||
|
// line-height: 48px;
|
||||||
|
// font-size: 16px;
|
||||||
|
// background-color: transparent;
|
||||||
|
// padding: 0 16px;
|
||||||
|
// border-bottom: 1px solid #EDEFF3;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
/*动作面板*/
|
||||||
|
// .ve-action-pane{
|
||||||
|
// border-top: none;
|
||||||
|
// .rc-tabs{
|
||||||
|
// .rc-tabs-bar{
|
||||||
|
// background-color: transparent;
|
||||||
|
// .rc-tabs-tab{
|
||||||
|
// line-height: 1;
|
||||||
|
// &.rc-tabs-tab-active{
|
||||||
|
|
||||||
.my-dock {
|
// }
|
||||||
padding: 0px 10px;
|
// }
|
||||||
cursor: pointer;
|
// }
|
||||||
align-self: stretch;
|
// }
|
||||||
display: flex;
|
// }
|
||||||
align-items: center;
|
|
||||||
.my-title-label {
|
/*设置面板*/
|
||||||
user-select: none;
|
// .ve-field .ve-field-head,
|
||||||
}
|
// .ve-field.ve-accordion2-field > .ve-field-head .ve-field-title-content{
|
||||||
&.actived, &:hover {
|
// padding: 0;
|
||||||
background-color: var(--pane-title-bg-color);
|
// }
|
||||||
.my-title {
|
// .ve-field.ve-accordion2-field > .ve-field-split-line{
|
||||||
color: var(--color-actived);
|
// display: none;
|
||||||
}
|
// }
|
||||||
}
|
// .vs-style .vs-style-source{
|
||||||
|
// margin: 0 0 16px;
|
||||||
|
// }
|
||||||
|
// .vs-code-button,
|
||||||
|
// .vs-json-button{
|
||||||
|
// margin: 0;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -184,13 +257,13 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
padding: 8px;
|
padding: 8px 12px 8px 16px;
|
||||||
.lc-top-area-left{}
|
|
||||||
.lc-top-area-center{
|
.lc-top-area-center{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: center;
|
||||||
margin-right: 8px;
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
.lc-top-area-right{
|
.lc-top-area-right{
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -222,8 +295,9 @@ body {
|
|||||||
}
|
}
|
||||||
.lc-pane-close{
|
.lc-pane-close{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 16px;
|
||||||
top: 6px;
|
top: 16px;
|
||||||
|
height: auto;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
.next-icon{
|
.next-icon{
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@ -231,17 +305,32 @@ body {
|
|||||||
}
|
}
|
||||||
.lc-tabs-title {
|
.lc-tabs-title {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 36px;
|
height: 32px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: center;
|
display: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(31,56,88,0.04);
|
// background: rgba(31,56,88,0.04);
|
||||||
|
border-bottom: 1px solid #EDEFF3;
|
||||||
|
.lc-tab-title{
|
||||||
|
flex: 1;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
&.actived {
|
||||||
|
color: #0079F2;
|
||||||
|
border-bottom-color: #0079F2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.lc-tabs-content {
|
.lc-tabs-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 36px;
|
top: 32px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -265,16 +354,23 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.lc-title{
|
.lc-title {
|
||||||
padding: 12px;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
&.has-tip{
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&.has-tip {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
&.actived{
|
&.actived{
|
||||||
color: #0079F2;
|
color: #0079F2;
|
||||||
}
|
}
|
||||||
.lc-title-icon{
|
.lc-title-icon {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
.next-icon:before {
|
.next-icon:before {
|
||||||
line-height: 1 !important;
|
line-height: 1 !important;
|
||||||
@ -301,8 +397,9 @@ body {
|
|||||||
}
|
}
|
||||||
.lc-pane-close {
|
.lc-pane-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 16px;
|
||||||
top: 6px;
|
top: 16px;
|
||||||
|
height: auto;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
.next-icon {
|
.next-icon {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@ -324,6 +421,7 @@ body {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
z-index: 10;
|
||||||
.lc-toolbar {
|
.lc-toolbar {
|
||||||
height: var(--toolbar-height);
|
height: var(--toolbar-height);
|
||||||
background-color: var(--color-pane-background);
|
background-color: var(--color-pane-background);
|
||||||
|
|||||||
@ -13,16 +13,16 @@ import RightArea from './right-area';
|
|||||||
import './workbench.less';
|
import './workbench.less';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class Workbench extends Component<{ skeleton: Skeleton, className?: string }> {
|
export class Workbench extends Component<{ skeleton: Skeleton, className?: string, topAreaItemClassName?: string }> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { skeleton, className } = this.props;
|
const { skeleton, className, topAreaItemClassName } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={classNames('lc-workbench', className)}>
|
<div className={classNames('lc-workbench', className)}>
|
||||||
<TopArea area={skeleton.topArea} />
|
<TopArea area={skeleton.topArea} itemClassName={topAreaItemClassName} />
|
||||||
<div className="lc-workbench-body">
|
<div className="lc-workbench-body">
|
||||||
<LeftArea area={skeleton.leftArea} />
|
<LeftArea area={skeleton.leftArea} />
|
||||||
<LeftFloatPane area={skeleton.leftFloatArea} />
|
<LeftFloatPane area={skeleton.leftFloatArea} />
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types';
|
import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types';
|
||||||
|
import { IconSlot } from '../icons/slot';
|
||||||
|
|
||||||
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
|
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
|
||||||
const { componentName, configure = {} } = metadata;
|
const { componentName, configure = {} } = metadata;
|
||||||
@ -46,7 +47,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
const supportedLifecycles =
|
const supportedLifecycles =
|
||||||
events.supportedLifecycles ||
|
events.supportedLifecycles ||
|
||||||
(isRoot
|
(isRoot
|
||||||
? [
|
? /*[
|
||||||
{
|
{
|
||||||
description: '初始化时',
|
description: '初始化时',
|
||||||
name: 'constructor',
|
name: 'constructor',
|
||||||
@ -63,7 +64,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
description: '卸载时',
|
description: '卸载时',
|
||||||
name: 'componentWillUnmount',
|
name: 'componentWillUnmount',
|
||||||
},
|
},
|
||||||
]
|
]*/ null
|
||||||
: null);
|
: null);
|
||||||
if (supportedLifecycles) {
|
if (supportedLifecycles) {
|
||||||
eventsDefinition.push({
|
eventsDefinition.push({
|
||||||
@ -80,7 +81,22 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 通用设置
|
// 通用设置
|
||||||
const propsGroup = props || [];
|
let propsGroup = props || [];
|
||||||
|
const basicInfo: any = {};
|
||||||
|
if (componentName === 'Slot') {
|
||||||
|
basicInfo.icon = IconSlot;
|
||||||
|
propsGroup = [{
|
||||||
|
name: '___title',
|
||||||
|
title: {
|
||||||
|
type: 'i18n',
|
||||||
|
'en-US': 'Slot Title',
|
||||||
|
'zh-CN': '插槽标题'
|
||||||
|
},
|
||||||
|
setter: 'StringSetter',
|
||||||
|
defaultValue: '插槽容器'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
/*
|
||||||
propsGroup.push({
|
propsGroup.push({
|
||||||
name: '#generals',
|
name: '#generals',
|
||||||
title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' },
|
title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' },
|
||||||
@ -101,14 +117,14 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
title: 'Ref',
|
title: 'Ref',
|
||||||
setter: 'StringSetter',
|
setter: 'StringSetter',
|
||||||
},
|
},
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
name: '!more',
|
name: '!more',
|
||||||
title: '更多',
|
title: '更多',
|
||||||
setter: 'PropertiesSetter',
|
setter: 'PropertiesSetter',
|
||||||
},*/
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
const combined: FieldConfig[] = [
|
const combined: FieldConfig[] = [
|
||||||
{
|
{
|
||||||
title: { type: 'i18n', 'zh-CN': '属性', 'en-US': 'Props' },
|
title: { type: 'i18n', 'zh-CN': '属性', 'en-US': 'Props' },
|
||||||
@ -182,8 +198,15 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: '___condition',
|
name: '___condition',
|
||||||
title: { type: 'i18n', 'zh-CN': '条件显示', 'en-US': 'Condition' },
|
title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' },
|
||||||
setter: 'ExpressionSetter',
|
setter: [{
|
||||||
|
componentName: 'BoolSetter',
|
||||||
|
props: {
|
||||||
|
defaultValue: true,
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
componentName: 'VariableSetter'
|
||||||
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '#loop',
|
name: '#loop',
|
||||||
@ -192,27 +215,14 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
{
|
{
|
||||||
name: '___loop',
|
name: '___loop',
|
||||||
title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' },
|
title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' },
|
||||||
setter: {
|
setter: [{
|
||||||
componentName: 'MixinSetter',
|
componentName: 'JsonSetter',
|
||||||
props: {
|
props: {
|
||||||
// TODO:
|
label: { type: 'i18n', 'zh-CN': '编辑数据', 'en-US': 'Edit Data'},
|
||||||
setters: [
|
|
||||||
{
|
|
||||||
componentName: 'JSONSetter',
|
|
||||||
props: {
|
|
||||||
mode: 'popup',
|
|
||||||
placeholder: { type: 'i18n', 'zh-CN': '编辑数据', 'en-US': 'Edit Data' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
componentName: 'ExpressionSetter',
|
|
||||||
props: {
|
|
||||||
placeholder: { type: 'i18n', 'zh-CN': '绑定数据', 'en-US': 'Bind Data' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
componentName: 'VariableSetter'
|
||||||
|
}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '___loopArgs.0',
|
name: '___loopArgs.0',
|
||||||
@ -236,8 +246,12 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
title: 'Key',
|
title: '循环 Key',
|
||||||
setter: 'ExpressionSetter',
|
setter: [{
|
||||||
|
componentName: 'StringSetter',
|
||||||
|
}, {
|
||||||
|
componentName: 'VariableSetter'
|
||||||
|
}],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -247,6 +261,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
|
...basicInfo,
|
||||||
configure: {
|
configure: {
|
||||||
...configure,
|
...configure,
|
||||||
combined,
|
combined,
|
||||||
|
|||||||
@ -45,6 +45,8 @@ export default class Dock implements IWidget {
|
|||||||
} else {
|
} else {
|
||||||
this._body = createElement(DockView, props);
|
this._body = createElement(DockView, props);
|
||||||
}
|
}
|
||||||
|
this.inited = true;
|
||||||
|
|
||||||
return this._body;
|
return this._body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,14 +59,14 @@ export default class PanelDock implements IWidget {
|
|||||||
this.id = uniqueId(`dock:${name}$`);
|
this.id = uniqueId(`dock:${name}$`);
|
||||||
this.panelName = config.panelName || name;
|
this.panelName = config.panelName || name;
|
||||||
if (content) {
|
if (content) {
|
||||||
|
const _panelProps: any = { ...panelProps };
|
||||||
|
if (_panelProps.title == null && props) {
|
||||||
|
_panelProps.title = composeTitle(props.title, undefined, props.description, true, true);
|
||||||
|
}
|
||||||
this._panel = this.skeleton.add({
|
this._panel = this.skeleton.add({
|
||||||
type: "Panel",
|
type: "Panel",
|
||||||
name: this.panelName,
|
name: this.panelName,
|
||||||
props: {
|
props: _panelProps,
|
||||||
// FIXME! give default title for panel
|
|
||||||
title: props ? composeTitle(props?.title, props?.icon, props?.description, true) : '',
|
|
||||||
...panelProps,
|
|
||||||
},
|
|
||||||
contentProps,
|
contentProps,
|
||||||
content,
|
content,
|
||||||
area: panelProps?.area
|
area: panelProps?.area
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { EventEmitter } from 'events';
|
||||||
import { createElement, ReactNode } from 'react';
|
import { createElement, ReactNode } from 'react';
|
||||||
import { obx } from '@ali/lowcode-editor-core';
|
import { obx } from '@ali/lowcode-editor-core';
|
||||||
import { uniqueId, createContent } from '@ali/lowcode-utils';
|
import { uniqueId, createContent } from '@ali/lowcode-utils';
|
||||||
@ -13,8 +14,9 @@ export default class Panel implements IWidget {
|
|||||||
readonly isWidget = true;
|
readonly isWidget = true;
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
@obx.ref inited: boolean = false;
|
@obx.ref inited = false;
|
||||||
@obx.ref private _actived: boolean = false;
|
@obx.ref private _actived = false;
|
||||||
|
private emitter = new EventEmitter();
|
||||||
get actived(): boolean {
|
get actived(): boolean {
|
||||||
return this._actived;
|
return this._actived;
|
||||||
}
|
}
|
||||||
@ -46,7 +48,7 @@ export default class Panel implements IWidget {
|
|||||||
|
|
||||||
readonly title: TitleContent;
|
readonly title: TitleContent;
|
||||||
readonly help?: HelpTipConfig;
|
readonly help?: HelpTipConfig;
|
||||||
private plain: boolean = false;
|
private plain = false;
|
||||||
|
|
||||||
private container?: WidgetContainer<Panel, PanelConfig>;
|
private container?: WidgetContainer<Panel, PanelConfig>;
|
||||||
private parent?: WidgetContainer;
|
private parent?: WidgetContainer;
|
||||||
@ -60,6 +62,9 @@ export default class Panel implements IWidget {
|
|||||||
this.plain = hideTitleBar || !title;
|
this.plain = hideTitleBar || !title;
|
||||||
this.help = help;
|
this.help = help;
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
|
if (content.length === 1) {
|
||||||
|
// todo: not show tabs
|
||||||
|
}
|
||||||
this.container = this.skeleton.createContainer(
|
this.container = this.skeleton.createContainer(
|
||||||
name,
|
name,
|
||||||
(item) => {
|
(item) => {
|
||||||
@ -121,7 +126,11 @@ export default class Panel implements IWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
active(item?: Panel | string | null) {
|
active(item?: Panel | string | null) {
|
||||||
|
if (item) {
|
||||||
this.container?.active(item);
|
this.container?.active(item);
|
||||||
|
} else {
|
||||||
|
this.setActive(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getName() {
|
getName() {
|
||||||
@ -143,9 +152,11 @@ export default class Panel implements IWidget {
|
|||||||
}
|
}
|
||||||
this._actived = true;
|
this._actived = true;
|
||||||
this.parent?.active(this);
|
this.parent?.active(this);
|
||||||
|
this.emitter.emit('activechange', true);
|
||||||
} else if (this.inited) {
|
} else if (this.inited) {
|
||||||
this._actived = false;
|
this._actived = false;
|
||||||
this.parent?.unactive(this);
|
this.parent?.unactive(this);
|
||||||
|
this.emitter.emit('activechange', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +190,16 @@ export default class Panel implements IWidget {
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
setPosition(position: string) {
|
setPosition(position: string) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
onActiveChange(fn: (flag: boolean) => void): () => void {
|
||||||
|
this.emitter.on('activechange', fn);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('activechange', fn);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { IconType, TitleContent, isI18nData, TipContent } from '@ali/lowcode-types';
|
import { IconType, TitleContent, isI18nData, TipContent, isTitleConfig } from '@ali/lowcode-types';
|
||||||
import { isValidElement } from 'react';
|
import { isValidElement } from 'react';
|
||||||
|
|
||||||
export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean) {
|
export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean, noIcon?: boolean) {
|
||||||
if (!title) {
|
if (!title) {
|
||||||
title = {};
|
title = {};
|
||||||
if (!icon || tipAsTitle) {
|
if (!icon || tipAsTitle) {
|
||||||
@ -11,6 +11,19 @@ export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipCon
|
|||||||
}
|
}
|
||||||
if (icon || tip) {
|
if (icon || tip) {
|
||||||
if (typeof title !== 'object' || isValidElement(title) || isI18nData(title)) {
|
if (typeof title !== 'object' || isValidElement(title) || isI18nData(title)) {
|
||||||
|
if (isValidElement(title)) {
|
||||||
|
if (title.type === 'svg' || (title.type as any).getIcon) {
|
||||||
|
if (!icon) {
|
||||||
|
icon = title as any;
|
||||||
|
}
|
||||||
|
if (tipAsTitle) {
|
||||||
|
title = tip as any;
|
||||||
|
tip = null;
|
||||||
|
} else {
|
||||||
|
title = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
title = {
|
title = {
|
||||||
label: title,
|
label: title,
|
||||||
icon,
|
icon,
|
||||||
@ -24,5 +37,8 @@ export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipCon
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isTitleConfig(title) && noIcon) {
|
||||||
|
title.icon = undefined;
|
||||||
|
}
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export default class WidgetContainer<T extends WidgetItem = any, G extends Widge
|
|||||||
if (nameOrItem && typeof nameOrItem === 'string') {
|
if (nameOrItem && typeof nameOrItem === 'string') {
|
||||||
item = this.get(nameOrItem);
|
item = this.get(nameOrItem);
|
||||||
}
|
}
|
||||||
if (!isActiveable(nameOrItem)) {
|
if (!isActiveable(item)) {
|
||||||
item = null;
|
item = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ export default class WidgetContainer<T extends WidgetItem = any, G extends Widge
|
|||||||
if (nameOrItem && typeof nameOrItem === 'string') {
|
if (nameOrItem && typeof nameOrItem === 'string') {
|
||||||
item = this.get(nameOrItem);
|
item = this.get(nameOrItem);
|
||||||
}
|
}
|
||||||
if (!isActiveable(nameOrItem)) {
|
if (!isActiveable(item)) {
|
||||||
item = null;
|
item = null;
|
||||||
}
|
}
|
||||||
if (this._current === item) {
|
if (this._current === item) {
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import Pane from './views/pane';
|
import Pane from './views/pane';
|
||||||
import { IconOutline } from './icons/outline';
|
import { IconOutline } from './icons/outline';
|
||||||
import { intl } from './locale';
|
import { intlNode } from './locale';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'outline-pane',
|
name: 'outline-pane',
|
||||||
props: {
|
props: {
|
||||||
icon: IconOutline,
|
icon: IconOutline,
|
||||||
description: intl('Outline Tree'),
|
description: intlNode('Outline Tree'),
|
||||||
},
|
},
|
||||||
content: Pane,
|
content: Pane,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { createIntl } from '@ali/lowcode-editor-core';
|
|||||||
import en_US from './en-US.json';
|
import en_US from './en-US.json';
|
||||||
import zh_CN from './zh-CN.json';
|
import zh_CN from './zh-CN.json';
|
||||||
|
|
||||||
const { intl, getLocale, setLocale } = createIntl({
|
const { intl, intlNode, getLocale, setLocale } = createIntl({
|
||||||
'en-US': en_US,
|
'en-US': en_US,
|
||||||
'zh-CN': zh_CN,
|
'zh-CN': zh_CN,
|
||||||
});
|
});
|
||||||
|
|
||||||
export { intl, getLocale, setLocale };
|
export { intl, intlNode, getLocale, setLocale };
|
||||||
|
|||||||
@ -122,7 +122,7 @@ export default class TreeNode {
|
|||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
if (isI18nData(title)) {
|
if (isI18nData(title)) {
|
||||||
return intl(title);
|
return intl(title) as string;
|
||||||
}
|
}
|
||||||
return this.node.componentName;
|
return this.node.componentName;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { observer, Title } from '@ali/lowcode-editor-core';
|
|||||||
import { ExclusiveGroup } from '@ali/lowcode-designer';
|
import { ExclusiveGroup } from '@ali/lowcode-designer';
|
||||||
import TreeNode from '../tree-node';
|
import TreeNode from '../tree-node';
|
||||||
import TreeNodeView from './tree-node';
|
import TreeNodeView from './tree-node';
|
||||||
import { intl } from '../locale';
|
import { intlNode } from '../locale';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class TreeBranches extends Component<{
|
export default class TreeBranches extends Component<{
|
||||||
@ -119,7 +119,7 @@ class TreeNodeSlots extends Component<{
|
|||||||
data-id={treeNode.id}
|
data-id={treeNode.id}
|
||||||
>
|
>
|
||||||
<div className="tree-node-slots-title">
|
<div className="tree-node-slots-title">
|
||||||
<Title title={{ type: 'i18n', intl: intl('Slots') }} />
|
<Title title={{ type: 'i18n', intl: intlNode('Slots') }} />
|
||||||
</div>
|
</div>
|
||||||
{treeNode.slots.map(tnode => (
|
{treeNode.slots.map(tnode => (
|
||||||
<TreeNodeView key={tnode.id} treeNode={tnode} />
|
<TreeNodeView key={tnode.id} treeNode={tnode} />
|
||||||
|
|||||||
@ -5,12 +5,11 @@ import { IconArrowRight } from '../icons/arrow-right';
|
|||||||
import { IconEyeClose } from '../icons/eye-close';
|
import { IconEyeClose } from '../icons/eye-close';
|
||||||
import { IconLock } from '../icons/lock';
|
import { IconLock } from '../icons/lock';
|
||||||
import { IconUnlock } from '../icons/unlock';
|
import { IconUnlock } from '../icons/unlock';
|
||||||
import { intl } from '../locale';
|
import { intl, intlNode } from '../locale';
|
||||||
import TreeNode from '../tree-node';
|
import TreeNode from '../tree-node';
|
||||||
import { IconEye } from '../icons/eye';
|
import { IconEye } from '../icons/eye';
|
||||||
import { IconCond } from '../icons/cond';
|
import { IconCond } from '../icons/cond';
|
||||||
import { IconLoop } from '../icons/loop';
|
import { IconLoop } from '../icons/loop';
|
||||||
import { IconSlot } from '../icons/slot';
|
|
||||||
import { createIcon } from '@ali/lowcode-utils';
|
import { createIcon } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -104,29 +103,28 @@ export default class TreeTitle extends Component<{
|
|||||||
{node.slotFor && (
|
{node.slotFor && (
|
||||||
<a className="tree-node-tag slot">
|
<a className="tree-node-tag slot">
|
||||||
{/* todo: click redirect to prop */}
|
{/* todo: click redirect to prop */}
|
||||||
<IconSlot />
|
<Tip>{intlNode('Slot for {prop}', { prop: node.slotFor.key })}</Tip>
|
||||||
<Tip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</Tip>
|
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{node.hasLoop() && (
|
{node.hasLoop() && (
|
||||||
<a className="tree-node-tag loop">
|
<a className="tree-node-tag loop">
|
||||||
{/* todo: click todo something */}
|
{/* todo: click todo something */}
|
||||||
<IconLoop />
|
<IconLoop />
|
||||||
<Tip>{intl('Loop')}</Tip>
|
<Tip>{intlNode('Loop')}</Tip>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{node.hasCondition() && !node.conditionGroup && (
|
{node.hasCondition() && !node.conditionGroup && (
|
||||||
<a className="tree-node-tag cond">
|
<a className="tree-node-tag cond">
|
||||||
{/* todo: click todo something */}
|
{/* todo: click todo something */}
|
||||||
<IconCond />
|
<IconCond />
|
||||||
<Tip>{intl('Conditional')}</Tip>
|
<Tip>{intlNode('Conditional')}</Tip>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isCNode && isNodeParent && <HideBtn treeNode={treeNode} />}
|
{isCNode && isNodeParent && <HideBtn treeNode={treeNode} />}
|
||||||
{isCNode && isNodeParent && <LockBtn treeNode={treeNode} />}
|
{/*isCNode && isNodeParent && <LockBtn treeNode={treeNode} />*/}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,6 @@
|
|||||||
"outDir": "lib"
|
"outDir": "lib"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/"
|
"./src/",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -228,6 +228,10 @@ export default class BaseEngine extends PureComponent {
|
|||||||
|
|
||||||
let Comp = components[schema.componentName] || Div;
|
let Comp = components[schema.componentName] || Div;
|
||||||
|
|
||||||
|
if (schema.hidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (schema.loop !== undefined) {
|
if (schema.loop !== undefined) {
|
||||||
return this.__createLoopVirtualDom(
|
return this.__createLoopVirtualDom(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"@recore/obx-react": "^1.0.7",
|
"@recore/obx-react": "^1.0.7",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16",
|
"react": "^16",
|
||||||
|
"@ali/vu-css-style": "^1.0.2",
|
||||||
"react-dom": "^16.7.0"
|
"react-dom": "^16.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ class Slot extends Component {
|
|||||||
componentName: 'Slot',
|
componentName: 'Slot',
|
||||||
configure: {
|
configure: {
|
||||||
props: [{
|
props: [{
|
||||||
name: '___title___',
|
name: '___title',
|
||||||
title: {
|
title: {
|
||||||
type: 'i18n',
|
type: 'i18n',
|
||||||
'en-US': 'Slot Title',
|
'en-US': 'Slot Title',
|
||||||
@ -15,7 +15,7 @@ class Slot extends Component {
|
|||||||
setter: 'StringSetter',
|
setter: 'StringSetter',
|
||||||
defaultValue: '插槽容器'
|
defaultValue: '插槽容器'
|
||||||
}, {
|
}, {
|
||||||
name: '___params___',
|
name: '___params',
|
||||||
title: {
|
title: {
|
||||||
type: 'i18n',
|
type: 'i18n',
|
||||||
'en-US': 'Slot Params',
|
'en-US': 'Slot Params',
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import LowCodeRenderer from '@ali/lowcode-react-renderer';
|
import LowCodeRenderer from '@ali/lowcode-react-renderer';
|
||||||
|
import { isObject } from 'lodash';
|
||||||
import { ReactInstance, Fragment, Component, createElement } from 'react';
|
import { ReactInstance, Fragment, Component, createElement } from 'react';
|
||||||
import { observer } from '@recore/obx-react';
|
import { observer } from '@recore/obx-react';
|
||||||
import { SimulatorRenderer } from './renderer';
|
import { SimulatorRenderer } from './renderer';
|
||||||
@ -7,7 +8,7 @@ import './renderer.less';
|
|||||||
|
|
||||||
// patch cloneElement avoid lost keyProps
|
// patch cloneElement avoid lost keyProps
|
||||||
const originCloneElement = window.React.cloneElement;
|
const originCloneElement = window.React.cloneElement;
|
||||||
(window as any).React.cloneElement = (child: any, { _leaf, ...props}: any = {}) => {
|
(window as any).React.cloneElement = (child: any, { _leaf, ...props }: any = {}) => {
|
||||||
if (child.ref && props.ref) {
|
if (child.ref && props.ref) {
|
||||||
const dRef = props.ref;
|
const dRef = props.ref;
|
||||||
const cRef = child.ref;
|
const cRef = child.ref;
|
||||||
@ -18,7 +19,7 @@ const originCloneElement = window.React.cloneElement;
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
cRef.current = x;
|
cRef.current = x;
|
||||||
} catch (e) { }
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dRef) {
|
if (dRef) {
|
||||||
@ -27,13 +28,13 @@ const originCloneElement = window.React.cloneElement;
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dRef.current = x;
|
dRef.current = x;
|
||||||
} catch (e) { }
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
return originCloneElement(child, props);
|
return originCloneElement(child, props);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default class SimulatorRendererView extends Component<{ renderer: SimulatorRenderer }> {
|
export default class SimulatorRendererView extends Component<{ renderer: SimulatorRenderer }> {
|
||||||
render() {
|
render() {
|
||||||
@ -84,10 +85,11 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
|||||||
const { __id, __desingMode, ...viewProps } = props;
|
const { __id, __desingMode, ...viewProps } = props;
|
||||||
viewProps.componentId = __id;
|
viewProps.componentId = __id;
|
||||||
viewProps._leaf = host.document.getNode(__id);
|
viewProps._leaf = host.document.getNode(__id);
|
||||||
|
|
||||||
return createElement(
|
return createElement(
|
||||||
Component,
|
Component,
|
||||||
viewProps,
|
viewProps,
|
||||||
children == null ? null : Array.isArray(children) ? children : [children],
|
children == null ? [] : Array.isArray(children) ? children : [children],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ReactElement, ReactNode } from 'react';
|
import { ReactElement, ReactNode } from 'react';
|
||||||
import { I18nData } from './i18n';
|
import { I18nData, isI18nData } from './i18n';
|
||||||
import { TipContent } from './tip';
|
import { TipContent } from './tip';
|
||||||
import { IconType } from './icon';
|
import { IconType } from './icon';
|
||||||
|
|
||||||
@ -13,3 +13,14 @@ export interface TitleConfig {
|
|||||||
|
|
||||||
export type TitleContent = string | I18nData | ReactElement | TitleConfig;
|
export type TitleContent = string | I18nData | ReactElement | TitleConfig;
|
||||||
|
|
||||||
|
function isPlainObject(value: any): value is object {
|
||||||
|
if (typeof value !== 'object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const proto = Object.getPrototypeOf(value);
|
||||||
|
return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isTitleConfig(obj: any): obj is TitleConfig {
|
||||||
|
return isPlainObject(obj) && !isI18nData(obj);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { isObject } from './is-object';
|
import { isObject } from './is-object';
|
||||||
|
|
||||||
export function isPlainObject(value: any) {
|
export function isPlainObject(value: any): value is object {
|
||||||
if (!isObject(value)) {
|
if (!isObject(value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,6 +100,22 @@ export default class Bundle {
|
|||||||
cp.setView(view);
|
cp.setView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO dirty fix
|
||||||
|
*/
|
||||||
|
addComponentBundle(bundles: any) {
|
||||||
|
/**
|
||||||
|
* Normal Component bundle: [ Prototype, PrototypeView ]
|
||||||
|
* Component without Prototype.js: [ View ]
|
||||||
|
*/
|
||||||
|
if (bundles.length >= 2) {
|
||||||
|
const prototype = bundles[0];
|
||||||
|
const prototypeView = bundles[1];
|
||||||
|
prototype.setView(prototypeView);
|
||||||
|
this.registerPrototype(prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private recursivelyRegisterViews(list: any[], viewName?: string): void {
|
private recursivelyRegisterViews(list: any[], viewName?: string): void {
|
||||||
list.forEach((item: any) => {
|
list.forEach((item: any) => {
|
||||||
if (Array.isArray(item.module)) {
|
if (Array.isArray(item.module)) {
|
||||||
|
|||||||
@ -237,7 +237,7 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collapse || collapsed || fieldCollapsed) {
|
if (collapse || collapsed || fieldCollapsed || extraProps.display === DISPLAY_TYPE.ENTRY) {
|
||||||
extraProps.defaultCollapsed = true;
|
extraProps.defaultCollapsed = true;
|
||||||
}
|
}
|
||||||
function isDisabled(field: Field) {
|
function isDisabled(field: Field) {
|
||||||
@ -287,10 +287,14 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
|
|||||||
if (slotName && initialValue === true) {
|
if (slotName && initialValue === true) {
|
||||||
initialFn = (field: any, value: any) => {
|
initialFn = (field: any, value: any) => {
|
||||||
if (isJSSlot(value)) {
|
if (isJSSlot(value)) {
|
||||||
return value;
|
return {
|
||||||
|
title: slotTitle || title,
|
||||||
|
...value,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'JSSlot',
|
type: 'JSSlot',
|
||||||
|
title: slotTitle || title,
|
||||||
value: initialChildren,
|
value: initialChildren,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -351,10 +355,14 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
|
|||||||
componentName: 'SlotSetter',
|
componentName: 'SlotSetter',
|
||||||
initialValue: (field: any, value: any) => {
|
initialValue: (field: any, value: any) => {
|
||||||
if (isJSSlot(value)) {
|
if (isJSSlot(value)) {
|
||||||
return value;
|
return {
|
||||||
|
title: slotTitle || title,
|
||||||
|
...value,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'JSSlot',
|
type: 'JSSlot',
|
||||||
|
title: slotTitle || title,
|
||||||
value: value == null ? initialChildren : value,
|
value: value == null ? initialChildren : value,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
110
packages/vision-preset/src/components/index.tsx
Normal file
110
packages/vision-preset/src/components/index.tsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onMouseOver = (node: Node) => (_: any, flag = true) => {
|
||||||
|
if (node && typeof node.hover === 'function') {
|
||||||
|
node.hover(flag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onMouseOut = (node: Node) => (_: any, flag = false) => {
|
||||||
|
if (node && typeof node.hover === 'function') {
|
||||||
|
node.hover(flag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
renderNodes = (node: Node) => {
|
||||||
|
const nodes = this.state.parentNodes || [];
|
||||||
|
const children = nodes.map((node, key) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={key}
|
||||||
|
onClick={this.onSelect(node)}
|
||||||
|
onMouseEnter={this.onMouseOver(node)}
|
||||||
|
onMouseLeave={this.onMouseOut(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,16 @@
|
|||||||
import { isJSBlock, isJSSlot } from '@ali/lowcode-types';
|
import { isJSBlock, isJSSlot } from '@ali/lowcode-types';
|
||||||
import { isPlainObject } from '@ali/lowcode-utils';
|
import { isPlainObject } from '@ali/lowcode-utils';
|
||||||
import { globalContext, Editor, registerSetter } from '@ali/lowcode-editor-core';
|
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
import { Designer, TransformStage } from '@ali/lowcode-designer';
|
import { Designer, TransformStage, addBuiltinComponentAction } from '@ali/lowcode-designer';
|
||||||
// import { registerSetters } from '@ali/lowcode-setters';
|
// import { registerSetters } from '@ali/lowcode-setters';
|
||||||
import Outline from '@ali/lowcode-plugin-outline-pane';
|
import Outline from '@ali/lowcode-plugin-outline-pane';
|
||||||
|
import { toCss } from '@ali/vu-css-style';
|
||||||
|
|
||||||
import DesignerPlugin from '@ali/lowcode-plugin-designer';
|
import DesignerPlugin from '@ali/lowcode-plugin-designer';
|
||||||
import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton';
|
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 { i18nReducer } from './i18n-reducer';
|
||||||
|
import { InstanceNodeSelector } from './components';
|
||||||
|
|
||||||
export const editor = new Editor();
|
export const editor = new Editor();
|
||||||
globalContext.register(editor, Editor);
|
globalContext.register(editor, Editor);
|
||||||
@ -66,6 +67,37 @@ function upgradePropsReducer(props: any) {
|
|||||||
}
|
}
|
||||||
designer.addPropsReducer(upgradePropsReducer, TransformStage.Init);
|
designer.addPropsReducer(upgradePropsReducer, TransformStage.Init);
|
||||||
|
|
||||||
|
// 设计器组件样式处理
|
||||||
|
function stylePropsReducer(props: any, node: any) {
|
||||||
|
if (props && typeof props === 'object' && props.__style__) {
|
||||||
|
const doc = designer.currentDocument?.simulator?.contentDocument;
|
||||||
|
if (!doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cssId = '_style_pesudo_' + node.id.replace(/\$/g, '_');
|
||||||
|
const cssClass = '_css_pesudo_' + node.id.replace(/\$/g, '_');
|
||||||
|
const dom = doc.getElementById(cssId);
|
||||||
|
if (dom) {
|
||||||
|
dom.parentNode?.removeChild(dom);
|
||||||
|
}
|
||||||
|
let styleProp = props.__style__;
|
||||||
|
if (typeof styleProp === 'object') {
|
||||||
|
styleProp = toCss(styleProp);
|
||||||
|
}
|
||||||
|
if (typeof styleProp === 'string') {
|
||||||
|
const s = doc.createElement('style');
|
||||||
|
props.className = cssClass;
|
||||||
|
s.setAttribute('type', 'text/css');
|
||||||
|
s.setAttribute('id', cssId);
|
||||||
|
doc.getElementsByTagName('head')[0].appendChild(s);
|
||||||
|
|
||||||
|
s.appendChild(doc.createTextNode(styleProp.replace(/:root/g, '.' + cssClass)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
designer.addPropsReducer(stylePropsReducer, TransformStage.Render);
|
||||||
|
|
||||||
skeleton.add({
|
skeleton.add({
|
||||||
area: 'mainArea',
|
area: 'mainArea',
|
||||||
name: 'designer',
|
name: 'designer',
|
||||||
@ -88,16 +120,6 @@ skeleton.add({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
skeleton.add({
|
|
||||||
area: 'topArea',
|
|
||||||
type: 'Dock',
|
|
||||||
name: 'preview',
|
|
||||||
props: {
|
|
||||||
align: 'right',
|
|
||||||
},
|
|
||||||
content: Preview,
|
|
||||||
});
|
|
||||||
|
|
||||||
// skeleton.add({
|
// skeleton.add({
|
||||||
// name: 'sourceEditor',
|
// name: 'sourceEditor',
|
||||||
// type: 'PanelDock',
|
// type: 'PanelDock',
|
||||||
@ -112,3 +134,11 @@ skeleton.add({
|
|||||||
// },
|
// },
|
||||||
// content: SourceEditor,
|
// content: SourceEditor,
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
// 实例节点选择器,线框高亮
|
||||||
|
addBuiltinComponentAction({
|
||||||
|
name: 'instance-node-selector',
|
||||||
|
content: InstanceNodeSelector,
|
||||||
|
important: true,
|
||||||
|
condition: 'always'
|
||||||
|
});
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { ALI_SCHEMA_VERSION } from './base/const';
|
import { ALI_SCHEMA_VERSION } from './base/const';
|
||||||
|
import { obx } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
interface ILiteralObject {
|
interface ILiteralObject {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Env {
|
export class Env {
|
||||||
|
@obx.val envs: ILiteralObject = {};
|
||||||
public envs: ILiteralObject;
|
|
||||||
|
|
||||||
private emitter: EventEmitter;
|
private emitter: EventEmitter;
|
||||||
private featureMap: ILiteralObject;
|
private featureMap: ILiteralObject;
|
||||||
@ -15,23 +15,22 @@ export class Env {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.emitter = new EventEmitter();
|
this.emitter = new EventEmitter();
|
||||||
this.emitter.setMaxListeners(0);
|
this.emitter.setMaxListeners(0);
|
||||||
this.envs = {};
|
|
||||||
this.featureMap = {};
|
this.featureMap = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(name: string): any {
|
get(name: string): any {
|
||||||
return this.getEnv(name);
|
return this.getEnv(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEnv(name: string): any {
|
getEnv(name: string): any {
|
||||||
return this.envs[name];
|
return this.envs[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public set(name: string, value: any) {
|
set(name: string, value: any) {
|
||||||
return this.setEnv(name, value);
|
return this.setEnv(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setEnv(name: string, value: any) {
|
setEnv(name: string, value: any) {
|
||||||
const orig = this.envs[name];
|
const orig = this.envs[name];
|
||||||
if (JSON.stringify(orig) === JSON.stringify(value)) {
|
if (JSON.stringify(orig) === JSON.stringify(value)) {
|
||||||
return;
|
return;
|
||||||
@ -40,47 +39,47 @@ export class Env {
|
|||||||
this.emitter.emit('envchange', this.envs, name, value);
|
this.emitter.emit('envchange', this.envs, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setEnvMap(envs: ILiteralObject): void {
|
setEnvMap(envs: ILiteralObject): void {
|
||||||
this.envs = Object.assign(this.envs, envs);
|
this.envs = Object.assign(this.envs, envs);
|
||||||
this.emitter.emit('envchange', this.envs);
|
this.emitter.emit('envchange', this.envs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLocale(): string {
|
getLocale(): string {
|
||||||
return this.getEnv('locale') || 'zh_CN';
|
return this.getEnv('locale') || 'zh_CN';
|
||||||
}
|
}
|
||||||
|
|
||||||
public setLocale(locale: string) {
|
setLocale(locale: string) {
|
||||||
this.setEnv('locale', locale);
|
this.setEnv('locale', locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setExpertMode(flag: string) {
|
setExpertMode(flag: string) {
|
||||||
this.setEnv('expertMode', !!flag);
|
this.setEnv('expertMode', !!flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isExpertMode() {
|
isExpertMode() {
|
||||||
return !!this.getEnv('expertMode');
|
return !!this.getEnv('expertMode');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSupportFeatures() {
|
getSupportFeatures() {
|
||||||
return Object.assign({}, this.featureMap);
|
return Object.assign({}, this.featureMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSupportFeatures(features: ILiteralObject) {
|
setSupportFeatures(features: ILiteralObject) {
|
||||||
this.featureMap = Object.assign({}, this.featureMap, features);
|
this.featureMap = Object.assign({}, this.featureMap, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
public supports(name = 'supports') {
|
supports(name = 'supports') {
|
||||||
return !!this.featureMap[name];
|
return !!this.featureMap[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public onEnvChange(func: (envs: ILiteralObject, name: string, value: any) => any) {
|
onEnvChange(func: (envs: ILiteralObject, name: string, value: any) => any) {
|
||||||
this.emitter.on('envchange', func);
|
this.emitter.on('envchange', func);
|
||||||
return () => {
|
return () => {
|
||||||
this.emitter.removeListener('envchange', func);
|
this.emitter.removeListener('envchange', func);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAliSchemaVersion() {
|
getAliSchemaVersion() {
|
||||||
return ALI_SCHEMA_VERSION;
|
return ALI_SCHEMA_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,4 +12,13 @@ export default {
|
|||||||
const nodes = designer.currentSelection?.getNodes();
|
const nodes = designer.currentSelection?.getNodes();
|
||||||
return nodes?.[0];
|
return nodes?.[0];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* TODO dirty fix
|
||||||
|
*/
|
||||||
|
onIntoView(func: (node: any, insertion: any) => any) {
|
||||||
|
// this.emitter.on('intoview', func);
|
||||||
|
return () => {
|
||||||
|
// this.emitter.removeListener('intoview', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const I18nUtil = require('@ali/ve-i18n-util');
|
|
||||||
import Env from './env';
|
import Env from './env';
|
||||||
|
const I18nUtil = require('@ali/ve-i18n-util');
|
||||||
|
|
||||||
interface I18nObject {
|
interface I18nObject {
|
||||||
type?: string;
|
type?: string;
|
||||||
@ -9,7 +9,9 @@ interface I18nObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function i18nReducer(obj?: any): any {
|
export function i18nReducer(obj?: any): any {
|
||||||
if (!obj) { return obj; }
|
if (!obj) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
return obj.map((item) => i18nReducer(item));
|
return obj.map((item) => i18nReducer(item));
|
||||||
}
|
}
|
||||||
@ -18,6 +20,7 @@ export function i18nReducer(obj?: any): any {
|
|||||||
// FIXME! use editor.get
|
// FIXME! use editor.get
|
||||||
let locale = Env.getLocale();
|
let locale = Env.getLocale();
|
||||||
if (obj.key) {
|
if (obj.key) {
|
||||||
|
// FIXME: 此处需要升级I18nUtil,改成响应式
|
||||||
return I18nUtil.get(obj.key, locale);
|
return I18nUtil.get(obj.key, locale);
|
||||||
}
|
}
|
||||||
if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) {
|
if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) {
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import * as utils from '@ali/ve-utils';
|
import * as utils from '@ali/ve-utils';
|
||||||
import Popup from '@ali/ve-popups';
|
import Popup from '@ali/ve-popups';
|
||||||
import Icons from '@ali/ve-icons';
|
import Icons from '@ali/ve-icons';
|
||||||
|
import logger from '@ali/vu-logger';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import I18nUtil from '@ali/ve-i18n-util';
|
import I18nUtil from '@ali/ve-i18n-util';
|
||||||
import { hotkey as Hotkey } from '@ali/lowcode-editor-core';
|
import { hotkey as Hotkey } from '@ali/lowcode-editor-core';
|
||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS } from './base/const';
|
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const';
|
||||||
import Bus from './bus';
|
import Bus from './bus';
|
||||||
import { skeleton } from './editor';
|
import { skeleton } from './editor';
|
||||||
import { Workbench } from '@ali/lowcode-editor-skeleton';
|
import { Workbench } from '@ali/lowcode-editor-skeleton';
|
||||||
@ -21,7 +22,10 @@ import * as Field from './fields';
|
|||||||
import Prop from './prop';
|
import Prop from './prop';
|
||||||
import Env from './env';
|
import Env from './env';
|
||||||
import DragEngine from './drag-engine';
|
import DragEngine from './drag-engine';
|
||||||
|
import Viewport from './viewport';
|
||||||
|
import Project from './project';
|
||||||
import { designer, editor } from './editor';
|
import { designer, editor } from './editor';
|
||||||
|
import Symbols from './symbols';
|
||||||
|
|
||||||
import './vision.less';
|
import './vision.less';
|
||||||
|
|
||||||
@ -41,6 +45,7 @@ function init(container?: Element) {
|
|||||||
createElement(Workbench, {
|
createElement(Workbench, {
|
||||||
skeleton,
|
skeleton,
|
||||||
className: 'engine-main',
|
className: 'engine-main',
|
||||||
|
topAreaItemClassName: 'engine-actionitem',
|
||||||
}),
|
}),
|
||||||
container,
|
container,
|
||||||
);
|
);
|
||||||
@ -101,6 +106,11 @@ const VisualEngine = {
|
|||||||
Bundle,
|
Bundle,
|
||||||
Pages,
|
Pages,
|
||||||
DragEngine,
|
DragEngine,
|
||||||
|
Viewport,
|
||||||
|
Version,
|
||||||
|
Project,
|
||||||
|
logger,
|
||||||
|
Symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(window as any).VisualEngine = VisualEngine;
|
(window as any).VisualEngine = VisualEngine;
|
||||||
@ -144,6 +154,11 @@ export {
|
|||||||
Bundle,
|
Bundle,
|
||||||
Pages,
|
Pages,
|
||||||
DragEngine,
|
DragEngine,
|
||||||
|
Viewport,
|
||||||
|
Version,
|
||||||
|
Project,
|
||||||
|
logger,
|
||||||
|
Symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,17 +6,28 @@ const { project } = designer;
|
|||||||
|
|
||||||
export interface OldPageData {
|
export interface OldPageData {
|
||||||
id: string;
|
id: string;
|
||||||
layout: RootSchema;
|
componentsTree: RootSchema[];
|
||||||
[dataAddon: string]: any;
|
[dataAddon: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pages = Object.assign(project, {
|
const pages = Object.assign(project, {
|
||||||
setPages(pages: OldPageData[]) {
|
setPages(pages: OldPageData[]) {
|
||||||
|
if (!pages || !Array.isArray(pages) || pages.length === 0) {
|
||||||
|
throw new Error('pages schema 不合法');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pages[0].componentsTree[0]) {
|
||||||
|
pages[0].componentsTree[0].componentName = 'Page';
|
||||||
|
// FIXME
|
||||||
|
pages[0].componentsTree[0].lifeCycles = {};
|
||||||
|
pages[0].componentsTree[0].methods = {};
|
||||||
|
}
|
||||||
|
|
||||||
project.load({
|
project.load({
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
componentsMap: [],
|
componentsMap: [],
|
||||||
componentsTree: pages.map(page => page.layout),
|
componentsTree: pages[0].componentsTree,
|
||||||
});
|
}, true);
|
||||||
},
|
},
|
||||||
addPage(data: OldPageData) {
|
addPage(data: OldPageData) {
|
||||||
return project.open(data.layout);
|
return project.open(data.layout);
|
||||||
|
|||||||
@ -69,17 +69,7 @@ function upgradeConfig(config: OldPaneConfig): IWidgetBaseConfig & { area: strin
|
|||||||
newConfig.type = 'PanelDock';
|
newConfig.type = 'PanelDock';
|
||||||
newConfig.area = 'left';
|
newConfig.area = 'left';
|
||||||
newConfig.props.description = description || title;
|
newConfig.props.description = description || title;
|
||||||
const {
|
const { contents, hideTitleBar, tip, width, maxWidth, height, maxHeight, menu, isAction } = config;
|
||||||
contents,
|
|
||||||
hideTitleBar,
|
|
||||||
tip,
|
|
||||||
width,
|
|
||||||
maxWidth,
|
|
||||||
height,
|
|
||||||
maxHeight,
|
|
||||||
menu,
|
|
||||||
isAction
|
|
||||||
} = config;
|
|
||||||
if (menu) {
|
if (menu) {
|
||||||
newConfig.props.title = menu;
|
newConfig.props.title = menu;
|
||||||
}
|
}
|
||||||
@ -95,15 +85,16 @@ function upgradeConfig(config: OldPaneConfig): IWidgetBaseConfig & { area: strin
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (contents && Array.isArray(contents)) {
|
if (contents && Array.isArray(contents)) {
|
||||||
newConfig.content = contents.map(({ title, content, tip }) => {
|
newConfig.content = contents.map(({ title, content, tip }, index) => {
|
||||||
return {
|
return {
|
||||||
type: "Panel",
|
type: 'Panel',
|
||||||
|
name: typeof title === 'string' ? title : `${name}:${index}`,
|
||||||
content,
|
content,
|
||||||
props: {
|
props: {
|
||||||
title,
|
title,
|
||||||
help: tip,
|
help: tip,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +153,11 @@ const dockPane = Object.assign(skeleton.leftArea, {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const name = item.name || item;
|
const name = item.name || item;
|
||||||
skeleton.getPanel(name)?.active();
|
const pane = skeleton.getPanel(name);
|
||||||
|
if (!pane) {
|
||||||
|
console.warn(`Could not find pane with name ${name}`);
|
||||||
|
}
|
||||||
|
pane?.active();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
17
packages/vision-preset/src/project.ts
Normal file
17
packages/vision-preset/src/project.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
class Project {
|
||||||
|
private schema: any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.schema = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
getSchema() {
|
||||||
|
return this.schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSchema(schema: any) {
|
||||||
|
this.schema = schema;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Project();
|
||||||
@ -2,11 +2,12 @@ import { Component } from 'react';
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { fromJS, Iterable, Map as IMMap } from 'immutable';
|
import { fromJS, Iterable, Map as IMMap } from 'immutable';
|
||||||
import logger from '@ali/vu-logger';
|
import logger from '@ali/vu-logger';
|
||||||
import { uniqueId, cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils';
|
import { cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils';
|
||||||
import I18nUtil from '@ali/ve-i18n-util';
|
import I18nUtil from '@ali/ve-i18n-util';
|
||||||
import { getSetter } from '@ali/lowcode-editor-core';
|
import { getSetter } from '@ali/lowcode-editor-core';
|
||||||
import { editor } from './editor';
|
import { editor } from './editor';
|
||||||
import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata';
|
import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata';
|
||||||
|
import { uniqueId } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
type IPropConfig = OldPropConfig;
|
type IPropConfig = OldPropConfig;
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ export default class Prop implements IVariableSettable {
|
|||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.id = uniqueId(null as any, 'prop', 'engine-prop');
|
this.id = uniqueId('prop');
|
||||||
|
|
||||||
if (typeof config.setter === 'string') {
|
if (typeof config.setter === 'string') {
|
||||||
config.setter = getSetter(config.setter)?.component as any;
|
config.setter = getSetter(config.setter)?.component as any;
|
||||||
|
|||||||
17
packages/vision-preset/src/symbols.ts
Normal file
17
packages/vision-preset/src/symbols.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export class SymbolManager {
|
||||||
|
private symbolMap: { [symbolName: string]: symbol } = {};
|
||||||
|
|
||||||
|
public create(name: string): symbol {
|
||||||
|
if (this.symbolMap[name]) {
|
||||||
|
return this.symbolMap[name];
|
||||||
|
}
|
||||||
|
this.symbolMap[name] = Symbol(name);
|
||||||
|
return this.symbolMap[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(name: string) {
|
||||||
|
return this.symbolMap[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new SymbolManager();
|
||||||
278
packages/vision-preset/src/viewport.ts
Normal file
278
packages/vision-preset/src/viewport.ts
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
const domReady = require('domready');
|
||||||
|
import Flags from './flags';
|
||||||
|
|
||||||
|
function enterFullscreen() {
|
||||||
|
const elem = document.documentElement;
|
||||||
|
if (elem.requestFullscreen) {
|
||||||
|
elem.requestFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitFullscreen() {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFullscreen() {
|
||||||
|
return document.fullscreen || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStyleResourceConfig {
|
||||||
|
media?: string;
|
||||||
|
type?: string;
|
||||||
|
content?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StyleResource {
|
||||||
|
config: IStyleResourceConfig;
|
||||||
|
styleElement: HTMLStyleElement;
|
||||||
|
mounted: boolean;
|
||||||
|
inited: boolean;
|
||||||
|
|
||||||
|
constructor(config: IStyleResourceConfig) {
|
||||||
|
this.config = config || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
matchDevice(device: string) {
|
||||||
|
const media = this.config.media;
|
||||||
|
|
||||||
|
if (!media || media === 'ALL' || media === '*') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return media.toUpperCase() === device.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if (this.inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inited = true;
|
||||||
|
|
||||||
|
const { type, content } = this.config;
|
||||||
|
|
||||||
|
let styleElement;
|
||||||
|
if (type === 'URL') {
|
||||||
|
styleElement = document.createElement('link');
|
||||||
|
styleElement.href = content || '';
|
||||||
|
styleElement.rel = 'stylesheet';
|
||||||
|
} else {
|
||||||
|
styleElement = document.createElement('style');
|
||||||
|
styleElement.setAttribute('type', 'text/css');
|
||||||
|
if (styleElement.styleSheet) {
|
||||||
|
styleElement.styleSheet.cssText = content;
|
||||||
|
} else {
|
||||||
|
styleElement.appendChild(document.createTextNode(content || ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.styleElement = styleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply() {
|
||||||
|
if (this.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
document.head.appendChild(this.styleElement);
|
||||||
|
this.mounted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unmount() {
|
||||||
|
if (!this.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.head.removeChild(this.styleElement);
|
||||||
|
this.mounted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Viewport {
|
||||||
|
preview: boolean;
|
||||||
|
focused: boolean;
|
||||||
|
slateFixed: boolean;
|
||||||
|
emitter: EventEmitter;
|
||||||
|
device: string;
|
||||||
|
focusTarget: any;
|
||||||
|
cssResourceSet: StyleResource[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.preview = false;
|
||||||
|
this.emitter = new EventEmitter();
|
||||||
|
document.addEventListener('webkitfullscreenchange', () => {
|
||||||
|
this.emitter.emit('fullscreenchange', this.isFullscreen());
|
||||||
|
});
|
||||||
|
domReady(() => this.applyMediaCSS());
|
||||||
|
}
|
||||||
|
|
||||||
|
setFullscreen(flag: boolean) {
|
||||||
|
const fullscreen = this.isFullscreen();
|
||||||
|
if (fullscreen && !flag) {
|
||||||
|
exitFullscreen();
|
||||||
|
} else if (!fullscreen && flag) {
|
||||||
|
enterFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleFullscreen() {
|
||||||
|
if (this.isFullscreen()) {
|
||||||
|
exitFullscreen();
|
||||||
|
} else {
|
||||||
|
enterFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isFullscreen() {
|
||||||
|
return isFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
setFocus(flag: boolean) {
|
||||||
|
if (this.focused && !flag) {
|
||||||
|
this.focused = false;
|
||||||
|
Flags.remove('view-focused');
|
||||||
|
this.emitter.emit('focuschange', false);
|
||||||
|
} else if (!this.focused && flag) {
|
||||||
|
this.focused = true;
|
||||||
|
Flags.add('view-focused');
|
||||||
|
this.emitter.emit('focuschange', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setFocusTarget(focusTarget: any) {
|
||||||
|
this.focusTarget = focusTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnFocus() {
|
||||||
|
if (this.focusTarget) {
|
||||||
|
this.focusTarget.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isFocus() {
|
||||||
|
return this.focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreview(flag: boolean) {
|
||||||
|
if (this.preview && !flag) {
|
||||||
|
this.preview = false;
|
||||||
|
Flags.setPreviewMode(false);
|
||||||
|
this.emitter.emit('preview', false);
|
||||||
|
this.changeViewport();
|
||||||
|
} else if (!this.preview && flag) {
|
||||||
|
this.preview = true;
|
||||||
|
Flags.setPreviewMode(true);
|
||||||
|
this.emitter.emit('preview', true);
|
||||||
|
this.changeViewport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePreview() {
|
||||||
|
if (this.isPreview()) {
|
||||||
|
this.setPreview(false);
|
||||||
|
} else {
|
||||||
|
this.setPreview(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isPreview() {
|
||||||
|
return this.preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDevice(device = 'pc') {
|
||||||
|
if (this.getDevice() !== device) {
|
||||||
|
this.device = device;
|
||||||
|
Flags.setSimulator(device);
|
||||||
|
this.applyMediaCSS();
|
||||||
|
this.emitter.emit('devicechange', device);
|
||||||
|
this.changeViewport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDevice() {
|
||||||
|
return this.device || 'pc';
|
||||||
|
}
|
||||||
|
|
||||||
|
changeViewport() {
|
||||||
|
this.emitter.emit('viewportchange', this.getViewport());
|
||||||
|
}
|
||||||
|
|
||||||
|
getViewport() {
|
||||||
|
return `${this.isPreview() ? 'preview' : 'design'}-${this.getDevice()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyMediaCSS() {
|
||||||
|
if (!document.head || !this.cssResourceSet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const device = this.getDevice();
|
||||||
|
this.cssResourceSet.forEach((item) => {
|
||||||
|
if (item.matchDevice(device)) {
|
||||||
|
item.apply();
|
||||||
|
} else {
|
||||||
|
item.unmount();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setGlobalCSS(resourceSet: IStyleResourceConfig[]) {
|
||||||
|
if (this.cssResourceSet) {
|
||||||
|
this.cssResourceSet.forEach((item) => {
|
||||||
|
item.unmount();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.cssResourceSet = resourceSet.map((item: IStyleResourceConfig) => new StyleResource(item)).reverse();
|
||||||
|
this.applyMediaCSS();
|
||||||
|
}
|
||||||
|
|
||||||
|
setWithShell(shell: string) {
|
||||||
|
Flags.setWithShell(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFullscreenChange(func: () => any) {
|
||||||
|
this.emitter.on('fullscreenchange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('fullscreenchange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onPreview(func: () => any) {
|
||||||
|
this.emitter.on('preview', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('preview', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeviceChange(func: () => any) {
|
||||||
|
this.emitter.on('devicechange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('devicechange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onSlateFixedChange(func: (flag: boolean) => any) {
|
||||||
|
this.emitter.on('slatefixed', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('slatefixed', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onViewportChange(func: () => any) {
|
||||||
|
this.emitter.on('viewportchange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('viewportchange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocusChange(func: (flag: boolean) => any) {
|
||||||
|
this.emitter.on('focuschange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('focuschange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Viewport();
|
||||||
@ -92,7 +92,8 @@ html.engine-blur #engine {
|
|||||||
.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,
|
.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,
|
||||||
.next-number-picker,.next-radio-group,.next-range,.next-range-picker,
|
.next-number-picker,.next-radio-group,.next-range,.next-range-picker,
|
||||||
.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,
|
.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,
|
||||||
.next-year-picker {
|
.next-year-picker,
|
||||||
|
.next-breadcrumb-item,.next-calendar-header,.next-calendar-table {
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,3 +101,9 @@ html.engine-blur #engine {
|
|||||||
.lc-left-float-pane {
|
.lc-left-float-pane {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.engine-preview-mode {
|
||||||
|
.lc-left-area, .lc-right-area {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user