ag-grid-url-sync 0.2.1 → 0.2.2

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2025 NearForm
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  # AG Grid URL Sync
4
4
 
5
- A lightweight TypeScript library for synchronizing AG Grid text filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
5
+ A lightweight TypeScript library for synchronizing AG Grid text and number filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
6
6
 
7
7
  ## Features
8
8
 
9
9
  - 🔍 **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
10
+ - 🔢 **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
10
11
  - 🔗 Manual URL generation for sharing filter states
11
12
  - ↔️ Bidirectional sync between grid and URL
12
13
  - 🛠️ Framework agnostic - works with any AG Grid setup
@@ -21,7 +22,9 @@ A lightweight TypeScript library for synchronizing AG Grid text filters with URL
21
22
 
22
23
  ## Supported Filter Types
23
24
 
24
- Supports **all AG Grid text filter operations** (8 total) with clean, human-readable URL parameters:
25
+ Supports **all AG Grid text and number filter operations** (17 total) with clean, human-readable URL parameters:
26
+
27
+ ### Text Filters (8 operations)
25
28
 
26
29
  | Filter Type | Operation | URL Format | Example | Description |
27
30
  | ----------- | ------------ | ---------------------------- | -------------------------- | --------------------------- |
@@ -34,41 +37,76 @@ Supports **all AG Grid text filter operations** (8 total) with clean, human-read
34
37
  | **Text** | Blank | `f_column_blank=true` | `f_optional_blank=true` | Field is empty/null |
35
38
  | **Text** | Not Blank | `f_column_notBlank=true` | `f_required_notBlank=true` | Field has any value |
36
39
 
40
+ ### Number Filters (9 operations)
41
+
42
+ | Filter Type | Operation | URL Format | Example | Description |
43
+ | ----------- | --------------------- | ------------------------ | ------------------------ | ----------------------------- |
44
+ | **Number** | Equals | `f_column_eq=value` | `f_age_eq=30` | Number equals value exactly |
45
+ | **Number** | Not Equal | `f_column_neq=value` | `f_salary_neq=50000` | Number does not equal value |
46
+ | **Number** | Greater Than | `f_column_gt=value` | `f_experience_gt=5` | Number is greater than value |
47
+ | **Number** | Greater Than or Equal | `f_column_gte=value` | `f_score_gte=85` | Number is ≥ value |
48
+ | **Number** | Less Than | `f_column_lt=value` | `f_budget_lt=10000` | Number is less than value |
49
+ | **Number** | Less Than or Equal | `f_column_lte=value` | `f_hours_lte=40` | Number is ≤ value |
50
+ | **Number** | In Range | `f_column_range=min,max` | `f_age_range=25,45` | Number is between min and max |
51
+ | **Number** | Blank | `f_column_blank=true` | `f_bonus_blank=true` | Field is empty/null |
52
+ | **Number** | Not Blank | `f_column_notBlank=true` | `f_salary_notBlank=true` | Field has any numeric value |
53
+
37
54
  > **💡 Naming Convention Note**: URL parameters use short, clean names for better readability (`eq` for equals, `neq` for not equal). These are automatically converted to the proper AG Grid operation names (`equals`, `notEqual`) internally. This design keeps URLs concise while maintaining full compatibility with AG Grid's filter API.
38
55
 
39
56
  ### Filter Detection
40
57
 
41
58
  The library automatically works with:
42
59
 
43
- - Columns configured with `filter: 'agTextColumnFilter'`
60
+ - **Text columns** configured with `filter: 'agTextColumnFilter'`
61
+ - **Number columns** configured with `filter: 'agNumberColumnFilter'`
62
+ - **Auto-detection** based on `cellDataType: 'number'` configuration
44
63
  - Columns with `filter: true` (AG Grid's default text filter)
45
- - Any column where users apply text-based filters
46
- - All AG Grid text filter operations through the filter menu
64
+ - Any column where users apply text or number-based filters
65
+ - All AG Grid text and number filter operations through the filter menu
66
+ - **Mixed filter types** - combine text and number filters in the same URL
47
67
 
48
68
  ### URL Examples
49
69
 
50
- **Simple filter:**
70
+ **Simple text filter:**
51
71
 
52
72
  ```
53
73
  https://app.com/data?f_name_contains=john
54
74
  ```
55
75
 
56
- **Multiple operations:**
76
+ **Simple number filter:**
77
+
78
+ ```
79
+ https://app.com/data?f_salary_gt=75000
80
+ ```
81
+
82
+ **Mixed text and number filters:**
83
+
84
+ ```
85
+ https://app.com/data?f_name_contains=john&f_department_eq=Engineering&f_salary_gte=80000&f_age_range=25,45
86
+ ```
87
+
88
+ **Complex filtering with range operations:**
57
89
 
58
90
  ```
59
- https://app.com/data?f_name_contains=john&f_department_eq=Engineering&f_email_startsWith=admin&f_status_neq=inactive
91
+ https://app.com/data?f_name_contains=manager&f_salary_range=60000,100000&f_experience_gte=5&f_status_eq=active
60
92
  ```
61
93
 
62
- **Complex filtering with all operations:**
94
+ **All text operations:**
63
95
 
64
96
  ```
65
97
  https://app.com/data?f_name_contains=john&f_email_startsWith=admin&f_status_neq=inactive&f_description_endsWith=test&f_optional_blank=true&f_required_notBlank=true&f_tags_notContains=spam&f_title_eq=manager
66
98
  ```
67
99
 
68
- **Blank operations:**
100
+ **All number operations:**
69
101
 
70
102
  ```
71
- https://app.com/data?f_comments_blank=true&f_name_notBlank=true
103
+ https://app.com/data?f_age_eq=30&f_salary_neq=50000&f_experience_gt=5&f_score_gte=85&f_budget_lt=10000&f_hours_lte=40&f_age_range=25,45&f_bonus_blank=true&f_salary_notBlank=true
104
+ ```
105
+
106
+ **Blank operations (both text and number):**
107
+
108
+ ```
109
+ https://app.com/data?f_comments_blank=true&f_bonus_blank=true&f_name_notBlank=true&f_salary_notBlank=true
72
110
  ```
73
111
 
74
112
  ## Installation
@@ -177,13 +215,23 @@ import { createUrlSync } from 'ag-grid-url-sync'
177
215
  // Initialize with AG Grid API
178
216
  const urlSync = createUrlSync(gridApi)
179
217
 
180
- // Generate shareable URL with current filters
218
+ // Generate shareable URL with current filters (text and number)
181
219
  const shareableUrl = urlSync.generateUrl()
220
+ // Result: https://app.com/data?f_name_contains=john&f_salary_gte=80000&f_age_range=25,45
182
221
 
183
- // Apply filters from URL
184
- urlSync.applyFromUrl()
222
+ // Apply filters from URL (automatically detects text vs number columns)
223
+ urlSync.applyFromUrl(
224
+ 'https://app.com/data?f_name_contains=manager&f_salary_gt=75000'
225
+ )
185
226
 
186
- // Clear all text filters
227
+ // Apply specific filter programmatically
228
+ urlSync.applyFilters({
229
+ name: { filterType: 'text', type: 'contains', filter: 'john' },
230
+ salary: { filterType: 'number', type: 'greaterThan', filter: 75000 },
231
+ age: { filterType: 'number', type: 'inRange', filter: 25, filterTo: 45 }
232
+ })
233
+
234
+ // Clear all text and number filters
187
235
  urlSync.clearFilters()
188
236
  ```
189
237
 
@@ -241,10 +289,32 @@ function GridComponent() {
241
289
  <AgGridReact
242
290
  onGridReady={params => setGridApi(params.api)}
243
291
  rowData={rowData}
244
- columnDefs={columnDefs}
292
+ columnDefs={[
293
+ {
294
+ field: 'name',
295
+ filter: 'agTextColumnFilter',
296
+ floatingFilter: true
297
+ },
298
+ {
299
+ field: 'email',
300
+ filter: 'agTextColumnFilter',
301
+ floatingFilter: true
302
+ },
303
+ {
304
+ field: 'salary',
305
+ filter: 'agNumberColumnFilter',
306
+ floatingFilter: true
307
+ },
308
+ {
309
+ field: 'age',
310
+ filter: 'agNumberColumnFilter',
311
+ floatingFilter: true
312
+ }
313
+ ]}
245
314
  defaultColDef={{
246
- filter: 'agTextColumnFilter',
247
- floatingFilter: true
315
+ flex: 1,
316
+ sortable: true,
317
+ resizable: true
248
318
  }}
249
319
  />
250
320
  </div>
@@ -253,65 +323,6 @@ function GridComponent() {
253
323
  }
254
324
  ```
255
325
 
256
- ### React Router Integration
257
-
258
- For single-page applications using React Router, you can sync filters with the browser URL:
259
-
260
- ```tsx
261
- import React, { useState } from 'react'
262
- import { useNavigate, useLocation } from 'react-router-dom'
263
- import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
264
-
265
- function RouterGridComponent() {
266
- const [gridApi, setGridApi] = useState(null)
267
- const navigate = useNavigate()
268
- const location = useLocation()
269
-
270
- const { shareUrl, clearFilters, hasFilters, isReady } = useAGGridUrlSync(
271
- gridApi,
272
- {
273
- autoApplyOnMount: true, // Automatically apply filters from URL on mount
274
- paramPrefix: 'f_'
275
- }
276
- )
277
-
278
- // Update browser URL with current filters
279
- const updateUrlWithFilters = () => {
280
- const url = shareUrl()
281
- const urlParams = new URL(url).searchParams
282
- const currentParams = new URLSearchParams(location.search)
283
-
284
- // Clear existing filter params
285
- for (const [key] of currentParams) {
286
- if (key.startsWith('f_')) {
287
- currentParams.delete(key)
288
- }
289
- }
290
-
291
- // Add current filter params
292
- for (const [key, value] of urlParams) {
293
- currentParams.set(key, value)
294
- }
295
-
296
- navigate(`${location.pathname}?${currentParams.toString()}`, {
297
- replace: true
298
- })
299
- }
300
-
301
- return (
302
- <div>
303
- <button onClick={updateUrlWithFilters} disabled={!isReady}>
304
- Update URL with Filters
305
- </button>
306
- <button onClick={clearFilters} disabled={!hasFilters}>
307
- Clear All Filters
308
- </button>
309
- {/* Grid component */}
310
- </div>
311
- )
312
- }
313
- ```
314
-
315
326
  ### React Hook API
316
327
 
317
328
  #### `useAGGridUrlSync(gridApi, options?)`
@@ -449,16 +460,20 @@ The library generates clean, human-readable URLs:
449
460
 
450
461
  ```
451
462
  Base URL: https://app.com/page
452
- With filters: https://app.com/page?f_name_contains=john&f_status_eq=active
463
+ With text filters: https://app.com/page?f_name_contains=john&f_status_eq=active
464
+ With number filters: https://app.com/page?f_salary_gte=75000&f_age_range=25,45
465
+ Mixed filters: https://app.com/page?f_name_contains=john&f_salary_gte=75000&f_age_lt=50
453
466
  ```
454
467
 
455
468
  Parameter structure:
456
469
 
457
470
  - Prefix: `f_` (configurable - useful for multi-grid scenarios)
458
471
  - Format: `f_{columnName}_{operation}={value}`
459
- - Operations: `contains`, `eq` (equals)
472
+ - **Text Operations**: `contains`, `eq`, `neq`, `startsWith`, `endsWith`, `notContains`, `blank`, `notBlank`
473
+ - **Number Operations**: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `range`, `blank`, `notBlank`
474
+ - **Range Format**: `f_column_range=min,max` (comma-separated values)
460
475
  - Standard URL encoding for special characters
461
- - Supports column names with underscores (e.g., `user_id`, `created_date`)
476
+ - Supports column names with underscores (e.g., `user_id`, `salary_base`, `created_date`)
462
477
 
463
478
  ## API Reference
464
479
 
@@ -568,32 +583,36 @@ Check out the [examples](./examples) directory for comprehensive working demos:
568
583
  Comprehensive demonstration showcasing all features:
569
584
 
570
585
  - **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
571
- - **Filter scenarios** - Pre-configured examples (Sales team, Engineering, Executive view, etc.)
572
- - **New operation demos** - Dedicated buttons for startsWith, endsWith, and notContains filters
586
+ - **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
587
+ - **Mixed filter scenarios** - Text and number filters working together (Sales team + salary filters, Engineering + experience, Executive view with high salaries)
588
+ - **Number operation demos** - Dedicated buttons for salary ranges, age filtering, experience thresholds, and blank number fields
573
589
  - **URL sharing workflow** - Copy to clipboard, email, and Slack integration
574
- - **Performance monitoring** - Real-time benchmarks and stress testing
575
- - **Error handling** - Malformed URL and invalid filter testing
576
- - **Complete API showcase** - Generate URLs, apply filters, clear filters
590
+ - **Performance monitoring** - Real-time benchmarks and stress testing with mixed filter types
591
+ - **Error handling** - Malformed URL and invalid filter testing for both text and numbers
592
+ - **Complete API showcase** - Generate URLs, apply filters, clear filters with comprehensive examples
577
593
 
578
594
  ### ⚛️ [React Integration](./examples/react-basic/basic-grid.tsx)
579
595
 
580
596
  Clean React component showing the `useAGGridUrlSync` hook:
581
597
 
582
- - React hook integration with AG Grid
583
- - Automatic filter state management
598
+ - React hook integration with AG Grid for text and number filters
599
+ - Automatic filter state management for mixed filter types
584
600
  - Share button with clipboard functionality
585
601
  - Filter status indicators and controls
586
- - Auto-apply filters on component mount
587
- - Full TypeScript support
602
+ - Auto-apply filters on component mount with both text and number support
603
+ - Enhanced employee data with salary, age, and experience columns
604
+ - Full TypeScript support with comprehensive type coverage
588
605
 
589
606
  ### 📊 [Shared Data](./examples/shared-data.js)
590
607
 
591
608
  Common data and column definitions used across examples:
592
609
 
593
- - Employee data with realistic company information
594
- - Project data with status and priority fields
595
- - Column definitions with complete text filter support
596
- - All 8 text filter operations enabled by default
610
+ - Enhanced employee data with salary, age, and experience number fields
611
+ - Project data with budget and numeric fields for comprehensive testing
612
+ - Column definitions with complete text and number filter support
613
+ - All 8 text filter operations and 9 number filter operations enabled
614
+ - Realistic data ranges for demonstrating number filters (salaries $58K-$95K, ages 26-42, experience 3-15 years)
615
+ - Includes null values for demonstrating blank/notBlank operations
597
616
 
598
617
  All examples work out-of-the-box and demonstrate the complete functionality. The HTML demo can be opened directly in your browser, while the React example shows clean integration patterns.
599
618
 
@@ -607,6 +626,6 @@ All examples work out-of-the-box and demonstrate the complete functionality. The
607
626
 
608
627
  ## License
609
628
 
610
- This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.
629
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
611
630
 
612
631
  [![banner](https://raw.githubusercontent.com/nearform/.github/refs/heads/master/assets/os-banner-green.svg)](https://www.nearform.com/contact/?utm_source=open-source&utm_medium=banner&utm_campaign=os-project-pages)
@@ -1,4 +1,9 @@
1
1
  import type { FilterState, InternalConfig } from './types.js';
2
+ import type { GridApi } from 'ag-grid-community';
3
+ /**
4
+ * Detects the expected filter type for a column based on AG Grid configuration
5
+ */
6
+ export declare function detectColumnFilterType(gridApi: GridApi, columnId: string): 'text' | 'number' | null;
2
7
  /**
3
8
  * Gets the current filter model from AG Grid
4
9
  */
@@ -1,4 +1,42 @@
1
- import { AG_GRID_OPERATION_NAMES, REVERSE_AG_GRID_OPERATION_NAMES } from './types.js';
1
+ import { AG_GRID_OPERATION_NAMES, REVERSE_AG_GRID_OPERATION_NAMES, TEXT_FILTER_OPERATIONS, NUMBER_FILTER_OPERATIONS } from './types.js';
2
+ /**
3
+ * Type predicate to check if an operation is a valid text filter operation
4
+ */
5
+ function isTextFilterOperation(operation) {
6
+ return TEXT_FILTER_OPERATIONS.includes(operation);
7
+ }
8
+ /**
9
+ * Type predicate to check if an operation is a valid number filter operation
10
+ */
11
+ function isNumberFilterOperation(operation) {
12
+ return NUMBER_FILTER_OPERATIONS.includes(operation);
13
+ }
14
+ /**
15
+ * Detects the expected filter type for a column based on AG Grid configuration
16
+ */
17
+ export function detectColumnFilterType(gridApi, columnId) {
18
+ try {
19
+ const column = gridApi.getColumn(columnId);
20
+ if (!column)
21
+ return null;
22
+ const colDef = column.getColDef();
23
+ // 1. Explicit filter configuration takes priority
24
+ if (colDef.filter === 'agNumberColumnFilter')
25
+ return 'number';
26
+ if (colDef.filter === 'agTextColumnFilter')
27
+ return 'text';
28
+ // 2. Cell data type configuration
29
+ if (colDef.cellDataType === 'number')
30
+ return 'number';
31
+ if (colDef.cellDataType === 'text')
32
+ return 'text';
33
+ // 3. Default to text for backward compatibility
34
+ return 'text';
35
+ }
36
+ catch {
37
+ return 'text'; // Safe fallback
38
+ }
39
+ }
2
40
  /**
3
41
  * Gets the current filter model from AG Grid
4
42
  */
@@ -12,17 +50,37 @@ export function getFilterModel(config) {
12
50
  for (const [column, filter] of Object.entries(model)) {
13
51
  if (!filter || typeof filter !== 'object')
14
52
  continue;
15
- const { filterType, type, filter: value } = filter;
16
- if (filterType !== 'text')
17
- continue;
18
- // Map AG Grid operations back to our internal operations using centralized mapping
19
- const internalOperation = REVERSE_AG_GRID_OPERATION_NAMES[type];
20
- if (internalOperation) {
21
- filterState[column] = {
22
- filterType: 'text',
23
- type: internalOperation,
24
- filter: value || ''
25
- };
53
+ const { filterType, type, filter: value, filterTo } = filter;
54
+ // Handle both text and number filters
55
+ if (filterType === 'text') {
56
+ // Map AG Grid operations back to our internal operations using centralized mapping
57
+ const internalOperation = REVERSE_AG_GRID_OPERATION_NAMES[type];
58
+ // Use type predicate to validate and narrow the type
59
+ if (internalOperation && isTextFilterOperation(internalOperation)) {
60
+ filterState[column] = {
61
+ filterType: 'text',
62
+ type: internalOperation, // Now properly typed as TextFilterOperation
63
+ filter: value || ''
64
+ };
65
+ }
66
+ }
67
+ else if (filterType === 'number') {
68
+ // Map AG Grid number operations back to our internal operations
69
+ const internalOperation = REVERSE_AG_GRID_OPERATION_NAMES[type];
70
+ // Use type predicate to validate and narrow the type
71
+ if (internalOperation && isNumberFilterOperation(internalOperation)) {
72
+ const numberFilter = {
73
+ filterType: 'number',
74
+ type: internalOperation, // Now properly typed as NumberFilterOperation
75
+ filter: typeof value === 'number' ? value : 0
76
+ };
77
+ // Handle range operations
78
+ if (internalOperation === 'inRange' && typeof filterTo === 'number') {
79
+ ;
80
+ numberFilter.filterTo = filterTo;
81
+ }
82
+ filterState[column] = numberFilter;
83
+ }
26
84
  }
27
85
  }
28
86
  return filterState;
@@ -34,6 +92,37 @@ export function getFilterModel(config) {
34
92
  return {};
35
93
  }
36
94
  }
95
+ /**
96
+ * Converts internal filter to AG Grid filter format
97
+ */
98
+ function convertToAGGridFilter(filter) {
99
+ if (filter.filterType === 'number') {
100
+ const agGridOperation = AG_GRID_OPERATION_NAMES[filter.type];
101
+ if (filter.type === 'inRange') {
102
+ const baseFilter = {
103
+ filterType: 'number',
104
+ type: agGridOperation,
105
+ filter: filter.filter
106
+ };
107
+ // Only include filterTo if it's defined
108
+ return filter.filterTo !== undefined
109
+ ? { ...baseFilter, filterTo: filter.filterTo }
110
+ : baseFilter;
111
+ }
112
+ return {
113
+ filterType: 'number',
114
+ type: agGridOperation,
115
+ filter: filter.filter
116
+ };
117
+ }
118
+ // Text filter handling
119
+ const agGridOperation = AG_GRID_OPERATION_NAMES[filter.type];
120
+ return {
121
+ filterType: 'text',
122
+ type: agGridOperation,
123
+ filter: filter.filter
124
+ };
125
+ }
37
126
  /**
38
127
  * Applies a filter state to AG Grid
39
128
  */
@@ -41,18 +130,19 @@ export function applyFilterModel(filterState, config) {
41
130
  try {
42
131
  const model = {};
43
132
  for (const [column, filter] of Object.entries(filterState)) {
44
- if (filter &&
45
- typeof filter === 'object' &&
46
- filter.filterType === 'text') {
47
- // Convert our internal operation to AG Grid operation using centralized mapping
48
- const agGridOperation = AG_GRID_OPERATION_NAMES[filter.type];
49
- if (agGridOperation) {
50
- model[column] = {
51
- filterType: filter.filterType,
52
- type: agGridOperation,
53
- filter: filter.filter
54
- };
55
- }
133
+ if (!filter || typeof filter !== 'object')
134
+ continue;
135
+ // Detect expected filter type for this column
136
+ const expectedType = detectColumnFilterType(config.gridApi, column);
137
+ // Validate filter type compatibility
138
+ if (filter.filterType === 'number' && expectedType !== 'number') {
139
+ console.warn(`Column '${column}' expects a text filter but received a number filter. This may indicate a configuration mismatch in the column definition or filter application.`);
140
+ continue;
141
+ }
142
+ // Convert to AG Grid filter model
143
+ const agGridFilter = convertToAGGridFilter(filter);
144
+ if (agGridFilter) {
145
+ model[column] = agGridFilter;
56
146
  }
57
147
  }
58
148
  config.gridApi.setFilterModel(model);
@@ -1 +1 @@
1
- {"version":3,"file":"grid-integration.js","sourceRoot":"","sources":["../../src/core/grid-integration.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAChC,MAAM,YAAY,CAAA;AAEnB;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,CAAA;QAC7C,MAAM,WAAW,GAAgB,EAAE,CAAA;QAEnC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxC,OAAO,WAAW,CAAA;QACpB,CAAC;QAED,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,SAAQ;YAEnD,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAa,CAAA;YACzD,IAAI,UAAU,KAAK,MAAM;gBAAE,SAAQ;YAEnC,mFAAmF;YACnF,MAAM,iBAAiB,GACrB,+BAA+B,CAC7B,IAAoD,CACrD,CAAA;YAEH,IAAI,iBAAiB,EAAE,CAAC;gBACtB,WAAW,CAAC,MAAM,CAAC,GAAG;oBACpB,UAAU,EAAE,MAAM;oBAClB,IAAI,EAAE,iBAAoC;oBAC1C,MAAM,EAAE,KAAK,IAAI,EAAE;iBACpB,CAAA;YACH,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAA;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,YAAY,CAAC,KAAc,CAAC,CAAA;QACrC,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAwB,EACxB,MAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,KAAK,GAAQ,EAAE,CAAA;QAErB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3D,IACE,MAAM;gBACN,OAAO,MAAM,KAAK,QAAQ;gBAC1B,MAAM,CAAC,UAAU,KAAK,MAAM,EAC5B,CAAC;gBACD,gFAAgF;gBAChF,MAAM,eAAe,GACnB,uBAAuB,CACrB,MAAM,CAAC,IAA4C,CACpD,CAAA;gBACH,IAAI,eAAe,EAAE,CAAC;oBACpB,KAAK,CAAC,MAAM,CAAC,GAAG;wBACd,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,IAAI,EAAE,eAAe;wBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;qBACtB,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,YAAY,CAAC,KAAc,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"grid-integration.js","sourceRoot":"","sources":["../../src/core/grid-integration.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { GridApi as AGGridApi } from 'ag-grid-community';
1
+ import type { GridApi as AGGridApi, TextFilterModel, NumberFilterModel } from 'ag-grid-community';
2
2
  /**
3
3
  * Configuration options for AG Grid URL Sync
4
4
  */
@@ -17,17 +17,52 @@ export interface AGGridUrlSyncConfig {
17
17
  onParseError?: (error: Error) => void;
18
18
  }
19
19
  /**
20
- * Supported filter operations
20
+ * Supported filter operations for both text and number filters
21
21
  */
22
- export type FilterOperation = 'contains' | 'eq' | 'notContains' | 'notEqual' | 'startsWith' | 'endsWith' | 'blank' | 'notBlank';
22
+ export type FilterOperation = 'contains' | 'eq' | 'notContains' | 'notEqual' | 'startsWith' | 'endsWith' | 'blank' | 'notBlank' | 'lessThan' | 'lessThanOrEqual' | 'greaterThan' | 'greaterThanOrEqual' | 'inRange';
23
23
  /**
24
- * Filter state for a single column
24
+ * Valid text filter operations as const array
25
25
  */
26
- export interface ColumnFilter {
27
- filterType: 'text';
26
+ export declare const TEXT_FILTER_OPERATIONS: readonly ["contains", "eq", "notContains", "notEqual", "startsWith", "endsWith", "blank", "notBlank"];
27
+ /**
28
+ * Valid number filter operations as const array
29
+ */
30
+ export declare const NUMBER_FILTER_OPERATIONS: readonly ["eq", "notEqual", "lessThan", "lessThanOrEqual", "greaterThan", "greaterThanOrEqual", "inRange", "blank", "notBlank"];
31
+ /**
32
+ * Text-specific filter operations
33
+ */
34
+ export type TextFilterOperation = (typeof TEXT_FILTER_OPERATIONS)[number];
35
+ /**
36
+ * Number-specific filter operations
37
+ */
38
+ export type NumberFilterOperation = (typeof NUMBER_FILTER_OPERATIONS)[number];
39
+ /**
40
+ * Base interface for column filters
41
+ */
42
+ interface BaseColumnFilter {
28
43
  type: FilterOperation;
44
+ }
45
+ /**
46
+ * Text filter configuration
47
+ */
48
+ export interface TextColumnFilter extends BaseColumnFilter {
49
+ filterType: 'text';
50
+ type: TextFilterOperation;
29
51
  filter: string;
30
52
  }
53
+ /**
54
+ * Number filter configuration
55
+ */
56
+ export interface NumberColumnFilter extends BaseColumnFilter {
57
+ filterType: 'number';
58
+ type: NumberFilterOperation;
59
+ filter: number;
60
+ filterTo?: number;
61
+ }
62
+ /**
63
+ * Filter state for a single column (union of text and number filters)
64
+ */
65
+ export type ColumnFilter = TextColumnFilter | NumberColumnFilter;
31
66
  /**
32
67
  * Complete filter state mapping
33
68
  */
@@ -55,58 +90,18 @@ export declare class InvalidURLError extends URLSyncError {
55
90
  export type ParsedFilterParam = {
56
91
  columnName: string;
57
92
  operation: FilterOperation;
58
- value: string;
93
+ filterType: 'text' | 'number' | 'auto';
94
+ value: string | number;
95
+ filterTo?: number;
59
96
  action: 'apply' | 'remove';
60
97
  };
61
98
  export type GridApi = AGGridApi;
62
99
  /**
63
- * Operation Mapping Strategy:
64
- *
65
- * We use three different naming conventions for better user experience:
66
- *
67
- * 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq')
68
- * 2. Internal Types: Consistent naming for our FilterOperation type
69
- * 3. AG Grid Operations: Exact names expected by AG Grid API (e.g., 'equals', 'notEqual')
70
- *
71
- * This approach keeps URLs readable while maintaining compatibility with AG Grid.
100
+ * Union type for AG Grid filters using official AG Grid types
72
101
  */
73
- export declare const OPERATION_MAP: {
74
- readonly contains: "contains";
75
- readonly eq: "eq";
76
- readonly notContains: "notContains";
77
- readonly neq: "notEqual";
78
- readonly startsWith: "startsWith";
79
- readonly endsWith: "endsWith";
80
- readonly blank: "blank";
81
- readonly notBlank: "notBlank";
82
- };
83
- export declare const INTERNAL_TO_URL_OPERATION_MAP: {
84
- readonly contains: "contains";
85
- readonly eq: "eq";
86
- readonly notContains: "notContains";
87
- readonly notEqual: "neq";
88
- readonly startsWith: "startsWith";
89
- readonly endsWith: "endsWith";
90
- readonly blank: "blank";
91
- readonly notBlank: "notBlank";
92
- };
93
- export declare const AG_GRID_OPERATION_NAMES: {
94
- readonly contains: "contains";
95
- readonly eq: "equals";
96
- readonly notContains: "notContains";
97
- readonly notEqual: "notEqual";
98
- readonly startsWith: "startsWith";
99
- readonly endsWith: "endsWith";
100
- readonly blank: "blank";
101
- readonly notBlank: "notBlank";
102
- };
103
- export declare const REVERSE_AG_GRID_OPERATION_NAMES: {
104
- readonly contains: "contains";
105
- readonly equals: "eq";
106
- readonly notContains: "notContains";
107
- readonly notEqual: "notEqual";
108
- readonly startsWith: "startsWith";
109
- readonly endsWith: "endsWith";
110
- readonly blank: "blank";
111
- readonly notBlank: "notBlank";
112
- };
102
+ export type AGGridFilter = TextFilterModel | NumberFilterModel;
103
+ export declare const OPERATION_MAP: Record<string, FilterOperation>;
104
+ export declare const INTERNAL_TO_URL_OPERATION_MAP: Record<FilterOperation, string>;
105
+ export declare const AG_GRID_OPERATION_NAMES: Record<FilterOperation, string>;
106
+ export declare const REVERSE_AG_GRID_OPERATION_NAMES: Record<string, FilterOperation>;
107
+ export {};
@@ -1,3 +1,30 @@
1
+ /**
2
+ * Valid text filter operations as const array
3
+ */
4
+ export const TEXT_FILTER_OPERATIONS = [
5
+ 'contains',
6
+ 'eq',
7
+ 'notContains',
8
+ 'notEqual',
9
+ 'startsWith',
10
+ 'endsWith',
11
+ 'blank',
12
+ 'notBlank'
13
+ ];
14
+ /**
15
+ * Valid number filter operations as const array
16
+ */
17
+ export const NUMBER_FILTER_OPERATIONS = [
18
+ 'eq',
19
+ 'notEqual',
20
+ 'lessThan',
21
+ 'lessThanOrEqual',
22
+ 'greaterThan',
23
+ 'greaterThanOrEqual',
24
+ 'inRange',
25
+ 'blank',
26
+ 'notBlank'
27
+ ];
1
28
  /**
2
29
  * Error types for URL sync operations
3
30
  */
@@ -24,56 +51,67 @@ export class InvalidURLError extends URLSyncError {
24
51
  *
25
52
  * We use three different naming conventions for better user experience:
26
53
  *
27
- * 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq')
54
+ * 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq', 'lt', 'gt')
28
55
  * 2. Internal Types: Consistent naming for our FilterOperation type
29
56
  * 3. AG Grid Operations: Exact names expected by AG Grid API (e.g., 'equals', 'notEqual')
30
57
  *
31
58
  * This approach keeps URLs readable while maintaining compatibility with AG Grid.
32
59
  */
33
- // URL parameter names to internal operation types
34
- // Uses short names for cleaner URLs: 'eq' instead of 'equals', 'neq' instead of 'notEqual'
35
- export const OPERATION_MAP = {
36
- contains: 'contains',
37
- eq: 'eq', // Short form for URL brevity
38
- notContains: 'notContains',
39
- neq: 'notEqual', // Short form: 'neq' -> 'notEqual'
40
- startsWith: 'startsWith',
41
- endsWith: 'endsWith',
42
- blank: 'blank',
43
- notBlank: 'notBlank'
44
- };
45
- // Internal operation types to URL parameter names
46
- export const INTERNAL_TO_URL_OPERATION_MAP = {
47
- contains: 'contains',
48
- eq: 'eq',
49
- notContains: 'notContains',
50
- notEqual: 'neq', // Internal 'notEqual' -> URL 'neq'
51
- startsWith: 'startsWith',
52
- endsWith: 'endsWith',
53
- blank: 'blank',
54
- notBlank: 'notBlank'
55
- };
56
- // Internal operation types to AG Grid operation names
57
- // AG Grid expects 'equals' not 'eq', 'notEqual' not 'neq'
58
- export const AG_GRID_OPERATION_NAMES = {
59
- contains: 'contains',
60
- eq: 'equals', // Internal 'eq' -> AG Grid 'equals'
61
- notContains: 'notContains',
62
- notEqual: 'notEqual',
63
- startsWith: 'startsWith',
64
- endsWith: 'endsWith',
65
- blank: 'blank',
66
- notBlank: 'notBlank'
60
+ /**
61
+ * Define special URL shorthand mappings (internal -> URL)
62
+ * Operations not listed here use their internal name as URL param
63
+ */
64
+ const URL_SHORTHAND_MAPPINGS = {
65
+ notEqual: 'neq',
66
+ lessThan: 'lt',
67
+ lessThanOrEqual: 'lte',
68
+ greaterThan: 'gt',
69
+ greaterThanOrEqual: 'gte',
70
+ inRange: 'range'
67
71
  };
68
- // AG Grid operation names to internal operation types (reverse mapping)
69
- export const REVERSE_AG_GRID_OPERATION_NAMES = {
70
- contains: 'contains',
71
- equals: 'eq', // AG Grid 'equals' -> Internal 'eq'
72
- notContains: 'notContains',
73
- notEqual: 'notEqual',
74
- startsWith: 'startsWith',
75
- endsWith: 'endsWith',
76
- blank: 'blank',
77
- notBlank: 'notBlank'
72
+ /**
73
+ * Define special AG Grid name mappings (internal -> AG Grid)
74
+ * Operations not listed here use their internal name for AG Grid
75
+ */
76
+ const AG_GRID_NAME_MAPPINGS = {
77
+ eq: 'equals'
78
78
  };
79
+ /**
80
+ * Helper function to create operation mappings dynamically
81
+ */
82
+ function createOperationMaps() {
83
+ const allOperations = [...TEXT_FILTER_OPERATIONS, ...NUMBER_FILTER_OPERATIONS];
84
+ // Remove duplicates (like 'eq', 'blank', etc. that appear in both arrays)
85
+ const uniqueOperations = [...new Set(allOperations)];
86
+ // Generate URL mappings
87
+ const operationMap = {};
88
+ const internalToUrlMap = {};
89
+ uniqueOperations.forEach(operation => {
90
+ const urlName = URL_SHORTHAND_MAPPINGS[operation] || operation;
91
+ operationMap[urlName] = operation;
92
+ internalToUrlMap[operation] = urlName;
93
+ });
94
+ // Generate AG Grid mappings
95
+ const agGridMap = {};
96
+ const reverseAgGridMap = {};
97
+ uniqueOperations.forEach(operation => {
98
+ const agGridName = AG_GRID_NAME_MAPPINGS[operation] ||
99
+ operation;
100
+ agGridMap[operation] = agGridName;
101
+ reverseAgGridMap[agGridName] = operation;
102
+ });
103
+ return {
104
+ operationMap,
105
+ internalToUrlMap,
106
+ agGridMap,
107
+ reverseAgGridMap
108
+ };
109
+ }
110
+ // Generate all mappings dynamically
111
+ const { operationMap, internalToUrlMap, agGridMap, reverseAgGridMap } = createOperationMaps();
112
+ // Export the dynamically generated maps
113
+ export const OPERATION_MAP = operationMap;
114
+ export const INTERNAL_TO_URL_OPERATION_MAP = internalToUrlMap;
115
+ export const AG_GRID_OPERATION_NAMES = agGridMap;
116
+ export const REVERSE_AG_GRID_OPERATION_NAMES = reverseAgGridMap;
79
117
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AA0DA;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAYD;;;;;;;;;;GAUG;AAEH,kDAAkD;AAClD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,UAAU;IACpB,EAAE,EAAE,IAAI,EAAE,6BAA6B;IACvC,WAAW,EAAE,aAAa;IAC1B,GAAG,EAAE,UAAU,EAAE,kCAAkC;IACnD,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACZ,CAAA;AAEV,kDAAkD;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,QAAQ,EAAE,UAAU;IACpB,EAAE,EAAE,IAAI;IACR,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,KAAK,EAAE,mCAAmC;IACpD,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACZ,CAAA;AAEV,sDAAsD;AACtD,0DAA0D;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE,UAAU;IACpB,EAAE,EAAE,QAAQ,EAAE,oCAAoC;IAClD,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACZ,CAAA;AAEV,wEAAwE;AACxE,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,IAAI,EAAE,oCAAoC;IAClD,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACZ,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AA4CA;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,UAAU;IACV,IAAI;IACJ,aAAa;IACb,UAAU;IACV,YAAY;IACZ,UAAU;IACV,OAAO;IACP,UAAU;CACF,CAAA;AAEV;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI;IACJ,UAAU;IACV,UAAU;IACV,iBAAiB;IACjB,aAAa;IACb,oBAAoB;IACpB,SAAS;IACT,OAAO;IACP,UAAU;CACF,CAAA;AAyDV;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAmBD;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,MAAM,sBAAsB,GAAG;IAC7B,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,IAAI;IACd,eAAe,EAAE,KAAK;IACtB,WAAW,EAAE,IAAI;IACjB,kBAAkB,EAAE,KAAK;IACzB,OAAO,EAAE,OAAO;CACR,CAAA;AAEV;;;GAGG;AACH,MAAM,qBAAqB,GAAG;IAC5B,EAAE,EAAE,QAAQ;CACJ,CAAA;AAEV;;GAEG;AACH,SAAS,mBAAmB;IAC1B,MAAM,aAAa,GAAG,CAAC,GAAG,sBAAsB,EAAE,GAAG,wBAAwB,CAAC,CAAA;IAE9E,0EAA0E;IAC1E,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAA;IAEpD,wBAAwB;IACxB,MAAM,YAAY,GAAG,EAAqC,CAAA;IAC1D,MAAM,gBAAgB,GAAG,EAAqC,CAAA;IAE9D,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QACnC,MAAM,OAAO,GACX,sBAAsB,CACpB,SAAgD,CACjD,IAAI,SAAS,CAAA;QAChB,YAAY,CAAC,OAAO,CAAC,GAAG,SAAS,CAAA;QACjC,gBAAgB,CAAC,SAAS,CAAC,GAAG,OAAO,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,4BAA4B;IAC5B,MAAM,SAAS,GAAG,EAAqC,CAAA;IACvD,MAAM,gBAAgB,GAAG,EAAqC,CAAA;IAE9D,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QACnC,MAAM,UAAU,GACd,qBAAqB,CAAC,SAA+C,CAAC;YACtE,SAAS,CAAA;QACX,SAAS,CAAC,SAAS,CAAC,GAAG,UAAU,CAAA;QACjC,gBAAgB,CAAC,UAAU,CAAC,GAAG,SAAS,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,YAAY;QACZ,gBAAgB;QAChB,SAAS;QACT,gBAAgB;KACjB,CAAA;AACH,CAAC;AAED,oCAAoC;AACpC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,GACnE,mBAAmB,EAAE,CAAA;AAEvB,wCAAwC;AACxC,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAA;AACzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,gBAAgB,CAAA;AAC7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,SAAS,CAAA;AAChD,MAAM,CAAC,MAAM,+BAA+B,GAAG,gBAAgB,CAAA"}
@@ -1,25 +1,71 @@
1
1
  import { validateFilterValue } from './validation.js';
2
2
  import { INTERNAL_TO_URL_OPERATION_MAP } from './types.js';
3
+ /**
4
+ * Serializes a single column filter to URL parameter
5
+ */
6
+ function serializeColumnFilter(columnName, filter, paramPrefix) {
7
+ const urlOperation = INTERNAL_TO_URL_OPERATION_MAP[filter.type];
8
+ if (!urlOperation)
9
+ return '';
10
+ const paramName = `${paramPrefix}${columnName}_${urlOperation}`;
11
+ // Handle range operations
12
+ if (filter.type === 'inRange' && filter.filterType === 'number') {
13
+ // Type guard: ensure this is a NumberColumnFilter with inRange operation
14
+ if ('filterTo' in filter && filter.filterTo !== undefined) {
15
+ // Don't encode the comma for range values - handle this directly
16
+ return `${paramName}=${filter.filter},${filter.filterTo}`;
17
+ }
18
+ return '';
19
+ }
20
+ // Handle blank operations
21
+ if (filter.type === 'blank' || filter.type === 'notBlank') {
22
+ return `${paramName}=true`;
23
+ }
24
+ // Handle number operations
25
+ if (filter.filterType === 'number') {
26
+ return `${paramName}=${filter.filter}`;
27
+ }
28
+ // Handle text operations (existing logic)
29
+ if (filter.filterType === 'text' && filter.filter) {
30
+ // Note: Validation should be done at the serializeFilters level, not here
31
+ return `${paramName}=${encodeURIComponent(filter.filter.toString())}`;
32
+ }
33
+ return '';
34
+ }
35
+ /**
36
+ * Helper function to append a serialized parameter to URLSearchParams
37
+ */
38
+ function appendSerializedParam(serialized, params) {
39
+ const [paramName, paramValue] = serialized.split('=');
40
+ if (paramName && paramValue) {
41
+ // Decode the parameter value to handle commas correctly
42
+ params.append(paramName, decodeURIComponent(paramValue));
43
+ }
44
+ }
3
45
  /**
4
46
  * Converts a filter state object into URL search parameters
5
47
  */
6
48
  export function serializeFilters(filterState, config) {
7
49
  const params = new URLSearchParams();
8
50
  for (const [column, filter] of Object.entries(filterState)) {
9
- if (filter.filterType !== 'text')
10
- continue;
11
- const operation = INTERNAL_TO_URL_OPERATION_MAP[filter.type];
12
- if (!operation)
51
+ // Support both text and number filters
52
+ if (filter.filterType !== 'text' && filter.filterType !== 'number')
13
53
  continue;
14
- const paramName = `${config.paramPrefix}${column}_${operation}`;
15
- // Special handling for blank operations
16
- if (filter.type === 'blank' || filter.type === 'notBlank') {
17
- params.append(paramName, 'true');
54
+ // Apply validation for text filters before serialization
55
+ if (filter.filterType === 'text') {
56
+ const validatedValue = validateFilterValue(filter.filter, config, filter.type);
57
+ const updatedFilter = { ...filter, filter: validatedValue };
58
+ const serialized = serializeColumnFilter(column, updatedFilter, config.paramPrefix);
59
+ if (serialized) {
60
+ appendSerializedParam(serialized, params);
61
+ }
18
62
  }
19
63
  else {
20
- const value = validateFilterValue(filter.filter, config, filter.type);
21
- // URLSearchParams already handles encoding, so don't double-encode
22
- params.append(paramName, value);
64
+ // Number filters don't need additional validation as they're already validated
65
+ const serialized = serializeColumnFilter(column, filter, config.paramPrefix);
66
+ if (serialized) {
67
+ appendSerializedParam(serialized, params);
68
+ }
23
69
  }
24
70
  }
25
71
  return params;
@@ -1 +1 @@
1
- {"version":3,"file":"url-generator.js","sourceRoot":"","sources":["../../src/core/url-generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAA;AAE1D;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAwB,EACxB,MAAsB;IAEtB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IAEpC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3D,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM;YAAE,SAAQ;QAE1C,MAAM,SAAS,GACb,6BAA6B,CAC3B,MAAM,CAAC,IAAkD,CAC1D,CAAA;QACH,IAAI,CAAC,SAAS;YAAE,SAAQ;QAExB,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,WAAW,GAAG,MAAM,IAAI,SAAS,EAAE,CAAA;QAE/D,wCAAwC;QACxC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAClC,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;YACrE,mEAAmE;YACnE,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,OAAe,EACf,WAAwB,EACxB,MAAsB;IAEtB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IAC5B,MAAM,YAAY,GAAG,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IAE1D,0CAA0C;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAED,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAA;IACpC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC"}
1
+ {"version":3,"file":"url-generator.js","sourceRoot":"","sources":["../../src/core/url-generator.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,23 @@
1
1
  import { InvalidFilterError, InvalidURLError, OPERATION_MAP } from './types.js';
2
- import { validateFilterValue, DEFAULT_CONFIG } from './validation.js';
2
+ import { validateFilterValue, validateAndParseNumber, validateNumberRange, validateNumberFilter, DEFAULT_CONFIG } from './validation.js';
3
+ /**
4
+ * Detects if an operation is number-specific
5
+ */
6
+ function isNumberOperation(operation) {
7
+ return [
8
+ 'lessThan',
9
+ 'lessThanOrEqual',
10
+ 'greaterThan',
11
+ 'greaterThanOrEqual',
12
+ 'inRange'
13
+ ].includes(operation);
14
+ }
15
+ /**
16
+ * Detects if an operation works with both text and number filters
17
+ */
18
+ function isSharedOperation(operation) {
19
+ return ['eq', 'notEqual', 'blank', 'notBlank'].includes(operation);
20
+ }
3
21
  /**
4
22
  * Extracts column name and operation from a filter parameter
5
23
  */
@@ -34,7 +52,35 @@ export function parseFilterParam(param, value, expectedPrefix) {
34
52
  if (!filterOp) {
35
53
  throw new InvalidFilterError(`Unsupported filter operation: ${operation}`);
36
54
  }
37
- // Special handling for blank operations - they don't use the value
55
+ // Handle range operations
56
+ if (filterOp === 'inRange') {
57
+ const rangeParts = value.split(',');
58
+ if (rangeParts.length !== 2) {
59
+ throw new InvalidFilterError('Range operation requires exactly two values separated by comma');
60
+ }
61
+ const min = validateAndParseNumber(rangeParts[0] || '');
62
+ const max = validateAndParseNumber(rangeParts[1] || '');
63
+ const rangeValidation = validateNumberRange(min, max);
64
+ if (!rangeValidation.valid) {
65
+ throw new InvalidFilterError(rangeValidation.error || 'Invalid range values');
66
+ }
67
+ return {
68
+ filterType: 'number',
69
+ type: filterOp,
70
+ filter: min,
71
+ filterTo: max
72
+ };
73
+ }
74
+ // Handle number operations
75
+ if (isNumberOperation(filterOp)) {
76
+ const numValue = validateAndParseNumber(value);
77
+ return {
78
+ filterType: 'number',
79
+ type: filterOp,
80
+ filter: numValue
81
+ };
82
+ }
83
+ // Handle blank operations first (work for both text and number but default to text)
38
84
  if (filterOp === 'blank' || filterOp === 'notBlank') {
39
85
  return {
40
86
  filterType: 'text',
@@ -42,6 +88,32 @@ export function parseFilterParam(param, value, expectedPrefix) {
42
88
  filter: '' // Blank operations don't use the value
43
89
  };
44
90
  }
91
+ // Handle shared operations (eq, notEqual) - detect if they should be number based on value
92
+ if (isSharedOperation(filterOp)) {
93
+ // Try to parse as number first
94
+ try {
95
+ const numValue = parseFloat(value);
96
+ if (!isNaN(numValue) && Number.isFinite(numValue)) {
97
+ const validation = validateNumberFilter(numValue);
98
+ if (validation.valid) {
99
+ return {
100
+ filterType: 'number',
101
+ type: filterOp,
102
+ filter: numValue
103
+ };
104
+ }
105
+ }
106
+ }
107
+ catch {
108
+ // Fall through to text handling
109
+ }
110
+ return {
111
+ filterType: 'text',
112
+ type: filterOp,
113
+ filter: value || ''
114
+ };
115
+ }
116
+ // Handle text operations (existing logic)
45
117
  return {
46
118
  filterType: 'text',
47
119
  type: filterOp,
@@ -62,11 +134,18 @@ export function parseUrlFilters(url, config) {
62
134
  // Extract column name and parse the filter parameter
63
135
  const { column: columnName } = extractColumnAndOperation(param, config.paramPrefix);
64
136
  const filterParam = parseFilterParam(param, value, config.paramPrefix);
65
- const validatedValue = validateFilterValue(value, config, filterParam.type);
66
- filterState[columnName] = {
67
- ...filterParam,
68
- filter: validatedValue
69
- };
137
+ // Apply validation based on filter type
138
+ if (filterParam.filterType === 'text') {
139
+ const validatedValue = validateFilterValue(value, config, filterParam.type);
140
+ filterState[columnName] = {
141
+ ...filterParam,
142
+ filter: validatedValue
143
+ };
144
+ }
145
+ else {
146
+ // Number filters are already validated in parseFilterParam
147
+ filterState[columnName] = filterParam;
148
+ }
70
149
  }
71
150
  catch (err) {
72
151
  if (config.onParseError) {
@@ -1 +1 @@
1
- {"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../../src/core/url-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../../src/core/url-parser.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,14 @@ export declare const DEFAULT_CONFIG: {
7
7
  readonly maxValueLength: 200;
8
8
  };
9
9
  /**
10
- * Validates a filter value against configuration constraints
10
+ * Validation result interface
11
+ */
12
+ export interface ValidationResult {
13
+ valid: boolean;
14
+ error?: string;
15
+ }
16
+ /**
17
+ * Validates a text filter value against configuration constraints
11
18
  *
12
19
  * @param value - The filter value to validate
13
20
  * @param config - Internal configuration with validation rules
@@ -16,3 +23,25 @@ export declare const DEFAULT_CONFIG: {
16
23
  * @throws InvalidFilterError if value exceeds maximum length
17
24
  */
18
25
  export declare function validateFilterValue(value: string, config: InternalConfig, operation?: FilterOperation): string;
26
+ /**
27
+ * Validates a number filter value
28
+ *
29
+ * @param value - The number value to validate
30
+ * @returns Validation result
31
+ */
32
+ export declare function validateNumberFilter(value: number): ValidationResult;
33
+ /**
34
+ * Validates a number range filter
35
+ *
36
+ * @param min - The minimum value
37
+ * @param max - The maximum value
38
+ * @returns Validation result
39
+ */
40
+ export declare function validateNumberRange(min: number, max: number): ValidationResult;
41
+ /**
42
+ * Validates a parsed number from string input
43
+ *
44
+ * @param value - String representation of number
45
+ * @returns Parsed number or throws InvalidFilterError
46
+ */
47
+ export declare function validateAndParseNumber(value: string): number;
@@ -7,7 +7,7 @@ export const DEFAULT_CONFIG = {
7
7
  maxValueLength: 200
8
8
  };
9
9
  /**
10
- * Validates a filter value against configuration constraints
10
+ * Validates a text filter value against configuration constraints
11
11
  *
12
12
  * @param value - The filter value to validate
13
13
  * @param config - Internal configuration with validation rules
@@ -25,4 +25,63 @@ export function validateFilterValue(value, config, operation) {
25
25
  }
26
26
  return value;
27
27
  }
28
+ /**
29
+ * Validates a number filter value
30
+ *
31
+ * @param value - The number value to validate
32
+ * @returns Validation result
33
+ */
34
+ export function validateNumberFilter(value) {
35
+ // Basic number validation
36
+ if (!Number.isFinite(value)) {
37
+ return { valid: false, error: 'Filter value must be a finite number' };
38
+ }
39
+ // Range validation for precision
40
+ if (Math.abs(value) > Number.MAX_SAFE_INTEGER) {
41
+ return { valid: false, error: 'Number value exceeds safe integer range' };
42
+ }
43
+ return { valid: true };
44
+ }
45
+ /**
46
+ * Validates a number range filter
47
+ *
48
+ * @param min - The minimum value
49
+ * @param max - The maximum value
50
+ * @returns Validation result
51
+ */
52
+ export function validateNumberRange(min, max) {
53
+ const minResult = validateNumberFilter(min);
54
+ if (!minResult.valid)
55
+ return minResult;
56
+ const maxResult = validateNumberFilter(max);
57
+ if (!maxResult.valid)
58
+ return maxResult;
59
+ if (min > max) {
60
+ return {
61
+ valid: false,
62
+ error: 'Range minimum must be less than or equal to maximum'
63
+ };
64
+ }
65
+ return { valid: true };
66
+ }
67
+ /**
68
+ * Validates a parsed number from string input
69
+ *
70
+ * @param value - String representation of number
71
+ * @returns Parsed number or throws InvalidFilterError
72
+ */
73
+ export function validateAndParseNumber(value) {
74
+ if (!value || value.trim() === '') {
75
+ throw new InvalidFilterError('Number filter value cannot be empty');
76
+ }
77
+ const numValue = parseFloat(value);
78
+ if (isNaN(numValue)) {
79
+ throw new InvalidFilterError(`Invalid number format: ${value}`);
80
+ }
81
+ const validation = validateNumberFilter(numValue);
82
+ if (!validation.valid) {
83
+ throw new InvalidFilterError(validation.error || 'Invalid number value');
84
+ }
85
+ return numValue;
86
+ }
28
87
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,GAAG;CACX,CAAA;AAEV;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,MAAsB,EACtB,SAA2B;IAE3B,kDAAkD;IAClD,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QACtD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,IAAI,kBAAkB,CAC1B,0CAA0C,MAAM,CAAC,cAAc,aAAa,CAC7E,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,GAAG;CACX,CAAA;AAUV;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,MAAsB,EACtB,SAA2B;IAE3B,kDAAkD;IAClD,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QACtD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,IAAI,kBAAkB,CAC1B,0CAA0C,MAAM,CAAC,cAAc,aAAa,CAC7E,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,0BAA0B;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAA;IACxE,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAA;IAC3E,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAW,EACX,GAAW;IAEX,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAA;IAC3C,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAEtC,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAA;IAC3C,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAEtC,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACd,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,qDAAqD;SAC7D,CAAA;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,kBAAkB,CAAC,qCAAqC,CAAC,CAAA;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,kBAAkB,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IACjD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,kBAAkB,CAAC,UAAU,CAAC,KAAK,IAAI,sBAAsB,CAAC,CAAA;IAC1E,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ag-grid-url-sync",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "AG Grid URL Sync - Synchronize AG Grid text filters with URL parameters",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -98,7 +98,7 @@
98
98
  "react"
99
99
  ],
100
100
  "author": "NearForm",
101
- "license": "ISC",
101
+ "license": "MIT",
102
102
  "bugs": {
103
103
  "url": "https://github.com/nearform/ag-grid-url-state-sync/issues"
104
104
  },
@@ -111,11 +111,11 @@
111
111
  "@commitlint/cli": "^19.8.1",
112
112
  "@commitlint/config-conventional": "^19.8.1",
113
113
  "@eslint/js": "^9.29.0",
114
- "@testing-library/react": "^14.0.0",
114
+ "@testing-library/react": "^16.3.0",
115
115
  "@types/jsdom": "^21.1.7",
116
116
  "@types/react": "^18.0.0",
117
117
  "@vitest/coverage-v8": "^3.2.4",
118
- "ag-grid-community": "^33.3.2",
118
+ "ag-grid-community": "^34.0.0",
119
119
  "bundlesize": "^0.18.2",
120
120
  "eslint": "^9.29.0",
121
121
  "eslint-config-prettier": "^10.1.5",