Skip to content

Commit 046f5b2

Browse files
committed
fix(datagrid-web): revert minwidth approach, use a small js-css contract for filterType instead
1 parent 6aaeec5 commit 046f5b2

8 files changed

Lines changed: 63 additions & 59 deletions

File tree

packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid.scss

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -603,26 +603,19 @@ $root: ".widget-datagrid";
603603
}
604604

605605
// Filter-aware min-content sizing for MockHeader cells.
606-
// Uses :has() to detect non-empty filters in each header column and applies
607-
// an invisible ::after element of matching width to the corresponding MockHeader cell.
608-
// Only affects flexible tracks (initial render); fixed tracks (after user resize) are unaffected.
609-
@for $i from 1 through 20 {
610-
$hcol: ".widget-datagrid-grid-head .tr > :nth-child(#{$i})";
611-
$mcol: ".grid-mock-header > :nth-child(#{$i})";
612-
613-
// Any non-empty filter → 100px minimum
614-
.widget-datagrid-grid:has(#{$hcol} .filter:not(:empty)) #{$mcol}::after {
615-
content: "";
616-
display: block;
617-
visibility: hidden;
618-
height: 0;
619-
width: 100px;
620-
}
606+
// The data-filter attribute is set by React based on the column's filter type.
607+
// The ::after pseudo-element establishes an invisible minimum intrinsic width
608+
// that CSS Grid's minmax(auto, 1fr) respects as a floor.
609+
.grid-mock-header > [data-filter]::after {
610+
content: "";
611+
display: block;
612+
visibility: hidden;
613+
height: 0;
614+
width: 100px;
615+
}
621616

622-
// Date filter (has calendar button) → 150px override
623-
.widget-datagrid-grid:has(#{$hcol} .filter .btn-calendar) #{$mcol}::after {
624-
width: 150px;
625-
}
617+
.grid-mock-header > [data-filter="date"]::after {
618+
width: 175px;
626619
}
627620

628621
:where(#{$root}-paging-bottom, #{$root}-padding-top) {

packages/pluggableWidgets/datagrid-web/src/components/GridHeader.tsx

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,23 @@ export function GridHeader(): ReactElement {
2424
<div className="widget-datagrid-grid-head" role="rowgroup" ref={gridSizeStore.gridHeaderRef}>
2525
<div key="headers_row" className="tr" role="row">
2626
<CheckboxColumnHeader key="headers_column_select_all" />
27-
{columns.map(column => {
28-
return (
29-
<ColumnProvider column={column} key={`${column.columnId}`}>
30-
<Header
31-
dropTarget={dragOver}
32-
isDragging={isDragging}
33-
resizer={
34-
<ColumnResizer
35-
minWidth={Math.max(
36-
column.minWidthLimit || 50,
37-
columnsStore.columnFilters[column.columnIndex]?.filterMinWidth ?? 0
38-
)}
39-
onResizeStart={() => columnsStore.setIsResizing(true)}
40-
onResizeEnds={() => columnsStore.setIsResizing(false)}
41-
setColumnWidth={(width: number) => column.setSize(width)}
42-
/>
43-
}
44-
setDropTarget={setDragOver}
45-
setIsDragging={setIsDragging}
46-
/>
47-
</ColumnProvider>
48-
);
49-
})}
27+
{columns.map(column => (
28+
<ColumnProvider column={column} key={`${column.columnId}`}>
29+
<Header
30+
dropTarget={dragOver}
31+
isDragging={isDragging}
32+
resizer={
33+
<ColumnResizer
34+
onResizeStart={() => columnsStore.setIsResizing(true)}
35+
onResizeEnds={() => columnsStore.setIsResizing(false)}
36+
setColumnWidth={(width: number) => column.setSize(width)}
37+
/>
38+
}
39+
setDropTarget={setDragOver}
40+
setIsDragging={setIsDragging}
41+
/>
42+
</ColumnProvider>
43+
))}
5044
{columnsHidable && (
5145
<ColumnSelector
5246
key="headers_column_selector"

packages/pluggableWidgets/datagrid-web/src/components/Header.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export function Header(props: HeaderProps): ReactElement {
3535
const canDrag = columnsDraggable && column.canDrag;
3636
const canSort = columnsSortable && column.canSort;
3737
const canResize = columnsResizable && column.canResize;
38-
const filterStore = columnsStore.columnFilters[column.columnIndex];
3938

4039
const draggableProps = useDraggable(
4140
canDrag,
@@ -84,7 +83,7 @@ export function Header(props: HeaderProps): ReactElement {
8483
</div>
8584
{columnsFilterable && (
8685
<div className="filter" style={{ pointerEvents: props.isDragging ? "none" : undefined }}>
87-
{filterStore?.renderFilterWidgets()}
86+
{columnsStore.columnFilters[column.columnIndex]?.renderFilterWidgets()}
8887
</div>
8988
)}
9089
</div>

packages/pluggableWidgets/datagrid-web/src/components/MockHeader.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { observer } from "mobx-react-lite";
21
import { ReactNode, useCallback, useEffect } from "react";
32
import { useColumnsStore, useDatagridConfig, useGridSizeStore } from "../model/hooks/injection-hooks";
43

5-
export const MockHeader = observer(function MockHeader(): ReactNode {
4+
export function MockHeader(): ReactNode {
65
const columnsStore = useColumnsStore();
76
const config = useDatagridConfig();
87
const gridSizeStore = useGridSizeStore();
@@ -40,6 +39,7 @@ export const MockHeader = observer(function MockHeader(): ReactNode {
4039
<div className={"grid-mock-header"} aria-hidden>
4140
{config.checkboxColumnEnabled && <div data-column-id="checkboxes" key={"checkboxes"}></div>}
4241
{columnsStore.visibleColumns.map(c => {
42+
const filterType = columnsStore.columnFilters[c.columnIndex]?.filterType;
4343
return (
4444
<div
4545
data-column-id={c.columnId}
@@ -48,6 +48,7 @@ export const MockHeader = observer(function MockHeader(): ReactNode {
4848
// as this mock header is aligned with CSS grid, so it is more reliable
4949
// the real header is aligned programmatically based on this header
5050
ref={ref => c.setHeaderElementRef(ref)}
51+
data-filter={filterType}
5152
>
5253
<span>{c.header}</span>
5354
</div>
@@ -56,4 +57,4 @@ export const MockHeader = observer(function MockHeader(): ReactNode {
5657
{config.selectorColumnEnabled && <div data-column-id="selector" key={"selector"}></div>}
5758
</div>
5859
);
59-
});
60+
}

packages/pluggableWidgets/datagrid-web/src/helpers/ColumnBase.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface BaseColumnProps {
88
width: WidthEnum;
99
size: number | null;
1010
alignment: AlignmentEnum;
11+
1112
wrapText: boolean;
1213
minWidth: MinWidthEnum;
1314
minWidthLimit: number;
@@ -44,10 +45,6 @@ export class BaseColumn {
4445
return this.properties.wrapText;
4546
}
4647

47-
get minWidthLimit(): number {
48-
return this.properties.minWidth === "manual" ? this.properties.minWidthLimit : 0;
49-
}
50-
5148
getCssWidth(): string {
5249
switch (this.properties.width) {
5350
case "autoFit": {

packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnFilterStore.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,26 @@ import { ReactNode } from "react";
1313
import { ColumnsType } from "../../../../typings/DatagridProps";
1414
import { StaticInfo } from "../../../typings/static-info";
1515

16+
export interface IColumnFilterStore {
17+
renderFilterWidgets(): ReactNode;
18+
}
19+
1620
type FilterStore = InputFilterStore | EnumFilterStore;
1721

1822
const { Provider } = getGlobalFilterContextObject();
1923

20-
export class ColumnFilterStore {
24+
export class ColumnFilterStore implements IColumnFilterStore {
2125
private _widget: ReactNode;
2226
private _error: APIError | null;
2327
private _filterStore: FilterStore | null = null;
2428
private _context: FilterAPI;
2529
private _filterHost: ObservableFilterHost;
26-
readonly filterMinWidth: number;
30+
readonly filterType: string | undefined;
2731

2832
constructor(props: ColumnsType, info: StaticInfo, filterHost: ObservableFilterHost) {
33+
this.filterType = ColumnFilterStore.resolveFilterType(props);
2934
this._filterHost = filterHost;
3035
this._widget = props.filter;
31-
this.filterMinWidth = props.filter ? (props.attribute?.type === "DateTime" ? 150 : 100) : 0;
3236
const storeResult = this.createFilterStore(props, null);
3337
if (storeResult === null) {
3438
this._error = this._filterStore = null;
@@ -102,6 +106,27 @@ export class ColumnFilterStore {
102106
this._filterStore?.fromJSON(data);
103107
}
104108
}
109+
110+
private static resolveFilterType(props: ColumnsType): string | undefined {
111+
if (!props.filter) {
112+
return undefined;
113+
}
114+
switch (props.attribute?.type) {
115+
case "DateTime":
116+
return "date";
117+
case "Integer":
118+
case "Long":
119+
case "Decimal":
120+
case "AutoNumber":
121+
return "number";
122+
case "Enum":
123+
case "EnumSet":
124+
case "Boolean":
125+
return "enum";
126+
default:
127+
return "text";
128+
}
129+
}
105130
}
106131

107132
const isListAttributeValue = (

packages/pluggableWidgets/datagrid-web/src/helpers/state/column/ColumnStore.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ export class ColumnStore implements GridColumn {
112112
return this.baseInfo.draggable;
113113
}
114114

115-
get minWidthLimit(): number {
116-
return this.baseInfo.minWidth === "manual" ? this.baseInfo.minWidthLimit : 0;
117-
}
118-
119115
// hiding
120116
get canHide(): boolean {
121117
return this.baseInfo.hidable;

packages/pluggableWidgets/datagrid-web/src/typings/GridColumn.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export interface GridColumn {
3333

3434
// sizing
3535
canResize: boolean;
36-
minWidthLimit: number;
3736
size: number | undefined;
3837
setSize(size: number): void;
3938
getCssWidth(): string;

0 commit comments

Comments
 (0)