diff --git a/packages/designer/package.json b/packages/designer/package.json index 1b1f34703..e271381bf 100644 --- a/packages/designer/package.json +++ b/packages/designer/package.json @@ -15,7 +15,9 @@ }, "license": "MIT", "dependencies": { - "@ali/lowcode-globals": "^0.9.3", + "@ali/lowcode-editor-core": "^0.8.0", + "@ali/lowcode-utils": "^0.8.0", + "@ali/lowcode-types": "^0.8.0", "classnames": "^2.2.6", "react": "^16", "react-dom": "^16.7.0" diff --git a/packages/designer/src/component-meta.ts b/packages/designer/src/component-meta.ts index 5509d13a5..1954f6091 100644 --- a/packages/designer/src/component-meta.ts +++ b/packages/designer/src/component-meta.ts @@ -11,7 +11,7 @@ import { import { computed } from '@ali/lowcode-editor-core'; import { Node, ParentalNode } from './document'; import { Designer } from './designer'; -import { intl } from './locale'; +import { intlNode } from './locale'; import { IconContainer } from './icons/container'; import { IconPage } from './icons/page'; import { IconComponent } from './icons/component'; @@ -235,6 +235,38 @@ function preprocessMetadata(metadata: ComponentMetadata): TransformedComponentMe }; } + +export interface MetadataTransducer { + (prev: TransformedComponentMetadata): TransformedComponentMetadata; + /** + * 0 - 9 system + * 10 - 99 builtin-plugin + * 100 - app & plugin + */ + level?: number; + /** + * use to replace TODO + */ + id?: string; +} +const metadataTransducers: MetadataTransducer[] = []; + +export function registerMetadataTransducer(transducer: MetadataTransducer, level: number = 100, id?: string) { + transducer.level = level; + transducer.id = id; + const i = metadataTransducers.findIndex((item) => item.level != null && item.level > level); + if (i < 0) { + metadataTransducers.push(transducer); + } else { + metadataTransducers.splice(i, 0, transducer); + } +} + +export function getRegisteredMetadataTransducers(): MetadataTransducer[] { + return metadataTransducers; +} + + registerMetadataTransducer((metadata) => { const { configure, componentName } = metadata; const { component = {} } = configure; @@ -280,7 +312,7 @@ const builtinComponentActions: ComponentAction[] = [ name: 'remove', content: { icon: IconRemove, - title: intl('remove'), + title: intlNode('remove'), action(node: Node) { node.remove(); }, @@ -291,7 +323,7 @@ const builtinComponentActions: ComponentAction[] = [ name: 'copy', content: { icon: IconClone, - title: intl('copy'), + title: intlNode('copy'), action(node: Node) { // node.remove(); }, @@ -309,33 +341,3 @@ export function removeBuiltinComponentAction(name: string) { export function addBuiltinComponentAction(action: ComponentAction) { builtinComponentActions.push(action); } - -export interface MetadataTransducer { - (prev: TransformedComponentMetadata): TransformedComponentMetadata; - /** - * 0 - 9 system - * 10 - 99 builtin-plugin - * 100 - app & plugin - */ - level?: number; - /** - * use to replace TODO - */ - id?: string; -} -const metadataTransducers: MetadataTransducer[] = []; - -export function registerMetadataTransducer(transducer: MetadataTransducer, level: number = 100, id?: string) { - transducer.level = level; - transducer.id = id; - const i = metadataTransducers.findIndex((item) => item.level != null && item.level > level); - if (i < 0) { - metadataTransducers.push(transducer); - } else { - metadataTransducers.splice(i, 0, transducer); - } -} - -export function getRegisteredMetadataTransducers(): MetadataTransducer[] { - return metadataTransducers; -} diff --git a/packages/designer/src/locale/index.ts b/packages/designer/src/locale/index.ts index dfd17521f..26507f0ef 100644 --- a/packages/designer/src/locale/index.ts +++ b/packages/designer/src/locale/index.ts @@ -2,9 +2,9 @@ import { createIntl } from '@ali/lowcode-editor-core'; import en_US from './en-US.json'; import zh_CN from './zh-CN.json'; -const { intl, getLocale, setLocale } = createIntl({ +const { intl, intlNode, getLocale, setLocale } = createIntl({ 'en-US': en_US, 'zh-CN': zh_CN, }); -export { intl, getLocale, setLocale }; +export { intl, intlNode, getLocale, setLocale }; diff --git a/packages/editor-core/cloud-build.json b/packages/editor-core/cloud-build.json index 2cfca99dd..15de75b91 100644 --- a/packages/editor-core/cloud-build.json +++ b/packages/editor-core/cloud-build.json @@ -3,8 +3,8 @@ [ "build-plugin-component", { - "filename": "globals", - "library": "LCEGlobals", + "filename": "core", + "library": "LCECore", "libraryTarget": "umd" } ], diff --git a/packages/editor-core/package.json b/packages/editor-core/package.json index c8fcce18c..0e9ac0349 100644 --- a/packages/editor-core/package.json +++ b/packages/editor-core/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-globals", - "version": "0.9.3", + "version": "0.8.6", "description": "Globals api for Ali lowCode engine", "license": "MIT", "main": "lib/index.js", @@ -27,13 +27,14 @@ }, "dependencies": { "@alifd/next": "^1.19.16", + "@ali/lowcode-types": "^0.8.0", + "@ali/lowcode-utils": "^0.8.0", "@recore/obx": "^1.0.8", "@recore/obx-react": "^1.0.7", "classnames": "^2.2.6", "power-di": "^2.2.4", "debug": "^4.1.1", "intl-messageformat": "^8.3.1", - "lodash": "^4.17.15", "store": "^2.0.12", "react": "^16", "react-dom": "^16.7.0" @@ -44,8 +45,6 @@ "@types/node": "^13.7.1", "@types/react": "^16", "@types/react-dom": "^16", - - "@types/lodash": "^4.14.149", "@types/store": "^2.0.2", "build-plugin-component": "^0.2.11", "build-plugin-fusion": "^0.1.0", diff --git a/packages/editor-core/src/di/index.ts b/packages/editor-core/src/di/index.ts index d60f74e53..75a4e84f1 100644 --- a/packages/editor-core/src/di/index.ts +++ b/packages/editor-core/src/di/index.ts @@ -1,3 +1,3 @@ export * from './setter'; export * from './ioc-context'; -export * from './tip'; +export * from '../widgets/tip/tip'; diff --git a/packages/editor-core/src/editor.ts b/packages/editor-core/src/editor.ts index aa7fe1083..8fd69d46c 100644 --- a/packages/editor-core/src/editor.ts +++ b/packages/editor-core/src/editor.ts @@ -20,6 +20,8 @@ export type GetReturnType = T extends undefined const NOT_FOUND = Symbol.for('not_found'); +import * as utils from './utils'; + export class Editor extends EventEmitter implements IEditor { /** * Ioc Container @@ -32,6 +34,8 @@ export class Editor extends EventEmitter implements IEditor { return globalLocale.getLocale(); } + readonly utils = utils; + constructor(readonly config: EditorConfig = {}, readonly components: PluginClassSet = {}) { super(); } diff --git a/packages/editor-core/src/widgets/tip/tip-item.tsx b/packages/editor-core/src/widgets/tip/tip-item.tsx index 558d13768..20ec87bea 100644 --- a/packages/editor-core/src/widgets/tip/tip-item.tsx +++ b/packages/editor-core/src/widgets/tip/tip-item.tsx @@ -1,7 +1,7 @@ import { Component } from 'react'; import classNames from 'classnames'; -import { intl } from '@ali/lowcode-editor-core'; import { TipConfig } from '@ali/lowcode-types'; +import { intl } from '../../intl'; import { resolvePosition } from './utils'; import { tipHandler } from './tip-handler'; diff --git a/packages/editor-skeleton/package.json b/packages/editor-skeleton/package.json index 3b66a00b7..7bc4a6f41 100644 --- a/packages/editor-skeleton/package.json +++ b/packages/editor-skeleton/package.json @@ -20,13 +20,14 @@ ], "author": "xiayang.xy", "dependencies": { - "@ali/lowcode-editor-core": "^0.8.6", "@alifd/next": "^1.x", - "prop-types": "^15.5.8", + "@ali/lowcode-editor-core": "^0.8.6", + "@ali/lowcode-designer": "^0.9.2", + "@ali/lowcode-types": "^0.8.0", + "@ali/lowcode-utils": "^0.8.0", + "classnames": "^2.2.6", "react": "^16.8.1", - "react-dom": "^16.8.1", - "react-router-dom": "^5.1.2", - "store": "^2.0.12" + "react-dom": "^16.8.1" }, "devDependencies": { "@alib/build-scripts": "^0.1.3", diff --git a/packages/editor-skeleton/src/components/field/index.less b/packages/editor-skeleton/src/components/field/index.less index 5fecb74d9..2a47edf15 100644 --- a/packages/editor-skeleton/src/components/field/index.less +++ b/packages/editor-skeleton/src/components/field/index.less @@ -1,5 +1,3 @@ -@import '../variables.less'; - @x-gap: 10px; @y-gap: 8px; @@ -57,7 +55,7 @@ &.lc-block-field, &.lc-accordion-field { display: block; &:not(:first-child) { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); + border-top: 1px solid var(--color-line-normal); } > .lc-field-head { padding-left: @x-gap; @@ -66,8 +64,8 @@ align-items: center; font-weight: 500; background: var(--color-block-background-shallow, rgba(31,56,88,.06)); - border-bottom: 1px solid var(--color-line-normal, @dark-alpha-2); - color: var(--color-title, @white-alpha-2); + border-bottom: 1px solid var(--color-line-normal); + color: var(--color-title); user-select: none; } @@ -76,7 +74,7 @@ } + .lc-inline-field { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); + border-top: 1px solid var(--color-line-normal); } } diff --git a/packages/editor-skeleton/src/components/settings/index.ts b/packages/editor-skeleton/src/components/settings/index.ts index be0ed6e8d..4738b3e54 100644 --- a/packages/editor-skeleton/src/components/settings/index.ts +++ b/packages/editor-skeleton/src/components/settings/index.ts @@ -1,7 +1,3 @@ -export * from './settings-pane'; -import './transducers/register'; -import './register'; import './style.less'; -import SettingsMainView from './settings-primary-view'; - -export default SettingsMainView; +export * from './settings-primary-pane'; +export * from './settings-pane'; diff --git a/packages/editor-skeleton/src/components/settings/package.json b/packages/editor-skeleton/src/components/settings/package.json deleted file mode 100644 index 2a0fab24e..000000000 --- a/packages/editor-skeleton/src/components/settings/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "@ali/lowcode-plugin-settings-pane", - "version": "0.8.10", - "description": "Settings pane for Ali lowCode engine", - "files": [ - "es", - "lib" - ], - "main": "lib/index.js", - "module": "es/index.js", - "scripts": { - "build": "build-scripts build --skip-demo", - "test": "ava", - "test:snapshot": "ava --update-snapshots" - }, - "dependencies": { - "@ali/lowcode-designer": "^0.9.2", - "@ali/lowcode-editor-core": "^0.8.5", - "@ali/lowcode-globals": "^0.9.2", - "@ali/lowcode-plugin-outline-pane": "^0.8.8", - "@ali/ve-stage-box": "^4.0.0", - "@alifd/next": "^1.19.16", - "classnames": "^2.2.6", - "react": "^16" - }, - "devDependencies": { - "@alib/build-scripts": "^0.1.18", - "@types/classnames": "^2.2.7", - "@types/node": "^13.7.1", - "@types/react": "^16", - "build-plugin-component": "^0.2.10", - "build-plugin-fusion": "^0.1.1", - "build-plugin-moment-locales": "^0.1.0" - }, - "ava": { - "compileEnhancements": false, - "snapshotDir": "test/fixtures/__snapshots__", - "extensions": [ - "ts" - ], - "require": [ - "ts-node/register" - ] - }, - "license": "MIT", - "publishConfig": { - "registry": "https://registry.npm.alibaba-inc.com" - } -} diff --git a/packages/editor-skeleton/src/components/settings/settings-primary-view.tsx b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx similarity index 97% rename from packages/editor-skeleton/src/components/settings/settings-primary-view.tsx rename to packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx index 7a4c49815..77c9eda0f 100644 --- a/packages/editor-skeleton/src/components/settings/settings-primary-view.tsx +++ b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx @@ -7,7 +7,7 @@ import { SettingsPane } from './settings-pane'; import { createIcon } from '@ali/lowcode-utils'; @observer -export default class SettingsMainView extends Component<{ editor: Editor }> { +export class SettingsPrimaryPane extends Component<{ editor: Editor }> { private main = new SettingsMain(this.props.editor); shouldComponentUpdate() { diff --git a/packages/editor-skeleton/src/components/settings/transducers/register.ts b/packages/editor-skeleton/src/components/settings/transducers/register.ts deleted file mode 100644 index 0ac451c52..000000000 --- a/packages/editor-skeleton/src/components/settings/transducers/register.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerMetadataTransducer } from '@ali/lowcode-designer'; -import parseProps from './parse-props'; -import addonCombine from './addon-combine'; - -// parseProps -registerMetadataTransducer(parseProps, 10, 'parse-props'); - -// addon/platform custom -registerMetadataTransducer(addonCombine, 11, 'combine-props'); diff --git a/packages/editor-skeleton/src/dock.ts b/packages/editor-skeleton/src/dock.ts deleted file mode 100644 index affa84d98..000000000 --- a/packages/editor-skeleton/src/dock.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { obx } from '@ali/lowcode-editor-core'; -import { uniqueId, createContent } from '@ali/lowcode-utils'; -import { DockConfig } from "./types"; -import { Skeleton } from './skeleton'; -import { DockView, WidgetView } from './components/widget-views'; -import { IWidget } from './widget/widget'; - -/** - * 带图标(主要)/标题(次要)的扩展 - */ -export default class Dock implements IWidget { - readonly isWidget = true; - readonly id = uniqueId('dock'); - readonly name: string; - readonly align?: string; - - @obx.ref private _visible: boolean = true; - get visible(): boolean { - return this._visible; - } - - get content(): ReactNode { - return createElement(WidgetView, { - widget: this, - key: this.id, - }); - } - - private inited: boolean = false; - private _body: ReactNode; - get body() { - if (this.inited) { - return this._body; - } - - const { props, content, contentProps } = this.config; - - if (content) { - this._body = createContent(content, { - ...contentProps, - config: this.config, - editor: this.skeleton.editor, - }); - } else { - this._body = createElement(DockView, props); - } - return this._body; - } - - constructor(readonly skeleton: Skeleton, readonly config: DockConfig) { - const { props = {}, name } = config; - this.name = name; - this.align = props.align; - } - - setVisible(flag: boolean) { - if (flag === this._visible) { - return; - } - if (flag) { - this._visible = true; - } else if (this.inited) { - this._visible = false; - } - } - - getContent() { - return this.content; - } - - getName() { - return this.name; - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } - - toggle() { - this.setVisible(!this._visible); - } -} diff --git a/packages/editor-skeleton/src/index.ts b/packages/editor-skeleton/src/index.ts index 923bd59cb..2a8dcdbf8 100644 --- a/packages/editor-skeleton/src/index.ts +++ b/packages/editor-skeleton/src/index.ts @@ -1 +1,7 @@ export { Workbench } from './layouts/workbench'; +export * from './skeleton'; +export * from './types'; +export * from './components/settings'; +export * from './components/field'; + +import './register-defaults'; diff --git a/packages/editor-skeleton/src/panel.ts b/packages/editor-skeleton/src/panel.ts deleted file mode 100644 index fd8a5de46..000000000 --- a/packages/editor-skeleton/src/panel.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { createElement, ReactNode } from 'react'; -import { TitleContent } from '@ali/lowcode-types'; -import { uniqueId, createContent } from '@ali/lowcode-utils'; -import { obx } from '@ali/lowcode-editor-core'; -import WidgetContainer from './widget/widget-container'; -import { PanelConfig, HelpTipConfig } from './types'; -import { TitledPanelView, TabsPanelView, PanelView } from './components/widget-views'; -import { Skeleton } from './skeleton'; -import { composeTitle } from './widget/utils'; -import { IWidget } from './widget/widget'; - -export default class Panel implements IWidget { - readonly isWidget = true; - readonly name: string; - readonly id: string; - @obx.ref inited: boolean = false; - @obx.ref private _actived: boolean = false; - get actived(): boolean { - return this._actived; - } - - get visible(): boolean { - if (this.parent?.visible) { - return this._actived; - } - return false; - } - - readonly isPanel = true; - - private _body?: ReactNode; - get body() { - this.initBody(); - return this._body; - } - - get content(): ReactNode { - if (this.plain) { - return createElement(PanelView, { - panel: this, - key: this.id, - }); - } - return createElement(TitledPanelView, { panel: this, key: this.id }); - } - - readonly title: TitleContent; - readonly help?: HelpTipConfig; - private plain: boolean = false; - - private container?: WidgetContainer; - private parent?: WidgetContainer; - - constructor(readonly skeleton: Skeleton, readonly config: PanelConfig) { - const { name, content, props = {} } = config; - const { hideTitleBar, title, icon, description, help, shortcut } = props; - this.name = name; - this.id = uniqueId(`pane:${name}$`); - this.title = composeTitle(title || name, icon, description); - this.plain = hideTitleBar || !title; - this.help = help; - if (Array.isArray(content)) { - this.container = this.skeleton.createContainer( - name, - (item) => { - if (isPanel(item)) { - return item; - } - return this.skeleton.createPanel(item); - }, - true, - () => this.visible, - true, - ); - content.forEach((item) => this.add(item)); - } - // todo: process shortcut - } - - private initBody() { - if (this.inited) { - return; - } - this.inited = true; - if (this.container) { - this._body = createElement(TabsPanelView, { - container: this.container, - }); - } else { - const { content, contentProps } = this.config; - this._body = createContent(content, { - ...contentProps, - editor: this.skeleton.editor, - config: this.config, - panel: this, - }); - } - } - - setParent(parent: WidgetContainer) { - if (parent === this.parent) { - return; - } - if (this.parent) { - this.parent.remove(this); - } - this.parent = parent; - } - - add(item: Panel | PanelConfig) { - return this.container?.add(item); - } - - getPane(name: string): Panel | null { - return this.container?.get(name) || null; - } - - remove(item: Panel | string) { - return this.container?.remove(item); - } - - active(item?: Panel | string | null) { - this.container?.active(item); - } - - getName() { - return this.name; - } - - getContent() { - return this.content; - } - - setActive(flag: boolean) { - if (flag === this._actived) { - // TODO: 如果移动到另外一个 container,会有问题 - return; - } - if (flag) { - if (!this.inited) { - this.initBody(); - } - this._actived = true; - this.parent?.active(this); - } else if (this.inited) { - this._actived = false; - this.parent?.unactive(this); - } - } - - toggle() { - this.setActive(!this._actived); - } - - hide() { - this.setActive(false); - } - - show() { - this.setActive(true); - } -} - -export function isPanel(obj: any): obj is Panel { - return obj && obj.isPanel; -} diff --git a/packages/editor-skeleton/src/components/settings/register.ts b/packages/editor-skeleton/src/register-defaults.ts similarity index 58% rename from packages/editor-skeleton/src/components/settings/register.ts rename to packages/editor-skeleton/src/register-defaults.ts index 1ff61b101..63bf0dd90 100644 --- a/packages/editor-skeleton/src/components/settings/register.ts +++ b/packages/editor-skeleton/src/register-defaults.ts @@ -1,8 +1,11 @@ import { registerSetter } from '@ali/lowcode-editor-core'; -import ArraySetter from '../array-setter'; -import ObjectSetter from '../object-setter'; -import MixedSetter from '../mixed-setter'; +import { registerMetadataTransducer } from '@ali/lowcode-designer'; +import ArraySetter from './components/array-setter'; +import ObjectSetter from './components/object-setter'; +import MixedSetter from './components/mixed-setter'; import { isPlainObject } from '@ali/lowcode-utils'; +import parseProps from './transducers/parse-props'; +import addonCombine from './transducers/addon-combine'; registerSetter('ArraySetter', { component: ArraySetter, @@ -28,3 +31,9 @@ registerSetter('ObjectSetter', { recommend: true, }); registerSetter('MixedSetter', MixedSetter); + +// parseProps +registerMetadataTransducer(parseProps, 10, 'parse-props'); + +// addon/platform custom +registerMetadataTransducer(addonCombine, 11, 'combine-props'); diff --git a/packages/editor-skeleton/src/components/settings/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts similarity index 100% rename from packages/editor-skeleton/src/components/settings/transducers/addon-combine.ts rename to packages/editor-skeleton/src/transducers/addon-combine.ts diff --git a/packages/editor-skeleton/src/components/settings/transducers/parse-props.ts b/packages/editor-skeleton/src/transducers/parse-props.ts similarity index 100% rename from packages/editor-skeleton/src/components/settings/transducers/parse-props.ts rename to packages/editor-skeleton/src/transducers/parse-props.ts diff --git a/packages/editor-skeleton/src/widget/utils.ts b/packages/editor-skeleton/src/widget/utils.ts index 301426a87..b635fbbe0 100644 --- a/packages/editor-skeleton/src/widget/utils.ts +++ b/packages/editor-skeleton/src/widget/utils.ts @@ -1,4 +1,4 @@ -import { IconType, TitleContent, isI18nData, TipContent } from '@ali/lowcode-globals'; +import { IconType, TitleContent, isI18nData, TipContent } from '@ali/lowcode-types'; import { isValidElement } from 'react'; export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean) { diff --git a/packages/editor-skeleton/src/widget/widget-container.ts b/packages/editor-skeleton/src/widget/widget-container.ts index b34827ae7..268f5fcfb 100644 --- a/packages/editor-skeleton/src/widget/widget-container.ts +++ b/packages/editor-skeleton/src/widget/widget-container.ts @@ -1,5 +1,6 @@ -import { obx, hasOwnProperty, computed } from '@ali/lowcode-globals'; +import { obx, computed } from '@ali/lowcode-editor-core'; import { isPanel } from './panel'; +import { hasOwnProperty } from '@ali/lowcode-utils'; export interface WidgetItem { name: string; } diff --git a/packages/editor/src/editor.ts b/packages/editor/src/editor.ts new file mode 100644 index 000000000..1cc9a8040 --- /dev/null +++ b/packages/editor/src/editor.ts @@ -0,0 +1,30 @@ +import { globalContext, Editor } from '@ali/lowcode-editor-core'; +import { Designer } from '@ali/lowcode-designer'; +import DesignerPlugin from '@ali/lowcode-plugin-designer'; +import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; + +export const editor = new Editor(); +globalContext.register(editor, Editor); + +export const skeleton = new Skeleton(editor); +editor.set(Skeleton, skeleton); + +export const designer = new Designer({ editor: editor }); +editor.set(Designer, designer); + +skeleton.add({ + area: 'mainArea', + name: 'designer', + type: 'Widget', + content: DesignerPlugin, +}); +skeleton.add({ + area: 'rightArea', + name: 'settingsPane', + type: 'Panel', + content: SettingsPrimaryPane, +}); + +export * from '@ali/lowcode-types'; +export * from '@ali/lowcode-designer'; +export * from '@ali/lowcode-editor-skeleton' diff --git a/packages/plugin-components-pane/package.json b/packages/plugin-components-pane/package.json index b51bed16c..a00043109 100644 --- a/packages/plugin-components-pane/package.json +++ b/packages/plugin-components-pane/package.json @@ -25,6 +25,7 @@ "@ali/iceluna-sdk": "^1.0.6-beta.6", "@ali/lowcode-designer": "^0.9.3", "@ali/lowcode-editor-core": "^0.8.6", + "@ali/lowcode-types": "^0.8.0", "@alifd/next": "^1.19.19", "react": "^16.8.1" }, diff --git a/packages/plugin-components-pane/src/index.tsx b/packages/plugin-components-pane/src/index.tsx index 3dc8ccd5a..7c5540f79 100644 --- a/packages/plugin-components-pane/src/index.tsx +++ b/packages/plugin-components-pane/src/index.tsx @@ -19,13 +19,10 @@ export interface IState { componentList: object[]; } -export default class ComponentListPlugin extends PureComponent< - PluginProps, - IState -> { +export default class ComponentListPlugin extends PureComponent { static displayName = 'LowcodeComponentListPlugin'; - constructor(props) { + constructor(props: any) { super(props); this.state = { loading: false, @@ -50,15 +47,15 @@ export default class ComponentListPlugin extends PureComponent< } } - transformMaterial = (componentList): any => { - return componentList.map(category => { + transformMaterial = (componentList: any): any => { + return componentList.map((category: any) => { return { name: category.title, - items: category.children.map(comp => { + items: category.children.map((comp: any) => { return { ...comp, name: comp.componentName, - snippets: comp.snippets.map(snippet => { + snippets: comp.snippets.map((snippet: any) => { return { name: snippet.title, screenshot: snippet.screenshot, @@ -76,7 +73,7 @@ export default class ComponentListPlugin extends PureComponent< const assets = editor.get('assets') || {}; const list: string[] = []; const libs: LibrayInfo[] = []; - Object.values(assets.packages).forEach((item): void => { + Object.values(assets.packages).forEach((item: any): void => { list.push(item.library); libs.push({ label: item.title, @@ -100,7 +97,7 @@ export default class ComponentListPlugin extends PureComponent< }); editor.set('dndHelper', { - handleResourceDragStart: function(ev, tagName, schema) { + handleResourceDragStart: function(ev: any, tagName: any, schema: any) { const designer = editor.get(Designer); if (designer) { designer.dragon.boost( @@ -125,18 +122,16 @@ export default class ComponentListPlugin extends PureComponent< const { searchKey, currentLib, componentList } = this.state; const libs = currentLib.split(','); return (componentList || []) - .map(cate => { + .map((cate: any) => { return { ...cate, - items: (cate.items || []).filter(item => { - let libFlag = libs.some(lib => lib == item.library); + items: (cate.items || []).filter((item: any) => { + let libFlag = libs.some((lib) => lib == item.library); let keyFlag = true; if (searchKey) { keyFlag = - `${item.name || ''} ${item.title || ''}` - .toLowerCase() - .indexOf(searchKey.trim().toLowerCase()) >= 0; + `${item.name || ''} ${item.title || ''}`.toLowerCase().indexOf(searchKey.trim().toLowerCase()) >= 0; } else { keyFlag = item.is_show === undefined || !!(item.is_show == 1); } @@ -144,7 +139,7 @@ export default class ComponentListPlugin extends PureComponent< }), }; }) - .filter(cate => { + .filter((cate) => { return cate.items && cate.items.length > 0; }); }; @@ -159,10 +154,10 @@ export default class ComponentListPlugin extends PureComponent< diff --git a/packages/plugin-components-pane/src/module.d.ts b/packages/plugin-components-pane/src/module.d.ts new file mode 100644 index 000000000..df9f49df3 --- /dev/null +++ b/packages/plugin-components-pane/src/module.d.ts @@ -0,0 +1 @@ +declare module "@ali/iceluna-comp-material-show"; diff --git a/packages/plugin-event-bind-dialog/package.json b/packages/plugin-event-bind-dialog/package.json index cc9d51e9b..9a37ec2f7 100644 --- a/packages/plugin-event-bind-dialog/package.json +++ b/packages/plugin-event-bind-dialog/package.json @@ -19,7 +19,8 @@ ], "author": "zude.hzd", "dependencies": { - "@ali/lowcode-editor-core": "^0.8.6", + "@ali/lowcode-types": "^0.8.0", + "@ali/lowcode-editor-core": "^0.8.0", "@alifd/next": "^1.19.16", "react": "^16.8.1", "react-dom": "^16.8.1" diff --git a/packages/plugin-event-bind-dialog/src/index.tsx b/packages/plugin-event-bind-dialog/src/index.tsx index 4aedba085..819f2dd4b 100644 --- a/packages/plugin-event-bind-dialog/src/index.tsx +++ b/packages/plugin-event-bind-dialog/src/index.tsx @@ -1,11 +1,9 @@ import { Component, isValidElement, ReactElement, ReactNode } from 'react'; import { Dialog, Search, Input } from '@alifd/next'; -import { Editor } from '@ali/lowcode-editor-core'; +import { PluginProps } from '@ali/lowcode-types'; import './index.scss'; -export default class EventBindDialog extends Component<{ - editor:Editor, -}> { +export default class EventBindDialog extends Component { private eventList: any[] = [ { name: 'getData', @@ -24,29 +22,29 @@ export default class EventBindDialog extends Component<{ }, ]; - state = { - visiable:false, + state: any = { + visiable: false, selectedEventName: '', eventName: '', }; - openDialog = (bindEventName:String) => { + openDialog = (bindEventName: String) => { this.setState({ - visiable:true, - eventName:bindEventName - }) - } + visiable: true, + eventName: bindEventName, + }); + }; closeDialog = () => { this.setState({ - visiable:false - }) - } + visiable: false, + }); + }; - componentDidMount (){ - const {editor,config} = this.props; - editor.on(`${config.pluginKey}.openDialog`,(bindEventName:String)=>{ - this.openDialog(bindEventName) + componentDidMount() { + const { editor, config } = this.props; + editor.on(`${config.pluginKey}.openDialog`, (bindEventName: String) => { + this.openDialog(bindEventName); }); } @@ -89,22 +87,28 @@ export default class EventBindDialog extends Component<{ onSearchEvent = (searchEventName: String) => {}; onOk = () => { - const {editor} = this.props; - editor.emit('event-setter.bindEvent',this.state.eventName); + const { editor } = this.props; + editor.emit('event-setter.bindEvent', this.state.eventName); // 选中的是新建事件 - if (this.state.selectedEventName == ''){ - editor.emit('sourceEditor.addFunction',{ - functionName:this.state.eventName - }) + if (this.state.selectedEventName == '') { + editor.emit('sourceEditor.addFunction', { + functionName: this.state.eventName, + }); } this.closeDialog(); }; render() { - const { selectedEventName, eventName,visiable} = this.state; + const { selectedEventName, eventName, visiable } = this.state; return ( - +
事件选择
diff --git a/packages/plugin-outline-pane/package.json b/packages/plugin-outline-pane/package.json index 5e3e4821b..315048104 100644 --- a/packages/plugin-outline-pane/package.json +++ b/packages/plugin-outline-pane/package.json @@ -16,7 +16,8 @@ "dependencies": { "@ali/lowcode-designer": "^0.9.3", "@ali/lowcode-editor-core": "^0.8.6", - "@ali/lowcode-globals": "^0.9.3", + "@ali/lowcode-utils": "^0.8.0", + "@ali/lowcode-types": "^0.8.0", "@alifd/next": "^1.19.16", "classnames": "^2.2.6", "react": "^16", diff --git a/packages/plugin-outline-pane/src/views/backup-pane.tsx b/packages/plugin-outline-pane/src/views/backup-pane.tsx new file mode 100644 index 000000000..f74eceaff --- /dev/null +++ b/packages/plugin-outline-pane/src/views/backup-pane.tsx @@ -0,0 +1,30 @@ +import { PureComponent } from 'react'; +import { PluginProps } from '@ali/lowcode-types'; +import OutlinePane from './pane'; + +export class OutlineBackupPane extends PureComponent { + state = { + outlineInited: false, + }; + private dispose = this.props.main.onceOutlineVisible(() => { + this.setState({ + outlineInited: true, + }); + }); + componentWillUnmount() { + this.dispose(); + } + render() { + if (!this.state.outlineInited) { + return null; + } + return ( + + ); + } +} diff --git a/packages/plugin-outline-pane/src/views/pane.tsx b/packages/plugin-outline-pane/src/views/pane.tsx index f539b51be..b11c5e4c1 100644 --- a/packages/plugin-outline-pane/src/views/pane.tsx +++ b/packages/plugin-outline-pane/src/views/pane.tsx @@ -21,7 +21,6 @@ export default class OutlinePane extends Component<{ config: any; editor: any; i } render() { - console.info(this.props); const tree = this.main.currentTree; if (!tree) { diff --git a/packages/plugin-settings-pane/CHANGELOG.md b/packages/plugin-settings-pane/CHANGELOG.md deleted file mode 100644 index c2f41be85..000000000 --- a/packages/plugin-settings-pane/CHANGELOG.md +++ /dev/null @@ -1,87 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - - -## [0.8.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.9...@ali/lowcode-plugin-settings-pane@0.8.10) (2020-04-16) - - - - -**Note:** Version bump only for package @ali/lowcode-plugin-settings-pane - - -## [0.8.9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.8...@ali/lowcode-plugin-settings-pane@0.8.9) (2020-04-15) - - -### Bug Fixes - -* plugin-designer ([2dfbcd4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2dfbcd4)) - - - - - -## [0.8.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.7...@ali/lowcode-plugin-settings-pane@0.8.8) (2020-03-31) - - - - -**Note:** Version bump only for package @ali/lowcode-plugin-settings-pane - - -## [0.8.7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.6...@ali/lowcode-plugin-settings-pane@0.8.7) (2020-03-30) - - -### Bug Fixes - -* **settings-pane:** overflow problem ([d2d8556](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/d2d8556)) - - - - - -## [0.8.6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.5...@ali/lowcode-plugin-settings-pane@0.8.6) (2020-03-30) - - - - -**Note:** Version bump only for package @ali/lowcode-plugin-settings-pane - - -## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-settings-pane@0.8.4...@ali/lowcode-plugin-settings-pane@0.8.5) (2020-03-30) - - - - -**Note:** Version bump only for package @ali/lowcode-plugin-settings-pane - - -## 0.8.4 (2020-03-30) - - -### Features - -* add color-setter ([a149921](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a149921)) -* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7)) -* 增加color-setter,json-setter ([93e76ce](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/93e76ce)) - - - - - -## 0.8.3 (2020-03-30) - - -### Features - -<<<<<<< HEAD -* add color-setter ([a149921](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a149921)) -* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7)) -* 增加color-setter,json-setter ([93e76ce](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/93e76ce)) -======= -* add color-setter ([a149921](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a14992174b65b1241e7bb82561c7efdfd6589606)) -* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7c0c488ef24f825760750a13d3fa083c96)) -* 增加color-setter,json-setter ([93e76ce](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/93e76ce3606603ee926ad83b21b29ffe28dc0682)) ->>>>>>> df955e1db90ff104cd11160def80113cfd6faccc diff --git a/packages/plugin-settings-pane/README.md b/packages/plugin-settings-pane/README.md deleted file mode 100644 index 9b40bf02b..000000000 --- a/packages/plugin-settings-pane/README.md +++ /dev/null @@ -1,15 +0,0 @@ -属性面板 - -其中 field 可独立出去一个包 - -提供: - 1. 快捷设置面板服务 - 2. 对应节点的设置面板服务 - 3. 右侧设置面板 - 4. 提供 setters 服务,setters 注册、获取机制 - -依赖: - -tip 处理 -field -popup diff --git a/packages/plugin-settings-pane/build.json b/packages/plugin-settings-pane/build.json deleted file mode 100644 index e791d5b6b..000000000 --- a/packages/plugin-settings-pane/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "plugins": [ - "build-plugin-component", - "build-plugin-fusion", - ["build-plugin-moment-locales", { - "locales": ["zh-cn"] - }] - ] -} diff --git a/packages/plugin-settings-pane/package.json b/packages/plugin-settings-pane/package.json deleted file mode 100644 index 2a0fab24e..000000000 --- a/packages/plugin-settings-pane/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "@ali/lowcode-plugin-settings-pane", - "version": "0.8.10", - "description": "Settings pane for Ali lowCode engine", - "files": [ - "es", - "lib" - ], - "main": "lib/index.js", - "module": "es/index.js", - "scripts": { - "build": "build-scripts build --skip-demo", - "test": "ava", - "test:snapshot": "ava --update-snapshots" - }, - "dependencies": { - "@ali/lowcode-designer": "^0.9.2", - "@ali/lowcode-editor-core": "^0.8.5", - "@ali/lowcode-globals": "^0.9.2", - "@ali/lowcode-plugin-outline-pane": "^0.8.8", - "@ali/ve-stage-box": "^4.0.0", - "@alifd/next": "^1.19.16", - "classnames": "^2.2.6", - "react": "^16" - }, - "devDependencies": { - "@alib/build-scripts": "^0.1.18", - "@types/classnames": "^2.2.7", - "@types/node": "^13.7.1", - "@types/react": "^16", - "build-plugin-component": "^0.2.10", - "build-plugin-fusion": "^0.1.1", - "build-plugin-moment-locales": "^0.1.0" - }, - "ava": { - "compileEnhancements": false, - "snapshotDir": "test/fixtures/__snapshots__", - "extensions": [ - "ts" - ], - "require": [ - "ts-node/register" - ] - }, - "license": "MIT", - "publishConfig": { - "registry": "https://registry.npm.alibaba-inc.com" - } -} diff --git a/packages/plugin-settings-pane/src/field/fields.tsx b/packages/plugin-settings-pane/src/field/fields.tsx deleted file mode 100644 index d36928604..000000000 --- a/packages/plugin-settings-pane/src/field/fields.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { Component } from 'react'; -import classNames from 'classnames'; -import { Icon } from '@alifd/next'; -import { Title, TitleContent } from '@ali/lowcode-globals'; -import { PopupPipe, PopupContext } from '../popup'; -import './index.less'; - -export interface FieldProps { - className?: string; - title?: TitleContent | null; - defaultDisplay?: 'accordion' | 'inline' | 'block'; - collapsed?: boolean; - onExpandChange?: (expandState: boolean) => void; -} - -export class Field extends Component { - state = { - collapsed: this.props.collapsed, - display: this.props.defaultDisplay || 'inline', - }; - - private toggleExpand = () => { - const { onExpandChange } = this.props; - const collapsed = !this.state.collapsed; - this.setState({ - collapsed, - }); - onExpandChange && onExpandChange(!collapsed); - }; - private body: HTMLDivElement | null = null; - private dispose?: () => void; - private deployBlockTesting() { - if (this.dispose) { - this.dispose(); - } - const body = this.body; - if (!body) { - return; - } - const check = () => { - const setter = body.firstElementChild; - if (setter && setter.classList.contains('lc-block-setter')) { - this.setState({ - display: 'block', - }); - } else { - this.setState({ - display: 'inline', - }); - } - }; - const observer = new MutationObserver(check); - check(); - observer.observe(body, { - childList: true, - subtree: true, - attributes: true, - attributeFilter: ['class'], - }); - this.dispose = () => observer.disconnect(); - } - componentDidMount() { - const { defaultDisplay } = this.props; - if (!defaultDisplay || defaultDisplay === 'inline') { - this.deployBlockTesting(); - } - } - componentWillUnmount() { - if (this.dispose) { - this.dispose(); - } - } - - render() { - const { className, children, title } = this.props; - const { display, collapsed } = this.state; - const isAccordion = display === 'accordion'; - return ( -
-
-
- - </div> - {isAccordion && <Icon className="lc-field-icon" type="arrow-up" size="xs" />} - </div> - <div key="body" ref={(shell) => (this.body = shell)} className="lc-field-body"> - {children} - </div> - </div> - ); - } -} - -export interface PopupFieldProps extends FieldProps { - width?: number; -} - -export class PopupField extends Component<PopupFieldProps> { - static contextType = PopupContext; - private pipe: any; - - static defaultProps: PopupFieldProps = { - width: 300, - }; - - render() { - const { className, children, title, width } = this.props; - if (!this.pipe) { - this.pipe = (this.context as PopupPipe).create({ width }); - } - - const titleElement = title && ( - <div className="lc-field-title"> - <Title title={title} /> - </div> - ); - - this.pipe.send(<div className="lc-field-body">{children}</div>, titleElement); - - return ( - <div className={classNames('lc-field lc-popup-field', className)}> - {title && ( - <div - className="lc-field-head" - onClick={(e) => { - this.pipe.show((e as any).target); - }} - > - <div className="lc-field-title"> - <Title title={title} /> - </div> - <Icon className="lc-field-icon" type="arrow-left" size="xs" /> - </div> - )} - </div> - ); - } -} - -export interface EntryFieldProps extends FieldProps { - stageName?: string; -} - -export class EntryField extends Component<EntryFieldProps> { - render() { - const { stageName, title, className } = this.props; - const classNameList = classNames('engine-setting-field', 'engine-entry-field', className); - const fieldProps: any = {}; - - if (stageName) { - // 为 stage 切换奠定基础 - fieldProps['data-stage-target'] = stageName; - } - - const innerElements = [ - <span className="engine-field-title" key="field-title"> - {title} - </span>, - // renderTip(tip, { propName }), - // <Icons name="arrow" className="engine-field-arrow" size="12px" key="engine-field-arrow-icon" />, - ]; - - return ( - <div className={classNameList} {...fieldProps}> - {innerElements} - </div> - ); - } -} - -export class PlainField extends Component<FieldProps> { - render() { - const { className, children } = this.props; - return ( - <div className={classNames(`lc-field lc-plain-field`, className)}> - <div className="lc-field-body">{children}</div> - </div> - ); - } -} diff --git a/packages/plugin-settings-pane/src/field/index.less b/packages/plugin-settings-pane/src/field/index.less deleted file mode 100644 index 5fecb74d9..000000000 --- a/packages/plugin-settings-pane/src/field/index.less +++ /dev/null @@ -1,154 +0,0 @@ -@import '../variables.less'; - -@x-gap: 10px; -@y-gap: 8px; - -.lc-field { - // head - .lc-field-head { - display: flex; - align-items: center; - justify-content: space-between; - - .lc-field-title { - display: flex; - align-items: center; - } - .lc-field-icon { - margin-right: @x-gap; - transform-origin: center; - transition: transform 0.1s; - } - } - - &.lc-plain-field { - // for top-level style - padding: 8px 10px; - > .lc-field-body { - flex: 1; - min-width: 0; - display: flex; - align-items: center; - } - } - - &.lc-inline-field { - display: flex; - align-items: center; - // for top-level style - padding: 8px 10px; - - > .lc-field-head { - width: 70px; - margin-right: 1px; - .lc-title-label { - width: 70px; - word-break: break-all; - } - } - > .lc-field-body { - flex: 1; - min-width: 0; - display: flex; - align-items: center; - } - } - - &.lc-block-field, &.lc-accordion-field { - display: block; - &:not(:first-child) { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); - } - > .lc-field-head { - padding-left: @x-gap; - height: 32px; - display: flex; - align-items: center; - font-weight: 500; - background: var(--color-block-background-shallow, rgba(31,56,88,.06)); - border-bottom: 1px solid var(--color-line-normal, @dark-alpha-2); - color: var(--color-title, @white-alpha-2); - user-select: none; - } - - > .lc-field-body { - padding: @y-gap @x-gap/2; - } - - + .lc-inline-field { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); - } - } - - .lc-setter-actions { - display: flex; - align-items: center; - } - - &.lc-block-field { - position: relative; - >.lc-field-body>.lc-block-setter>.lc-setter-actions { - position: absolute; - right: 10px; - top: 0; - height: 32px; - display: flex; - align-items: center; - } - } - - &.lc-accordion-field { - // collapsed - &.lc-field-is-collapsed { - > .lc-field-head .lc-field-icon { - transform: rotate(180deg); - } - > .lc-field-body { - display: none; - } - } - - // 邻近的保持上下距离 - + .lc-field { - margin-top: @y-gap; - } - } - - // 2rd level reset - .lc-field-body { - .lc-inline-field { - padding: @y-gap @x-gap/2 0 @x-gap/2; - &:first-child { - padding-top: 0; - } - + .lc-accordion-field, +.lc-block-field { - margin-top: @y-gap; - } - } - - .lc-field { - border-top: none !important; - } - - .lc-accordion-field, .lc-block-field { - > .lc-field-head { - padding-left: @x-gap/2; - background: var(--color-block-background-light); - border-bottom-color: var(--color-line-light); - > .lc-field-icon { - margin-right: @x-gap/2; - } - } - } - - // 3rd level field title width should short - .lc-field-body .lc-inline-field { - > .lc-field-head { - width: 50px; - .lc-title-label { - width: 50px; - } - } - } - } -} diff --git a/packages/plugin-settings-pane/src/field/index.ts b/packages/plugin-settings-pane/src/field/index.ts deleted file mode 100644 index 2f50d53ff..000000000 --- a/packages/plugin-settings-pane/src/field/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { TitleContent } from '@ali/lowcode-globals'; -import './index.less'; -import { Field, PopupField, EntryField, PlainField } from './fields'; - -export interface FieldProps { - className?: string; - title?: TitleContent | null; - display?: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry'; - collapsed?: boolean; - onExpandChange?: (collapsed: boolean) => void; - [extra: string]: any; -} - -export function createField(props: FieldProps, children: ReactNode, type?: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry') { - if (type === 'popup') { - return createElement(PopupField, props, children); - } - if (type === 'entry') { - return createElement(EntryField, props, children); - } - if (type === 'plain' || !props.title) { - return createElement(PlainField, props, children); - } - return createElement(Field, { ...props, defaultDisplay: type }, children); -} - -export { Field, PopupField, EntryField, PlainField }; diff --git a/packages/plugin-settings-pane/src/icons/convert.tsx b/packages/plugin-settings-pane/src/icons/convert.tsx deleted file mode 100644 index 71ab8630e..000000000 --- a/packages/plugin-settings-pane/src/icons/convert.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { SVGIcon, IconProps } from "@ali/lowcode-globals"; - -export function IconConvert(props: IconProps) { - return ( - <SVGIcon viewBox="0 0 1024 1024" {...props}> - <path d="M508.16 889.6C291.84 889.6 115.2 714.24 115.2 497.92 115.2 281.6 291.84 106.24 509.44 106.24c43.52 0 85.76 6.4 124.16 20.48l-10.24 30.72c-35.84-11.52-72.96-17.92-113.92-17.92-199.68 0-362.24 161.28-362.24 359.68s162.56 358.4 360.96 358.4 359.68-161.28 359.68-359.68c0-66.56-17.92-131.84-51.2-185.6L844.8 294.4c37.12 60.16 56.32 130.56 56.32 203.52-1.28 216.32-176.64 391.68-392.96 391.68z" /> - <path d="M627.2 140.8m-15.36 0a15.36 15.36 0 1 0 30.72 0 15.36 15.36 0 1 0-30.72 0Z" /> - <path d="M832 304.64m-15.36 0a15.36 15.36 0 1 0 30.72 0 15.36 15.36 0 1 0-30.72 0Z" /> - <path d="M348.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - <path d="M508.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - <path d="M668.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - </SVGIcon> - ); -} - -IconConvert.displayName = 'Convert'; diff --git a/packages/plugin-settings-pane/src/index.tsx b/packages/plugin-settings-pane/src/index.tsx deleted file mode 100644 index 7816548bc..000000000 --- a/packages/plugin-settings-pane/src/index.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createSettingFieldView } from './settings/settings-pane'; -import './transducers/register'; -import './setters/register'; -import './style.less'; -import SettingsMainView from './settings/main-view'; - -export default SettingsMainView; - -export { createSettingFieldView }; diff --git a/packages/plugin-settings-pane/src/popup/index.tsx b/packages/plugin-settings-pane/src/popup/index.tsx deleted file mode 100644 index 503e986f9..000000000 --- a/packages/plugin-settings-pane/src/popup/index.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { createContext, ReactNode, Component, PureComponent } from 'react'; -import { EventEmitter } from 'events'; -import { Balloon } from '@alifd/next'; -import { uniqueId } from '@ali/lowcode-globals'; -import './style.less'; - -export const PopupContext = createContext<PopupPipe>({} as any); - -export class PopupPipe { - private emitter = new EventEmitter(); - private currentId?: string; - - create(props?: object): { send: (content: ReactNode, title: ReactNode) => void; show: (target: Element) => void } { - let sendContent: ReactNode = null; - let sendTitle: ReactNode = null; - const id = uniqueId('popup'); - return { - send: (content: ReactNode, title: ReactNode) => { - sendContent = content; - sendTitle = title; - if (this.currentId === id) { - this.popup({ - ...props, - content, - title, - }); - } - }, - show: (target: Element, actionKey?: string) => { - this.currentId = id; - this.popup( - { - ...props, - actionKey, - content: sendContent, - title: sendTitle, - }, - target, - ); - }, - }; - } - - private popup(props: object, target?: Element) { - Promise.resolve().then(() => { - this.emitter.emit('popupchange', props, target); - }); - } - - onPopupChange(fn: (props: object, target?: Element) => void): () => void { - this.emitter.on('popupchange', fn); - return () => { - this.emitter.removeListener('popupchange', fn); - }; - } - - purge() { - this.emitter.removeAllListeners(); - } -} - -export default class PopupService extends Component<{ actionKey?: string; safeId?: string }> { - private popupPipe = new PopupPipe(); - - componentWillUnmount() { - this.popupPipe.purge(); - } - - render() { - const { children, actionKey, safeId } = this.props; - return ( - <PopupContext.Provider value={this.popupPipe}> - {children} - <PopupContent key={'pop' + actionKey} safeId={safeId} /> - </PopupContext.Provider> - ); - } -} - -export class PopupContent extends PureComponent<{ safeId?: string }> { - static contextType = PopupContext; - state: any = { - visible: false, - pos: {}, - }; - - private dispose = (this.context as PopupPipe).onPopupChange((props, target) => { - const state: any = { - ...props, - visible: true, - }; - if (target) { - const rect = target.getBoundingClientRect(); - state.pos = { - top: rect.top, - height: rect.height, - }; - // todo: compute the align method - } - this.setState(state); - }); - - componentWillUnmount() { - this.dispose(); - } - - render() { - const { content, visible, width, title, pos, actionKey } = this.state; - if (!visible) { - return null; - } - let avoidLaterHidden = true; - setTimeout(() => { - avoidLaterHidden = false; - }, 10); - - const id = uniqueId('ball'); - - return ( - <Balloon - className="lc-ballon" - align="l" - id={this.props.safeId} - safeNode={id} - visible={visible} - style={{ width }} - onVisibleChange={(visible) => { - if (avoidLaterHidden) { - return; - } - if (!visible) { - this.setState({ visible: false }); - } - }} - trigger={<div className="lc-popup-placeholder" style={pos} />} - triggerType="click" - animation={false} - // needAdjust - shouldUpdatePosition - > - <div className="lc-ballon-title">{title}</div> - <div className="lc-ballon-content"> - <PopupService actionKey={actionKey} safeId={id}> - {content} - </PopupService> - </div> - </Balloon> - ); - } -} diff --git a/packages/plugin-settings-pane/src/popup/style.less b/packages/plugin-settings-pane/src/popup/style.less deleted file mode 100644 index b115fd371..000000000 --- a/packages/plugin-settings-pane/src/popup/style.less +++ /dev/null @@ -1,22 +0,0 @@ -.lc-popup-placeholder { - position: fixed; - width: 100%; - pointer-events: none; -} - -.lc-ballon { - padding: 10px; - max-width: 640px; - width: 640px; - .lc-ballon-title { - font-size: 14px; - } - .lc-ballon-content { - margin-top: 10px; - // width: 300px; - } - .next-balloon-close { - top: 4px; - right: 4px; - } -} diff --git a/packages/plugin-settings-pane/src/setters/array-setter/bugs.md b/packages/plugin-settings-pane/src/setters/array-setter/bugs.md deleted file mode 100644 index 8fe96cc16..000000000 --- a/packages/plugin-settings-pane/src/setters/array-setter/bugs.md +++ /dev/null @@ -1,5 +0,0 @@ -* 拖拽排序有问题 -* forceInline 有问题 -* 部分改变不响应 -* 样式还原 -* autofocus diff --git a/packages/plugin-settings-pane/src/setters/array-setter/index.tsx b/packages/plugin-settings-pane/src/setters/array-setter/index.tsx deleted file mode 100644 index 344bd8a0f..000000000 --- a/packages/plugin-settings-pane/src/setters/array-setter/index.tsx +++ /dev/null @@ -1,279 +0,0 @@ -import { Component, Fragment } from 'react'; -import { Icon, Button, Message } from '@alifd/next'; -import { Title, SetterType, FieldConfig, SetterConfig } from '@ali/lowcode-globals'; -import { createSettingFieldView } from '../../settings/settings-pane'; -import { PopupContext, PopupPipe } from '../../popup'; -import Sortable from './sortable'; -import './style.less'; -import { SettingField } from '@ali/lowcode-designer'; - -interface ArraySetterState { - items: SettingField[]; - itemsMap: Map<string | number, SettingField>; - prevLength: number; -} - -interface ArraySetterProps { - value: any[]; - field: SettingField; - itemSetter?: SetterType; - columns?: FieldConfig[]; - multiValue?: boolean; -} - -export class ListSetter extends Component<ArraySetterProps, ArraySetterState> { - static getDerivedStateFromProps(props: ArraySetterProps, state: ArraySetterState) { - const { value, field } = props; - const newLength = value && Array.isArray(value) ? value.length : 0; - if (state && state.prevLength === newLength) { - return null; - } - - // props value length change will go here - const originLength = state ? state.items.length : 0; - if (state && originLength === newLength) { - return { - prevLength: newLength, - }; - } - - const itemsMap = state ? state.itemsMap : new Map<string | number, SettingField>(); - let items = state ? state.items.slice() : []; - if (newLength > originLength) { - for (let i = originLength; i < newLength; i++) { - const item = field.createField({ - name: i, - setter: props.itemSetter, - // FIXME: - forceInline: 1, - }); - items[i] = item; - itemsMap.set(item.id, item); - } - } else if (newLength < originLength) { - const deletes = items.splice(newLength); - deletes.forEach((item) => { - itemsMap.delete(item.id); - }); - } - return { - items, - itemsMap, - prevLength: newLength, - }; - } - - state: ArraySetterState = { - items: [], - itemsMap: new Map<string | number, SettingField>(), - prevLength: 0, - }; - - onSort(sortedIds: Array<string | number>) { - const { itemsMap } = this.state; - const items = sortedIds.map((id, index) => { - const item = itemsMap.get(id)!; - item.setKey(index); - return item; - }); - this.setState({ - items, - }); - } - - private scrollToLast: boolean = false; - onAdd() { - const { items, itemsMap } = this.state; - const { itemSetter } = this.props; - const initialValue = typeof itemSetter === 'object' ? (itemSetter as any).initialValue : null; - const item = this.props.field.createField({ - name: items.length, - setter: itemSetter, - // FIXME: - forceInline: 1, - }); - items.push(item); - itemsMap.set(item.id, item); - item.setValue(typeof initialValue === 'function' ? initialValue(item) : initialValue); - this.scrollToLast = true; - this.setState({ - items: items.slice(), - }); - } - - onRemove(field: SettingField) { - const { items } = this.state; - let i = items.indexOf(field); - if (i < 0) { - return; - } - items.splice(i, 1); - const l = items.length; - while (i < l) { - items[i].setKey(i); - i++; - } - field.remove(); - this.setState({ items: items.slice() }); - } - - componentWillUnmount() { - this.state.items.forEach((field) => { - field.purge(); - }); - } - - shouldComponentUpdate(_: any, nextState: ArraySetterState) { - if (nextState.items !== this.state.items) { - return true; - } - return false; - } - - render() { - let columns: any = null; - if (this.props.columns) { - columns = this.props.columns.map((column) => <Title key={column.name} title={column.title || (column.name as string)} />); - } - - const { items } = this.state; - const scrollToLast = this.scrollToLast; - this.scrollToLast = false; - const lastIndex = items.length - 1; - - const content = - items.length > 0 ? ( - <div className="lc-setter-list-scroll-body"> - <Sortable itemClassName="lc-setter-list-card" onSort={this.onSort.bind(this)}> - {items.map((field, index) => ( - <ArrayItem - key={field.id} - scrollIntoView={scrollToLast && index === lastIndex} - field={field} - onRemove={this.onRemove.bind(this, field)} - /> - ))} - </Sortable> - </div> - ) : this.props.multiValue ? ( - <Message type="warning">当前选择了多个节点,且值不一致,修改会覆盖所有值</Message> - ) : ( - <Message type="notice">当前项目为空</Message> - ); - - return ( - <div className="lc-setter-list lc-block-setter"> - {/*<div className="lc-block-setter-actions"> - <Button size="medium" onClick={this.onAdd.bind(this)}> - <Icon type="add" /> - <span>添加</span> - </Button> - </div>*/} - {columns && <div className="lc-setter-list-columns">{columns}</div>} - {content} - <Button className="lc-setter-list-add" type="primary" onClick={this.onAdd.bind(this)}> - <Icon type="add" /> - <span>添加一项</span> - </Button> - </div> - ); - } -} - -class ArrayItem extends Component<{ - field: SettingField; - onRemove: () => void; - scrollIntoView: boolean; -}> { - shouldComponentUpdate() { - return false; - } - private shell?: HTMLDivElement | null; - componentDidMount() { - if (this.props.scrollIntoView && this.shell) { - this.shell.parentElement!.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - } - } - render() { - const { onRemove, field } = this.props; - return ( - <div className="lc-listitem" ref={(ref) => (this.shell = ref)}> - <div draggable className="lc-listitem-handler"> - <Icon type="ellipsis" size="small" /> - </div> - <div className="lc-listitem-body">{createSettingFieldView(field, field.parent)}</div> - <div className="lc-listitem-actions"> - <div className="lc-listitem-action" onClick={onRemove}> - <Icon type="ashbin" size="small" /> - </div> - </div> - </div> - ); - } -} - -class TableSetter extends ListSetter { - // todo: - // forceInline = 1 - // has more actions -} - -export default class ArraySetter extends Component<{ - value: any[]; - field: SettingField; - itemSetter?: SetterType; - mode?: 'popup' | 'list'; - forceInline?: boolean; - multiValue?: boolean; -}> { - static contextType = PopupContext; - private pipe: any; - render() { - const { mode, forceInline, ...props } = this.props; - const { field, itemSetter } = props; - let columns: FieldConfig[] | undefined; - if ((itemSetter as SetterConfig)?.componentName === 'ObjectSetter') { - const items: FieldConfig[] = (itemSetter as any).props?.config?.items; - if (items && Array.isArray(items)) { - columns = items.filter((item) => item.isRequired || item.important || (item.setter as any)?.isRequired); - if (columns.length > 4) { - columns = columns.slice(0, 4); - } - } - } - - if (mode === 'popup' || forceInline) { - const title = ( - <Fragment> - 编辑: - <Title title={field.title} /> - </Fragment> - ); - if (!this.pipe) { - let width = 360; - if (columns) { - if (columns.length === 3) { - width = 480; - } else if (columns.length > 3) { - width = 600; - } - } - this.pipe = (this.context as PopupPipe).create({ width }); - } - this.pipe.send(<TableSetter key={field.id} {...props} columns={columns} />, title); - return ( - <Button - type={forceInline ? 'normal' : 'primary'} - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon type="edit" /> - {forceInline ? title : '编辑数组'} - </Button> - ); - } else { - return <ListSetter {...props} columns={columns?.slice(0, 2)} />; - } - } -} diff --git a/packages/plugin-settings-pane/src/setters/array-setter/sortable.less b/packages/plugin-settings-pane/src/setters/array-setter/sortable.less deleted file mode 100644 index 12e9512cd..000000000 --- a/packages/plugin-settings-pane/src/setters/array-setter/sortable.less +++ /dev/null @@ -1,29 +0,0 @@ -.lc-sortable { - position: relative; - - .lc-sortable-card { - box-sizing: border-box; - &:after, &:before { - content: ""; - display: table; - } - &:after { - clear: both; - } - - &.lc-dragging { - outline: 2px dashed var(--color-brand); - outline-offset: -2px; - > * { - visibility: hidden; - } - border-color: transparent !important; - box-shadow: none !important; - background: transparent !important; - } - } - - [draggable] { - cursor: ns-resize; - } -} diff --git a/packages/plugin-settings-pane/src/setters/array-setter/sortable.tsx b/packages/plugin-settings-pane/src/setters/array-setter/sortable.tsx deleted file mode 100644 index 3329470f1..000000000 --- a/packages/plugin-settings-pane/src/setters/array-setter/sortable.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import { Component, Children, ReactElement } from 'react'; -import classNames from 'classnames'; -import './sortable.less'; - -class Sortable extends Component<{ - className?: string; - itemClassName?: string; - onSort?: (sortedIds: Array<string | number>) => void; - dragImageSourceHandler?: (elem: Element) => Element; - children: ReactElement[]; -}> { - private shell?: HTMLDivElement | null; - private items?: Array<string | number>; - private willDetach?: () => void; - componentDidMount() { - const box = this.shell!; - - let isDragEnd: boolean = false; - - /** - * target node to be dragged - */ - let source: Element | null; - - /** - * node to be placed - */ - let ref: Element | null; - - /** - * next sibling of the source node - */ - let origRef: Element | null; - - /** - * accurately locate the node from event - */ - const locate = (e: DragEvent) => { - let y = e.clientY; - if (e.view !== window && e.view!.frameElement) { - y += e.view!.frameElement.getBoundingClientRect().top; - } - let node = box.firstElementChild as HTMLDivElement; - while (node) { - if (node !== source && node.dataset.id) { - const rect = node.getBoundingClientRect(); - - if (rect.height <= 0) continue; - if (y < rect.top + rect.height / 2) { - break; - } - } - node = node.nextElementSibling as HTMLDivElement; - } - return node; - }; - - /** - * find the source node - */ - const getSource = (e: DragEvent) => { - const target = e.target as Element; - if (!target || !box.contains(target) || target === box) { - return null; - } - - let node = box.firstElementChild; - while (node) { - if (node.contains(target)) { - return node; - } - node = node.nextElementSibling; - } - - return null; - }; - - const sort = (beforeId: string | number | null | undefined) => { - if (!source) return; - - const sourceId = (source as HTMLDivElement).dataset.id; - const items = this.items!; - const origIndex = items.findIndex(id => id == sourceId); - - let newIndex = beforeId ? items.findIndex(id => id == beforeId) : items.length; - - if (origIndex < 0 || newIndex < 0) return; - if (this.props.onSort) { - if (newIndex > origIndex) { - newIndex -= 1; - } - if (origIndex === newIndex) return; - const item = items.splice(origIndex, 1); - items.splice(newIndex, 0, item[0]); - - this.props.onSort(items); - } - }; - - const dragstart = (e: DragEvent) => { - isDragEnd = false; - source = getSource(e); - if (!source) { - return false; - } - origRef = source.nextElementSibling; - const rect = source.getBoundingClientRect(); - let dragSource = source; - if (this.props.dragImageSourceHandler) { - dragSource = this.props.dragImageSourceHandler(source); - } - if (e.dataTransfer) { - e.dataTransfer.setDragImage(dragSource, e.clientX - rect.left, e.clientY - rect.top); - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.dropEffect = 'move'; - try { - e.dataTransfer.setData('application/json', {} as any); - } catch (ex) { - // eslint-disable-line - } - } - - setTimeout(() => { - source!.classList.add('lc-dragging'); - }, 0); - return true; - }; - - const placeAt = (beforeRef: Element | null) => { - if (beforeRef) { - if (beforeRef !== source) { - box.insertBefore(source!, beforeRef); - } - } else { - box.appendChild(source!); - } - }; - - const adjust = (e: DragEvent) => { - if (isDragEnd) return; - ref = locate(e); - placeAt(ref); - }; - - let lastDragEvent: DragEvent | null; - const drag = (e: DragEvent) => { - if (!source) return; - e.preventDefault(); - if (lastDragEvent) { - if (lastDragEvent.clientX === e.clientX && lastDragEvent.clientY === e.clientY) { - return; - } - } - lastDragEvent = e; - if (e.dataTransfer) { - e.dataTransfer.effectAllowed = 'move'; - } - adjust(e); - }; - - const dragend = (e: DragEvent) => { - isDragEnd = true; - if (!source) return; - e.preventDefault(); - source.classList.remove('lc-dragging'); - placeAt(origRef); - sort(ref ? (ref as HTMLDivElement).dataset.id : null); - source = null; - ref = null; - origRef = null; - lastDragEvent = null; - }; - - box.addEventListener('dragstart', dragstart); - document.addEventListener('dragover', drag); - document.addEventListener('drag', drag); - document.addEventListener('dragend', dragend); - - this.willDetach = () => { - box.removeEventListener('dragstart', dragstart); - document.removeEventListener('dragover', drag); - document.removeEventListener('drag', drag); - document.removeEventListener('dragend', dragend); - }; - } - - componentWillUnmount() { - if (this.willDetach) { - this.willDetach(); - } - } - - render() { - const { className, itemClassName, children } = this.props; - const items: Array<string | number> = []; - const cards = Children.map(children, child => { - const id = child.key!; - items.push(id); - return ( - <div key={id} data-id={id} className={classNames('lc-sortable-card', itemClassName)}> - {child} - </div> - ); - }); - this.items = items; - - return ( - <div - className={classNames('lc-sortable', className)} - ref={ref => { - this.shell = ref; - }} - > - {cards} - </div> - ); - } -} - -export default Sortable; diff --git a/packages/plugin-settings-pane/src/setters/array-setter/style.less b/packages/plugin-settings-pane/src/setters/array-setter/style.less deleted file mode 100644 index 8e0da024b..000000000 --- a/packages/plugin-settings-pane/src/setters/array-setter/style.less +++ /dev/null @@ -1,103 +0,0 @@ -.lc-setter-list { - [draggable] { - cursor: move; - } - color: var(--color-text); - - .next-btn { - display: inline-flex; - align-items: center; - line-height: 1 !important; - max-width: 100%; - text-overflow: ellipsis; - } - - .lc-setter-list-add { - display: block; - width: 100%; - margin-top: 8px;; - } - - - .lc-setter-list-columns { - display: flex; - > .lc-title { - flex: 1; - justify-content: center; - } - margin-left: 47px; - margin-right: 28px; - margin-bottom: 5px; - } - - .lc-setter-list-scroll-body { - margin: -8px -5px; - padding: 8px 10px; - overflow-y: auto; - max-height: 300px; - } - - .lc-setter-list-card { - border: 1px solid rgba(31,56,88,.2); - background-color: var(--color-block-background-light); - border-radius: 3px; - &:not(:last-child) { - margin-bottom: 5px; - } - - .lc-listitem { - position: relative; - outline: none; - display: flex; - align-items: stretch; - height: 34px; - - .lc-listitem-actions { - margin: 0 3px; - display: inline-flex; - align-items: center; - justify-content: flex-end; - .lc-listitem-action { - text-align: center; - cursor: pointer; - opacity: 0.6; - &:hover { - opacity: 1; - } - } - } - .lc-listitem-body { - flex: 1; - display: flex; - align-items: stretch; - overflow: hidden; - min-width: 0; - text-overflow: ellipsis; - .lc-field { - padding: 0 !important; - display: flex; - align-items: center; - >.lc-field-body { - justify-content: center; - } - } - > * { - width: 100%; - } - .next-btn { - display: block; - width: 100%; - } - } - .lc-listitem-handler { - margin-left: 2px; - display: inline-flex; - align-items: center; - .next-icon-ellipsis { - transform: rotate(90deg); - } - opacity: 0.6; - } - } - } -} diff --git a/packages/plugin-settings-pane/src/setters/mixed-setter/index.tsx b/packages/plugin-settings-pane/src/setters/mixed-setter/index.tsx deleted file mode 100644 index 5217322c2..000000000 --- a/packages/plugin-settings-pane/src/setters/mixed-setter/index.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import React, { Component, isValidElement } from 'react'; -import classNames from 'classnames'; -import { Dropdown, Button, Menu } from '@alifd/next'; -import { - getSetter, - getSettersMap, - SetterConfig, - computed, - obx, - CustomView, - DynamicProps, - DynamicSetter, - TitleContent, - isSetterConfig, - Title, - createSetterContent, - observer, - isDynamicSetter, - shallowIntl, - EmbedTip, - isI18nData, -} from '@ali/lowcode-globals'; -import { IconConvert } from '../../icons/convert'; - -import './style.less'; -import { SettingField } from '@ali/lowcode-designer'; - -export interface SetterItem { - name: string; - title: TitleContent; - setter: string | DynamicSetter | CustomView; - props?: object | DynamicProps; - condition?: (field: SettingField) => boolean; - initialValue?: any | ((field: SettingField) => any); - list: boolean; -} - -function nomalizeSetters(setters?: Array<string | SetterConfig | CustomView | DynamicSetter>): SetterItem[] { - if (!setters) { - const normalized: SetterItem[] = []; - getSettersMap().forEach((setter, name) => { - if (name === 'MixedSetter') { - return; - } - normalized.push({ - name, - title: setter.title || name, - setter: name, - condition: setter.condition, - initialValue: setter.initialValue, - list: setter.recommend || false, - }); - }); - return normalized; - } - const names: string[] = []; - function generateName(n: string) { - let idx = 1; - let got = n; - while (names.indexOf(got) > -1) { - got = `${n}:${idx++}`; - } - names.push(got); - return got; - } - return setters.map((setter) => { - const config: any = { - setter, - list: true, - }; - if (isSetterConfig(setter)) { - config.setter = setter.componentName; - config.props = setter.props; - config.condition = setter.condition; - config.initialValue = setter.initialValue; - config.title = setter.title; - } - if (typeof config.setter === 'string') { - config.name = config.setter; - names.push(config.name); - const info = getSetter(config.setter); - if (!config.title) { - config.title = info?.title || config.setter; - } - if (!config.condition) { - config.condition = info?.condition; - } - if (!config.initialValue) { - config.initialValue = info?.initialValue; - } - } else { - config.name = generateName((config.setter as any).displayName || (config.setter as any).name || 'CustomSetter'); - if (!config.title) { - config.title = config.name; - } - } - return config; - }); -} - -@observer -export default class MixedSetter extends Component<{ - field: SettingField; - setters?: Array<string | SetterConfig | CustomView | DynamicSetter>; - onSetterChange?: (field: SettingField, name: string) => void; - onChange?: (val: any) => void; - value?: any; - className?: string; -}> { - private setters = nomalizeSetters(this.props.setters); - @obx.ref private used?: string; - @computed private getCurrentSetter() { - const { field } = this.props; - let firstMatched: SetterItem | undefined; - for (const setter of this.setters) { - const matched = !setter.condition || setter.condition(field); - if (matched) { - if (setter.name === this.used) { - return setter; - } - if (!firstMatched) { - firstMatched = setter; - } - } - } - return firstMatched; - } - - private useSetter = (name: string) => { - if (name === this.used) { - return; - } - const { field, onChange } = this.props; - const setter = this.setters.find((item) => item.name === name); - this.used = name; - if (setter) { - let newValue: any = setter.initialValue; - if (newValue && typeof newValue === 'function') { - newValue = newValue(field); - } - onChange && onChange(newValue); - } - }; - - private shell: HTMLDivElement | null = null; - private checkIsBlockField() { - if (this.shell) { - const setter = this.shell.firstElementChild; - if (setter && setter.classList.contains('lc-block-setter')) { - this.shell.classList.add('lc-block-setter'); - } else { - this.shell.classList.remove('lc-block-setter'); - } - } - } - componentDidUpdate() { - this.checkIsBlockField(); - } - componentDidMount() { - this.checkIsBlockField(); - } - - render() { - const { className, field, setters, onSetterChange, ...restProps } = this.props; - - const currentSetter = this.getCurrentSetter(); - const isTwoType = this.setters.length < 3; - - let setterContent: any; - const triggerTitle: any = { - tip: { - type: 'i18n', - 'zh-CN': '切换格式', - 'en-US': 'Switch Format', - }, - icon: <IconConvert size={24} />, - }; - if (currentSetter) { - const { setter, title, props } = currentSetter; - let setterProps: any = {}; - let setterType: any; - if (isDynamicSetter(setter)) { - setterType = setter.call(field, field); - } else { - setterType = setter; - } - if (props) { - setterProps = props; - if (typeof setterProps === 'function') { - setterProps = setterProps(field); - } - } - - setterContent = createSetterContent(setterType, { - ...shallowIntl(setterProps), - field, - ...restProps, - }); - if (title) { - if (typeof title !== 'object' || isI18nData(title) || isValidElement(title)) { - triggerTitle.tip = title; - } else { - triggerTitle.tip = title.tip || title.label; - } - } - } else { - // 未匹配的 null 值,显示 NullValue 空值 - // 未匹配的 其它 值,显示 InvalidValue 非法值 - if (restProps.value == null) { - setterContent = <span>NullValue</span>; - } else { - setterContent = <span>InvalidValue</span>; - } - } - const usedName = currentSetter?.name || this.used; - let moreBtnNode = ( - <Title - title={triggerTitle} - className="lc-switch-trigger" - onClick={ - isTwoType - ? () => { - if (this.setters[0]?.name === usedName) { - this.useSetter(this.setters[1]?.name); - } else { - this.useSetter(this.setters[0]?.name); - } - } - : undefined - } - /> - ); - if (!isTwoType) { - moreBtnNode = ( - <Dropdown trigger={moreBtnNode} triggerType="click" align="tr br"> - <Menu selectMode="single" hasSelectedIcon={true} selectedKeys={usedName} onItemClick={this.useSetter}> - {this.setters.filter(setter => setter.list || setter.name === usedName).map((setter) => { - return ( - <Menu.Item key={setter.name}> - <Title title={setter.title} /> - </Menu.Item> - ); - })} - </Menu> - </Dropdown> - ); - } - - return ( - <div ref={(shell) => (this.shell = shell)} className={classNames('lc-setter-mixed', className)}> - {setterContent} - - <div className="lc-setter-actions">{moreBtnNode}</div> - </div> - ); - } -} diff --git a/packages/plugin-settings-pane/src/setters/mixed-setter/style.less b/packages/plugin-settings-pane/src/setters/mixed-setter/style.less deleted file mode 100644 index 6efebb28c..000000000 --- a/packages/plugin-settings-pane/src/setters/mixed-setter/style.less +++ /dev/null @@ -1,30 +0,0 @@ -.lc-setter-mixed { - flex: 1; - min-width: 0; - margin-right: 26px; - display: block; - position: relative; - >.lc-setter-actions { - position: absolute; - right: -2px; - top: 50%; - transform: translate(100%, -50%); - .lc-switch-trigger { - cursor: pointer; - opacity: 0.6; - &:hover { - opacity: 1; - } - } - } - .next-input,.next-date-picker { - width: 100%; - } - &.lc-block-setter { - position: static; - margin-right: 0; - >.lc-setter-actions { - transform: none; - } - } -} diff --git a/packages/plugin-settings-pane/src/setters/object-setter/index.tsx b/packages/plugin-settings-pane/src/setters/object-setter/index.tsx deleted file mode 100644 index 2f84c8adb..000000000 --- a/packages/plugin-settings-pane/src/setters/object-setter/index.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { Component, Fragment } from 'react'; -import { Icon, Button } from '@alifd/next'; -import { Title, SetterType, FieldConfig } from '@ali/lowcode-globals'; -import { createSettingFieldView } from '../../settings/settings-pane'; -import { PopupContext, PopupPipe } from '../../popup'; -import { SettingField } from '@ali/lowcode-designer'; -import './style.less'; - -export default class ObjectSetter extends Component<{ - field: SettingField; - descriptor?: string | ((rowField: SettingField) => string); - config: ObjectSetterConfig; - mode?: 'popup' | 'form'; - // 1: in tablerow 2: in listrow 3: in column-cell - forceInline?: number; -}> { - render() { - const { mode, forceInline = 0, ...props } = this.props; - if (forceInline || mode === 'popup') { - if (forceInline > 2 || mode === 'popup') { - // popup - return <RowSetter {...props} primaryButton={forceInline ? false : true} />; - } else { - return <RowSetter columns={forceInline > 1 ? 2 : 4} {...props} />; - } - } else { - // form - return <FormSetter {...props} />; - } - } -} - -interface ObjectSetterConfig { - items?: FieldConfig[]; - extraSetter?: SetterType; -} - -interface RowSetterProps { - field: SettingField; - descriptor?: string | ((rowField: SettingField) => string); - config: ObjectSetterConfig; - columns?: number; - primaryButton?: boolean; -} - -class RowSetter extends Component<RowSetterProps> { - static contextType = PopupContext; - - state: any = { - descriptor: '', - }; - - private items?: SettingField[]; - constructor(props: RowSetterProps) { - super(props); - const { config, descriptor, field, columns } = props; - const items: SettingField[] = []; - if (columns && config.items) { - const l = Math.min(config.items.length, columns); - for (let i = 0; i < l; i++) { - const conf = config.items[i]; - if (conf.isRequired || conf.important || (conf.setter as any)?.isRequired) { - const item = field.createField({ - ...conf, - // in column-cell - forceInline: 3, - }); - items.push(item); - } - } - } - - if (items.length > 0) { - this.items = items; - } - - let firstRun: boolean = true; - field.onEffect(() => { - let state: any = {}; - if (descriptor) { - if (typeof descriptor === 'function') { - state.descriptor = descriptor(field); - } else { - state.descriptor = field.getPropValue(descriptor); - } - } else { - state.descriptor = field.title; - } - - if (firstRun) { - firstRun = false; - this.state = state; - } else { - this.setState(state); - } - }); - } - - shouldComponentUpdate(_: any, nextState: any) { - if (this.state.decriptor !== nextState.decriptor) { - return true; - } - return false; - } - - private pipe: any; - render() { - const items = this.items; - const { field, primaryButton, config } = this.props; - - if (!this.pipe) { - this.pipe = (this.context as PopupPipe).create({ width: 320 }); - } - - const title = ( - <Fragment> - 编辑: - <Title title={this.state.descriptor} /> - </Fragment> - ); - - this.pipe.send(<FormSetter key={field.id} field={field} config={config} />, title); - - if (items) { - return ( - <div className="lc-setter-object-row"> - <div - className="lc-setter-object-row-edit" - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon size="small" type="edit" /> - </div> - <div className="lc-setter-object-row-body">{items.map((item) => createSettingFieldView(item, field))}</div> - </div> - ); - } - - return ( - <Button - type={primaryButton === false ? 'normal' : 'primary'} - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon type="edit" /> - {title} - </Button> - ); - } -} - -interface FormSetterProps { - field: SettingField; - config: ObjectSetterConfig; -} -class FormSetter extends Component<FormSetterProps> { - private items: SettingField[]; - constructor(props: RowSetterProps) { - super(props); - const { config, field } = props; - this.items = (config.items || []).map((conf) => field.createField(conf)); - - // TODO: extraConfig for custom fields - } - - shouldComponentUpdate() { - return false; - } - - render() { - const { field } = this.props; - return ( - <div className="lc-setter-object lc-block-setter"> - {this.items.map((item, index) => createSettingFieldView(item, field, index))} - </div> - ); - } -} diff --git a/packages/plugin-settings-pane/src/setters/object-setter/style.less b/packages/plugin-settings-pane/src/setters/object-setter/style.less deleted file mode 100644 index 6d6064df1..000000000 --- a/packages/plugin-settings-pane/src/setters/object-setter/style.less +++ /dev/null @@ -1,31 +0,0 @@ -.lc-setter-object-row { - display: flex; - align-items: stretch; - width: 100%; - .lc-setter-object-row-edit { - width: 20px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - } - .lc-setter-object-row-body { - display: flex; - flex: 1; - min-width: 0; - align-items: center; - .lc-field { - padding: 0 !important; - .lc-field-body { - padding: 0 !important; margin: 0 !important; - } - } - > * { - flex: 1; - flex-shrink: 1; - margin-left: 2px; - min-width: 0; - overflow: hidden; - } - } -} diff --git a/packages/plugin-settings-pane/src/setters/register.ts b/packages/plugin-settings-pane/src/setters/register.ts deleted file mode 100644 index 13eb3f56f..000000000 --- a/packages/plugin-settings-pane/src/setters/register.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { registerSetter, isPlainObject } from '@ali/lowcode-globals'; -import ArraySetter from './array-setter'; -import ObjectSetter from './object-setter'; -import MixedSetter from './mixed-setter'; - -registerSetter('ArraySetter', { - component: ArraySetter, - defaultProps: {}, - title: 'ArraySetter', // TODO - condition: (field: any) => { - const v = field.getValue(); - return v == null || Array.isArray(v); - }, - initialValue: [], - recommend: true, -}); -registerSetter('ObjectSetter', { - component: ObjectSetter, - // todo: defaultProps - defaultProps: {}, - title: 'ObjectSetter', // TODO - condition: (field: any) => { - const v = field.getValue(); - return v == null || isPlainObject(v); - }, - initialValue: {}, - recommend: true, -}); -registerSetter('MixedSetter', MixedSetter); diff --git a/packages/plugin-settings-pane/src/settings/main-view.tsx b/packages/plugin-settings-pane/src/settings/main-view.tsx deleted file mode 100644 index e77fb9e2e..000000000 --- a/packages/plugin-settings-pane/src/settings/main-view.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import React, { Component, PureComponent } from 'react'; -import { Tab, Breadcrumb } from '@alifd/next'; -import { Title, createIcon, observer } from '@ali/lowcode-globals'; -import { Node, isSettingField, SettingField } from '@ali/lowcode-designer'; -import { Pane as OutlinePane } from '@ali/lowcode-plugin-outline-pane'; -import Editor from '@ali/lowcode-editor-core'; -import { SettingsMain } from './main'; -import SettingsPane from './settings-pane'; - -@observer -export default class SettingsMainView extends Component<{ editor: Editor }> { - private main = new SettingsMain(this.props.editor); - - shouldComponentUpdate() { - return false; - } - - componentWillUnmount() { - this.main.purge(); - } - - renderBreadcrumb() { - const { settings } = this.main; - if (!settings) { - return null; - } - if (settings.isMultiple) { - return ( - <div className="lc-settings-navigator"> - {createIcon(settings.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} - <Title title={settings.componentMeta!.title} /> - <span>x {settings.nodes.length}</span> - </div> - ); - } - - let node: Node | null = settings.first; - const items = []; - let l = 3; - while (l-- > 0 && node) { - const props = - l === 2 - ? {} - : { - onMouseOver: hoverNode.bind(null, node, true), - onMouseOut: hoverNode.bind(null, node, false), - onClick: selectNode.bind(null, node), - }; - items.unshift(<Breadcrumb.Item {...props} key={node.id}><Title title={node.title} /></Breadcrumb.Item>); - node = node.parent; - } - - return ( - <div className="lc-settings-navigator"> - {createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} - <Breadcrumb className="lc-settings-node-breadcrumb">{items}</Breadcrumb> - </div> - ); - } - - render() { - const { settings } = this.main; - if (!settings) { - // 未选中节点,提示选中 或者 显示根节点设置 - return ( - <div className="lc-settings-main"> - <OutlinePaneEntry main={this.main} /> - <div className="lc-settings-notice"> - <p>请在左侧画布选中节点</p> - </div> - </div> - ); - } - - if (!settings.isSameComponent) { - // todo: future support 获取设置项交集编辑 - return ( - <div className="lc-settings-main"> - <OutlinePaneEntry main={this.main} /> - <div className="lc-settings-notice"> - <p>请选中同一类型节点编辑</p> - </div> - </div> - ); - } - - const { items } = settings; - if (items.length > 5 || items.some(item => !isSettingField(item) || !item.isGroup)) { - return ( - <div className="lc-settings-main"> - <OutlinePaneEntry main={this.main} /> - {this.renderBreadcrumb()} - <div className="lc-settings-body"> - <SettingsPane target={settings} /> - </div> - </div> - ); - } - - return ( - <div className="lc-settings-main"> - <OutlinePaneEntry main={this.main} /> - <Tab - navClassName="lc-settings-tabs" - animation={false} - excessMode="dropdown" - contentClassName="lc-settings-tabs-content" - extra={this.renderBreadcrumb()} - > - {(items as SettingField[]).map(field => ( - <Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}> - <SettingsPane target={field} key={field.id} /> - </Tab.Item> - ))} - </Tab> - </div> - ); - } -} - -class OutlinePaneEntry extends PureComponent<{ main: SettingsMain }> { - state = { - outlineInited: false, - }; - private dispose = this.props.main.onceOutlineVisible(() => { - this.setState({ - outlineInited: true, - }); - }); - componentWillUnmount() { - this.dispose(); - } - render() { - if (!this.state.outlineInited) { - return null; - } - return <OutlinePane editor={this.props.main.editor} config={{ - name: '__IN_SETTINGS__' - }} />; - } -} - -function hoverNode(node: Node, flag: boolean) { - node.hover(flag); -} -function selectNode(node: Node) { - node.select(); -} diff --git a/packages/plugin-settings-pane/src/settings/main.ts b/packages/plugin-settings-pane/src/settings/main.ts deleted file mode 100644 index f752add28..000000000 --- a/packages/plugin-settings-pane/src/settings/main.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { EventEmitter } from 'events'; -import { obx, computed } from '@ali/lowcode-globals'; -import { Node, Designer, Selection, SettingTopEntry } from '@ali/lowcode-designer'; -import { getTreeMaster } from '@ali/lowcode-plugin-outline-pane'; -import Editor from '@ali/lowcode-editor-core'; - -function generateSessionId(nodes: Node[]) { - return nodes - .map((node) => node.id) - .sort() - .join(','); -} - -export class SettingsMain { - private emitter = new EventEmitter(); - private _sessionId = ''; - @obx.ref private _settings?: SettingTopEntry; - - @computed get length(): number | undefined { - return this._settings?.nodes.length; - } - - @computed get componentMeta() { - return this._settings?.componentMeta; - } - - get settings() { - return this._settings; - } - - private disposeListener: () => void; - - private designer?: Designer; - - constructor(readonly editor: Editor) { - this.init(); - } - - private async init() { - const setupSelection = (selection?: Selection) => { - if (selection) { - this.setup(selection.getNodes()); - } else { - this.setup([]); - } - }; - this.editor.on('designer.selection.change', setupSelection); - this.disposeListener = () => { - this.editor.removeListener('designer.selection.change', setupSelection); - }; - const designer = await this.editor.onceGot(Designer); - this.designer = designer; - getTreeMaster(designer).onceEnableBuiltin(() => { - this.emitter.emit('outline-visible'); - }); - setupSelection(designer.currentSelection); - } - - private setup(nodes: Node[]) { - // check nodes change - const sessionId = generateSessionId(nodes); - if (sessionId === this._sessionId) { - return; - } - this._sessionId = sessionId; - if (nodes.length < 1) { - this._settings = undefined; - return; - } - - if (!this.designer) { - this.designer = nodes[0].document.designer; - } - - 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() { - this.disposeListener(); - this.emitter.removeAllListeners(); - } -} diff --git a/packages/plugin-settings-pane/src/settings/settings-pane.tsx b/packages/plugin-settings-pane/src/settings/settings-pane.tsx deleted file mode 100644 index 11edc8a4c..000000000 --- a/packages/plugin-settings-pane/src/settings/settings-pane.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { Component } from 'react'; -import { - createContent, - CustomView, - intl, - shallowIntl, - isSetterConfig, - createSetterContent, - observer, -} from '@ali/lowcode-globals'; -import { Field, createField } from '../field'; -import PopupService from '../popup'; -import { SettingField, isSettingField, SettingTopEntry, SettingEntry } from '@ali/lowcode-designer'; - -@observer -class SettingFieldView extends Component<{ field: SettingField }> { - render() { - const { field } = this.props; - const { extraProps } = field; - const { condition, defaultValue } = extraProps; - const visible = field.isSingle && typeof condition === 'function' ? condition(field) !== false : true; - if (!visible) { - return null; - } - const { setter } = field; - - let setterProps: any = {}; - let setterType: any; - if (Array.isArray(setter)) { - setterType = 'MixedSetter'; - setterProps = { - setters: setter, - }; - } else if (isSetterConfig(setter)) { - setterType = setter.componentName; - if (setter.props) { - setterProps = setter.props; - if (typeof setterProps === 'function') { - setterProps = setterProps(field); - } - } - } else if (setter) { - setterType = setter; - } - let value = null; - if (field.type === 'field') { - if (defaultValue != null && !('defaultValue' in setterProps)) { - setterProps.defaultValue = defaultValue; - } - if (field.valueState > 0) { - value = field.getValue(); - } else { - setterProps.multiValue = true; - if (!('placeholder' in setterProps)) { - // FIXME! move to locale file - setterProps.placeholder = intl({ - type: 'i18n', - 'zh-CN': '多种值', - 'en-US': 'Multiple Value', - }); - } - } - } - - // todo: error handling - - return createField({ - title: field.title, - collapsed: !field.expanded, - onExpandChange: (expandState) => field.setExpanded(expandState), - }, createSetterContent(setterType, { - ...shallowIntl(setterProps), - forceInline: extraProps.forceInline, - key: field.id, - // === injection - prop: field, // for compatible vision - field, - // === IO - value, // reaction point - onChange: (value: any) => { - this.setState({ - value, - }); - field.setValue(value); - }, - }), extraProps.forceInline ? 'plain' : extraProps.display); - } -} - -@observer -class SettingGroupView extends Component<{ field: SettingField }> { - shouldComponentUpdate() { - return false; - } - - render() { - const { field } = this.props; - const { extraProps } = field; - const { condition } = extraProps; - const visible = field.isSingle && typeof condition === 'function' ? condition(field) !== false : true; - - if (!visible) { - return null; - } - - // todo: split collapsed state | field.items for optimize - return ( - <Field defaultDisplay="accordion" title={field.title} collapsed={!field.expanded} onExpandChange={(expandState) => { - field.setExpanded(expandState); - }}> - {field.items.map((item, index) => createSettingFieldView(item, field, index))} - </Field> - ); - } -} - -export function createSettingFieldView(item: SettingField | CustomView, field: SettingEntry, index?: number) { - if (isSettingField(item)) { - if (item.isGroup) { - return <SettingGroupView field={item} key={item.id} />; - } else { - return <SettingFieldView field={item} key={item.id} />; - } - } else { - return createContent(item, { key: index, field }); - } -} - -@observer -export default class SettingsPane extends Component<{ target: SettingTopEntry | SettingField }> { - shouldComponentUpdate() { - return false; - } - - render() { - const { target } = this.props; - const items = target.items - return ( - <div className="lc-settings-pane"> - {/* todo: add head for single use */} - <PopupService> - <div className="lc-settings-content"> - {items.map((item, index) => createSettingFieldView(item, target, index))} - </div> - </PopupService> - </div> - ); - } -} diff --git a/packages/plugin-settings-pane/src/style.less b/packages/plugin-settings-pane/src/style.less deleted file mode 100644 index 9b2c2b403..000000000 --- a/packages/plugin-settings-pane/src/style.less +++ /dev/null @@ -1,124 +0,0 @@ -.lc-settings-main { - position: relative; - height: 100%; - overflow: hidden; - - .lc-settings-notice { - text-align: center; - font-size: 12px; - font-family: PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica,Arial,sans-serif; - color: var(--color-text ,rgba(0,0,0,.6)); - padding: 50px 15px 0; - } - - .lc-settings-navigator { - height: 30px; - display: flex; - align-items: center; - padding-left: 5px; - border-bottom: 1px solid var(--color-line-normal); - .lc-settings-navigator-icon { - width: 16px; - height: 16px; - * { - fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4)); - } - } - .lc-settings-node-breadcrumb { - margin-left: 5px; - .next-breadcrumb { - display: inline-flex; - align-items: stretch; - height: 24px; - } - .next-breadcrumb-item { - display: inline-flex; - align-items: center; - cursor: default; - &:not(:last-child):hover { - cursor: pointer; - } - .next-breadcrumb-text { - font-size: 12px; - } - } - } - } - - .lc-settings-body { - position: absolute; - top: 30px; - right: 0; - left: 0; - bottom: 0; - overflow-y: auto; - } - - // ====== reset fusion-tabs ===== - .lc-settings-tabs { - position: relative; - overflow: visible; - > .next-tabs-nav-extra { - position: absolute !important; - top: 40px !important; - left: 0 !important; - height: 30px; - right: 0; - transform: none !important; - - } - .next-tabs-nav-container { - .next-tabs-nav { - display: flex; - .next-tabs-tab.lc-settings-tab-item { - flex: 1; - min-width: 0; - outline: none; - .next-tabs-tab-inner { - text-align: center; - padding: 12px 0; - } - } - } - } - } - - .lc-settings-tabs-content { - position: absolute; - top: 70px; - left:0; - right: 0; - bottom: 0; - .next-tabs-tabpane { - position: absolute; - top: 0; - right: 0; - left: 0; - bottom: 0; - overflow-y: auto; - outline: none !important; - box-shadow: none !important; - } - } - .lc-outline-pane { - position: absolute; - z-index: 100; - background-color: white; - top: 0; - bottom: 0; - display: none; - } -} - -.lc-settings-pane { - padding-bottom: 50px; - .next-btn { - line-height: 1 !important; - } -} - -html.lc-cursor-dragging:not(.lowcode-has-fixed-tree) { - .lc-settings-main .lc-outline-pane { - display: block; - } -} diff --git a/packages/plugin-settings-pane/src/transducers/addon-combine.ts b/packages/plugin-settings-pane/src/transducers/addon-combine.ts deleted file mode 100644 index 4f6b3e42d..000000000 --- a/packages/plugin-settings-pane/src/transducers/addon-combine.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { TransformedComponentMetadata, FieldConfig } from '@ali/lowcode-globals'; -import { SettingField } from '../settings/setting-field'; - -export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { - const { componentName, configure = {} } = metadata; - if (componentName === 'Leaf') { - return { - ...metadata, - configure: { - ...configure, - combined: [ - { - name: 'children', - title: { type: 'i18n', 'zh-CN': '内容设置', 'en-US': 'Content' }, - setter: { - componentName: 'MixinSetter', - props: { - // TODO: - setters: [ - { - componentName: 'StringSetter', - props: { - // TODO: textarea mode - multiline: true, - }, - initialValue: '', - }, - { - componentName: 'ExpressionSetter', - initialValue: { - type: 'JSExpression', - value: '', - }, - }, - ], - }, - }, - }, - ], - }, - }; - } - - const { props, events = {}, styles } = configure as any; - const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; - const eventsDefinition: any[] = []; - const supportedLifecycles = - events.supportedLifecycles || - (isRoot - ? [ - { - description: '初始化时', - name: 'constructor', - }, - { - description: '装载后', - name: 'componentDidMount', - }, - { - description: '更新时', - name: 'componentDidMount', - }, - { - description: '卸载时', - name: 'componentWillUnmount', - }, - ] - : null); - if (supportedLifecycles) { - eventsDefinition.push({ - type: 'lifeCycleEvent', - title: '生命周期', - list: supportedLifecycles.map((event: any) => (typeof event === 'string' ? { name: event } : event)), - }); - } - if (events.supportedEvents) { - eventsDefinition.push({ - type: 'events', - title: '事件', - list: (events.supportedEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)), - }); - } - // 通用设置 - const propsGroup = props || []; - propsGroup.push({ - name: '#generals', - title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' }, - items: [ - { - name: 'id', - title: 'ID', - setter: 'StringSetter', - }, - { - name: 'key', - title: 'Key', - // todo: use Mixin - setter: 'StringSetter', - }, - { - name: 'ref', - title: 'Ref', - setter: 'StringSetter', - }, - /* - { - name: '!more', - title: '更多', - setter: 'PropertiesSetter', - },*/ - ], - }); - const combined: FieldConfig[] = [ - { - title: { type: 'i18n', 'zh-CN': '属性', 'en-US': 'Props' }, - name: '#props', - items: propsGroup, - }, - ]; - const stylesGroup: FieldConfig[] = []; - if (styles?.supportClassName) { - stylesGroup.push({ - name: 'className', - title: { type: 'i18n', 'zh-CN': '类名绑定', 'en-US': 'ClassName' }, - setter: 'ClassNameSetter', - }); - } - if (styles?.supportInlineStyle) { - stylesGroup.push({ - name: 'style', - title: { type: 'i18n', 'zh-CN': '行内样式', 'en-US': 'Style' }, - setter: 'StyleSetter', - }); - } - if (stylesGroup.length > 0) { - combined.push({ - name: '#styles', - title: { type: 'i18n', 'zh-CN': '样式', 'en-US': 'Styles' }, - items: stylesGroup, - }); - } - - if (eventsDefinition.length > 0) { - combined.push({ - name: '#events', - title: { type: 'i18n', 'zh-CN': '事件', 'en-US': 'Events' }, - items: [ - { - name: '!events', - title: { type: 'i18n', 'zh-CN': '事件设置', 'en-US': 'Events' }, - setter: { - componentName: 'EventsSetter', - props: { - definition: eventsDefinition, - }, - }, - getValue(field: SettingField, val?: any[]) { - // todo: - return val; - }, - - setValue(field: SettingField, eventDataList: any[]) { - // todo: - return; - }, - }, - ], - }); - } - - if (isRoot) { - /* - combined.push({ - name: '#advanced', - title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' }, - items: [], - }); - */ - } else { - combined.push({ - name: '#advanced', - title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' }, - items: [ - { - name: '__condition', - title: { type: 'i18n', 'zh-CN': '条件显示', 'en-US': 'Condition' }, - setter: 'ExpressionSetter', - }, - { - name: '#loop', - title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' }, - items: [ - { - name: '__loop', - title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, - setter: { - componentName: 'MixinSetter', - props: { - // TODO: - 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' }, - }, - }, - ], - }, - }, - }, - { - name: '__loopArgs.0', - title: { type: 'i18n', 'zh-CN': '迭代变量名', 'en-US': 'Loop Item' }, - setter: { - componentName: 'StringSetter', - props: { - placeholder: { type: 'i18n', 'zh-CN': '默认为: item', 'en-US': 'Defaults: item' }, - } - }, - }, - { - name: '__loopArgs.1', - title: { type: 'i18n', 'zh-CN': '索引变量名', 'en-US': 'Loop Index' }, - setter: { - componentName: 'StringSetter', - props: { - placeholder: { type: 'i18n', 'zh-CN': '默认为: index', 'en-US': 'Defaults: index' }, - } - }, - }, - { - name: 'key', - title: 'Key', - setter: 'ExpressionSetter', - }, - ], - }, - ], - }); - } - - return { - ...metadata, - configure: { - ...configure, - combined, - }, - }; -} diff --git a/packages/plugin-settings-pane/src/transducers/parse-props.ts b/packages/plugin-settings-pane/src/transducers/parse-props.ts deleted file mode 100644 index 43bd44221..000000000 --- a/packages/plugin-settings-pane/src/transducers/parse-props.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { - FieldConfig, - PropConfig, - PropType, - SetterType, - OneOf, - Shape, - ObjectOf, - ArrayOf, - TransformedComponentMetadata, -} from '@ali/lowcode-globals'; - -function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig { - const { name, description } = propConfig; - const title = { - label: { - type: 'i18n', - 'en-US': name, - 'zh-CN': description?.slice(0, 10) || name, - }, - tip: description ? `${name} | ${description}` : undefined, - }; - return { - title, - ...propConfig, - setter: propTypeToSetter(propConfig.propType), - }; -} - -function propTypeToSetter(propType: PropType): SetterType { - let typeName: string; - let isRequired: boolean | undefined = false; - if (typeof propType === 'string') { - typeName = propType; - } else { - typeName = propType.type; - isRequired = propType.isRequired; - } - // TODO: use mixinSetter wrapper - switch (typeName) { - case 'string': - return { - componentName: 'StringSetter', - isRequired, - initialValue: '', - }; - - case 'number': - return { - componentName: 'NumberSetter', - isRequired, - initialValue: 0, - }; - case 'bool': - return { - componentName: 'NumberSetter', - isRequired, - initialValue: false, - }; - case 'oneOf': - const dataSource = ((propType as OneOf).value || []).map((value, index) => { - const t = typeof value; - return { - label: t === 'string' || t === 'number' || t === 'boolean' ? String(value) : `value ${index}`, - value, - }; - }); - const componentName = dataSource.length > 4 ? 'SelectSetter' : 'RadioGroupSetter'; - return { - componentName, - props: { dataSource }, - isRequired, - initialValue: dataSource[0] ? dataSource[0].value : null, - }; - - case 'element': - case 'node': // TODO: use Mixin - return { - // slotSetter - componentName: 'NodeSetter', - props: { - mode: typeName, - }, - isRequired, - initialValue: { - type: 'JSSlot', - value: '', - }, - }; - case 'shape': - case 'exact': - const items = (propType as Shape).value.map((item) => propConfigToFieldConfig(item)); - return { - componentName: 'ObjectSetter', - props: { - config: { - items, - extraSetter: typeName === 'shape' ? propTypeToSetter('any') : null, - }, - }, - isRequired, - initialValue: (field: any) => { - const data: any = {}; - items.forEach((item) => { - let initial = item.defaultValue; - if (initial == null && item.setter && typeof item.setter === 'object') { - initial = (item.setter as any).initialValue; - } - data[item.name] = initial ? (typeof initial === 'function' ? initial(field) : initial) : null; - }); - return data; - }, - }; - case 'object': - case 'objectOf': - return { - componentName: 'ObjectSetter', - props: { - config: { - extraSetter: propTypeToSetter(typeName === 'objectOf' ? (propType as ObjectOf).value : 'any'), - }, - }, - isRequired, - }; - case 'array': - case 'arrayOf': - return { - componentName: 'ArraySetter', - props: { - itemSetter: propTypeToSetter(typeName === 'arrayOf' ? (propType as ArrayOf).value : 'any'), - }, - isRequired, - initialValue: [], - }; - case 'func': - return { - componentName: 'FunctionSetter', - isRequired, - initialValue: { - type: 'JSFunction', - value: 'function(){}', - }, - }; - case 'oneOfType': - return { - componentName: 'MixinSetter', - props: { - // TODO: - // setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)), - }, - isRequired, - }; - } - - return { - componentName: 'MixinSetter', - isRequired, - }; -} - -const EVENT_RE = /^on[A-Z][\w]*$/; - -export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { - const { configure } = metadata; - if (configure.props) { - return metadata; - } - - if (!metadata.props) { - return { - ...metadata, - configure: { - ...configure, - props: [], - }, - }; - } - const { component = {}, events = {}, styles = {} } = configure; - const supportedEvents: any[] | null = (events as any).supportedEvents ? null : []; - const props: FieldConfig[] = []; - - metadata.props.forEach((prop) => { - const { name, propType, description } = prop; - if ( - name === 'children' && - (component.isContainer || propType === 'node' || propType === 'element' || propType === 'any') - ) { - if (component.isContainer !== false) { - component.isContainer = true; - return; - } - } - - if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) { - if (supportedEvents) { - supportedEvents.push({ - name, - description, - }); - (events as any).supportedEvents = supportedEvents; - } - return; - } - - if (name === 'className' && (propType === 'string' || propType === 'any')) { - if ((styles as any).supportClassName == null) { - (styles as any).supportClassName = true; - } - return; - } - - if (name === 'style' && (propType === 'object' || propType === 'any')) { - if ((styles as any).supportInlineStyle == null) { - (styles as any).supportInlineStyle = true; - } - return; - } - - props.push(propConfigToFieldConfig(prop)); - }); - - return { - ...metadata, - configure: { - ...configure, - props, - events, - styles, - component, - }, - }; -} diff --git a/packages/plugin-settings-pane/src/transducers/register.ts b/packages/plugin-settings-pane/src/transducers/register.ts deleted file mode 100644 index a09e685ed..000000000 --- a/packages/plugin-settings-pane/src/transducers/register.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerMetadataTransducer } from '@ali/lowcode-globals'; -import parseProps from './parse-props'; -import addonCombine from './addon-combine'; - -// parseProps -registerMetadataTransducer(parseProps, 10, 'parse-props'); - -// addon/platform custom -registerMetadataTransducer(addonCombine, 11, 'combine-props'); diff --git a/packages/plugin-settings-pane/src/utils.js b/packages/plugin-settings-pane/src/utils.js deleted file mode 100644 index b8f5bbdcc..000000000 --- a/packages/plugin-settings-pane/src/utils.js +++ /dev/null @@ -1,41 +0,0 @@ -function getHotterFromSetter(setter) { - return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line -} - -function getTransducerFromSetter(setter) { - return setter && ( - setter.transducer || setter.Transducer - || (setter.type && (setter.type.transducer || setter.type.Transducer)) - ) || null; // eslint-disable-line -} - -function combineTransducer(transducer, arr, context) { - if (!transducer && Array.isArray(arr)) { - const [toHot, toNative] = arr; - transducer = { toHot, toNative }; - } - - return { - toHot: (transducer && transducer.toHot || (x => x)).bind(context), // eslint-disable-line - toNative: (transducer && transducer.toNative || (x => x)).bind(context), // eslint-disable-line - }; -} - -export class Transducer { - constructor(context, config) { - this.setterTransducer = combineTransducer( - getTransducerFromSetter(config.setter), - getHotterFromSetter(config.setter), - context, - ); - this.context = context; - } - - toHot(data) { - return this.setterTransducer.toHot(data); - } - - toNative(data) { - return this.setterTransducer.toNative(data); - } -} diff --git a/packages/plugin-settings-pane/src/variables.less b/packages/plugin-settings-pane/src/variables.less deleted file mode 100644 index f61f2341c..000000000 --- a/packages/plugin-settings-pane/src/variables.less +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 基础的 DPL 定义使用了 kuma base 的定义,参考: - * https://github.com/uxcore/kuma-base/tree/master/variables - */ - -/** - * =========================================================== - * ==================== Font Family ========================== - * =========================================================== - */ - -/* - * @font-family: "STHeiti", "Microsoft Yahei", "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif; - */ - - @font-family: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Helvetica, Arial, sans-serif; - @font-family-code: Monaco, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Helvetica, Arial, sans-serif; - - /** - * =========================================================== - * ===================== Color DPL =========================== - * =========================================================== - */ - - @brand-color-1: rgba(0, 108, 255, 1); - @brand-color-2: rgba(25, 122, 255, 1); - @brand-color-3: rgba(0, 96, 229, 1); - - @brand-color-1-3: rgba(0, 108, 255, 0.6); - @brand-color-1-4: rgba(0, 108, 255, 0.4); - @brand-color-1-5: rgba(0, 108, 255, 0.3); - @brand-color-1-6: rgba(0, 108, 255, 0.2); - @brand-color-1-7: rgba(0, 108, 255, 0.1); - - @brand-color: @brand-color-1; - - @white-alpha-1: rgb(255, 255, 255); // W-1 - @white-alpha-2: rgba(255, 255, 255, 0.8); // W-2 A80 - @white-alpha-3: rgba(255, 255, 255, 0.6); // W-3 A60 - @white-alpha-4: rgba(255, 255, 255, 0.4); // W-4 A40 - @white-alpha-5: rgba(255, 255, 255, 0.3); // W-5 A30 - @white-alpha-6: rgba(255, 255, 255, 0.2); // W-6 A20 - @white-alpha-7: rgba(255, 255, 255, 0.1); // W-7 A10 - @white-alpha-8: rgba(255, 255, 255, 0.06); // W-8 A6 - - @dark-alpha-1: rgba(0, 0, 0, 1); // D-1 A100 - @dark-alpha-2: rgba(0, 0, 0, 0.8); // D-2 A80 - @dark-alpha-3: rgba(0, 0, 0, 0.6); // D-3 A60 - @dark-alpha-4: rgba(0, 0, 0, 0.4); // D-4 A40 - @dark-alpha-5: rgba(0, 0, 0, 0.3); // D-5 A30 - @dark-alpha-6: rgba(0, 0, 0, 0.2); // D-6 A20 - @dark-alpha-7: rgba(0, 0, 0, 0.1); // D-7 A10 - @dark-alpha-8: rgba(0, 0, 0, 0.06); // D-8 A6 - @dark-alpha-9: rgba(0, 0, 0, 0.04); // D-9 A4 - - @normal-alpha-1: rgba(31, 56, 88, 1); // N-1 A100 - @normal-alpha-2: rgba(31, 56, 88, 0.8); // N-2 A80 - @normal-alpha-3: rgba(31, 56, 88, 0.6); // N-3 A60 - @normal-alpha-4: rgba(31, 56, 88, 0.4); // N-4 A40 - @normal-alpha-5: rgba(31, 56, 88, 0.3); // N-5 A30 - @normal-alpha-6: rgba(31, 56, 88, 0.2); // N-6 A20 - @normal-alpha-7: rgba(31, 56, 88, 0.1); // N-7 A10 - @normal-alpha-8: rgba(31, 56, 88, 0.06); // N-8 A6 - @normal-alpha-9: rgba(31, 56, 88, 0.04); // N-9 A4 - - @normal-3: #77879c; - @normal-4: #a3aebd; - @normal-5: #bac3cc; - @normal-6: #d1d7de; - - @gray-dark: #333; // N2_4 - @gray: #666; // N2_3 - @gray-light: #999; // N2_2 - @gray-lighter: #ccc; // N2_1 - - @brand-secondary: #2c2f33; // B2_3 - // 补色 - @brand-complement: #00b3e8; // B3_1 - // 复合 - @brand-comosite: #00c587; // B3_2 - // 浓度 - @brand-deep: #73461d; // B3_3 - - // F1-1 - @brand-danger: rgb(240, 70, 49); - // F1-2 (10% white) - @brand-danger-hover: rgba(240, 70, 49, 0.9); - // F1-3 (5% black) - @brand-danger-focus: rgba(240, 70, 49, 0.95); - - // F2-1 - @brand-warning: rgb(250, 189, 14); - // F3-1 - @brand-success: rgb(102, 188, 92); - // F4-1 - @brand-link: rgb(102, 188, 92); - // F4-2 - @brand-link-hover: #2e76a6; - - // F1-1-7 A10 - @brand-danger-alpha-7: rgba(240, 70, 49, 0.9); - // F1-1-8 A6 - @brand-danger-alpha-8: rgba(240, 70, 49, 0.8); - // F2-1-2 A80 - @brand-warning-alpha-2: rgba(250, 189, 14, 0.8); - // F2-1-7 A10 - @brand-warning-alpha-7: rgba(250, 189, 14, 0.9); - // F3-1-2 A80 - @brand-success-alpha-2: rgba(102, 188, 92, 0.8); - // F3-1-7 A10 - @brand-success-alpha-7: rgba(102, 188, 92, 0.9); - // F4-1-7 A10 - @brand-link-alpha-7: rgba(102, 188, 92, 0.9); - - // 文本色 - @text-primary-color: @dark-alpha-3; - @text-secondary-color: @normal-alpha-3; - @text-thirdary-color: @dark-alpha-4; - @text-disabled-color: @normal-alpha-5; - @text-helper-color: @dark-alpha-4; - @text-danger-color: @brand-danger; - @text-ali-color: #ec6c00; - - /** - * =========================================================== - * =================== Shadow Box ============================ - * =========================================================== - */ - - @box-shadow-1: 0 1px 4px 0 rgba(31, 56, 88, 0.15); // 1 级阴影,物体由原来存在于底面的物体展开,物体和底面关联紧密 - @box-shadow-2: 0 2px 10px 0 rgba(31, 56, 88, 0.15); // 2 级阴影,hover状态,物体层级较高 - @box-shadow-3: 0 4px 15px 0 rgba(31, 56, 88, 0.15); // 3 级阴影,当物体层级高于所有界面元素,弹窗用 - - /** - * =========================================================== - * ================= FontSize of Level ======================= - * =========================================================== - */ - - @fontSize-1: 26px; - @fontSize-2: 20px; - @fontSize-3: 16px; - @fontSize-4: 14px; - @fontSize-5: 12px; - - @fontLineHeight-1: 38px; - @fontLineHeight-2: 30px; - @fontLineHeight-3: 26px; - @fontLineHeight-4: 24px; - @fontLineHeight-5: 20px; - - /** - * =========================================================== - * ================= FontSize of Level ======================= - * =========================================================== - */ - - @global-border-radius: 3px; - @input-border-radius: 3px; - @popup-border-radius: 6px; - - /** - * =========================================================== - * ===================== Transistion ========================= - * =========================================================== - */ - - @transition-duration: 0.3s; - @transition-ease: cubic-bezier(0.23, 1, 0.32, 1); - @transition-delay: 0s; diff --git a/packages/plugin-source-editor/src/index.tsx b/packages/plugin-source-editor/src/index.tsx index 9039c2a67..fb957dbb6 100644 --- a/packages/plugin-source-editor/src/index.tsx +++ b/packages/plugin-source-editor/src/index.tsx @@ -1,9 +1,8 @@ import { Component, isValidElement, ReactElement, ReactNode } from 'react'; import { Tab, Search, Input, Button } from '@alifd/next'; -import Editor from '@ali/lowcode-editor-core'; +import { Editor } from '@ali/lowcode-editor-core'; import { js_beautify, css_beautify } from 'js-beautify'; import MonacoEditor from 'react-monaco-editor'; -import Panel from '../../vision-polyfill/src/skeleton/widget/panel'; // import lolizer from './sorceEditorPlugin', @@ -47,12 +46,12 @@ interface FunctionEventParam { export default class SourceEditor extends Component<{ editor: Editor; - panel?: Panel + panel?: any }> { - private monocoEditer: Object; - private editorCmd: Object; + private monocoEditer: any; + private editorCmd: any; - state = { + state: any = { isShow: false, tabKey: TAB_KEY.JS_TAB, }; @@ -117,18 +116,13 @@ export default class SourceEditor extends Component<{ } openPluginPannel = () => { - const { editor, panel } = this.props; - // 判断面板是否处于激活状态 - if (!editor.leftNav || editor.leftNav != 'sourceEditor') { - // 打开面板 - editor.emit('leftNav.change', 'sourceEditor'); - } + const { panel } = this.props; if (panel) { panel.show(); } } - callEditorEvent = (eventName, params) => { + callEditorEvent = (eventName: any, params: any) => { if (!this.monocoEditer) { this.editorCmd = { eventName, @@ -146,7 +140,7 @@ export default class SourceEditor extends Component<{ }; - initCode = (schema) => { + initCode = (schema: any) => { let jsCode = js_beautify(transfrom.schema2Code(schema), { indent_size: 2, indent_empty_lines: true }); let css; @@ -167,13 +161,13 @@ export default class SourceEditor extends Component<{ */ addFunction(params: FunctionEventParam) { const count = this.monocoEditer.getModel().getLineCount() || 0; - const range = new monaco.Range(count, 1, count, 1); + const range = new (window as any).monaco.Range(count, 1, count, 1); const functionCode = transfrom.getNewFunctionCode(params.functionName); this.monocoEditer.executeEdits('log-source', [ { identifier: 'event_id', range: range, text: functionCode, forceMoveMarkers: true }, ]); setTimeout(() => { - let newPosition = new monaco.Position(count + 1, 2); + let newPosition = new (window as any).monaco.Position(count + 1, 2); this.monocoEditer.setPosition(newPosition); this.monocoEditer.focus(); }, 100); @@ -204,7 +198,7 @@ export default class SourceEditor extends Component<{ } } - editorDidMount = (editor, monaco) => { + editorDidMount = (editor: any, monaco: any) => { console.log('editorDidMount', editor); this.monocoEditer = editor; @@ -247,13 +241,13 @@ export default class SourceEditor extends Component<{ // }); }; - onTabChange = (key) => { + onTabChange = (key: any) => { this.setState({ selectTab: key, }); }; - updateCode = (newCode) => { + updateCode = (newCode: any) => { const { selectTab } = this.state; if (selectTab === TAB_KEY.JS_TAB) { this.setState({ @@ -283,7 +277,7 @@ export default class SourceEditor extends Component<{ {isShow && ( <MonacoEditor value={selectTab == TAB_KEY.JS_TAB ? jsCode : css} - {...defaultEditorOption} + {...defaultEditorOption as any} {...{ language: selectTab == TAB_KEY.JS_TAB ? 'javascript' : 'css' }} onChange={(newCode) => this.updateCode(newCode)} editorDidMount={this.editorDidMount} diff --git a/packages/plugin-source-editor/src/module.d.ts b/packages/plugin-source-editor/src/module.d.ts new file mode 100644 index 000000000..0a8caf778 --- /dev/null +++ b/packages/plugin-source-editor/src/module.d.ts @@ -0,0 +1 @@ +declare module "js-beautify"; diff --git a/packages/plugin-undo-redo/package.json b/packages/plugin-undo-redo/package.json index 8220080f0..a51075418 100644 --- a/packages/plugin-undo-redo/package.json +++ b/packages/plugin-undo-redo/package.json @@ -22,6 +22,8 @@ "@ali/lowcode-designer": "^0.9.3", "@ali/lowcode-editor-core": "^0.8.6", "@ali/lowcode-editor-skeleton": "^0.8.7", + "@ali/lowcode-types": "^0.8.0", + "@ali/lowcode-utils": "^0.8.0", "react": "^16.8.1", "react-dom": "^16.8.1" }, diff --git a/packages/plugin-undo-redo/src/index.tsx b/packages/plugin-undo-redo/src/index.tsx index 945b62490..249ed6649 100644 --- a/packages/plugin-undo-redo/src/index.tsx +++ b/packages/plugin-undo-redo/src/index.tsx @@ -1,10 +1,11 @@ import React, { PureComponent } from 'react'; import './index.scss'; -import Editor, { PluginProps } from '@ali/lowcode-editor-core'; +import { Editor } from '@ali/lowcode-editor-core'; import { TopIcon } from '@ali/lowcode-editor-skeleton'; import { Designer } from '@ali/lowcode-designer'; +import { PluginProps } from '@ali/lowcode-types'; -export interface IProps { +export interface IProps extends PluginProps { editor: Editor; logo?: string; } @@ -14,10 +15,7 @@ export interface IState { redoEnable: boolean; } -export default class UndoRedo extends PureComponent< - IProps & PluginProps, - IState -> { +export default class UndoRedo extends PureComponent<IProps, IState> { public static display = 'LowcodeUndoRedo'; private history: any; @@ -80,18 +78,8 @@ export default class UndoRedo extends PureComponent< const { undoEnable, redoEnable } = this.state; return ( <div className="lowcode-plugin-undo-redo"> - <TopIcon - icon="houtui" - title="后退" - disabled={!undoEnable} - onClick={this.handleUndoClick} - /> - <TopIcon - icon="qianjin" - title="前进" - disabled={!redoEnable} - onClick={this.handleRedoClick} - /> + <TopIcon icon="houtui" title="后退" disabled={!undoEnable} onClick={this.handleUndoClick} /> + <TopIcon icon="qianjin" title="前进" disabled={!redoEnable} onClick={this.handleRedoClick} /> </div> ); } diff --git a/packages/plugin-zh-en/package.json b/packages/plugin-zh-en/package.json index fac4b38d7..220a12831 100644 --- a/packages/plugin-zh-en/package.json +++ b/packages/plugin-zh-en/package.json @@ -15,7 +15,8 @@ }, "dependencies": { "@ali/lowcode-editor-core": "^0.8.6", - "@ali/lowcode-globals": "^0.9.3", + "@ali/lowcode-utils": "^0.8.0", + "@ali/lowcode-types": "^0.8.0", "react": "^16.8.1", "react-dom": "^16.8.1" }, diff --git a/packages/plugin-zh-en/src/icons/en.tsx b/packages/plugin-zh-en/src/icons/en.tsx index b0c773309..01b545973 100644 --- a/packages/plugin-zh-en/src/icons/en.tsx +++ b/packages/plugin-zh-en/src/icons/en.tsx @@ -1,4 +1,4 @@ -import { SVGIcon, IconProps } from '@ali/lowcode-globals'; +import { SVGIcon, IconProps } from '@ali/lowcode-utils'; export function IconEn(props: IconProps) { return ( diff --git a/packages/plugin-zh-en/src/icons/zh.tsx b/packages/plugin-zh-en/src/icons/zh.tsx index 98ddad296..b5b324dd2 100644 --- a/packages/plugin-zh-en/src/icons/zh.tsx +++ b/packages/plugin-zh-en/src/icons/zh.tsx @@ -1,4 +1,4 @@ -import { SVGIcon, IconProps } from '@ali/lowcode-globals'; +import { SVGIcon, IconProps } from '@ali/lowcode-utils'; export function IconZh(props: IconProps) { return ( diff --git a/packages/plugin-zh-en/src/locale/index.ts b/packages/plugin-zh-en/src/locale/index.ts index 913dd42f8..dfd17521f 100644 --- a/packages/plugin-zh-en/src/locale/index.ts +++ b/packages/plugin-zh-en/src/locale/index.ts @@ -1,4 +1,4 @@ -import { createIntl } from '@ali/lowcode-globals'; +import { createIntl } from '@ali/lowcode-editor-core'; import en_US from './en-US.json'; import zh_CN from './zh-CN.json'; diff --git a/packages/react-simulator-renderer/package.json b/packages/react-simulator-renderer/package.json index aec6c9bce..cca8bc1ea 100644 --- a/packages/react-simulator-renderer/package.json +++ b/packages/react-simulator-renderer/package.json @@ -14,7 +14,8 @@ }, "dependencies": { "@ali/lowcode-designer": "^0.9.3", - "@ali/lowcode-globals": "^0.9.3", + "@ali/lowcode-types": "^0.8.0", + "@ali/lowcode-utils": "^0.8.0", "@ali/lowcode-react-renderer": "^0.8.4", "@recore/obx": "^1.0.8", "@recore/obx-react": "^1.0.7", diff --git a/packages/setters/src/index.tsx b/packages/setters/src/index.tsx index 90ee52426..59b691ebd 100644 --- a/packages/setters/src/index.tsx +++ b/packages/setters/src/index.tsx @@ -30,7 +30,7 @@ export const DateYearSetter = DatePicker.YearPicker; export const DateMonthSetter = DatePicker.MonthPicker; export const DateRangeSetter = DatePicker.RangePicker; -export { ExpressionSetter, MixinSetter, EventsSetter } +export { ExpressionSetter, EventsSetter } // todo: export const ClassNameSetter = () => { diff --git a/packages/types/package.json b/packages/types/package.json index 9bbd9d826..9937c1d98 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -14,21 +14,14 @@ "test:snapshot": "ava --update-snapshots" }, "dependencies": { - "@alifd/next": "^1.19.16", - "classnames": "^2.2.6", - "monaco-editor": "^0.20.0", "react": "^16", - "react-dom": "^16.7.0" + "power-di": "^2.2.4" }, "devDependencies": { "@alib/build-scripts": "^0.1.18", - "@types/classnames": "^2.2.7", "@types/node": "^13.7.1", "@types/react": "^16", - "@types/react-dom": "^16", - "build-plugin-component": "^0.2.10", - "build-plugin-fusion": "^0.1.0", - "build-plugin-moment-locales": "^0.1.0" + "build-plugin-component": "^0.2.10" }, "ava": { "compileEnhancements": false, diff --git a/packages/types/src/setter-config.ts b/packages/types/src/setter-config.ts index 7bac84279..19eb46f99 100644 --- a/packages/types/src/setter-config.ts +++ b/packages/types/src/setter-config.ts @@ -1,8 +1,15 @@ -import { isReactComponent } from '@ali/lowcode-utils'; -import { ComponentType, ReactElement, isValidElement } from 'react'; +import { ComponentClass, Component, ComponentType, ReactElement, isValidElement } from 'react'; import { TitleContent } from './title'; import { SettingTarget } from './setting-target'; +function isReactClass(obj: any): obj is ComponentClass<any> { + return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component); +} + +function isReactComponent(obj: any): obj is ComponentType<any> { + return obj && (isReactClass(obj) || typeof obj === 'function'); +} + export type CustomView = ReactElement | ComponentType<any>; export type DynamicProps = (target: SettingTarget) => object; diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 000000000..604aaccb8 --- /dev/null +++ b/packages/utils/README.md @@ -0,0 +1 @@ +公用函数集合 diff --git a/packages/utils/build.json b/packages/utils/build.json new file mode 100644 index 000000000..bd5cf18dd --- /dev/null +++ b/packages/utils/build.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + "build-plugin-component" + ] +} diff --git a/packages/utils/package.json b/packages/utils/package.json index e69de29bb..18b5b1318 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -0,0 +1,40 @@ +{ + "name": "@ali/lowcode-utils", + "version": "0.8.0", + "description": "Utils for Ali lowCode engine", + "files": [ + "es", + "lib" + ], + "main": "lib/index.js", + "module": "es/index.js", + "scripts": { + "build": "build-scripts build --skip-demo", + "test": "ava", + "test:snapshot": "ava --update-snapshots" + }, + "dependencies": { + "react": "^16", + "@alifd/next": "^1.19.16", + "@ali/lowcode-utils": "^0.8.0" + }, + "devDependencies": { + "@alib/build-scripts": "^0.1.18", + "@types/node": "^13.7.1", + "@types/react": "^16", + "build-plugin-component": "^0.2.10" + }, + "ava": { + "compileEnhancements": false, + "snapshotDir": "test/fixtures/__snapshots__", + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register" + ] + }, + "publishConfig": { + "registry": "https://registry.npm.alibaba-inc.com" + } +} diff --git a/packages/plugin-settings-pane/tsconfig.json b/packages/utils/tsconfig.json similarity index 100% rename from packages/plugin-settings-pane/tsconfig.json rename to packages/utils/tsconfig.json diff --git a/packages/vision-polyfill/src/bundle/prototype.ts b/packages/vision-polyfill/src/bundle/prototype.ts index 11030b8f9..8fa44e3cd 100644 --- a/packages/vision-polyfill/src/bundle/prototype.ts +++ b/packages/vision-polyfill/src/bundle/prototype.ts @@ -1,12 +1,11 @@ import { ComponentType, ReactElement } from 'react'; +import { ComponentMetadata, FieldConfig, InitialItem } from '@ali/lowcode-types'; import { - ComponentMetadata, - uniqueId, + ComponentMeta, + addBuiltinComponentAction, + isComponentMeta, registerMetadataTransducer, - FieldConfig, - InitialItem, -} from '@ali/lowcode-globals'; -import { ComponentMeta, addBuiltinComponentAction, isComponentMeta } from '@ali/lowcode-designer'; +} from '@ali/lowcode-designer'; import { OldPropConfig, OldPrototypeConfig, @@ -16,6 +15,7 @@ import { upgradeConfigure, } from './upgrade-metadata'; import { designer } from '../editor'; +import { uniqueId } from '@ali/lowcode-utils'; const GlobalPropsConfigure: Array<{ position: string; initials?: InitialItem[]; config: FieldConfig }> = []; const Overrides: { diff --git a/packages/vision-polyfill/src/bundle/trunk.ts b/packages/vision-polyfill/src/bundle/trunk.ts index cd676fdf2..a35625282 100644 --- a/packages/vision-polyfill/src/bundle/trunk.ts +++ b/packages/vision-polyfill/src/bundle/trunk.ts @@ -1,6 +1,6 @@ import { ReactElement, ComponentType } from 'react'; import { EventEmitter } from 'events'; -import { registerSetter } from '@ali/lowcode-globals'; +import { registerSetter } from '@ali/lowcode-editor-core'; import Bundle from './bundle'; export class Trunk { diff --git a/packages/vision-polyfill/src/bundle/upgrade-metadata.ts b/packages/vision-polyfill/src/bundle/upgrade-metadata.ts index 00a81efb7..e64ed5556 100644 --- a/packages/vision-polyfill/src/bundle/upgrade-metadata.ts +++ b/packages/vision-polyfill/src/bundle/upgrade-metadata.ts @@ -1,10 +1,11 @@ import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react'; -import { isI18nData, SettingTarget, InitialItem, isPlainObject, isJSSlot, isJSExpression } from '@ali/lowcode-globals'; +import { isPlainObject } from '@ali/lowcode-utils'; +import { isI18nData, SettingTarget, InitialItem, isJSSlot, isJSExpression } from '@ali/lowcode-types'; type Field = SettingTarget; export enum DISPLAY_TYPE { - NONE = 'none', // => condition'plain' + NONE = 'none', // => condition'plain' PLAIN = 'plain', INLINE = 'inline', BLOCK = 'block', @@ -35,7 +36,7 @@ export interface OldPropConfig { }; defaultValue?: any; // => extraProps.defaultValue initialValue?: any | ((value: any, defaultValue: any) => any); // => initials.initialValue - initial?: (value: any, defaultValue: any) => any // => initials.initialValue + initial?: (value: any, defaultValue: any) => any; // => initials.initialValue display?: DISPLAY_TYPE; // => fieldExtraProps fieldStyle?: DISPLAY_TYPE; // => fieldExtraProps @@ -71,12 +72,12 @@ export interface OldPropConfig { mutator?( // => setValue this: Field, value: any, - /* - hotValue: any, // => x + hotValue: any, + ): /* preValue: any, // => x preHotValue: any, // => x */ - ): void; + void; /** * other values' change will trigger sync function here */ @@ -218,13 +219,13 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) newConfig.title = { label: title, tip: tip.content, - docUrl: tip.url + docUrl: tip.url, }; } else { newConfig.title = { ...(title as any), tip: tip.content, - docUrl: tip.url + docUrl: tip.url, }; } } @@ -260,7 +261,9 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) if (ignore != null || disabled != null) { // FIXME! addFilter extraProps.virtual = (field: Field) => { - if (isDisabled(field)) { return true; } + if (isDisabled(field)) { + return true; + } if (typeof ignore === 'function') { return ignore.call(field, field.getValue()) === true; @@ -302,7 +305,7 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) } return currentValue == null ? defaults : currentValue; - } + }, }); if (sync) { @@ -311,11 +314,11 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) if (value !== undefined) { field.setValue(value); } - } + }; } if (mutator && !slotName) { extraProps.setValue = (field: Field, value: any) => { - mutator.call(field, value); + mutator.call(field, value, value); }; } @@ -324,18 +327,20 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) if (!newConfig.title && slotTitle) { newConfig.title = slotTitle; } - const setters: any[] = [{ - componentName: 'SlotSetter', - initialValue: (field: any, value: any) => { - if (isJSSlot(value)) { - return value; - } - return { - type: 'JSSlot', - value: value == null ? initialChildren : value - }; + const setters: any[] = [ + { + componentName: 'SlotSetter', + initialValue: (field: any, value: any) => { + if (isJSSlot(value)) { + return value; + } + return { + type: 'JSSlot', + value: value == null ? initialChildren : value, + }; + }, }, - }]; + ]; if (allowTextInput !== false) { setters.unshift('StringSetter'); // FIXME: use I18nSetter @@ -351,19 +356,21 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) let primarySetter: any; if (type === 'composite') { const initials: InitialItem[] = []; - const objItems = items ? upgradeConfigure(items, (item) => { - initials.push(item); - }) : []; + const objItems = items + ? upgradeConfigure(items, (item) => { + initials.push(item); + }) + : []; const initial = (target: SettingTarget, value?: any) => { // TODO: const defaults = extraProps.defaultValue; const data: any = {}; - initials.forEach(item => { + initials.forEach((item) => { // FIXME! Target may be a wrong data[item.name] = item.initial(target, isPlainObject(value) ? value[item.name] : null); }); return data; - } + }; addInitial({ name, initial, @@ -385,9 +392,11 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) primarySetter = setter.map(({ setter, condition }) => { return { componentName: setter, - condition: condition ? (field: Field) => { - return condition.call(field, field.getValue()); - } : null, + condition: condition + ? (field: Field) => { + return condition.call(field, field.getValue()); + } + : null, }; }); } else { @@ -396,7 +405,9 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) } if (supportVariable) { if (primarySetter) { - const setters = Array.isArray(primarySetter) ? primarySetter.concat('ExpressionSetter') : [primarySetter, 'ExpressionSetter']; + const setters = Array.isArray(primarySetter) + ? primarySetter.concat('ExpressionSetter') + : [primarySetter, 'ExpressionSetter']; primarySetter = { componentName: 'MixedSetter', props: { @@ -405,8 +416,8 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) if (useVariableChange) { useVariableChange.call(field, { isUseVariable: name === 'ExpressionSetter' }); } - } - } + }, + }, }; } else { primarySetter = 'ExpressionSetter'; @@ -447,7 +458,7 @@ export function upgradeActions(actions?: Array<ComponentType<any> | ReactElement return actions.map((content) => { const type: any = isValidElement(content) ? content.type : content; if (typeof content === 'function') { - const fn = content as (() => ReactElement); + const fn = content as () => ReactElement; content = (({ node }: any) => { fn.call(node); }) as any; @@ -457,7 +468,7 @@ export function upgradeActions(actions?: Array<ComponentType<any> | ReactElement content, important: true, }; - }) + }); } /** @@ -492,10 +503,11 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { canDroping, // hooks - canDraging, canDragging, // handleDragging + canDraging, + canDragging, // handleDragging // events didDropOut, // onNodeRemove - didDropIn, // onNodeAdd + didDropIn, // onNodeAdd subtreeModified, // onSubtreeModified canResizing, // resizing @@ -504,7 +516,6 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { onResizeEnd, // onResizeEnd } = oldConfig; - const meta: any = { componentName, title, @@ -566,7 +577,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { experimental.context = context; } if (snippets) { - experimental.snippets = snippets.map(data => { + experimental.snippets = snippets.map((data) => { const { schema = {} } = data; if (!schema.children && initialChildren && typeof initialChildren !== 'function') { schema.children = initialChildren; @@ -596,9 +607,12 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { } } if (initialChildren) { - experimental.initialChildren = typeof initialChildren === 'function' ? (field: Field) => { - return initialChildren.call(field, (field as any).props); - } : initialChildren; + experimental.initialChildren = + typeof initialChildren === 'function' + ? (field: Field) => { + return initialChildren.call(field, (field as any).props); + } + : initialChildren; } if (view) { experimental.view = view; @@ -644,21 +658,21 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { // todo: what is trigger? const { trigger, deltaX, deltaY } = e; onResize(e, trigger, currentNode, deltaX, deltaY); - } + }; } if (onResizeStart) { callbacks.onResizeStart = (e: any, currentNode: any) => { // todo: what is trigger? const { trigger } = e; onResizeStart(e, trigger, currentNode); - } + }; } if (onResizeEnd) { callbacks.onResizeEnd = (e: any, currentNode: any) => { // todo: what is trigger? const { trigger } = e; onResizeEnd(e, trigger, currentNode); - } + }; } experimental.callbacks = callbacks; @@ -675,5 +689,3 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { meta.experimental = experimental; return meta; } - - diff --git a/packages/vision-polyfill/src/demo/index.ts b/packages/vision-polyfill/src/demo/index.ts index af165b707..93bf90a09 100644 --- a/packages/vision-polyfill/src/demo/index.ts +++ b/packages/vision-polyfill/src/demo/index.ts @@ -6,7 +6,7 @@ import getTrunkPane from '@ali/ve-trunk-pane'; import EventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'; import loadUrls from './loader'; import { upgradeAssetsBundle } from './upgrade-assets'; -import { isCSSUrl } from '@ali/lowcode-globals'; +import { isCSSUrl } from '@ali/lowcode-utils'; const { editor, skeleton } = Engine; diff --git a/packages/vision-polyfill/src/drag-engine.ts b/packages/vision-polyfill/src/drag-engine.ts index b6e2fc8a1..97849cd57 100644 --- a/packages/vision-polyfill/src/drag-engine.ts +++ b/packages/vision-polyfill/src/drag-engine.ts @@ -1,5 +1,5 @@ import { designer } from './editor'; -import { DragObjectType, isNode, TransformStage } from '@ali/lowcode-designer'; +import { DragObjectType, isNode } from '@ali/lowcode-designer'; const dragon = designer.dragon; const DragEngine = { diff --git a/packages/vision-polyfill/src/editor.ts b/packages/vision-polyfill/src/editor.ts index 8c5a1afed..c4f8922d2 100644 --- a/packages/vision-polyfill/src/editor.ts +++ b/packages/vision-polyfill/src/editor.ts @@ -1,11 +1,11 @@ -import { globalContext, isPlainObject, isJSBlock } from '@ali/lowcode-globals'; -import Editor from '@ali/lowcode-editor-core'; +import { isJSBlock } from '@ali/lowcode-types'; +import { isPlainObject } from '@ali/lowcode-utils'; +import { globalContext, Editor } from '@ali/lowcode-editor-core'; import { Designer, TransformStage } from '@ali/lowcode-designer'; import { registerSetters } from '@ali/lowcode-setters'; import Outline from '@ali/lowcode-plugin-outline-pane'; -import SettingsPane from '@ali/lowcode-plugin-settings-pane'; import DesignerPlugin from '@ali/lowcode-plugin-designer'; -import { Skeleton } from './skeleton/skeleton'; +import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; import Preview from '@ali/lowcode-plugin-sample-preview'; @@ -78,7 +78,7 @@ skeleton.add({ area: 'rightArea', name: 'settingsPane', type: 'Panel', - content: SettingsPane, + content: SettingsPrimaryPane, }); skeleton.add({ area: 'leftArea', diff --git a/packages/vision-polyfill/src/module.d.ts b/packages/vision-polyfill/src/module.d.ts new file mode 100644 index 000000000..3e142d5dd --- /dev/null +++ b/packages/vision-polyfill/src/module.d.ts @@ -0,0 +1,3 @@ +declare module "@ali/visualengine"; +declare module "@ali/visualengine-utils"; +declare module "@ali/ve-trunk-pane" diff --git a/packages/vision-polyfill/src/pages.ts b/packages/vision-polyfill/src/pages.ts index 198ad0db6..4cb868667 100644 --- a/packages/vision-polyfill/src/pages.ts +++ b/packages/vision-polyfill/src/pages.ts @@ -1,5 +1,5 @@ import { designer } from './editor'; -import { RootSchema } from '@ali/lowcode-globals'; +import { RootSchema } from '@ali/lowcode-types'; import { DocumentModel } from '@ali/lowcode-designer'; const { project } = designer; diff --git a/packages/vision-polyfill/src/panes.ts b/packages/vision-polyfill/src/panes.ts index 268bc2d75..c45c4b886 100644 --- a/packages/vision-polyfill/src/panes.ts +++ b/packages/vision-polyfill/src/panes.ts @@ -1,6 +1,6 @@ import { skeleton, editor } from './editor'; import { ReactElement } from 'react'; -import { IWidgetBaseConfig } from './skeleton/types'; +import { IWidgetBaseConfig } from '@ali/lowcode-editor-skeleton'; export interface IContentItemConfig { title: string; diff --git a/packages/vision-polyfill/src/prop.ts b/packages/vision-polyfill/src/prop.ts index fb00d47ef..478fe0ec2 100644 --- a/packages/vision-polyfill/src/prop.ts +++ b/packages/vision-polyfill/src/prop.ts @@ -4,7 +4,7 @@ import { fromJS, Iterable, Map as IMMap } from 'immutable'; import logger from '@ali/vu-logger'; import { uniqueId, cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils'; import I18nUtil from '@ali/ve-i18n-util'; -import { getSetter } from '@ali/lowcode-globals'; +import { getSetter } from '@ali/lowcode-editor-core'; import { editor } from './editor'; import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata'; @@ -264,7 +264,7 @@ export default class Prop implements IVariableSettable { }) { const accessor = this.config.accessor; if (accessor && (!options || !options.disableAccessor)) { - const value = accessor.call(this, this.value); + const value = accessor.call(this as any, this.value); if (!disableCache) { this.value = value; } @@ -314,7 +314,7 @@ export default class Prop implements IVariableSettable { const sync = this.config.sync; if (sync) { - const value = sync.call(this, this.getValue(true)); + const value = sync.call(this as any, this.getValue(true)); if (value !== undefined) { this.setValue(value); } @@ -377,7 +377,7 @@ export default class Prop implements IVariableSettable { this.emitter.emit('ve.prop.useVariableChange', { isUseVariable: flag }); if (this.config.useVariableChange) { - this.config.useVariableChange.call(this, { isUseVariable: flag }); + this.config.useVariableChange.call(this as any, { isUseVariable: flag }); } } @@ -418,7 +418,7 @@ export default class Prop implements IVariableSettable { } if (mutator && !extraOptions.disableMutator) { - mutator.call(this, this.value); + mutator.call(this as any, this.value); } if (this.modify(force)) { @@ -485,7 +485,7 @@ export default class Prop implements IVariableSettable { if (!options || !options.disableMutator) { const mutator = this.config.mutator; if (mutator) { - mutator.call(this, value); + mutator.call(this as any, value); } } @@ -512,7 +512,7 @@ export default class Prop implements IVariableSettable { let hidden = this.config.hidden; if (typeof hidden === 'function') { - hidden = hidden.call(this, this.getValue()); + hidden = hidden.call(this as any, this.getValue()); } return hidden === true; } @@ -520,7 +520,7 @@ export default class Prop implements IVariableSettable { public isDisabled() { let disabled = this.config.disabled; if (typeof disabled === 'function') { - disabled = disabled.call(this, this.getValue()); + disabled = disabled.call(this as any, this.getValue()); } return disabled === true; } @@ -530,7 +530,7 @@ export default class Prop implements IVariableSettable { let ignore = this.config.ignore; if (typeof ignore === 'function') { - ignore = ignore.call(this, this.getValue()); + ignore = ignore.call(this as any, this.getValue()); } return ignore === true; } diff --git a/packages/vision-polyfill/src/skeleton/area.ts b/packages/vision-polyfill/src/skeleton/area.ts deleted file mode 100644 index 3877e175d..000000000 --- a/packages/vision-polyfill/src/skeleton/area.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { obx, computed } from '@ali/lowcode-globals'; -import WidgetContainer from './widget/widget-container'; -import { Skeleton } from './skeleton'; -import { IWidget } from './widget/widget'; -import { IWidgetBaseConfig } from './types'; - -export default class Area<C extends IWidgetBaseConfig = any, T extends IWidget = IWidget> { - @obx private _visible: boolean = true; - - @computed get visible() { - if (this.exclusive) { - return this.container.current != null; - } - return this._visible; - } - - get current() { - if (this.exclusive) { - return this.container.current; - } - return null; - } - - readonly container: WidgetContainer<T, C>; - constructor(readonly skeleton: Skeleton, readonly name: string, handle: (item: T | C) => T, private exclusive?: boolean, defaultSetCurrent: boolean = false) { - this.container = skeleton.createContainer(name, handle, exclusive, () => this.visible, defaultSetCurrent); - } - - @computed isEmpty(): boolean { - return this.container.items.length < 1; - } - - add(config: T | C): T { - return this.container.add(config); - } - - private lastCurrent: T | null = null; - setVisible(flag: boolean) { - if (this.exclusive) { - const current = this.container.current; - if (flag && !current) { - this.container.active(this.lastCurrent || this.container.getAt(0)) - } else if (current) { - this.lastCurrent = current; - this.container.unactive(current); - } - return; - } - this._visible = flag; - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/array-setter/bugs.md b/packages/vision-polyfill/src/skeleton/components/array-setter/bugs.md deleted file mode 100644 index 8fe96cc16..000000000 --- a/packages/vision-polyfill/src/skeleton/components/array-setter/bugs.md +++ /dev/null @@ -1,5 +0,0 @@ -* 拖拽排序有问题 -* forceInline 有问题 -* 部分改变不响应 -* 样式还原 -* autofocus diff --git a/packages/vision-polyfill/src/skeleton/components/array-setter/index.tsx b/packages/vision-polyfill/src/skeleton/components/array-setter/index.tsx deleted file mode 100644 index 344bd8a0f..000000000 --- a/packages/vision-polyfill/src/skeleton/components/array-setter/index.tsx +++ /dev/null @@ -1,279 +0,0 @@ -import { Component, Fragment } from 'react'; -import { Icon, Button, Message } from '@alifd/next'; -import { Title, SetterType, FieldConfig, SetterConfig } from '@ali/lowcode-globals'; -import { createSettingFieldView } from '../../settings/settings-pane'; -import { PopupContext, PopupPipe } from '../../popup'; -import Sortable from './sortable'; -import './style.less'; -import { SettingField } from '@ali/lowcode-designer'; - -interface ArraySetterState { - items: SettingField[]; - itemsMap: Map<string | number, SettingField>; - prevLength: number; -} - -interface ArraySetterProps { - value: any[]; - field: SettingField; - itemSetter?: SetterType; - columns?: FieldConfig[]; - multiValue?: boolean; -} - -export class ListSetter extends Component<ArraySetterProps, ArraySetterState> { - static getDerivedStateFromProps(props: ArraySetterProps, state: ArraySetterState) { - const { value, field } = props; - const newLength = value && Array.isArray(value) ? value.length : 0; - if (state && state.prevLength === newLength) { - return null; - } - - // props value length change will go here - const originLength = state ? state.items.length : 0; - if (state && originLength === newLength) { - return { - prevLength: newLength, - }; - } - - const itemsMap = state ? state.itemsMap : new Map<string | number, SettingField>(); - let items = state ? state.items.slice() : []; - if (newLength > originLength) { - for (let i = originLength; i < newLength; i++) { - const item = field.createField({ - name: i, - setter: props.itemSetter, - // FIXME: - forceInline: 1, - }); - items[i] = item; - itemsMap.set(item.id, item); - } - } else if (newLength < originLength) { - const deletes = items.splice(newLength); - deletes.forEach((item) => { - itemsMap.delete(item.id); - }); - } - return { - items, - itemsMap, - prevLength: newLength, - }; - } - - state: ArraySetterState = { - items: [], - itemsMap: new Map<string | number, SettingField>(), - prevLength: 0, - }; - - onSort(sortedIds: Array<string | number>) { - const { itemsMap } = this.state; - const items = sortedIds.map((id, index) => { - const item = itemsMap.get(id)!; - item.setKey(index); - return item; - }); - this.setState({ - items, - }); - } - - private scrollToLast: boolean = false; - onAdd() { - const { items, itemsMap } = this.state; - const { itemSetter } = this.props; - const initialValue = typeof itemSetter === 'object' ? (itemSetter as any).initialValue : null; - const item = this.props.field.createField({ - name: items.length, - setter: itemSetter, - // FIXME: - forceInline: 1, - }); - items.push(item); - itemsMap.set(item.id, item); - item.setValue(typeof initialValue === 'function' ? initialValue(item) : initialValue); - this.scrollToLast = true; - this.setState({ - items: items.slice(), - }); - } - - onRemove(field: SettingField) { - const { items } = this.state; - let i = items.indexOf(field); - if (i < 0) { - return; - } - items.splice(i, 1); - const l = items.length; - while (i < l) { - items[i].setKey(i); - i++; - } - field.remove(); - this.setState({ items: items.slice() }); - } - - componentWillUnmount() { - this.state.items.forEach((field) => { - field.purge(); - }); - } - - shouldComponentUpdate(_: any, nextState: ArraySetterState) { - if (nextState.items !== this.state.items) { - return true; - } - return false; - } - - render() { - let columns: any = null; - if (this.props.columns) { - columns = this.props.columns.map((column) => <Title key={column.name} title={column.title || (column.name as string)} />); - } - - const { items } = this.state; - const scrollToLast = this.scrollToLast; - this.scrollToLast = false; - const lastIndex = items.length - 1; - - const content = - items.length > 0 ? ( - <div className="lc-setter-list-scroll-body"> - <Sortable itemClassName="lc-setter-list-card" onSort={this.onSort.bind(this)}> - {items.map((field, index) => ( - <ArrayItem - key={field.id} - scrollIntoView={scrollToLast && index === lastIndex} - field={field} - onRemove={this.onRemove.bind(this, field)} - /> - ))} - </Sortable> - </div> - ) : this.props.multiValue ? ( - <Message type="warning">当前选择了多个节点,且值不一致,修改会覆盖所有值</Message> - ) : ( - <Message type="notice">当前项目为空</Message> - ); - - return ( - <div className="lc-setter-list lc-block-setter"> - {/*<div className="lc-block-setter-actions"> - <Button size="medium" onClick={this.onAdd.bind(this)}> - <Icon type="add" /> - <span>添加</span> - </Button> - </div>*/} - {columns && <div className="lc-setter-list-columns">{columns}</div>} - {content} - <Button className="lc-setter-list-add" type="primary" onClick={this.onAdd.bind(this)}> - <Icon type="add" /> - <span>添加一项</span> - </Button> - </div> - ); - } -} - -class ArrayItem extends Component<{ - field: SettingField; - onRemove: () => void; - scrollIntoView: boolean; -}> { - shouldComponentUpdate() { - return false; - } - private shell?: HTMLDivElement | null; - componentDidMount() { - if (this.props.scrollIntoView && this.shell) { - this.shell.parentElement!.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - } - } - render() { - const { onRemove, field } = this.props; - return ( - <div className="lc-listitem" ref={(ref) => (this.shell = ref)}> - <div draggable className="lc-listitem-handler"> - <Icon type="ellipsis" size="small" /> - </div> - <div className="lc-listitem-body">{createSettingFieldView(field, field.parent)}</div> - <div className="lc-listitem-actions"> - <div className="lc-listitem-action" onClick={onRemove}> - <Icon type="ashbin" size="small" /> - </div> - </div> - </div> - ); - } -} - -class TableSetter extends ListSetter { - // todo: - // forceInline = 1 - // has more actions -} - -export default class ArraySetter extends Component<{ - value: any[]; - field: SettingField; - itemSetter?: SetterType; - mode?: 'popup' | 'list'; - forceInline?: boolean; - multiValue?: boolean; -}> { - static contextType = PopupContext; - private pipe: any; - render() { - const { mode, forceInline, ...props } = this.props; - const { field, itemSetter } = props; - let columns: FieldConfig[] | undefined; - if ((itemSetter as SetterConfig)?.componentName === 'ObjectSetter') { - const items: FieldConfig[] = (itemSetter as any).props?.config?.items; - if (items && Array.isArray(items)) { - columns = items.filter((item) => item.isRequired || item.important || (item.setter as any)?.isRequired); - if (columns.length > 4) { - columns = columns.slice(0, 4); - } - } - } - - if (mode === 'popup' || forceInline) { - const title = ( - <Fragment> - 编辑: - <Title title={field.title} /> - </Fragment> - ); - if (!this.pipe) { - let width = 360; - if (columns) { - if (columns.length === 3) { - width = 480; - } else if (columns.length > 3) { - width = 600; - } - } - this.pipe = (this.context as PopupPipe).create({ width }); - } - this.pipe.send(<TableSetter key={field.id} {...props} columns={columns} />, title); - return ( - <Button - type={forceInline ? 'normal' : 'primary'} - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon type="edit" /> - {forceInline ? title : '编辑数组'} - </Button> - ); - } else { - return <ListSetter {...props} columns={columns?.slice(0, 2)} />; - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.less b/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.less deleted file mode 100644 index 12e9512cd..000000000 --- a/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.less +++ /dev/null @@ -1,29 +0,0 @@ -.lc-sortable { - position: relative; - - .lc-sortable-card { - box-sizing: border-box; - &:after, &:before { - content: ""; - display: table; - } - &:after { - clear: both; - } - - &.lc-dragging { - outline: 2px dashed var(--color-brand); - outline-offset: -2px; - > * { - visibility: hidden; - } - border-color: transparent !important; - box-shadow: none !important; - background: transparent !important; - } - } - - [draggable] { - cursor: ns-resize; - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.tsx b/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.tsx deleted file mode 100644 index 3329470f1..000000000 --- a/packages/vision-polyfill/src/skeleton/components/array-setter/sortable.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import { Component, Children, ReactElement } from 'react'; -import classNames from 'classnames'; -import './sortable.less'; - -class Sortable extends Component<{ - className?: string; - itemClassName?: string; - onSort?: (sortedIds: Array<string | number>) => void; - dragImageSourceHandler?: (elem: Element) => Element; - children: ReactElement[]; -}> { - private shell?: HTMLDivElement | null; - private items?: Array<string | number>; - private willDetach?: () => void; - componentDidMount() { - const box = this.shell!; - - let isDragEnd: boolean = false; - - /** - * target node to be dragged - */ - let source: Element | null; - - /** - * node to be placed - */ - let ref: Element | null; - - /** - * next sibling of the source node - */ - let origRef: Element | null; - - /** - * accurately locate the node from event - */ - const locate = (e: DragEvent) => { - let y = e.clientY; - if (e.view !== window && e.view!.frameElement) { - y += e.view!.frameElement.getBoundingClientRect().top; - } - let node = box.firstElementChild as HTMLDivElement; - while (node) { - if (node !== source && node.dataset.id) { - const rect = node.getBoundingClientRect(); - - if (rect.height <= 0) continue; - if (y < rect.top + rect.height / 2) { - break; - } - } - node = node.nextElementSibling as HTMLDivElement; - } - return node; - }; - - /** - * find the source node - */ - const getSource = (e: DragEvent) => { - const target = e.target as Element; - if (!target || !box.contains(target) || target === box) { - return null; - } - - let node = box.firstElementChild; - while (node) { - if (node.contains(target)) { - return node; - } - node = node.nextElementSibling; - } - - return null; - }; - - const sort = (beforeId: string | number | null | undefined) => { - if (!source) return; - - const sourceId = (source as HTMLDivElement).dataset.id; - const items = this.items!; - const origIndex = items.findIndex(id => id == sourceId); - - let newIndex = beforeId ? items.findIndex(id => id == beforeId) : items.length; - - if (origIndex < 0 || newIndex < 0) return; - if (this.props.onSort) { - if (newIndex > origIndex) { - newIndex -= 1; - } - if (origIndex === newIndex) return; - const item = items.splice(origIndex, 1); - items.splice(newIndex, 0, item[0]); - - this.props.onSort(items); - } - }; - - const dragstart = (e: DragEvent) => { - isDragEnd = false; - source = getSource(e); - if (!source) { - return false; - } - origRef = source.nextElementSibling; - const rect = source.getBoundingClientRect(); - let dragSource = source; - if (this.props.dragImageSourceHandler) { - dragSource = this.props.dragImageSourceHandler(source); - } - if (e.dataTransfer) { - e.dataTransfer.setDragImage(dragSource, e.clientX - rect.left, e.clientY - rect.top); - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.dropEffect = 'move'; - try { - e.dataTransfer.setData('application/json', {} as any); - } catch (ex) { - // eslint-disable-line - } - } - - setTimeout(() => { - source!.classList.add('lc-dragging'); - }, 0); - return true; - }; - - const placeAt = (beforeRef: Element | null) => { - if (beforeRef) { - if (beforeRef !== source) { - box.insertBefore(source!, beforeRef); - } - } else { - box.appendChild(source!); - } - }; - - const adjust = (e: DragEvent) => { - if (isDragEnd) return; - ref = locate(e); - placeAt(ref); - }; - - let lastDragEvent: DragEvent | null; - const drag = (e: DragEvent) => { - if (!source) return; - e.preventDefault(); - if (lastDragEvent) { - if (lastDragEvent.clientX === e.clientX && lastDragEvent.clientY === e.clientY) { - return; - } - } - lastDragEvent = e; - if (e.dataTransfer) { - e.dataTransfer.effectAllowed = 'move'; - } - adjust(e); - }; - - const dragend = (e: DragEvent) => { - isDragEnd = true; - if (!source) return; - e.preventDefault(); - source.classList.remove('lc-dragging'); - placeAt(origRef); - sort(ref ? (ref as HTMLDivElement).dataset.id : null); - source = null; - ref = null; - origRef = null; - lastDragEvent = null; - }; - - box.addEventListener('dragstart', dragstart); - document.addEventListener('dragover', drag); - document.addEventListener('drag', drag); - document.addEventListener('dragend', dragend); - - this.willDetach = () => { - box.removeEventListener('dragstart', dragstart); - document.removeEventListener('dragover', drag); - document.removeEventListener('drag', drag); - document.removeEventListener('dragend', dragend); - }; - } - - componentWillUnmount() { - if (this.willDetach) { - this.willDetach(); - } - } - - render() { - const { className, itemClassName, children } = this.props; - const items: Array<string | number> = []; - const cards = Children.map(children, child => { - const id = child.key!; - items.push(id); - return ( - <div key={id} data-id={id} className={classNames('lc-sortable-card', itemClassName)}> - {child} - </div> - ); - }); - this.items = items; - - return ( - <div - className={classNames('lc-sortable', className)} - ref={ref => { - this.shell = ref; - }} - > - {cards} - </div> - ); - } -} - -export default Sortable; diff --git a/packages/vision-polyfill/src/skeleton/components/array-setter/style.less b/packages/vision-polyfill/src/skeleton/components/array-setter/style.less deleted file mode 100644 index 8e0da024b..000000000 --- a/packages/vision-polyfill/src/skeleton/components/array-setter/style.less +++ /dev/null @@ -1,103 +0,0 @@ -.lc-setter-list { - [draggable] { - cursor: move; - } - color: var(--color-text); - - .next-btn { - display: inline-flex; - align-items: center; - line-height: 1 !important; - max-width: 100%; - text-overflow: ellipsis; - } - - .lc-setter-list-add { - display: block; - width: 100%; - margin-top: 8px;; - } - - - .lc-setter-list-columns { - display: flex; - > .lc-title { - flex: 1; - justify-content: center; - } - margin-left: 47px; - margin-right: 28px; - margin-bottom: 5px; - } - - .lc-setter-list-scroll-body { - margin: -8px -5px; - padding: 8px 10px; - overflow-y: auto; - max-height: 300px; - } - - .lc-setter-list-card { - border: 1px solid rgba(31,56,88,.2); - background-color: var(--color-block-background-light); - border-radius: 3px; - &:not(:last-child) { - margin-bottom: 5px; - } - - .lc-listitem { - position: relative; - outline: none; - display: flex; - align-items: stretch; - height: 34px; - - .lc-listitem-actions { - margin: 0 3px; - display: inline-flex; - align-items: center; - justify-content: flex-end; - .lc-listitem-action { - text-align: center; - cursor: pointer; - opacity: 0.6; - &:hover { - opacity: 1; - } - } - } - .lc-listitem-body { - flex: 1; - display: flex; - align-items: stretch; - overflow: hidden; - min-width: 0; - text-overflow: ellipsis; - .lc-field { - padding: 0 !important; - display: flex; - align-items: center; - >.lc-field-body { - justify-content: center; - } - } - > * { - width: 100%; - } - .next-btn { - display: block; - width: 100%; - } - } - .lc-listitem-handler { - margin-left: 2px; - display: inline-flex; - align-items: center; - .next-icon-ellipsis { - transform: rotate(90deg); - } - opacity: 0.6; - } - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/field/fields.tsx b/packages/vision-polyfill/src/skeleton/components/field/fields.tsx deleted file mode 100644 index d36928604..000000000 --- a/packages/vision-polyfill/src/skeleton/components/field/fields.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { Component } from 'react'; -import classNames from 'classnames'; -import { Icon } from '@alifd/next'; -import { Title, TitleContent } from '@ali/lowcode-globals'; -import { PopupPipe, PopupContext } from '../popup'; -import './index.less'; - -export interface FieldProps { - className?: string; - title?: TitleContent | null; - defaultDisplay?: 'accordion' | 'inline' | 'block'; - collapsed?: boolean; - onExpandChange?: (expandState: boolean) => void; -} - -export class Field extends Component<FieldProps> { - state = { - collapsed: this.props.collapsed, - display: this.props.defaultDisplay || 'inline', - }; - - private toggleExpand = () => { - const { onExpandChange } = this.props; - const collapsed = !this.state.collapsed; - this.setState({ - collapsed, - }); - onExpandChange && onExpandChange(!collapsed); - }; - private body: HTMLDivElement | null = null; - private dispose?: () => void; - private deployBlockTesting() { - if (this.dispose) { - this.dispose(); - } - const body = this.body; - if (!body) { - return; - } - const check = () => { - const setter = body.firstElementChild; - if (setter && setter.classList.contains('lc-block-setter')) { - this.setState({ - display: 'block', - }); - } else { - this.setState({ - display: 'inline', - }); - } - }; - const observer = new MutationObserver(check); - check(); - observer.observe(body, { - childList: true, - subtree: true, - attributes: true, - attributeFilter: ['class'], - }); - this.dispose = () => observer.disconnect(); - } - componentDidMount() { - const { defaultDisplay } = this.props; - if (!defaultDisplay || defaultDisplay === 'inline') { - this.deployBlockTesting(); - } - } - componentWillUnmount() { - if (this.dispose) { - this.dispose(); - } - } - - render() { - const { className, children, title } = this.props; - const { display, collapsed } = this.state; - const isAccordion = display === 'accordion'; - return ( - <div - className={classNames(`lc-field lc-${display}-field`, className, { - 'lc-field-is-collapsed': isAccordion && collapsed, - })} - > - <div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}> - <div className="lc-field-title"> - <Title title={title || ''} /> - </div> - {isAccordion && <Icon className="lc-field-icon" type="arrow-up" size="xs" />} - </div> - <div key="body" ref={(shell) => (this.body = shell)} className="lc-field-body"> - {children} - </div> - </div> - ); - } -} - -export interface PopupFieldProps extends FieldProps { - width?: number; -} - -export class PopupField extends Component<PopupFieldProps> { - static contextType = PopupContext; - private pipe: any; - - static defaultProps: PopupFieldProps = { - width: 300, - }; - - render() { - const { className, children, title, width } = this.props; - if (!this.pipe) { - this.pipe = (this.context as PopupPipe).create({ width }); - } - - const titleElement = title && ( - <div className="lc-field-title"> - <Title title={title} /> - </div> - ); - - this.pipe.send(<div className="lc-field-body">{children}</div>, titleElement); - - return ( - <div className={classNames('lc-field lc-popup-field', className)}> - {title && ( - <div - className="lc-field-head" - onClick={(e) => { - this.pipe.show((e as any).target); - }} - > - <div className="lc-field-title"> - <Title title={title} /> - </div> - <Icon className="lc-field-icon" type="arrow-left" size="xs" /> - </div> - )} - </div> - ); - } -} - -export interface EntryFieldProps extends FieldProps { - stageName?: string; -} - -export class EntryField extends Component<EntryFieldProps> { - render() { - const { stageName, title, className } = this.props; - const classNameList = classNames('engine-setting-field', 'engine-entry-field', className); - const fieldProps: any = {}; - - if (stageName) { - // 为 stage 切换奠定基础 - fieldProps['data-stage-target'] = stageName; - } - - const innerElements = [ - <span className="engine-field-title" key="field-title"> - {title} - </span>, - // renderTip(tip, { propName }), - // <Icons name="arrow" className="engine-field-arrow" size="12px" key="engine-field-arrow-icon" />, - ]; - - return ( - <div className={classNameList} {...fieldProps}> - {innerElements} - </div> - ); - } -} - -export class PlainField extends Component<FieldProps> { - render() { - const { className, children } = this.props; - return ( - <div className={classNames(`lc-field lc-plain-field`, className)}> - <div className="lc-field-body">{children}</div> - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/field/index.less b/packages/vision-polyfill/src/skeleton/components/field/index.less deleted file mode 100644 index 5fecb74d9..000000000 --- a/packages/vision-polyfill/src/skeleton/components/field/index.less +++ /dev/null @@ -1,154 +0,0 @@ -@import '../variables.less'; - -@x-gap: 10px; -@y-gap: 8px; - -.lc-field { - // head - .lc-field-head { - display: flex; - align-items: center; - justify-content: space-between; - - .lc-field-title { - display: flex; - align-items: center; - } - .lc-field-icon { - margin-right: @x-gap; - transform-origin: center; - transition: transform 0.1s; - } - } - - &.lc-plain-field { - // for top-level style - padding: 8px 10px; - > .lc-field-body { - flex: 1; - min-width: 0; - display: flex; - align-items: center; - } - } - - &.lc-inline-field { - display: flex; - align-items: center; - // for top-level style - padding: 8px 10px; - - > .lc-field-head { - width: 70px; - margin-right: 1px; - .lc-title-label { - width: 70px; - word-break: break-all; - } - } - > .lc-field-body { - flex: 1; - min-width: 0; - display: flex; - align-items: center; - } - } - - &.lc-block-field, &.lc-accordion-field { - display: block; - &:not(:first-child) { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); - } - > .lc-field-head { - padding-left: @x-gap; - height: 32px; - display: flex; - align-items: center; - font-weight: 500; - background: var(--color-block-background-shallow, rgba(31,56,88,.06)); - border-bottom: 1px solid var(--color-line-normal, @dark-alpha-2); - color: var(--color-title, @white-alpha-2); - user-select: none; - } - - > .lc-field-body { - padding: @y-gap @x-gap/2; - } - - + .lc-inline-field { - border-top: 1px solid var(--color-line-normal, @dark-alpha-2); - } - } - - .lc-setter-actions { - display: flex; - align-items: center; - } - - &.lc-block-field { - position: relative; - >.lc-field-body>.lc-block-setter>.lc-setter-actions { - position: absolute; - right: 10px; - top: 0; - height: 32px; - display: flex; - align-items: center; - } - } - - &.lc-accordion-field { - // collapsed - &.lc-field-is-collapsed { - > .lc-field-head .lc-field-icon { - transform: rotate(180deg); - } - > .lc-field-body { - display: none; - } - } - - // 邻近的保持上下距离 - + .lc-field { - margin-top: @y-gap; - } - } - - // 2rd level reset - .lc-field-body { - .lc-inline-field { - padding: @y-gap @x-gap/2 0 @x-gap/2; - &:first-child { - padding-top: 0; - } - + .lc-accordion-field, +.lc-block-field { - margin-top: @y-gap; - } - } - - .lc-field { - border-top: none !important; - } - - .lc-accordion-field, .lc-block-field { - > .lc-field-head { - padding-left: @x-gap/2; - background: var(--color-block-background-light); - border-bottom-color: var(--color-line-light); - > .lc-field-icon { - margin-right: @x-gap/2; - } - } - } - - // 3rd level field title width should short - .lc-field-body .lc-inline-field { - > .lc-field-head { - width: 50px; - .lc-title-label { - width: 50px; - } - } - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/field/index.ts b/packages/vision-polyfill/src/skeleton/components/field/index.ts deleted file mode 100644 index 2f50d53ff..000000000 --- a/packages/vision-polyfill/src/skeleton/components/field/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { TitleContent } from '@ali/lowcode-globals'; -import './index.less'; -import { Field, PopupField, EntryField, PlainField } from './fields'; - -export interface FieldProps { - className?: string; - title?: TitleContent | null; - display?: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry'; - collapsed?: boolean; - onExpandChange?: (collapsed: boolean) => void; - [extra: string]: any; -} - -export function createField(props: FieldProps, children: ReactNode, type?: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry') { - if (type === 'popup') { - return createElement(PopupField, props, children); - } - if (type === 'entry') { - return createElement(EntryField, props, children); - } - if (type === 'plain' || !props.title) { - return createElement(PlainField, props, children); - } - return createElement(Field, { ...props, defaultDisplay: type }, children); -} - -export { Field, PopupField, EntryField, PlainField }; diff --git a/packages/vision-polyfill/src/skeleton/components/mixed-setter/index.tsx b/packages/vision-polyfill/src/skeleton/components/mixed-setter/index.tsx deleted file mode 100644 index 5217322c2..000000000 --- a/packages/vision-polyfill/src/skeleton/components/mixed-setter/index.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import React, { Component, isValidElement } from 'react'; -import classNames from 'classnames'; -import { Dropdown, Button, Menu } from '@alifd/next'; -import { - getSetter, - getSettersMap, - SetterConfig, - computed, - obx, - CustomView, - DynamicProps, - DynamicSetter, - TitleContent, - isSetterConfig, - Title, - createSetterContent, - observer, - isDynamicSetter, - shallowIntl, - EmbedTip, - isI18nData, -} from '@ali/lowcode-globals'; -import { IconConvert } from '../../icons/convert'; - -import './style.less'; -import { SettingField } from '@ali/lowcode-designer'; - -export interface SetterItem { - name: string; - title: TitleContent; - setter: string | DynamicSetter | CustomView; - props?: object | DynamicProps; - condition?: (field: SettingField) => boolean; - initialValue?: any | ((field: SettingField) => any); - list: boolean; -} - -function nomalizeSetters(setters?: Array<string | SetterConfig | CustomView | DynamicSetter>): SetterItem[] { - if (!setters) { - const normalized: SetterItem[] = []; - getSettersMap().forEach((setter, name) => { - if (name === 'MixedSetter') { - return; - } - normalized.push({ - name, - title: setter.title || name, - setter: name, - condition: setter.condition, - initialValue: setter.initialValue, - list: setter.recommend || false, - }); - }); - return normalized; - } - const names: string[] = []; - function generateName(n: string) { - let idx = 1; - let got = n; - while (names.indexOf(got) > -1) { - got = `${n}:${idx++}`; - } - names.push(got); - return got; - } - return setters.map((setter) => { - const config: any = { - setter, - list: true, - }; - if (isSetterConfig(setter)) { - config.setter = setter.componentName; - config.props = setter.props; - config.condition = setter.condition; - config.initialValue = setter.initialValue; - config.title = setter.title; - } - if (typeof config.setter === 'string') { - config.name = config.setter; - names.push(config.name); - const info = getSetter(config.setter); - if (!config.title) { - config.title = info?.title || config.setter; - } - if (!config.condition) { - config.condition = info?.condition; - } - if (!config.initialValue) { - config.initialValue = info?.initialValue; - } - } else { - config.name = generateName((config.setter as any).displayName || (config.setter as any).name || 'CustomSetter'); - if (!config.title) { - config.title = config.name; - } - } - return config; - }); -} - -@observer -export default class MixedSetter extends Component<{ - field: SettingField; - setters?: Array<string | SetterConfig | CustomView | DynamicSetter>; - onSetterChange?: (field: SettingField, name: string) => void; - onChange?: (val: any) => void; - value?: any; - className?: string; -}> { - private setters = nomalizeSetters(this.props.setters); - @obx.ref private used?: string; - @computed private getCurrentSetter() { - const { field } = this.props; - let firstMatched: SetterItem | undefined; - for (const setter of this.setters) { - const matched = !setter.condition || setter.condition(field); - if (matched) { - if (setter.name === this.used) { - return setter; - } - if (!firstMatched) { - firstMatched = setter; - } - } - } - return firstMatched; - } - - private useSetter = (name: string) => { - if (name === this.used) { - return; - } - const { field, onChange } = this.props; - const setter = this.setters.find((item) => item.name === name); - this.used = name; - if (setter) { - let newValue: any = setter.initialValue; - if (newValue && typeof newValue === 'function') { - newValue = newValue(field); - } - onChange && onChange(newValue); - } - }; - - private shell: HTMLDivElement | null = null; - private checkIsBlockField() { - if (this.shell) { - const setter = this.shell.firstElementChild; - if (setter && setter.classList.contains('lc-block-setter')) { - this.shell.classList.add('lc-block-setter'); - } else { - this.shell.classList.remove('lc-block-setter'); - } - } - } - componentDidUpdate() { - this.checkIsBlockField(); - } - componentDidMount() { - this.checkIsBlockField(); - } - - render() { - const { className, field, setters, onSetterChange, ...restProps } = this.props; - - const currentSetter = this.getCurrentSetter(); - const isTwoType = this.setters.length < 3; - - let setterContent: any; - const triggerTitle: any = { - tip: { - type: 'i18n', - 'zh-CN': '切换格式', - 'en-US': 'Switch Format', - }, - icon: <IconConvert size={24} />, - }; - if (currentSetter) { - const { setter, title, props } = currentSetter; - let setterProps: any = {}; - let setterType: any; - if (isDynamicSetter(setter)) { - setterType = setter.call(field, field); - } else { - setterType = setter; - } - if (props) { - setterProps = props; - if (typeof setterProps === 'function') { - setterProps = setterProps(field); - } - } - - setterContent = createSetterContent(setterType, { - ...shallowIntl(setterProps), - field, - ...restProps, - }); - if (title) { - if (typeof title !== 'object' || isI18nData(title) || isValidElement(title)) { - triggerTitle.tip = title; - } else { - triggerTitle.tip = title.tip || title.label; - } - } - } else { - // 未匹配的 null 值,显示 NullValue 空值 - // 未匹配的 其它 值,显示 InvalidValue 非法值 - if (restProps.value == null) { - setterContent = <span>NullValue</span>; - } else { - setterContent = <span>InvalidValue</span>; - } - } - const usedName = currentSetter?.name || this.used; - let moreBtnNode = ( - <Title - title={triggerTitle} - className="lc-switch-trigger" - onClick={ - isTwoType - ? () => { - if (this.setters[0]?.name === usedName) { - this.useSetter(this.setters[1]?.name); - } else { - this.useSetter(this.setters[0]?.name); - } - } - : undefined - } - /> - ); - if (!isTwoType) { - moreBtnNode = ( - <Dropdown trigger={moreBtnNode} triggerType="click" align="tr br"> - <Menu selectMode="single" hasSelectedIcon={true} selectedKeys={usedName} onItemClick={this.useSetter}> - {this.setters.filter(setter => setter.list || setter.name === usedName).map((setter) => { - return ( - <Menu.Item key={setter.name}> - <Title title={setter.title} /> - </Menu.Item> - ); - })} - </Menu> - </Dropdown> - ); - } - - return ( - <div ref={(shell) => (this.shell = shell)} className={classNames('lc-setter-mixed', className)}> - {setterContent} - - <div className="lc-setter-actions">{moreBtnNode}</div> - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/mixed-setter/style.less b/packages/vision-polyfill/src/skeleton/components/mixed-setter/style.less deleted file mode 100644 index 6efebb28c..000000000 --- a/packages/vision-polyfill/src/skeleton/components/mixed-setter/style.less +++ /dev/null @@ -1,30 +0,0 @@ -.lc-setter-mixed { - flex: 1; - min-width: 0; - margin-right: 26px; - display: block; - position: relative; - >.lc-setter-actions { - position: absolute; - right: -2px; - top: 50%; - transform: translate(100%, -50%); - .lc-switch-trigger { - cursor: pointer; - opacity: 0.6; - &:hover { - opacity: 1; - } - } - } - .next-input,.next-date-picker { - width: 100%; - } - &.lc-block-setter { - position: static; - margin-right: 0; - >.lc-setter-actions { - transform: none; - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/object-setter/index.tsx b/packages/vision-polyfill/src/skeleton/components/object-setter/index.tsx deleted file mode 100644 index 2f84c8adb..000000000 --- a/packages/vision-polyfill/src/skeleton/components/object-setter/index.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { Component, Fragment } from 'react'; -import { Icon, Button } from '@alifd/next'; -import { Title, SetterType, FieldConfig } from '@ali/lowcode-globals'; -import { createSettingFieldView } from '../../settings/settings-pane'; -import { PopupContext, PopupPipe } from '../../popup'; -import { SettingField } from '@ali/lowcode-designer'; -import './style.less'; - -export default class ObjectSetter extends Component<{ - field: SettingField; - descriptor?: string | ((rowField: SettingField) => string); - config: ObjectSetterConfig; - mode?: 'popup' | 'form'; - // 1: in tablerow 2: in listrow 3: in column-cell - forceInline?: number; -}> { - render() { - const { mode, forceInline = 0, ...props } = this.props; - if (forceInline || mode === 'popup') { - if (forceInline > 2 || mode === 'popup') { - // popup - return <RowSetter {...props} primaryButton={forceInline ? false : true} />; - } else { - return <RowSetter columns={forceInline > 1 ? 2 : 4} {...props} />; - } - } else { - // form - return <FormSetter {...props} />; - } - } -} - -interface ObjectSetterConfig { - items?: FieldConfig[]; - extraSetter?: SetterType; -} - -interface RowSetterProps { - field: SettingField; - descriptor?: string | ((rowField: SettingField) => string); - config: ObjectSetterConfig; - columns?: number; - primaryButton?: boolean; -} - -class RowSetter extends Component<RowSetterProps> { - static contextType = PopupContext; - - state: any = { - descriptor: '', - }; - - private items?: SettingField[]; - constructor(props: RowSetterProps) { - super(props); - const { config, descriptor, field, columns } = props; - const items: SettingField[] = []; - if (columns && config.items) { - const l = Math.min(config.items.length, columns); - for (let i = 0; i < l; i++) { - const conf = config.items[i]; - if (conf.isRequired || conf.important || (conf.setter as any)?.isRequired) { - const item = field.createField({ - ...conf, - // in column-cell - forceInline: 3, - }); - items.push(item); - } - } - } - - if (items.length > 0) { - this.items = items; - } - - let firstRun: boolean = true; - field.onEffect(() => { - let state: any = {}; - if (descriptor) { - if (typeof descriptor === 'function') { - state.descriptor = descriptor(field); - } else { - state.descriptor = field.getPropValue(descriptor); - } - } else { - state.descriptor = field.title; - } - - if (firstRun) { - firstRun = false; - this.state = state; - } else { - this.setState(state); - } - }); - } - - shouldComponentUpdate(_: any, nextState: any) { - if (this.state.decriptor !== nextState.decriptor) { - return true; - } - return false; - } - - private pipe: any; - render() { - const items = this.items; - const { field, primaryButton, config } = this.props; - - if (!this.pipe) { - this.pipe = (this.context as PopupPipe).create({ width: 320 }); - } - - const title = ( - <Fragment> - 编辑: - <Title title={this.state.descriptor} /> - </Fragment> - ); - - this.pipe.send(<FormSetter key={field.id} field={field} config={config} />, title); - - if (items) { - return ( - <div className="lc-setter-object-row"> - <div - className="lc-setter-object-row-edit" - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon size="small" type="edit" /> - </div> - <div className="lc-setter-object-row-body">{items.map((item) => createSettingFieldView(item, field))}</div> - </div> - ); - } - - return ( - <Button - type={primaryButton === false ? 'normal' : 'primary'} - onClick={(e) => { - this.pipe.show((e as any).target, field.id); - }} - > - <Icon type="edit" /> - {title} - </Button> - ); - } -} - -interface FormSetterProps { - field: SettingField; - config: ObjectSetterConfig; -} -class FormSetter extends Component<FormSetterProps> { - private items: SettingField[]; - constructor(props: RowSetterProps) { - super(props); - const { config, field } = props; - this.items = (config.items || []).map((conf) => field.createField(conf)); - - // TODO: extraConfig for custom fields - } - - shouldComponentUpdate() { - return false; - } - - render() { - const { field } = this.props; - return ( - <div className="lc-setter-object lc-block-setter"> - {this.items.map((item, index) => createSettingFieldView(item, field, index))} - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/object-setter/style.less b/packages/vision-polyfill/src/skeleton/components/object-setter/style.less deleted file mode 100644 index 6d6064df1..000000000 --- a/packages/vision-polyfill/src/skeleton/components/object-setter/style.less +++ /dev/null @@ -1,31 +0,0 @@ -.lc-setter-object-row { - display: flex; - align-items: stretch; - width: 100%; - .lc-setter-object-row-edit { - width: 20px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - } - .lc-setter-object-row-body { - display: flex; - flex: 1; - min-width: 0; - align-items: center; - .lc-field { - padding: 0 !important; - .lc-field-body { - padding: 0 !important; margin: 0 !important; - } - } - > * { - flex: 1; - flex-shrink: 1; - margin-left: 2px; - min-width: 0; - overflow: hidden; - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/popup/index.tsx b/packages/vision-polyfill/src/skeleton/components/popup/index.tsx deleted file mode 100644 index 503e986f9..000000000 --- a/packages/vision-polyfill/src/skeleton/components/popup/index.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { createContext, ReactNode, Component, PureComponent } from 'react'; -import { EventEmitter } from 'events'; -import { Balloon } from '@alifd/next'; -import { uniqueId } from '@ali/lowcode-globals'; -import './style.less'; - -export const PopupContext = createContext<PopupPipe>({} as any); - -export class PopupPipe { - private emitter = new EventEmitter(); - private currentId?: string; - - create(props?: object): { send: (content: ReactNode, title: ReactNode) => void; show: (target: Element) => void } { - let sendContent: ReactNode = null; - let sendTitle: ReactNode = null; - const id = uniqueId('popup'); - return { - send: (content: ReactNode, title: ReactNode) => { - sendContent = content; - sendTitle = title; - if (this.currentId === id) { - this.popup({ - ...props, - content, - title, - }); - } - }, - show: (target: Element, actionKey?: string) => { - this.currentId = id; - this.popup( - { - ...props, - actionKey, - content: sendContent, - title: sendTitle, - }, - target, - ); - }, - }; - } - - private popup(props: object, target?: Element) { - Promise.resolve().then(() => { - this.emitter.emit('popupchange', props, target); - }); - } - - onPopupChange(fn: (props: object, target?: Element) => void): () => void { - this.emitter.on('popupchange', fn); - return () => { - this.emitter.removeListener('popupchange', fn); - }; - } - - purge() { - this.emitter.removeAllListeners(); - } -} - -export default class PopupService extends Component<{ actionKey?: string; safeId?: string }> { - private popupPipe = new PopupPipe(); - - componentWillUnmount() { - this.popupPipe.purge(); - } - - render() { - const { children, actionKey, safeId } = this.props; - return ( - <PopupContext.Provider value={this.popupPipe}> - {children} - <PopupContent key={'pop' + actionKey} safeId={safeId} /> - </PopupContext.Provider> - ); - } -} - -export class PopupContent extends PureComponent<{ safeId?: string }> { - static contextType = PopupContext; - state: any = { - visible: false, - pos: {}, - }; - - private dispose = (this.context as PopupPipe).onPopupChange((props, target) => { - const state: any = { - ...props, - visible: true, - }; - if (target) { - const rect = target.getBoundingClientRect(); - state.pos = { - top: rect.top, - height: rect.height, - }; - // todo: compute the align method - } - this.setState(state); - }); - - componentWillUnmount() { - this.dispose(); - } - - render() { - const { content, visible, width, title, pos, actionKey } = this.state; - if (!visible) { - return null; - } - let avoidLaterHidden = true; - setTimeout(() => { - avoidLaterHidden = false; - }, 10); - - const id = uniqueId('ball'); - - return ( - <Balloon - className="lc-ballon" - align="l" - id={this.props.safeId} - safeNode={id} - visible={visible} - style={{ width }} - onVisibleChange={(visible) => { - if (avoidLaterHidden) { - return; - } - if (!visible) { - this.setState({ visible: false }); - } - }} - trigger={<div className="lc-popup-placeholder" style={pos} />} - triggerType="click" - animation={false} - // needAdjust - shouldUpdatePosition - > - <div className="lc-ballon-title">{title}</div> - <div className="lc-ballon-content"> - <PopupService actionKey={actionKey} safeId={id}> - {content} - </PopupService> - </div> - </Balloon> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/popup/style.less b/packages/vision-polyfill/src/skeleton/components/popup/style.less deleted file mode 100644 index b115fd371..000000000 --- a/packages/vision-polyfill/src/skeleton/components/popup/style.less +++ /dev/null @@ -1,22 +0,0 @@ -.lc-popup-placeholder { - position: fixed; - width: 100%; - pointer-events: none; -} - -.lc-ballon { - padding: 10px; - max-width: 640px; - width: 640px; - .lc-ballon-title { - font-size: 14px; - } - .lc-ballon-content { - margin-top: 10px; - // width: 300px; - } - .next-balloon-close { - top: 4px; - right: 4px; - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/register.ts b/packages/vision-polyfill/src/skeleton/components/register.ts deleted file mode 100644 index 3c096aa82..000000000 --- a/packages/vision-polyfill/src/skeleton/components/register.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { registerSetter, isPlainObject } from '@ali/lowcode-globals'; -import ArraySetter from './array-setter'; -import ObjectSetter from './settings-pane/src/setters/object-setter'; -import MixedSetter from './mixed-setter'; - -registerSetter('ArraySetter', { - component: ArraySetter, - defaultProps: {}, - title: 'ArraySetter', // TODO - condition: (field: any) => { - const v = field.getValue(); - return v == null || Array.isArray(v); - }, - initialValue: [], - recommend: true, -}); -registerSetter('ObjectSetter', { - component: ObjectSetter, - // todo: defaultProps - defaultProps: {}, - title: 'ObjectSetter', // TODO - condition: (field: any) => { - const v = field.getValue(); - return v == null || isPlainObject(v); - }, - initialValue: {}, - recommend: true, -}); -registerSetter('MixedSetter', MixedSetter); diff --git a/packages/vision-polyfill/src/skeleton/components/settings/index.ts b/packages/vision-polyfill/src/skeleton/components/settings/index.ts deleted file mode 100644 index f51b7b704..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createSettingFieldView } from './settings-pane'; -import './transducers/register'; -import '../../register'; -import './style.less'; -import SettingsMainView from './settings-primary-view'; - -export default SettingsMainView; - -export { createSettingFieldView }; diff --git a/packages/vision-polyfill/src/skeleton/components/settings/main.ts b/packages/vision-polyfill/src/skeleton/components/settings/main.ts deleted file mode 100644 index f752add28..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/main.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { EventEmitter } from 'events'; -import { obx, computed } from '@ali/lowcode-globals'; -import { Node, Designer, Selection, SettingTopEntry } from '@ali/lowcode-designer'; -import { getTreeMaster } from '@ali/lowcode-plugin-outline-pane'; -import Editor from '@ali/lowcode-editor-core'; - -function generateSessionId(nodes: Node[]) { - return nodes - .map((node) => node.id) - .sort() - .join(','); -} - -export class SettingsMain { - private emitter = new EventEmitter(); - private _sessionId = ''; - @obx.ref private _settings?: SettingTopEntry; - - @computed get length(): number | undefined { - return this._settings?.nodes.length; - } - - @computed get componentMeta() { - return this._settings?.componentMeta; - } - - get settings() { - return this._settings; - } - - private disposeListener: () => void; - - private designer?: Designer; - - constructor(readonly editor: Editor) { - this.init(); - } - - private async init() { - const setupSelection = (selection?: Selection) => { - if (selection) { - this.setup(selection.getNodes()); - } else { - this.setup([]); - } - }; - this.editor.on('designer.selection.change', setupSelection); - this.disposeListener = () => { - this.editor.removeListener('designer.selection.change', setupSelection); - }; - const designer = await this.editor.onceGot(Designer); - this.designer = designer; - getTreeMaster(designer).onceEnableBuiltin(() => { - this.emitter.emit('outline-visible'); - }); - setupSelection(designer.currentSelection); - } - - private setup(nodes: Node[]) { - // check nodes change - const sessionId = generateSessionId(nodes); - if (sessionId === this._sessionId) { - return; - } - this._sessionId = sessionId; - if (nodes.length < 1) { - this._settings = undefined; - return; - } - - if (!this.designer) { - this.designer = nodes[0].document.designer; - } - - 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() { - this.disposeListener(); - this.emitter.removeAllListeners(); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/settings/package.json b/packages/vision-polyfill/src/skeleton/components/settings/package.json deleted file mode 100644 index 2a0fab24e..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "@ali/lowcode-plugin-settings-pane", - "version": "0.8.10", - "description": "Settings pane for Ali lowCode engine", - "files": [ - "es", - "lib" - ], - "main": "lib/index.js", - "module": "es/index.js", - "scripts": { - "build": "build-scripts build --skip-demo", - "test": "ava", - "test:snapshot": "ava --update-snapshots" - }, - "dependencies": { - "@ali/lowcode-designer": "^0.9.2", - "@ali/lowcode-editor-core": "^0.8.5", - "@ali/lowcode-globals": "^0.9.2", - "@ali/lowcode-plugin-outline-pane": "^0.8.8", - "@ali/ve-stage-box": "^4.0.0", - "@alifd/next": "^1.19.16", - "classnames": "^2.2.6", - "react": "^16" - }, - "devDependencies": { - "@alib/build-scripts": "^0.1.18", - "@types/classnames": "^2.2.7", - "@types/node": "^13.7.1", - "@types/react": "^16", - "build-plugin-component": "^0.2.10", - "build-plugin-fusion": "^0.1.1", - "build-plugin-moment-locales": "^0.1.0" - }, - "ava": { - "compileEnhancements": false, - "snapshotDir": "test/fixtures/__snapshots__", - "extensions": [ - "ts" - ], - "require": [ - "ts-node/register" - ] - }, - "license": "MIT", - "publishConfig": { - "registry": "https://registry.npm.alibaba-inc.com" - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/settings/settings-pane.tsx b/packages/vision-polyfill/src/skeleton/components/settings/settings-pane.tsx deleted file mode 100644 index 11edc8a4c..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/settings-pane.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { Component } from 'react'; -import { - createContent, - CustomView, - intl, - shallowIntl, - isSetterConfig, - createSetterContent, - observer, -} from '@ali/lowcode-globals'; -import { Field, createField } from '../field'; -import PopupService from '../popup'; -import { SettingField, isSettingField, SettingTopEntry, SettingEntry } from '@ali/lowcode-designer'; - -@observer -class SettingFieldView extends Component<{ field: SettingField }> { - render() { - const { field } = this.props; - const { extraProps } = field; - const { condition, defaultValue } = extraProps; - const visible = field.isSingle && typeof condition === 'function' ? condition(field) !== false : true; - if (!visible) { - return null; - } - const { setter } = field; - - let setterProps: any = {}; - let setterType: any; - if (Array.isArray(setter)) { - setterType = 'MixedSetter'; - setterProps = { - setters: setter, - }; - } else if (isSetterConfig(setter)) { - setterType = setter.componentName; - if (setter.props) { - setterProps = setter.props; - if (typeof setterProps === 'function') { - setterProps = setterProps(field); - } - } - } else if (setter) { - setterType = setter; - } - let value = null; - if (field.type === 'field') { - if (defaultValue != null && !('defaultValue' in setterProps)) { - setterProps.defaultValue = defaultValue; - } - if (field.valueState > 0) { - value = field.getValue(); - } else { - setterProps.multiValue = true; - if (!('placeholder' in setterProps)) { - // FIXME! move to locale file - setterProps.placeholder = intl({ - type: 'i18n', - 'zh-CN': '多种值', - 'en-US': 'Multiple Value', - }); - } - } - } - - // todo: error handling - - return createField({ - title: field.title, - collapsed: !field.expanded, - onExpandChange: (expandState) => field.setExpanded(expandState), - }, createSetterContent(setterType, { - ...shallowIntl(setterProps), - forceInline: extraProps.forceInline, - key: field.id, - // === injection - prop: field, // for compatible vision - field, - // === IO - value, // reaction point - onChange: (value: any) => { - this.setState({ - value, - }); - field.setValue(value); - }, - }), extraProps.forceInline ? 'plain' : extraProps.display); - } -} - -@observer -class SettingGroupView extends Component<{ field: SettingField }> { - shouldComponentUpdate() { - return false; - } - - render() { - const { field } = this.props; - const { extraProps } = field; - const { condition } = extraProps; - const visible = field.isSingle && typeof condition === 'function' ? condition(field) !== false : true; - - if (!visible) { - return null; - } - - // todo: split collapsed state | field.items for optimize - return ( - <Field defaultDisplay="accordion" title={field.title} collapsed={!field.expanded} onExpandChange={(expandState) => { - field.setExpanded(expandState); - }}> - {field.items.map((item, index) => createSettingFieldView(item, field, index))} - </Field> - ); - } -} - -export function createSettingFieldView(item: SettingField | CustomView, field: SettingEntry, index?: number) { - if (isSettingField(item)) { - if (item.isGroup) { - return <SettingGroupView field={item} key={item.id} />; - } else { - return <SettingFieldView field={item} key={item.id} />; - } - } else { - return createContent(item, { key: index, field }); - } -} - -@observer -export default class SettingsPane extends Component<{ target: SettingTopEntry | SettingField }> { - shouldComponentUpdate() { - return false; - } - - render() { - const { target } = this.props; - const items = target.items - return ( - <div className="lc-settings-pane"> - {/* todo: add head for single use */} - <PopupService> - <div className="lc-settings-content"> - {items.map((item, index) => createSettingFieldView(item, target, index))} - </div> - </PopupService> - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/settings/settings-primary-view.tsx b/packages/vision-polyfill/src/skeleton/components/settings/settings-primary-view.tsx deleted file mode 100644 index caf45bc22..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/settings-primary-view.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { Component, PureComponent } from 'react'; -import { Tab, Breadcrumb } from '@alifd/next'; -import { Title, createIcon, observer } from '@ali/lowcode-globals'; -import { Node, isSettingField, SettingField } from '@ali/lowcode-designer'; -import Editor from '@ali/lowcode-editor-core'; -import { SettingsMain } from './main'; -import SettingsPane from './settings-pane'; - -@observer -export default class SettingsMainView extends Component<{ editor: Editor }> { - private main = new SettingsMain(this.props.editor); - - shouldComponentUpdate() { - return false; - } - - componentWillUnmount() { - this.main.purge(); - } - - renderBreadcrumb() { - const { settings } = this.main; - if (!settings) { - return null; - } - if (settings.isMultiple) { - return ( - <div className="lc-settings-navigator"> - {createIcon(settings.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} - <Title title={settings.componentMeta!.title} /> - <span>x {settings.nodes.length}</span> - </div> - ); - } - - let node: Node | null = settings.first; - const items = []; - let l = 3; - while (l-- > 0 && node) { - const props = - l === 2 - ? {} - : { - onMouseOver: hoverNode.bind(null, node, true), - onMouseOut: hoverNode.bind(null, node, false), - onClick: selectNode.bind(null, node), - }; - items.unshift(<Breadcrumb.Item {...props} key={node.id}><Title title={node.title} /></Breadcrumb.Item>); - node = node.parent; - } - - return ( - <div className="lc-settings-navigator"> - {createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} - <Breadcrumb className="lc-settings-node-breadcrumb">{items}</Breadcrumb> - </div> - ); - } - - render() { - const { settings } = this.main; - if (!settings) { - // 未选中节点,提示选中 或者 显示根节点设置 - return ( - <div className="lc-settings-main"> - <div className="lc-settings-notice"> - <p>请在左侧画布选中节点</p> - </div> - </div> - ); - } - - if (!settings.isSameComponent) { - // todo: future support 获取设置项交集编辑 - return ( - <div className="lc-settings-main"> - <div className="lc-settings-notice"> - <p>请选中同一类型节点编辑</p> - </div> - </div> - ); - } - - const { items } = settings; - if (items.length > 5 || items.some(item => !isSettingField(item) || !item.isGroup)) { - return ( - <div className="lc-settings-main"> - {this.renderBreadcrumb()} - <div className="lc-settings-body"> - <SettingsPane target={settings} /> - </div> - </div> - ); - } - - return ( - <div className="lc-settings-main"> - <Tab - navClassName="lc-settings-tabs" - animation={false} - excessMode="dropdown" - contentClassName="lc-settings-tabs-content" - extra={this.renderBreadcrumb()} - > - {(items as SettingField[]).map(field => ( - <Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}> - <SettingsPane target={field} key={field.id} /> - </Tab.Item> - ))} - </Tab> - </div> - ); - } -} - -function hoverNode(node: Node, flag: boolean) { - node.hover(flag); -} -function selectNode(node: Node) { - node.select(); -} diff --git a/packages/vision-polyfill/src/skeleton/components/settings/style.less b/packages/vision-polyfill/src/skeleton/components/settings/style.less deleted file mode 100644 index 9b2c2b403..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/style.less +++ /dev/null @@ -1,124 +0,0 @@ -.lc-settings-main { - position: relative; - height: 100%; - overflow: hidden; - - .lc-settings-notice { - text-align: center; - font-size: 12px; - font-family: PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica,Arial,sans-serif; - color: var(--color-text ,rgba(0,0,0,.6)); - padding: 50px 15px 0; - } - - .lc-settings-navigator { - height: 30px; - display: flex; - align-items: center; - padding-left: 5px; - border-bottom: 1px solid var(--color-line-normal); - .lc-settings-navigator-icon { - width: 16px; - height: 16px; - * { - fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4)); - } - } - .lc-settings-node-breadcrumb { - margin-left: 5px; - .next-breadcrumb { - display: inline-flex; - align-items: stretch; - height: 24px; - } - .next-breadcrumb-item { - display: inline-flex; - align-items: center; - cursor: default; - &:not(:last-child):hover { - cursor: pointer; - } - .next-breadcrumb-text { - font-size: 12px; - } - } - } - } - - .lc-settings-body { - position: absolute; - top: 30px; - right: 0; - left: 0; - bottom: 0; - overflow-y: auto; - } - - // ====== reset fusion-tabs ===== - .lc-settings-tabs { - position: relative; - overflow: visible; - > .next-tabs-nav-extra { - position: absolute !important; - top: 40px !important; - left: 0 !important; - height: 30px; - right: 0; - transform: none !important; - - } - .next-tabs-nav-container { - .next-tabs-nav { - display: flex; - .next-tabs-tab.lc-settings-tab-item { - flex: 1; - min-width: 0; - outline: none; - .next-tabs-tab-inner { - text-align: center; - padding: 12px 0; - } - } - } - } - } - - .lc-settings-tabs-content { - position: absolute; - top: 70px; - left:0; - right: 0; - bottom: 0; - .next-tabs-tabpane { - position: absolute; - top: 0; - right: 0; - left: 0; - bottom: 0; - overflow-y: auto; - outline: none !important; - box-shadow: none !important; - } - } - .lc-outline-pane { - position: absolute; - z-index: 100; - background-color: white; - top: 0; - bottom: 0; - display: none; - } -} - -.lc-settings-pane { - padding-bottom: 50px; - .next-btn { - line-height: 1 !important; - } -} - -html.lc-cursor-dragging:not(.lowcode-has-fixed-tree) { - .lc-settings-main .lc-outline-pane { - display: block; - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/settings/utils.js b/packages/vision-polyfill/src/skeleton/components/settings/utils.js deleted file mode 100644 index b8f5bbdcc..000000000 --- a/packages/vision-polyfill/src/skeleton/components/settings/utils.js +++ /dev/null @@ -1,41 +0,0 @@ -function getHotterFromSetter(setter) { - return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line -} - -function getTransducerFromSetter(setter) { - return setter && ( - setter.transducer || setter.Transducer - || (setter.type && (setter.type.transducer || setter.type.Transducer)) - ) || null; // eslint-disable-line -} - -function combineTransducer(transducer, arr, context) { - if (!transducer && Array.isArray(arr)) { - const [toHot, toNative] = arr; - transducer = { toHot, toNative }; - } - - return { - toHot: (transducer && transducer.toHot || (x => x)).bind(context), // eslint-disable-line - toNative: (transducer && transducer.toNative || (x => x)).bind(context), // eslint-disable-line - }; -} - -export class Transducer { - constructor(context, config) { - this.setterTransducer = combineTransducer( - getTransducerFromSetter(config.setter), - getHotterFromSetter(config.setter), - context, - ); - this.context = context; - } - - toHot(data) { - return this.setterTransducer.toHot(data); - } - - toNative(data) { - return this.setterTransducer.toNative(data); - } -} diff --git a/packages/vision-polyfill/src/skeleton/components/widget-views.tsx b/packages/vision-polyfill/src/skeleton/components/widget-views.tsx deleted file mode 100644 index 6d32600b1..000000000 --- a/packages/vision-polyfill/src/skeleton/components/widget-views.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import { Component, ReactElement } from 'react'; -import classNames from 'classnames'; -import { Title, observer } from '@ali/lowcode-globals'; -import { DockProps } from '../types'; -import PanelDock from '../widget/panel-dock'; -import { composeTitle } from '../widget/utils'; -import WidgetContainer from '../widget/widget-container'; -import Panel from '../widget/panel'; -import { IWidget } from '../widget/widget'; -import { SkeletonEvents } from '../skeleton'; - -export function DockView({ title, icon, description, size, className, onClick }: DockProps) { - return ( - <Title - title={composeTitle(title, icon, description)} - className={classNames('lc-dock', className, { - [`lc-dock-${size}`]: size, - })} - onClick={onClick} - /> - ); -} - -@observer -export class PanelDockView extends Component<DockProps & { dock: PanelDock }> { - componentDidMount() { - this.checkActived(); - } - componentDidUpdate() { - this.checkActived(); - } - private lastActived: boolean = false; - checkActived() { - const { dock } = this.props; - if (dock.actived !== this.lastActived) { - this.lastActived = dock.actived; - if (this.lastActived) { - dock.skeleton.postEvent(SkeletonEvents.PANEL_DOCK_ACTIVE, dock.name, dock); - } else { - dock.skeleton.postEvent(SkeletonEvents.PANEL_DOCK_UNACTIVE, dock.name, dock); - } - } - } - - render() { - const { dock, className, onClick, ...props } = this.props; - return DockView({ - ...props, - className: classNames(className, { - actived: dock.actived, - }), - onClick: () => { - onClick && onClick(); - dock.togglePanel(); - }, - }); - } -} - -export class DialogDockView extends Component { - -} - -@observer -export class TitledPanelView extends Component<{ panel: Panel }> { - shouldComponentUpdate() { - return false; - } - componentDidMount() { - this.checkVisible(); - } - componentDidUpdate() { - this.checkVisible(); - } - private lastVisible: boolean = false; - checkVisible() { - const { panel } = this.props; - const currentVisible = panel.inited && panel.visible; - if (currentVisible !== this.lastVisible) { - this.lastVisible = currentVisible; - if (this.lastVisible) { - panel.skeleton.postEvent(SkeletonEvents.PANEL_SHOW, panel.name, panel); - } else { - panel.skeleton.postEvent(SkeletonEvents.PANEL_HIDE, panel.name, panel); - } - } - } - render() { - const { panel } = this.props; - if (!panel.inited) { - return null; - } - return ( - <div className={classNames('lc-titled-panel', { - hidden: !panel.visible, - })}> - <PanelTitle panel={panel} /> - <div className="lc-pane-body">{panel.body}</div> - </div> - ); - } -} - -@observer -export class PanelView extends Component<{ panel: Panel }> { - shouldComponentUpdate() { - return false; - } - componentDidMount() { - this.checkVisible(); - } - componentDidUpdate() { - this.checkVisible(); - } - private lastVisible: boolean = false; - checkVisible() { - const { panel } = this.props; - const currentVisible = panel.inited && panel.visible; - if (currentVisible !== this.lastVisible) { - this.lastVisible = currentVisible; - if (this.lastVisible) { - panel.skeleton.postEvent(SkeletonEvents.PANEL_SHOW, panel.name, panel); - // FIXME! remove this line - panel.skeleton.postEvent('leftPanel.show' as any, panel.name, panel); - } else { - panel.skeleton.postEvent(SkeletonEvents.PANEL_HIDE, panel.name, panel); - // FIXME! remove this line - panel.skeleton.postEvent('leftPanel.hide' as any, panel.name, panel); - } - } - } - render() { - const { panel } = this.props; - if (!panel.inited) { - return null; - } - return ( - <div - className={classNames('lc-panel', { - hidden: !panel.visible, - })} - > - {panel.body} - </div> - ); - } -} - -@observer -export class TabsPanelView extends Component<{ container: WidgetContainer<Panel> }> { - render() { - const { container } = this.props; - const titles: ReactElement[] = []; - const contents: ReactElement[] = []; - container.items.forEach((item: any) => { - titles.push(<PanelTitle key={item.id} panel={item} className="lc-tab-title" />); - contents.push(<PanelView key={item.id} panel={item} />); - }); - - return ( - <div className="lc-tabs"> - <div - className="lc-tabs-title" - onClick={(e) => { - const shell = e.currentTarget; - const t = e.target as Element; - let elt = shell.firstElementChild; - while (elt) { - if (elt.contains(t)) { - break; - } - elt = elt.nextElementSibling; - } - if (elt) { - container.active((elt as any).dataset.name); - } - }} - > - {titles} - </div> - <div className="lc-tabs-content">{contents}</div> - </div> - ); - } -} - -@observer -class PanelTitle extends Component<{ panel: Panel; className?: string }> { - render() { - const { panel, className } = this.props; - return ( - <div - className={classNames('lc-panel-title', className, { - actived: panel.actived, - })} - data-name={panel.name} - > - <Title title={panel.title || panel.name} /> - {/*pane.help ? <HelpTip tip={panel.help} /> : null*/} - </div> - ); - } -} - -@observer -export class WidgetView extends Component<{ widget: IWidget }> { - shouldComponentUpdate() { - return false; - } - componentDidMount() { - this.checkVisible(); - } - componentDidUpdate() { - this.checkVisible(); - } - private lastVisible: boolean = false; - checkVisible() { - const { widget } = this.props; - const currentVisible = widget.visible; - if (currentVisible !== this.lastVisible) { - this.lastVisible = currentVisible; - if (this.lastVisible) { - widget.skeleton.postEvent(SkeletonEvents.WIDGET_SHOW, widget.name, widget); - } else { - widget.skeleton.postEvent(SkeletonEvents.WIDGET_SHOW, widget.name, widget); - } - } - } - render() { - const { widget } = this.props; - if (!widget.visible) { - return null; - } - return widget.body; - } -} diff --git a/packages/vision-polyfill/src/skeleton/dock.ts b/packages/vision-polyfill/src/skeleton/dock.ts deleted file mode 100644 index 721c6b9c6..000000000 --- a/packages/vision-polyfill/src/skeleton/dock.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { uniqueId, createContent, obx } from '@ali/lowcode-globals'; -import { DockConfig } from "./types"; -import { Skeleton } from './skeleton'; -import { DockView, WidgetView } from './components/widget-views'; -import { IWidget } from './widget/widget'; - -/** - * 带图标(主要)/标题(次要)的扩展 - */ -export default class Dock implements IWidget { - readonly isWidget = true; - readonly id = uniqueId('dock'); - readonly name: string; - readonly align?: string; - - @obx.ref private _visible: boolean = true; - get visible(): boolean { - return this._visible; - } - - get content(): ReactNode { - return createElement(WidgetView, { - widget: this, - key: this.id, - }); - } - - private inited: boolean = false; - private _body: ReactNode; - get body() { - if (this.inited) { - return this._body; - } - - const { props, content, contentProps } = this.config; - - if (content) { - this._body = createContent(content, { - ...contentProps, - config: this.config, - editor: this.skeleton.editor, - }); - } else { - this._body = createElement(DockView, props); - } - return this._body; - } - - constructor(readonly skeleton: Skeleton, readonly config: DockConfig) { - const { props = {}, name } = config; - this.name = name; - this.align = props.align; - } - - setVisible(flag: boolean) { - if (flag === this._visible) { - return; - } - if (flag) { - this._visible = true; - } else if (this.inited) { - this._visible = false; - } - } - - getContent() { - return this.content; - } - - getName() { - return this.name; - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } - - toggle() { - this.setVisible(!this._visible); - } -} diff --git a/packages/vision-polyfill/src/skeleton/icons/convert.tsx b/packages/vision-polyfill/src/skeleton/icons/convert.tsx deleted file mode 100644 index 71ab8630e..000000000 --- a/packages/vision-polyfill/src/skeleton/icons/convert.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { SVGIcon, IconProps } from "@ali/lowcode-globals"; - -export function IconConvert(props: IconProps) { - return ( - <SVGIcon viewBox="0 0 1024 1024" {...props}> - <path d="M508.16 889.6C291.84 889.6 115.2 714.24 115.2 497.92 115.2 281.6 291.84 106.24 509.44 106.24c43.52 0 85.76 6.4 124.16 20.48l-10.24 30.72c-35.84-11.52-72.96-17.92-113.92-17.92-199.68 0-362.24 161.28-362.24 359.68s162.56 358.4 360.96 358.4 359.68-161.28 359.68-359.68c0-66.56-17.92-131.84-51.2-185.6L844.8 294.4c37.12 60.16 56.32 130.56 56.32 203.52-1.28 216.32-176.64 391.68-392.96 391.68z" /> - <path d="M627.2 140.8m-15.36 0a15.36 15.36 0 1 0 30.72 0 15.36 15.36 0 1 0-30.72 0Z" /> - <path d="M832 304.64m-15.36 0a15.36 15.36 0 1 0 30.72 0 15.36 15.36 0 1 0-30.72 0Z" /> - <path d="M348.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - <path d="M508.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - <path d="M668.16 497.92m-35.84 0a35.84 35.84 0 1 0 71.68 0 35.84 35.84 0 1 0-71.68 0Z" fill="#35A2D4" /> - </SVGIcon> - ); -} - -IconConvert.displayName = 'Convert'; diff --git a/packages/vision-polyfill/src/skeleton/index.ts b/packages/vision-polyfill/src/skeleton/index.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/vision-polyfill/src/skeleton/layouts/bottom-area.tsx b/packages/vision-polyfill/src/skeleton/layouts/bottom-area.tsx deleted file mode 100644 index ae251cd2e..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/bottom-area.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; -import Panel from '../widget/panel'; - -@observer -export default class BottomArea extends Component<{ area: Area<any, Panel> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - if (area.isEmpty()) { - return null; - } - return ( - <div className={classNames('lc-bottom-area', { - 'lc-area-visible': area.visible, - })}> - <Contents area={area} /> - </div> - ); - } -} - -@observer -class Contents extends Component<{ area: Area<any, Panel> }> { - render() { - const { area } = this.props; - return ( - <Fragment> - {area.container.items.map((item) => item.content)} - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/left-area.tsx b/packages/vision-polyfill/src/skeleton/layouts/left-area.tsx deleted file mode 100644 index 8fe785055..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/left-area.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; - -@observer -export default class LeftArea extends Component<{ area: Area }> { - render() { - const { area } = this.props; - return ( - <div className={classNames("lc-left-area", { - 'lc-area-visible': area.visible - })}> - <Contents area={area} /> - </div> - ); - } -} - - -@observer -class Contents extends Component<{ area: Area }> { - render() { - const { area } = this.props; - const top: any[] = []; - const bottom: any[] = []; - area.container.items.forEach(item => { - if (item.align === 'bottom') { - bottom.push(item.content); - } else { - top.push(item.content); - } - }); - return ( - <Fragment> - <div className="lc-left-area-top">{top}</div> - <div className="lc-left-area-bottom">{bottom}</div> - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/left-fixed-pane.tsx b/packages/vision-polyfill/src/skeleton/layouts/left-fixed-pane.tsx deleted file mode 100644 index bae3a9eae..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/left-fixed-pane.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import { Button, Icon } from '@alifd/next'; -import Area from '../area'; -import { PanelConfig } from '../types'; -import Panel from '../widget/panel'; - -@observer -export default class LeftFixedPane extends Component<{ area: Area<PanelConfig, Panel> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - return ( - <div - className={classNames('lc-left-fixed-pane', { - 'lc-area-visible': area.visible, - })} - > - <Button - text - className="lc-pane-close" - onClick={() => { - area.setVisible(false); - }} - > - <Icon type="close" /> - </Button> - <Contents area={area} /> - </div> - ); - } -} - -@observer -class Contents extends Component<{ area: Area<PanelConfig, Panel> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - return ( - <Fragment> - {area.container.items.map((panel) => panel.content)} - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/left-float-pane.tsx b/packages/vision-polyfill/src/skeleton/layouts/left-float-pane.tsx deleted file mode 100644 index fefe6d525..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/left-float-pane.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import { Button, Icon } from '@alifd/next'; -import Area from '../area'; -import Panel from '../widget/panel'; - -@observer -export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }> { - shouldComponentUpdate() { - return false; - } - - private dispose?: () => void; - componentDidMount() { - const { area } = this.props; - const triggerClose = () => area.setVisible(false); - area.skeleton.editor.on('designer.dragstart', triggerClose); - this.dispose = () => { - area.skeleton.editor.removeListener('designer.dragstart', triggerClose); - } - } - - componentWillUnmount() { - this.dispose?.(); - } - - render() { - const { area } = this.props; - // TODO: add focusingManager - // focusin set focus (push|replace) - // focusout remove focus - // onEsc - const width = area.current?.config.props?.width; - const style = width ? { - width - } : undefined; - return ( - <div - className={classNames('lc-left-float-pane', { - 'lc-area-visible': area.visible, - })} - style={style} - > - <Button - text - className="lc-pane-close" - onClick={() => { - area.setVisible(false); - }} - > - <Icon type="close" /> - </Button> - <Contents area={area} /> - </div> - ); - } -} - -@observer -class Contents extends Component<{ area: Area<any, Panel> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - return ( - <Fragment> - {area.container.items.map((panel) => panel.content)} - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/main-area.tsx b/packages/vision-polyfill/src/skeleton/layouts/main-area.tsx deleted file mode 100644 index a531398b0..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/main-area.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Component } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; -import Panel from '../widget/panel'; -import Widget from '../widget/widget'; - -@observer -export default class MainArea extends Component<{ area: Area<any, Panel | Widget> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - return ( - <div className={classNames('lc-main-area')}> - {area.container.items.map((item) => item.content)} - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/right-area.tsx b/packages/vision-polyfill/src/skeleton/layouts/right-area.tsx deleted file mode 100644 index b27223f1f..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/right-area.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; -import Panel from '../widget/panel'; - -@observer -export default class RightArea extends Component<{ area: Area<any, Panel> }> { - shouldComponentUpdate() { - return false; - } - render() { - const { area } = this.props; - return ( - <div className={classNames('lc-right-area', { - 'lc-area-visible': area.visible, - })}> - <Contents area={area} /> - </div> - ); - } -} - - -@observer -class Contents extends Component<{ area: Area<any, Panel> }> { - render() { - const { area } = this.props; - return ( - <Fragment> - {area.container.items.map((item) => item.content)} - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/theme.less b/packages/vision-polyfill/src/skeleton/layouts/theme.less deleted file mode 100644 index 5171884c0..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/theme.less +++ /dev/null @@ -1,60 +0,0 @@ -@import '~@ali/ve-less-variables/index.less'; - -/* - * Theme Colors - * - * 乐高设计器的主要主题色变量 - */ -:root { - --color-brand: @brand-color-1; - --color-brand-light: @brand-color-2; - --color-brand-dark: @brand-color-3; - - --color-canvas-background: @normal-alpha-8; - - --color-icon-normal: @normal-alpha-4; - --color-icon-hover: @normal-alpha-3; - --color-icon-active: @brand-color-1; - --color-icon-reverse: @white-alpha-1; - - --color-line-normal: @normal-alpha-7; - --color-line-darken: darken(@normal-alpha-7, 10%); - - --color-title: @dark-alpha-2; - --color-text: @dark-alpha-3; - --color-text-dark: darken(@dark-alpha-3, 10%); - --color-text-light: lighten(@dark-alpha-3, 10%); - --color-text-reverse: @white-alpha-2; - --color-text-regular: @normal-alpha-2; - - --color-field-label: @dark-alpha-4; - --color-field-text: @dark-alpha-3; - --color-field-placeholder: @normal-alpha-5; - --color-field-border: @normal-alpha-5; - --color-field-border-hover: @normal-alpha-4; - --color-field-border-active: @normal-alpha-3; - --color-field-background: @white-alpha-1; - - --color-function-success: @brand-success; - --color-function-success-dark: darken(@brand-success, 10%); - --color-function-success-light: lighten(@brand-success, 10%); - --color-function-warning: @brand-warning; - --color-function-warning-dark: darken(@brand-warning, 10%); - --color-function-warning-light: lighten(@brand-warning, 10%); - --color-function-information: @brand-link-hover; - --color-function-information-dark: darken(@brand-link-hover, 10%); - --color-function-information-light: lighten(@brand-link-hover, 10%); - --color-function-error: @brand-danger; - --color-function-error-dark: darken(@brand-danger, 10%); - --color-function-error-light: lighten(@brand-danger, 10%); - - --color-pane-background: @white-alpha-1; - --color-block-background-normal: @white-alpha-1; - --color-block-background-light: @normal-alpha-9; - --color-block-background-shallow: @normal-alpha-8; - --color-block-background-dark: @normal-alpha-7; - --color-block-background-disabled: @normal-alpha-6; - --color-block-background-deep-dark: @normal-5; - --color-layer-mask-background: @dark-alpha-7; - --color-layer-tooltip-background: rgba(44,47,51,0.8); -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/toolbar.tsx b/packages/vision-polyfill/src/skeleton/layouts/toolbar.tsx deleted file mode 100644 index ea9c02ef0..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/toolbar.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; - -@observer -export default class Toolbar extends Component<{ area: Area }> { - render() { - const { area } = this.props; - if (area.isEmpty()) { - return null; - } - return ( - <div - className={classNames('lc-toolbar', { - 'lc-area-visible': area.visible, - })} - > - <Contents area={area} /> - </div> - ); - } -} - -@observer -class Contents extends Component<{ area: Area }> { - render() { - const { area } = this.props; - const left: any[] = []; - const center: any[] = []; - const right: any[] = []; - area.container.items.forEach((item) => { - if (item.align === 'center') { - center.push(item.content); - } else if (item.align === 'right') { - right.push(item.content); - } else { - left.push(item.content); - } - }); - return ( - <Fragment> - <div className="lc-toolbar-left">{left}</div> - <div className="lc-toolbar-center">{center}</div> - <div className="lc-toolbar-right">{right}</div> - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/top-area.tsx b/packages/vision-polyfill/src/skeleton/layouts/top-area.tsx deleted file mode 100644 index 13da4d17e..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/top-area.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { Component, Fragment } from 'react'; -import classNames from 'classnames'; -import { observer } from '@ali/lowcode-globals'; -import Area from '../area'; - -@observer -export default class TopArea extends Component<{ area: Area }> { - render() { - const { area } = this.props; - return ( - <div className={classNames("lc-top-area", { - 'lc-area-visible': area.visible - })}> - <Contents area={area} /> - </div> - ); - } -} - -@observer -class Contents extends Component<{ area: Area }> { - render() { - const { area } = this.props; - const left: any[] = []; - const center: any[] = []; - const right: any[] = []; - area.container.items.forEach(item => { - if (item.align === 'center') { - center.push(item.content); - } else if (item.align === 'left') { - left.push(item.content); - } else { - right.push(item.content); - } - }); - return ( - <Fragment> - <div className="lc-top-area-left">{left}</div> - <div className="lc-top-area-center">{center}</div> - <div className="lc-top-area-right">{right}</div> - </Fragment> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/workbench.less b/packages/vision-polyfill/src/skeleton/layouts/workbench.less deleted file mode 100644 index 92deeeacd..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/workbench.less +++ /dev/null @@ -1,375 +0,0 @@ -@import "./theme.less"; - -:root { - --font-family: @font-family; - --font-size-label: @fontSize-4; - --font-size-text: @fontSize-5; - --font-size-btn-large: @fontSize-3; - --font-size-btn-medium: @fontSize-4; - --font-size-btn-small: @fontSize-5; - - --global-border-radius: @global-border-radius; - --input-border-radius: @input-border-radius; - --popup-border-radius: @popup-border-radius; - - --left-area-width: 48px; - --right-area-width: 280px; - --top-area-height: 48px; - --toolbar-height: 36px; - --dock-pane-width: 280px; - --dock-fixed-pane-width: 280px; -} - -@media (min-width: 1860px) { - :root { - --right-area-width: 400px; - --dock-pane-width: 452px; - --dock-fixed-pane-width: 350px; - } -} - -html, -body { - height: 100%; - overflow: hidden; - padding: 0; - margin: 0; - position: relative; - font-family: var(--font-family); - font-size: var(--font-size-text); - color: var(--color-text); - background-color:#EDEFF3; -} - -* { - box-sizing: border-box; -} - - -.lc-titled-panel { - width: 100%; - height: 100%; - position: relative; - .pane-title { - // height: var(--pane-title-height); - background-color: var(--pane-title-bg-color); - display: flex; - align-items: center; - padding: 0 15px; - .my-help-tip { - margin-left: 4px; - } - } - - .pane-body { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - overflow: auto; - .my-tabs { - width: 100%; - height: 100%; - position: relative; - .tabs-title { - display: flex; - height: var(--pane-title-height); - > .tab-title { - cursor: pointer; - padding: 0; - flex: 1; - min-width: 0; - justify-content: center; - border-bottom: 2px solid transparent; - &.actived { - cursor: default; - color: var(--color-text-avtived); - border-bottom-color: #3896ee; - } - } - } - .tabs-content { - position: absolute; - top: var(--pane-title-height); - bottom: 0; - left: 0; - right: 0; - height: calc(100% - var(--pane-title-height)); - overflow: hidden; - } - } - } - - &.titled > .pane-body { - top: var(--pane-title-height); - } -} -.lc-panel { - height: 100%; - width: 100%; - overflow: auto; - &.hidden { - display: none; - } - .pane-title { - height: var(--pane-title-height); - background-color: var(--pane-title-bg-color); - display: flex; - align-items: center; - padding: 0 15px; - .my-help-tip { - margin-left: 4px; - } - } - .my-tabs { - width: 100%; - height: 100%; - position: relative; - .tabs-title { - display: flex; - height: var(--pane-title-height); - margin-right: 30px; - > .tab-title { - cursor: pointer; - padding: 0; - flex: 1; - min-width: 0; - justify-content: center; - border-bottom: 2px solid transparent; - &.actived { - cursor: default; - color: var(--color-text-avtived); - border-bottom-color: #3896ee; - } - } - } - .tabs-content { - position: absolute; - top: var(--pane-title-height); - bottom: 0; - left: 0; - right: 0; - height: calc(100% - var(--pane-title-height)); - overflow: hidden; - } - } -} - -.my-dock { - padding: 0px 10px; - cursor: pointer; - align-self: stretch; - display: flex; - align-items: center; - .my-title-label { - user-select: none; - } - &.actived, &:hover { - background-color: var(--pane-title-bg-color); - .my-title { - color: var(--color-actived); - } - } -} - - -.lc-workbench { - height: 100%; - display: flex; - flex-direction: column; - background-color: #EDEFF3; - .lc-top-area { - height: var(--top-area-height); - background-color: var(--color-pane-background); - width: 100%; - display: flex; - margin-bottom: 2px; - padding: 8px; - .lc-top-area-left{} - .lc-top-area-center{ - flex: 1; - display: flex; - justify-content: flex-end; - margin-right: 8px; - } - .lc-top-area-right{ - display: flex; - align-items: center; - >* { - margin-left: 4px; - margin-right: 4px; - } - } - } - .lc-workbench-body { - flex: 1; - display: flex; - min-height: 0; - position: relative; - .lc-left-float-pane { - position: absolute; - top: 0; - bottom: 0; - width: var(--dock-pane-width); - left: calc(var(--left-area-width) + 1px); - background-color: var(--color-pane-background); - box-shadow: 4px 0 16px 0 rgba(31,50,88,0.08); - z-index: 820; - display: none; - // padding-top: 36px; - &.lc-area-visible { - display: block; - } - .lc-pane-close{ - position: absolute; - right: 10px; - top: 6px; - z-index: 2; - .next-icon{ - line-height: 1; - } - } - .lc-tabs-title { - width: 100%; - height: 36px; - position: relative; - display: center; - display: flex; - justify-content: center; - align-items: center; - background: rgba(31,56,88,0.04); - } - .lc-tabs-content { - position: absolute; - top: 36px; - bottom: 0; - left: 0; - right: 0; - } - } - .lc-left-area { - height: 100%; - width: var(--left-area-width); - background-color: var(--color-pane-background); - display: none; - flex-shrink: 0; - flex-direction: column; - justify-content: space-between; - &.lc-area-visible { - display: flex; - } - .lc-left-area-top, - .lc-left-area-bottom{ - width: 100%; - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - .lc-title{ - padding: 12px; - flex-direction: column; - &.has-tip{ - cursor: pointer; - } - &.actived{ - color: #0079F2; - } - .lc-title-icon{ - margin: 0; - .next-icon:before { - line-height: 1 !important; - } - } - } - } - .lc-left-area-top{ - padding-top: 12px; - } - .lc-left-area-bottom{ - padding-bottom: 12px; - } - } - .lc-left-fixed-pane { - width: var(--dock-fixed-pane-width); - background-color: var(--color-pane-background); - height: 100%; - display: none; - flex-shrink: 0; - position: relative; - &.lc-area-visible { - display: block; - } - .lc-pane-close { - position: absolute; - right: 10px; - top: 6px; - z-index: 2; - .next-icon { - line-height: 1; - } - } - } - .lc-left-area.lc-area-visible ~ .lc-left-fixed-pane { - margin-left: 1px; - } - .lc-left-area.lc-area-visible ~ .lc-workbench-center { - margin-left: 2px; - } - .lc-outline-pane{ - .lc-outline-tree .tree-node .tree-node-title{ - border-bottom: none; - } - } - .lc-workbench-center { - flex: 1; - display: flex; - flex-direction: column; - .lc-toolbar { - height: var(--toolbar-height); - background-color: var(--color-pane-background); - padding: 8px 16px; - } - .lc-main-area { - flex: 1; - } - .lc-bottom-area { - height: var(--bottom-area-height); - background-color: var(--color-pane-background); - display: none; - &.lc-area-visible { - display: block; - } - } - } - .lc-right-area { - height: 100%; - width: var(--right-area-width); - background-color: var(--color-pane-background); - display: none; - flex-shrink: 0; - margin-left: 2px; - &.lc-area-visible { - display: block; - } - .lc-settings-tabs{ - > .next-tabs-nav-extra{ - top: 36px !important; - } - .lc-settings-tab-item{ - .next-tabs-tab-inner{ - font-size: 12px; - line-height: 12px; - } - } - .lc-title{ - color: inherit; - line-height: inherit !important; - } - } - .lc-settings-tabs-content{ - top: 66px; - } - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/layouts/workbench.tsx b/packages/vision-polyfill/src/skeleton/layouts/workbench.tsx deleted file mode 100644 index c55633f39..000000000 --- a/packages/vision-polyfill/src/skeleton/layouts/workbench.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Component } from 'react'; -import { TipContainer, observer } from '@ali/lowcode-globals'; -import { Skeleton } from '../skeleton'; -import TopArea from './top-area'; -import LeftArea from './left-area'; -import LeftFixedPane from './left-fixed-pane'; -import LeftFloatPane from './left-float-pane'; -import Toolbar from './toolbar'; -import MainArea from './main-area'; -import BottomArea from './bottom-area'; -import RightArea from './right-area'; -import './workbench.less'; - -@observer -export class VisionWorkbench extends Component<{ skeleton: Skeleton}> { - shouldComponentUpdate() { - return false; - } - - render() { - const { skeleton } = this.props; - return ( - <div className="lc-workbench"> - <TopArea area={skeleton.topArea} /> - <div className="lc-workbench-body"> - <LeftArea area={skeleton.leftArea} /> - <LeftFloatPane area={skeleton.leftFloatArea} /> - <LeftFixedPane area={skeleton.leftFixedArea} /> - <div className="lc-workbench-center"> - <Toolbar area={skeleton.toolbar} /> - <MainArea area={skeleton.mainArea} /> - <BottomArea area={skeleton.bottomArea} /> - </div> - <RightArea area={skeleton.rightArea} /> - </div> - <TipContainer /> - </div> - ); - } -} diff --git a/packages/vision-polyfill/src/skeleton/panel.ts b/packages/vision-polyfill/src/skeleton/panel.ts deleted file mode 100644 index c9e2e890d..000000000 --- a/packages/vision-polyfill/src/skeleton/panel.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { createElement, ReactNode } from 'react'; -import { obx, uniqueId, createContent, TitleContent } from '@ali/lowcode-globals'; -import WidgetContainer from './widget-container'; -import { PanelConfig, HelpTipConfig } from './types'; -import { TitledPanelView, TabsPanelView, PanelView } from './components/widget-views'; -import { Skeleton } from './skeleton'; -import { composeTitle } from './widget/utils'; -import { IWidget } from './widget'; - -export default class Panel implements IWidget { - readonly isWidget = true; - readonly name: string; - readonly id: string; - @obx.ref inited: boolean = false; - @obx.ref private _actived: boolean = false; - get actived(): boolean { - return this._actived; - } - - get visible(): boolean { - if (this.parent?.visible) { - return this._actived; - } - return false; - } - - readonly isPanel = true; - - private _body?: ReactNode; - get body() { - this.initBody(); - return this._body; - } - - get content(): ReactNode { - if (this.plain) { - return createElement(PanelView, { - panel: this, - key: this.id, - }); - } - return createElement(TitledPanelView, { panel: this, key: this.id }); - } - - readonly title: TitleContent; - readonly help?: HelpTipConfig; - private plain: boolean = false; - - private container?: WidgetContainer<Panel, PanelConfig>; - private parent?: WidgetContainer; - - constructor(readonly skeleton: Skeleton, readonly config: PanelConfig) { - const { name, content, props = {} } = config; - const { hideTitleBar, title, icon, description, help, shortcut } = props; - this.name = name; - this.id = uniqueId(`pane:${name}$`); - this.title = composeTitle(title || name, icon, description); - this.plain = hideTitleBar || !title; - this.help = help; - if (Array.isArray(content)) { - this.container = this.skeleton.createContainer( - name, - (item) => { - if (isPanel(item)) { - return item; - } - return this.skeleton.createPanel(item); - }, - true, - () => this.visible, - true, - ); - content.forEach((item) => this.add(item)); - } - // todo: process shortcut - } - - private initBody() { - if (this.inited) { - return; - } - this.inited = true; - if (this.container) { - this._body = createElement(TabsPanelView, { - container: this.container, - }); - } else { - const { content, contentProps } = this.config; - this._body = createContent(content, { - ...contentProps, - editor: this.skeleton.editor, - config: this.config, - panel: this, - }); - } - } - - setParent(parent: WidgetContainer) { - if (parent === this.parent) { - return; - } - if (this.parent) { - this.parent.remove(this); - } - this.parent = parent; - } - - add(item: Panel | PanelConfig) { - return this.container?.add(item); - } - - getPane(name: string): Panel | null { - return this.container?.get(name) || null; - } - - remove(item: Panel | string) { - return this.container?.remove(item); - } - - active(item?: Panel | string | null) { - this.container?.active(item); - } - - getName() { - return this.name; - } - - getContent() { - return this.content; - } - - setActive(flag: boolean) { - if (flag === this._actived) { - // TODO: 如果移动到另外一个 container,会有问题 - return; - } - if (flag) { - if (!this.inited) { - this.initBody(); - } - this._actived = true; - this.parent?.active(this); - } else if (this.inited) { - this._actived = false; - this.parent?.unactive(this); - } - } - - toggle() { - this.setActive(!this._actived); - } - - hide() { - this.setActive(false); - } - - show() { - this.setActive(true); - } -} - -export function isPanel(obj: any): obj is Panel { - return obj && obj.isPanel; -} diff --git a/packages/vision-polyfill/src/skeleton/skeleton.ts b/packages/vision-polyfill/src/skeleton/skeleton.ts deleted file mode 100644 index 2ed0c7b39..000000000 --- a/packages/vision-polyfill/src/skeleton/skeleton.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { Editor } from '@ali/lowcode-editor-core'; -import { - DockConfig, - PanelConfig, - WidgetConfig, - IWidgetBaseConfig, - PanelDockConfig, - DialogDockConfig, - isDockConfig, - isPanelDockConfig, - isPanelConfig, - DividerConfig, - isDividerConfig -} from './types'; -import Panel, { isPanel } from './widget/panel'; -import WidgetContainer from './widget/widget-container'; -import Area from './area'; -import Widget, { isWidget, IWidget } from './widget/widget'; -import PanelDock from './widget/panel-dock'; -import Dock from './widget/dock'; -import { Stage, StageConfig } from './widget/stage'; -import { isValidElement } from 'react'; -import { isPlainObject } from 'globals/src/utils'; -import { Divider } from '@alifd/next'; - -export enum SkeletonEvents { - PANEL_DOCK_ACTIVE = 'skeleton.panel-dock.active', - PANEL_DOCK_UNACTIVE = 'skeleton.panel-dock.unactive', - PANEL_SHOW = 'skeleton.panel.show', - PANEL_HIDE = 'skeleton.panel.hide', - WIDGET_SHOW = 'skeleton.widget.show', - WIDGET_HIDE = 'skeleton.widget.hide', -} - -export class Skeleton { - private panels = new Map<string, Panel>(); - private containers = new Map<string, WidgetContainer<any>>(); - readonly leftArea: Area<DockConfig | PanelDockConfig | DialogDockConfig>; - readonly topArea: Area<DockConfig | DividerConfig | PanelDockConfig | DialogDockConfig>; - readonly toolbar: Area<DockConfig | DividerConfig | PanelDockConfig | DialogDockConfig>; - readonly leftFixedArea: Area<PanelConfig, Panel>; - readonly leftFloatArea: Area<PanelConfig, Panel>; - readonly rightArea: Area<PanelConfig, Panel>; - readonly mainArea: Area<WidgetConfig | PanelConfig, Widget | Panel>; - readonly bottomArea: Area<PanelConfig, Panel>; - readonly stages: Area<StageConfig, Stage>; - - constructor(readonly editor: Editor) { - this.leftArea = new Area( - this, - 'leftArea', - (config) => { - if (isWidget(config)) { - return config; - } - return this.createWidget(config); - }, - false, - ); - this.topArea = new Area( - this, - 'topArea', - (config) => { - if (isWidget(config)) { - return config; - } - return this.createWidget(config); - }, - false, - ); - this.toolbar = new Area( - this, - 'toolbar', - (config) => { - if (isWidget(config)) { - return config; - } - return this.createWidget(config); - }, - false, - ); - this.leftFixedArea = new Area( - this, - 'leftFixedArea', - (config) => { - if (isPanel(config)) { - return config; - } - return this.createPanel(config); - }, - true, - ); - this.leftFloatArea = new Area( - this, - 'leftFloatArea', - (config) => { - if (isPanel(config)) { - return config; - } - return this.createPanel(config); - }, - true, - ); - this.rightArea = new Area( - this, - 'rightArea', - (config) => { - if (isPanel(config)) { - return config; - } - return this.createPanel(config); - }, - true, - true, - ); - this.mainArea = new Area( - this, - 'mainArea', - (config) => { - if (isWidget(config)) { - return config as Widget; - } - return this.createWidget(config) as Widget; - }, - true, - true, - ); - this.bottomArea = new Area( - this, - 'bottomArea', - (config) => { - if (isPanel(config)) { - return config; - } - return this.createPanel(config); - }, - true, - ); - this.stages = new Area(this, 'stages', (config) => { - if (isWidget(config)) { - return config; - } - return new Stage(this, config); - }); - - this.setupPlugins(); - } - - private setupPlugins() { - const { config, components: componentsMap } = this.editor; - const { plugins } = config; - if (!plugins) { - return; - } - Object.keys(plugins).forEach((area) => { - plugins[area].forEach((item) => { - const { pluginKey, type, props = {}, pluginProps } = item; - const config: any = { - area, - type: 'Widget', - name: pluginKey, - contentProps: pluginProps, - }; - const { dialogProps, balloonProps, panelProps, linkProps, ...restProps } = props; - config.props = restProps; - if (dialogProps) { - config.dialogProps = dialogProps; - } - if (balloonProps) { - config.balloonProps = balloonProps; - } - if (panelProps) { - config.panelProps = panelProps; - } - if (linkProps) { - config.linkProps = linkProps; - } - if (type === 'TabPanel') { - config.type = 'Panel'; - } else if (/Icon$/.test(type)) { - config.type = type.replace('Icon', 'Dock'); - } - if (pluginKey in componentsMap) { - config.content = componentsMap[pluginKey]; - } - this.add(config); - }); - }); - } - - postEvent(event: SkeletonEvents, ...args: any[]) { - this.editor.emit(event, ...args); - } - - createWidget(config: IWidgetBaseConfig | IWidget) { - if (isWidget(config)) { - return config; - } - - config = this.parseConfig(config); - let widget: IWidget; - if (isDockConfig(config)) { - if (isPanelDockConfig(config)) { - widget = new PanelDock(this, config); - } else if (false) { - // DialogDock - // others... - } else { - - widget = new Dock(this, config); - } - } else if (isDividerConfig(config)) { - widget = new Widget(this, { - ...config, - type: 'Widget', - content: Divider, - }); - } else if (isPanelConfig(config)) { - widget = this.createPanel(config); - } else { - widget = new Widget(this, config as WidgetConfig); - } - return widget; - } - - createPanel(config: PanelConfig) { - config = this.parseConfig(config); - const panel = new Panel(this, config); - this.panels.set(panel.name, panel); - return panel; - } - - getPanel(name: string): Panel | undefined { - return this.panels.get(name); - } - - createContainer( - name: string, - handle: (item: any) => any, - exclusive = false, - checkVisible: () => boolean = () => true, - defaultSetCurrent = false, - ) { - const container = new WidgetContainer(name, handle, exclusive, checkVisible, defaultSetCurrent); - this.containers.set(name, container); - return container; - } - - private parseConfig(config: IWidgetBaseConfig): any { - if ((config as any).parsed) { - return config; - } - const { content, ...restConfig } = config; - if (content) { - if (isPlainObject(content) && !isValidElement(content)) { - Object.keys(content).forEach((key) => { - if (/props$/i.test(key) && restConfig[key]) { - restConfig[key] = { - ...restConfig[key], - ...content[key], - }; - } else { - restConfig[key] = content[key]; - } - }); - } else { - restConfig.content = content; - } - } - restConfig.pluginKey = restConfig.name; - restConfig.parsed = true; - return restConfig; - } - - add(config: IWidgetBaseConfig & { area?: string }, extraConfig?: object) { - const parsedConfig: any = { - ...this.parseConfig(config), - ...extraConfig, - }; - let { area } = parsedConfig; - if (!area) { - if (parsedConfig.type === 'Panel') { - area = 'leftFloatArea' - } else if (parsedConfig.type === 'Widget') { - area = 'mainArea'; - } else { - area = 'leftArea'; - } - } - switch (area) { - case 'leftArea': - case 'left': - return this.leftArea.add(parsedConfig); - case 'rightArea': - case 'right': - return this.rightArea.add(parsedConfig); - case 'topArea': - case 'top': - return this.topArea.add(parsedConfig); - case 'toolbar': - return this.toolbar.add(parsedConfig); - case 'mainArea': - case 'main': - case 'center': - case 'centerArea': - return this.mainArea.add(parsedConfig); - case 'bottomArea': - case 'bottom': - return this.bottomArea.add(parsedConfig); - case 'leftFixedArea': - return this.leftFixedArea.add(parsedConfig); - case 'leftFloatArea': - return this.leftFloatArea.add(parsedConfig); - case 'stages': - return this.stages.add(parsedConfig); - } - } -} diff --git a/packages/vision-polyfill/src/skeleton/transducers/addon-combine.ts b/packages/vision-polyfill/src/skeleton/transducers/addon-combine.ts deleted file mode 100644 index 80ad16cc1..000000000 --- a/packages/vision-polyfill/src/skeleton/transducers/addon-combine.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { TransformedComponentMetadata, FieldConfig } from '@ali/lowcode-globals'; - -export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { - const { componentName, configure = {} } = metadata; - if (componentName === 'Leaf') { - return { - ...metadata, - configure: { - ...configure, - combined: [ - { - name: 'children', - title: { type: 'i18n', 'zh-CN': '内容设置', 'en-US': 'Content' }, - setter: { - componentName: 'MixinSetter', - props: { - // TODO: - setters: [ - { - componentName: 'StringSetter', - props: { - // TODO: textarea mode - multiline: true, - }, - initialValue: '', - }, - { - componentName: 'ExpressionSetter', - initialValue: { - type: 'JSExpression', - value: '', - }, - }, - ], - }, - }, - }, - ], - }, - }; - } - - const { props, events = {}, styles } = configure as any; - const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; - const eventsDefinition: any[] = []; - const supportedLifecycles = - events.supportedLifecycles || - (isRoot - ? [ - { - description: '初始化时', - name: 'constructor', - }, - { - description: '装载后', - name: 'componentDidMount', - }, - { - description: '更新时', - name: 'componentDidMount', - }, - { - description: '卸载时', - name: 'componentWillUnmount', - }, - ] - : null); - if (supportedLifecycles) { - eventsDefinition.push({ - type: 'lifeCycleEvent', - title: '生命周期', - list: supportedLifecycles.map((event: any) => (typeof event === 'string' ? { name: event } : event)), - }); - } - if (events.supportedEvents) { - eventsDefinition.push({ - type: 'events', - title: '事件', - list: (events.supportedEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)), - }); - } - // 通用设置 - const propsGroup = props || []; - propsGroup.push({ - name: '#generals', - title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' }, - items: [ - { - name: 'id', - title: 'ID', - setter: 'StringSetter', - }, - { - name: 'key', - title: 'Key', - // todo: use Mixin - setter: 'StringSetter', - }, - { - name: 'ref', - title: 'Ref', - setter: 'StringSetter', - }, - /* - { - name: '!more', - title: '更多', - setter: 'PropertiesSetter', - },*/ - ], - }); - const combined: FieldConfig[] = [ - { - title: { type: 'i18n', 'zh-CN': '属性', 'en-US': 'Props' }, - name: '#props', - items: propsGroup, - }, - ]; - const stylesGroup: FieldConfig[] = []; - if (styles?.supportClassName) { - stylesGroup.push({ - name: 'className', - title: { type: 'i18n', 'zh-CN': '类名绑定', 'en-US': 'ClassName' }, - setter: 'ClassNameSetter', - }); - } - if (styles?.supportInlineStyle) { - stylesGroup.push({ - name: 'style', - title: { type: 'i18n', 'zh-CN': '行内样式', 'en-US': 'Style' }, - setter: 'StyleSetter', - }); - } - if (stylesGroup.length > 0) { - combined.push({ - name: '#styles', - title: { type: 'i18n', 'zh-CN': '样式', 'en-US': 'Styles' }, - items: stylesGroup, - }); - } - - if (eventsDefinition.length > 0) { - combined.push({ - name: '#events', - title: { type: 'i18n', 'zh-CN': '事件', 'en-US': 'Events' }, - items: [ - { - name: '!events', - title: { type: 'i18n', 'zh-CN': '事件设置', 'en-US': 'Events' }, - setter: { - componentName: 'EventsSetter', - props: { - definition: eventsDefinition, - }, - }, - getValue(field: SettingField, val?: any[]) { - // todo: - return val; - }, - - setValue(field: SettingField, eventDataList: any[]) { - // todo: - return; - }, - }, - ], - }); - } - - if (isRoot) { - /* - combined.push({ - name: '#advanced', - title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' }, - items: [], - }); - */ - } else { - combined.push({ - name: '#advanced', - title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' }, - items: [ - { - name: '__condition', - title: { type: 'i18n', 'zh-CN': '条件显示', 'en-US': 'Condition' }, - setter: 'ExpressionSetter', - }, - { - name: '#loop', - title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' }, - items: [ - { - name: '__loop', - title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, - setter: { - componentName: 'MixinSetter', - props: { - // TODO: - 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' }, - }, - }, - ], - }, - }, - }, - { - name: '__loopArgs.0', - title: { type: 'i18n', 'zh-CN': '迭代变量名', 'en-US': 'Loop Item' }, - setter: { - componentName: 'StringSetter', - props: { - placeholder: { type: 'i18n', 'zh-CN': '默认为: item', 'en-US': 'Defaults: item' }, - } - }, - }, - { - name: '__loopArgs.1', - title: { type: 'i18n', 'zh-CN': '索引变量名', 'en-US': 'Loop Index' }, - setter: { - componentName: 'StringSetter', - props: { - placeholder: { type: 'i18n', 'zh-CN': '默认为: index', 'en-US': 'Defaults: index' }, - } - }, - }, - { - name: 'key', - title: 'Key', - setter: 'ExpressionSetter', - }, - ], - }, - ], - }); - } - - return { - ...metadata, - configure: { - ...configure, - combined, - }, - }; -} diff --git a/packages/vision-polyfill/src/skeleton/transducers/parse-props.ts b/packages/vision-polyfill/src/skeleton/transducers/parse-props.ts deleted file mode 100644 index 43bd44221..000000000 --- a/packages/vision-polyfill/src/skeleton/transducers/parse-props.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { - FieldConfig, - PropConfig, - PropType, - SetterType, - OneOf, - Shape, - ObjectOf, - ArrayOf, - TransformedComponentMetadata, -} from '@ali/lowcode-globals'; - -function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig { - const { name, description } = propConfig; - const title = { - label: { - type: 'i18n', - 'en-US': name, - 'zh-CN': description?.slice(0, 10) || name, - }, - tip: description ? `${name} | ${description}` : undefined, - }; - return { - title, - ...propConfig, - setter: propTypeToSetter(propConfig.propType), - }; -} - -function propTypeToSetter(propType: PropType): SetterType { - let typeName: string; - let isRequired: boolean | undefined = false; - if (typeof propType === 'string') { - typeName = propType; - } else { - typeName = propType.type; - isRequired = propType.isRequired; - } - // TODO: use mixinSetter wrapper - switch (typeName) { - case 'string': - return { - componentName: 'StringSetter', - isRequired, - initialValue: '', - }; - - case 'number': - return { - componentName: 'NumberSetter', - isRequired, - initialValue: 0, - }; - case 'bool': - return { - componentName: 'NumberSetter', - isRequired, - initialValue: false, - }; - case 'oneOf': - const dataSource = ((propType as OneOf).value || []).map((value, index) => { - const t = typeof value; - return { - label: t === 'string' || t === 'number' || t === 'boolean' ? String(value) : `value ${index}`, - value, - }; - }); - const componentName = dataSource.length > 4 ? 'SelectSetter' : 'RadioGroupSetter'; - return { - componentName, - props: { dataSource }, - isRequired, - initialValue: dataSource[0] ? dataSource[0].value : null, - }; - - case 'element': - case 'node': // TODO: use Mixin - return { - // slotSetter - componentName: 'NodeSetter', - props: { - mode: typeName, - }, - isRequired, - initialValue: { - type: 'JSSlot', - value: '', - }, - }; - case 'shape': - case 'exact': - const items = (propType as Shape).value.map((item) => propConfigToFieldConfig(item)); - return { - componentName: 'ObjectSetter', - props: { - config: { - items, - extraSetter: typeName === 'shape' ? propTypeToSetter('any') : null, - }, - }, - isRequired, - initialValue: (field: any) => { - const data: any = {}; - items.forEach((item) => { - let initial = item.defaultValue; - if (initial == null && item.setter && typeof item.setter === 'object') { - initial = (item.setter as any).initialValue; - } - data[item.name] = initial ? (typeof initial === 'function' ? initial(field) : initial) : null; - }); - return data; - }, - }; - case 'object': - case 'objectOf': - return { - componentName: 'ObjectSetter', - props: { - config: { - extraSetter: propTypeToSetter(typeName === 'objectOf' ? (propType as ObjectOf).value : 'any'), - }, - }, - isRequired, - }; - case 'array': - case 'arrayOf': - return { - componentName: 'ArraySetter', - props: { - itemSetter: propTypeToSetter(typeName === 'arrayOf' ? (propType as ArrayOf).value : 'any'), - }, - isRequired, - initialValue: [], - }; - case 'func': - return { - componentName: 'FunctionSetter', - isRequired, - initialValue: { - type: 'JSFunction', - value: 'function(){}', - }, - }; - case 'oneOfType': - return { - componentName: 'MixinSetter', - props: { - // TODO: - // setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)), - }, - isRequired, - }; - } - - return { - componentName: 'MixinSetter', - isRequired, - }; -} - -const EVENT_RE = /^on[A-Z][\w]*$/; - -export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { - const { configure } = metadata; - if (configure.props) { - return metadata; - } - - if (!metadata.props) { - return { - ...metadata, - configure: { - ...configure, - props: [], - }, - }; - } - const { component = {}, events = {}, styles = {} } = configure; - const supportedEvents: any[] | null = (events as any).supportedEvents ? null : []; - const props: FieldConfig[] = []; - - metadata.props.forEach((prop) => { - const { name, propType, description } = prop; - if ( - name === 'children' && - (component.isContainer || propType === 'node' || propType === 'element' || propType === 'any') - ) { - if (component.isContainer !== false) { - component.isContainer = true; - return; - } - } - - if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) { - if (supportedEvents) { - supportedEvents.push({ - name, - description, - }); - (events as any).supportedEvents = supportedEvents; - } - return; - } - - if (name === 'className' && (propType === 'string' || propType === 'any')) { - if ((styles as any).supportClassName == null) { - (styles as any).supportClassName = true; - } - return; - } - - if (name === 'style' && (propType === 'object' || propType === 'any')) { - if ((styles as any).supportInlineStyle == null) { - (styles as any).supportInlineStyle = true; - } - return; - } - - props.push(propConfigToFieldConfig(prop)); - }); - - return { - ...metadata, - configure: { - ...configure, - props, - events, - styles, - component, - }, - }; -} diff --git a/packages/vision-polyfill/src/skeleton/transducers/register.ts b/packages/vision-polyfill/src/skeleton/transducers/register.ts deleted file mode 100644 index a09e685ed..000000000 --- a/packages/vision-polyfill/src/skeleton/transducers/register.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerMetadataTransducer } from '@ali/lowcode-globals'; -import parseProps from './parse-props'; -import addonCombine from './addon-combine'; - -// parseProps -registerMetadataTransducer(parseProps, 10, 'parse-props'); - -// addon/platform custom -registerMetadataTransducer(addonCombine, 11, 'combine-props'); diff --git a/packages/vision-polyfill/src/skeleton/types.ts b/packages/vision-polyfill/src/skeleton/types.ts deleted file mode 100644 index b44b7b165..000000000 --- a/packages/vision-polyfill/src/skeleton/types.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { ReactElement, ComponentType } from 'react'; -import { TitleContent, IconType, I18nData, TipContent } from '@ali/lowcode-globals'; - -export interface IWidgetBaseConfig { - type: string; - name: string; - area?: string; // 停靠位置, 默认 float, 如果添加非固定区, - props?: object; - content?: any; - contentProps?: object; - // index?: number; - [extra: string]: any; -} - -export interface WidgetConfig extends IWidgetBaseConfig { - type: "Widget"; - props?: { - align?: "left" | "right" | "bottom" | "center" | "top"; - }; - content?: string | ReactElement | ComponentType<any>; // children -} - -export function isWidgetConfig(obj: any): obj is WidgetConfig { - return obj && obj.type === "Widget"; -} - -export interface DockProps { - title?: TitleContent; - icon?: IconType; - size?: 'small' | 'medium' | 'large'; - className?: string; - description?: TipContent; - onClick?: () => void; -} - -export interface DividerConfig extends IWidgetBaseConfig { - type: "Divider"; - props?: { - align?: "left" | "right" | "center"; - }; -} - -export function isDividerConfig(obj: any): obj is DividerConfig { - return obj && obj.type === "Divider"; -} - -export interface IDockBaseConfig extends IWidgetBaseConfig { - props?: DockProps & { - align?: "left" | "right" | "bottom" | "center" | "top"; - }; -} - -export interface DockConfig extends IDockBaseConfig { - type: "Dock"; - content?: string | ReactElement | ComponentType<any>; -} - -export function isDockConfig(obj: any): obj is DockConfig { - return obj && /Dock$/.test(obj.type); -} - -// 按钮弹窗扩展 -export interface DialogDockConfig extends IDockBaseConfig { - type: "DialogDock"; - dialogProps?: { - title?: TitleContent; - [key: string]: any; - }; -} - -export function isDialogDockConfig(obj: any): obj is DialogDockConfig { - return obj && obj.type === 'DialogDock'; -} - -// 窗格扩展 -export interface PanelConfig extends IWidgetBaseConfig { - type: "Panel"; - content?: string | ReactElement | ComponentType<any> | PanelConfig[]; // as children - props?: PanelProps; -} - -export function isPanelConfig(obj: any): obj is PanelConfig { - return obj && obj.type === 'Panel'; -} - -export type HelpTipConfig = string | { url?: string; content?: string | ReactElement }; - -export interface PanelProps { - title?: TitleContent; - icon?: any; // 冗余字段 - description?: string | I18nData; - hideTitleBar?: boolean; // panel.props 兼容,不暴露 - help?: HelpTipConfig; // 显示问号帮助 - width?: number; // panel.props - height?: number; // panel.props - maxWidth?: number; // panel.props - maxHeight?: number; // panel.props - onInit?: () => any; - onDestroy?: () => any; - shortcut?: string; // 只有在特定位置,可触发 toggle show -} - -export interface PanelDockConfig extends IDockBaseConfig { - type: "PanelDock"; - panelName?: string; - panelProps?: PanelProps & { - area?: string; - }; - content?: string | ReactElement | ComponentType<any> | PanelConfig[]; // content for pane -} - -export function isPanelDockConfig(obj: any): obj is PanelDockConfig { - return obj && obj.type === 'PanelDock'; -} diff --git a/packages/vision-polyfill/src/skeleton/widget/dialog-dock.ts b/packages/vision-polyfill/src/skeleton/widget/dialog-dock.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/vision-polyfill/src/skeleton/widget/dock.ts b/packages/vision-polyfill/src/skeleton/widget/dock.ts deleted file mode 100644 index 019b2e321..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/dock.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { uniqueId, createContent, obx } from '@ali/lowcode-globals'; -import { DockConfig } from "../types"; -import { Skeleton } from '../skeleton'; -import { DockView, WidgetView } from '../components/widget-views'; -import { IWidget } from './widget'; - -/** - * 带图标(主要)/标题(次要)的扩展 - */ -export default class Dock implements IWidget { - readonly isWidget = true; - readonly id = uniqueId('dock'); - readonly name: string; - readonly align?: string; - - @obx.ref private _visible: boolean = true; - get visible(): boolean { - return this._visible; - } - - get content(): ReactNode { - return createElement(WidgetView, { - widget: this, - key: this.id, - }); - } - - private inited: boolean = false; - private _body: ReactNode; - get body() { - if (this.inited) { - return this._body; - } - - const { props, content, contentProps } = this.config; - - if (content) { - this._body = createContent(content, { - ...contentProps, - config: this.config, - editor: this.skeleton.editor, - }); - } else { - this._body = createElement(DockView, props); - } - return this._body; - } - - constructor(readonly skeleton: Skeleton, readonly config: DockConfig) { - const { props = {}, name } = config; - this.name = name; - this.align = props.align; - } - - setVisible(flag: boolean) { - if (flag === this._visible) { - return; - } - if (flag) { - this._visible = true; - } else if (this.inited) { - this._visible = false; - } - } - - getContent() { - return this.content; - } - - getName() { - return this.name; - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } - - toggle() { - this.setVisible(!this._visible); - } -} diff --git a/packages/vision-polyfill/src/skeleton/widget/panel-dock.ts b/packages/vision-polyfill/src/skeleton/widget/panel-dock.ts deleted file mode 100644 index c47d3290a..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/panel-dock.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { uniqueId, obx, computed } from '@ali/lowcode-globals'; -import { createElement, ReactNode } from 'react'; -import { Skeleton } from '../skeleton'; -import { PanelDockConfig } from '../types'; -import Panel from './panel'; -import { PanelDockView, WidgetView } from '../components/widget-views'; -import { IWidget } from './widget'; - -export default class PanelDock implements IWidget { - readonly isWidget = true; - readonly id: string; - readonly name: string; - readonly align?: string; - - private inited: boolean = false; - private _body: ReactNode; - get body() { - if (this.inited) { - return this._body; - } - this.inited = true; - const { props } = this.config; - - this._body = createElement(PanelDockView, { - ...props, - dock: this, - }); - - return this._body; - } - - get content(): ReactNode { - return createElement(WidgetView, { - widget: this, - key: this.id, - }); - } - - @obx.ref private _visible: boolean = true; - get visible() { - return this._visible; - } - - @computed get actived(): boolean { - return this.panel?.visible || false; - } - - readonly panelName: string; - private _panel?: Panel; - @computed get panel() { - return this._panel || this.skeleton.getPanel(this.panelName); - } - - constructor(readonly skeleton: Skeleton, readonly config: PanelDockConfig) { - const { content, contentProps, panelProps, name, props } = config; - this.name = name; - this.id = uniqueId(`dock:${name}$`); - this.panelName = config.panelName || name; - if (content) { - this._panel = this.skeleton.add({ - type: "Panel", - name: this.panelName, - props: { - // FIXME! give default title for panel - // title: props ? composeTitle(props?.title, props?.icon, props?.description, true) : '', - ...panelProps, - }, - contentProps, - content, - area: panelProps?.area - }) as Panel; - } - } - - setVisible(flag: boolean) { - if (flag === this._visible) { - return; - } - if (flag) { - this._visible = true; - } else if (this.inited) { - this._visible = false; - } - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } - - toggle() { - this.setVisible(!this._visible); - } - - togglePanel() { - this.panel?.toggle(); - } - - getName() { - return this.name; - } - - getContent() { - return this.content; - } - - hidePanel() { - this.panel?.setActive(false); - } - - showPanel() { - this.panel?.setActive(true); - } -} diff --git a/packages/vision-polyfill/src/skeleton/widget/panel.ts b/packages/vision-polyfill/src/skeleton/widget/panel.ts deleted file mode 100644 index 9a33c3e44..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/panel.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { createElement, ReactNode } from 'react'; -import { obx, uniqueId, createContent, TitleContent } from '@ali/lowcode-globals'; -import WidgetContainer from './widget-container'; -import { PanelConfig, HelpTipConfig } from '../types'; -import { TitledPanelView, TabsPanelView, PanelView } from '../components/widget-views'; -import { Skeleton } from '../skeleton'; -import { composeTitle } from './utils'; -import { IWidget } from './widget'; - -export default class Panel implements IWidget { - readonly isWidget = true; - readonly name: string; - readonly id: string; - @obx.ref inited: boolean = false; - @obx.ref private _actived: boolean = false; - get actived(): boolean { - return this._actived; - } - - get visible(): boolean { - if (this.parent?.visible) { - return this._actived; - } - return false; - } - - readonly isPanel = true; - - private _body?: ReactNode; - get body() { - this.initBody(); - return this._body; - } - - get content(): ReactNode { - if (this.plain) { - return createElement(PanelView, { - panel: this, - key: this.id, - }); - } - return createElement(TitledPanelView, { panel: this, key: this.id }); - } - - readonly title: TitleContent; - readonly help?: HelpTipConfig; - private plain: boolean = false; - - private container?: WidgetContainer<Panel, PanelConfig>; - private parent?: WidgetContainer; - - constructor(readonly skeleton: Skeleton, readonly config: PanelConfig) { - const { name, content, props = {} } = config; - const { hideTitleBar, title, icon, description, help, shortcut } = props; - this.name = name; - this.id = uniqueId(`pane:${name}$`); - this.title = composeTitle(title || name, icon, description); - this.plain = hideTitleBar || !title; - this.help = help; - if (Array.isArray(content)) { - this.container = this.skeleton.createContainer( - name, - (item) => { - if (isPanel(item)) { - return item; - } - return this.skeleton.createPanel(item); - }, - true, - () => this.visible, - true, - ); - content.forEach((item) => this.add(item)); - } - // todo: process shortcut - } - - private initBody() { - if (this.inited) { - return; - } - this.inited = true; - if (this.container) { - this._body = createElement(TabsPanelView, { - container: this.container, - }); - } else { - const { content, contentProps } = this.config; - this._body = createContent(content, { - ...contentProps, - editor: this.skeleton.editor, - config: this.config, - panel: this, - }); - } - } - - setParent(parent: WidgetContainer) { - if (parent === this.parent) { - return; - } - if (this.parent) { - this.parent.remove(this); - } - this.parent = parent; - } - - add(item: Panel | PanelConfig) { - return this.container?.add(item); - } - - getPane(name: string): Panel | null { - return this.container?.get(name) || null; - } - - remove(item: Panel | string) { - return this.container?.remove(item); - } - - active(item?: Panel | string | null) { - this.container?.active(item); - } - - getName() { - return this.name; - } - - getContent() { - return this.content; - } - - setActive(flag: boolean) { - if (flag === this._actived) { - // TODO: 如果移动到另外一个 container,会有问题 - return; - } - if (flag) { - if (!this.inited) { - this.initBody(); - } - this._actived = true; - this.parent?.active(this); - } else if (this.inited) { - this._actived = false; - this.parent?.unactive(this); - } - } - - toggle() { - this.setActive(!this._actived); - } - - hide() { - this.setActive(false); - } - - show() { - this.setActive(true); - } -} - -export function isPanel(obj: any): obj is Panel { - return obj && obj.isPanel; -} diff --git a/packages/vision-polyfill/src/skeleton/widget/stage.ts b/packages/vision-polyfill/src/skeleton/widget/stage.ts deleted file mode 100644 index a4bf483f2..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/stage.ts +++ /dev/null @@ -1,51 +0,0 @@ -import Widget from './widget'; -import { Skeleton } from '../skeleton'; -import { WidgetConfig } from '../types'; - -export interface StageConfig extends WidgetConfig { - isRoot?: boolean; -} - -export class Stage extends Widget { - readonly isRoot: boolean; - private previous?: Stage; - private refer?: { - stage?: Stage; - direction?: 'right' | 'left'; - }; - - constructor(skeleton: Skeleton, config: StageConfig) { - super(skeleton, config); - this.isRoot = config.isRoot || false; - } - - setPrevious(stage: Stage) { - this.previous = stage; - } - - getPrevious() { - return this.previous; - } - - hasBack(): boolean { - return this.previous && !this.isRoot ? true : false; - } - - setRefer(stage: Stage, direction: 'right' | 'left') { - this.refer = { stage, direction }; - } - - setReferRight(stage: Stage) { - this.setRefer(stage, 'right'); - } - - setReferLeft(stage: Stage) { - this.setRefer(stage, 'left'); - } - - getRefer() { - const refer = this.refer; - this.refer = undefined; - return refer; - } -} diff --git a/packages/vision-polyfill/src/skeleton/widget/utils.ts b/packages/vision-polyfill/src/skeleton/widget/utils.ts deleted file mode 100644 index 301426a87..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { IconType, TitleContent, isI18nData, TipContent } from '@ali/lowcode-globals'; -import { isValidElement } from 'react'; - -export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean) { - if (!title) { - title = {}; - if (!icon || tipAsTitle) { - title.label = tip; - tip = undefined; - } - } - if (icon || tip) { - if (typeof title !== 'object' || isValidElement(title) || isI18nData(title)) { - title = { - label: title, - icon, - tip, - }; - } else { - title = { - ...title, - icon, - tip - }; - } - } - return title; -} diff --git a/packages/vision-polyfill/src/skeleton/widget/widget-container.ts b/packages/vision-polyfill/src/skeleton/widget/widget-container.ts deleted file mode 100644 index b34827ae7..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/widget-container.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { obx, hasOwnProperty, computed } from '@ali/lowcode-globals'; -import { isPanel } from './panel'; -export interface WidgetItem { - name: string; -} - -export interface Activeable { - setActive(flag: boolean): void; -} - -function isActiveable(obj: any): obj is Activeable { - return obj && obj.setActive; -} - -export default class WidgetContainer<T extends WidgetItem = any, G extends WidgetItem = any> { - @obx.val items: T[] = []; - private maps: { [name: string]: T } = {}; - @obx.ref private _current: T & Activeable | null = null; - - get current() { - return this._current; - } - - constructor( - readonly name: string, - private handle: (item: T | G) => T, - private exclusive: boolean = false, - private checkVisible: () => boolean = () => true, - private defaultSetCurrent: boolean = false, - ) {} - - @computed get visible() { - return this.checkVisible(); - } - - active(nameOrItem?: T | string | null) { - let item: any = nameOrItem; - if (nameOrItem && typeof nameOrItem === 'string') { - item = this.get(nameOrItem); - } - if (!isActiveable(nameOrItem)) { - item = null; - } - - if (this.exclusive) { - if (this._current === item) { - return; - } - if (this._current) { - this._current.setActive(false); - } - this._current = item; - } - - if (item) { - item.setActive(true); - } - } - - unactive(nameOrItem?: T | string | null) { - let item: any = nameOrItem; - if (nameOrItem && typeof nameOrItem === 'string') { - item = this.get(nameOrItem); - } - if (!isActiveable(nameOrItem)) { - item = null; - } - if (this._current === item) { - this._current = null; - } - if (item) { - item.setActive(false); - } - } - - add(item: T | G): T { - item = this.handle(item); - const origin = this.get(item.name); - if (origin === item) { - return origin; - } - const i = origin ? this.items.indexOf(origin) : -1; - if (i > -1) { - this.items[i] = item; - } else { - this.items.push(item); - } - this.maps[item.name] = item; - if (isPanel(item)) { - item.setParent(this); - } - if (this.defaultSetCurrent) { - if (!this._current) { - this.active(item); - } - } - return item; - } - - get(name: string): T | null { - return this.maps[name] || null; - } - - getAt(index: number): T | null { - return this.items[index] || null; - } - - has(name: string): boolean { - return hasOwnProperty(this.maps, name); - } - - indexOf(item: T): number { - return this.items.indexOf(item); - } - - /** - * return indexOf the deletion - */ - remove(item: string | T): number { - const thing = typeof item === 'string' ? this.get(item) : item; - if (!thing) { - return -1; - } - const i = this.items.indexOf(thing); - if (i > -1) { - this.items.splice(i, 1); - } - delete this.maps[thing.name]; - if (thing === this.current) { - this._current = null; - } - return i; - } -} diff --git a/packages/vision-polyfill/src/skeleton/widget/widget.ts b/packages/vision-polyfill/src/skeleton/widget/widget.ts deleted file mode 100644 index 1f7a7d84a..000000000 --- a/packages/vision-polyfill/src/skeleton/widget/widget.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { ReactNode, createElement } from 'react'; -import { createContent, uniqueId, obx } from '@ali/lowcode-globals'; -import { WidgetConfig, IWidgetBaseConfig } from '../types'; -import { Skeleton } from '../skeleton'; -import { WidgetView } from '../components/widget-views'; - -export interface IWidget { - readonly name: string; - readonly content: ReactNode; - readonly align?: string; - readonly isWidget: true; - readonly visible: boolean; - readonly body: ReactNode; - readonly skeleton: Skeleton; - readonly config: IWidgetBaseConfig; - - getName(): string; - getContent(): any; - show(): void; - hide(): void; - toggle(): void; -} - -export default class Widget implements IWidget { - readonly isWidget = true; - readonly id = uniqueId('widget'); - readonly name: string; - readonly align?: string; - - @obx.ref private _visible: boolean = true; - get visible(): boolean { - return this._visible; - } - - @obx.ref inited: boolean = false; - private _body: ReactNode; - get body() { - if (this.inited) { - return this._body; - } - this.inited = true; - const { content, contentProps } = this.config; - this._body = createContent(content, { - ...contentProps, - config: this.config, - editor: this.skeleton.editor, - }); - return this._body; - } - - get content(): ReactNode { - return createElement(WidgetView, { - widget: this, - key: this.id, - }); - } - - constructor(readonly skeleton: Skeleton, readonly config: WidgetConfig) { - const { props = {}, name } = config; - this.name = name; - this.align = props.align; - } - - getName() { - return this.name; - } - - getContent() { - return this.content; - } - - hide() { - this.setVisible(false); - } - - show() { - this.setVisible(true); - } - - setVisible(flag: boolean) { - if (flag === this._visible) { - return; - } - if (flag) { - this._visible = true; - } else if (this.inited) { - this._visible = false; - } - } - - toggle() { - this.setVisible(!this._visible); - } -} - -export function isWidget(obj: any): obj is IWidget { - return obj && obj.isWidget; -} - - diff --git a/packages/vision-polyfill/src/symbols.ts b/packages/vision-polyfill/src/symbols.ts deleted file mode 100644 index 4b8493292..000000000 --- a/packages/vision-polyfill/src/symbols.ts +++ /dev/null @@ -1,17 +0,0 @@ -export class SymbolManager { - private symbolMap: { [symbolName: string]: symbol } = {}; - - create(name: string): symbol { - if (this.symbolMap[name]) { - return this.symbolMap[name]; - } - this.symbolMap[name] = Symbol(name); - return this.symbolMap[name]; - } - - get(name: string) { - return this.symbolMap[name]; - } -} - -export default new SymbolManager(); diff --git a/packages/vision-polyfill/src/vision.ts b/packages/vision-polyfill/src/vision.ts index 7bca93882..969228f67 100644 --- a/packages/vision-polyfill/src/vision.ts +++ b/packages/vision-polyfill/src/vision.ts @@ -3,13 +3,12 @@ import Popup from '@ali/ve-popups'; import Icons from '@ali/ve-icons'; import { render } from 'react-dom'; import I18nUtil from '@ali/ve-i18n-util'; -import { hotkey as Hotkey } from '@ali/lowcode-globals'; +import { hotkey as Hotkey } from '@ali/lowcode-editor-core'; import { createElement } from 'react'; import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS } from './const'; import Bus from './bus'; -import Symbols from './symbols'; import { skeleton, editor } from './editor'; -import { VisionWorkbench } from './skeleton/layouts/workbench'; +import { Workbench } from '@ali/lowcode-editor-skeleton'; import Panes from './panes'; import Exchange from './exchange'; import VisualEngineContext from './context'; @@ -23,6 +22,8 @@ import Prop from './prop'; import Env from './env'; import './vision.less'; import DragEngine from './drag-engine'; +import * as EditorCore from '@ali/lowcode-editor-core'; +import * as Designer from '@ali/lowcode-designer'; function init(container?: Element) { if (!container) { @@ -32,7 +33,7 @@ function init(container?: Element) { container.id = 'engine'; render( - createElement(VisionWorkbench, { + createElement(Workbench, { skeleton, }), container, @@ -60,6 +61,8 @@ const modules = { const context = new VisualEngineContext(); const VisualEngine = { + EditorCore, + Designer, editor, skeleton, /** @@ -79,8 +82,6 @@ const VisualEngine = { EVENTS, /* 修饰方法 */ HOOKS, - /* Symbol 管理类 */ - Symbols, Exchange, context, /** @@ -103,6 +104,7 @@ export default VisualEngine; (window as any).VisualEngine = VisualEngine; + /* console.log( `%cLowcodeEngine %cv${VERSION}`,