diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-detecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-detecting.tsx index 1f1735801..abc1c9cc5 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-detecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-detecting.tsx @@ -73,6 +73,14 @@ export class BorderDetecting extends Component<{ host: BuiltinSimulatorHost }> { render() { const { host } = this.props; const { current } = this; + + const canHoverHook = current?.componentMeta.getMetadata()?.experimental?.callbacks?.onHoverHook; + const canHover = (canHoverHook && typeof canHoverHook === 'function') ? canHoverHook(current) : true; + + if (!canHover) { + return null; + } + if (!current || host.viewport.scrolling || host.liveEditing.editing) { return null; } diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx index 7b47b709b..4a6b98d8f 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx @@ -82,7 +82,7 @@ export class BoxResizingForNode extends Component<{ host: BuiltinSimulatorHost; const { node } = this.props; const { designer } = this.host; - if (!instances || instances.length < 1) { + if (!instances || instances.length < 1 || this.dragging) { return null; } return ( @@ -114,9 +114,15 @@ export class BoxResizingInstance extends Component<{ // private outline: any; private willUnbind: () => any; - private outlineRight: any; - - private outlineLeft: any; + // outline of eight direction + private outlineN: any; + private outlineE: any; + private outlineS: any; + private outlineW: any; + private outlineNE: any; + private outlineNW: any; + private outlineSE: any; + private outlineSW: any; private dragEngine: DragResizeEngine; @@ -204,29 +210,33 @@ export class BoxResizingInstance extends Component<{ this.willUnbind(); } - if (!this.outlineRight && !this.outlineLeft) { + if ( + !this.outlineN && + !this.outlineE && + !this.outlineS && + !this.outlineW && + !this.outlineNE && + !this.outlineNW && + !this.outlineSE && + !this.outlineSW + ) { return; } const unBind: any[] = []; + const node = this.props.observed.node; unBind.push( - this.dragEngine.from(this.outlineRight, 'e', () => { - // if (!this.hoveringLine.hasOutline()) { - // return null; - // } - // return this.hoveringLine.getCurrentNode(); - return this.props.observed.node; - }), - ); - unBind.push( - this.dragEngine.from(this.outlineLeft, 'w', () => { - return this.props.observed.node; - // if (!this.hoveringLine.hasOutline()) { - // return null; - // } - // return this.hoveringLine.getCurrentNode(); - }), + ...[ + this.dragEngine.from(this.outlineN, 'n', () => node), + this.dragEngine.from(this.outlineE, 'e', () => node), + this.dragEngine.from(this.outlineS, 's', () => node), + this.dragEngine.from(this.outlineW, 'w', () => node), + this.dragEngine.from(this.outlineNE, 'ne', () => node), + this.dragEngine.from(this.outlineNW, 'nw', () => node), + this.dragEngine.from(this.outlineSE, 'se', () => node), + this.dragEngine.from(this.outlineSW, 'sw', () => node), + ], ); this.willUnbind = () => { @@ -252,29 +262,36 @@ export class BoxResizingInstance extends Component<{ triggerVisible = metaData.experimental.getResizingHandlers(node); } - const className = classNames('lc-borders lc-resize-box'); + const baseSideClass = 'lc-borders lc-resize-side'; + const baseCornerClass = 'lc-borders lc-resize-corner'; return (
- {triggerVisible.includes('w') && ( + {triggerVisible.includes('n') && (
{ - this.outlineLeft = ref; - }} - className={className} + ref={(ref) => { this.outlineN = ref; }} + className={classNames(baseSideClass, 'n')} style={{ - height: offsetHeight, - transform: `translate(${offsetLeft - 10}px, ${offsetTop}px)`, - width: 20, + height: 20, + transform: `translate(${offsetLeft}px, ${offsetTop - 10}px)`, + width: offsetWidth, + }} + /> + )} + {triggerVisible.includes('ne') && ( +
{ this.outlineNE = ref; }} + className={classNames(baseCornerClass, 'ne')} + style={{ + transform: `translate(${offsetLeft + offsetWidth - 5}px, ${offsetTop - 3}px)`, + cursor: 'nesw-resize', }} /> )} {triggerVisible.includes('e') && (
{ - this.outlineRight = ref; - }} + className={classNames(baseSideClass, 'e')} + ref={(ref) => { this.outlineE = ref; }} style={{ height: offsetHeight, transform: `translate(${offsetLeft + offsetWidth - 10}px, ${offsetTop}px)`, @@ -282,6 +299,58 @@ export class BoxResizingInstance extends Component<{ }} /> )} + {triggerVisible.includes('se') && ( +
{ this.outlineSE = ref; }} + className={classNames(baseCornerClass, 'se')} + style={{ + transform: `translate(${offsetLeft + offsetWidth - 5}px, ${offsetTop + offsetHeight - 5}px)`, + cursor: 'nwse-resize', + }} + /> + )} + {triggerVisible.includes('s') && ( +
{ this.outlineS = ref; }} + className={classNames(baseSideClass, 's')} + style={{ + height: 20, + transform: `translate(${offsetLeft}px, ${offsetTop + offsetHeight - 10}px)`, + width: offsetWidth, + }} + /> + )} + {triggerVisible.includes('sw') && ( +
{ this.outlineSW = ref; }} + className={classNames(baseCornerClass, 'sw')} + style={{ + transform: `translate(${offsetLeft - 3}px, ${offsetTop + offsetHeight - 5}px)`, + cursor: 'nesw-resize', + }} + /> + )} + {triggerVisible.includes('w') && ( +
{ this.outlineW = ref; }} + className={classNames(baseSideClass, 'w')} + style={{ + height: offsetHeight, + transform: `translate(${offsetLeft - 10}px, ${offsetTop}px)`, + width: 20, + }} + /> + )} + {triggerVisible.includes('nw') && ( +
{ this.outlineNW = ref; }} + className={classNames(baseCornerClass, 'nw')} + style={{ + transform: `translate(${offsetLeft - 3}px, ${offsetTop - 3}px)`, + cursor: 'nwse-resize', + }} + /> + )}
); } diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx index 919bcf876..0a09dd1d9 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx @@ -46,6 +46,12 @@ export class BorderSelectingInstance extends Component<{ dragging, }); + const hideSelectTools = observed.node.componentMeta.getMetadata().experimental?.hideSelectTools; + + if (hideSelectTools) { + return null; + } + return (
{!dragging && } diff --git a/packages/designer/src/builtin-simulator/bem-tools/borders.less b/packages/designer/src/builtin-simulator/bem-tools/borders.less index 4b10396ed..b5df1dc52 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/borders.less +++ b/packages/designer/src/builtin-simulator/bem-tools/borders.less @@ -49,10 +49,19 @@ } } - &.lc-resize-box { + &.lc-resize-corner { + display: inline-block; + width: 8px; + height: 8px; + border: 1px solid #197aff; + background: #fff; + pointer-events: auto; + z-index: 2; + } + + &.lc-resize-side { border-width: 0; z-index: 1; - cursor: ew-resize; pointer-events: auto; align-items: center; justify-content: center; @@ -61,13 +70,32 @@ &:after { content: ""; display: block; - height: calc(100% - 20px); - min-height: 50%; - width: 4px; - background: #738397; + border: 1px solid #197aff; + background: #fff; + // background: #738397; border-radius: 2px; // animation: flashing 1.5s infinite linear; } + + &.e, + &.w { + cursor: ew-resize; + &:after { + width: 4px; + // height: calc(100% - 20px); + min-height: 50%; + } + } + + &.n, + &.s { + cursor: ns-resize; + &:after { + // width: calc(100% - 20px); + min-width: 50%; + height: 4px; + } + } } // &&-hovering { diff --git a/packages/designer/src/designer/drag-ghost/index.tsx b/packages/designer/src/designer/drag-ghost/index.tsx index 021dee612..195d3cacd 100644 --- a/packages/designer/src/designer/drag-ghost/index.tsx +++ b/packages/designer/src/designer/drag-ghost/index.tsx @@ -37,7 +37,7 @@ export default class DragGhost extends Component<{ designer: Designer }> { this.y = e.globalY; if (isSimulatorHost(e.sensor)) { const container = e.sensor.getDropContainer(e); - if (container.container.componentMeta.getMetadata().experimental?.isAbsoluteLayoutContainer) { + if (container?.container.componentMeta.getMetadata().experimental?.isAbsoluteLayoutContainer) { this.isAbsoluteLayoutContainer = true; return; } diff --git a/packages/editor-preset-vision/src/bundle/upgrade-metadata.ts b/packages/editor-preset-vision/src/bundle/upgrade-metadata.ts index 2f98b4c22..3333bbbec 100644 --- a/packages/editor-preset-vision/src/bundle/upgrade-metadata.ts +++ b/packages/editor-preset-vision/src/bundle/upgrade-metadata.ts @@ -137,6 +137,7 @@ export interface OldPrototypeConfig { isContainer?: boolean; // => configure.component.isContainer isAbsoluteLayoutContainer?: boolean; // => meta.experimental.isAbsoluteLayoutContainer 是否是绝对定位容器 + hideSelectTools?: boolean; // => meta.experimental.hideSelectTools isModal?: boolean; // => configure.component.isModal isFloating?: boolean; // => configure.component.isFloating descriptor?: string; // => configure.component.descriptor @@ -144,6 +145,7 @@ export interface OldPrototypeConfig { // alias to canDragging canDraging?: boolean; // => onDrag canDragging?: boolean; // => ? + canHovering?: ((dragment: Node) => boolean) | boolean; canSelecting?: boolean; // => onClickHook canOperating?: boolean; // => disabledActions @@ -596,6 +598,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { transducers, isContainer, isAbsoluteLayoutContainer, + hideSelectTools, rectSelector, isModal, isFloating, @@ -614,6 +617,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { canDraging, canDragging, // handleDragging canSelecting, // onClickHook + canHovering, // events didDropOut, // onNodeRemove didDropIn, // onNodeAdd @@ -686,6 +690,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { // 未考虑清楚的,放在实验性段落 const experimental: any = { isAbsoluteLayoutContainer, + hideSelectTools, }; if (context) { // for prototype.getContextInfo @@ -743,7 +748,7 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { if (canResizing) { // TODO: enhance experimental.getResizingHandlers = (currentNode: any) => { - const directs = ['n', 'w', 's', 'e']; + const directs = ['n', 'e', 's', 'w', 'ne', 'nw', 'se', 'sw']; if (canResizing === true) { return directs; } @@ -766,6 +771,9 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { } callbacks.onClickHook = () => v; } + if (canHovering != null) { + callbacks.onHoverHook = typeof canHovering === 'boolean' ? () => canHovering : canHovering; + } if (didDropIn) { callbacks.onNodeAdd = didDropIn; } diff --git a/packages/types/src/metadata.ts b/packages/types/src/metadata.ts index 96299d66c..7ea0428fc 100644 --- a/packages/types/src/metadata.ts +++ b/packages/types/src/metadata.ts @@ -66,6 +66,7 @@ export interface Experimental { callbacks?: Callbacks; initialChildren?: NodeData[] | ((target: SettingTarget) => NodeData[]); isAbsoluteLayoutContainer: boolean; + hideSelectTools?: boolean; // 样式 及 位置,handle上必须有明确的标识以便事件路由判断,或者主动设置事件独占模式 // NWSE 是交给引擎计算放置位置,ReactElement 必须自己控制初始位置 @@ -183,6 +184,7 @@ export interface Callbacks { // onLocateHook?: (e: any, currentNode: any) => any; // onAcceptHook?: (currentNode: any, locationData: any) => any; onMoveHook?: (currentNode: any) => boolean; // thinkof 限制性拖拽 + onHoverHook?: (currentNode: any) => boolean; onChildMoveHook?: (childNode: any, currentNode: any) => boolean; // events