advanced-filter-system 1.0.6 → 1.0.8

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,324 +1,560 @@
1
- # Advanced Filter System
2
-
3
- A powerful and flexible JavaScript library for filtering DOM elements with comprehensive search, sorting, and filtering capabilities.
1
+ # Advanced Filter System (AFS)
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)
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
+ - [Basic Usage](#basic-usage)
17
+ - [Filtering](#filtering)
18
+ - [Searching](#searching)
19
+ - [Sorting](#sorting)
20
+ - [Pagination](#pagination)
21
+ - [Advanced Usage](#advanced-usage)
22
+ - [Custom Animation](#custom-animation)
23
+ - [Filter Groups](#filter-groups)
24
+ - [Custom Sorting](#custom-sorting)
25
+ - [URL State Management](#url-state-management)
26
+ - [Components](#components)
27
+ - [Filter System](#filter-system)
28
+ - [Range Filter](#range-filter)
29
+ - [Date Filter](#date-filter)
30
+ - [Search System](#search-system)
31
+ - [Sort System](#sort-system)
32
+ - [Pagination](#pagination-1)
33
+ - [URL Manager](#url-manager)
34
+ - [Styling \& Theming](#styling--theming)
35
+ - [Built-in Themes](#built-in-themes)
36
+ - [Custom Themes](#custom-themes)
37
+ - [Animations](#animations)
38
+ - [Browser Support](#browser-support)
39
+ - [TypeScript Support](#typescript-support)
40
+ - [Contributing](#contributing)
41
+ - [License](#license)
4
42
 
5
43
  ## Features
6
44
 
7
- ### Core Filtering
8
-
9
- - 🔍 Multiple filter types (category, price, status, etc.)
10
- - 🔀 Flexible filter modes (AND/OR logic)
11
- - 👥 Filter groups with independent logic
12
- - 📊 Multi-criteria sorting
13
- - 🔎 Text search with debouncing
14
- - 📱 Responsive design support
15
- - Smooth animations and transitions
16
- - 🔢 Results counter
17
- - 🔗 URL state management
18
-
19
- ### Advanced Features
20
-
21
- - 📑 Pagination support
22
- - 📊 Range-based filtering
23
- - 💾 Filter presets (save/load)
24
- - 📈 Analytics integration
25
- - ⌨️ Keyboard navigation
26
- - 🔄 Custom sort comparators
27
- - 🎯 Event system
28
- - 📱 Responsive breakpoints
29
- - 🔍 Multiple search keys
30
- - 🎨 Customizable animations
45
+ - 🔍 **Advanced Filtering**
46
+ - Multiple filter types (text, range, date)
47
+ - AND/OR logic
48
+ - Filter groups
49
+ - Dynamic filters
50
+ - 🔎 **Smart Search**
51
+ - Real-time search
52
+ - Multiple fields
53
+ - Highlight matches
54
+ - Minimum character threshold
55
+ - ↕️ **Flexible Sorting**
56
+ - Multi-column sort
57
+ - Custom comparators
58
+ - Auto-detect data types
59
+ - 📄 **Pagination**
60
+ - Dynamic page size
61
+ - Custom controls
62
+ - Scroll to top
63
+ - 🔗 **URL Management**
64
+ - State persistence
65
+ - Browser history support
66
+ - Shareable URLs
67
+ - **Performance**
68
+ - Debounced updates
69
+ - Efficient DOM manipulation
70
+ - Minimal reflows
71
+ - 🎨 **Rich Animation**
72
+ - 15+ built-in animations
73
+ - Custom transitions
74
+ - Hardware acceleration
75
+ - 💾 **State Management**
76
+ - Centralized state
77
+ - Import/Export
78
+ - Undo/Redo support
79
+ - 🎯 **Event System**
80
+ - Rich event API
81
+ - Custom events
82
+ - Event debugging
31
83
 
32
84
  ## Installation
33
85
 
34
- ### Via npm
35
-
36
86
  ```bash
87
+ # NPM
37
88
  npm install advanced-filter-system
38
- ```
39
89
 
40
- ### Via yarn
41
-
42
- ```bash
90
+ # Yarn
43
91
  yarn add advanced-filter-system
92
+
93
+ # PNPM
94
+ pnpm add advanced-filter-system
44
95
  ```
45
96
 
46
- ### Direct Download
97
+ Or include via CDN:
47
98
 
48
- Download `src/AFS.js` from this repository and include it in your project.
99
+ ```html
100
+ <script src="https://unpkg.com/advanced-filter-system@1.0.8/dist/AFS.min.js"></script>
101
+ ```
49
102
 
50
- ## Usage Guide
103
+ ## Quick Start
51
104
 
52
- ### Basic Setup
105
+ ### HTML Structure
53
106
 
54
107
  ```html
55
- <div class="filter-container">
56
- <!-- Filter buttons -->
57
- <div class="filters">
58
- <button class="btn-filter" data-filter="*">All</button>
59
- <button class="btn-filter" data-filter="category:web">Web</button>
60
- <button class="btn-filter" data-filter="category:design">Design</button>
61
- </div>
108
+ <!DOCTYPE html>
109
+ <html>
110
+ <head>
111
+ <title>AFS Demo</title>
112
+ </head>
113
+ <body>
114
+ <!-- Counter -->
115
+ <div class="filter-counter"></div>
62
116
 
63
- <!-- Optional components -->
117
+ <!-- Search -->
64
118
  <input type="text" class="filter-search" placeholder="Search...">
65
- <div class="filter-counter"></div>
119
+
120
+ <!-- Filter Buttons -->
121
+ <div class="filter-buttons">
122
+ <button class="btn-filter" data-filter="all">All</button>
123
+ <button class="btn-filter" data-filter="category1">Category 1</button>
124
+ <button class="btn-filter" data-filter="category2">Category 2</button>
125
+ </div>
126
+
127
+ <!-- Sort Buttons -->
128
+ <div class="sort-buttons">
129
+ <button class="btn-sort" data-sort-key="price">
130
+ Price <span class="sort-direction">↑</span>
131
+ </button>
132
+ <button class="btn-sort" data-sort-key="date">
133
+ Date <span class="sort-direction">↑</span>
134
+ </button>
135
+ </div>
66
136
 
67
- <!-- Filterable items -->
68
- <div class="items">
137
+ <!-- Range Filter -->
138
+ <div id="price-range"></div>
139
+
140
+ <!-- Date Filter -->
141
+ <div id="date-filter"></div>
142
+
143
+ <!-- Items Container -->
144
+ <div id="items-container">
69
145
  <div class="filter-item"
70
- data-categories="category:web"
71
- data-title="Project 1"
72
- data-price="599"
73
- data-year="2023">
74
- <!-- Content -->
146
+ data-categories="category1"
147
+ data-price="99.99"
148
+ data-date="2024-03-15"
149
+ data-title="Item 1"
150
+ data-description="Description for item 1">
151
+ <h3>Item 1</h3>
152
+ <p>$99.99</p>
153
+ <p>March 15, 2024</p>
75
154
  </div>
155
+ <!-- More items... -->
76
156
  </div>
77
- </div>
157
+
158
+ <!-- Pagination -->
159
+ <div class="pagination-container"></div>
160
+
161
+ <!-- Scripts -->
162
+ <script src="https://unpkg.com/advanced-filter-system@1.0.8/dist/AFS.min.js"></script>
163
+ <script>
164
+ const afs = AFS.createAFS({
165
+ containerSelector: '#items-container',
166
+ itemSelector: '.filter-item',
167
+ searchInputSelector: '.filter-search',
168
+ filterButtonSelector: '.btn-filter',
169
+ sortButtonSelector: '.btn-sort',
170
+ counterSelector: '.filter-counter',
171
+ debug: true,
172
+ responsive: true,
173
+ preserveState: true,
174
+ animation: {
175
+ type: 'fade',
176
+ duration: 300
177
+ },
178
+ pagination: {
179
+ enabled: true,
180
+ itemsPerPage: 10
181
+ }
182
+ });
183
+
184
+ // Add range filter
185
+ afs.rangeFilter.addRangeSlider({
186
+ key: 'price',
187
+ container: document.querySelector('#price-range'),
188
+ min: 0,
189
+ max: 1000,
190
+ step: 10
191
+ });
192
+
193
+ // Add date filter
194
+ afs.dateFilter.addDateRange({
195
+ key: 'date',
196
+ container: document.querySelector('#date-filter')
197
+ });
198
+ </script>
199
+ </body>
200
+ </html>
78
201
  ```
79
202
 
80
- ### Basic JavaScript Initialization
203
+ ### JavaScript Initialization
204
+
205
+ Using ES modules:
81
206
 
82
207
  ```javascript
83
- import { AFS } from 'advanced-filter-system';
208
+ import { createAFS } from 'advanced-filter-system';
84
209
 
85
- const filter = new AFS({
86
- containerSelector: '.filter-container',
210
+ const afs = createAFS({
211
+ containerSelector: '#items-container',
87
212
  itemSelector: '.filter-item',
88
- filterButtonSelector: '.btn-filter'
213
+ debug: true,
214
+ animation: {
215
+ type: 'fade',
216
+ duration: 300
217
+ }
89
218
  });
90
219
  ```
91
220
 
92
- ## Feature Documentation
221
+ ## Basic Usage
93
222
 
94
- ### 1. Filter Modes
223
+ ### Filtering
95
224
 
96
225
  ```javascript
97
- // Set filter logic mode
98
- filter.setFilterMode('AND'); // Items must match all selected filters
99
- filter.setFilterMode('OR'); // Items must match any selected filter
226
+ // HTML
227
+ <button class="btn-filter" data-filter="category1">Category 1</button>
228
+ <button class="btn-filter" data-filter="category2">Category 2</button>
100
229
 
101
- // Alternative method
102
- filter.setLogic('AND');
103
- filter.setLogic(true); // true = AND, false = OR
104
- ```
105
-
106
- ### 2. Filter Groups
230
+ <div class="filter-item" data-categories="category1,category2">
231
+ Item content
232
+ </div>
107
233
 
108
- Groups allow complex filtering logic with independent AND/OR operations.
234
+ // JavaScript
235
+ // Set filter mode
236
+ afs.filter.setFilterMode('AND'); // or 'OR'
109
237
 
110
- ```javascript
111
- // Add filter groups
112
- filter.addFilterGroup('categories', ['category:tech', 'category:web'], 'OR');
113
- filter.addFilterGroup('price', ['price:low', 'price:medium'], 'AND');
238
+ // Add filter programmatically
239
+ afs.filter.addFilter('category1');
114
240
 
115
- // Set how groups combine
116
- filter.setGroupMode('AND'); // Items must match all groups
117
- filter.setGroupMode('OR'); // Items must match any group
241
+ // Remove filter
242
+ afs.filter.removeFilter('category1');
118
243
 
119
- // Remove groups
120
- filter.removeFilterGroup('price');
244
+ // Clear all filters
245
+ afs.filter.clearAllFilters();
121
246
  ```
122
247
 
123
- ### 3. Search Functionality
248
+ ### Searching
124
249
 
125
250
  ```javascript
251
+ // HTML
252
+ <input type="text" class="filter-search">
253
+ <div class="filter-item"
254
+ data-title="Product Name"
255
+ data-description="Product description">
256
+ Item content
257
+ </div>
258
+
259
+ // JavaScript
126
260
  // Configure search
127
- const filter = new AFS({
128
- searchInputSelector: '.filter-search',
129
- searchKeys: ['title', 'description'], // Data attributes to search in
130
- debounceTime: 300 // Milliseconds
261
+ afs.search.updateConfig({
262
+ searchKeys: ['title', 'description'],
263
+ minSearchLength: 2,
264
+ highlightMatches: true,
265
+ debounceTime: 300
131
266
  });
132
267
 
133
- // Programmatic search
134
- filter.search('query');
268
+ // Perform search programmatically
269
+ afs.search.search('query');
270
+
271
+ // Clear search
272
+ afs.search.clearSearch();
135
273
  ```
136
274
 
137
- ### 4. Sorting
275
+ ### Sorting
138
276
 
139
277
  ```javascript
140
- // Multi-criteria sorting
141
- filter.sortMultiple([
142
- { key: 'year', direction: 'desc' },
143
- { key: 'title', direction: 'asc' }
144
- ]);
278
+ // HTML
279
+ <button class="btn-sort" data-sort-key="price">Sort by Price</button>
280
+ <button class="btn-sort" data-sort-key="date">Sort by Date</button>
145
281
 
146
- // Custom comparator
147
- filter.sortWithComparator('price', (a, b) => parseFloat(a) - parseFloat(b));
148
- ```
149
-
150
- ### 5. Range Filtering
282
+ <div class="filter-item" data-price="99.99" data-date="2024-03-15">
283
+ Item content
284
+ </div>
151
285
 
152
- ```javascript
153
- // Filter by numeric range
154
- filter.addRangeFilter('price', 100, 500);
155
- ```
286
+ // JavaScript
287
+ // Basic sort
288
+ afs.sort.sort('price', 'asc');
156
289
 
157
- ### 6. Pagination
290
+ // Multiple criteria sort
291
+ afs.sort.sortMultiple([
292
+ { key: 'category', direction: 'asc' },
293
+ { key: 'price', direction: 'desc' }
294
+ ]);
158
295
 
159
- ```javascript
160
- // Enable pagination
161
- filter.setPagination(12); // 12 items per page
296
+ // Reset sort
297
+ afs.sort.reset();
162
298
  ```
163
299
 
164
- ### 7. State Management
300
+ ### Pagination
165
301
 
166
302
  ```javascript
167
- // URL State
168
- // Automatically managed, creates URLs like:
169
- // ?category=web,design&price=low,medium&search=project
303
+ // HTML
304
+ <div class="pagination-container"></div>
305
+
306
+ // JavaScript
307
+ // Configure pagination
308
+ const afs = createAFS({
309
+ pagination: {
310
+ enabled: true,
311
+ itemsPerPage: 10,
312
+ maxButtons: 7,
313
+ showPrevNext: true,
314
+ scrollToTop: true
315
+ }
316
+ });
170
317
 
171
- // Export/Import State
172
- const state = filter.exportState();
173
- filter.importState(state);
318
+ // Navigate pages
319
+ afs.pagination.goToPage(2);
174
320
 
175
- // Presets
176
- filter.savePreset('myFilters');
177
- filter.loadPreset('myFilters');
321
+ // Change items per page
322
+ afs.pagination.setItemsPerPage(20);
323
+
324
+ // Get pagination info
325
+ const info = afs.pagination.getPageInfo();
178
326
  ```
179
327
 
180
- ### 8. Analytics
328
+ ## Advanced Usage
329
+
330
+ ### Custom Animation
181
331
 
182
332
  ```javascript
183
- filter.enableAnalytics((data) => {
184
- console.log('Filter event:', data);
185
- // { type: 'filter', filters: [...], visibleItems: 10, timestamp: '...' }
333
+ // Custom animation configuration
334
+ const afs = createAFS({
335
+ animation: {
336
+ type: 'custom',
337
+ duration: 500,
338
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
339
+ inClass: 'my-enter',
340
+ outClass: 'my-leave'
341
+ }
186
342
  });
343
+
344
+ // CSS
345
+ .my-enter {
346
+ opacity: 0;
347
+ transform: scale(0.9);
348
+ }
349
+
350
+ .my-enter.my-enter-active {
351
+ opacity: 1;
352
+ transform: scale(1);
353
+ transition: opacity 500ms cubic-bezier(0.4, 0, 0.2, 1),
354
+ transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
355
+ }
356
+
357
+ .my-leave {
358
+ opacity: 1;
359
+ transform: scale(1);
360
+ }
361
+
362
+ .my-leave.my-leave-active {
363
+ opacity: 0;
364
+ transform: scale(0.9);
365
+ transition: opacity 500ms cubic-bezier(0.4, 0, 0.2, 1),
366
+ transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
367
+ }
187
368
  ```
188
369
 
189
- ### 9. Responsive Design
370
+ ### Filter Groups
190
371
 
191
372
  ```javascript
192
- filter.setResponsiveOptions({
193
- '768': {
194
- animationDuration: 200,
195
- itemsPerPage: 8
196
- },
197
- '480': {
198
- animationDuration: 0,
199
- itemsPerPage: 4
200
- }
373
+ // Create filter groups with different operators
374
+ afs.filter.addFilterGroup('price', {
375
+ ranges: [[0, 100], [101, 500], [501, 1000]],
376
+ operator: 'OR'
377
+ });
378
+
379
+ afs.filter.addFilterGroup('categories', {
380
+ filters: ['electronics', 'books'],
381
+ operator: 'AND'
201
382
  });
383
+
384
+ // Set group mode
385
+ afs.filter.setGroupMode('AND');
386
+
387
+ // Remove group
388
+ afs.filter.removeFilterGroup('price');
202
389
  ```
203
390
 
204
- ### 10. Animation Configuration
391
+ ### Custom Sorting
205
392
 
206
393
  ```javascript
207
- filter.setAnimationOptions({
208
- duration: 300,
209
- type: 'ease-out'
394
+ // Custom comparator for special sorting needs
395
+ afs.sort.sortWithComparator('title', (a, b) => {
396
+ // Sort by last word
397
+ const getLastWord = str => str.split(' ').pop();
398
+ const lastA = getLastWord(a);
399
+ const lastB = getLastWord(b);
400
+ return lastA.localeCompare(lastB);
401
+ });
402
+
403
+ // Sort with multiple languages
404
+ afs.sort.sortWithComparator('title', (a, b) => {
405
+ return a.localeCompare(b, 'es', {
406
+ sensitivity: 'base',
407
+ numeric: true
408
+ });
210
409
  });
211
410
  ```
212
411
 
213
- ### 11. Event System
412
+ ### URL State Management
214
413
 
215
414
  ```javascript
216
- filter.on('filter', (data) => {
217
- console.log('Filter changed:', data);
415
+ // Enable URL state
416
+ const afs = createAFS({
417
+ urlStateEnabled: true,
418
+ urlStateKey: 'filter'
218
419
  });
219
- ```
220
420
 
221
- ### 12. Keyboard Navigation
421
+ // Handle state changes
422
+ afs.on('urlStateLoaded', (state) => {
423
+ console.log('State loaded:', state);
424
+ });
222
425
 
223
- ```javascript
224
- filter.enableKeyboardNavigation();
426
+ // Manual control
427
+ afs.urlManager.updateURL();
428
+ afs.urlManager.loadFromURL();
429
+ afs.urlManager.clearURL();
430
+
431
+ // Get specific parameter
432
+ const searchQuery = afs.urlManager.getParam('search');
225
433
  ```
226
434
 
227
- ### 13. Sort asc/desc
435
+ ## Components
228
436
 
229
- ```javascript
230
- filter.sortWithComparator('price', (a, b) => parseFloat(a) - parseFloat(b), 'asc');
437
+ Each component can be used independently or as part of the AFS system.
231
438
 
232
- // or
439
+ ### Filter System
440
+ See [Filter Documentation](docs/filter.md)
233
441
 
234
- filter.sortWithOrder('price');
235
- ```
442
+ ### Range Filter
443
+ See [Range Filter Documentation](docs/range-filter.md)
236
444
 
237
- ### 13. Shuffle
445
+ ### Date Filter
446
+ See [Date Filter Documentation](docs/date-filter.md)
238
447
 
239
- ```javascript
240
- filter.shuffle();
241
- ```
448
+ ### Search System
449
+ See [Search Documentation](docs/search.md)
450
+
451
+ ### Sort System
452
+ See [Sort Documentation](docs/sort.md)
453
+
454
+ ### Pagination
455
+ See [Pagination Documentation](docs/pagination.md)
242
456
 
243
- ## Browser Compatibility
457
+ ### URL Manager
458
+ See [URL Manager Documentation](docs/url-manager.md)
244
459
 
245
- - Chrome
246
- - ✅ Firefox
247
- - ✅ Safari
248
- - ✅ Edge
249
- - ✅ IE11 (with polyfills)
460
+ ## Styling & Theming
250
461
 
251
- ## Full Configuration Options
462
+ ### Built-in Themes
252
463
 
253
464
  ```javascript
254
- const filter = new AFS({
255
- // Required
256
- containerSelector: '.filter-container',
257
- itemSelector: '.filter-item',
258
- filterButtonSelector: '.btn-filter',
259
-
260
- // Optional (with defaults)
261
- searchInputSelector: '.filter-search',
262
- counterSelector: '.filter-counter',
263
- activeClass: 'active',
264
- hiddenClass: 'hidden',
265
- animationDuration: 300,
266
- filterMode: 'OR',
267
- searchKeys: ['title'],
268
- debounceTime: 300,
269
- debug: false, // Enable console logs
270
- logLevel: 'info', // 'info', 'warn', 'error', 'debug'
465
+ const afs = createAFS({
466
+ styles: {
467
+ colors: {
468
+ primary: '#3b82f6',
469
+ background: '#f3f4f6',
470
+ text: '#1f2937'
471
+ }
472
+ }
271
473
  });
272
474
  ```
273
475
 
274
- ## API Methods Reference
476
+ ### Custom Themes
275
477
 
276
- ### Filter Management
478
+ ```javascript
479
+ const afs = createAFS({
480
+ styles: {
481
+ colors: {
482
+ primary: '#custom-color',
483
+ background: '#custom-bg',
484
+ text: '#custom-text'
485
+ },
486
+ components: {
487
+ button: {
488
+ borderRadius: '8px',
489
+ padding: '8px 16px'
490
+ },
491
+ input: {
492
+ borderWidth: '2px',
493
+ focusRing: '3px'
494
+ }
495
+ }
496
+ }
497
+ });
498
+ ```
277
499
 
278
- - `addFilter(type, value)`
279
- - `removeFilter(type, value)`
280
- - `getActiveFiltersByType(type)`
281
- - `setFilterMode(mode)`
282
- - `resetFilters()`
500
+ ### Animations
283
501
 
284
- ### Filter Groups
502
+ ```javascript
503
+ const afs = createAFS({
504
+ animation: {
505
+ type: 'fade', // or 'slide', 'scale', etc.
506
+ duration: 300,
507
+ }
508
+ });
509
+ ```
285
510
 
286
- - `addFilterGroup(groupId, filters, operator)`
287
- - `removeFilterGroup(groupId)`
288
- - `setGroupMode(mode)`
511
+ ## Browser Support
289
512
 
290
- ### Search and Sort
513
+ - Chrome (last 2 versions)
514
+ - Firefox (last 2 versions)
515
+ - Safari (last 2 versions)
516
+ - Edge (last 2 versions)
517
+ - iOS Safari (last 2 versions)
518
+ - Android Chrome (last 2 versions)
291
519
 
292
- - `search(query)`
293
- - `sortMultiple(criteria)`
294
- - `sortWithComparator(key, comparator)`
295
- - `addRangeFilter(key, min, max)`
296
- - `shuffle()`
297
- - `sortWithOrder(key)`
520
+ Required browser features:
298
521
 
299
- ### State Management
522
+ - CSS Transitions
523
+ - Flexbox
524
+ - CSS Grid (optional)
525
+ - History API
526
+ - localStorage
527
+ - MutationObserver
300
528
 
301
- - `exportState()`
302
- - `importState(state)`
303
- - `savePreset(presetName)`
304
- - `loadPreset(presetName)`
529
+ ## TypeScript Support
305
530
 
306
- ### UI and Display
531
+ Full TypeScript support with type definitions included:
307
532
 
308
- - `setPagination(itemsPerPage)`
309
- - `setAnimationOptions(options)`
310
- - `setResponsiveOptions(breakpoints)`
311
- - `enableKeyboardNavigation()`
533
+ ```typescript
534
+ import { createAFS, AFSOptions } from 'advanced-filter-system';
312
535
 
313
- ### Events and Analytics
536
+ const options: AFSOptions = {
537
+ containerSelector: '#items-container',
538
+ itemSelector: '.filter-item'
539
+ };
314
540
 
315
- - `on(eventName, callback)`
316
- - `enableAnalytics(callback)`
541
+ const afs = createAFS(options);
542
+ ```
317
543
 
318
544
  ## Contributing
319
545
 
320
- Contributions are welcome! Please feel free to submit issues and pull requests.
546
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:
547
+
548
+ 1. Setting up the development environment
549
+ 2. Coding standards
550
+ 3. Pull request process
551
+ 4. Bug reporting
552
+ 5. Feature requests
321
553
 
322
554
  ## License
323
555
 
324
- MIT License - feel free to use this in your projects!
556
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
557
+
558
+ ---
559
+
560
+ Made with ♥ by [misits](https://github.com/misits)