Skip to content

Commit cd6cb96

Browse files
authored
Merge pull request #1707 from ghiscoding/bugfix/column-picker-autopos
fix: Column Picker should auto-position left/right with available space
2 parents 359ccbf + 801ea8c commit cd6cb96

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const gridStub = {
1616
applyHtmlCode: (elm, val) => elm.innerHTML = val || '',
1717
getColumnIndex: vi.fn(),
1818
getColumns: vi.fn(),
19+
getGridPosition: vi.fn(),
1920
getOptions: vi.fn(),
2021
getSelectedRows: vi.fn(),
2122
getUID: () => gridUid,
@@ -362,6 +363,26 @@ describe('ColumnPickerControl', () => {
362363
expect(control.menuElement?.classList.contains('slick-dark-mode')).toBeTruthy();
363364
});
364365

366+
it('should reposition menu to the left when no available space on the right', () => {
367+
vi.spyOn(gridStub, 'getGridPosition').mockReturnValue({ left: 50, top: 0, right: 0, bottom: 200, height: 22, width: 300, visible: true });
368+
vi.spyOn(gridStub, 'getColumnIndex').mockReturnValue(undefined as any).mockReturnValue(1);
369+
370+
control.init();
371+
372+
const groupElm = createDomElement('div', { className: 'slick-column-name' });
373+
gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub);
374+
vi.spyOn(control, 'createPickerMenu').mockImplementation(() => {
375+
if (control.menuElement) {
376+
Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 });
377+
return control.menuElement;
378+
}
379+
return document.createElement('div');
380+
});
381+
gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub);
382+
Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 });
383+
expect(control.menuElement?.style.left).toBe('183px');
384+
});
385+
365386
describe('onColumnsReordered event', () => {
366387
it('should reorder some columns', () => {
367388
const columnsUnorderedMock: Column[] = [

packages/common/src/extensions/slickColumnPicker.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ export class SlickColumnPicker {
201201
/** Mouse header context handler when doing a right+click on any of the header column title */
202202
protected handleHeaderContextMenu(e: SlickEventData): void {
203203
e.preventDefault();
204-
emptyElement(this._listElm);
204+
emptyElement(this._menuElm);
205205
this._columnCheckboxes = [];
206206

207207
this._menuElm = this.createPickerMenu();
@@ -221,8 +221,16 @@ export class SlickColumnPicker {
221221
protected repositionMenu(event: DOMMouseOrTouchEvent<HTMLDivElement> | SlickEventData): void {
222222
const targetEvent: MouseEvent | Touch = (event as TouchEvent)?.touches?.[0] ?? event;
223223
if (this._menuElm) {
224+
// auto-positioned menu left/right by available viewport space
225+
const gridPos = this.grid.getGridPosition();
226+
const menuWidth = this._menuElm.clientWidth || 0;
227+
let menuOffsetLeft = targetEvent.pageX || 0;
228+
if (gridPos?.width && (menuOffsetLeft + menuWidth >= gridPos.width)) {
229+
menuOffsetLeft = menuOffsetLeft - menuWidth;
230+
}
231+
224232
this._menuElm.style.top = `${targetEvent.pageY - 10}px`;
225-
this._menuElm.style.left = `${targetEvent.pageX - 10}px`;
233+
this._menuElm.style.left = `${menuOffsetLeft}px`;
226234
this._menuElm.style.minHeight = findWidthOrDefault(this.addonOptions.minHeight, '');
227235
this._menuElm.style.maxHeight = findWidthOrDefault(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`);
228236
this._menuElm.style.display = 'block';

0 commit comments

Comments
 (0)