@linzjs/step-ag-grid 29.9.0 → 29.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@linzjs/step-ag-grid",
3
3
  "repository": "github:linz/step-ag-grid.git",
4
4
  "license": "MIT",
5
- "version": "29.9.0",
5
+ "version": "29.11.0",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -23,6 +23,9 @@ interface FilterUIProps {
23
23
  onToggleOne: (value: string, checked: boolean) => void;
24
24
  }
25
25
 
26
+ const EMPTY_KEY = '__EMPTY__';
27
+ const DEFAULT_EMPTY_LABEL = '-';
28
+
26
29
  const FilterUI: React.FC<FilterUIProps> = ({
27
30
  allValues,
28
31
  selected,
@@ -34,8 +37,8 @@ const FilterUI: React.FC<FilterUIProps> = ({
34
37
  const allChecked = allValues.length > 0 && selected.size === allValues.length;
35
38
 
36
39
  const getDisplayLabel = (raw: string): string => {
37
- const mapped = labels[raw] ?? raw;
38
- return labelFormatter ? labelFormatter(mapped) : mapped;
40
+ const base = raw === EMPTY_KEY ? (labels[EMPTY_KEY] ?? DEFAULT_EMPTY_LABEL) : (labels[raw] ?? raw);
41
+ return labelFormatter ? labelFormatter(base) : base;
39
42
  };
40
43
 
41
44
  return (
@@ -72,26 +75,27 @@ export class GridFilterColumnsMultiSelect implements IFilterComp {
72
75
  private labelFormatter?: (value: string) => string;
73
76
  private reactRoot: Root | null = null;
74
77
 
78
+ private normalizeCellValue(value: unknown): string {
79
+ if (typeof value === 'string') return value.trim() === '' ? EMPTY_KEY : value;
80
+ return EMPTY_KEY;
81
+ }
82
+
75
83
  private loadFieldValues(): string[] {
76
84
  const field = this.params.colDef.field as string;
77
85
  const values = new Set<string>();
78
86
 
79
87
  this.params.api.forEachNode((node) => {
80
- const data = node.data;
81
- const cellValue = data?.[field];
82
- if (
83
- data &&
84
- typeof data === 'object' &&
85
- field in data &&
86
- typeof cellValue === 'string' &&
87
- cellValue !== undefined &&
88
- cellValue !== null
89
- ) {
90
- values.add(cellValue);
91
- }
88
+ const data = node.data ?? {};
89
+ const raw = (data as Record<string, unknown>)[field];
90
+ const norm = this.normalizeCellValue(raw);
91
+ values.add(norm);
92
92
  });
93
93
 
94
- return Array.from(values).sort();
94
+ return Array.from(values).sort((a, b) => {
95
+ if (a === EMPTY_KEY && b !== EMPTY_KEY) return -1;
96
+ if (b === EMPTY_KEY && a !== EMPTY_KEY) return 1;
97
+ return a.localeCompare(b);
98
+ });
95
99
  }
96
100
 
97
101
  init(params: CheckboxMultiFilterParams): void {
@@ -99,6 +103,10 @@ export class GridFilterColumnsMultiSelect implements IFilterComp {
99
103
  this.labels = { ...params.labels };
100
104
  this.labelFormatter = params.labelFormatter;
101
105
 
106
+ if (!(EMPTY_KEY in this.labels)) {
107
+ this.labels[EMPTY_KEY] = DEFAULT_EMPTY_LABEL;
108
+ }
109
+
102
110
  this.allValues = this.loadFieldValues();
103
111
  this.selectedValues = new Set(this.allValues);
104
112
 
@@ -150,18 +158,15 @@ export class GridFilterColumnsMultiSelect implements IFilterComp {
150
158
  return this.selectedValues.size > 0;
151
159
  }
152
160
 
153
- doesFilterPass(params: IDoesFilterPassParams): boolean {
161
+ doesFilterPass(p: IDoesFilterPassParams): boolean {
154
162
  const field = this.params.colDef.field as string;
155
- if (!params.data || typeof params.data !== 'object' || !(field in params.data)) {
156
- return false;
157
- }
158
-
159
- const cellValue = (params.data as Record<string, unknown>)[field];
160
- if (typeof cellValue !== 'string') {
161
- return false;
163
+ if (!p.data || typeof p.data !== 'object') {
164
+ return this.selectedValues.has(EMPTY_KEY);
162
165
  }
163
166
 
164
- return this.selectedValues.has(cellValue);
167
+ const raw = (p.data as Record<string, unknown>)[field];
168
+ const norm = this.normalizeCellValue(raw);
169
+ return this.selectedValues.has(norm);
165
170
  }
166
171
 
167
172
  getModel(): CheckboxMultiFilterModel | null {
@@ -185,6 +190,6 @@ export const createCheckboxMultiFilterParams = (
185
190
  labels: Record<string, string> = {},
186
191
  labelFormatter?: (value: string) => string,
187
192
  ): Partial<CheckboxMultiFilterParams> => ({
188
- labels,
193
+ labels: { [EMPTY_KEY]: DEFAULT_EMPTY_LABEL, ...labels },
189
194
  labelFormatter,
190
195
  });
@@ -60,6 +60,7 @@ const GridFilterColumnsMultiSelectTemplate: StoryFn<typeof Grid<ITestRow>> = (pr
60
60
  filterParams: createCheckboxMultiFilterParams({
61
61
  Developer: 'FE Dev',
62
62
  Manager: 'Tech Manager',
63
+ __EMPTY__: 'None',
63
64
  }),
64
65
  }),
65
66
  GridCell({
@@ -81,7 +82,7 @@ const GridFilterColumnsMultiSelectTemplate: StoryFn<typeof Grid<ITestRow>> = (pr
81
82
  { id: 1001, position: 'Developer', age: 12, desc: 'Frontend developer' },
82
83
  { id: 1002, position: 'Manager', age: 65, desc: 'Technical Manager' },
83
84
  { id: 1003, position: 'Tester', age: 30, desc: 'E2E tester' },
84
- { id: 1004, position: 'Developer', age: 12, desc: 'Fullstack Developer' },
85
+ { id: 1004, age: 12, desc: 'Fullstack Developer' },
85
86
  { id: 1005, position: 'Developer', age: 13, desc: 'Backend Developer' },
86
87
  { id: 1006, position: 'Architect', age: 30, desc: 'Architect' },
87
88
  ]);
@@ -144,7 +144,7 @@ $grid-base-font-size: calc(#{lui.$base-font-size} - 1px);
144
144
  }
145
145
 
146
146
  .ag-icon-filter {
147
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%232A292C'%3E%3Cpath d='M6 12.984v-1.969h12v1.969zM3 6h18v2.016H3zm6.984 12v-2.016h4.031V18z'/%3E%3C/svg%3E") !important;
147
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23007198'%3E%3Cpath d='M6 12.984v-1.969h12v1.969zM3 6h18v2.016H3zm6.984 12v-2.016h4.031V18z'/%3E%3C/svg%3E") !important;
148
148
  background-repeat: no-repeat;
149
149
  background-position: center;
150
150
  background-size: contain;
@@ -154,6 +154,12 @@ $grid-base-font-size: calc(#{lui.$base-font-size} - 1px);
154
154
  content: none !important;
155
155
  }
156
156
  }
157
+
158
+ .ag-header-cell-filter-button.ag-has-popup-positioned-under .ag-icon-filter {
159
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M6 12.984v-1.969h12v1.969zM3 6h18v2.016H3zm6.984 12v-2.016h4.031V18z'/%3E%3C/svg%3E") !important;
160
+ background-color: #007198;
161
+ border-radius: 2px;
162
+ }
157
163
 
158
164
  .ag-header-group-cell {
159
165
  text-transform: uppercase;