diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index 3782d394..d5833884 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -58,7 +58,11 @@ diff --git a/packages/editor/src/components/SplitView.vue b/packages/editor/src/components/SplitView.vue index ccb2c748..cc6d5c30 100644 --- a/packages/editor/src/components/SplitView.vue +++ b/packages/editor/src/components/SplitView.vue @@ -27,7 +27,7 @@ import { OnDrag } from 'gesto'; import Resizer from './Resizer.vue'; defineOptions({ - name: 'MEditorLayout', + name: 'MEditorSplitView', }); const emit = defineEmits(['update:left', 'change', 'update:right']); diff --git a/packages/editor/src/editorProps.ts b/packages/editor/src/editorProps.ts index 8feb750c..942b5c31 100644 --- a/packages/editor/src/editorProps.ts +++ b/packages/editor/src/editorProps.ts @@ -78,6 +78,8 @@ export interface EditorProps { disabledMultiSelect?: boolean; /** 禁用页面片 */ disabledPageFragment?: boolean; + /** 禁用双击在浮层中单独编辑选中组件 */ + disabledStageOverlay?: boolean; /** 中间工作区域中画布渲染的内容 */ render?: (stage: StageCore) => HTMLDivElement | Promise; /** 选中时会在画布上复制出一个大小相同的dom,实际拖拽的是这个dom,此方法用于干预这个dom的生成方式 */ @@ -95,6 +97,7 @@ export const defaultEditorProps = { renderType: RenderType.IFRAME, disabledMultiSelect: false, disabledPageFragment: false, + disabledStageOverlay: false, containerHighlightClassName: CONTAINER_HIGHLIGHT_CLASS_NAME, containerHighlightDuration: 800, containerHighlightType: ContainerHighlightType.DEFAULT, diff --git a/packages/editor/src/hooks/use-stage-overlay.ts b/packages/editor/src/hooks/use-stage-overlay.ts deleted file mode 100644 index 01ba8cc2..00000000 --- a/packages/editor/src/hooks/use-stage-overlay.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { computed, inject, nextTick, ref, watch } from 'vue'; - -import type StageCore from '@tmagic/stage'; - -import type { Services, StageOptions } from '@editor/type'; - -import { useStage } from './use-stage'; - -export const useStageOverlay = () => { - const services = inject('services'); - const stageOptions = inject('stageOptions'); - - const wrapWidth = ref(0); - const wrapHeight = ref(0); - const stageOverlayVisible = ref(false); - const stageOverlay = ref(); - - const stage = computed(() => services?.editorService.get('stage')); - - let subStage: StageCore | null = null; - - const div = document.createElement('div'); - let selectEl: HTMLElement | null = null; - - const render = () => { - if (!selectEl) return; - - const content = selectEl.cloneNode(true) as HTMLElement; - content.style.position = 'static'; - Array.from(div.children).forEach((element) => { - element.remove(); - }); - div.appendChild(content); - - subStage?.renderer.contentWindow?.magic.onPageElUpdate(div); - - subStage?.select(content); - }; - - const copyDocumentElement = () => { - const doc = subStage?.renderer.getDocument(); - const documentElement = stage.value?.renderer.getDocument()?.documentElement; - - if (doc && documentElement) { - doc.replaceChild(documentElement.cloneNode(true), doc.documentElement); - } - }; - - const updateOverlay = () => { - if (!selectEl) return; - - const { scrollWidth, scrollHeight } = selectEl; - - stageOverlay.value!.style.width = `${scrollWidth}px`; - stageOverlay.value!.style.height = `${scrollHeight}px`; - - wrapWidth.value = scrollWidth; - wrapHeight.value = scrollHeight; - }; - - const updateHandler = () => { - render(); - updateOverlay(); - }; - - const addHandler = () => { - render(); - updateOverlay(); - }; - - const removeHandler = () => { - render(); - updateOverlay(); - }; - - const openOverlay = async (el: HTMLElement) => { - selectEl = el; - - stageOverlayVisible.value = true; - - if (!stageOverlay.value) { - await nextTick(); - } - - if (!stageOptions) { - return; - } - - subStage = useStage({ - ...stageOptions, - runtimeUrl: '', - autoScrollIntoView: false, - render(stage: StageCore) { - copyDocumentElement(); - - const rootEl = stage.renderer.getDocument()?.getElementById('app'); - if (rootEl) { - rootEl.remove(); - } - - div.style.cssText = ` - width: ${el.scrollWidth}px; - height: ${el.scrollHeight}px; - background-color: #fff; - `; - - render(); - - return div; - }, - }); - subStage.mount(stageOverlay.value!); - - const { mask, renderer } = subStage; - - const { contentWindow } = renderer; - mask.showRule(false); - - updateOverlay(); - - contentWindow?.magic.onRuntimeReady({}); - - services?.editorService.on('update', updateHandler); - services?.editorService.on('add', addHandler); - services?.editorService.on('remove', removeHandler); - }; - - const closeOverlay = () => { - stageOverlayVisible.value = false; - subStage?.destroy(); - subStage = null; - - services?.editorService.off('update', updateHandler); - services?.editorService.off('add', addHandler); - services?.editorService.off('remove', removeHandler); - }; - - watch(stage, (stage) => { - if (stage) { - stage.on('dblclick', async (event: MouseEvent) => { - const el = await stage.actionManager.getElementFromPoint(event); - if (el) { - openOverlay(el); - } - }); - } else if (subStage) { - closeOverlay(); - } - }); - - return { - wrapWidth, - wrapHeight, - stageOverlayVisible, - stageOverlay, - closeOverlay, - }; -}; diff --git a/packages/editor/src/hooks/use-stage.ts b/packages/editor/src/hooks/use-stage.ts index f0cf7ab8..e6052f29 100644 --- a/packages/editor/src/hooks/use-stage.ts +++ b/packages/editor/src/hooks/use-stage.ts @@ -33,7 +33,9 @@ export const useStage = (stageOptions: StageOptions) => { disabledDragStart: stageOptions.disabledDragStart, renderType: stageOptions.renderType, canSelect: (el, event, stop) => { - const elCanSelect = stageOptions.canSelect(el); + if (!stageOptions.canSelect) return true; + + const elCanSelect = stageOptions.canSelect?.(el); // 在组件联动过程中不能再往下选择,返回并触发 ui-select if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') { document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: el })); diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index b36c4468..2c1b4428 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -54,6 +54,7 @@ export { default as historyService } from './services/history'; export { default as storageService } from './services/storage'; export { default as eventsService } from './services/events'; export { default as dataSourceService } from './services/dataSource'; +export { default as stageOverlayService } from './services/stageOverlay'; export { default as uiService } from './services/ui'; export { default as codeBlockService } from './services/codeBlock'; export { default as depService } from './services/dep'; diff --git a/packages/editor/src/layouts/sidebar/ComponentListPanel.vue b/packages/editor/src/layouts/sidebar/ComponentListPanel.vue index 4f0dff08..db899a14 100644 --- a/packages/editor/src/layouts/sidebar/ComponentListPanel.vue +++ b/packages/editor/src/layouts/sidebar/ComponentListPanel.vue @@ -108,8 +108,8 @@ const dragendHandler = () => { globalThis.clearTimeout(timeout); timeout = undefined; } - const doc = stage.value?.renderer.contentWindow?.document; - if (doc && stageOptions) { + const doc = stage.value?.renderer.getDocument(); + if (doc && stageOptions?.containerHighlightClassName) { removeClassNameByClassName(doc, stageOptions.containerHighlightClassName); } clientX = 0; diff --git a/packages/editor/src/layouts/workspace/Workspace.vue b/packages/editor/src/layouts/workspace/Workspace.vue index b3df0ec6..6bd84aaf 100644 --- a/packages/editor/src/layouts/workspace/Workspace.vue +++ b/packages/editor/src/layouts/workspace/Workspace.vue @@ -5,6 +5,7 @@ @@ -28,10 +29,16 @@ defineOptions({ name: 'MEditorWorkspace', }); -defineProps<{ - stageContentMenu: (MenuButton | MenuComponent)[]; - customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[]; -}>(); +withDefaults( + defineProps<{ + stageContentMenu: (MenuButton | MenuComponent)[]; + disabledStageOverlay?: boolean; + customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[]; + }>(), + { + disabledStageOverlay: false, + }, +); const services = inject('services'); diff --git a/packages/editor/src/layouts/workspace/viewer/Stage.vue b/packages/editor/src/layouts/workspace/viewer/Stage.vue index 3ce7d6f1..f77842c4 100644 --- a/packages/editor/src/layouts/workspace/viewer/Stage.vue +++ b/packages/editor/src/layouts/workspace/viewer/Stage.vue @@ -26,7 +26,7 @@