Skip to content

Commit c8baaca

Browse files
authored
refactor(columns): split filter and sort properties (#14)
1 parent 7b50bee commit c8baaca

File tree

16 files changed

+120
-86
lines changed

16 files changed

+120
-86
lines changed

CHANGELOG.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222

2323
```ts
2424
const columns: ColumnConfiguration<User>[] = [
25-
{ key: 'id', headerText: 'User ID', type: 'number', filter: true, sort: true },
26-
{ key: 'name', filter: true, sort: true },
25+
{ key: 'id', headerText: 'User ID', type: 'number', filterable: true, sortable: true },
26+
{ key: 'name', filterable: true, sortable: true },
2727
];
2828
```
2929

@@ -35,17 +35,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
key="id"
3636
header-text="User ID"
3737
type="number"
38-
.filter=${true}
39-
.sort=${true}
38+
filterable
39+
sortable
4040
></igc-grid-lite-column>
4141
<igc-grid-lite-column
4242
key="name"
43-
.filter=${true}
44-
.sort=${true}
43+
filterable
44+
sortable
4545
></igc-grid-lite-column>
4646
</igc-grid-lite>
4747
```
4848

49+
- **BREAKING:** Column `sort` and `filter` properties have been replaced with separate boolean and configuration properties:
50+
- `sort``sortable` (boolean) + `sortingCaseSensitive` (boolean) + `sortConfiguration` (object with `comparer` option)
51+
- `filter``filterable` (boolean) + `filteringCaseSensitive` (boolean)
52+
53+
- **BREAKING:** Removed `ColumnFilterConfiguration` type. Use `filteringCaseSensitive` boolean property directly on the column.
4954
- **BREAKING:** Renamed `GridSortConfiguration` type to `GridLiteSortingOptions`.
5055
- **BREAKING:** Renamed `IgcGridLite.sortConfiguration` property to `sortingOptions`.
5156
- **BREAKING:** Renamed `IgcGridLite.sortExpressions` property to `sortingExpressions`.

demo/demo.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,19 @@ const themeChoose = html`
106106
`;
107107

108108
const columns: ColumnConfiguration<User>[] = [
109-
{ key: 'id', headerText: 'User ID', resizable: true, type: 'number', filter: true, sort: true },
109+
{
110+
key: 'id',
111+
headerText: 'User ID',
112+
resizable: true,
113+
type: 'number',
114+
filterable: true,
115+
sortable: true,
116+
},
110117
{
111118
key: 'name',
112119
cellTemplate: (params) => html`<igc-input .value=${params.value}></igc-input>`,
113-
filter: true,
114-
sort: true,
120+
filterable: true,
121+
sortable: true,
115122
},
116123
{
117124
key: 'avatar',
@@ -124,8 +131,8 @@ const columns: ColumnConfiguration<User>[] = [
124131
{
125132
key: 'satisfaction',
126133
type: 'number',
127-
sort: true,
128-
filter: true,
134+
sortable: true,
135+
filterable: true,
129136
cellTemplate: (params) =>
130137
html`<igc-rating
131138
readonly
@@ -144,7 +151,8 @@ const columns: ColumnConfiguration<User>[] = [
144151
(choice) => html`<igc-select-item .value=${choice}>${choice}</igc-select-item>`,
145152
)}</igc-select
146153
>`,
147-
sort: {
154+
sortable: true,
155+
sortConfiguration: {
148156
comparer: (a, b) => choices.indexOf(a) - choices.indexOf(b),
149157
},
150158
},
@@ -157,8 +165,8 @@ const columns: ColumnConfiguration<User>[] = [
157165
{
158166
key: 'subscribed',
159167
type: 'boolean',
160-
sort: true,
161-
filter: true,
168+
sortable: true,
169+
filterable: true,
162170
cellTemplate: (params) =>
163171
html`<igc-checkbox
164172
label-position="before"
@@ -189,7 +197,7 @@ const toggleFiltering = () => {
189197
(col) => col.key === 'name',
190198
)!;
191199

192-
column.filter = !column.filter;
200+
column.filterable = !column.filterable;
193201
};
194202

195203
render(
@@ -214,8 +222,9 @@ render(
214222
.headerText=${col.headerText}
215223
?hidden=${col.hidden}
216224
?resizable=${col.resizable}
217-
.sort=${col.sort}
218-
.filter=${col.filter}
225+
?sortable=${col.sortable}
226+
.sortConfiguration=${col.sortConfiguration}
227+
?filterable=${col.filterable}
219228
.cellTemplate=${col.cellTemplate}
220229
.headerTemplate=${col.headerTemplate as any}
221230
></igc-grid-lite-column>`,

src/components/column.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { registerComponent } from '../internal/register.js';
66
import { GRID_COLUMN_TAG } from '../internal/tags.js';
77
import type {
88
BaseColumnConfiguration,
9-
ColumnFilterConfiguration,
109
ColumnSortConfiguration,
1110
IgcCellContext,
1211
IgcHeaderContext,
@@ -62,13 +61,25 @@ export class IgcGridLiteColumn<T extends object>
6261
@property({ type: Boolean })
6362
public resizable = false;
6463

65-
/** Sort configuration for the column. */
66-
@property({ attribute: false })
67-
public sort?: ColumnSortConfiguration<T> | boolean = false;
64+
/** Indicates whether the column is sortable. */
65+
@property({ type: Boolean })
66+
public sortable = false;
67+
68+
/** Whether sort operations will be case sensitive. */
69+
@property({ type: Boolean, attribute: 'sorting-case-sensitive' })
70+
public sortingCaseSensitive = false;
6871

69-
/** Filter configuration for the column. */
72+
/** Sort configuration for the column (e.g., custom comparer). */
7073
@property({ attribute: false })
71-
public filter?: ColumnFilterConfiguration | boolean = false;
74+
public sortConfiguration?: ColumnSortConfiguration<T>;
75+
76+
/** Indicates whether the column is filterable. */
77+
@property({ type: Boolean })
78+
public filterable = false;
79+
80+
/** Whether filter operations will be case sensitive. */
81+
@property({ type: Boolean, attribute: 'filtering-case-sensitive' })
82+
public filteringCaseSensitive = false;
7283

7384
/** Custom header template for the column. */
7485
@property({ attribute: false })

src/components/filter-row.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ export default class IgcFilterRow<T extends object> extends LitElement {
377377
? nothing
378378
: html`
379379
<div part="filter-row-preview">
380-
${column.filter ? this.renderFilterState(column) : nothing}
380+
${column.filterable ? this.renderFilterState(column) : nothing}
381381
</div>
382382
`
383383
);

src/components/grid.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ export class IgcGridLite<T extends object> extends EventEmitterBase<IgcGridLiteE
476476

477477
protected _renderFilterRow() {
478478
return html`${cache(
479-
this._stateController.columns.some((column) => column.filter)
479+
this._stateController.columns.some((column) => column.filterable)
480480
? html`<igc-filter-row style=${styleMap(this._domController.columnSizes)}></igc-filter-row>`
481481
: nothing
482482
)}`;

src/components/header.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default class IgcGridLiteHeader<T extends object> extends LitElement {
3636
}
3737

3838
protected get isSortable() {
39-
return Boolean(this.column.sort);
39+
return Boolean(this.column.sortable);
4040
}
4141

4242
protected get resizeController() {

src/controllers/filter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,15 @@ export class FilterController<T extends object> implements ReactiveController {
7171
}
7272

7373
public setActiveColumn(column?: ColumnConfiguration<T>) {
74-
if (column?.filter && this.filterRow?.active) {
74+
if (column?.filterable && this.filterRow?.active) {
7575
this.filterRow.column = column;
7676
this.filterRow.expression = this.getDefaultExpression(column);
7777
this.host.requestUpdate();
7878
}
7979
}
8080

8181
public getDefaultExpression(column: ColumnConfiguration<T>) {
82-
const caseSensitive =
83-
typeof column.filter === 'boolean' ? false : Boolean(column.filter?.caseSensitive);
82+
const caseSensitive = Boolean(column.filteringCaseSensitive);
8483
const operands = getFilterOperandsFor(column);
8584
const keys = Object.keys(operands) as Keys<typeof operands>[];
8685

src/controllers/sort.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import type { ReactiveController } from 'lit';
22
import { PIPELINE } from '../internal/constants.js';
3-
import type {
4-
ColumnConfiguration,
5-
ColumnSortConfiguration,
6-
GridHost,
7-
Keys,
8-
} from '../internal/types.js';
3+
import type { ColumnConfiguration, GridHost, Keys } from '../internal/types.js';
94
import { asArray } from '../internal/utils.js';
105
import type { SortingDirection, SortingExpression, SortState } from '../operations/sort/types.js';
116

@@ -24,29 +19,29 @@ export class SortController<T extends object> implements ReactiveController {
2419
return true;
2520
}
2621

27-
#resolveSortOptions(options?: boolean | ColumnSortConfiguration<T>) {
22+
#resolveSortOptions(column?: ColumnConfiguration<T>) {
2823
const expr: Pick<SortingExpression<T>, 'caseSensitive' | 'comparer'> = {
2924
caseSensitive: false,
3025
comparer: undefined,
3126
};
3227

33-
if (!options || typeof options === 'boolean') {
28+
if (!column) {
3429
return expr as Partial<SortingExpression<T>>;
3530
}
3631

3732
return Object.assign(expr, {
38-
caseSensitive: options.caseSensitive,
39-
comparer: options.comparer,
33+
caseSensitive: column.sortingCaseSensitive,
34+
comparer: column.sortConfiguration?.comparer,
4035
}) as Partial<SortingExpression<T>>;
4136
}
4237

4338
#createDefaultExpression(key: Keys<T>) {
44-
const options = this.host.getColumn(key)?.sort;
39+
const column = this.host.getColumn(key);
4540

4641
return {
4742
key,
4843
direction: 'ascending',
49-
...this.#resolveSortOptions(options),
44+
...this.#resolveSortOptions(column),
5045
} as SortingExpression<T>;
5146
}
5247

@@ -93,18 +88,18 @@ export class SortController<T extends object> implements ReactiveController {
9388
this.#emitSortedEvent(expression);
9489
}
9590

96-
public prepareExpression({ key, sort: options }: ColumnConfiguration<T>): SortingExpression<T> {
97-
if (this.state.has(key)) {
98-
const expr = this.state.get(key)!;
91+
public prepareExpression(column: ColumnConfiguration<T>): SortingExpression<T> {
92+
if (this.state.has(column.key)) {
93+
const expr = this.state.get(column.key)!;
9994

10095
return Object.assign(expr, {
10196
direction: this.#orderBy(expr.direction),
102-
...this.#resolveSortOptions(options),
97+
...this.#resolveSortOptions(column),
10398
});
10499
}
105100

106101
// Initial state
107-
return this.#createDefaultExpression(key);
102+
return this.#createDefaultExpression(column.key);
108103
}
109104

110105
public reset(key?: Keys<T>) {

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export type {
1111
BaseIgcCellContext,
1212
BasePropertyType,
1313
ColumnConfiguration,
14-
ColumnFilterConfiguration,
1514
ColumnSortConfiguration,
1615
DataPipelineConfiguration,
1716
DataPipelineHook,

src/internal/constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export const DEFAULT_COLUMN_CONFIG = Object.freeze<ColumnConfiguration<any>>({
1818
type: 'string',
1919
resizable: false,
2020
hidden: false,
21-
sort: false,
22-
filter: false,
21+
sortable: false,
22+
filterable: false,
2323
});
2424
export const NAVIGATION_STATE: Map<NavigationState, ActiveNode<any>> = new Map([
2525
['previous', SENTINEL_NODE],

0 commit comments

Comments
 (0)