diff --git a/demo/scripts/controls/BuildInPluginState.ts b/demo/scripts/controls/BuildInPluginState.ts
index 4aa4f850a83..47ac1c80f26 100644
--- a/demo/scripts/controls/BuildInPluginState.ts
+++ b/demo/scripts/controls/BuildInPluginState.ts
@@ -34,6 +34,7 @@ export default interface BuildInPluginState {
experimentalFeatures: ExperimentalFeatures[];
forcePreserveRatio: boolean;
isRtl: boolean;
+ tableFeaturesContainerSelector: string;
}
export interface BuildInPluginProps extends BuildInPluginState, SidePaneElementProps {}
diff --git a/demo/scripts/controls/MainPaneBase.tsx b/demo/scripts/controls/MainPaneBase.tsx
index ff2fb6b97f7..ccd28c983a7 100644
--- a/demo/scripts/controls/MainPaneBase.tsx
+++ b/demo/scripts/controls/MainPaneBase.tsx
@@ -176,7 +176,7 @@ export default abstract class MainPaneBase extends React.Component<{}, MainPaneB
this.updateContentPlugin.forceUpdate();
return (
-
+
{this.state.editorCreator && (
void
+ ) => void,
+ private anchorContainerSelector?: string
) {}
/**
@@ -131,11 +135,16 @@ export default class TableResize implements EditorPlugin {
}
if (!this.tableEditor && table && this.editor && table.rows.length > 0) {
+ const container = this.anchorContainerSelector
+ ? this.editor.getDocument().querySelector(this.anchorContainerSelector)
+ : undefined;
+
this.tableEditor = new TableEditor(
this.editor,
table,
this.invalidateTableRects,
this.onShowHelperElement,
+ safeInstanceOf(container, 'HTMLElement') ? container : undefined,
e?.currentTarget
);
}
diff --git a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts
index e2650028815..d5146c2981e 100644
--- a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts
+++ b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableEditor.ts
@@ -81,6 +81,7 @@ export default class TableEditor {
elementData: CreateElementData,
helperType: 'CellResizer' | 'TableInserter' | 'TableResizer' | 'TableSelector'
) => void,
+ private anchorContainer?: HTMLElement,
private contentDiv?: EventTarget | null
) {
this.isRTL = getComputedStyle(table, 'direction') == 'rtl';
@@ -211,23 +212,24 @@ export default class TableEditor {
if (!this.tableSelector) {
this.tableSelector = createTableSelector(
this.table,
- this.editor.getZoomScale(),
this.editor,
this.onSelect,
this.getOnMouseOut,
this.onShowHelperElement,
- this.contentDiv
+ this.contentDiv,
+ this.anchorContainer
);
}
if (!this.tableResizer) {
this.tableResizer = createTableResizer(
this.table,
- this.editor.getZoomScale(),
- this.isRTL,
+ this.editor,
this.onStartTableResize,
this.onFinishEditing,
- this.onShowHelperElement
+ this.onShowHelperElement,
+ this.contentDiv,
+ this.anchorContainer
);
}
}
diff --git a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts
index f383ffcb5b4..3214ee7f643 100644
--- a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts
+++ b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableResizer.ts
@@ -1,7 +1,13 @@
import DragAndDropHelper from '../../../pluginUtils/DragAndDropHelper';
import TableEditFeature from './TableEditorFeature';
-import { createElement, normalizeRect, VTable } from 'roosterjs-editor-dom';
-import { CreateElementData } from 'roosterjs-editor-types';
+import { CreateElementData, IEditor, Rect } from 'roosterjs-editor-types';
+import {
+ createElement,
+ getComputedStyle,
+ normalizeRect,
+ safeInstanceOf,
+ VTable,
+} from 'roosterjs-editor-dom';
const TABLE_RESIZER_LENGTH = 12;
const MIN_CELL_WIDTH = 30;
@@ -12,16 +18,25 @@ const MIN_CELL_HEIGHT = 20;
*/
export default function createTableResizer(
table: HTMLTableElement,
- zoomScale: number,
- isRTL: boolean,
+ editor: IEditor,
onStart: () => void,
onDragEnd: () => false,
onShowHelperElement?: (
elementData: CreateElementData,
helperType: 'CellResizer' | 'TableInserter' | 'TableResizer' | 'TableSelector'
- ) => void
+ ) => void,
+ contentDiv?: EventTarget | null,
+ anchorContainer?: HTMLElement
): TableEditFeature | null {
+ const rect = normalizeRect(table.getBoundingClientRect());
+
+ if (!isTableBottomVisible(editor, rect, contentDiv)) {
+ return null;
+ }
+
const document = table.ownerDocument;
+ const isRTL = getComputedStyle(table, 'direction') == 'rtl';
+ const zoomScale = editor.getZoomScale();
const createElementData = {
tag: 'div',
style: `position: fixed; cursor: ${
@@ -35,7 +50,8 @@ export default function createTableResizer(
div.style.width = `${TABLE_RESIZER_LENGTH}px`;
div.style.height = `${TABLE_RESIZER_LENGTH}px`;
- document.body.appendChild(div);
+
+ (anchorContainer || document.body).appendChild(div);
const context: DragAndDropContext = {
isRTL,
@@ -44,12 +60,12 @@ export default function createTableResizer(
onStart,
};
- setResizeDivPosition(context, div);
+ setDivPosition(context, div);
const featureHandler = new DragAndDropHelper(
div,
context,
- setResizeDivPosition,
+ setDivPosition,
{
onDragStart,
onDragging,
@@ -137,7 +153,7 @@ function onDragging(
}
}
-function setResizeDivPosition(context: DragAndDropContext, trigger: HTMLElement) {
+function setDivPosition(context: DragAndDropContext, trigger: HTMLElement) {
const { table, isRTL } = context;
const rect = normalizeRect(table.getBoundingClientRect());
@@ -148,3 +164,22 @@ function setResizeDivPosition(context: DragAndDropContext, trigger: HTMLElement)
: `${rect.right}px`;
}
}
+
+function isTableBottomVisible(
+ editor: IEditor,
+ rect: Rect | null,
+ contentDiv?: EventTarget | null
+): boolean {
+ const visibleViewport = editor.getVisibleViewport();
+ if (contentDiv && safeInstanceOf(contentDiv, 'HTMLElement') && visibleViewport && rect) {
+ const containerRect = normalizeRect(contentDiv.getBoundingClientRect());
+
+ return (
+ !!containerRect &&
+ containerRect.bottom >= rect.bottom &&
+ visibleViewport.bottom >= rect.bottom
+ );
+ }
+
+ return true;
+}
diff --git a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts
index 35b507828a5..b1536f81847 100644
--- a/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts
+++ b/packages/roosterjs-editor-plugins/lib/plugins/TableResize/editors/TableSelector.ts
@@ -1,8 +1,13 @@
import DragAndDropHandler from '../../../pluginUtils/DragAndDropHandler';
import DragAndDropHelper from '../../../pluginUtils/DragAndDropHelper';
import TableEditorFeature from './TableEditorFeature';
-import { createElement, normalizeRect, safeInstanceOf } from 'roosterjs-editor-dom';
import { CreateElementData, IEditor, Rect } from 'roosterjs-editor-types';
+import {
+ createElement,
+ normalizeRect,
+ safeInstanceOf,
+ getComputedStyle,
+} from 'roosterjs-editor-dom';
const TABLE_SELECTOR_LENGTH = 12;
const TABLE_SELECTOR_ID = '_Table_Selector';
@@ -12,7 +17,6 @@ const TABLE_SELECTOR_ID = '_Table_Selector';
*/
export default function createTableSelector(
table: HTMLTableElement,
- zoomScale: number,
editor: IEditor,
onFinishDragging: (table: HTMLTableElement) => void,
getOnMouseOut: (feature: HTMLElement) => (ev: MouseEvent) => void,
@@ -20,7 +24,8 @@ export default function createTableSelector(
elementData: CreateElementData,
helperType: 'CellResizer' | 'TableInserter' | 'TableResizer' | 'TableSelector'
) => void,
- contentDiv?: EventTarget | null
+ contentDiv?: EventTarget | null,
+ anchorContainer?: HTMLElement
): TableEditorFeature | null {
const rect = normalizeRect(table.getBoundingClientRect());
@@ -28,6 +33,7 @@ export default function createTableSelector(
return null;
}
+ const zoomScale = editor.getZoomScale();
const document = table.ownerDocument;
const createElementData = {
tag: 'div',
@@ -41,15 +47,17 @@ export default function createTableSelector(
div.id = TABLE_SELECTOR_ID;
div.style.width = `${TABLE_SELECTOR_LENGTH}px`;
div.style.height = `${TABLE_SELECTOR_LENGTH}px`;
- document.body.appendChild(div);
+
+ (anchorContainer || document.body).appendChild(div);
const context: TableSelectorContext = {
table,
zoomScale,
rect,
+ isRTL: getComputedStyle(table, 'direction') == 'rtl',
};
- setSelectorDivPosition(context, div);
+ setDivPosition(context, div);
const onDragEnd = (context: TableSelectorContext, event: MouseEvent): false => {
if (event.target == div) {
@@ -61,11 +69,11 @@ export default function createTableSelector(
const featureHandler = new TableSelectorFeature(
div,
context,
- setSelectorDivPosition,
+ setDivPosition,
{
onDragEnd,
},
- zoomScale,
+ context.zoomScale,
getOnMouseOut
);
@@ -76,6 +84,7 @@ interface TableSelectorContext {
table: HTMLTableElement;
zoomScale: number;
rect: Rect | null;
+ isRTL: boolean;
}
interface TableSelectorInitValue {
@@ -88,11 +97,16 @@ class TableSelectorFeature extends DragAndDropHelper void,
+ onSubmit: (
+ context: TableSelectorContext,
+ trigger: HTMLElement,
+ container?: HTMLElement
+ ) => void,
handler: DragAndDropHandler,
zoomScale: number,
getOnMouseOut: (feature: HTMLElement) => (ev: MouseEvent) => void,
- forceMobile?: boolean
+ forceMobile?: boolean | undefined,
+ container?: HTMLElement
) {
super(div, context, onSubmit, handler, zoomScale, forceMobile);
this.onMouseOut = getOnMouseOut(div);
@@ -108,7 +122,7 @@ class TableSelectorFeature extends DragAndDropHelper {
//Act
const result = createTableSelector(
target as HTMLTableElement,
- 1,
editor,
() => {},
() => () => {},
() => {},
- node
+ node
);
//Assert