diff --git a/packages/vision-preset/src/bundle/bundle.ts b/packages/vision-preset/src/bundle/bundle.ts index 6e00f7e58..d74c3de12 100644 --- a/packages/vision-preset/src/bundle/bundle.ts +++ b/packages/vision-preset/src/bundle/bundle.ts @@ -100,6 +100,22 @@ export default class Bundle { cp.setView(view); } + /** + * TODO dirty fix + */ + addComponentBundle(bundles: any) { + /** + * Normal Component bundle: [ Prototype, PrototypeView ] + * Component without Prototype.js: [ View ] + */ + if (bundles.length >= 2) { + const prototype = bundles[0]; + const prototypeView = bundles[1]; + prototype.setView(prototypeView); + this.registerPrototype(prototype); + } + } + private recursivelyRegisterViews(list: any[], viewName?: string): void { list.forEach((item: any) => { if (Array.isArray(item.module)) { diff --git a/packages/vision-preset/src/editor.ts b/packages/vision-preset/src/editor.ts index 96cc11e03..61d3b0843 100644 --- a/packages/vision-preset/src/editor.ts +++ b/packages/vision-preset/src/editor.ts @@ -80,15 +80,15 @@ skeleton.add({ type: 'Panel', content: SettingsPrimaryPane, }); -skeleton.add({ - area: 'leftArea', - name: 'outlinePane', - type: 'PanelDock', - content: Outline, - panelProps: { - area: 'leftFixedArea', - }, -}); +// skeleton.add({ +// area: 'leftArea', +// name: 'outlinePane', +// type: 'PanelDock', +// content: Outline, +// panelProps: { +// area: 'leftFixedArea', +// }, +// }); skeleton.add({ area: 'topArea', diff --git a/packages/vision-preset/src/exchange.ts b/packages/vision-preset/src/exchange.ts index df71cff14..6e1f8c13e 100644 --- a/packages/vision-preset/src/exchange.ts +++ b/packages/vision-preset/src/exchange.ts @@ -12,4 +12,13 @@ export default { const nodes = designer.currentSelection?.getNodes(); return nodes?.[0]; }, + /** + * TODO dirty fix + */ + onIntoView(func: (node: any, insertion: any) => any) { + // this.emitter.on('intoview', func); + return () => { + // this.emitter.removeListener('intoview', func); + }; + } } diff --git a/packages/vision-preset/src/index.ts b/packages/vision-preset/src/index.ts index 2c4db40e9..b3eaa9b01 100644 --- a/packages/vision-preset/src/index.ts +++ b/packages/vision-preset/src/index.ts @@ -1,11 +1,12 @@ import * as utils from '@ali/ve-utils'; import Popup from '@ali/ve-popups'; import Icons from '@ali/ve-icons'; +import logger from '@ali/vu-logger'; import { render } from 'react-dom'; import I18nUtil from '@ali/ve-i18n-util'; import { hotkey as Hotkey } from '@ali/lowcode-editor-core'; import { createElement } from 'react'; -import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS } from './base/const'; +import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const'; import Bus from './bus'; import { skeleton } from './editor'; import { Workbench } from '@ali/lowcode-editor-skeleton'; @@ -21,6 +22,8 @@ import * as Field from './fields'; import Prop from './prop'; import Env from './env'; import DragEngine from './drag-engine'; +import Viewport from './viewport'; +import Project from './project'; import { designer, editor } from './editor'; import './vision.less'; @@ -101,6 +104,10 @@ const VisualEngine = { Bundle, Pages, DragEngine, + Viewport, + Version, + Project, + logger, }; (window as any).VisualEngine = VisualEngine; @@ -144,6 +151,10 @@ export { Bundle, Pages, DragEngine, + Viewport, + Version, + Project, + logger, }; diff --git a/packages/vision-preset/src/project.ts b/packages/vision-preset/src/project.ts new file mode 100644 index 000000000..ba5d2309b --- /dev/null +++ b/packages/vision-preset/src/project.ts @@ -0,0 +1,17 @@ +class Project { + private schema: any; + + constructor() { + this.schema = {}; + } + + getSchema() { + return this.schema; + } + + setSchema(schema: any) { + this.schema = schema; + } +} + +export default new Project(); diff --git a/packages/vision-preset/src/viewport.ts b/packages/vision-preset/src/viewport.ts new file mode 100644 index 000000000..0b5ec7cb7 --- /dev/null +++ b/packages/vision-preset/src/viewport.ts @@ -0,0 +1,278 @@ +import { EventEmitter } from 'events'; + +const domReady = require('domready'); +import Flags from './flags'; + +function enterFullscreen() { + const elem = document.documentElement; + if (elem.requestFullscreen) { + elem.requestFullscreen(); + } +} + +function exitFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen(); + } +} + +function isFullscreen() { + return document.fullscreen || false; +} + +interface IStyleResourceConfig { + media?: string; + type?: string; + content?: string; +} + +class StyleResource { + config: IStyleResourceConfig; + styleElement: HTMLStyleElement; + mounted: boolean; + inited: boolean; + + constructor(config: IStyleResourceConfig) { + this.config = config || {}; + } + + matchDevice(device: string) { + const media = this.config.media; + + if (!media || media === 'ALL' || media === '*') { + return true; + } + + return media.toUpperCase() === device.toUpperCase(); + } + + init() { + if (this.inited) { + return; + } + + this.inited = true; + + const { type, content } = this.config; + + let styleElement; + if (type === 'URL') { + styleElement = document.createElement('link'); + styleElement.href = content || ''; + styleElement.rel = 'stylesheet'; + } else { + styleElement = document.createElement('style'); + styleElement.setAttribute('type', 'text/css'); + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = content; + } else { + styleElement.appendChild(document.createTextNode(content || '')); + } + } + this.styleElement = styleElement; + } + + apply() { + if (this.mounted) { + return; + } + + this.init(); + document.head.appendChild(this.styleElement); + this.mounted = true; + } + + unmount() { + if (!this.mounted) { + return; + } + document.head.removeChild(this.styleElement); + this.mounted = false; + } +} + +export class Viewport { + preview: boolean; + focused: boolean; + slateFixed: boolean; + emitter: EventEmitter; + device: string; + focusTarget: any; + cssResourceSet: StyleResource[]; + + constructor() { + this.preview = false; + this.emitter = new EventEmitter(); + document.addEventListener('webkitfullscreenchange', () => { + this.emitter.emit('fullscreenchange', this.isFullscreen()); + }); + domReady(() => this.applyMediaCSS()); + } + + setFullscreen(flag: boolean) { + const fullscreen = this.isFullscreen(); + if (fullscreen && !flag) { + exitFullscreen(); + } else if (!fullscreen && flag) { + enterFullscreen(); + } + } + + toggleFullscreen() { + if (this.isFullscreen()) { + exitFullscreen(); + } else { + enterFullscreen(); + } + } + + isFullscreen() { + return isFullscreen(); + } + + setFocus(flag: boolean) { + if (this.focused && !flag) { + this.focused = false; + Flags.remove('view-focused'); + this.emitter.emit('focuschange', false); + } else if (!this.focused && flag) { + this.focused = true; + Flags.add('view-focused'); + this.emitter.emit('focuschange', true); + } + } + + setFocusTarget(focusTarget: any) { + this.focusTarget = focusTarget; + } + + returnFocus() { + if (this.focusTarget) { + this.focusTarget.focus(); + } + } + + isFocus() { + return this.focused; + } + + setPreview(flag: boolean) { + if (this.preview && !flag) { + this.preview = false; + Flags.setPreviewMode(false); + this.emitter.emit('preview', false); + this.changeViewport(); + } else if (!this.preview && flag) { + this.preview = true; + Flags.setPreviewMode(true); + this.emitter.emit('preview', true); + this.changeViewport(); + } + } + + togglePreview() { + if (this.isPreview()) { + this.setPreview(false); + } else { + this.setPreview(true); + } + } + + isPreview() { + return this.preview; + } + + setDevice(device = 'pc') { + if (this.getDevice() !== device) { + this.device = device; + Flags.setSimulator(device); + this.applyMediaCSS(); + this.emitter.emit('devicechange', device); + this.changeViewport(); + } + } + + getDevice() { + return this.device || 'pc'; + } + + changeViewport() { + this.emitter.emit('viewportchange', this.getViewport()); + } + + getViewport() { + return `${this.isPreview() ? 'preview' : 'design'}-${this.getDevice()}`; + } + + applyMediaCSS() { + if (!document.head || !this.cssResourceSet) { + return; + } + const device = this.getDevice(); + this.cssResourceSet.forEach((item) => { + if (item.matchDevice(device)) { + item.apply(); + } else { + item.unmount(); + } + }); + } + + setGlobalCSS(resourceSet: IStyleResourceConfig[]) { + if (this.cssResourceSet) { + this.cssResourceSet.forEach((item) => { + item.unmount(); + }); + } + this.cssResourceSet = resourceSet.map((item: IStyleResourceConfig) => new StyleResource(item)).reverse(); + this.applyMediaCSS(); + } + + setWithShell(shell: string) { + Flags.setWithShell(shell); + } + + onFullscreenChange(func: () => any) { + this.emitter.on('fullscreenchange', func); + return () => { + this.emitter.removeListener('fullscreenchange', func); + }; + } + + onPreview(func: () => any) { + this.emitter.on('preview', func); + return () => { + this.emitter.removeListener('preview', func); + }; + } + + onDeviceChange(func: () => any) { + this.emitter.on('devicechange', func); + return () => { + this.emitter.removeListener('devicechange', func); + }; + } + + onSlateFixedChange(func: (flag: boolean) => any) { + this.emitter.on('slatefixed', func); + return () => { + this.emitter.removeListener('slatefixed', func); + }; + } + + onViewportChange(func: () => any) { + this.emitter.on('viewportchange', func); + return () => { + this.emitter.removeListener('viewportchange', func); + }; + } + + onFocusChange(func: (flag: boolean) => any) { + this.emitter.on('focuschange', func); + return () => { + this.emitter.removeListener('focuschange', func); + }; + } +} + +export default new Viewport();