npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

advanced-filter-system

v1.8.0

Published

Advanced filtering system for DOM elements with multiple features

Readme

Advanced Filter System (AFS)

A flexible, dependency-free JavaScript library for filtering DOM elements — with search, sorting, range filters, pagination and URL state built in.

Live Demo · NPM · Documentation

Features

  • Filtering — buttons, checkboxes, radios and dropdowns, with OR / AND / mixed logic configurable per filter type
  • Search — debounced text search across any data attributes, with optional match highlighting
  • Sorting — by any data attribute (numbers, dates, strings auto-detected), multi-criteria, custom comparators, shuffle
  • Range filters — draggable sliders (with optional histogram), min/max number inputs, date ranges
  • Pagination — page controls, items-per-page, smooth scroll-to-top, fully aware of active filters and sort order
  • URL state — the full filter state lives in the URL: shareable links, restored on load, updated via replaceState so it never floods browser history
  • Animations — fade, slide, scale, flip, rotate, zoom, bounce, blur and more
  • TypeScript — complete type definitions included

Installation

npm install advanced-filter-system

Or via CDN:

<script type="module">
  import { AFS } from 'https://unpkg.com/advanced-filter-system@latest/dist/afs.modern.js';
</script>

Quick start

A minimal, complete setup — filter buttons, search, counter and pagination:

<!-- Filter controls -->
<button class="btn-filter" data-filter="*">All</button>
<button class="btn-filter" data-filter="category:tech">Tech</button>
<button class="btn-filter" data-filter="category:design">Design</button>

<!-- Search and counter -->
<input type="text" class="filter-search" placeholder="Search…">
<div class="filter-counter"></div>

<!-- Items: data-categories holds space-separated "type:value" pairs -->
<div class="items-container">
  <div class="filter-item" data-categories="category:tech brand:apple"
       data-title="MacBook Pro" data-price="2499">
    MacBook Pro — $2,499
  </div>
  <div class="filter-item" data-categories="category:design brand:moleskine"
       data-title="Sketchbook" data-price="29">
    Sketchbook — $29
  </div>
</div>

<!-- Pagination controls are rendered in here -->
<div class="afs-pagination-container"></div>
import { AFS } from 'advanced-filter-system';

const afs = new AFS({
  containerSelector: '.items-container',   // required
  itemSelector: '.filter-item',            // required
  filterButtonSelector: '.btn-filter',
  searchInputSelector: '.filter-search',
  counterSelector: '.filter-counter',
  searchKeys: ['title', 'categories'],
  pagination: { enabled: true, itemsPerPage: 12 },
  animation: { type: 'fade', duration: 300 },
});
/* AFS toggles these two classes — style them however you like */
.btn-filter.active { background: #000; color: #fff; }
.filter-item.hidden { display: none !important; }

That's it. Clicking a filter button, typing in the search box or changing pages all update the items, the counter and the URL.

How filtering works

Every item declares its facets in data-categories, as space-separated type:value pairs:

<div class="filter-item" data-categories="category:tech brand:apple color:silver">

Filter controls target those pairs through data-filter:

| data-filter value | Meaning | |---|---| | category:tech | Toggle this filter | | * | Reset — show everything | | category:* | Clear every active category: filter |

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:

const afs = new AFS({
  filterCategoryMode: 'mixed',
  filterTypeLogic: {
    category: { mode: 'OR', multi: true },  // multi-select (checkbox-style)
    brand: 'OR',                            // exclusive (one at a time)
    tags: 'AND',                            // items must match all selected
  },
});

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.

Documentation

| Module | Covers | |---|---| | Filter | Buttons, checkboxes, radios, dropdowns, logic modes, filter groups | | Search | Text search, debouncing, highlighting | | Sort | Sort buttons, multi-criteria, custom comparators, shuffle | | Pagination | Page controls, items-per-page, scroll-to-top | | Range Filter | Slider with optional histogram (numbers or dates) | | Input Range Filter | Min/max number inputs | | Date Filter | Date range pickers | | URL Manager | URL parameters, shareable state, history |

Common options

All options with their defaults live in src/core/Options.js. The ones you'll touch most:

const afs = new AFS({
  // Selectors (containerSelector and itemSelector are required)
  containerSelector: '.afs-filter-container',
  itemSelector: '.afs-filter-item',
  filterButtonSelector: '.afs-btn-filter',
  filterDropdownSelector: '.afs-filter-dropdown',
  searchInputSelector: '.afs-filter-search',
  counterSelector: '.afs-filter-counter',
  sortButtonSelector: '.afs-btn-sort',

  // CSS classes AFS toggles
  activeClass: 'active',
  hiddenClass: 'hidden',
  activeSortClass: 'sort-active',

  // Filter logic
  filterCategoryMode: 'mixed',   // 'mixed' | 'OR' | 'AND'
  filterTypeLogic: {},           // per-type config, see above

  // Search
  searchKeys: ['title'],
  debounceTime: 300,

  // Pagination (disabled by default)
  pagination: {
    enabled: false,
    itemsPerPage: 10,
    container: '.afs-pagination-container',
    showPrevNext: true,
    scrollToTop: false,          // scrolls back to the top of the items list
    scrollOffset: 50,
    scrollBehavior: 'smooth',    // 'smooth' | 'auto'
  },

  // Counter
  counter: {
    template: 'Showing {visible} of {total}',
    showFiltered: true,
    filteredTemplate: '({filtered} filtered)',
    noResultsTemplate: 'No items found',
  },

  // Animations
  animation: { type: 'fade', duration: 300 },

  // Misc
  debug: false,                  // log to console
  preserveState: false,          // persist state in sessionStorage across tab switches
});

API at a glance

Each feature lives on the instance: afs.filter, afs.search, afs.sort, afs.pagination, afs.rangeFilter, afs.inputRangeFilter, afs.dateFilter, afs.urlManager.

// Filtering
afs.filter.addFilter('category:tech');
afs.filter.removeFilter('category:tech');
afs.filter.clearAllFilters();                 // filters + search + dropdowns + checkboxes

// Search
afs.search.setValue('macbook');
afs.search.clearSearch();

// Sorting
afs.sort.sort('price', 'desc');
afs.sort.shuffle();
afs.sort.reset();

// Pagination
afs.pagination.goToPage(2);
afs.pagination.nextPage();
afs.pagination.setItemsPerPage(24);
afs.pagination.getPageInfo();                 // { currentPage, itemsPerPage, totalPages }

// Range widgets (containers are DOM elements)
afs.rangeFilter.addRangeSlider({
  key: 'price', type: 'number',
  container: document.querySelector('.price-slider'),
  min: 0, max: 1000, step: 10,
  ui: { showHistogram: true, bins: 12 },
});
afs.inputRangeFilter.addInputRange({ key: 'rating', container: el, min: 0, max: 5, step: 0.5 });
afs.dateFilter.addDateRange({ key: 'date', container: el });

// Lifecycle
afs.refresh();                                // re-scan items (after DOM changes)
afs.destroy();

Events

afs.on('filtersApplied', ({ activeFilters, visibleItems }) => { /* … */ });
afs.on('search', ({ query, matches, total }) => { /* … */ });
afs.on('sort', ({ key, direction }) => { /* … */ });
afs.on('pageChanged', ({ currentPage, totalPages }) => { /* … */ });
afs.on('filtersCleared', () => { /* … */ });
afs.on('urlStateLoaded', ({ params }) => { /* … */ });

on, once, off, removeAllListeners are available. Each module's documentation lists its events and payloads.

TypeScript

Type definitions ship with the package:

import { AFS, AFSOptions, FilterTypeLogic } from 'advanced-filter-system';

const logic: FilterTypeLogic = {
  category: { mode: 'OR', multi: true },
  brand: 'OR',
};

const afs = new AFS({
  containerSelector: '#items',
  itemSelector: '.item',
  filterTypeLogic: logic,
});

Browser support

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.

Development

git clone https://github.com/misits/advanced-filter-system.git
cd advanced-filter-system
npm install

npm test             # jest test suite
npm run build        # build dist/ (development)
npm run build:prod   # minified production build

# Try the demo (imports ../dist/afs.modern.js, so build first)
npm run build && npx serve .
# then open http://localhost:3000/examples/demo.html

License

MIT — see LICENSE.


Made with ♥ by misits