From 6339f43c0a235f7a3036235321a7d4ce23c7db63 Mon Sep 17 00:00:00 2001 From: robers Date: Thu, 3 Oct 2024 18:01:37 -0600 Subject: [PATCH 1/4] Fix: always visible columns options --- packages/common/src/extensions/slickColumnPicker.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/common/src/extensions/slickColumnPicker.ts b/packages/common/src/extensions/slickColumnPicker.ts index 91105a165..f0447b9df 100644 --- a/packages/common/src/extensions/slickColumnPicker.ts +++ b/packages/common/src/extensions/slickColumnPicker.ts @@ -221,8 +221,15 @@ export class SlickColumnPicker { protected repositionMenu(event: DOMMouseOrTouchEvent | SlickEventData): void { const targetEvent: MouseEvent | Touch = (event as TouchEvent)?.touches?.[0] ?? event; if (this._menuElm) { + const availableWidth = window.innerWidth - (this._menuElm.getBoundingClientRect().right + targetEvent.pageX) + let leftPosition = 10 + + if (availableWidth < 0) { + leftPosition = leftPosition + 60 + Math.abs(availableWidth) + } + this._menuElm.style.top = `${targetEvent.pageY - 10}px`; - this._menuElm.style.left = `${targetEvent.pageX - 10}px`; + this._menuElm.style.left = `${targetEvent.pageX - leftPosition}px`; this._menuElm.style.minHeight = findWidthOrDefault(this.addonOptions.minHeight, ''); this._menuElm.style.maxHeight = findWidthOrDefault(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`); this._menuElm.style.display = 'block'; From 48c2d13e05d7e305bfaf40a2fe23fa74635cf5eb Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Wed, 9 Oct 2024 21:08:20 -0400 Subject: [PATCH 2/4] fix: Column Picker should auto-position left/right with available space - similar to what we've done with the Header Menu, then the Column Picker should also auto-position itself to the left if doesn't have enough space on the right and vice-versa --- .../__tests__/slickColumnPicker.spec.ts | 21 +++++++++++++++++++ .../src/extensions/slickColumnPicker.ts | 16 +++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts b/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts index b39291afc..e61152e32 100644 --- a/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts +++ b/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts @@ -16,6 +16,7 @@ const gridStub = { applyHtmlCode: (elm, val) => elm.innerHTML = val || '', getColumnIndex: vi.fn(), getColumns: vi.fn(), + getGridPosition: vi.fn(), getOptions: vi.fn(), getSelectedRows: vi.fn(), getUID: () => gridUid, @@ -362,6 +363,26 @@ describe('ColumnPickerControl', () => { expect(control.menuElement?.classList.contains('slick-dark-mode')).toBeTruthy(); }); + it('should reposition menu to the left when no available space on the right', () => { + vi.spyOn(gridStub, 'getGridPosition').mockReturnValue({ left: 50, top: 0, right: 0, bottom: 200, height: 22, width: 300, visible: true }); + vi.spyOn(gridStub, 'getColumnIndex').mockReturnValue(undefined as any).mockReturnValue(1); + + control.init(); + + const groupElm = createDomElement('div', { className: 'slick-column-name' }); + gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub); + vi.spyOn(control, 'createPickerMenu').mockImplementation(() => { + if (control.menuElement) { + Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 }); + return control.menuElement; + } + return document.createElement('div'); + }); + gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub); + Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 }); + expect(control.menuElement?.style.left).toBe('183px'); + }); + describe('onColumnsReordered event', () => { it('should reorder some columns', () => { const columnsUnorderedMock: Column[] = [ diff --git a/packages/common/src/extensions/slickColumnPicker.ts b/packages/common/src/extensions/slickColumnPicker.ts index f0447b9df..49a60645f 100644 --- a/packages/common/src/extensions/slickColumnPicker.ts +++ b/packages/common/src/extensions/slickColumnPicker.ts @@ -201,7 +201,7 @@ export class SlickColumnPicker { /** Mouse header context handler when doing a right+click on any of the header column title */ protected handleHeaderContextMenu(e: SlickEventData): void { e.preventDefault(); - emptyElement(this._listElm); + emptyElement(this._menuElm); this._columnCheckboxes = []; this._menuElm = this.createPickerMenu(); @@ -221,18 +221,18 @@ export class SlickColumnPicker { protected repositionMenu(event: DOMMouseOrTouchEvent | SlickEventData): void { const targetEvent: MouseEvent | Touch = (event as TouchEvent)?.touches?.[0] ?? event; if (this._menuElm) { - const availableWidth = window.innerWidth - (this._menuElm.getBoundingClientRect().right + targetEvent.pageX) - let leftPosition = 10 - - if (availableWidth < 0) { - leftPosition = leftPosition + 60 + Math.abs(availableWidth) + // auto-positioned menu left/right by available position + const gridPos = this.grid.getGridPosition(); + const menuWidth = this._menuElm.clientWidth || 0; + let menuOffsetLeft = targetEvent.pageX || 0; + if (gridPos?.width && (menuOffsetLeft + menuWidth >= gridPos.width)) { + menuOffsetLeft = menuOffsetLeft - menuWidth; } this._menuElm.style.top = `${targetEvent.pageY - 10}px`; - this._menuElm.style.left = `${targetEvent.pageX - leftPosition}px`; + this._menuElm.style.left = `${menuOffsetLeft}px`; this._menuElm.style.minHeight = findWidthOrDefault(this.addonOptions.minHeight, ''); this._menuElm.style.maxHeight = findWidthOrDefault(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`); - this._menuElm.style.display = 'block'; this._menuElm.ariaExpanded = 'true'; this._menuElm.appendChild(this._listElm); } From ceaa358fb57414af81221d27f2478647098c4def Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Wed, 9 Oct 2024 21:15:52 -0400 Subject: [PATCH 3/4] chore: add missing style display --- packages/common/src/extensions/slickColumnPicker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/common/src/extensions/slickColumnPicker.ts b/packages/common/src/extensions/slickColumnPicker.ts index 49a60645f..fdee9afa7 100644 --- a/packages/common/src/extensions/slickColumnPicker.ts +++ b/packages/common/src/extensions/slickColumnPicker.ts @@ -233,6 +233,7 @@ export class SlickColumnPicker { this._menuElm.style.left = `${menuOffsetLeft}px`; this._menuElm.style.minHeight = findWidthOrDefault(this.addonOptions.minHeight, ''); this._menuElm.style.maxHeight = findWidthOrDefault(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`); + this._menuElm.style.display = 'block'; this._menuElm.ariaExpanded = 'true'; this._menuElm.appendChild(this._listElm); } From 801ea8ca49c7b5e04ce2491ccfccf792288a606e Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Wed, 9 Oct 2024 21:22:02 -0400 Subject: [PATCH 4/4] chore: improve auto-position comment --- packages/common/src/extensions/slickColumnPicker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/src/extensions/slickColumnPicker.ts b/packages/common/src/extensions/slickColumnPicker.ts index fdee9afa7..26ad9b52e 100644 --- a/packages/common/src/extensions/slickColumnPicker.ts +++ b/packages/common/src/extensions/slickColumnPicker.ts @@ -221,7 +221,7 @@ export class SlickColumnPicker { protected repositionMenu(event: DOMMouseOrTouchEvent | SlickEventData): void { const targetEvent: MouseEvent | Touch = (event as TouchEvent)?.touches?.[0] ?? event; if (this._menuElm) { - // auto-positioned menu left/right by available position + // auto-positioned menu left/right by available viewport space const gridPos = this.grid.getGridPosition(); const menuWidth = this._menuElm.clientWidth || 0; let menuOffsetLeft = targetEvent.pageX || 0;