ag-grid-url-sync 0.1.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.
Files changed (43) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +435 -52
  3. package/dist/{ag-grid-url-sync.js → core/ag-grid-url-sync.js} +4 -2
  4. package/dist/core/ag-grid-url-sync.js.map +1 -0
  5. package/dist/core/grid-integration.d.ts +14 -0
  6. package/dist/core/grid-integration.js +156 -0
  7. package/dist/core/grid-integration.js.map +1 -0
  8. package/dist/core/index.d.ts +6 -0
  9. package/dist/core/index.js +11 -0
  10. package/dist/core/index.js.map +1 -0
  11. package/dist/core/types.d.ts +107 -0
  12. package/dist/core/types.js +117 -0
  13. package/dist/core/types.js.map +1 -0
  14. package/dist/core/url-generator.d.ts +9 -0
  15. package/dist/core/url-generator.js +88 -0
  16. package/dist/core/url-generator.js.map +1 -0
  17. package/dist/core/url-parser.d.ts +9 -0
  18. package/dist/core/url-parser.js +164 -0
  19. package/dist/core/url-parser.js.map +1 -0
  20. package/dist/core/validation.d.ts +47 -0
  21. package/dist/core/validation.js +87 -0
  22. package/dist/core/validation.js.map +1 -0
  23. package/dist/index.d.ts +6 -3
  24. package/dist/index.js +11 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/react/index.d.ts +3 -0
  27. package/dist/react/index.js +2 -0
  28. package/dist/react/index.js.map +1 -0
  29. package/dist/react/types.d.ts +64 -0
  30. package/dist/react/types.js +2 -0
  31. package/dist/react/types.js.map +1 -0
  32. package/dist/react/use-ag-grid-url-sync.d.ts +10 -0
  33. package/dist/react/use-ag-grid-url-sync.js +215 -0
  34. package/dist/react/use-ag-grid-url-sync.js.map +1 -0
  35. package/package.json +97 -8
  36. package/dist/ag-grid-url-sync.js.map +0 -1
  37. package/dist/types.d.ts +0 -69
  38. package/dist/types.js +0 -31
  39. package/dist/types.js.map +0 -1
  40. package/dist/utils.d.ts +0 -36
  41. package/dist/utils.js +0 -188
  42. package/dist/utils.js.map +0 -1
  43. /package/dist/{ag-grid-url-sync.d.ts → core/ag-grid-url-sync.d.ts} +0 -0
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,14 +2,16 @@
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
- - 🔍 Text filter synchronization (`contains` and `equals` operations)
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
14
+ - ⚛️ **React hook** - dedicated `useAGGridUrlSync` with state management
13
15
  - 📝 Full TypeScript support with strict mode compliance
14
16
  - 🚦 Graceful error handling with configurable error callbacks
15
17
  - 🧹 Clean, human-readable URL format
@@ -18,6 +20,95 @@ A lightweight TypeScript library for synchronizing AG Grid text filters with URL
18
20
  - 🛡️ Robust edge case handling (special characters, malformed URLs)
19
21
  - 📦 Lightweight bundle size (~3KB gzipped)
20
22
 
23
+ ## Supported Filter Types
24
+
25
+ Supports **all AG Grid text and number filter operations** (17 total) with clean, human-readable URL parameters:
26
+
27
+ ### Text Filters (8 operations)
28
+
29
+ | Filter Type | Operation | URL Format | Example | Description |
30
+ | ----------- | ------------ | ---------------------------- | -------------------------- | --------------------------- |
31
+ | **Text** | Contains | `f_column_contains=value` | `f_name_contains=john` | Text contains value |
32
+ | **Text** | Equals | `f_column_eq=value` | `f_status_eq=active` | Text equals value exactly |
33
+ | **Text** | Not Contains | `f_column_notContains=value` | `f_name_notContains=spam` | Text does not contain value |
34
+ | **Text** | Not Equal | `f_column_neq=value` | `f_status_neq=inactive` | Text does not equal value |
35
+ | **Text** | Starts With | `f_column_startsWith=value` | `f_email_startsWith=admin` | Text starts with value |
36
+ | **Text** | Ends With | `f_column_endsWith=value` | `f_file_endsWith=.pdf` | Text ends with value |
37
+ | **Text** | Blank | `f_column_blank=true` | `f_optional_blank=true` | Field is empty/null |
38
+ | **Text** | Not Blank | `f_column_notBlank=true` | `f_required_notBlank=true` | Field has any value |
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
+
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.
55
+
56
+ ### Filter Detection
57
+
58
+ The library automatically works with:
59
+
60
+ - **Text columns** configured with `filter: 'agTextColumnFilter'`
61
+ - **Number columns** configured with `filter: 'agNumberColumnFilter'`
62
+ - **Auto-detection** based on `cellDataType: 'number'` configuration
63
+ - Columns with `filter: true` (AG Grid's default text filter)
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
67
+
68
+ ### URL Examples
69
+
70
+ **Simple text filter:**
71
+
72
+ ```
73
+ https://app.com/data?f_name_contains=john
74
+ ```
75
+
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:**
89
+
90
+ ```
91
+ https://app.com/data?f_name_contains=manager&f_salary_range=60000,100000&f_experience_gte=5&f_status_eq=active
92
+ ```
93
+
94
+ **All text operations:**
95
+
96
+ ```
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
98
+ ```
99
+
100
+ **All number operations:**
101
+
102
+ ```
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
110
+ ```
111
+
21
112
  ## Installation
22
113
 
23
114
  ```bash
@@ -26,6 +117,96 @@ npm install ag-grid-url-sync
26
117
 
27
118
  ## Usage
28
119
 
120
+ ### Importing the Library
121
+
122
+ The library provides two main entry points:
123
+
124
+ ```typescript
125
+ // Core functionality - works with any framework
126
+ import { createUrlSync } from 'ag-grid-url-sync'
127
+
128
+ // React hook - for React applications
129
+ import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
130
+
131
+ // TypeScript types (available from both imports)
132
+ import type { FilterState, AGGridUrlSyncConfig } from 'ag-grid-url-sync'
133
+ ```
134
+
135
+ ### Tree-Shaking & Granular Imports
136
+
137
+ For optimal bundle sizes, you can import only the specific utilities you need:
138
+
139
+ ```typescript
140
+ import {
141
+ validateFilterValue,
142
+ DEFAULT_CONFIG
143
+ } from 'ag-grid-url-sync/validation'
144
+
145
+ import { parseUrlFilters, parseFilterParam } from 'ag-grid-url-sync/url-parser'
146
+
147
+ import { serializeFilters, generateUrl } from 'ag-grid-url-sync/url-generator'
148
+
149
+ import {
150
+ getFilterModel,
151
+ applyFilterModel
152
+ } from 'ag-grid-url-sync/grid-integration'
153
+
154
+ import type {
155
+ FilterState,
156
+ ColumnFilter,
157
+ FilterOperation
158
+ } from 'ag-grid-url-sync/types'
159
+ ```
160
+
161
+ #### Bundle Size Comparison
162
+
163
+ | Import Pattern | Bundle Size | Use Case |
164
+ | ---------------- | ----------- | ---------------------- |
165
+ | Full library | 5KB | Complete functionality |
166
+ | Core class only | 3.2KB | Basic URL sync |
167
+ | React hook only | 7KB | React applications |
168
+ | URL parsing only | 1.05KB | Parse existing URLs |
169
+ | Validation only | 318B | Input validation |
170
+ | Types only | 0B | TypeScript types |
171
+
172
+ #### Example: Custom URL Parser
173
+
174
+ ```typescript
175
+ import { parseUrlFilters } from 'ag-grid-url-sync/url-parser'
176
+ import { DEFAULT_CONFIG } from 'ag-grid-url-sync/validation'
177
+ import type { FilterState } from 'ag-grid-url-sync/types'
178
+
179
+ function getFiltersFromUrl(url: string): FilterState {
180
+ const config = {
181
+ gridApi: null, // Not needed for parsing
182
+ ...DEFAULT_CONFIG,
183
+ onParseError: error => console.error('Parse error:', error)
184
+ }
185
+
186
+ return parseUrlFilters(url, config)
187
+ }
188
+ ```
189
+
190
+ #### Example: Custom URL Generator
191
+
192
+ ```typescript
193
+ import { generateUrl, serializeFilters } from 'ag-grid-url-sync/url-generator'
194
+ import type { FilterState } from 'ag-grid-url-sync/types'
195
+
196
+ function createShareableUrl(filters: FilterState, baseUrl: string): string {
197
+ const config = {
198
+ gridApi: null, // Not needed for generation
199
+ paramPrefix: 'f_',
200
+ maxValueLength: 200,
201
+ onParseError: () => {}
202
+ }
203
+
204
+ return generateUrl(baseUrl, filters, config)
205
+ }
206
+ ```
207
+
208
+ **💡 Pro Tip**: Use granular imports in libraries and applications where bundle size matters. All existing import patterns remain fully supported for backward compatibility.
209
+
29
210
  ### Basic Example
30
211
 
31
212
  ```typescript
@@ -34,50 +215,240 @@ import { createUrlSync } from 'ag-grid-url-sync'
34
215
  // Initialize with AG Grid API
35
216
  const urlSync = createUrlSync(gridApi)
36
217
 
37
- // Generate shareable URL with current filters
218
+ // Generate shareable URL with current filters (text and number)
38
219
  const shareableUrl = urlSync.generateUrl()
220
+ // Result: https://app.com/data?f_name_contains=john&f_salary_gte=80000&f_age_range=25,45
39
221
 
40
- // Apply filters from URL
41
- 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
+ )
226
+
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
+ })
42
233
 
43
- // Clear all text filters
234
+ // Clear all text and number filters
44
235
  urlSync.clearFilters()
45
236
  ```
46
237
 
47
- ### React Integration
238
+ ## React Integration
239
+
240
+ For React applications, use the dedicated `useAGGridUrlSync` hook that provides a complete solution with React-specific features and state management.
241
+
242
+ ### Installation for React
243
+
244
+ ```bash
245
+ npm install ag-grid-url-sync
246
+ ```
247
+
248
+ ### Basic React Usage
48
249
 
49
250
  ```tsx
50
- import { createUrlSync } from 'ag-grid-url-sync'
51
- import { useCallback, useMemo } from 'react'
251
+ import React, { useState } from 'react'
252
+ import { AgGridReact } from 'ag-grid-react'
253
+ import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
254
+
255
+ function GridComponent() {
256
+ const [gridApi, setGridApi] = useState(null)
257
+
258
+ const {
259
+ shareUrl,
260
+ applyUrlFilters,
261
+ clearFilters,
262
+ hasFilters,
263
+ isReady,
264
+ currentUrl
265
+ } = useAGGridUrlSync(gridApi, {
266
+ autoApplyOnMount: true,
267
+ paramPrefix: 'filter_'
268
+ })
269
+
270
+ const handleShare = async () => {
271
+ const url = shareUrl()
272
+ await navigator.clipboard.writeText(url)
273
+ alert('Filter URL copied!')
274
+ }
52
275
 
53
- function useGridUrlSync(gridApi) {
54
- const urlSync = useMemo(
55
- () => (gridApi ? createUrlSync(gridApi) : null),
56
- [gridApi]
276
+ return (
277
+ <div>
278
+ <div style={{ marginBottom: '10px' }}>
279
+ <button onClick={handleShare} disabled={!isReady}>
280
+ 📋 Share Filters
281
+ </button>
282
+ <button onClick={clearFilters} disabled={!hasFilters}>
283
+ 🗑️ Clear Filters
284
+ </button>
285
+ <button onClick={applyUrlFilters}>🔄 Apply URL Filters</button>
286
+ </div>
287
+
288
+ <div className="ag-theme-alpine" style={{ height: 400, width: '100%' }}>
289
+ <AgGridReact
290
+ onGridReady={params => setGridApi(params.api)}
291
+ rowData={rowData}
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
+ ]}
314
+ defaultColDef={{
315
+ flex: 1,
316
+ sortable: true,
317
+ resizable: true
318
+ }}
319
+ />
320
+ </div>
321
+ </div>
57
322
  )
323
+ }
324
+ ```
58
325
 
59
- const shareUrl = useCallback(() => urlSync?.generateUrl() || '', [urlSync])
326
+ ### React Hook API
60
327
 
61
- const applyUrlFilters = useCallback(() => urlSync?.applyFromUrl(), [urlSync])
328
+ #### `useAGGridUrlSync(gridApi, options?)`
62
329
 
63
- return { shareUrl, applyUrlFilters }
330
+ ```tsx
331
+ import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
332
+
333
+ const {
334
+ shareUrl,
335
+ getQueryParams,
336
+ applyUrlFilters,
337
+ clearFilters,
338
+ isReady,
339
+ currentUrl,
340
+ hasFilters,
341
+ parseUrlFilters,
342
+ applyFilters
343
+ } = useAGGridUrlSync(gridApi, options)
344
+ ```
345
+
346
+ #### Hook Options
347
+
348
+ ```tsx
349
+ interface UseAGGridUrlSyncOptions {
350
+ // Core options (same as createUrlSync)
351
+ paramPrefix?: string // Default: 'f_'
352
+ maxValueLength?: number // Default: 200
353
+ onParseError?: (error: Error) => void
354
+
355
+ // React-specific options
356
+ autoApplyOnMount?: boolean // Default: false
357
+ enabledWhenReady?: boolean // Default: true
64
358
  }
359
+ ```
65
360
 
66
- // In your component
67
- function GridComponent() {
68
- const { shareUrl, applyUrlFilters } = useGridUrlSync(gridApi)
361
+ #### Hook Return Values
362
+
363
+ | Property | Type | Description |
364
+ | ----------------- | -------------------------------- | ----------------------------------------------- |
365
+ | `shareUrl` | `(baseUrl?: string) => string` | Generate shareable URL with current filters |
366
+ | `getQueryParams` | `() => string` | Get filter state as query parameters |
367
+ | `applyUrlFilters` | `(url?: string) => void` | Apply filters from URL to grid |
368
+ | `clearFilters` | `() => void` | Clear all text filters |
369
+ | `isReady` | `boolean` | Whether grid API is available and hook is ready |
370
+ | `currentUrl` | `string` | Current URL with filters applied |
371
+ | `hasFilters` | `boolean` | Whether grid has any active text filters |
372
+ | `parseUrlFilters` | `(url: string) => FilterState` | Parse filters from URL without applying |
373
+ | `applyFilters` | `(filters: FilterState) => void` | Apply filter state object to grid |
374
+
375
+ ### React Features
376
+
377
+ - **🔄 Automatic State Management**: Tracks grid state and filter changes automatically
378
+ - **⚡ Ready State**: `isReady` indicates when the grid API is available
379
+ - **🎯 Auto-Apply**: `autoApplyOnMount` applies URL filters when component mounts
380
+ - **🧹 Cleanup**: Automatically cleans up resources when component unmounts
381
+ - **🛡️ Error Boundaries**: Graceful error handling with configurable callbacks
382
+ - **📊 Filter Status**: `hasFilters` tracks whether any filters are active
383
+
384
+ ### Advanced React Example
385
+
386
+ ```tsx
387
+ import React, { useState, useEffect } from 'react'
388
+ import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
389
+
390
+ function AdvancedGridComponent() {
391
+ const [gridApi, setGridApi] = useState(null)
392
+ const [shareMessage, setShareMessage] = useState('')
393
+
394
+ const {
395
+ shareUrl,
396
+ applyUrlFilters,
397
+ clearFilters,
398
+ hasFilters,
399
+ isReady,
400
+ currentUrl,
401
+ parseUrlFilters
402
+ } = useAGGridUrlSync(gridApi, {
403
+ autoApplyOnMount: true,
404
+ paramPrefix: 'emp_',
405
+ maxValueLength: 100,
406
+ onParseError: error => {
407
+ console.warn('Filter parsing error:', error.message)
408
+ setShareMessage('Invalid filter URL detected')
409
+ }
410
+ })
411
+
412
+ // Watch for URL changes
413
+ useEffect(() => {
414
+ if (currentUrl !== window.location.href) {
415
+ setShareMessage('Filters have changed - URL ready to share')
416
+ }
417
+ }, [currentUrl])
418
+
419
+ const handleShareToEmail = () => {
420
+ const url = shareUrl()
421
+ const subject = 'Check out this filtered data'
422
+ const body = `View the filtered data here: ${url}`
423
+ window.open(
424
+ `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
425
+ )
426
+ }
427
+
428
+ const handlePreviewFilters = () => {
429
+ const url = prompt('Enter URL to preview filters:')
430
+ if (url) {
431
+ const filters = parseUrlFilters(url)
432
+ console.log('Parsed filters:', filters)
433
+ alert(`Found ${Object.keys(filters).length} filter(s)`)
434
+ }
435
+ }
69
436
 
70
437
  return (
71
438
  <div>
72
- <button
73
- onClick={() => {
74
- const url = shareUrl()
75
- navigator.clipboard.writeText(url)
76
- }}
77
- >
78
- Share Filters
79
- </button>
80
- <button onClick={applyUrlFilters}>Apply URL Filters</button>
439
+ <div className="controls">
440
+ <button onClick={handleShareToEmail} disabled={!isReady}>
441
+ 📧 Share via Email
442
+ </button>
443
+ <button onClick={handlePreviewFilters}>👁️ Preview URL Filters</button>
444
+ <button onClick={clearFilters} disabled={!hasFilters}>
445
+ Clear ({hasFilters ? 'has filters' : 'no filters'})
446
+ </button>
447
+ </div>
448
+
449
+ {shareMessage && <div className="message">{shareMessage}</div>}
450
+
451
+ {/* Grid component */}
81
452
  </div>
82
453
  )
83
454
  }
@@ -89,16 +460,20 @@ The library generates clean, human-readable URLs:
89
460
 
90
461
  ```
91
462
  Base URL: https://app.com/page
92
- 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
93
466
  ```
94
467
 
95
468
  Parameter structure:
96
469
 
97
470
  - Prefix: `f_` (configurable - useful for multi-grid scenarios)
98
471
  - Format: `f_{columnName}_{operation}={value}`
99
- - 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)
100
475
  - Standard URL encoding for special characters
101
- - 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`)
102
477
 
103
478
  ## API Reference
104
479
 
@@ -203,35 +578,43 @@ interface AGGridUrlSyncConfig {
203
578
 
204
579
  Check out the [examples](./examples) directory for comprehensive working demos:
205
580
 
206
- ### 📝 [Basic Example](./examples/basic-example.html)
581
+ ### 🚀 [Vanilla JavaScript Demo](./examples/vanilla-js/demo.html)
207
582
 
208
- Simple HTML/JS implementation showing core functionality:
583
+ Comprehensive demonstration showcasing all features:
209
584
 
210
- - Initialize URL sync with AG Grid
211
- - Generate shareable URLs
212
- - Apply filters from URLs
213
- - Handle filter changes
585
+ - **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
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
589
+ - **URL sharing workflow** - Copy to clipboard, email, and Slack integration
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
214
593
 
215
- ### 🚀 [Advanced Demo](./examples/advanced-demo.html)
594
+ ### ⚛️ [React Integration](./examples/react-basic/basic-grid.tsx)
216
595
 
217
- Feature-rich demonstration including:
596
+ Clean React component showing the `useAGGridUrlSync` hook:
218
597
 
219
- - Performance monitoring and benchmarks
220
- - Multiple filter scenarios (Sales, Engineering, Executive views)
221
- - URL sharing workflow with copy/email/Slack functionality
222
- - Error testing with malformed URLs and invalid filters
223
- - Memory and stress testing capabilities
598
+ - React hook integration with AG Grid for text and number filters
599
+ - Automatic filter state management for mixed filter types
600
+ - Share button with clipboard functionality
601
+ - Filter status indicators and controls
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
224
605
 
225
- ### 🔗 [Multi-Grid Demo](./examples/multi-grid-demo.html)
606
+ ### 📊 [Shared Data](./examples/shared-data.js)
226
607
 
227
- Complex example with multiple independent grids:
608
+ Common data and column definitions used across examples:
228
609
 
229
- - Four separate grids (Employees, Projects, Departments, Metrics)
230
- - Individual URL namespacing with different prefixes
231
- - Combined URL generation merging all grid states
232
- - Independent grid controls and clearing functions
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
233
616
 
234
- All examples work out-of-the-box by opening the HTML files in your browser.
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.
235
618
 
236
619
  ## Contributing
237
620
 
@@ -243,6 +626,6 @@ All examples work out-of-the-box by opening the HTML files in your browser.
243
626
 
244
627
  ## License
245
628
 
246
- 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.
247
630
 
248
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,5 +1,7 @@
1
- import { DEFAULT_CONFIG } from './utils.js';
2
- import { parseUrlFilters, generateUrl, getFilterModel, applyFilterModel } from './utils.js';
1
+ import { DEFAULT_CONFIG } from './validation.js';
2
+ import { parseUrlFilters } from './url-parser.js';
3
+ import { generateUrl } from './url-generator.js';
4
+ import { getFilterModel, applyFilterModel } from './grid-integration.js';
3
5
  /**
4
6
  * AGGridUrlSync class for synchronizing AG Grid text filters with URL parameters
5
7
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ag-grid-url-sync.js","sourceRoot":"","sources":["../../src/core/ag-grid-url-sync.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExE;;GAEG;AACH,MAAM,OAAO,aAAa;IAChB,MAAM,CAAgB;IAE9B;;;;OAIG;IACH,YAAY,OAAgB,EAAE,SAA8B,EAAE;QAC5D,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO;YACP,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,cAAc,CAAC,WAAW;YAC7D,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,cAAc,CAAC,cAAc;YACtE,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;SAChD,CAAA;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,OAAgB;QAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC/C,MAAM,GAAG,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC3C,OAAO,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACnD,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAA;IACtB,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,GAAY;QACvB,MAAM,UAAU,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC9C,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5D,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;IAChC,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,WAAwB;QACnC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,2DAA2D;IAC7D,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAgB,EAChB,MAA4B;IAE5B,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,14 @@
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;
7
+ /**
8
+ * Gets the current filter model from AG Grid
9
+ */
10
+ export declare function getFilterModel(config: InternalConfig): FilterState;
11
+ /**
12
+ * Applies a filter state to AG Grid
13
+ */
14
+ export declare function applyFilterModel(filterState: FilterState, config: InternalConfig): void;