diff --git a/apps/editor/src/ui/components/popup.ts b/apps/editor/src/ui/components/popup.ts index 8da3d67eeb..e0b5b48d5b 100644 --- a/apps/editor/src/ui/components/popup.ts +++ b/apps/editor/src/ui/components/popup.ts @@ -1,6 +1,7 @@ import { ExecCommand, HidePopup, PopupInfo, Pos } from '@t/ui'; import { Emitter } from '@t/event'; import { closest, cls } from '@/utils/dom'; +import { shallowEqual } from '@/utils/common'; import html from '../vdom/template'; import { Component } from '../vdom/component'; @@ -16,7 +17,13 @@ interface Props { execCommand: ExecCommand; } -export class Popup extends Component { +interface State { + popupPos: Pos | null; +} + +const MARGIN_FROM_RIGHT_SIDE = 20; + +export class Popup extends Component { private handleMousedown = (ev: MouseEvent) => { if ( !closest(ev.target as HTMLElement, `.${cls('popup')}`) && @@ -34,18 +41,39 @@ export class Popup extends Component { document.removeEventListener('mousedown', this.handleMousedown); } - render() { - const { info, show, hidePopup, eventEmitter, execCommand } = this.props; - const { className = '', style, render, pos, initialValues = {} } = info || {}; - const popupStyle: PopupStyle = { display: show ? 'block' : 'none', ...style }; + updated(prevProps: Props) { + const { show, info } = this.props; - if (pos) { - popupStyle.left = pos.left; - popupStyle.top = pos.top; + if (show && info.pos && prevProps.show !== show) { + const popupPos = { ...info.pos }; + const { offsetWidth } = this.refs.el; + const toolbarEl = closest(this.refs.el, `.${cls('toolbar')}`) as HTMLElement; + const { offsetWidth: toolbarOffsetWidth } = toolbarEl; + + if (popupPos.left + offsetWidth >= toolbarOffsetWidth) { + popupPos.left = toolbarOffsetWidth - offsetWidth - MARGIN_FROM_RIGHT_SIDE; + } + if (!shallowEqual(this.state.popupPos, popupPos)) { + this.setState({ popupPos }); + } } + } + + render() { + const { info, show, hidePopup, eventEmitter, execCommand } = this.props; + const { className = '', style, render, initialValues = {} } = info || {}; + const popupStyle: PopupStyle = { + display: show ? 'block' : 'none', + ...style, + ...this.state.popupPos, + }; return html` -
+
(this.refs.el = el)} + >
${render && render({ eventEmitter, show, hidePopup, execCommand, initialValues })}
diff --git a/apps/editor/src/utils/common.ts b/apps/editor/src/utils/common.ts index 9869973af3..1022463fee 100644 --- a/apps/editor/src/utils/common.ts +++ b/apps/editor/src/utils/common.ts @@ -68,7 +68,7 @@ function isNil(value: unknown): value is null | undefined { return isNull(value) || isUndefined(value); } -export function shallowEqual(o1: Record, o2: Record) { +export function shallowEqual(o1: Record | null, o2: Record | null) { if (o1 === null && o1 === o2) { return true; }