advanced-filter-system 1.5.1 → 1.6.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/README.md CHANGED
@@ -1,610 +1,283 @@
1
1
  # Advanced Filter System (AFS)
2
2
 
3
- A powerful and flexible vanilla JavaScript filtering system that provides advanced filtering, searching, sorting, and pagination capabilities for DOM elements. Zero dependencies, lightweight, and highly customizable.
4
-
5
- [Live Demo](https://misits.github.io/advanced-filter-system) | [NPM Package](https://www.npmjs.com/package/advanced-filter-system) | [Interactive Examples](examples/demo.html)
6
-
7
- ## Table of Contents
8
-
9
- - [Advanced Filter System (AFS)](#advanced-filter-system-afs)
10
- - [Table of Contents](#table-of-contents)
11
- - [Features](#features)
12
- - [Installation](#installation)
13
- - [Quick Start](#quick-start)
14
- - [HTML Structure](#html-structure)
15
- - [JavaScript Initialization](#javascript-initialization)
16
- - [Filter Logic Modes](#filter-logic-modes)
17
- - [Mixed Mode (Recommended)](#mixed-mode-recommended)
18
- - [Per-Type Logic Configuration](#per-type-logic-configuration)
19
- - [Legacy Modes](#legacy-modes)
20
- - [Filter Types & UI Components](#filter-types--ui-components)
21
- - [Button Filters](#button-filters)
22
- - [Select Dropdowns](#select-dropdowns)
23
- - [Radio Buttons](#radio-buttons)
24
- - [Checkboxes](#checkboxes)
25
- - [Range Sliders](#range-sliders)
26
- - [Date Range Filters](#date-range-filters)
27
- - [Advanced Features](#advanced-features)
28
- - [Search & Filtering](#search--filtering)
29
- - [Sorting](#sorting)
30
- - [Pagination](#pagination)
31
- - [URL State Management](#url-state-management)
32
- - [Animations](#animations)
33
- - [Configuration Options](#configuration-options)
34
- - [API Reference](#api-reference)
35
- - [Examples](#examples)
36
- - [Browser Support](#browser-support)
37
- - [TypeScript Support](#typescript-support)
38
- - [Contributing](#contributing)
39
- - [License](#license)
3
+ A flexible, dependency-free JavaScript library for filtering DOM elements with search, sorting, range filters, pagination and URL state built in.
4
+
5
+ [Live Demo](https://misits.github.io/advanced-filter-system) · [NPM](https://www.npmjs.com/package/advanced-filter-system) · [Documentation](docs/README.md)
40
6
 
41
7
  ## Features
42
8
 
43
- - 🎯 **Advanced Filter Logic**
44
- - Mixed mode (OR within categories, AND between)
45
- - Per-type logic configuration
46
- - Multi-select and toggle modes
47
- - Category-specific clearing
48
- - 🔍 **Multiple Filter Types**
49
- - Button filters (toggle/multi-select)
50
- - Select dropdowns
51
- - Radio buttons (exclusive)
52
- - Checkboxes (multi-select)
53
- - Range sliders with histograms
54
- - Date range filters
55
- - 🔎 **Smart Search**
56
- - Real-time fuzzy search
57
- - Multiple searchable fields
58
- - Configurable debouncing
59
- - Minimum character threshold
60
- - ↕️ **Flexible Sorting**
61
- - Multi-column sorting
62
- - Custom sort functions
63
- - Auto-detect data types
64
- - Sort direction indicators
65
- - 📄 **Advanced Pagination**
66
- - Dynamic page sizes
67
- - Smooth transitions
68
- - Scroll-to-top option
69
- - Custom pagination controls
70
- - 🎨 **Rich Animations**
71
- - 14+ animation types (fade, slide, scale, flip, etc.)
72
- - Hardware-accelerated transitions
73
- - Customizable duration and easing
74
- - 🔗 **State Management**
75
- - URL state persistence
76
- - Browser history support
77
- - Shareable filtered URLs
78
- - State import/export
79
- - ⚡ **Performance Optimized**
80
- - Debounced updates
81
- - Efficient DOM manipulation
82
- - Minimal reflows and repaints
83
- - 🎯 **Event System**
84
- - Comprehensive event API
85
- - Custom event support
86
- - Debug mode with logging
9
+ - **Filtering** buttons, checkboxes, radios and dropdowns, with OR / AND / mixed logic configurable per filter type
10
+ - **Search** debounced text search across any data attributes, with optional match highlighting
11
+ - **Sorting** — by any data attribute (numbers, dates, strings auto-detected), multi-criteria, custom comparators, shuffle
12
+ - **Range filters** draggable sliders (with optional histogram), min/max number inputs, date ranges
13
+ - **Pagination** — page controls, items-per-page, smooth scroll-to-top, fully aware of active filters and sort order
14
+ - **URL state** the full filter state lives in the URL: shareable links, back/forward navigation, restored on load
15
+ - **Animations** fade, slide, scale, flip, rotate, zoom, bounce, blur and more
16
+ - **TypeScript** — complete type definitions included
87
17
 
88
18
  ## Installation
89
19
 
90
20
  ```bash
91
- # NPM
92
21
  npm install advanced-filter-system
93
-
94
- # Yarn
95
- yarn add advanced-filter-system
96
-
97
- # PNPM
98
- pnpm add advanced-filter-system
99
22
  ```
100
23
 
101
- Or include via CDN:
24
+ Or via CDN:
102
25
 
103
26
  ```html
104
27
  <script type="module">
105
- import { AFS } from 'https://unpkg.com/advanced-filter-system@latest/dist/afs.modern.js';
28
+ import { AFS } from 'https://unpkg.com/advanced-filter-system@latest/dist/afs.modern.js';
106
29
  </script>
107
30
  ```
108
31
 
109
- ## Quick Start
32
+ ## Quick start
110
33
 
111
- ### HTML Structure
34
+ A minimal, complete setup — filter buttons, search, counter and pagination:
112
35
 
113
36
  ```html
114
- <!DOCTYPE html>
115
- <html>
116
- <head>
117
- <title>AFS Demo</title>
118
- </head>
119
- <body>
120
- <!-- Filter Controls -->
121
- <div class="filter-controls">
122
- <button class="btn-filter" data-filter="*">All</button>
123
- <button class="btn-filter" data-filter="category:tech">Technology</button>
124
- <button class="btn-filter" data-filter="category:design">Design</button>
125
- </div>
126
-
127
- <!-- Search Input -->
128
- <input type="text" class="filter-search" placeholder="Search...">
129
-
130
- <!-- Results Counter -->
131
- <div class="filter-counter"></div>
132
-
133
- <!-- Filterable Items -->
134
- <div class="items-container">
135
- <div class="filter-item"
136
- data-categories="category:tech brand:apple"
137
- data-title="MacBook Pro"
138
- data-price="2499"
139
- data-date="2024-03-15">
140
- <h3>MacBook Pro</h3>
141
- <p>$2,499</p>
142
- </div>
143
- <!-- More items... -->
144
- </div>
145
-
146
- <!-- Pagination Container -->
147
- <div class="afs-pagination-container"></div>
148
- </body>
149
- </html>
37
+ <!-- Filter controls -->
38
+ <button class="btn-filter" data-filter="*">All</button>
39
+ <button class="btn-filter" data-filter="category:tech">Tech</button>
40
+ <button class="btn-filter" data-filter="category:design">Design</button>
41
+
42
+ <!-- Search and counter -->
43
+ <input type="text" class="filter-search" placeholder="Search…">
44
+ <div class="filter-counter"></div>
45
+
46
+ <!-- Items: data-categories holds space-separated "type:value" pairs -->
47
+ <div class="items-container">
48
+ <div class="filter-item" data-categories="category:tech brand:apple"
49
+ data-title="MacBook Pro" data-price="2499">
50
+ MacBook Pro $2,499
51
+ </div>
52
+ <div class="filter-item" data-categories="category:design brand:moleskine"
53
+ data-title="Sketchbook" data-price="29">
54
+ Sketchbook — $29
55
+ </div>
56
+ </div>
57
+
58
+ <!-- Pagination controls are rendered in here -->
59
+ <div class="afs-pagination-container"></div>
150
60
  ```
151
61
 
152
- ### JavaScript Initialization
153
-
154
62
  ```javascript
155
63
  import { AFS } from 'advanced-filter-system';
156
64
 
157
65
  const afs = new AFS({
158
- // Required selectors
159
- containerSelector: '.items-container',
160
- itemSelector: '.filter-item',
161
- filterButtonSelector: '.btn-filter',
162
- searchInputSelector: '.filter-search',
163
- counterSelector: '.filter-counter',
164
-
165
- // Search configuration
166
- searchKeys: ['title', 'categories'],
167
-
168
- // NEW: Advanced filter logic
169
- filterCategoryMode: 'mixed', // OR within categories, AND between
170
- filterTypeLogic: {
171
- category: { mode: 'OR', multi: true }, // Multi-select OR
172
- brand: 'OR', // Toggle mode
173
- price: 'AND' // Multi-select AND
174
- },
175
-
176
- // Pagination
177
- pagination: {
178
- enabled: true,
179
- itemsPerPage: 12
180
- },
181
-
182
- // Animations
183
- animation: {
184
- type: 'fade',
185
- duration: 300
186
- },
187
-
188
- // Debug mode
189
- debug: true
190
- });
191
- ```
192
-
193
- ## Filter Logic Modes
194
-
195
- ### Mixed Mode (Recommended)
196
-
197
- The most intuitive filtering experience - OR logic within filter categories, AND logic between different categories.
198
-
199
- ```javascript
200
- const afs = new AFS({
201
- filterCategoryMode: 'mixed',
202
- // When user selects: Tech OR Design AND Apple OR Samsung
203
- // Shows: (Tech OR Design) AND (Apple OR Samsung)
204
- });
205
- ```
206
-
207
- ### Per-Type Logic Configuration
208
-
209
- Configure each filter type independently for maximum flexibility.
210
-
211
- ```javascript
212
- const afs = new AFS({
213
- filterCategoryMode: 'mixed',
214
- filterTypeLogic: {
215
- category: { mode: 'OR', multi: true }, // Multi-select checkboxes
216
- brand: 'OR', // Toggle buttons (exclusive)
217
- price: 'AND', // Multi-select with AND logic
218
- features: { mode: 'OR', multi: true } // Multi-select with OR logic
219
- }
66
+ containerSelector: '.items-container', // required
67
+ itemSelector: '.filter-item', // required
68
+ filterButtonSelector: '.btn-filter',
69
+ searchInputSelector: '.filter-search',
70
+ counterSelector: '.filter-counter',
71
+ searchKeys: ['title', 'categories'],
72
+ pagination: { enabled: true, itemsPerPage: 12 },
73
+ animation: { type: 'fade', duration: 300 },
220
74
  });
221
-
222
- // Update logic at runtime
223
- afs.filter.setFilterTypeLogic('brand', { mode: 'OR', multi: true });
224
- ```
225
-
226
- ### Legacy Modes
227
-
228
- ```javascript
229
- // Legacy OR mode (all filters use OR logic)
230
- const afs = new AFS({ filterCategoryMode: 'OR' });
231
-
232
- // Legacy AND mode (all filters use AND logic)
233
- const afs = new AFS({ filterCategoryMode: 'AND' });
234
- ```
235
-
236
- ## Filter Types & UI Components
237
-
238
- ### Button Filters
239
-
240
- ```html
241
- <!-- Toggle mode (exclusive) -->
242
- <button class="btn-filter" data-filter="category:tech">Technology</button>
243
-
244
- <!-- Multi-select mode -->
245
- <button class="btn-filter" data-filter="brand:apple">Apple</button>
246
- <button class="btn-filter" data-filter="brand:samsung">Samsung</button>
247
-
248
- <!-- Clear specific category -->
249
- <button class="btn-filter" data-filter="category:*">Clear Categories</button>
250
75
  ```
251
76
 
252
- ### Select Dropdowns
253
-
254
- ```html
255
- <select class="afs-filter-dropdown">
256
- <option value="*">All Categories</option>
257
- <option value="category:tech">Technology</option>
258
- <option value="category:design">Design</option>
259
- </select>
77
+ ```css
78
+ /* AFS toggles these two classes — style them however you like */
79
+ .btn-filter.active { background: #000; color: #fff; }
80
+ .filter-item.hidden { display: none !important; }
260
81
  ```
261
82
 
262
- ### Radio Buttons
83
+ That's it. Clicking a filter button, typing in the search box or changing pages all update the items, the counter and the URL.
263
84
 
264
- ```html
265
- <label><input type="radio" name="category" class="btn-filter" data-filter="*" checked> All</label>
266
- <label><input type="radio" name="category" class="btn-filter" data-filter="category:tech"> Tech</label>
267
- <label><input type="radio" name="category" class="btn-filter" data-filter="category:design"> Design</label>
268
- ```
85
+ ## How filtering works
269
86
 
270
- ### Checkboxes
87
+ Every item declares its facets in `data-categories`, as space-separated `type:value` pairs:
271
88
 
272
89
  ```html
273
- <label><input type="checkbox" class="btn-filter" data-filter="category:tech"> Technology</label>
274
- <label><input type="checkbox" class="btn-filter" data-filter="category:design"> Design</label>
275
- ```
276
-
277
- ### Range Sliders
278
-
279
- ```javascript
280
- // Add price range slider with histogram
281
- afs.rangeFilter.addRangeSlider({
282
- key: 'price',
283
- type: 'number',
284
- container: '.price-range-container',
285
- min: 0,
286
- max: 3000,
287
- step: 50,
288
- ui: {
289
- showHistogram: true,
290
- bins: 10
291
- }
292
- });
293
-
294
- // Add rating range slider
295
- afs.rangeFilter.addRangeSlider({
296
- key: 'rating',
297
- type: 'number',
298
- container: '.rating-range-container',
299
- min: 4.0,
300
- max: 5.0,
301
- step: 0.1
302
- });
303
- ```
304
-
305
- ### Date Range Filters
306
-
307
- ```javascript
308
- // Add date range filter
309
- afs.dateFilter.addDateRange({
310
- key: 'date',
311
- container: '.date-range-container',
312
- minDate: new Date('2024-01-01'),
313
- maxDate: new Date(),
314
- format: 'YYYY-MM-DD'
315
- });
316
- ```
317
-
318
- ## Advanced Features
319
-
320
- ### Search & Filtering
321
-
322
- ```javascript
323
- // Configure search
324
- afs.search.configure({
325
- keys: ['title', 'description', 'categories'],
326
- fuzzy: true,
327
- minLength: 2,
328
- debounce: 300
329
- });
330
-
331
- // Programmatic filtering
332
- afs.filter.addFilter('category:tech');
333
- afs.filter.removeFilter('category:tech');
334
- afs.filter.clearAllFilters();
335
- ```
336
-
337
- ### Sorting
338
-
339
- ```javascript
340
- // Sort by single field
341
- afs.filter.sortWithOrder('price', 'DESC');
342
-
343
- // Custom sorting
344
- afs.sort.sortWithComparator('title', (a, b) => {
345
- return a.localeCompare(b, 'en', { numeric: true });
346
- });
347
-
348
- // Shuffle items
349
- afs.filter.shuffle();
90
+ <div class="filter-item" data-categories="category:tech brand:apple color:silver">
350
91
  ```
351
92
 
352
- ### Pagination
93
+ Filter controls target those pairs through `data-filter`:
353
94
 
354
- ```javascript
355
- // Configure pagination
356
- afs.pagination.configure({
357
- itemsPerPage: 12,
358
- showControls: true,
359
- scrollToTop: true,
360
- scrollBehavior: 'smooth'
361
- });
362
-
363
- // Toggle pagination mode
364
- afs.pagination.setPaginationMode(true); // Enable
365
- afs.pagination.setPaginationMode(false); // Show all
366
- ```
95
+ | `data-filter` value | Meaning |
96
+ |---|---|
97
+ | `category:tech` | Toggle this filter |
98
+ | `*` | Reset — show everything |
99
+ | `category:*` | Clear every active `category:` filter |
367
100
 
368
- ### URL State Management
101
+ By default AFS runs in **mixed mode**: filters of the same type combine with OR, different types combine with AND. Selecting *Tech*, *Design* and *Apple* shows items that are `(tech OR design) AND apple`. Each type's logic is configurable:
369
102
 
370
103
  ```javascript
371
- // Enable URL state persistence
372
104
  const afs = new AFS({
373
- preserveState: true,
374
- urlStateKey: 'filters' // Custom URL parameter name
105
+ filterCategoryMode: 'mixed',
106
+ filterTypeLogic: {
107
+ category: { mode: 'OR', multi: true }, // multi-select (checkbox-style)
108
+ brand: 'OR', // exclusive (one at a time)
109
+ tags: 'AND', // items must match all selected
110
+ },
375
111
  });
376
-
377
- // Manual state management
378
- const state = afs.getState();
379
- afs.setState(state);
380
112
  ```
381
113
 
382
- ### Animations
114
+ Buttons, checkboxes (`<input type="checkbox" data-filter>`), radios (`<input type="radio" data-filter>`) and dropdowns (`<select data-filter-type>`) are all supported — see the [Filter documentation](docs/filter.md).
383
115
 
384
- ```javascript
385
- const afs = new AFS({
386
- animation: {
387
- type: 'fade', // fade, slide, scale, flip, rotate, zoom, bounce, blur, etc.
388
- duration: 400,
389
- easing: 'ease-out'
390
- }
391
- });
116
+ ## Documentation
392
117
 
393
- // Change animation at runtime
394
- afs.filter.animation.setAnimation('slide');
395
- ```
118
+ | Module | Covers |
119
+ |---|---|
120
+ | [Filter](docs/filter.md) | Buttons, checkboxes, radios, dropdowns, logic modes, filter groups |
121
+ | [Search](docs/search.md) | Text search, debouncing, highlighting |
122
+ | [Sort](docs/sort.md) | Sort buttons, multi-criteria, custom comparators, shuffle |
123
+ | [Pagination](docs/pagination.md) | Page controls, items-per-page, scroll-to-top |
124
+ | [Range Filter](docs/range-filter.md) | Slider with optional histogram (numbers or dates) |
125
+ | [Input Range Filter](docs/input-range-filter.md) | Min/max number inputs |
126
+ | [Date Filter](docs/date-filter.md) | Date range pickers |
127
+ | [URL Manager](docs/url-manager.md) | URL parameters, shareable state, history |
396
128
 
397
- ## Configuration Options
129
+ ## Common options
130
+
131
+ All options with their defaults live in [`src/core/Options.js`](src/core/Options.js). The ones you'll touch most:
398
132
 
399
133
  ```javascript
400
134
  const afs = new AFS({
401
- // Required selectors
402
- containerSelector: '.items-container',
403
- itemSelector: '.filter-item',
404
- filterButtonSelector: '.btn-filter',
405
- searchInputSelector: '.filter-search',
406
- counterSelector: '.filter-counter',
407
-
408
- // Filter logic (NEW!)
409
- filterCategoryMode: 'mixed', // 'mixed', 'OR', 'AND'
410
- filterTypeLogic: {
411
- category: { mode: 'OR', multi: true },
412
- brand: 'OR',
413
- price: 'AND'
414
- },
415
-
416
- // Search configuration
417
- searchKeys: ['title', 'categories', 'description'],
418
- searchMode: 'fuzzy', // 'fuzzy' or 'exact'
419
- searchMinChars: 2,
420
- debounceTime: 300,
421
-
422
- // Pagination
423
- pagination: {
424
- enabled: true,
425
- itemsPerPage: 12,
426
- container: '.afs-pagination-container',
427
- showPrevNext: true,
428
- scrollToTop: true,
429
- scrollBehavior: 'smooth'
430
- },
431
-
432
- // Counter display
433
- counter: {
434
- template: 'Showing {visible} of {total} items',
435
- filteredTemplate: '({filtered} filtered)',
436
- noResultsTemplate: 'No items found'
437
- },
438
-
439
- // Animations
440
- animation: {
441
- type: 'fade',
442
- duration: 300,
443
- easing: 'ease-out'
444
- },
445
-
446
- // State management
447
- preserveState: true,
448
- urlStateKey: 'filters',
449
-
450
- // Styling
451
- styles: {
452
- colors: {
453
- primary: '#000',
454
- background: '#f5f5f5',
455
- text: '#333'
456
- },
457
- button: {
458
- borderRadius: '6px',
459
- padding: '8px 16px'
460
- }
461
- },
462
-
463
- // Debug mode
464
- debug: true
135
+ // Selectors (containerSelector and itemSelector are required)
136
+ containerSelector: '.afs-filter-container',
137
+ itemSelector: '.afs-filter-item',
138
+ filterButtonSelector: '.afs-btn-filter',
139
+ filterDropdownSelector: '.afs-filter-dropdown',
140
+ searchInputSelector: '.afs-filter-search',
141
+ counterSelector: '.afs-filter-counter',
142
+ sortButtonSelector: '.afs-btn-sort',
143
+
144
+ // CSS classes AFS toggles
145
+ activeClass: 'active',
146
+ hiddenClass: 'hidden',
147
+ activeSortClass: 'sort-active',
148
+
149
+ // Filter logic
150
+ filterCategoryMode: 'mixed', // 'mixed' | 'OR' | 'AND'
151
+ filterTypeLogic: {}, // per-type config, see above
152
+
153
+ // Search
154
+ searchKeys: ['title'],
155
+ debounceTime: 300,
156
+
157
+ // Pagination (disabled by default)
158
+ pagination: {
159
+ enabled: false,
160
+ itemsPerPage: 10,
161
+ container: '.afs-pagination-container',
162
+ showPrevNext: true,
163
+ scrollToTop: false, // scrolls back to the top of the items list
164
+ scrollOffset: 50,
165
+ scrollBehavior: 'smooth', // 'smooth' | 'auto'
166
+ },
167
+
168
+ // Counter
169
+ counter: {
170
+ template: 'Showing {visible} of {total}',
171
+ showFiltered: true,
172
+ filteredTemplate: '({filtered} filtered)',
173
+ noResultsTemplate: 'No items found',
174
+ },
175
+
176
+ // Animations
177
+ animation: { type: 'fade', duration: 300 },
178
+
179
+ // Misc
180
+ debug: false, // log to console
181
+ preserveState: false, // persist state in sessionStorage across tab switches
465
182
  });
466
183
  ```
467
184
 
468
- ## API Reference
185
+ ## API at a glance
469
186
 
470
- ### Core Methods
187
+ Each feature lives on the instance: `afs.filter`, `afs.search`, `afs.sort`, `afs.pagination`, `afs.rangeFilter`, `afs.inputRangeFilter`, `afs.dateFilter`, `afs.urlManager`.
471
188
 
472
189
  ```javascript
473
- // Filter management
190
+ // Filtering
474
191
  afs.filter.addFilter('category:tech');
475
192
  afs.filter.removeFilter('category:tech');
476
- afs.filter.clearAllFilters();
477
- afs.filter.setFilterTypeLogic('brand', 'AND');
193
+ afs.filter.clearAllFilters(); // filters + search + dropdowns + checkboxes
478
194
 
479
195
  // Search
480
- afs.search.search('query');
196
+ afs.search.setValue('macbook');
481
197
  afs.search.clearSearch();
482
198
 
483
199
  // Sorting
484
- afs.filter.sortWithOrder('price', 'DESC');
485
- afs.filter.shuffle();
200
+ afs.sort.sort('price', 'desc');
201
+ afs.sort.shuffle();
202
+ afs.sort.reset();
486
203
 
487
204
  // Pagination
488
205
  afs.pagination.goToPage(2);
489
206
  afs.pagination.nextPage();
490
- afs.pagination.previousPage();
491
-
492
- // State
493
- const state = afs.getState();
494
- afs.setState(state);
207
+ afs.pagination.setItemsPerPage(24);
208
+ afs.pagination.getPageInfo(); // { currentPage, itemsPerPage, totalPages }
495
209
 
496
- // Events
497
- afs.on('filter:applied', (data) => {
498
- console.log(`Showing ${data.visible} of ${data.total} items`);
210
+ // Range widgets (containers are DOM elements)
211
+ afs.rangeFilter.addRangeSlider({
212
+ key: 'price', type: 'number',
213
+ container: document.querySelector('.price-slider'),
214
+ min: 0, max: 1000, step: 10,
215
+ ui: { showHistogram: true, bins: 12 },
499
216
  });
500
- ```
501
-
502
- ### Event System
217
+ afs.inputRangeFilter.addInputRange({ key: 'rating', container: el, min: 0, max: 5, step: 0.5 });
218
+ afs.dateFilter.addDateRange({ key: 'date', container: el });
503
219
 
504
- ```javascript
505
- // Available events
506
- afs.on('filter:applied', callback);
507
- afs.on('search:performed', callback);
508
- afs.on('sort:applied', callback);
509
- afs.on('pagination:changed', callback);
510
- afs.on('state:changed', callback);
220
+ // Lifecycle
221
+ afs.refresh(); // re-scan items (after DOM changes)
222
+ afs.destroy();
511
223
  ```
512
224
 
513
- ## Examples
514
-
515
- The project includes comprehensive examples demonstrating all features:
516
-
517
- - **[Interactive Demo](examples/demo.html)** - Complete demo with all filter types
518
- - **[Button Filters](examples/demo.html#buttons)** - Toggle and multi-select buttons
519
- - **[Select Dropdowns](examples/demo.html#select)** - Dropdown filter controls
520
- - **[Radio Buttons](examples/demo.html#radio)** - Exclusive radio button filters
521
- - **[Checkboxes](examples/demo.html#checkbox)** - Multi-select checkbox filters
522
- - **[Range Filters](examples/demo.html#range)** - Sliders with histogram support
523
- - **[Search Functionality](examples/demo.html#search)** - Real-time search examples
524
-
525
- ### Running Examples Locally
225
+ ### Events
526
226
 
527
- ```bash
528
- # Clone the repository
529
- git clone https://github.com/misits/advanced-filter-system.git
530
- cd advanced-filter-system
531
-
532
- # Open examples in browser
533
- open examples/index.html
227
+ ```javascript
228
+ afs.on('filtersApplied', ({ activeFilters, visibleItems }) => { /* … */ });
229
+ afs.on('search', ({ query, matches, total }) => { /* … */ });
230
+ afs.on('sort', ({ key, direction }) => { /* … */ });
231
+ afs.on('pageChanged', ({ currentPage, totalPages }) => { /* … */ });
232
+ afs.on('filtersCleared', () => { /* … */ });
233
+ afs.on('urlStateLoaded', ({ params }) => { /* … */ });
534
234
  ```
535
235
 
536
- ## Browser Support
537
-
538
- - Chrome (latest)
539
- - Firefox (latest)
540
- - Safari (latest)
541
- - Edge (latest)
542
- - Opera (latest)
236
+ `on`, `once`, `off`, `removeAllListeners` are available. Each module's documentation lists its events and payloads.
543
237
 
544
- Modern browser features used:
545
- - ES6 Modules
546
- - CSS Custom Properties
547
- - IntersectionObserver API
548
- - URLSearchParams API
238
+ ## TypeScript
549
239
 
550
- ## TypeScript Support
551
-
552
- Full TypeScript support with comprehensive type definitions:
240
+ Type definitions ship with the package:
553
241
 
554
242
  ```typescript
555
243
  import { AFS, AFSOptions, FilterTypeLogic } from 'advanced-filter-system';
556
244
 
557
- interface CustomOptions extends AFSOptions {
558
- customProperty: string;
559
- }
560
-
561
- const filterLogic: FilterTypeLogic = {
562
- category: { mode: 'OR', multi: true },
563
- brand: 'OR'
245
+ const logic: FilterTypeLogic = {
246
+ category: { mode: 'OR', multi: true },
247
+ brand: 'OR',
564
248
  };
565
249
 
566
250
  const afs = new AFS({
567
- containerSelector: '#items',
568
- itemSelector: '.item',
569
- filterTypeLogic: filterLogic
570
- } as CustomOptions);
251
+ containerSelector: '#items',
252
+ itemSelector: '.item',
253
+ filterTypeLogic: logic,
254
+ });
571
255
  ```
572
256
 
573
- ## Contributing
257
+ ## Browser support
574
258
 
575
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:
259
+ Modern evergreen browsers (Chrome, Firefox, Safari, Edge). Uses ES modules, `URLSearchParams` and the History API. `dist/afs.legacy.js` (UMD) is provided for non-module environments.
576
260
 
577
- 1. Setting up the development environment
578
- 2. Code style and standards
579
- 3. Testing requirements
580
- 4. Pull request process
581
- 5. Bug reporting guidelines
582
- 6. Feature request templates
583
-
584
- ### Development Setup
261
+ ## Development
585
262
 
586
263
  ```bash
587
- # Clone and install
588
264
  git clone https://github.com/misits/advanced-filter-system.git
589
265
  cd advanced-filter-system
590
266
  npm install
591
267
 
592
- # Run development server
593
- npm run dev
594
-
595
- # Build for production
596
- npm run build
268
+ npm test # jest test suite
269
+ npm run build # build dist/ (development)
270
+ npm run build:prod # minified production build
597
271
 
598
- # Run tests
599
- npm test
272
+ # Try the demo (imports ../dist/afs.modern.js, so build first)
273
+ npm run build && npx serve .
274
+ # then open http://localhost:3000/examples/demo.html
600
275
  ```
601
276
 
602
277
  ## License
603
278
 
604
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
279
+ MIT see [LICENSE](LICENSE).
605
280
 
606
281
  ---
607
282
 
608
283
  Made with ♥ by [misits](https://github.com/misits)
609
-
610
- **Star ⭐ this repo if you find it helpful!**