From 769ce68654f18046e2956a3119faf7d4355973fe Mon Sep 17 00:00:00 2001 From: Rahman Date: Wed, 18 Feb 2026 16:33:23 +0100 Subject: [PATCH 1/4] fix(datagrid-web): enforce filter-aware minimum width during column resize --- .../datawidgets/web/_datagrid.scss | 7 ++++ .../datagrid-web/CHANGELOG.md | 4 ++ .../src/components/GridHeader.tsx | 40 +++++++++++-------- .../src/components/MockHeader.tsx | 4 +- .../datagrid-web/src/helpers/ColumnBase.ts | 5 ++- .../state/column/ColumnFilterStore.tsx | 24 +++++++++++ .../src/helpers/state/column/ColumnStore.tsx | 4 ++ .../datagrid-web/src/typings/GridColumn.ts | 1 + 8 files changed, 70 insertions(+), 19 deletions(-) diff --git a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss index 79b2ac631b..53c66c9df2 100644 --- a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss +++ b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss @@ -591,6 +591,13 @@ $root: ".widget-datagrid"; .grid-mock-header { display: contents; + + span { + visibility: hidden; + height: 0; + display: block; + overflow: hidden; + } } :where(#{$root}-paging-bottom, #{$root}-padding-top) { diff --git a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md index 7144838bb3..70f3a22dd4 100644 --- a/packages/pluggableWidgets/datagrid-web/CHANGELOG.md +++ b/packages/pluggableWidgets/datagrid-web/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Fixed + +- We fixed an issue where columns could be resized narrower than their header filter widget required, making filters unusable. + ## [3.8.1] - 2026-02-19 ### Fixed diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx index a378cd42b7..80fd99b94d 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx @@ -24,23 +24,29 @@ export function GridHeader(): ReactElement {
- {columns.map(column => ( - -
columnsStore.setIsResizing(true)} - onResizeEnds={() => columnsStore.setIsResizing(false)} - setColumnWidth={(width: number) => column.setSize(width)} - /> - } - setDropTarget={setDragOver} - setIsDragging={setIsDragging} - /> - - ))} + {columns.map(column => { + const filterMinWidth = columnsStore.columnFilters[column.columnIndex]?.suggestedMinWidth ?? 0; + const minWidth = Math.max(50, column.minWidthLimit, filterMinWidth); + + return ( + +
columnsStore.setIsResizing(true)} + onResizeEnds={() => columnsStore.setIsResizing(false)} + setColumnWidth={(width: number) => column.setSize(width)} + /> + } + setDropTarget={setDragOver} + setIsDragging={setIsDragging} + /> + + ); + })} {columnsHidable && ( c.setHeaderElementRef(ref)} - >
+ > + {c.header} +
))} {config.selectorColumnEnabled &&
} diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts index 5d518b5c6b..98dc748ada 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts @@ -8,7 +8,6 @@ interface BaseColumnProps { width: WidthEnum; size: number | null; alignment: AlignmentEnum; - wrapText: boolean; minWidth: MinWidthEnum; minWidthLimit: number; @@ -45,6 +44,10 @@ export class BaseColumn { return this.properties.wrapText; } + get minWidthLimit(): number { + return this.properties.minWidthLimit; + } + getCssWidth(): string { switch (this.properties.width) { case "autoFit": { diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx index 7a372da113..d1917977fe 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx @@ -27,10 +27,12 @@ export class ColumnFilterStore implements IColumnFilterStore { private _filterStore: FilterStore | null = null; private _context: FilterAPI; private _filterHost: ObservableFilterHost; + private _attributeType: ListAttributeValue["type"] | undefined; constructor(props: ColumnsType, info: StaticInfo, filterHost: ObservableFilterHost) { this._filterHost = filterHost; this._widget = props.filter; + this._attributeType = isListAttributeValue(props.attribute) ? props.attribute.type : undefined; const storeResult = this.createFilterStore(props, null); if (storeResult === null) { this._error = this._filterStore = null; @@ -104,6 +106,28 @@ export class ColumnFilterStore implements IColumnFilterStore { this._filterStore?.fromJSON(data); } } + + get suggestedMinWidth(): number { + if (this._attributeType === undefined) { + return 0; + } + switch (this._attributeType) { + case "DateTime": + return 150; + case "AutoNumber": + case "Decimal": + case "Integer": + case "Long": + return 120; + case "String": + case "HashString": + case "Boolean": + case "Enum": + return 100; + default: + return 0; + } + } } const isListAttributeValue = ( diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx index f2136d3e8e..89e0b70677 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx @@ -112,6 +112,10 @@ export class ColumnStore implements GridColumn { return this.baseInfo.draggable; } + get minWidthLimit(): number { + return this.baseInfo.minWidthLimit; + } + // hiding get canHide(): boolean { return this.baseInfo.hidable; diff --git a/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts b/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts index 23448457fe..2be5eb95f5 100644 --- a/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts +++ b/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts @@ -33,6 +33,7 @@ export interface GridColumn { // sizing canResize: boolean; + minWidthLimit: number; size: number | undefined; setSize(size: number): void; getCssWidth(): string; From 7988b24e9bac1c082ccdf90e0415998f4f3fb83e Mon Sep 17 00:00:00 2001 From: Rahman Date: Tue, 24 Feb 2026 14:03:14 +0100 Subject: [PATCH 2/4] fix(datagrid-web): replace hardcoded filter min-width lookup with DOM measurement and overflow --- .../src/components/GridHeader.tsx | 4 -- .../datagrid-web/src/components/Header.tsx | 10 +++- .../src/components/MockHeader.tsx | 33 +++++++----- .../datagrid-web/src/helpers/ColumnBase.ts | 2 +- .../state/column/ColumnFilterStore.tsx | 53 +++++++++---------- .../src/helpers/state/column/ColumnStore.tsx | 2 +- 6 files changed, 55 insertions(+), 49 deletions(-) diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx index 80fd99b94d..543b82bf4b 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx @@ -25,9 +25,6 @@ export function GridHeader(): ReactElement {
{columns.map(column => { - const filterMinWidth = columnsStore.columnFilters[column.columnIndex]?.suggestedMinWidth ?? 0; - const minWidth = Math.max(50, column.minWidthLimit, filterMinWidth); - return (
columnsStore.setIsResizing(true)} onResizeEnds={() => columnsStore.setIsResizing(false)} setColumnWidth={(width: number) => column.setSize(width)} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx index 1c396b3b75..38069d09ae 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx @@ -35,6 +35,8 @@ export function Header(props: HeaderProps): ReactElement { const canDrag = columnsDraggable && column.canDrag; const canSort = columnsSortable && column.canSort; const canResize = columnsResizable && column.canResize; + const filterStore = columnsStore.columnFilters[column.columnIndex]; + const filterRef = useCallback((el: HTMLDivElement | null) => filterStore?.setFilterElement(el), [filterStore]); const draggableProps = useDraggable( canDrag, @@ -82,8 +84,12 @@ export function Header(props: HeaderProps): ReactElement { {sortIcon}
{columnsFilterable && ( -
- {columnsStore.columnFilters[column.columnIndex]?.renderFilterWidgets()} +
+ {filterStore?.renderFilterWidgets()}
)}
diff --git a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx index a5f8629a5b..a4eb0878fc 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx @@ -1,7 +1,8 @@ +import { observer } from "mobx-react-lite"; import { ReactNode, useCallback, useEffect } from "react"; import { useColumnsStore, useDatagridConfig, useGridSizeStore } from "../model/hooks/injection-hooks"; -export function MockHeader(): ReactNode { +export const MockHeader = observer(function MockHeader(): ReactNode { const columnsStore = useColumnsStore(); const config = useDatagridConfig(); const gridSizeStore = useGridSizeStore(); @@ -38,19 +39,23 @@ export function MockHeader(): ReactNode { return (
{config.checkboxColumnEnabled &&
} - {columnsStore.visibleColumns.map(c => ( -
c.setHeaderElementRef(ref)} - > - {c.header} -
- ))} + {columnsStore.visibleColumns.map(c => { + const filterMinWidth = columnsStore.columnFilters[c.columnIndex]?.measuredFilterWidth; + return ( +
c.setHeaderElementRef(ref)} + > + {c.header} +
+ ); + })} {config.selectorColumnEnabled &&
}
); -} +}); diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts index 98dc748ada..c49424bb27 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts @@ -45,7 +45,7 @@ export class BaseColumn { } get minWidthLimit(): number { - return this.properties.minWidthLimit; + return this.properties.minWidth === "manual" ? this.properties.minWidthLimit : 0; } getCssWidth(): string { diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx index d1917977fe..1ae51af52e 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx @@ -8,31 +8,28 @@ import { ObservableFilterHost } from "@mendix/widget-plugin-filtering/typings/Ob import { disposeBatch } from "@mendix/widget-plugin-mobx-kit/disposeBatch"; import { ListAttributeListValue, ListAttributeValue } from "mendix"; import { FilterCondition } from "mendix/filters"; -import { computed, makeObservable } from "mobx"; +import { action, computed, makeObservable, observable, runInAction } from "mobx"; import { ReactNode } from "react"; import { ColumnsType } from "../../../../typings/DatagridProps"; import { StaticInfo } from "../../../typings/static-info"; -export interface IColumnFilterStore { - renderFilterWidgets(): ReactNode; -} - type FilterStore = InputFilterStore | EnumFilterStore; const { Provider } = getGlobalFilterContextObject(); -export class ColumnFilterStore implements IColumnFilterStore { +export class ColumnFilterStore { private _widget: ReactNode; private _error: APIError | null; private _filterStore: FilterStore | null = null; private _context: FilterAPI; private _filterHost: ObservableFilterHost; - private _attributeType: ListAttributeValue["type"] | undefined; + private _filterResizeObserver: ResizeObserver | null = null; + + measuredFilterWidth: number = 0; constructor(props: ColumnsType, info: StaticInfo, filterHost: ObservableFilterHost) { this._filterHost = filterHost; this._widget = props.filter; - this._attributeType = isListAttributeValue(props.attribute) ? props.attribute.type : undefined; const storeResult = this.createFilterStore(props, null); if (storeResult === null) { this._error = this._filterStore = null; @@ -46,6 +43,7 @@ export class ColumnFilterStore implements IColumnFilterStore { this._context = this.createContext(this._filterStore, info); makeObservable(this, { + measuredFilterWidth: observable, condition: computed }); } @@ -55,6 +53,10 @@ export class ColumnFilterStore implements IColumnFilterStore { if (this._filterStore && "setup" in this._filterStore) { add(this._filterStore.setup()); } + add(() => { + this._filterResizeObserver?.disconnect(); + this._filterResizeObserver = null; + }); return disposeAll; } @@ -107,26 +109,23 @@ export class ColumnFilterStore implements IColumnFilterStore { } } - get suggestedMinWidth(): number { - if (this._attributeType === undefined) { - return 0; - } - switch (this._attributeType) { - case "DateTime": - return 150; - case "AutoNumber": - case "Decimal": - case "Integer": - case "Long": - return 120; - case "String": - case "HashString": - case "Boolean": - case "Enum": - return 100; - default: - return 0; + setFilterElement(el: HTMLDivElement | null): void { + this._filterResizeObserver?.disconnect(); + this._filterResizeObserver = null; + + if (el === null) { + runInAction(() => { + this.measuredFilterWidth = 0; + }); + return; } + + this._filterResizeObserver = new ResizeObserver( + action((entries: ResizeObserverEntry[]) => { + this.measuredFilterWidth = (entries[0].target as HTMLElement).scrollWidth; + }) + ); + this._filterResizeObserver.observe(el); } } diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx index 89e0b70677..0e4c1ba150 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx @@ -113,7 +113,7 @@ export class ColumnStore implements GridColumn { } get minWidthLimit(): number { - return this.baseInfo.minWidthLimit; + return this.baseInfo.minWidth === "manual" ? this.baseInfo.minWidthLimit : 0; } // hiding From 6aaeec53211643c18e7c5b7978dbc297f0f75c42 Mon Sep 17 00:00:00 2001 From: Rahman Date: Wed, 25 Feb 2026 16:22:57 +0100 Subject: [PATCH 3/4] fix(datagrid-web): switch to css based solutuion --- .../datawidgets/web/_datagrid.scss | 25 +++++++++++++++ .../src/components/GridHeader.tsx | 4 +++ .../datagrid-web/src/components/Header.tsx | 7 +---- .../src/components/MockHeader.tsx | 2 -- .../state/column/ColumnFilterStore.tsx | 31 ++----------------- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss index 53c66c9df2..b0ff4076ab 100644 --- a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss +++ b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss @@ -143,6 +143,7 @@ $root: ".widget-datagrid"; /* Header filter */ .filter { display: flex; + overflow: hidden; margin-top: 4px; > .form-group { margin-bottom: 0; @@ -304,6 +305,7 @@ $root: ".widget-datagrid"; :where(.table .th .filter input:not([type="checkbox"])) { font-weight: normal; flex-grow: 1; + min-width: 0; width: 100%; } @@ -600,6 +602,29 @@ $root: ".widget-datagrid"; } } +// Filter-aware min-content sizing for MockHeader cells. +// Uses :has() to detect non-empty filters in each header column and applies +// an invisible ::after element of matching width to the corresponding MockHeader cell. +// Only affects flexible tracks (initial render); fixed tracks (after user resize) are unaffected. +@for $i from 1 through 20 { + $hcol: ".widget-datagrid-grid-head .tr > :nth-child(#{$i})"; + $mcol: ".grid-mock-header > :nth-child(#{$i})"; + + // Any non-empty filter → 100px minimum + .widget-datagrid-grid:has(#{$hcol} .filter:not(:empty)) #{$mcol}::after { + content: ""; + display: block; + visibility: hidden; + height: 0; + width: 100px; + } + + // Date filter (has calendar button) → 150px override + .widget-datagrid-grid:has(#{$hcol} .filter .btn-calendar) #{$mcol}::after { + width: 150px; + } +} + :where(#{$root}-paging-bottom, #{$root}-padding-top) { display: flex; flex-flow: row nowrap; diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx index 543b82bf4b..92b22599ba 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx @@ -32,6 +32,10 @@ export function GridHeader(): ReactElement { isDragging={isDragging} resizer={ columnsStore.setIsResizing(true)} onResizeEnds={() => columnsStore.setIsResizing(false)} setColumnWidth={(width: number) => column.setSize(width)} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx index 38069d09ae..a77d571540 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/Header.tsx @@ -36,7 +36,6 @@ export function Header(props: HeaderProps): ReactElement { const canSort = columnsSortable && column.canSort; const canResize = columnsResizable && column.canResize; const filterStore = columnsStore.columnFilters[column.columnIndex]; - const filterRef = useCallback((el: HTMLDivElement | null) => filterStore?.setFilterElement(el), [filterStore]); const draggableProps = useDraggable( canDrag, @@ -84,11 +83,7 @@ export function Header(props: HeaderProps): ReactElement { {sortIcon} {columnsFilterable && ( -
+
{filterStore?.renderFilterWidgets()}
)} diff --git a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx index a4eb0878fc..a3cf048f8f 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx @@ -40,12 +40,10 @@ export const MockHeader = observer(function MockHeader(): ReactNode {
{config.checkboxColumnEnabled &&
} {columnsStore.visibleColumns.map(c => { - const filterMinWidth = columnsStore.columnFilters[c.columnIndex]?.measuredFilterWidth; return (
(this, { - measuredFilterWidth: observable, condition: computed }); } @@ -53,10 +51,6 @@ export class ColumnFilterStore { if (this._filterStore && "setup" in this._filterStore) { add(this._filterStore.setup()); } - add(() => { - this._filterResizeObserver?.disconnect(); - this._filterResizeObserver = null; - }); return disposeAll; } @@ -108,25 +102,6 @@ export class ColumnFilterStore { this._filterStore?.fromJSON(data); } } - - setFilterElement(el: HTMLDivElement | null): void { - this._filterResizeObserver?.disconnect(); - this._filterResizeObserver = null; - - if (el === null) { - runInAction(() => { - this.measuredFilterWidth = 0; - }); - return; - } - - this._filterResizeObserver = new ResizeObserver( - action((entries: ResizeObserverEntry[]) => { - this.measuredFilterWidth = (entries[0].target as HTMLElement).scrollWidth; - }) - ); - this._filterResizeObserver.observe(el); - } } const isListAttributeValue = ( From 8cc619d0123b4ab96cf19753f9297c5fbbd5974c Mon Sep 17 00:00:00 2001 From: Rahman Date: Fri, 27 Feb 2026 10:18:58 +0100 Subject: [PATCH 4/4] fix(datagrid-web): revert minwidth approach, use a small js-css contract for filterType instead --- .../datawidgets/web/_datagrid.scss | 33 ++++++--------- .../src/components/GridHeader.tsx | 40 ++++++++----------- .../datagrid-web/src/components/Header.tsx | 3 +- .../src/components/MockHeader.tsx | 7 ++-- .../datagrid-web/src/helpers/ColumnBase.ts | 5 +-- .../state/column/ColumnFilterStore.tsx | 31 ++++++++++++-- .../src/helpers/state/column/ColumnStore.tsx | 4 -- .../datagrid-web/src/typings/GridColumn.ts | 1 - 8 files changed, 63 insertions(+), 61 deletions(-) diff --git a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss index b0ff4076ab..f27e450bf5 100644 --- a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss +++ b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss @@ -143,7 +143,6 @@ $root: ".widget-datagrid"; /* Header filter */ .filter { display: flex; - overflow: hidden; margin-top: 4px; > .form-group { margin-bottom: 0; @@ -305,7 +304,6 @@ $root: ".widget-datagrid"; :where(.table .th .filter input:not([type="checkbox"])) { font-weight: normal; flex-grow: 1; - min-width: 0; width: 100%; } @@ -603,26 +601,19 @@ $root: ".widget-datagrid"; } // Filter-aware min-content sizing for MockHeader cells. -// Uses :has() to detect non-empty filters in each header column and applies -// an invisible ::after element of matching width to the corresponding MockHeader cell. -// Only affects flexible tracks (initial render); fixed tracks (after user resize) are unaffected. -@for $i from 1 through 20 { - $hcol: ".widget-datagrid-grid-head .tr > :nth-child(#{$i})"; - $mcol: ".grid-mock-header > :nth-child(#{$i})"; - - // Any non-empty filter → 100px minimum - .widget-datagrid-grid:has(#{$hcol} .filter:not(:empty)) #{$mcol}::after { - content: ""; - display: block; - visibility: hidden; - height: 0; - width: 100px; - } +// The data-filter attribute is set by React based on the column's filter type. +// The ::after pseudo-element establishes an invisible minimum intrinsic width +// that CSS Grid's minmax(auto, 1fr) respects as a floor. +.grid-mock-header > [data-filter]::after { + content: ""; + display: block; + visibility: hidden; + height: 0; + width: 100px; +} - // Date filter (has calendar button) → 150px override - .widget-datagrid-grid:has(#{$hcol} .filter .btn-calendar) #{$mcol}::after { - width: 150px; - } +.grid-mock-header > [data-filter="date"]::after { + width: 175px; } :where(#{$root}-paging-bottom, #{$root}-padding-top) { diff --git a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx index 92b22599ba..a378cd42b7 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx @@ -24,29 +24,23 @@ export function GridHeader(): ReactElement {
- {columns.map(column => { - return ( - -
columnsStore.setIsResizing(true)} - onResizeEnds={() => columnsStore.setIsResizing(false)} - setColumnWidth={(width: number) => column.setSize(width)} - /> - } - setDropTarget={setDragOver} - setIsDragging={setIsDragging} - /> - - ); - })} + {columns.map(column => ( + +
columnsStore.setIsResizing(true)} + onResizeEnds={() => columnsStore.setIsResizing(false)} + setColumnWidth={(width: number) => column.setSize(width)} + /> + } + setDropTarget={setDragOver} + setIsDragging={setIsDragging} + /> + + ))} {columnsHidable && ( {columnsFilterable && (
- {filterStore?.renderFilterWidgets()} + {columnsStore.columnFilters[column.columnIndex]?.renderFilterWidgets()}
)}
diff --git a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx index a3cf048f8f..7fd430713b 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx @@ -1,8 +1,7 @@ -import { observer } from "mobx-react-lite"; import { ReactNode, useCallback, useEffect } from "react"; import { useColumnsStore, useDatagridConfig, useGridSizeStore } from "../model/hooks/injection-hooks"; -export const MockHeader = observer(function MockHeader(): ReactNode { +export function MockHeader(): ReactNode { const columnsStore = useColumnsStore(); const config = useDatagridConfig(); const gridSizeStore = useGridSizeStore(); @@ -40,6 +39,7 @@ export const MockHeader = observer(function MockHeader(): ReactNode {
{config.checkboxColumnEnabled &&
} {columnsStore.visibleColumns.map(c => { + const filterType = columnsStore.columnFilters[c.columnIndex]?.filterType; return (
c.setHeaderElementRef(ref)} + data-filter={filterType} > {c.header}
@@ -56,4 +57,4 @@ export const MockHeader = observer(function MockHeader(): ReactNode { {config.selectorColumnEnabled &&
}
); -}); +} diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts index c49424bb27..5d518b5c6b 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts @@ -8,6 +8,7 @@ interface BaseColumnProps { width: WidthEnum; size: number | null; alignment: AlignmentEnum; + wrapText: boolean; minWidth: MinWidthEnum; minWidthLimit: number; @@ -44,10 +45,6 @@ export class BaseColumn { return this.properties.wrapText; } - get minWidthLimit(): number { - return this.properties.minWidth === "manual" ? this.properties.minWidthLimit : 0; - } - getCssWidth(): string { switch (this.properties.width) { case "autoFit": { diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx index 4dd203b28a..c22f50e673 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx @@ -13,22 +13,26 @@ import { ReactNode } from "react"; import { ColumnsType } from "../../../../typings/DatagridProps"; import { StaticInfo } from "../../../typings/static-info"; +export interface IColumnFilterStore { + renderFilterWidgets(): ReactNode; +} + type FilterStore = InputFilterStore | EnumFilterStore; const { Provider } = getGlobalFilterContextObject(); -export class ColumnFilterStore { +export class ColumnFilterStore implements IColumnFilterStore { private _widget: ReactNode; private _error: APIError | null; private _filterStore: FilterStore | null = null; private _context: FilterAPI; private _filterHost: ObservableFilterHost; - readonly filterMinWidth: number; + readonly filterType: string | undefined; constructor(props: ColumnsType, info: StaticInfo, filterHost: ObservableFilterHost) { + this.filterType = ColumnFilterStore.resolveFilterType(props); this._filterHost = filterHost; this._widget = props.filter; - this.filterMinWidth = props.filter ? (props.attribute?.type === "DateTime" ? 150 : 100) : 0; const storeResult = this.createFilterStore(props, null); if (storeResult === null) { this._error = this._filterStore = null; @@ -102,6 +106,27 @@ export class ColumnFilterStore { this._filterStore?.fromJSON(data); } } + + private static resolveFilterType(props: ColumnsType): string | undefined { + if (!props.filter) { + return undefined; + } + switch (props.attribute?.type) { + case "DateTime": + return "date"; + case "Integer": + case "Long": + case "Decimal": + case "AutoNumber": + return "number"; + case "Enum": + case "EnumSet": + case "Boolean": + return "enum"; + default: + return "text"; + } + } } const isListAttributeValue = ( diff --git a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx index 0e4c1ba150..f2136d3e8e 100644 --- a/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx @@ -112,10 +112,6 @@ export class ColumnStore implements GridColumn { return this.baseInfo.draggable; } - get minWidthLimit(): number { - return this.baseInfo.minWidth === "manual" ? this.baseInfo.minWidthLimit : 0; - } - // hiding get canHide(): boolean { return this.baseInfo.hidable; diff --git a/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts b/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts index 2be5eb95f5..23448457fe 100644 --- a/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts +++ b/packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts @@ -33,7 +33,6 @@ export interface GridColumn { // sizing canResize: boolean; - minWidthLimit: number; size: number | undefined; setSize(size: number): void; getCssWidth(): string;