diff --git a/packages/core/src/commands/view/ComponentDrag.ts b/packages/core/src/commands/view/ComponentDrag.ts index d856d79e0..d4993b1cb 100644 --- a/packages/core/src/commands/view/ComponentDrag.ts +++ b/packages/core/src/commands/view/ComponentDrag.ts @@ -385,43 +385,16 @@ export default { position, }); } - - // TODO: remove this and move to the drag:start event - const originComponent = target; - const originComponentView = getComponentView(originComponent?.getEl()); - const originGuides = this.renderGuideInfo(guidesTarget); - - const dragStartProps: DragEventProps = { - originComponent, - originComponentView, - originGuides, - }; - - this.editor!.trigger(`${evName}:drag:start`, dragStartProps); }, onDrag() { const { guidesTarget, opts } = this; - let matchedGuides: MatchedGuide[] = []; const guidesTargetActive = guidesTarget?.filter((item) => item.active) ?? []; this.updateGuides(guidesTarget); opts?.debug && guidesTarget?.forEach((item) => this.renderGuide(item)); - opts?.guidesInfo && (matchedGuides = this.renderGuideInfo(guidesTargetActive)); + opts?.guidesInfo && this.renderGuideInfo(guidesTargetActive); opts?.onDrag?.(this._getDragData()); - - const matchedComponentEl = matchedGuides[0]?.matched.origin; - let matchedComponent = getComponentModel(matchedComponentEl); - let matchedComponentView = getComponentView(matchedComponentEl); - - const dragMoveProps: DragEventProps = { - matchedComponent, - matchedComponentView, - matchedGuides, - }; - - // TODO: use the `${evName}:move` event - this.editor!.trigger(`${evName}:drag:move`, dragMoveProps); }, onEnd(ev, _dragger, opt) { @@ -431,8 +404,6 @@ export default { this.hideGuidesInfo(); this.em.trigger(`${evName}:end`, this.getEventOpts()); - - this.em.trigger(`${evName}:drag:end`, undefined); }, hideGuidesInfo() { @@ -442,94 +413,101 @@ export default { }); }, - /** - * Render guides with spacing information - */ - // TODO: consider splitting this method into getMatchedGuides and renderGuideInfo renderGuideInfo(guides = []) { - const { guidesStatic } = this; + const matchedGuides = this.getMatchedGuides(guides); + this.hideGuidesInfo(); - const guidesData = guides.map((item) => { - const { origin, x } = item; - const rectOrigin = this.getElementPos(origin); - const axis = isUndefined(x) ? 'y' : 'x'; - const isY = axis === 'y'; - const origEdge1 = rectOrigin[isY ? 'left' : 'top']; - const origEdge1Raw = rectOrigin.rect[isY ? 'left' : 'top']; - const origEdge2 = isY ? origEdge1 + rectOrigin.width : origEdge1 + rectOrigin.height; - const origEdge2Raw = isY ? origEdge1Raw + rectOrigin.rect.width : origEdge1Raw + rectOrigin.rect.height; - const elGuideInfo = this[`elGuideInfo${axis.toUpperCase()}` as ElGuideInfoKey]; - const elGuideInfoCnt = this[`elGuideInfoContent${axis.toUpperCase()}` as ElGuideInfoContentKey]; - const guideInfoStyle = elGuideInfo?.style; - - let guideMatched: MatchedGuide | null = null; - - // Find the nearest element - const matched = guidesStatic - ?.filter((stat) => stat.type === item.type) - .map((stat) => { - const { left, width, top, height } = stat.originRect; - const statEdge1 = isY ? left : top; + matchedGuides.forEach((matchedGuide) => { + // TODO: improve this + if (!this.opts?.skipGuidesRender) { + this.renderSingleGuideInfo(matchedGuide); + } + + this.em.trigger(`${evName}:active`, { + ...this.getEventOpts(), + ...matchedGuide, + }); + }); + }, + + renderSingleGuideInfo(matchedGuide: MatchedGuide) { + const { posFirst, posSecond, size, sizeRaw, guide, elGuideInfo, elGuideInfoCnt } = matchedGuide; + + const axis = isUndefined(guide.x) ? 'y' : 'x'; + const isY = axis === 'y'; + const guideInfoStyle = elGuideInfo?.style; + + if (guideInfoStyle) { + guideInfoStyle.display = ''; + guideInfoStyle[isY ? 'top' : 'left'] = `${posFirst}px`; + guideInfoStyle[isY ? 'left' : 'top'] = `${posSecond}px`; + guideInfoStyle[isY ? 'width' : 'height'] = `${size}px`; + } + + if (elGuideInfoCnt) { + elGuideInfoCnt.innerHTML = `${Math.round(sizeRaw)}px`; + } + }, + + getMatchedGuides(guides = []): MatchedGuide[] { + const { guidesStatic } = this; + + return guides + .map((item) => { + const { origin, x } = item; + const rectOrigin = this.getElementPos(origin); + const axis = isUndefined(x) ? 'y' : 'x'; + const isY = axis === 'y'; + const origEdge1 = rectOrigin[isY ? 'left' : 'top']; + const origEdge2 = isY ? origEdge1 + rectOrigin.width : origEdge1 + rectOrigin.height; + const elGuideInfo = this[`elGuideInfo${axis.toUpperCase()}` as ElGuideInfoKey]; + const elGuideInfoCnt = this[`elGuideInfoContent${axis.toUpperCase()}` as ElGuideInfoContentKey]; + + // Find the nearest element + const matched = guidesStatic + ?.filter((stat) => stat.type === item.type) + .map((stat) => { + const { left, width, top, height } = stat.originRect; + const statEdge1 = isY ? left : top; + const statEdge2 = isY ? left + width : top + height; + return { + gap: statEdge2 < origEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2, + guide: stat, + }; + }) + .filter((item) => item.gap > 0) + .sort((a, b) => a.gap - b.gap) + .map((item) => item.guide)[0]; + + if (matched) { + const { left, width, top, height, rect } = matched.originRect; + const isEdge1 = isY ? left < rectOrigin.left : top < rectOrigin.top; const statEdge2 = isY ? left + width : top + height; + const posFirst = isY ? item.y : item.x; + const posSecond = isEdge1 ? statEdge2 : origEdge2; + const size = isEdge1 ? origEdge1 - statEdge2 : statEdge2 - origEdge2; + const sizeRaw = isEdge1 + ? rectOrigin.rect[isY ? 'left' : 'top'] - rect[isY ? 'left' : 'top'] + : rect[isY ? 'left' : 'top'] - rectOrigin.rect[isY ? 'left' : 'top']; + const sizePercent = (sizeRaw / (isY ? matched.originRect.height : matched.originRect.width)) * 100; + return { - gap: statEdge2 < origEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2, - guide: stat, + guide: item, + guidesStatic, + matched, + posFirst, + posSecond, + size, + sizeRaw, + sizePercent, + elGuideInfo, + elGuideInfoCnt, }; - }) - .filter((item) => item.gap > 0) - .sort((a, b) => a.gap - b.gap) - .map((item) => item.guide)[0]; - - if (matched) { - const { left, width, top, height, rect } = matched.originRect; - const isEdge1 = isY ? left < rectOrigin.left : top < rectOrigin.top; - const statEdge1 = isY ? left : top; - const statEdge1Raw = isY ? rect.left : rect.top; - const statEdge2 = isY ? left + width : top + height; - const statEdge2Raw = isY ? rect.left + rect.width : rect.top + rect.height; - const posFirst = isY ? item.y : item.x; - const posSecond = isEdge1 ? statEdge2 : origEdge2; - const pos2 = `${posFirst}px`; - const size = isEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2; - const sizeRaw = isEdge1 ? origEdge1Raw - statEdge2Raw : statEdge1Raw - origEdge2Raw; - const sizePercent = (sizeRaw / (isY ? matched.originRect.height : matched.originRect.width)) * 100; // TODO: fix calculation - - // INFO: skip rendering the guide info if the option is set - if (!this?.opts?.skipGuidesRender) { - if (guideInfoStyle) { - guideInfoStyle.display = ''; - guideInfoStyle[isY ? 'top' : 'left'] = pos2; - guideInfoStyle[isY ? 'left' : 'top'] = `${posSecond}px`; - guideInfoStyle[isY ? 'width' : 'height'] = `${size}px`; - } - if (elGuideInfoCnt) { - elGuideInfoCnt.innerHTML = `${Math.round(sizeRaw)}px`; - } } - guideMatched = { - guide: item, - guidesStatic, - matched, - posFirst, - posSecond, - size, - sizeRaw, - sizePercent, - elGuideInfo, - elGuideInfoCnt, - }; - - this.em.trigger(`${evName}:active`, { - ...this.getEventOpts(), - ...guideMatched, - }); - } - - return guideMatched; - }); - - return guidesData.filter(Boolean) as MatchedGuide[]; + return null; + }) + .filter(Boolean) as MatchedGuide[]; }, toggleDrag(enable) { @@ -580,7 +558,9 @@ interface ComponentDragProps { onDrag: DraggerOptions['onDrag']; onEnd: DraggerOptions['onEnd']; hideGuidesInfo: () => void; - renderGuideInfo: (guides?: Guide[]) => MatchedGuide[]; + renderGuideInfo: (guides?: Guide[]) => void; + renderSingleGuideInfo: (matchedGuide: MatchedGuide) => void; + getMatchedGuides: (guides?: Guide[]) => MatchedGuide[]; toggleDrag: (enable?: boolean) => void; }