advanced-filter-system 1.0.6 → 1.0.7
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 +446 -208
- package/dist/AFS.esm.js +4484 -759
- package/dist/AFS.esm.js.map +1 -1
- package/dist/AFS.js +4486 -760
- package/dist/AFS.js.map +1 -1
- package/dist/AFS.min.js +1 -1
- package/dist/AFS.min.js.map +1 -1
- package/package.json +1 -1
package/dist/AFS.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AFS.min.js","sources":["../src/AFS.js"],"sourcesContent":["/**\n * @fileoverview Advanced Filter System for DOM elements\n * @version 1.0.6\n *\n * A flexible and customizable filtering system that supports:\n * - Multiple filtering modes (OR/AND)\n * - Text search with debouncing\n * - Multiple sorting criteria\n * - Range filtering\n * - URL state management\n * - Animation and transitions\n * - Results counter\n */\n\n/**\n * Utility function for debouncing\n * @param {Function} func - Function to debounce\n * @param {number} wait - Delay in milliseconds\n * @returns {Function} Debounced function\n */\nfunction debounce(func, wait) {\n let timeout;\n return function executedFunction(...args) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n}\n\nclass AFS {\n /**\n * @typedef {Object} FilterOptions\n * @property {string} containerSelector - Main container selector\n * @property {string} itemSelector - Items to filter selector\n * @property {string} filterButtonSelector - Filter buttons selector\n * @property {string} [searchInputSelector] - Search input selector\n * @property {string} [counterSelector] - Results counter selector\n * @property {string} [activeClass='active'] - Active state class\n * @property {string} [hiddenClass='hidden'] - Hidden state class\n * @property {number} [animationDuration=300] - Animation duration in ms\n * @property {string} [filterMode='OR'] - Filter mode ('OR' or 'AND')\n * @property {string[]} [searchKeys=['title']] - Data attributes to search in\n * @property {number} [debounceTime=300] - Search debounce delay in ms\n */\n\n /**\n * @param {FilterOptions} options - Filter configuration options\n */\n constructor(options = {}) {\n this.options = {\n containerSelector: \".filter-container\",\n itemSelector: \".filter-item\",\n filterButtonSelector: \".btn-filter\",\n searchInputSelector: \".filter-search\",\n counterSelector: \".filter-counter\",\n activeClass: \"active\",\n hiddenClass: \"hidden\",\n animationDuration: 300,\n filterMode: \"OR\",\n searchKeys: [\"title\"],\n debounceTime: 300,\n debug: false,\n logLevel: 'info',\n ...options,\n };\n\n // Define logging levels hierarchy\n this.logLevels = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3\n };\n\n // Initialize elements\n this.container = document.querySelector(this.options.containerSelector);\n this.items = document.querySelectorAll(this.options.itemSelector);\n this.sortOrders = {};\n this.filterButtons = document.querySelectorAll(\n this.options.filterButtonSelector,\n );\n this.searchInput = document.querySelector(this.options.searchInputSelector);\n this.counter = document.querySelector(this.options.counterSelector);\n\n // Initialize state\n this.currentFilters = new Set([\"*\"]);\n this.currentSearch = \"\";\n this.visibleItems = new Set(this.items);\n this.filterGroups = new Map();\n this.groupMode = \"OR\"; // Default group mode\n\n this.log('debug', 'Initializing AFS with options:', this.options);\n this.init();\n }\n\n /**\n * Internal logging method\n * Handles debug message output based on current log level\n * \n * @private\n * @param {string} level - Log level ('error', 'warn', 'info', 'debug')\n * @param {...any} args - Arguments to log\n */\n log(level, ...args) {\n if (!this.options.debug) return;\n \n const currentLevelValue = this.logLevels[this.options.logLevel];\n const messageLevel = this.logLevels[level];\n\n if (messageLevel <= currentLevelValue) {\n const timestamp = new Date().toISOString();\n const prefix = `[AFS ${level.toUpperCase()}] ${timestamp}`;\n\n switch (level) {\n case 'error':\n console.error(prefix, ...args);\n break;\n case 'warn':\n console.warn(prefix, ...args);\n break;\n case 'info':\n console.info(prefix, ...args);\n break;\n case 'debug':\n console.debug(prefix, ...args);\n break;\n }\n }\n }\n\n /**\n * Configure debug mode settings\n * \n * @public\n * @param {boolean} enabled - Enable or disable debug mode\n * @param {string} [level='info'] - Log level ('error', 'warn', 'info', 'debug')\n */\n setDebugMode(enabled, level = 'info') {\n this.options.debug = enabled;\n if (this.logLevels.hasOwnProperty(level)) {\n this.options.logLevel = level;\n }\n this.log('info', `Debug mode ${enabled ? 'enabled' : 'disabled'} with level: ${level}`);\n }\n\n /**\n * Initialize the filter system\n * Sets up styles, events, and initial state\n * \n * @private\n */\n init() {\n this.log('debug', 'Starting initialization');\n \n if (!this.container) {\n this.log('error', `Container not found: ${this.options.containerSelector}`);\n return;\n }\n\n this.addStyles();\n this.bindEvents();\n this.loadFromURL();\n this.updateCounter();\n \n this.log('info', 'Initialization complete');\n }\n\n /**\n * Add required styles to document\n * @private\n */\n addStyles() {\n const styles = `\n .${this.options.hiddenClass} {\n display: none !important;\n }\n\n ${this.options.itemSelector} {\n opacity: 1;\n transform: scale(1);\n transition: opacity ${this.options.animationDuration}ms ease-out,\n transform ${this.options.animationDuration}ms ease-out;\n }\n\n ${this.options.filterButtonSelector} {\n opacity: 0.5;\n transition: opacity ${this.options.animationDuration}ms ease;\n }\n\n ${this.options.filterButtonSelector}.${this.options.activeClass} {\n opacity: 1;\n }\n `;\n\n const styleSheet = document.createElement(\"style\");\n styleSheet.textContent = styles;\n document.head.appendChild(styleSheet);\n this.log('debug', 'Styles added to document');\n }\n\n /**\n * Bind all event listeners\n * @private\n */\n bindEvents() {\n this.log('debug', 'Binding events');\n\n this.filterButtons.forEach((button) => {\n button.addEventListener(\"click\", () => this.handleFilterClick(button));\n });\n\n if (this.searchInput) {\n this.searchInput.addEventListener(\n \"input\",\n debounce((e) => {\n this.search(e.target.value);\n }, this.options.debounceTime),\n );\n }\n\n window.addEventListener(\"popstate\", () => this.loadFromURL());\n\n this.log('debug', 'Events bound successfully');\n }\n\n /**\n * Handle filter button clicks\n * @private\n * @param {HTMLElement} button - Clicked filter button\n */\n handleFilterClick(button) {\n const filterValue = button.dataset.filter;\n this.log('debug', 'Filter button clicked:', filterValue);\n\n if (filterValue === \"*\") {\n this.resetFilters();\n } else {\n this.toggleFilter(filterValue, button);\n }\n\n this.filter();\n this.updateURL();\n }\n\n /**\n * Reset all filters to default state\n * @private\n */\n resetFilters() {\n this.log('debug', 'Resetting filters');\n\n this.filterButtons.forEach((btn) =>\n btn.classList.remove(this.options.activeClass),\n );\n this.currentFilters.clear();\n this.currentFilters.add(\"*\");\n this.filterButtons[0].classList.add(this.options.activeClass);\n this.resetCounter();\n }\n\n /**\n * Reset visible items counter\n * @private\n */\n resetCounter() {\n this.visibleItems = new Set(this.items);\n this.updateCounter();\n }\n\n /**\n * Toggle individual filter state\n * @private\n * @param {string} filterValue - Filter value to toggle\n * @param {HTMLElement} button - Filter button element\n */\n toggleFilter(filterValue, button) {\n this.log('debug', `Toggling filter: ${filterValue}`);\n\n this.currentFilters.delete(\"*\");\n this.filterButtons[0].classList.remove(this.options.activeClass);\n\n if (button.classList.contains(this.options.activeClass)) {\n button.classList.remove(this.options.activeClass);\n this.currentFilters.delete(filterValue);\n\n // If no filters are selected, reset to default state and clear URL\n if (this.currentFilters.size === 0) {\n this.resetFilters();\n window.history.pushState({}, \"\", window.location.pathname);\n return;\n }\n } else {\n button.classList.add(this.options.activeClass);\n this.currentFilters.add(filterValue);\n }\n }\n\n /**\n * Sort items based on auto-detecting ASC or DESC for each key\n * @public\n * @param {string} key - The data attribute key to sort by (e.g., 'title', 'price', 'date')\n */\n sortWithOrder(key) {\n const items = [...this.items];\n\n // Check if the current sort order is ASC, default to ASC if undefined\n const currentOrder = this.sortOrders[key] || \"asc\";\n const newOrder = currentOrder === \"asc\" ? \"desc\" : \"asc\"; // Toggle order\n\n // Sort items based on the new order\n items.sort((a, b) => {\n let valueA = a.dataset[key];\n let valueB = b.dataset[key];\n\n // Check if values are numeric and convert them to numbers if they are\n const isNumeric = !isNaN(valueA) && !isNaN(valueB);\n if (isNumeric) {\n valueA = parseFloat(valueA);\n valueB = parseFloat(valueB);\n }\n\n if (newOrder === \"asc\") {\n return isNumeric ? valueA - valueB : valueA.localeCompare(valueB);\n } else {\n return isNumeric ? valueB - valueA : valueB.localeCompare(valueA);\n }\n });\n\n // Update the current sort order for the key\n this.sortOrders[key] = newOrder;\n\n // Reorder items in the DOM\n items.forEach((item) => this.container.appendChild(item));\n\n this.log('debug', `Sorting items by ${key} in ${newOrder} order`);\n }\n\n /**\n * Shuffle items randomly and display in the container\n * @public\n */\n shuffle() {\n const itemsArray = [...this.items];\n\n // Shuffle the itemsArray using Fisher-Yates algorithm\n for (let i = itemsArray.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [itemsArray[i], itemsArray[j]] = [itemsArray[j], itemsArray[i]];\n }\n\n // Re-append the shuffled items to the container\n itemsArray.forEach((item) => this.container.appendChild(item));\n\n this.log('debug', 'Shuffling items');\n }\n\n /**\n * Apply current filters to items\n * @public\n */\n /**\n * Apply current filters to items\n * @public\n */\n filter() {\n // Store the original filter logic\n const standardFilter = () => {\n this.log('debug', 'Applying filters');\n\n this.visibleItems.clear();\n\n this.items.forEach((item) => {\n if (this.currentFilters.has(\"*\")) {\n this.showItem(item);\n this.visibleItems.add(item);\n } else {\n const itemCategories = new Set(\n item.dataset.categories?.split(\" \") || [],\n );\n const matchesFilter =\n this.options.filterMode === \"OR\"\n ? this.matchesAnyFilter(itemCategories)\n : this.matchesAllFilters(itemCategories);\n\n if (matchesFilter) {\n this.showItem(item);\n this.visibleItems.add(item);\n } else {\n this.hideItem(item);\n }\n }\n });\n };\n\n // Check if we should use group filtering or standard filtering\n if (this.filterGroups.size === 0) {\n standardFilter();\n } else {\n this.visibleItems.clear();\n\n this.items.forEach((item) => {\n if (this.currentFilters.has(\"*\")) {\n this.showItem(item);\n this.visibleItems.add(item);\n } else {\n const itemCategories = new Set(\n item.dataset.categories?.split(\" \") || [],\n );\n const matchesGroups = this.matchesFilterGroups(itemCategories);\n\n if (matchesGroups) {\n this.showItem(item);\n this.visibleItems.add(item);\n } else {\n this.hideItem(item);\n }\n }\n });\n }\n\n setTimeout(() => {\n this.updateCounter();\n }, this.options.animationDuration);\n\n this.log('info', `Filter applied. Visible items: ${this.visibleItems.size}`);\n }\n\n /**\n * Add or update a filter group\n * @public\n * @param {string} groupId - Group identifier\n * @param {string[]} filters - Array of filter values\n * @param {string} [operator='OR'] - Operator within group ('AND' or 'OR')\n * @returns {boolean} Success status\n */\n addFilterGroup(groupId, filters, operator = \"OR\") {\n try {\n // Validate inputs\n if (!groupId || !Array.isArray(filters)) {\n this.log('error', 'Invalid group ID or filters');\n return false;\n }\n\n const validOperator = operator.toUpperCase();\n if (![\"AND\", \"OR\"].includes(validOperator)) {\n this.log('error', 'Invalid operator:', operator);\n operator = \"OR\";\n }\n\n // Create or update group\n this.filterGroups.set(groupId, {\n filters: new Set(filters),\n operator: validOperator,\n });\n\n // Only update if we have active groups\n if (this.filterGroups.size > 0) {\n this.updateFiltersFromGroups();\n this.filter();\n this.updateURL();\n }\n\n return true;\n } catch (error) {\n this.log('error', 'Error adding filter group:', error);\n return false;\n }\n }\n\n /**\n * Set how groups combine with each other\n * @public\n * @param {string} mode - Mode for combining groups ('AND' or 'OR')\n */\n setGroupMode(mode) {\n const validMode = mode.toUpperCase();\n if ([\"AND\", \"OR\"].includes(validMode)) {\n this.groupMode = validMode;\n if (this.filterGroups.size > 0) {\n this.filter();\n }\n }\n }\n\n /**\n * Remove a filter group\n * @public\n * @param {string} groupId - Group identifier\n * @returns {boolean} Success status\n */\n removeFilterGroup(groupId) {\n if (this.filterGroups.has(groupId)) {\n this.filterGroups.delete(groupId);\n\n // If no groups left, revert to normal filtering\n if (this.filterGroups.size === 0) {\n this.resetFilters();\n } else {\n this.updateFiltersFromGroups();\n }\n\n this.filter();\n this.updateURL();\n return true;\n }\n return false;\n }\n\n /**\n * Update filters based on groups\n * @private\n */\n updateFiltersFromGroups() {\n // Only process if we have groups\n if (this.filterGroups.size === 0) return;\n\n // Clear current filters except '*'\n if (!this.currentFilters.has(\"*\")) {\n this.currentFilters.clear();\n }\n\n // Combine all group filters\n for (const group of this.filterGroups.values()) {\n group.filters.forEach((filter) => {\n if (filter !== \"*\") {\n this.currentFilters.add(filter);\n }\n });\n }\n }\n\n /**\n * Check if item matches any active filter (OR mode)\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches any filter\n */\n matchesAnyFilter(itemCategories) {\n return [...this.currentFilters].some((filter) => {\n const [type, value] = filter.split(\":\");\n return itemCategories.has(`${type}:${value}`);\n });\n }\n\n /**\n * Check if item matches all active filters (AND mode)\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches all filters\n */\n matchesAllFilters(itemCategories) {\n return [...this.currentFilters].every((filter) => {\n const [type, value] = filter.split(\":\");\n return itemCategories.has(`${type}:${value}`);\n });\n }\n\n /**\n * Show an item with animation\n * @private\n * @param {HTMLElement} item - Item to show\n */\n showItem(item) {\n this.visibleItems.add(item);\n item.classList.remove(this.options.hiddenClass);\n item.style.opacity = \"0\";\n item.style.transform = \"scale(0.95)\";\n\n item.offsetHeight;\n\n requestAnimationFrame(() => {\n item.style.opacity = \"1\";\n item.style.transform = \"scale(1)\";\n });\n }\n\n /**\n * Hide an item with animation\n * @private\n * @param {HTMLElement} item - Item to hide\n */\n hideItem(item) {\n item.style.opacity = \"0\";\n item.style.transform = \"scale(0.95)\";\n\n setTimeout(() => {\n if (item.style.opacity === \"0\") {\n item.classList.add(this.options.hiddenClass);\n this.visibleItems.delete(item);\n }\n }, this.options.animationDuration);\n }\n\n /**\n * Search items by text\n * @public\n * @param {string} query - Search query\n */\n search(query) {\n this.log('debug', 'Performing search with query:', query);\n\n this.currentSearch = query.toLowerCase().trim();\n let matches = 0;\n\n this.items.forEach((item) => {\n const searchText = this.options.searchKeys\n .map((key) => item.dataset[key] || \"\")\n .join(\" \")\n .toLowerCase();\n\n const matchesSearch =\n this.currentSearch === \"\" || searchText.includes(this.currentSearch);\n\n if (matchesSearch) {\n this.showItem(item);\n matches++;\n } else {\n this.hideItem(item);\n }\n });\n\n this.updateURL();\n this.log('info', `Search complete. Found ${matches} matches`);\n\n setTimeout(() => {\n this.updateCounter();\n }, this.options.animationDuration);\n }\n\n /**\n * Sort items by multiple criteria\n * @public\n * @param {Array<{key: string, direction: string}>} criteria - Sort criteria\n */\n sortMultiple(criteria) {\n const items = [...this.items];\n\n items.sort((a, b) => {\n for (const criterion of criteria) {\n const valueA = a.dataset[criterion.key];\n const valueB = b.dataset[criterion.key];\n\n const comparison =\n criterion.direction === \"asc\"\n ? valueA.localeCompare(valueB)\n : valueB.localeCompare(valueA);\n\n if (comparison !== 0) return comparison;\n }\n return 0;\n });\n\n items.forEach((item) => this.container.appendChild(item));\n\n this.log('debug', 'Sorting items by multiple criteria:', criteria);\n }\n\n /**\n * Filter items by numeric range\n * @public\n * @param {string} key - Data attribute key\n * @param {number} min - Minimum value\n * @param {number} max - Maximum value\n */\n addRangeFilter(key, min, max) {\n this.items.forEach((item) => {\n const value = parseFloat(item.dataset[key]);\n const inRange = value >= min && value <= max;\n\n if (inRange) {\n this.showItem(item);\n } else {\n this.hideItem(item);\n }\n });\n\n setTimeout(() => {\n this.updateCounter();\n }, this.options.animationDuration);\n\n this.log('debug', `Filtering items by range: ${key} between ${min} and ${max}`);\n }\n\n /**\n * Check if item matches filter groups\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches the group filters\n */\n matchesFilterGroups(itemCategories) {\n const groupMatches = [...this.filterGroups.values()].map((group) => {\n const groupFilters = [...group.filters];\n if (groupFilters.length === 0) return true;\n\n return group.operator === \"OR\"\n ? groupFilters.some((filter) => itemCategories.has(filter))\n : groupFilters.every((filter) => itemCategories.has(filter));\n });\n\n return this.groupMode === \"OR\"\n ? groupMatches.some((matches) => matches)\n : groupMatches.every((matches) => matches);\n }\n\n /**\n * Update URL with current filter state\n * @private\n */\n updateURL() {\n this.log('debug', 'Updating URL');\n\n // If only \"*\" filter is active or no filters are active, clear the URL\n if (\n this.currentFilters.size === 0 ||\n (this.currentFilters.size === 1 && this.currentFilters.has(\"*\"))\n ) {\n window.history.pushState({}, \"\", window.location.pathname);\n return;\n }\n\n const params = new URLSearchParams(window.location.search);\n\n // Add groups to URL if they exist\n if (this.filterGroups.size > 0) {\n for (const [groupId, group] of this.filterGroups.entries()) {\n params.set(`group_${groupId}`, [...group.filters].join(\",\"));\n params.set(`groupOp_${groupId}`, group.operator.toLowerCase());\n }\n params.set(\"groupMode\", this.groupMode.toLowerCase());\n }\n\n // Separate filters by type\n const filtersByType = {};\n for (const filter of this.currentFilters) {\n if (filter !== \"*\") {\n const [type, value] = filter.split(\":\");\n if (!filtersByType[type]) {\n filtersByType[type] = new Set();\n }\n filtersByType[type].add(value);\n }\n }\n\n // Add each filter type to the URL\n Object.entries(filtersByType).forEach(([type, values]) => {\n params.set(type, Array.from(values).join(\",\"));\n });\n\n if (this.currentSearch) {\n params.set(\"search\", this.currentSearch);\n }\n\n const newURL = `${window.location.pathname}${\n params.toString() ? \"?\" + params.toString() : \"\"\n }`;\n window.history.pushState({}, \"\", newURL);\n this.log('debug', 'URL updated:', newURL);\n }\n\n /**\n * Load filter state from URL\n * @private\n */\n loadFromURL() {\n this.log('debug', 'Loading state from URL');\n const params = new URLSearchParams(window.location.search);\n\n // Load groups if they exist\n this.filterGroups.clear();\n for (const [key, value] of params.entries()) {\n if (key.startsWith(\"group_\")) {\n const groupId = key.replace(\"group_\", \"\");\n const operator =\n params.get(`groupOp_${groupId}`)?.toUpperCase() || \"OR\";\n const filters = value.split(\",\");\n this.addFilterGroup(groupId, filters, operator);\n }\n }\n\n // Set group mode if present\n const groupMode = params.get(\"groupMode\")?.toUpperCase();\n if (groupMode && [\"AND\", \"OR\"].includes(groupMode)) {\n this.groupMode = groupMode;\n }\n\n this.currentFilters.clear();\n\n // Si aucun filtre n'est présent, utiliser '*'\n let hasFilters = false;\n\n // Parcourir tous les paramètres\n for (const [type, values] of params.entries()) {\n if (type !== \"search\") {\n hasFilters = true;\n values.split(\",\").forEach((value) => {\n this.currentFilters.add(`${type}:${value}`);\n });\n }\n }\n\n if (!hasFilters) {\n this.currentFilters.add(\"*\");\n }\n\n // Update active buttons\n this.filterButtons.forEach((button) => {\n const filterValue = button.dataset.filter;\n if (\n this.currentFilters.has(filterValue) ||\n (filterValue === \"*\" && this.currentFilters.has(\"*\"))\n ) {\n button.classList.add(this.options.activeClass);\n } else {\n button.classList.remove(this.options.activeClass);\n }\n });\n\n // Load search\n const search = params.get(\"search\") || \"\";\n if (this.searchInput) {\n this.searchInput.value = search;\n }\n\n this.filter();\n if (search) {\n this.search(search);\n }\n\n this.log('info', 'State loaded from URL');\n }\n\n /**\n * Update results counter\n * @private\n * @returns {{total: number, visible: number}}\n */\n updateCounter() {\n const total = this.items.length;\n const visible = this.visibleItems.size;\n\n if (this.counter) {\n this.counter.textContent = `Showing ${visible} of ${total}`;\n }\n \n this.log('debug', `Counter updated: ${visible}/${total}`);\n return { total, visible };\n }\n\n /**\n * Set animation options\n * @public\n * @param {Object} options - Animation options\n */\n setAnimationOptions(options = {}) {\n this.options.animationDuration =\n options.duration || this.options.animationDuration;\n this.options.animationType = options.type || \"ease-out\";\n this.addStyles(); // Refresh styles with new options\n }\n\n /**\n * Event handling system\n */\n addEventSystem() {\n this.events = {};\n\n this.on = (eventName, callback) => {\n if (!this.events[eventName]) {\n this.events[eventName] = [];\n }\n this.events[eventName].push(callback);\n };\n\n this.emit = (eventName, data) => {\n if (this.events[eventName]) {\n this.events[eventName].forEach((callback) => callback(data));\n }\n };\n }\n\n /**\n * Add pagination\n * @public\n * @param {number} itemsPerPage - Number of items per page\n */\n setPagination(itemsPerPage) {\n this.pagination = {\n currentPage: 1,\n itemsPerPage: itemsPerPage,\n totalPages: Math.ceil(this.visibleItems.size / itemsPerPage),\n };\n this.updatePagination();\n }\n\n updatePagination() {\n const start =\n (this.pagination.currentPage - 1) * this.pagination.itemsPerPage;\n const end = start + this.pagination.itemsPerPage;\n\n [...this.visibleItems].forEach((item, index) => {\n if (index >= start && index < end) {\n this.showItem(item);\n } else {\n this.hideItem(item);\n }\n });\n }\n\n /**\n * Enable analytics tracking\n * @public\n * @param {Function} callback - Analytics callback function\n */\n enableAnalytics(callback) {\n this.analyticsCallback = callback;\n this.on(\"filter\", (data) => {\n this.analyticsCallback({\n type: \"filter\",\n filters: [...this.currentFilters],\n visibleItems: this.visibleItems.size,\n timestamp: new Date().toISOString(),\n });\n });\n }\n\n /**\n * Sort with custom comparator\n * @public\n * @param {string} key - Data attribute key\n * @param {Function} comparator - Custom comparison function\n */\n sortWithComparator(key, comparator) {\n const items = [...this.items];\n items.sort((a, b) => {\n const valueA = a.dataset[key];\n const valueB = b.dataset[key];\n return comparator(valueA, valueB);\n });\n items.forEach((item) => this.container.appendChild(item));\n }\n\n /**\n * Add responsive behavior\n * @public\n * @param {Object} breakpoints - Breakpoint configurations\n */\n setResponsiveOptions(breakpoints) {\n window.addEventListener(\n \"resize\",\n debounce(() => {\n const width = window.innerWidth;\n for (const [breakpoint, options] of Object.entries(breakpoints)) {\n if (width <= parseInt(breakpoint)) {\n Object.assign(this.options, options);\n this.filter();\n break;\n }\n }\n }, 250),\n );\n }\n\n /**\n * Enable keyboard navigation\n * @public\n */\n enableKeyboardNavigation() {\n document.addEventListener(\"keydown\", (e) => {\n if (\n e.key === \"Enter\" &&\n document.activeElement.classList.contains(\n this.options.filterButtonSelector.slice(1),\n )\n ) {\n document.activeElement.click();\n }\n });\n }\n\n /**\n * Export current filter state\n * @public\n * @returns {Object} Filter state\n */\n exportState() {\n return {\n filters: [...this.currentFilters],\n search: this.currentSearch,\n mode: this.options.filterMode,\n timestamp: new Date().toISOString(),\n };\n }\n\n /**\n * Import filter state\n * @public\n * @param {Object} state - Filter state to import\n */\n importState(state) {\n if (state.filters) {\n this.currentFilters = new Set(state.filters);\n this.currentSearch = state.search || \"\";\n this.options.filterMode = state.mode || \"OR\";\n this.filter();\n this.updateURL();\n }\n }\n\n /**\n * Save current filter state as preset\n * @public\n * @param {string} presetName - Name of the preset\n */\n savePreset(presetName) {\n const preset = {\n filters: [...this.currentFilters],\n search: this.currentSearch,\n mode: this.options.filterMode,\n };\n localStorage.setItem(`afs_preset_${presetName}`, JSON.stringify(preset));\n\n this.log('info', `Preset saved: ${presetName}`);\n }\n\n /**\n * Load filter preset\n * @public\n * @param {string} presetName - Name of the preset to load\n */\n loadPreset(presetName) {\n const preset = JSON.parse(localStorage.getItem(`afs_preset_${presetName}`));\n if (preset) {\n this.currentFilters = new Set(preset.filters);\n this.currentSearch = preset.search;\n this.options.filterMode = preset.mode;\n this.filter();\n this.updateURL();\n }\n }\n\n /**\n * Set filter logic mode (alias for setFilterMode)\n * @public\n * @param {string} logic - New filter logic ('AND' or 'OR')\n */\n setLogic(logic) {\n if (typeof logic === \"boolean\") {\n // Handle boolean input (true = AND, false = OR)\n this.options.filterMode = logic ? \"AND\" : \"OR\";\n this.filter();\n return;\n }\n\n const mode = logic.toUpperCase();\n if ([\"OR\", \"AND\"].includes(mode)) {\n this.options.filterMode = mode;\n this.filter();\n }\n }\n\n /**\n * Change filter mode\n * @public\n * @param {string} mode - New filter mode ('OR' or 'AND')\n */\n setFilterMode(mode) {\n if ([\"OR\", \"AND\"].includes(mode.toUpperCase())) {\n this.options.filterMode = mode.toUpperCase();\n this.filter();\n }\n }\n\n /**\n * Add filter by type and value\n * @public\n * @param {string} type - Filter type\n * @param {string} value - Filter value\n */\n addFilter(type, value) {\n this.currentFilters.add(`${type}:${value}`);\n this.filter();\n this.updateURL();\n }\n\n /**\n * Remove filter by type and value\n * @public\n * @param {string} type - Filter type\n */\n removeFilter(type, value) {\n this.currentFilters.delete(`${type}:${value}`);\n if (this.currentFilters.size === 0) {\n this.currentFilters.add(\"*\");\n }\n this.filter();\n this.updateURL();\n }\n\n /**\n * Get active filters by type\n * @public\n * @param {string} type - Filter type\n */\n getActiveFiltersByType(type) {\n return [...this.currentFilters]\n .filter((filter) => filter.startsWith(`${type}:`))\n .map((filter) => filter.split(\":\")[1]);\n }\n\n /**\n * Clear all filters, url and search\n *\n * @public\n */\n clearAllFilters() {\n this.currentFilters.clear();\n this.currentFilters.add(\"*\");\n this.filter();\n this.updateURL();\n\n // Uncheck all checkboxes if any with activeClass\n const checkboxes = document.querySelectorAll('input[type=\"checkbox\"]');\n checkboxes.forEach((checkbox) => {\n if (checkbox.classList.contains(this.options.activeClass)) {\n checkbox.checked = false;\n checkbox.classList.remove(this.options.activeClass);\n }\n });\n\n // Clear active on buttons\n this.filterButtons.forEach((btn) => {\n btn.classList.remove(this.options.activeClass);\n });\n\n // Clear search input\n if (this.searchInput) {\n this.searchInput.value = \"\";\n }\n\n this.log('info', 'All filters cleared');\n }\n}\n\nexport { AFS };\n"],"names":["debounce","func","wait","timeout","_len","arguments","length","args","Array","_key","clearTimeout","setTimeout","later","constructor","options","undefined","this","containerSelector","itemSelector","filterButtonSelector","searchInputSelector","counterSelector","activeClass","hiddenClass","animationDuration","filterMode","searchKeys","debounceTime","debug","logLevel","logLevels","error","warn","info","container","document","querySelector","items","querySelectorAll","sortOrders","filterButtons","searchInput","counter","currentFilters","Set","currentSearch","visibleItems","filterGroups","Map","groupMode","log","init","level","currentLevelValue","timestamp","Date","toISOString","prefix","toUpperCase","_len2","_key2","console","setDebugMode","enabled","hasOwnProperty","addStyles","bindEvents","loadFromURL","updateCounter","styles","styleSheet","createElement","textContent","head","appendChild","forEach","button","addEventListener","handleFilterClick","e","search","target","value","window","filterValue","dataset","filter","resetFilters","toggleFilter","updateURL","btn","classList","remove","clear","add","resetCounter","delete","contains","size","history","pushState","location","pathname","sortWithOrder","key","newOrder","sort","a","b","valueA","valueB","isNumeric","isNaN","parseFloat","localeCompare","item","shuffle","itemsArray","i","j","Math","floor","random","standardFilter","has","showItem","itemCategories","categories","split","matchesAnyFilter","matchesAllFilters","hideItem","matchesFilterGroups","addFilterGroup","groupId","filters","operator","isArray","validOperator","includes","set","updateFiltersFromGroups","setGroupMode","mode","validMode","removeFilterGroup","group","values","some","type","every","style","opacity","transform","offsetHeight","requestAnimationFrame","query","toLowerCase","trim","matches","searchText","map","join","sortMultiple","criteria","criterion","comparison","direction","addRangeFilter","min","max","groupMatches","groupFilters","params","URLSearchParams","entries","filtersByType","Object","_ref","from","newURL","toString","startsWith","replace","get","hasFilters","total","visible","setAnimationOptions","duration","animationType","addEventSystem","events","on","eventName","callback","push","emit","data","setPagination","itemsPerPage","pagination","currentPage","totalPages","ceil","updatePagination","start","end","index","enableAnalytics","analyticsCallback","sortWithComparator","comparator","setResponsiveOptions","breakpoints","width","innerWidth","breakpoint","parseInt","assign","enableKeyboardNavigation","activeElement","slice","click","exportState","importState","state","savePreset","presetName","preset","localStorage","setItem","JSON","stringify","loadPreset","parse","getItem","setLogic","logic","setFilterMode","addFilter","removeFilter","getActiveFiltersByType","clearAllFilters","checkbox","checked"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AFS.min.js","sources":["../src/core/Logger.js","../src/core/Options.js","../src/core/State.js","../src/styles/StyleManager.js","../src/core/EventEmitter.js","../src/styles/Animation.js","../src/features/Filter.js","../src/utils/index.js","../src/features/Search.js","../src/features/Sort.js","../src/features/Pagination.js","../src/features/URLManager.js","../src/features/RangeFilter.js","../src/features/DateFilter.js","../src/AFS.js"],"sourcesContent":["/**\n * @fileoverview Logging system for AFS\n */\n\nexport class Logger {\n /**\n * @param {boolean} [debug=false] - Enable debug mode\n * @param {string} [logLevel='info'] - Logging level\n */\n constructor(debug = false, logLevel = 'info') {\n this.enabled = debug;\n this.level = logLevel;\n this.levels = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3\n };\n }\n\n /**\n * Internal log method\n * @private\n */\n _log(level, ...args) {\n if (!this.enabled) return;\n\n const currentLevelValue = this.levels[this.level];\n const messageLevel = this.levels[level];\n\n if (messageLevel <= currentLevelValue) {\n const timestamp = new Date().toISOString();\n const prefix = `[AFS ${level.toUpperCase()}] ${timestamp}`;\n\n switch (level) {\n case 'error':\n console.error(prefix, ...args);\n break;\n case 'warn':\n console.warn(prefix, ...args);\n break;\n case 'info':\n console.info(prefix, ...args);\n break;\n case 'debug':\n console.debug(prefix, ...args);\n break;\n }\n }\n }\n\n /**\n * Log error message\n * @public\n */\n error(...args) {\n this._log('error', ...args);\n }\n\n /**\n * Log warning message\n * @public\n */\n warn(...args) {\n this._log('warn', ...args);\n }\n\n /**\n * Log info message\n * @public\n */\n info(...args) {\n this._log('info', ...args);\n }\n\n /**\n * Log debug message\n * @public\n */\n debug(...args) {\n this._log('debug', ...args);\n }\n\n /**\n * Enable or disable debug mode\n * @public\n */\n setDebugMode(enabled, level = 'info') {\n this.enabled = enabled;\n if (this.levels.hasOwnProperty(level)) {\n this.level = level;\n }\n this._log('info', `Debug mode ${enabled ? 'enabled' : 'disabled'} with level: ${level}`);\n }\n}","/**\n * @fileoverview Configuration management for AFS\n */\n\nexport class Options {\n /**\n * @typedef {Object} AFSOptions\n * @property {string} containerSelector - Main container selector\n * @property {string} itemSelector - Items to filter selector\n * @property {string} filterButtonSelector - Filter buttons selector\n * @property {string} searchInputSelector - Search input selector\n * @property {string} counterSelector - Results counter selector\n * @property {string} activeClass - Active state class\n * @property {string} hiddenClass - Hidden state class\n * @property {number} animationDuration - Animation duration in ms\n * @property {string} filterMode - Filter mode ('OR' or 'AND')\n * @property {string[]} searchKeys - Data attributes to search in\n * @property {number} debounceTime - Search debounce delay in ms\n * @property {boolean} debug - Enable debug mode\n * @property {string} logLevel - Log level\n * @property {string} dateFormat - Date format\n * @property {Object} counter - Counter-related options\n * @property {Object} styles - Style-related options\n */\n\n /**\n * @type {AFSOptions}\n */\n static defaults = {\n // Selectors\n containerSelector: '.filter-container',\n itemSelector: '.filter-item',\n filterButtonSelector: '.btn-filter',\n searchInputSelector: '.filter-search',\n counterSelector: '.filter-counter',\n\n // Classes\n activeClass: 'active',\n hiddenClass: 'hidden',\n\n // Animation\n animationDuration: 300,\n animationType: 'fade',\n animationEasing: 'ease-out',\n\n // Filtering\n filterMode: 'OR',\n searchKeys: ['title'],\n debounceTime: 300,\n\n // Debug\n debug: false,\n logLevel: 'info',\n\n // Date handling\n dateFormat: 'YYYY-MM-DD',\n\n counter: {\n template: 'Showing {visible} of {total}',\n showFiltered: true,\n filteredTemplate: '({filtered} filtered)',\n noResultsTemplate: 'No items found',\n formatter: (num) => num.toLocaleString()\n },\n\n // Styles\n styles: {\n slider: {\n class: 'afs-range-slider',\n trackClass: 'afs-range-track',\n thumbClass: 'afs-range-thumb',\n valueClass: 'afs-range-value',\n selectedClass: 'afs-range-selected',\n // Add new UI options\n ui: {\n showHistogram: false,\n bins: 10 // Number of bins for histogram\n }\n },\n colors: {\n primary: '#000',\n background: '#e5e7eb',\n text: '#000',\n histogram: '#e5e7eb', // For histogram bars\n histogramActive: '#000' // For active histogram bars\n }\n },\n\n // Pagination\n pagination: {\n enabled: false,\n itemsPerPage: 10,\n container: '.afs-pagination-container',\n pageButtonClass: 'afs-page-button',\n activePageClass: 'afs-page-active',\n containerClass: 'afs-pagination',\n scrollToTop: false,\n scrollOffset: 50,\n scrollBehavior: 'smooth', // or 'auto' for instant scroll\n }\n };\n\n constructor(userOptions = {}) {\n this.options = this.mergeOptions(Options.defaults, userOptions);\n this.initializeStyles();\n this.validate();\n }\n\n /**\n * Initialize styles with defaults\n * @private\n */\n initializeStyles() {\n const defaultStyles = Options.defaults.styles;\n const currentStyles = this.options.styles || {};\n\n this.options.styles = this.mergeOptions(defaultStyles, currentStyles);\n\n // Ensure colors object exists and has all required properties\n this.options.styles.colors = {\n ...defaultStyles.colors,\n ...(currentStyles.colors || {})\n };\n}\n\n /**\n * Deep merge options\n * @private\n * @param {Object} target - Target object\n * @param {Object} source - Source object\n * @returns {Object} Merged options\n */\n mergeOptions(target, source) {\n const result = { ...target };\n \n for (const key in source) {\n if (source[key] !== null && typeof source[key] === 'object' && !Array.isArray(source[key])) {\n // If the key doesn't exist in target or isn't an object, create/override it\n if (!target[key] || typeof target[key] !== 'object') {\n result[key] = {};\n }\n // Recursively merge nested objects\n result[key] = this.mergeOptions(result[key], source[key]);\n } else if (source[key] !== undefined) {\n // Only override if the source value is defined\n result[key] = source[key];\n }\n }\n \n return result;\n }\n\n /**\n * Validate options\n * @private\n * @throws {Error} If options are invalid\n */\n validate() {\n // Required selectors\n const requiredSelectors = ['containerSelector', 'itemSelector'];\n for (const selector of requiredSelectors) {\n if (typeof this.options[selector] !== 'string') {\n throw new Error(`${selector} must be a string`);\n }\n }\n\n // Animation duration\n if (typeof this.options.animationDuration !== 'number' || this.options.animationDuration < 0) {\n throw new Error('animationDuration must be a positive number');\n }\n\n // Filter mode\n if (!['OR', 'AND'].includes(this.options.filterMode.toUpperCase())) {\n throw new Error('filterMode must be either \"OR\" or \"AND\"');\n }\n\n // Search keys\n if (!Array.isArray(this.options.searchKeys) || this.options.searchKeys.length === 0) {\n throw new Error('searchKeys must be a non-empty array');\n }\n\n // Counter validation\n if (this.options.counter) {\n if (typeof this.options.counter.template !== 'string') {\n throw new Error('counter.template must be a string');\n }\n if (typeof this.options.counter.showFiltered !== 'boolean') {\n this.options.counter.showFiltered = true; // Set default\n }\n if (typeof this.options.counter.formatter !== 'function') {\n this.options.counter.formatter = (num) => num.toLocaleString(); // Set default\n }\n } else {\n this.options.counter = { ...Options.defaults.counter }; // Set defaults if missing\n }\n }\n\n /**\n * Get option value\n * @param {string} path - Dot notation path to option\n * @returns {any} Option value\n */\n get(path) {\n return path.split('.').reduce((obj, key) => obj?.[key], this.options);\n }\n\n /**\n * Set option value\n * @param {string} path - Dot notation path to option\n * @param {any} value - New value\n */\n set(path, value) {\n const parts = path.split('.');\n const last = parts.pop();\n const target = parts.reduce((obj, key) => {\n if (!(key in obj)) obj[key] = {};\n return obj[key];\n }, this.options);\n\n target[last] = value;\n this.validate();\n }\n\n /**\n * Update multiple options\n * @param {Object} updates - Options to update\n */\n update(updates) {\n this.options = this.mergeOptions(this.options, updates);\n this.validate();\n }\n\n /**\n * Reset options to defaults\n */\n reset() {\n this.options = { ...Options.defaults };\n }\n\n /**\n * Export options\n * @returns {Object} Current options\n */\n export() {\n return { ...this.options };\n }\n}","/**\n * @fileoverview State management for AFS\n */\n\nexport class State {\n constructor() {\n this.state = {\n filters: {\n current: new Set(['*']),\n groups: new Map(),\n ranges: new Map(),\n dateRanges: new Map(),\n mode: 'OR',\n groupMode: 'OR'\n },\n search: {\n query: '',\n keys: ['title']\n },\n sort: {\n orders: {},\n current: null\n },\n items: {\n visible: new Set(),\n total: 0\n },\n pagination: {\n currentPage: 1,\n itemsPerPage: 10,\n totalPages: 0\n }\n };\n }\n\n /**\n * Get current state\n * @returns {Object} Current state\n */\n getState() {\n return this.state;\n }\n\n /**\n * Update state\n * @param {string} path - Dot notation path to update\n * @param {any} value - New value\n */\n setState(path, value) {\n const parts = path.split('.');\n let current = this.state;\n \n for (let i = 0; i < parts.length - 1; i++) {\n if (!(parts[i] in current)) {\n current[parts[i]] = {};\n }\n current = current[parts[i]];\n }\n \n current[parts[parts.length - 1]] = value;\n }\n\n /**\n * Export state\n * @returns {Object} Exportable state\n */\n export() {\n return {\n filters: {\n current: Array.from(this.state.filters.current),\n groups: Array.from(this.state.filters.groups.entries()),\n ranges: Array.from(this.state.filters.ranges.entries()),\n dateRanges: Array.from(this.state.filters.dateRanges.entries()),\n mode: this.state.filters.mode,\n groupMode: this.state.filters.groupMode\n },\n search: { ...this.state.search },\n sort: { ...this.state.sort },\n pagination: { ...this.state.pagination }\n };\n }\n\n /**\n * Import state\n * @param {Object} importedState - State to import\n */\n import(importedState) {\n if (importedState.filters) {\n this.state.filters.current = new Set(importedState.filters.current);\n this.state.filters.groups = new Map(importedState.filters.groups);\n this.state.filters.ranges = new Map(importedState.filters.ranges);\n this.state.filters.dateRanges = new Map(importedState.filters.dateRanges);\n this.state.filters.mode = importedState.filters.mode;\n this.state.filters.groupMode = importedState.filters.groupMode;\n }\n\n if (importedState.search) {\n this.state.search = { ...importedState.search };\n }\n\n if (importedState.sort) {\n this.state.sort = { ...importedState.sort };\n }\n\n if (importedState.pagination) {\n this.state.pagination = { ...importedState.pagination };\n }\n }\n\n /**\n * Reset state to initial values\n */\n reset() {\n this.state = {\n filters: {\n current: new Set(['*']),\n groups: new Map(),\n ranges: new Map(),\n dateRanges: new Map(),\n mode: 'OR',\n groupMode: 'OR'\n },\n search: {\n query: '',\n keys: ['title']\n },\n sort: {\n orders: {},\n current: null\n },\n items: {\n visible: new Set(),\n total: 0\n },\n pagination: {\n currentPage: 1,\n itemsPerPage: 10,\n totalPages: 0\n }\n };\n }\n}","/**\n * @fileoverview Style management for AFS\n */\n\nexport class StyleManager {\n /**\n * @param {import('../core/Options').Options} options - Options instance\n */\n constructor(options) {\n this.options = options;\n this.styleElement = null;\n this.defaultStyles = {\n slider: {\n class: \"afs-range-slider\",\n trackClass: \"afs-range-track\",\n thumbClass: \"afs-range-thumb\",\n valueClass: \"afs-range-value\",\n selectedClass: \"afs-range-selected\",\n },\n colors: {\n primary: \"#000\",\n background: \"#ddd\",\n text: \"#000\",\n },\n animation: {\n duration: \"300ms\",\n type: \"ease-out\",\n },\n };\n }\n\n /**\n * Create base styles\n * @private\n * @returns {string} CSS styles\n */\n createBaseStyles() {\n const hiddenClass = this.options.get(\"hiddenClass\") || \"hidden\";\n const itemSelector = this.options.get(\"itemSelector\") || \".filter-item\";\n const filterButtonSelector = this.options.get(\"filterButtonSelector\") || \".btn-filter\";\n const activeClass = this.options.get(\"activeClass\") || \"active\";\n const animationDuration = this.options.get(\"animationDuration\") || '300ms';\n const animationEasing = this.options.get(\"animationEasing\") || 'ease-out';\n \n return `\n .${hiddenClass} {\n display: none !important;\n }\n\n ${itemSelector} {\n opacity: 1;\n transform: scale(1);\n filter: blur(0);\n transition: opacity ${animationDuration} ${animationEasing},\n transform ${animationDuration} ${animationEasing},\n filter ${animationDuration} ${animationEasing};\n }\n\n ${itemSelector}.${hiddenClass} {\n opacity: 0;\n transform: scale(0.95);\n filter: blur(5px);\n }\n\n ${filterButtonSelector} {\n opacity: 0.5;\n transition: opacity ${animationDuration} ${animationEasing};\n }\n\n ${filterButtonSelector}.${activeClass} {\n opacity: 1;\n }\n `;\n}\n\n /**\n * Create range slider styles\n * @private\n * @returns {string} CSS styles\n */\n createRangeStyles() {\n const styles = this.options.get(\"styles\") || this.defaultStyles;\n const sliderStyles = styles.slider || this.defaultStyles.slider;\n const colors = styles.colors || this.defaultStyles.colors;\n\n return `\n /* Range Slider Styles */\n .${sliderStyles.class} {\n position: relative;\n width: auto;\n height: 40px;\n margin: 10px 0;\n padding: 0 8px;\n }\n\n .${sliderStyles.trackClass} {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 100%;\n height: 4px;\n background: ${colors.background};\n border-radius: 2px;\n }\n\n .${sliderStyles.thumbClass} {\n position: absolute;\n top: 50%;\n width: 16px;\n height: 16px;\n background: ${colors.primary};\n border-radius: 50%;\n transform: translate(-50%, -50%);\n cursor: pointer;\n z-index: 2;\n }\n\n .${sliderStyles.valueClass} {\n position: absolute;\n top: -20px;\n transform: translateX(-50%);\n font-size: 10px;\n color: ${colors.text};\n }\n\n .${sliderStyles.selectedClass} {\n position: absolute;\n height: 4px;\n background: ${colors.primary};\n top: 50%;\n transform: translateY(-50%);\n }\n\n /* Histogram Styles */\n .afs-histogram {\n position: absolute;\n bottom: 22px;\n left: 8px;\n right: 8px;\n height: 20px;\n display: flex;\n align-items: flex-end;\n gap: 1px;\n opacity: 0.5;\n }\n\n .afs-histogram-bar {\n flex: 1;\n background-color: ${colors.background};\n min-height: 4px;\n transition: background-color 0.2s ease;\n }\n\n .afs-histogram-bar.active {\n background-color: ${colors.primary};\n }\n `;\n }\n\n /**\n * Create date filter styles\n * @private\n * @returns {string} CSS styles\n */\n createDateStyles() {\n const colors = (this.options.get(\"styles\") || this.defaultStyles).colors;\n\n return `\n .afs-date-range-container {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 10px 0;\n }\n\n .afs-date-input-wrapper {\n flex: 1;\n }\n\n .afs-date-input-wrapper label {\n display: block;\n font-size: 0.875rem;\n color: ${colors.text};\n margin-bottom: 0.5rem;\n }\n\n .afs-date-input {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid ${colors.background};\n border-radius: 0.25rem;\n font-size: 0.875rem;\n color: ${colors.text};\n transition: border-color 0.2s ease;\n }\n\n .afs-date-input:focus {\n outline: none;\n border-color: ${colors.primary};\n }\n `;\n }\n\n /**\n * Apply all styles\n * @public\n */\n applyStyles() {\n try {\n const styles = `\n /* Base styles */\n ${this.createBaseStyles()}\n\n /* Range slider styles */\n ${this.createRangeStyles()}\n\n /* Date filter styles */\n ${this.createDateStyles()}\n\n /* Pagination styles */\n ${this.createPaginationStyles()}\n\n /* Search styles */\n ${this.createSearchStyles()}\n `;\n\n if (this.styleElement) {\n this.styleElement.textContent = styles;\n } else {\n this.styleElement = document.createElement(\"style\");\n this.styleElement.textContent = styles;\n document.head.appendChild(this.styleElement);\n }\n } catch (error) {\n console.error(\"Error applying styles:\", error);\n const fallbackStyles = this.createBaseStyles();\n if (this.styleElement) {\n this.styleElement.textContent = fallbackStyles;\n } else {\n this.styleElement = document.createElement(\"style\");\n this.styleElement.textContent = fallbackStyles;\n document.head.appendChild(this.styleElement);\n }\n }\n }\n\n /**\n * Create pagination styles\n * @private\n * @returns {string} CSS styles\n */\n createPaginationStyles() {\n const paginationOptions = this.options.get(\"pagination\") || {};\n const colors = (this.options.get(\"styles\") || this.defaultStyles).colors;\n\n const containerClass = paginationOptions.containerClass || \"afs-pagination\";\n const buttonClass = paginationOptions.pageButtonClass || \"afs-page-button\";\n const activeClass = paginationOptions.activePageClass || \"afs-page-active\";\n\n return `\n .${containerClass} {\n display: flex;\n justify-content: center;\n gap: 8px;\n margin-top: 20px;\n }\n\n .${buttonClass} {\n padding: 8px 12px;\n border: 1px solid ${colors.primary};\n border-radius: 4px;\n cursor: pointer;\n transition: all 200ms ease-out;\n background: transparent;\n color: ${colors.primary};\n }\n\n .${buttonClass}:hover {\n background: ${colors.primary};\n color: white;\n }\n\n .${buttonClass}.${activeClass} {\n background: ${colors.primary};\n color: white;\n }\n\n .${buttonClass}:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `;\n }\n\n /**\n * Create search styles\n * @private\n * @returns {string} CSS styles\n */\n createSearchStyles() {\n const searchClass = this.options.get(\"searchInputClass\") || \"afs-search\";\n const colors = (this.options.get(\"styles\") || this.defaultStyles).colors;\n\n return `\n .${searchClass} {\n padding: 8px;\n border: 1px solid ${colors.background};\n border-radius: 4px;\n width: 100%;\n max-width: 300px;\n transition: border-color 200ms ease-out;\n }\n\n .${searchClass}:focus {\n outline: none;\n border-color: ${colors.primary};\n }\n `;\n }\n\n /**\n * Update styles\n * @public\n * @param {Object} newOptions - New style options\n */\n updateStyles(newOptions) {\n this.options = newOptions;\n this.applyStyles();\n }\n\n /**\n * Remove styles\n * @public\n */\n removeStyles() {\n if (this.styleElement) {\n this.styleElement.remove();\n this.styleElement = null;\n }\n }\n}\n","/**\n * @fileoverview Event handling system for AFS\n */\n\nexport class EventEmitter {\n constructor() {\n this.events = new Map();\n this.onceEvents = new Map();\n }\n\n /**\n * Subscribe to an event\n * @param {string} eventName - Name of the event\n * @param {Function} callback - Callback function\n * @returns {Function} Unsubscribe function\n */\n on(eventName, callback) {\n if (!this.events.has(eventName)) {\n this.events.set(eventName, new Set());\n }\n\n this.events.get(eventName).add(callback);\n\n // Return unsubscribe function\n return () => this.off(eventName, callback);\n }\n\n /**\n * Subscribe to an event once\n * @param {string} eventName - Name of the event\n * @param {Function} callback - Callback function\n * @returns {Function} Unsubscribe function\n */\n once(eventName, callback) {\n const onceWrapper = (...args) => {\n this.off(eventName, onceWrapper);\n callback.apply(this, args);\n };\n\n if (!this.onceEvents.has(eventName)) {\n this.onceEvents.set(eventName, new Map());\n }\n\n this.onceEvents.get(eventName).set(callback, onceWrapper);\n return this.on(eventName, onceWrapper);\n }\n\n /**\n * Unsubscribe from an event\n * @param {string} eventName - Name of the event\n * @param {Function} callback - Callback function\n */\n off(eventName, callback) {\n // Remove from regular events\n if (this.events.has(eventName)) {\n this.events.get(eventName).delete(callback);\n\n // Cleanup if no more listeners\n if (this.events.get(eventName).size === 0) {\n this.events.delete(eventName);\n }\n }\n\n // Remove from once events\n if (this.onceEvents.has(eventName)) {\n const onceWrapper = this.onceEvents.get(eventName).get(callback);\n if (onceWrapper) {\n this.events.get(eventName)?.delete(onceWrapper);\n this.onceEvents.get(eventName).delete(callback);\n }\n\n // Cleanup if no more once listeners\n if (this.onceEvents.get(eventName).size === 0) {\n this.onceEvents.delete(eventName);\n }\n }\n }\n\n /**\n * Emit an event\n * @param {string} eventName - Name of the event\n * @param {...any} args - Arguments to pass to callbacks\n */\n emit(eventName, ...args) {\n if (this.events.has(eventName)) {\n this.events.get(eventName).forEach(callback => {\n try {\n callback.apply(this, args);\n } catch (error) {\n console.error(`Error in event handler for ${eventName}:`, error);\n }\n });\n }\n }\n\n /**\n * Remove all event listeners\n * @param {string} [eventName] - Optional event name to clear specific event\n */\n removeAllListeners(eventName) {\n if (eventName) {\n this.events.delete(eventName);\n this.onceEvents.delete(eventName);\n } else {\n this.events.clear();\n this.onceEvents.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event\n * @param {string} eventName - Name of the event\n * @returns {number} Number of listeners\n */\n listenerCount(eventName) {\n return (this.events.get(eventName)?.size || 0) + \n (this.onceEvents.get(eventName)?.size || 0);\n }\n}","/**\n * @fileoverview Animation management for AFS\n */\n\nexport class Animation {\n constructor(afs) {\n this.afs = afs;\n this.options = this.afs.options;\n this.animations = {\n fade: {\n in: { opacity: 1, transform: 'scale(1)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'scale(0.95)', transitionTimingFunction: 'ease-out' },\n },\n slide: {\n in: { opacity: 1, transform: 'translateY(0)', transitionTimingFunction: 'ease-in-out' },\n out: { opacity: 0, transform: 'translateY(20px)', transitionTimingFunction: 'ease-in-out' },\n },\n scale: {\n in: { opacity: 1, transform: 'scale(1)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'scale(0.8)', transitionTimingFunction: 'ease-out' },\n },\n rotate: {\n in: { opacity: 1, transform: 'rotate(0deg) scale(1)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'rotate(90deg) scale(0.9)', transitionTimingFunction: 'ease-out' },\n },\n flip: {\n in: { opacity: 1, transform: 'rotateY(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'rotateY(180deg)', transitionTimingFunction: 'ease-out' },\n },\n zoom: {\n in: { opacity: 1, transform: 'scale(1.2)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'scale(0.8)', transitionTimingFunction: 'ease-out' },\n },\n bounce: {\n in: { opacity: 1, transform: 'translateY(0)', animation: 'bounce 1s cubic-bezier(0.68, -0.55, 0.27, 1.55)' },\n out: { opacity: 0, transform: 'translateY(-20px)', animation: 'bounceOut 1s ease-out' },\n },\n blur: {\n in: { opacity: 1, filter: 'blur(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, filter: 'blur(5px)', transitionTimingFunction: 'ease-out' },\n },\n skew: {\n in: { opacity: 1, transform: 'skew(0deg)', transitionTimingFunction: 'ease-in-out' },\n out: { opacity: 0, transform: 'skew(10deg)', transitionTimingFunction: 'ease-in-out' },\n },\n slideInLeft: {\n in: { opacity: 1, transform: 'translateX(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'translateX(-100%)', transitionTimingFunction: 'ease-out' },\n },\n slideInRight: {\n in: { opacity: 1, transform: 'translateX(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'translateX(100%)', transitionTimingFunction: 'ease-out' },\n },\n fadeInUp: {\n in: { opacity: 1, transform: 'translateY(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'translateY(10px)', transitionTimingFunction: 'ease-out' },\n },\n fadeInDown: {\n in: { opacity: 1, transform: 'translateY(0)', transitionTimingFunction: 'ease-in' },\n out: { opacity: 0, transform: 'translateY(-10px)', transitionTimingFunction: 'ease-out' },\n },\n bounceIn: {\n in: { opacity: 1, transform: 'scale(1.05)', transitionTimingFunction: 'cubic-bezier(0.68, -0.55, 0.27, 1.55)' },\n out: { opacity: 0, transform: 'scale(0.9)', transitionTimingFunction: 'ease-out' },\n },\n };\n }\n \n applyShowAnimation(item, animationType = 'fade') {\n const duration = this.options.get('animationDuration') || '300ms';\n const animation = this.animations[animationType]?.in || this.animations.fade.in;\n \n item.style.display = 'block';\n requestAnimationFrame(() => {\n Object.assign(item.style, animation, {\n transition: `opacity ${duration} ${animation.transitionTimingFunction}, transform ${duration} ${animation.transitionTimingFunction}`,\n });\n });\n }\n \n applyHideAnimation(item, animationType = 'fade') {\n const duration = this.options.get('animationDuration') || '300ms';\n const animation = this.animations[animationType]?.out || this.animations.fade.out;\n \n Object.assign(item.style, animation, {\n transition: `opacity ${duration} ${animation.transitionTimingFunction}, transform ${duration} ${animation.transitionTimingFunction}`,\n });\n\n const handleTransitionEnd = () => {\n item.style.display = 'none';\n item.removeEventListener('transitionend', handleTransitionEnd);\n };\n item.addEventListener('transitionend', handleTransitionEnd);\n }\n\n setAnimation(animationType) {\n this.afs.options.set('animationType', animationType);\n }\n}","/**\n * @fileoverview Filter functionality for AFS\n */\n\nimport { Animation } from '../styles/Animation.js';\n\nexport class Filter {\n /**\n * @param {import('../AFS').AFS} afs - Main AFS instance\n */\n constructor(afs) {\n this.afs = afs;\n this.animation = new Animation(afs);\n this.filterButtons = new Map();\n this.activeFilters = new Set([\"*\"]);\n this.currentFilters = new Set([\"*\"]);\n this.filterGroups = new Map();\n this.sortOrders = new Map();\n this.setupFilters();\n }\n\n /**\n * Setup filters\n * @private\n */\n setupFilters() {\n this.afs.logger.debug(\"Setting up filters\");\n const filterSelector = this.afs.options.get(\"filterButtonSelector\");\n if (!filterSelector) return;\n\n // Initialize filter buttons\n document.querySelectorAll(filterSelector).forEach((button) => {\n const filterValue = button.dataset.filter;\n if (!filterValue) {\n this.afs.logger.warn(\n \"Filter button missing data-filter attribute:\",\n button,\n );\n return;\n }\n\n this.filterButtons.set(button, filterValue);\n this.bindFilterEvent(button);\n });\n\n this.afs.logger.debug(\"Filters initialized\");\n }\n\n /**\n * Set filter logic mode\n * @public\n * @param {string|boolean} logic - 'AND'/'OR' or true/false (true = AND, false = OR)\n */\n setLogic(logic) {\n if (typeof logic === \"boolean\") {\n // Handle boolean input (true = AND, false = OR)\n this.afs.options.set(\"filterMode\", logic ? \"AND\" : \"OR\");\n } else {\n const mode = logic.toUpperCase();\n if ([\"OR\", \"AND\"].includes(mode)) {\n this.afs.options.set(\"filterMode\", mode);\n } else {\n this.afs.logger.warn(`Invalid filter mode: ${logic}`);\n return;\n }\n }\n\n this.afs.logger.debug(\n `Filter logic set to: ${this.afs.options.get(\"filterMode\")}`,\n );\n this.applyFilters();\n }\n\n /**\n * Clear all filters\n * @public\n */\n clearAllFilters() {\n this.afs.logger.debug(\"Clearing all filters\");\n\n // Reset filters\n this.activeFilters.clear();\n this.activeFilters.add(\"*\");\n\n // Reset filter buttons\n this.filterButtons.forEach((_, button) => {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n });\n\n // Reset filter groups\n this.filterGroups.clear();\n\n // Find and activate \"all\" button if exists\n const allButton = this.findAllButton();\n if (allButton) {\n allButton.classList.add(this.afs.options.get(\"activeClass\"));\n }\n\n // Clear sorting\n this.sortOrders.clear();\n\n // Apply changes and update UI\n this.applyFilters();\n this.afs.urlManager.updateURL();\n this.afs.emit(\"filtersCleared\");\n }\n\n /**\n * Bind filter event to button\n * @private\n * @param {HTMLElement} button - Filter button\n */\n bindFilterEvent(button) {\n this.afs.logger.debug(\"Binding filter event to button:\", button);\n\n button.addEventListener(\"click\", () => {\n const filterValue = this.filterButtons.get(button);\n\n if (!filterValue) return;\n\n if (filterValue === \"*\") {\n this.resetFilters();\n } else {\n this.toggleFilter(filterValue, button);\n }\n\n // Update the URL after filter change\n this.afs.urlManager.updateURL();\n });\n }\n\n /**\n * Reset filters to default state\n * @public\n */\n resetFilters() {\n this.afs.logger.debug(\"Resetting filters\");\n \n // Clear existing filters\n this.activeFilters.clear();\n \n // Reset button states\n this.filterButtons.forEach((_, button) => {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n });\n \n // Add \"*\" filter and activate \"all\" button\n this.activeFilters.add(\"*\");\n const allButton = this.findAllButton();\n if (allButton) {\n allButton.classList.add(this.afs.options.get(\"activeClass\"));\n }\n \n // Clear filter groups\n this.filterGroups.clear();\n \n // Force all items to be visible first\n const visibleItems = new Set(this.afs.items);\n this.afs.state.setState(\"items.visible\", visibleItems);\n \n // Show all items with animation\n this.afs.items.forEach(item => {\n item.classList.remove(this.afs.options.get('hiddenClass'));\n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(item, this.afs.options.get(\"animationType\"));\n });\n });\n \n // Update counter after reset\n this.afs.updateCounter();\n \n // Update URL after reset\n this.afs.urlManager.updateURL();\n\n // Emit event\n this.afs.emit(\"filtersReset\");\n }\n\n /**\n * Find \"all\" filter button\n * @private\n * @returns {HTMLElement|null} All button\n */\n findAllButton() {\n for (const [button, value] of this.filterButtons.entries()) {\n if (value === \"*\") return button;\n }\n\n return null;\n }\n\n handleFilterClick(button) {\n const filterValue = button.dataset.filter;\n this.afs.logger.debug(\"Filter clicked:\", filterValue);\n\n if (filterValue === \"*\") {\n this.resetFilters();\n } else {\n this.toggleFilter(filterValue, button);\n }\n\n this.filter();\n\n // Call updateURL to reflect the new filter state in the URL\n this.updateURL();\n }\n\n /**\n * Toggle filter state\n * @private\n * @param {string} filterValue - Filter value\n * @param {HTMLElement} button - Filter button\n */\n toggleFilter(filterValue, button) {\n // Remove \"all\" filter\n this.activeFilters.delete(\"*\");\n const allButton = this.findAllButton();\n if (allButton) {\n allButton.classList.remove(this.afs.options.get(\"activeClass\"));\n }\n\n // Toggle filter\n if (button.classList.contains(this.afs.options.get(\"activeClass\"))) {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n this.activeFilters.delete(filterValue);\n\n // Reset to \"all\" if no filters active\n if (this.activeFilters.size === 0) {\n this.resetFilters();\n return;\n }\n } else {\n button.classList.add(this.afs.options.get(\"activeClass\"));\n this.activeFilters.add(filterValue);\n }\n\n this.applyFilters();\n\n // Emit event\n this.afs.emit(\"filterToggled\", {\n filter: filterValue,\n activeFilters: Array.from(this.activeFilters),\n });\n\n this.afs.logger.debug(\"Filter toggled:\", filterValue);\n }\n\n /**\n * Apply current filters\n * @public\n */\n applyFilters() {\n // Log active filters\n const activeFilters = Array.from(this.activeFilters);\n this.afs.logger.debug(\"Active filters:\", activeFilters);\n this.afs.logger.debug(\"Applying filters\");\n\n const previouslyVisible = new Set(this.afs.state.getState().items.visible);\n const visibleItems = new Set();\n\n // First pass: determine which items should be visible\n this.afs.items.forEach(item => {\n if (this.activeFilters.has(\"*\") || this.itemMatchesFilters(item)) {\n visibleItems.add(item);\n }\n });\n\n // Update state with determined visible items\n this.afs.state.setState(\"items.visible\", visibleItems);\n\n // Second pass: apply animations based on visibility changes\n this.afs.items.forEach(item => {\n if (visibleItems.has(item)) {\n // Remove hidden class first\n item.classList.remove(this.afs.options.get('hiddenClass'));\n // Then apply show animation in next frame\n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(item, this.afs.options.get(\"animationType\"));\n });\n } else {\n // Apply hide animation\n requestAnimationFrame(() => {\n this.animation.applyHideAnimation(item, this.afs.options.get(\"animationType\"));\n });\n }\n });\n\n // Emit events and update UI\n this.emitFilterEvents(previouslyVisible, visibleItems);\n\n // Schedule UI updates\n requestAnimationFrame(() => {\n // Force reflow to ensure animations play\n this.afs.container.offsetHeight;\n\n // Update counter - this needs to happen after filter changes\n this.afs.updateCounter();\n \n // Update URL\n this.afs.urlManager.updateURL();\n\n // Emit final event\n this.afs.emit(\"filtersApplied\", {\n activeFilters,\n visibleItems: visibleItems.size,\n });\n });\n}\n\n /**\n * Check if item matches current filters\n * @private\n * @param {HTMLElement} item - DOM element\n * @returns {boolean} Whether item matches filters\n */\n itemMatchesFilters(item) {\n // Show all items if \"*\" is active\n if (this.activeFilters.has(\"*\")) {\n return true;\n }\n \n // Regular filter matching\n const itemCategories = new Set(item.dataset.categories?.split(\" \") || []);\n \n // If using filter groups\n if (this.filterGroups.size > 0) {\n return this.itemMatchesFilterGroups(itemCategories);\n }\n \n // Regular filtering\n return this.afs.options.get(\"filterMode\") === \"OR\"\n ? this.itemMatchesAnyFilter(itemCategories)\n : this.itemMatchesAllFilters(itemCategories);\n }\n\n /**\n * Check if item matches any active filter (OR mode)\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches any filter\n */\n itemMatchesAnyFilter(itemCategories) {\n return Array.from(this.activeFilters).some((filter) => {\n if (filter === \"*\") return true;\n return itemCategories.has(filter);\n });\n }\n\n /**\n * Check if item matches all active filters (AND mode)\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches all filters\n */\n itemMatchesAllFilters(itemCategories) {\n return Array.from(this.activeFilters).every((filter) => {\n if (filter === \"*\") return true;\n return itemCategories.has(filter);\n });\n }\n\n /**\n * Check if item matches filter groups\n * @private\n * @param {Set} itemCategories - Item's categories\n * @returns {boolean} Whether item matches groups\n */\n itemMatchesFilterGroups(itemCategories) {\n const groupMatches = Array.from(this.filterGroups.values()).map((group) => {\n if (group.filters.size === 0) return true;\n\n return group.operator === \"OR\"\n ? Array.from(group.filters).some((filter) => itemCategories.has(filter))\n : Array.from(group.filters).every((filter) =>\n itemCategories.has(filter),\n );\n });\n\n return this.afs.options.get(\"groupMode\") === \"OR\"\n ? groupMatches.some((matches) => matches)\n : groupMatches.every((matches) => matches);\n }\n\n /**\n * Emit filter-related events\n * @private\n * @param {Set} previouslyVisible - Previously visible items\n * @param {Set} nowVisible - Currently visible items\n */\n emitFilterEvents(previouslyVisible, nowVisible) {\n // Determine added and removed items\n const added = new Set(\n [...nowVisible].filter((item) => !previouslyVisible.has(item)),\n );\n const removed = new Set(\n [...previouslyVisible].filter((item) => !nowVisible.has(item)),\n );\n\n // Emit filter event\n this.afs.emit(\"filter\", {\n activeFilters: Array.from(this.activeFilters),\n visibleItems: nowVisible.size,\n added: added.size,\n removed: removed.size,\n });\n\n // Emit specific events for added/removed items\n if (added.size > 0) {\n this.afs.emit(\"itemsShown\", { items: added });\n }\n if (removed.size > 0) {\n this.afs.emit(\"itemsHidden\", { items: removed });\n }\n }\n\n /**\n * Add or update a filter group\n * @public\n * @param {string} groupId - Group identifier\n * @param {string[]} filters - Array of filter values\n * @param {string} [operator='OR'] - Operator within group\n */\n addFilterGroup(groupId, filters, operator = \"OR\") {\n this.afs.logger.debug(`Adding filter group: ${groupId}`);\n\n if (!Array.isArray(filters)) {\n this.afs.logger.error(\"Filters must be an array\");\n return;\n }\n\n const validOperator = operator.toUpperCase();\n if (![\"AND\", \"OR\"].includes(validOperator)) {\n this.afs.logger.warn(`Invalid operator: ${operator}, defaulting to OR`);\n operator = \"OR\";\n }\n\n this.filterGroups.set(groupId, {\n filters: new Set(filters),\n operator: validOperator,\n });\n\n this.applyFilters();\n }\n\n /**\n * Remove a filter group\n * @public\n * @param {string} groupId - Group identifier\n */\n removeFilterGroup(groupId) {\n if (this.filterGroups.delete(groupId)) {\n this.afs.logger.debug(`Removed filter group: ${groupId}`);\n\n if (this.filterGroups.size === 0) {\n this.resetFilters();\n } else {\n this.applyFilters();\n }\n }\n }\n\n /**\n * Set filter group mode\n * @public\n * @param {string} mode - Mode for combining groups\n */\n setGroupMode(mode) {\n const validMode = mode.toUpperCase();\n if ([\"AND\", \"OR\"].includes(validMode)) {\n this.afs.options.set(\"groupMode\", validMode);\n this.afs.logger.debug(`Set group mode to: ${validMode}`);\n this.applyFilters();\n } else {\n this.afs.logger.warn(`Invalid group mode: ${mode}`);\n }\n }\n\n /**\n * Add filter manually\n * @public\n * @param {string} filter - Filter value\n */\n addFilter(filter) {\n this.afs.logger.debug(`Adding filter: ${filter}`);\n\n if (filter === \"*\") {\n this.resetFilters();\n return;\n }\n\n this.activeFilters.delete(\"*\");\n this.activeFilters.add(filter);\n\n // Update button states\n this.filterButtons.forEach((value, button) => {\n if (value === filter) {\n button.classList.add(this.afs.options.get(\"activeClass\"));\n } else if (value === \"*\") {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n }\n });\n\n this.applyFilters();\n }\n\n /**\n * Remove filter manually\n * @public\n * @param {string} filter - Filter value\n */\n removeFilter(filter) {\n this.afs.logger.debug(`Removing filter: ${filter}`);\n\n this.activeFilters.delete(filter);\n\n // Update button states\n this.filterButtons.forEach((value, button) => {\n if (value === filter) {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n }\n });\n\n // Reset to all if no filters active\n if (this.activeFilters.size === 0) {\n this.resetFilters();\n } else {\n this.applyFilters();\n }\n }\n\n /**\n * Set filter mode\n * @public\n * @param {string} mode - Filter mode ('AND' or 'OR')\n */\n setFilterMode(mode) {\n this.afs.logger.debug(`Setting filter mode to: ${mode}`);\n\n const validMode = mode.toUpperCase();\n if ([\"AND\", \"OR\"].includes(validMode)) {\n this.afs.options.set(\"filterMode\", validMode);\n this.afs.logger.debug(`Set filter mode to: ${validMode}`);\n this.applyFilters();\n } else {\n this.afs.logger.warn(`Invalid filter mode: ${mode}`);\n }\n }\n\n /**\n * Get active filters\n * @public\n * @returns {Set} Active filters\n */\n getActiveFilters() {\n return new Set(this.activeFilters);\n }\n\n /**\n * Get filter groups\n * @public\n * @returns {Map} Filter groups\n */\n getFilterGroups() {\n return new Map(this.filterGroups);\n }\n\n /**\n * Add filter button dynamically\n * @public\n * @param {HTMLElement} button - Button element\n * @param {string} filter - Filter value\n */\n addFilterButton(button, filter) {\n if (!filter) {\n this.afs.logger.warn(\"Filter value required for new filter button\");\n return;\n }\n\n this.filterButtons.set(button, filter);\n this.bindFilterEvent(button);\n this.afs.logger.debug(`Added filter button for: ${filter}`);\n }\n\n /**\n * Remove filter button\n * @public\n * @param {HTMLElement} button - Button to remove\n */\n removeFilter(filter) {\n this.afs.logger.debug(`Removing filter: ${filter}`);\n\n this.activeFilters.delete(filter);\n\n // Update button states\n this.filterButtons.forEach((value, button) => {\n if (value === filter) {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n }\n });\n\n // Reset to all if no filters active\n if (this.activeFilters.size === 0) {\n this.resetFilters();\n } else {\n this.applyFilters();\n }\n }\n\n /**\n * Sort items with automatic order detection\n * @public\n * @param {string} key - The data attribute key to sort by\n */\n sortWithOrder(key) {\n this.afs.logger.debug(`Sorting by ${key}`);\n\n try {\n const items = Array.from(this.afs.items);\n\n // Toggle sort order for the key\n const currentOrder = this.sortOrders.get(key) || \"asc\";\n const newOrder = currentOrder === \"asc\" ? \"desc\" : \"asc\";\n this.sortOrders.set(key, newOrder);\n\n // Determine sort type from first item\n const sortType = this.determineSortType(items[0], key);\n\n // Sort items\n items.sort((a, b) => {\n const valueA = this.getSortValue(a, key, sortType);\n const valueB = this.getSortValue(b, key, sortType);\n\n return this.compareValues(valueA, valueB, newOrder);\n });\n\n // Reorder DOM elements\n this.reorderItems(items);\n\n // Emit event\n this.afs.emit(\"sort\", { key, order: newOrder });\n\n this.afs.logger.info(`Sorted items by ${key} in ${newOrder} order`);\n\n return newOrder; // Return the new order for UI updates\n } catch (error) {\n this.afs.logger.error(\"Sort error:\", error);\n return null;\n }\n }\n\n /**\n * Shuffle items randomly\n * @public\n */\n shuffle() {\n this.afs.logger.debug(\"Shuffling items\");\n\n try {\n const items = Array.from(this.afs.items);\n\n // Fisher-Yates shuffle algorithm\n for (let i = items.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [items[i], items[j]] = [items[j], items[i]];\n }\n\n // Use the existing reorderItems method to update the DOM\n this.reorderItems(items);\n\n // Clear any existing sort orders as we've shuffled\n this.sortOrders.clear();\n\n this.afs.emit(\"shuffled\", {\n itemCount: items.length,\n });\n\n this.afs.logger.debug(\"Items shuffled successfully\");\n } catch (error) {\n this.afs.logger.error(\"Shuffle error:\", error);\n }\n }\n\n /**\n * Determine sort type from item value\n * @private\n * @param {HTMLElement} item - DOM element\n * @param {string} key - Sort key\n * @returns {string} Sort type ('number', 'date', or 'string')\n */\n determineSortType(item, key) {\n this.afs.logger.debug(`Determining sort type for ${key}`);\n\n const value = item.dataset[key];\n\n if (!value) return \"string\";\n if (!isNaN(value)) return \"number\";\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) return \"date\";\n\n return \"string\";\n }\n\n /**\n * Get sort value from item\n * @private\n * @param {HTMLElement} item - DOM element\n * @param {string} key - Sort key\n * @param {string} type - Sort type\n * @returns {any} Parsed value for sorting\n */\n getSortValue(item, key, type) {\n const value = item.dataset[key];\n\n switch (type) {\n case \"number\":\n return parseFloat(value) || 0;\n case \"date\":\n return new Date(value).getTime() || 0;\n default:\n return (value || \"\").toLowerCase();\n }\n }\n\n /**\n * Compare two values for sorting\n * @private\n * @param {any} a - First value\n * @param {any} b - Second value\n * @param {string} order - Sort order ('asc' or 'desc')\n * @returns {number} Comparison result\n */\n compareValues(a, b, order) {\n // Handle null/undefined values\n if (a === null || a === undefined) return order === \"asc\" ? 1 : -1;\n if (b === null || b === undefined) return order === \"asc\" ? -1 : 1;\n\n // Compare values\n const comparison = a < b ? -1 : a > b ? 1 : 0;\n return order === \"asc\" ? comparison : -comparison;\n }\n\n /**\n * Reorder DOM elements\n * @private\n * @param {HTMLElement[]} items - Sorted items\n */\n reorderItems(items) {\n const fragment = document.createDocumentFragment();\n items.forEach((item) => fragment.appendChild(item));\n this.afs.container.appendChild(fragment);\n }\n\n /**\n * Get current sort order for key\n * @public\n * @param {string} key - Sort key\n * @returns {string} Current sort order ('asc' or 'desc')\n */\n getCurrentSortOrder(key) {\n return this.sortOrders.get(key) || \"asc\";\n }\n\n /**\n * Clear all sort orders\n * @public\n */\n clearSortOrders() {\n this.afs.logger.debug(\"Clearing all sort orders\");\n\n this.sortOrders.clear();\n this.afs.emit(\"sortCleared\");\n }\n\n /**\n * Clear all filters, url and search\n * @public\n */\n clearAllFilters() {\n this.afs.logger.debug(\"Clearing all filters and search\");\n\n // Reset filters\n this.activeFilters.clear();\n this.activeFilters.add(\"*\");\n\n // Update filter buttons\n this.filterButtons.forEach((_, button) => {\n button.classList.remove(this.afs.options.get(\"activeClass\"));\n });\n\n // Find and activate \"all\" button if exists\n const allButton = this.findAllButton();\n if (allButton) {\n allButton.classList.add(this.afs.options.get(\"activeClass\"));\n }\n\n // Clear checkboxes\n const checkboxes = document.querySelectorAll('input[type=\"checkbox\"]');\n checkboxes.forEach((checkbox) => {\n if (checkbox.classList.contains(this.afs.options.get(\"activeClass\"))) {\n checkbox.checked = false;\n checkbox.classList.remove(this.afs.options.get(\"activeClass\"));\n }\n });\n\n // Clear search\n if (this.afs.search) {\n this.afs.search.setValue(\"\");\n }\n\n // Clear filter groups and sort orders\n this.filterGroups.clear();\n this.sortOrders.clear();\n\n // Apply changes and ensure counter is updated\n this.applyFilters();\n \n // Update URL if URLManager exists\n if (this.afs.urlManager) {\n this.afs.urlManager.updateURL();\n }\n\n // Emit event\n this.afs.emit(\"filtersCleared\");\n\n this.afs.logger.info(\"All filters cleared\");\n }\n\n /**\n * Refresh the view\n * @public\n */\n refresh() {\n this.afs.logger.debug(\"Refreshing view\");\n\n this.applyFilters();\n this.afs.updateCounter();\n }\n\n removeFilterButton(button) {\n this.filterButtons.delete(button);\n button.removeEventListener(\"click\", this.handleFilterClick);\n }\n\n /**\n * Destroy instance\n * @public\n */\n destroy() {\n this.filterButtons.forEach((_, button) => {\n this.removeFilterButton(button);\n });\n this.filterButtons.clear();\n this.activeFilters.clear();\n this.filterGroups.clear();\n this.afs.logger.debug(\"Filter functionality destroyed\");\n }\n}\n","/**\n * @fileoverview Utility functions for AFS\n */\n\n/**\n * Debounce function\n * @param {Function} func - Function to debounce\n * @param {number} wait - Delay in milliseconds\n * @param {boolean} [immediate=false] - Execute immediately\n * @returns {Function} Debounced function\n */\nexport function debounce(func, wait, immediate = false) {\n let timeout;\n return function executedFunction(...args) {\n const context = this;\n const later = () => {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n const callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n }\n \n /**\n * Throttle function\n * @param {Function} func - Function to throttle\n * @param {number} limit - Time limit in milliseconds\n * @returns {Function} Throttled function\n */\n export function throttle(func, limit) {\n let inThrottle;\n return function executedFunction(...args) {\n const context = this;\n if (!inThrottle) {\n func.apply(context, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n }\n \n /**\n * Parse date string according to format\n * @param {string} dateStr - Date string to parse\n * @param {string} format - Date format\n * @returns {Date|null} Parsed date object or null if invalid\n */\n export function parseDate(dateStr, format) {\n const formats = {\n 'YYYY-MM-DD': /^\\d{4}-\\d{2}-\\d{2}$/,\n 'DD-MM-YYYY': /^\\d{2}-\\d{2}-\\d{4}$/,\n 'MM/DD/YYYY': /^\\d{2}\\/\\d{2}\\/\\d{4}$/\n };\n \n try {\n if (formats[format]?.test(dateStr)) {\n const parts = dateStr.split(/[-\\/]/);\n switch (format) {\n case 'YYYY-MM-DD':\n return new Date(parts[0], parts[1] - 1, parts[2]);\n case 'DD-MM-YYYY':\n return new Date(parts[2], parts[1] - 1, parts[0]);\n case 'MM/DD/YYYY':\n return new Date(parts[2], parts[0] - 1, parts[1]);\n }\n }\n return new Date(dateStr);\n } catch {\n return null;\n }\n }\n \n /**\n * Get element's computed style value\n * @param {HTMLElement} element - Target element\n * @param {string} property - CSS property\n * @returns {string} Computed style value\n */\n export function getStyle(element, property) {\n return window.getComputedStyle(element).getPropertyValue(property);\n }\n \n /**\n * Check if element matches a selector\n * @param {HTMLElement} element - Element to check\n * @param {string} selector - CSS selector\n * @returns {boolean} Whether element matches selector\n */\n export function matches(element, selector) {\n return (\n element.matches ||\n element.matchesSelector ||\n element.msMatchesSelector ||\n element.mozMatchesSelector ||\n element.webkitMatchesSelector ||\n element.oMatchesSelector\n ).call(element, selector);\n }\n \n /**\n * Deep clone an object\n * @param {Object} obj - Object to clone\n * @returns {Object} Cloned object\n */\n export function deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (obj instanceof Date) return new Date(obj);\n if (obj instanceof Array) return obj.map(item => deepClone(item));\n if (obj instanceof Set) return new Set([...obj].map(item => deepClone(item)));\n if (obj instanceof Map) return new Map([...obj].map(([k, v]) => [deepClone(k), deepClone(v)]));\n \n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [key, deepClone(value)])\n );\n }\n \n /**\n * Generate unique ID\n * @param {string} [prefix=''] - ID prefix\n * @returns {string} Unique ID\n */\n export function uniqueId(prefix = '') {\n return `${prefix}${Math.random().toString(36).substr(2, 9)}`;\n }\n \n /**\n * Check if value is plain object\n * @param {any} value - Value to check\n * @returns {boolean} Whether value is plain object\n */\n export function isPlainObject(value) {\n return Object.prototype.toString.call(value) === '[object Object]';\n }","/**\n * @fileoverview Search functionality for AFS\n */\n\nimport { debounce } from '../utils';\n\nexport class Search {\n /**\n * @param {import('../AFS').AFS} afs - Main AFS instance\n */\n constructor(afs) {\n this.afs = afs;\n this.searchInput = null;\n this.searchKeys = ['title']; // Default search keys\n this.minSearchLength = 2;\n this.highlightClass = 'afs-highlight';\n this.setupSearch();\n }\n\n /**\n * Setup search functionality\n * @private\n */\n setupSearch() {\n const searchSelector = this.afs.options.get('searchInputSelector');\n if (!searchSelector) return;\n\n this.searchInput = document.querySelector(searchSelector);\n if (!this.searchInput) {\n this.afs.logger.warn(`Search input not found: ${searchSelector}`);\n return;\n }\n\n // Configure search\n this.searchKeys = this.afs.options.get('searchKeys') || this.searchKeys;\n this.minSearchLength = this.afs.options.get('minSearchLength') || this.minSearchLength;\n\n // Bind events\n this.bindSearchEvents();\n this.afs.logger.debug('Search functionality initialized');\n }\n\n /**\n * Bind search events\n * @private\n */\n bindSearchEvents() {\n if (!this.searchInput) return;\n\n // Create debounced search function\n const debouncedSearch = debounce((e) => {\n this.search(e.target.value);\n }, this.afs.options.get('debounceTime') || 300);\n\n // Bind input event\n this.searchInput.addEventListener('input', debouncedSearch);\n\n // Bind clear event\n this.searchInput.addEventListener('search', (e) => {\n if (!e.target.value) {\n this.clearSearch();\n }\n });\n\n // Handle Enter key\n this.searchInput.addEventListener('keypress', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.search(e.target.value);\n }\n });\n }\n\n /**\n * Perform search\n * @public\n * @param {string} query - Search query\n */\n search(query) {\n this.afs.logger.debug('Performing search:', query);\n const normalizedQuery = this.normalizeQuery(query);\n\n // Update state\n this.afs.state.setState('search.query', normalizedQuery);\n let matches = 0;\n\n // Special case for empty query\n if (!normalizedQuery) {\n this.clearSearch();\n return;\n }\n\n // Skip if query is too short\n if (normalizedQuery.length < this.minSearchLength) {\n this.afs.logger.debug('Search query too short');\n return;\n }\n\n try {\n // Create search regex\n const regex = this.createSearchRegex(normalizedQuery);\n\n // Search through items\n this.afs.items.forEach(item => {\n const searchText = this.getItemSearchText(item);\n const matchesSearch = regex.test(searchText);\n\n if (matchesSearch) {\n this.afs.showItem(item);\n this.highlightMatches(item, regex);\n matches++;\n } else {\n this.afs.hideItem(item);\n this.removeHighlights(item);\n }\n });\n\n // Update URL and emit event\n this.afs.urlManager.updateURL();\n this.afs.emit('search', {\n query: normalizedQuery,\n matches,\n total: this.afs.items.length\n });\n\n this.afs.logger.info(`Search complete. Found ${matches} matches`);\n } catch (error) {\n this.afs.logger.error('Search error:', error);\n }\n\n // Update counter after animation\n setTimeout(() => {\n this.afs.updateCounter();\n }, this.afs.options.get('animationDuration'));\n }\n\n /**\n * Normalize search query\n * @private\n * @param {string} query - Raw search query\n * @returns {string} Normalized query\n */\n normalizeQuery(query) {\n return query\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, ' ');\n }\n\n /**\n * Create search regex\n * @private\n * @param {string} query - Normalized search query\n * @returns {RegExp} Search regex\n */\n createSearchRegex(query) {\n // Escape special regex characters\n const escapedQuery = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n \n // Split into words for whole word matching\n const words = escapedQuery.split(' ').filter(Boolean);\n \n // Create regex pattern\n const pattern = words\n .map(word => `(?=.*\\\\b${word})`)\n .join('');\n \n return new RegExp(pattern, 'i');\n }\n\n /**\n * Get searchable text from item\n * @private\n * @param {HTMLElement} item - DOM element\n * @returns {string} Searchable text\n */\n getItemSearchText(item) {\n return this.searchKeys\n .map(key => item.dataset[key] || '')\n .join(' ')\n .toLowerCase();\n }\n\n /**\n * Highlight search matches\n * @private\n * @param {HTMLElement} item - DOM element\n * @param {RegExp} regex - Search regex\n */\n highlightMatches(item, regex) {\n if (!this.afs.options.get('highlightMatches')) return;\n\n this.searchKeys.forEach(key => {\n const target = item.querySelector(`[data-search-key=\"${key}\"]`);\n if (!target) return;\n\n const text = target.textContent;\n const words = this.afs.state.getState().search.query.split(' ');\n\n let highlightedText = text;\n words.forEach(word => {\n if (!word) return;\n const wordRegex = new RegExp(`(${word})`, 'gi');\n highlightedText = highlightedText.replace(\n wordRegex,\n `<span class=\"${this.highlightClass}\">$1</span>`\n );\n });\n\n target.innerHTML = highlightedText;\n });\n }\n\n /**\n * Remove highlights\n * @private\n * @param {HTMLElement} item - DOM element\n */\n removeHighlights(item) {\n if (!this.afs.options.get('highlightMatches')) return;\n\n this.searchKeys.forEach(key => {\n const target = item.querySelector(`[data-search-key=\"${key}\"]`);\n if (!target) return;\n\n const highlights = target.querySelectorAll(`.${this.highlightClass}`);\n highlights.forEach(highlight => {\n const text = highlight.textContent;\n highlight.replaceWith(text);\n });\n });\n }\n\n /**\n * Clear search\n * @public\n */\n clearSearch() {\n this.afs.logger.debug('Clearing search');\n\n // Clear input\n if (this.searchInput) {\n this.searchInput.value = '';\n }\n\n // Clear state\n this.afs.state.setState('search.query', '');\n\n // Show all items\n this.afs.items.forEach(item => {\n this.afs.showItem(item);\n this.removeHighlights(item);\n });\n\n // Update URL and emit event\n this.afs.urlManager.updateURL();\n this.afs.emit('searchCleared');\n\n // Update counter\n setTimeout(() => {\n this.afs.updateCounter();\n }, this.afs.options.get('animationDuration'));\n }\n\n /**\n * Set search value\n * @public\n * @param {string} value - Search value\n */\n setValue(value) {\n if (this.searchInput) {\n this.searchInput.value = value;\n }\n this.search(value);\n }\n\n /**\n * Get current search value\n * @public\n * @returns {string} Current search value\n */\n getValue() {\n return this.afs.state.getState().search.query;\n }\n\n /**\n * Update search configuration\n * @public\n * @param {Object} config - Search configuration\n */\n updateConfig({\n searchKeys,\n minSearchLength,\n highlightClass,\n debounceTime\n } = {}) {\n if (searchKeys) this.searchKeys = searchKeys;\n if (minSearchLength) this.minSearchLength = minSearchLength;\n if (highlightClass) this.highlightClass = highlightClass;\n if (debounceTime) {\n this.bindSearchEvents(); // Rebind with new debounce time\n }\n }\n\n /**\n * Destroy search functionality\n * @public\n */\n destroy() {\n if (this.searchInput) {\n this.searchInput.removeEventListener('input', this.debouncedSearch);\n this.searchInput.removeEventListener('search', this.handleClear);\n this.searchInput.removeEventListener('keypress', this.handleEnter);\n }\n this.clearSearch();\n }\n}","/**\n * @fileoverview Sort functionality for AFS\n */\n\nexport class Sort {\n /**\n * @param {import('../AFS').AFS} afs - Main AFS instance\n */\n constructor(afs) {\n this.afs = afs;\n this.sortButtons = new Map();\n this.setupSort();\n }\n\n /**\n * Setup sort functionality\n * @private\n */\n setupSort() {\n const sortSelector = this.afs.options.get(\"sortButtonSelector\");\n if (!sortSelector) return;\n\n // Find and setup sort buttons\n document.querySelectorAll(sortSelector).forEach((button) => {\n const key = button.dataset.sortKey;\n if (!key) {\n this.afs.logger.warn(\n \"Sort button missing data-sort-key attribute:\",\n button,\n );\n return;\n }\n\n this.sortButtons.set(button, {\n key,\n direction: button.dataset.sortDirection || \"asc\",\n });\n\n this.bindSortEvent(button);\n });\n\n this.afs.logger.debug(\"Sort functionality initialized\");\n }\n\n /**\n * Bind sort event to button\n * @private\n * @param {HTMLElement} button - Sort button\n */\n bindSortEvent(button) {\n this.afs.logger.debug(\"Binding sort event to button:\", button);\n\n button.addEventListener(\"click\", () => {\n const sortData = this.sortButtons.get(button);\n if (!sortData) return;\n\n // Toggle direction\n sortData.direction = sortData.direction === \"asc\" ? \"desc\" : \"asc\";\n this.sortButtons.set(button, sortData);\n\n // Update button state\n this.updateSortButtonState(button, sortData);\n\n // Perform sort\n this.sort(sortData.key, sortData.direction);\n });\n }\n\n /**\n * Update sort button visual state\n * @private\n * @param {HTMLElement} button - Sort button\n * @param {Object} sortData - Sort data\n */\n updateSortButtonState(button, sortData) {\n // Remove active class from all buttons\n this.sortButtons.forEach((_, btn) => {\n btn.classList.remove(this.afs.options.get(\"activeSortClass\"));\n });\n\n // Add active class to current button\n button.classList.add(this.afs.options.get(\"activeSortClass\"));\n\n // Update direction indicator\n const indicator = button.querySelector(\".sort-direction\");\n if (indicator) {\n indicator.textContent = sortData.direction === \"asc\" ? \"↑\" : \"↓\";\n }\n }\n\n /**\n * Sort items\n * @public\n * @param {string} key - Sort key\n * @param {string} direction - Sort direction ('asc' or 'desc')\n */\n sort(key, direction = \"asc\") {\n this.afs.logger.debug(`Sorting by ${key} in ${direction} order`);\n\n try {\n // Update state\n this.afs.state.setState(\"sort.current\", { key, direction });\n\n // Get all items as array\n const items = Array.from(this.afs.items);\n\n // Determine sort type\n const sortType = this.determineSortType(items[0], key);\n\n // Sort items\n items.sort((a, b) => {\n const valueA = this.getSortValue(a, key, sortType);\n const valueB = this.getSortValue(b, key, sortType);\n\n return this.compareValues(valueA, valueB, direction);\n });\n\n // Reorder DOM elements\n this.reorderItems(items);\n\n // Update URL and emit event\n this.afs.urlManager.updateURL();\n this.afs.emit(\"sort\", { key, direction });\n\n this.afs.logger.info(`Sorted items by ${key} ${direction}`);\n } catch (error) {\n this.afs.logger.error(\"Sort error:\", error);\n }\n }\n\n /**\n * Determine sort type from first item\n * @private\n * @param {HTMLElement} item - First item\n * @param {string} key - Sort key\n * @returns {string} Sort type\n */\n determineSortType(item, key) {\n const value = item.dataset[key];\n\n if (!value) return \"string\";\n if (!isNaN(value)) return \"number\";\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) return \"date\";\n\n return \"string\";\n }\n\n /**\n * Get sort value from item\n * @private\n * @param {HTMLElement} item - DOM element\n * @param {string} key - Sort key\n * @param {string} type - Sort type\n * @returns {any} Sort value\n */\n getSortValue(item, key, type) {\n const value = item.dataset[key];\n\n switch (type) {\n case \"number\":\n return parseFloat(value);\n case \"date\":\n return new Date(value).getTime();\n default:\n return value.toLowerCase();\n }\n }\n\n /**\n * Compare two values\n * @private\n * @param {any} a - First value\n * @param {any} b - Second value\n * @param {string} direction - Sort direction\n * @returns {number} Comparison result\n */\n compareValues(a, b, direction) {\n const modifier = direction === \"asc\" ? 1 : -1;\n\n if (a === b) return 0;\n if (a === undefined || a === null) return 1;\n if (b === undefined || b === null) return -1;\n\n return a > b ? modifier : -modifier;\n }\n\n /**\n * Reorder DOM elements\n * @private\n * @param {HTMLElement[]} items - Sorted items\n */\n reorderItems(items) {\n const container = this.afs.options.get(\"container\");\n const fragment = document.createDocumentFragment();\n\n items.forEach((item) => fragment.appendChild(item));\n container.appendChild(fragment);\n }\n /**\n * Sort with multiple criteria\n * @public\n * @param {Array<{key: string, direction: string}>} criteria - Sort criteria\n */\n sortMultiple(criteria) {\n this.afs.logger.debug(\"Sorting by multiple criteria:\", criteria);\n\n try {\n const items = Array.from(this.afs.items);\n\n items.sort((a, b) => {\n for (const { key, direction } of criteria) {\n const type = this.determineSortType(items[0], key);\n const valueA = this.getSortValue(a, key, type);\n const valueB = this.getSortValue(b, key, type);\n\n const comparison = this.compareValues(valueA, valueB, direction);\n if (comparison !== 0) return comparison;\n }\n return 0;\n });\n\n this.reorderItems(items);\n\n // Update state with primary sort\n if (criteria.length > 0) {\n this.afs.state.setState(\"sort.current\", criteria[0]);\n }\n\n this.afs.urlManager.updateURL();\n this.afs.emit(\"multiSort\", { criteria });\n } catch (error) {\n this.afs.logger.error(\"Multiple sort error:\", error);\n }\n }\n\n /**\n * Sort with custom comparator\n * @public\n * @param {string} key - Sort key\n * @param {Function} comparator - Custom comparison function\n */\n sortWithComparator(key, comparator) {\n this.afs.logger.debug(`Sorting by ${key} with custom comparator`);\n\n try {\n const items = Array.from(this.afs.items);\n\n items.sort((a, b) => {\n const valueA = a.dataset[key];\n const valueB = b.dataset[key];\n return comparator(valueA, valueB);\n });\n\n this.reorderItems(items);\n this.afs.emit(\"customSort\", { key, comparator });\n } catch (error) {\n this.afs.logger.error(\"Custom sort error:\", error);\n }\n }\n\n /**\n * Shuffle items randomly\n * @public\n */\n shuffle() {\n this.afs.logger.debug(\"Shuffling items\");\n\n try {\n const items = Array.from(this.afs.items);\n\n // Fisher-Yates shuffle algorithm\n for (let i = items.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [items[i], items[j]] = [items[j], items[i]];\n }\n\n this.reorderItems(items);\n\n // Clear current sort state\n this.afs.state.setState(\"sort.current\", null);\n\n // Update UI\n this.sortButtons.forEach((_, button) => {\n button.classList.remove(this.afs.options.get(\"activeSortClass\"));\n const indicator = button.querySelector(\".sort-direction\");\n if (indicator) indicator.textContent = \"\";\n });\n\n this.afs.urlManager.updateURL();\n this.afs.emit(\"shuffle\");\n } catch (error) {\n this.afs.logger.error(\"Shuffle error:\", error);\n }\n }\n\n /**\n * Reset sort to default state\n * @public\n */\n reset() {\n this.afs.logger.debug(\"Resetting sort\");\n\n // Clear sort state\n this.afs.state.setState(\"sort.current\", null);\n\n // Reset UI\n this.sortButtons.forEach((_, button) => {\n button.classList.remove(this.afs.options.get(\"activeSortClass\"));\n const indicator = button.querySelector(\".sort-direction\");\n if (indicator) indicator.textContent = \"\";\n });\n\n // Reset sort data\n this.sortButtons.forEach((data, button) => {\n data.direction = \"asc\";\n this.sortButtons.set(button, data);\n });\n\n this.afs.urlManager.updateURL();\n this.afs.emit(\"sortReset\");\n }\n\n /**\n * Get current sort state\n * @public\n * @returns {Object|null} Current sort state\n */\n getCurrentSort() {\n return this.afs.state.getState().sort.current;\n }\n\n /**\n * Add sort button dynamically\n * @public\n * @param {HTMLElement} button - Sort button element\n * @param {string} key - Sort key\n * @param {string} [direction='asc'] - Initial sort direction\n */\n addSortButton(button, key, direction = \"asc\") {\n if (!key) {\n this.afs.logger.warn(\"Sort key required for new sort button\");\n return;\n }\n\n this.sortButtons.set(button, { key, direction });\n this.bindSortEvent(button);\n this.afs.logger.debug(`Added sort button for ${key}`);\n }\n\n /**\n * Remove sort button\n * @public\n * @param {HTMLElement} button - Sort button to remove\n */\n removeSortButton(button) {\n if (this.sortButtons.has(button)) {\n button.removeEventListener(\"click\", this.bindSortEvent);\n this.sortButtons.delete(button);\n this.afs.logger.debug(\"Removed sort button\");\n }\n }\n\n /**\n * Destroy sort functionality\n * @public\n */\n destroy() {\n this.sortButtons.forEach((_, button) => {\n this.removeSortButton(button);\n });\n this.sortButtons.clear();\n this.afs.logger.debug(\"Sort functionality destroyed\");\n }\n}\n","/**\n * @fileoverview Pagination functionality for AFS\n */\nimport { Animation } from \"../styles/Animation.js\";\n\nexport class Pagination {\n /**\n * @param {import('../AFS').AFS} afs - Main AFS instance\n */\n constructor(afs) {\n this.afs = afs;\n this.container = null;\n this.animation = new Animation(afs);\n this.options = this.afs.options.get(\"pagination\");\n this.setupPagination();\n }\n\n /**\n * Setup pagination\n * @private\n */\n setupPagination() {\n this.afs.logger.debug(\"Setting up pagination\");\n if (!this.afs.options.get('pagination.enabled')) return;\n console.log('Pagination enabled');\n\n this.container = document.createElement(\"div\");\n this.container.className = this.options.containerClass;\n\n const itemsContainer = document.querySelector(\n this.afs.options.get(\"pagination.container\"),\n );\n if (!itemsContainer) {\n this.afs.logger.error(\"Items container not found.\");\n return;\n }\n itemsContainer.appendChild(this.container);\n\n // Initialize pagination state with defaults\n this.afs.state.setState(\"pagination\", {\n currentPage: 1,\n itemsPerPage: this.options.itemsPerPage,\n totalPages: 0,\n });\n\n this.bindEvents();\n this.update();\n this.afs.logger.debug(\"Pagination initialized\");\n }\n\n /**\n * Bind pagination events\n * @private\n */\n bindEvents() {\n this.afs.on(\"filter\", () => this.update());\n this.afs.on(\"search\", () => this.update());\n this.afs.on(\"sort\", () => this.update());\n\n this.container.addEventListener(\"click\", (e) => {\n const button = e.target.closest(\"button\");\n if (!button) return;\n\n const page = button.dataset.page;\n if (page) {\n this.goToPage(parseInt(page, 10));\n }\n });\n }\n\n /**\n * Update pagination\n * @public\n */\n update() {\n const visibleItems = Array.from(this.afs.state.getState().items.visible);\n const itemsPerPage = this.afs.state.getState().pagination.itemsPerPage;\n const totalPages = Math.max(\n 1,\n Math.ceil(visibleItems.length / itemsPerPage),\n );\n\n // Update state\n const currentState = this.afs.state.getState().pagination;\n let currentPage = currentState.currentPage;\n\n // Adjust current page if it's beyond the total pages\n if (currentPage > totalPages) {\n currentPage = totalPages;\n }\n\n // Update pagination state\n this.afs.state.setState(\"pagination\", {\n ...currentState,\n currentPage,\n totalPages,\n });\n\n // Update visibility before rendering pagination controls\n this.updateVisibility(visibleItems);\n this.renderPagination();\n this.afs.urlManager.updateURL();\n\n this.afs.emit(\"pagination\", {\n currentPage,\n totalPages,\n itemsPerPage,\n visibleItems: visibleItems.length,\n });\n }\n\n /**\n * Update items visibility based on current page\n * @private\n */\n updateVisibility(visibleItems) {\n const { currentPage, itemsPerPage } = this.afs.state.getState().pagination;\n const startIndex = (currentPage - 1) * itemsPerPage;\n const endIndex = startIndex + itemsPerPage;\n\n // First hide all items\n this.afs.items.forEach((item) => {\n item.style.display = \"none\";\n item.classList.add(this.afs.options.get(\"hiddenClass\"));\n });\n\n // Then show only the items for the current page\n const itemsToShow = visibleItems.slice(startIndex, endIndex);\n\n // Ensure we're not trying to display non-existent items\n if (itemsToShow.length === 0 && visibleItems.length > 0) {\n // If we have no items to show but we do have visible items,\n // we're probably on an invalid page - go to page 1\n this.goToPage(1);\n return;\n }\n\n // Show items with animation\n requestAnimationFrame(() => {\n itemsToShow.forEach((item) => {\n // Remove hidden class and restore display\n item.style.display = \"\";\n item.classList.remove(this.afs.options.get(\"hiddenClass\"));\n\n // Apply show animation in the next frame\n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(\n item,\n this.options.animationType || \"fade\",\n );\n });\n });\n });\n }\n\n /**\n * Render pagination controls\n * @private\n */\n renderPagination() {\n const { currentPage, totalPages } = this.afs.state.getState().pagination;\n\n this.container.innerHTML = \"\";\n\n if (totalPages <= 1) {\n this.container.style.display = \"none\";\n return;\n }\n\n this.container.style.display = \"flex\";\n const controls = this.createPaginationControls(currentPage, totalPages);\n this.container.appendChild(controls);\n }\n\n /**\n * Create pagination controls\n * @private\n * @param {number} currentPage - Current page\n * @param {number} totalPages - Total pages\n * @returns {DocumentFragment} Pagination controls\n */\n createPaginationControls(currentPage, totalPages) {\n const fragment = document.createDocumentFragment();\n\n if (this.options.showPrevNext) {\n const prevButton = this.createPageButton(\"‹\", currentPage - 1, {\n disabled: currentPage === 1,\n class: \"afs-pagination-prev\",\n });\n fragment.appendChild(prevButton);\n }\n\n fragment.appendChild(\n this.createPageButton(\"1\", 1, { active: currentPage === 1 }),\n );\n\n const range = this.calculatePageRange(currentPage, totalPages);\n\n if (range.start > 2) fragment.appendChild(this.createEllipsis());\n\n for (let i = range.start; i <= range.end; i++) {\n if (i === 1 || i === totalPages) continue;\n fragment.appendChild(\n this.createPageButton(i.toString(), i, { active: currentPage === i }),\n );\n }\n\n if (range.end < totalPages - 1) fragment.appendChild(this.createEllipsis());\n\n if (totalPages > 1)\n fragment.appendChild(\n this.createPageButton(totalPages.toString(), totalPages, {\n active: currentPage === totalPages,\n }),\n );\n\n if (this.options.showPrevNext) {\n const nextButton = this.createPageButton(\"›\", currentPage + 1, {\n disabled: currentPage === totalPages,\n class: \"afs-pagination-next\",\n });\n fragment.appendChild(nextButton);\n }\n\n return fragment;\n }\n\n /**\n * Create page button\n * @private\n */\n createPageButton(\n text,\n page,\n { active = false, disabled = false, class: className = \"\" } = {},\n ) {\n const button = document.createElement(\"button\");\n button.textContent = text;\n button.dataset.page = page;\n button.classList.add(this.options.pageButtonClass || \"afs-page-button\");\n\n if (className) button.classList.add(className);\n if (active)\n button.classList.add(this.options.activePageClass || \"afs-page-active\");\n if (disabled) button.disabled = true;\n\n return button;\n }\n\n createEllipsis() {\n const span = document.createElement(\"span\");\n span.textContent = \"...\";\n span.classList.add(\"afs-pagination-ellipsis\");\n return span;\n }\n\n calculatePageRange(currentPage, totalPages) {\n const maxButtons = this.options.maxButtons || 7;\n const sideButtons = Math.floor((maxButtons - 3) / 2);\n\n let start = Math.max(2, currentPage - sideButtons);\n let end = Math.min(totalPages - 1, start + maxButtons - 3);\n\n if (end - start < maxButtons - 3)\n start = Math.max(2, end - (maxButtons - 3));\n\n return { start, end };\n }\n\n /**\n * Go to specific page\n * @public\n */\n goToPage(page) {\n const state = this.afs.state.getState().pagination;\n const targetPage = Math.max(1, Math.min(page, state.totalPages));\n\n if (targetPage === state.currentPage) return;\n\n // Update state\n this.afs.state.setState(\"pagination.currentPage\", targetPage);\n\n // Force a reflow before updating\n this.afs.container.offsetHeight;\n\n // Update visibility and controls\n this.update();\n\n // Scroll to top if enabled\n if (this.options.scrollToTop) {\n setTimeout(() => this.scrollToTop(), 100);\n }\n\n // Emit page change event\n this.afs.emit(\"pageChanged\", {\n previousPage: state.currentPage,\n currentPage: targetPage,\n totalPages: state.totalPages,\n });\n }\n\n scrollToTop() {\n const container = document.querySelector(\n this.afs.options.get(\"pagination.container\"),\n );\n if (!container) {\n this.afs.logger.warn(\"Scroll container not found.\");\n return;\n }\n\n window.scrollTo({\n top: container.offsetTop - this.options.scrollOffset,\n behavior: \"smooth\",\n });\n }\n\n /**\n * Set pagination mode\n * @public\n */\n setPaginationMode(enabled) {\n this.afs.logger.debug(`Setting pagination mode to: ${enabled}`);\n \n // Update options\n this.afs.options.set('pagination.enabled', enabled);\n \n if (enabled) {\n // Enable pagination\n this.setupPagination();\n } else {\n // Disable pagination and show all items\n this.container.remove();\n this.showAllItems();\n }\n\n // Emit event\n this.afs.emit('paginationModeChanged', { enabled });\n }\n\n /**\n * Show all items (for infinite scroll mode)\n * @private\n */\n showAllItems() {\n const visibleItems = Array.from(this.afs.state.getState().items.visible);\n \n requestAnimationFrame(() => {\n visibleItems.forEach(item => {\n item.style.display = '';\n item.classList.remove(this.afs.options.get('hiddenClass'));\n \n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(item, this.options.animationType || 'fade');\n });\n });\n });\n }\n}\n","/**\n * @fileoverview URL state management for AFS\n */\n\nexport class URLManager {\n /**\n * @param {import('../AFS').AFS} afs - Main AFS instance\n */\n constructor(afs) {\n this.afs = afs;\n this.defaultParams = new URLSearchParams();\n this.setupPopStateHandler();\n \n // Load URL state after a small delay to ensure all features are ready\n setTimeout(() => {\n this.loadFromURL();\n }, 0);\n }\n\n /**\n * Setup history popstate handler\n * @private\n */\n setupPopStateHandler() {\n window.addEventListener('popstate', () => {\n this.loadFromURL();\n });\n }\n\n /**\n * Update URL with current filter state\n * @public\n */\n /**\n * Update URL with current filter state\n * @public\n */\nupdateURL() {\n this.afs.logger.debug(\"Updating URL state\");\n const params = new URLSearchParams();\n const state = this.afs.state.getState(); // Get current state of filters\n\n // Get active filters directly from the Filter instance\n const activeFilters = this.afs.filter.getActiveFilters();\n\n // Update the state object with the active filters\n state.filters.current = activeFilters;\n\n // Add filters to URL\n this.addFiltersToURL(params, state);\n \n // Add ranges (if applicable) to URL\n this.addRangesToURL(params, state);\n \n // Add search query to URL\n this.addSearchToURL(params, state);\n \n // Add sort state to URL\n this.addSortToURL(params, state);\n \n // Add pagination to URL\n this.addPaginationToURL(params, state);\n \n // Push the updated URL\n this.pushState(params); // Push the new URL state to the browser\n}\n\n /**\n * Add filters to URL parameters\n * @private\n * @param {URLSearchParams} params\n * @param {Object} state\n */\n addFiltersToURL(params, state) {\n const filters = state.filters;\n\n // Skip if only default filter is active\n if (filters.current.size === 0 || \n (filters.current.size === 1 && filters.current.has('*'))) {\n return;\n }\n\n // Group filters by type\n const filtersByType = {};\n for (const filter of filters.current) {\n if (filter !== '*') {\n const [type, value] = filter.split(':');\n if (!filtersByType[type]) {\n filtersByType[type] = new Set();\n }\n filtersByType[type].add(value);\n }\n }\n\n // Add filters to params\n Object.entries(filtersByType).forEach(([type, values]) => {\n params.set(type, Array.from(values).join(','));\n });\n\n // Add filter mode if not default\n if (filters.mode !== 'OR') {\n params.set('filterMode', filters.mode.toLowerCase());\n }\n\n // Add group mode if groups exist and mode isn't default\n if (filters.groups.size > 0 && filters.groupMode !== 'OR') {\n params.set('groupMode', filters.groupMode.toLowerCase());\n }\n\n // Add filter groups if they exist\n filters.groups.forEach((group, groupId) => {\n params.set(`group_${groupId}`, Array.from(group.filters).join(','));\n if (group.operator !== 'OR') {\n params.set(`groupOp_${groupId}`, group.operator.toLowerCase());\n }\n });\n }\n\n /**\n * Add range filters to URL parameters\n * @private\n * @param {URLSearchParams} params\n * @param {Object} state\n */\n addRangesToURL(params, state) {\n // Handle numeric ranges\n state.filters.ranges.forEach((range, key) => {\n const { currentMin, currentMax } = range;\n if (currentMin !== range.min || currentMax !== range.max) {\n params.set(`range_${key}`, `${currentMin},${currentMax}`);\n }\n });\n\n // Handle date ranges\n state.filters.dateRanges.forEach((range, key) => {\n const { start, end } = range;\n params.set(`dateRange_${key}`, `${start.toISOString()},${end.toISOString()}`);\n });\n }\n\n /**\n * Add search parameters to URL\n * @private\n * @param {URLSearchParams} params\n * @param {Object} state\n */\n addSearchToURL(params, state) {\n if (state.search.query) {\n params.set('search', state.search.query);\n }\n }\n\n /**\n * Add sort parameters to URL\n * @private\n * @param {URLSearchParams} params\n * @param {Object} state\n */\n addSortToURL(params, state) {\n if (state.sort.current) {\n const { key, direction } = state.sort.current;\n params.set('sort', `${key},${direction}`);\n }\n }\n\n /**\n * Add pagination parameters to URL\n * @private\n * @param {URLSearchParams} params\n * @param {Object} state\n */\n addPaginationToURL(params, state) {\n const { currentPage, itemsPerPage } = state.pagination;\n if (currentPage > 1) {\n params.set('page', currentPage.toString());\n }\n if (itemsPerPage !== this.afs.options.get('pagination.itemsPerPage')) {\n params.set('perPage', itemsPerPage.toString());\n }\n }\n\n /**\n * Update browser URL\n * @private\n * @param {URLSearchParams} params\n */\n pushState(params) {\n const queryString = params.toString();\n const newURL = `${window.location.pathname}${queryString ? '?' + queryString : ''}`;\n \n // Only update if URL actually changed\n if (newURL !== window.location.href) {\n window.history.pushState({}, '', newURL);\n this.afs.logger.debug('URL updated:', newURL);\n }\n }\n\n /**\n * Load filter state from URL\n * @public\n */\nloadFromURL() {\n this.afs.logger.debug('Loading state from URL');\n const params = new URLSearchParams(window.location.search);\n\n try {\n // Clear existing state first\n if (this.afs.filter) {\n this.afs.filter.clearAllFilters();\n }\n\n // Process filter mode first\n const filterMode = params.get('filterMode');\n if (filterMode && this.afs.filter) {\n this.afs.filter.setFilterMode(filterMode.toUpperCase());\n }\n\n // Process regular filters\n const filterParams = Array.from(params.entries()).filter(([key]) => this.isRegularFilter(key));\n if (filterParams.length > 0 && this.afs.filter) {\n // Remove default '*' filter\n this.afs.filter.activeFilters.clear();\n \n // Add filters and update button states\n filterParams.forEach(([type, values]) => {\n values.split(',').forEach(value => {\n const filter = `${type}:${value}`;\n this.afs.filter.activeFilters.add(filter);\n \n // Update button UI\n this.afs.filter.filterButtons.forEach((buttonFilter, button) => {\n if (buttonFilter === filter) {\n button.classList.add(this.afs.options.get('activeClass'));\n } else if (buttonFilter === '*') {\n button.classList.remove(this.afs.options.get('activeClass'));\n }\n });\n });\n });\n }\n\n // Apply filters before processing other parameters\n if (this.afs.filter) {\n this.afs.filter.applyFilters();\n }\n\n // Process search\n const searchQuery = params.get('search');\n if (searchQuery && this.afs.search) {\n this.afs.search.setValue(searchQuery);\n }\n\n // Process sort\n const sortParam = params.get('sort');\n if (sortParam && this.afs.sort) {\n const [key, direction] = sortParam.split(',');\n this.afs.sort.sort(key, direction);\n }\n\n // Process pagination\n const page = parseInt(params.get('page'));\n if (!isNaN(page) && this.afs.pagination) {\n this.afs.pagination.goToPage(page);\n }\n\n this.afs.emit('urlStateLoaded', { params: Object.fromEntries(params) });\n this.afs.logger.info('State loaded from URL');\n } catch (error) {\n this.afs.logger.error('Error loading state from URL:', error);\n // Reset to default state on error\n if (this.afs.filter) {\n this.afs.filter.clearAllFilters();\n }\n }\n}\n \n /**\n * Process filters from URL parameters\n * @private\n * @param {URLSearchParams} params\n */\n processFiltersFromURL(params) {\n const state = this.afs.state.getState();\n let hasFilters = false;\n\n // Process filter mode\n const filterMode = params.get('filterMode');\n if (filterMode) {\n state.filters.mode = filterMode.toUpperCase();\n }\n\n // Process group mode\n const groupMode = params.get('groupMode');\n if (groupMode) {\n state.filters.groupMode = groupMode.toUpperCase();\n }\n\n // Process regular filters\n for (const [type, values] of params.entries()) {\n if (this.isRegularFilter(type)) {\n values.split(',').filter(Boolean).forEach(value => {\n hasFilters = true;\n state.filters.current.add(`${type}:${value}`);\n });\n }\n }\n\n // Process filter groups\n for (const [key, value] of params.entries()) {\n if (key.startsWith('group_')) {\n const groupId = key.replace('group_', '');\n const operator = params.get(`groupOp_${groupId}`)?.toUpperCase() || 'OR';\n state.filters.groups.set(groupId, {\n filters: new Set(value.split(',')),\n operator\n });\n }\n }\n\n // Set default if no filters\n if (!hasFilters && state.filters.groups.size === 0) {\n state.filters.current.add('*');\n }\n }\n\n /**\n * Process range filters from URL parameters\n * @private\n * @param {URLSearchParams} params\n */\n processRangesFromURL(params) {\n const state = this.afs.state.getState();\n\n // Process numeric ranges\n for (const [key, value] of params.entries()) {\n if (key.startsWith('range_')) {\n const rangeKey = key.replace('range_', '');\n const [min, max] = value.split(',').map(Number);\n state.filters.ranges.set(rangeKey, { currentMin: min, currentMax: max });\n }\n }\n\n // Process date ranges\n for (const [key, value] of params.entries()) {\n if (key.startsWith('dateRange_')) {\n const rangeKey = key.replace('dateRange_', '');\n const [start, end] = value.split(',').map(str => new Date(str));\n state.filters.dateRanges.set(rangeKey, { start, end });\n }\n }\n }\n\n /**\n * Process search from URL parameters\n * @private\n * @param {URLSearchParams} params\n */\n processSearchFromURL(params) {\n const searchQuery = params.get('search') || '';\n this.afs.state.setState('search.query', searchQuery);\n \n if (this.afs.options.get('searchInput')) {\n this.afs.options.get('searchInput').value = searchQuery;\n }\n }\n\n /**\n * Process sort from URL parameters\n * @private\n * @param {URLSearchParams} params\n */\n processSortFromURL(params) {\n const sortParam = params.get('sort');\n if (sortParam) {\n const [key, direction] = sortParam.split(',');\n this.afs.state.setState('sort.current', { key, direction });\n }\n }\n\n /**\n * Process pagination from URL parameters\n * @private\n * @param {URLSearchParams} params\n */\n processPaginationFromURL(params) {\n const page = parseInt(params.get('page')) || 1;\n const perPage = parseInt(params.get('perPage')) || \n this.afs.options.get('pagination.itemsPerPage');\n\n this.afs.state.setState('pagination', {\n currentPage: page,\n itemsPerPage: perPage\n });\n }\n\n /**\n * Check if parameter is a regular filter\n * @private\n * @param {string} param - Parameter name\n * @returns {boolean}\n */\n isRegularFilter(param) {\n const excludedParams = [\n 'search', 'sort', 'page', 'perPage', 'filterMode', 'groupMode'\n ];\n return !excludedParams.includes(param) && \n !param.startsWith('group_') && \n !param.startsWith('groupOp_') && \n !param.startsWith('range_') && \n !param.startsWith('dateRange_');\n }\n\n /**\n * Clear URL parameters\n * @public\n */\n clearURL() {\n window.history.pushState({}, '', window.location.pathname);\n this.afs.state.reset();\n if (this.afs.filter) {\n this.afs.filter.clearAllFilters();\n }\n }\n\n /**\n * Get current URL parameters\n * @public\n * @returns {URLSearchParams}\n */\n getURLParams() {\n return new URLSearchParams(window.location.search);\n }\n\n /**\n * Check if URL has parameters\n * @public\n * @returns {boolean}\n */\n hasParams() {\n return window.location.search.length > 1;\n }\n\n /**\n * Get parameter value\n * @public\n * @param {string} param - Parameter name\n * @returns {string|null}\n */\n getParam(param) {\n return new URLSearchParams(window.location.search).get(param);\n }\n}","/**\n * @fileoverview Range filter implementation for AFS\n */\n\nimport { debounce } from \"../utils\";\nimport { StyleManager } from \"../styles/StyleManager\";\n\nexport class RangeFilter {\n constructor(afs) {\n this.afs = afs;\n this.activeRanges = new Map();\n\n if (!this.afs.styleManager) {\n this.afs.styleManager = new StyleManager(this.afs.options);\n }\n\n // Apply styles immediately\n this.afs.styleManager.applyStyles();\n }\n\n /**\n * @typedef {Object} RangeOptions\n * @property {string} key - Data attribute key\n * @property {string} type - Type of range ('number' or 'date')\n * @property {HTMLElement} container - Container element\n * @property {number|string} [min] - Minimum value\n * @property {number|string} [max] - Maximum value\n * @property {number} [step] - Step value\n */\n\n /**\n * Add range slider\n * @param {RangeOptions} options - Range slider options\n */\n addRangeSlider({ key, type, container, min, max, step = 1, ui }) {\n this.afs.logger.debug(`Adding range slider for ${key}`);\n\n if (!container) {\n this.afs.logger.error(\"Container element required for range slider\");\n return;\n }\n\n // Calculate min/max if not provided\n const values = this.calculateMinMax(key, type);\n min = min ?? values.min;\n max = max ?? values.max;\n\n // Get global UI options and merge with slider-specific options\n const globalUiOptions = this.afs.options.get(\"styles.slider.ui\") || {\n showHistogram: false,\n bins: 10,\n };\n const sliderUiOptions = {\n ...globalUiOptions,\n ...ui, // Override with slider-specific options if provided\n };\n\n // Only calculate histogram data if enabled\n const histogramData = sliderUiOptions.showHistogram\n ? this.calculateHistogramData(key, sliderUiOptions.bins)\n : { counts: [], binEdges: [], max: 0 };\n\n // Create slider elements\n const elements = this.createSliderElements(histogramData, sliderUiOptions);\n const state = this.initializeState(min, max, step, type);\n\n // Store histogram data and UI options in state\n state.ui = sliderUiOptions;\n if (sliderUiOptions.showHistogram) {\n state.histogram = histogramData;\n }\n\n // Add elements to container\n this.appendElements(container, elements);\n\n // Setup event handlers\n this.setupEventHandlers(elements, state, key);\n\n // Store state\n this.activeRanges.set(key, { state, elements });\n\n // Initial update\n this.updateSliderUI(key);\n\n // Setup histogram highlight updates only if enabled\n if (sliderUiOptions.showHistogram) {\n this.setupHistogramHighlight(elements, state, histogramData.binEdges);\n }\n\n this.afs.logger.info(`Range slider added for ${key}`);\n }\n /**\n * Calculate min and max values from items\n * @private\n */\n calculateMinMax(key, type) {\n const values = Array.from(this.afs.items)\n .map((item) => {\n const value = item.dataset[key];\n return type === \"date\" ? new Date(value).getTime() : parseFloat(value);\n })\n .filter((value) => !isNaN(value));\n\n return {\n min: Math.min(...values),\n max: Math.max(...values),\n };\n }\n\n /**\n * Create slider DOM elements\n * @private\n * @param {Object} histogramData - Histogram data\n * @param {Object} sliderUiOptions - UI options for this slider\n */\n createSliderElements(histogramData, sliderUiOptions) {\n const styles =\n this.afs.options.get(\"styles\") || this.afs.styleManager.defaultStyles;\n const sliderStyles =\n styles.slider || this.afs.styleManager.defaultStyles.slider;\n const colors = styles.colors || this.afs.styleManager.defaultStyles.colors;\n\n const container = document.createElement(\"div\");\n container.className = \"price-range-container\";\n\n const slider = document.createElement(\"div\");\n slider.className = sliderStyles.class;\n\n const track = document.createElement(\"div\");\n track.className = sliderStyles.trackClass;\n\n // Only add histogram if enabled in the slider-specific options\n if (sliderUiOptions?.showHistogram && histogramData?.counts?.length > 0) {\n const histogram = this.createHistogramBars(histogramData, colors);\n slider.appendChild(histogram);\n }\n\n const selectedRange = document.createElement(\"div\");\n selectedRange.className = sliderStyles.selectedClass;\n\n const minThumb = document.createElement(\"div\");\n minThumb.className = sliderStyles.thumbClass;\n\n const maxThumb = document.createElement(\"div\");\n maxThumb.className = sliderStyles.thumbClass;\n\n const minValue = document.createElement(\"div\");\n minValue.className = sliderStyles.valueClass;\n\n const maxValue = document.createElement(\"div\");\n maxValue.className = sliderStyles.valueClass;\n\n // Build the slider\n slider.appendChild(track);\n slider.appendChild(selectedRange);\n slider.appendChild(minThumb);\n slider.appendChild(maxThumb);\n slider.appendChild(minValue);\n slider.appendChild(maxValue);\n\n container.appendChild(slider);\n\n return {\n container,\n slider,\n track,\n selectedRange,\n minThumb,\n maxThumb,\n minValue,\n maxValue,\n };\n }\n\n // Add helper method for creating histogram\n createHistogram(data, colors) {\n const histogram = document.createElement(\"div\");\n histogram.className = \"afs-histogram\";\n\n // Create histogram bars\n data.forEach((value, index) => {\n const bar = document.createElement(\"div\");\n bar.className = \"afs-histogram-bar\";\n bar.style.height = `${value}%`;\n bar.style.backgroundColor = colors.histogram;\n histogram.appendChild(bar);\n });\n\n return histogram;\n }\n\n /**\n * Calculate histogram data from items\n * @private\n * @param {string} key - Data attribute key (e.g., 'price')\n * @param {number} [bins=10] - Number of bins for histogram\n * @returns {Object} Histogram data and metadata\n */\n calculateHistogramData(key, bins = 10) {\n try {\n const values = Array.from(this.afs.items)\n .map((item) => parseFloat(item.dataset[key]))\n .filter((value) => !isNaN(value));\n\n if (values.length === 0) {\n return { counts: [], binEdges: [], max: 0 };\n }\n\n const min = Math.min(...values);\n const max = Math.max(...values);\n const binWidth = (max - min) / bins;\n\n const counts = new Array(bins).fill(0);\n const binEdges = new Array(bins + 1);\n\n // Calculate bin edges\n for (let i = 0; i <= bins; i++) {\n binEdges[i] = min + i * binWidth;\n }\n\n // Count values in each bin\n values.forEach((value) => {\n if (value === max) {\n counts[counts.length - 1]++;\n return;\n }\n\n const binIndex = Math.floor((value - min) / binWidth);\n counts[binIndex]++;\n });\n\n // Normalize heights to be more subtle\n const maxCount = Math.max(...counts);\n const normalizedCounts = counts.map(\n (count) => Math.max(20, Math.round((count / maxCount) * 100)), // Minimum height of 20%\n );\n\n return {\n counts: normalizedCounts,\n binEdges,\n max: maxCount,\n min,\n max,\n };\n } catch (error) {\n this.afs.logger.error(\"Error calculating histogram:\", error);\n return { counts: [], binEdges: [], max: 0 };\n }\n }\n\n /**\n * Setup histogram highlight on range changes\n * @private\n */\n setupHistogramHighlight(elements, state, binEdges) {\n const bars = elements.slider.querySelectorAll(\".afs-histogram-bar\");\n\n const updateHistogram = () => {\n const minVal = state.currentMin;\n const maxVal = state.currentMax;\n\n bars.forEach((bar, index) => {\n const binStart = binEdges[index];\n const binEnd = binEdges[index + 1];\n\n // Highlight bars within the selected range\n if (binStart >= minVal && binEnd <= maxVal) {\n bar.classList.add(\"active\");\n } else {\n bar.classList.remove(\"active\");\n }\n });\n };\n\n // Update histogram on range changes using AFS instance\n this.afs.on(\"rangeFilter\", () => updateHistogram());\n\n // Initial update\n updateHistogram();\n }\n\n /**\n * Create histogram bars\n * @private\n */\n createHistogramBars(histogramData, colors) {\n const { counts } = histogramData;\n const histogram = document.createElement(\"div\");\n histogram.className = \"afs-histogram\";\n\n counts.forEach((height) => {\n const bar = document.createElement(\"div\");\n bar.className = \"afs-histogram-bar\";\n bar.style.height = `${height}%`;\n histogram.appendChild(bar);\n });\n\n return histogram;\n }\n\n /**\n * Initialize slider state\n * @private\n */\n initializeState(min, max, step, type) {\n return {\n min,\n max,\n currentMin: min,\n currentMax: max,\n step,\n type,\n isDragging: false,\n };\n }\n\n /**\n * Append elements to container\n * @private\n */\n appendElements(container, elements) {\n const {\n slider,\n track,\n selectedRange,\n minThumb,\n maxThumb,\n minValue,\n maxValue,\n } = elements;\n\n slider.appendChild(track);\n slider.appendChild(selectedRange);\n slider.appendChild(minThumb);\n slider.appendChild(maxThumb);\n slider.appendChild(minValue);\n slider.appendChild(maxValue);\n container.appendChild(slider);\n }\n\n /**\n * Setup event handlers for slider\n * @private\n */\n setupEventHandlers(elements, state, key) {\n const { minThumb, maxThumb } = elements;\n\n const handleStart = (isMin) => (e) => {\n e.preventDefault(); // Prevent scrolling while dragging on mobile\n state.isDragging = true;\n \n // Get the correct event coordinates whether mouse or touch\n const getEventXY = (event) => {\n return event.touches ? event.touches[0] : event;\n };\n\n const moveHandler = (moveEvent) => {\n const evt = getEventXY(moveEvent);\n this.createMoveHandler(elements, state, key, isMin)(evt);\n };\n\n const stopHandler = () => {\n state.isDragging = false;\n \n // Remove both mouse and touch event listeners\n window.removeEventListener('mousemove', moveHandler);\n window.removeEventListener('mouseup', stopHandler);\n window.removeEventListener('touchmove', moveHandler);\n window.removeEventListener('touchend', stopHandler);\n window.removeEventListener('touchcancel', stopHandler);\n \n this.applyFilter(key);\n };\n\n // Add both mouse and touch event listeners\n window.addEventListener('mousemove', moveHandler);\n window.addEventListener('mouseup', stopHandler);\n window.addEventListener('touchmove', moveHandler, { passive: false });\n window.addEventListener('touchend', stopHandler);\n window.addEventListener('touchcancel', stopHandler);\n };\n\n // Add both mouse and touch event listeners to thumbs\n minThumb.addEventListener('mousedown', handleStart(true));\n minThumb.addEventListener('touchstart', handleStart(true), { passive: false });\n maxThumb.addEventListener('mousedown', handleStart(false));\n maxThumb.addEventListener('touchstart', handleStart(false), { passive: false });\n }\n\n /**\n * Update slider UI\n * @private\n */\n updateSliderUI(key) {\n const { state, elements } = this.activeRanges.get(key);\n const { minThumb, maxThumb, selectedRange, minValue, maxValue } = elements;\n\n // Calculate positions with padding consideration\n const range = state.max - state.min;\n const minPos = ((state.currentMin - state.min) / range) * 100;\n const maxPos = ((state.currentMax - state.min) / range) * 100;\n\n // Ensure thumbs stay within bounds\n const clampedMinPos = Math.max(0, Math.min(minPos, 100));\n const clampedMaxPos = Math.max(0, Math.min(maxPos, 100));\n\n // Position thumbs\n minThumb.style.left = `${clampedMinPos}%`;\n maxThumb.style.left = `${clampedMaxPos}%`;\n\n // Position selected range\n selectedRange.style.left = `${clampedMinPos}%`;\n selectedRange.style.width = `${clampedMaxPos - clampedMinPos}%`;\n\n // Format values\n const formatValue =\n state.type === \"date\"\n ? (value) => new Date(value).toLocaleDateString()\n : (value) => value.toFixed(2);\n\n // Update value labels\n minValue.textContent = formatValue(state.currentMin);\n maxValue.textContent = formatValue(state.currentMax);\n\n // Position value labels considering bounds\n minValue.style.left = `${clampedMinPos}%`;\n maxValue.style.left = `${clampedMaxPos}%`;\n\n // Handle edge cases for value label positioning\n if (clampedMinPos < 5) {\n minValue.style.transform = \"translateX(0)\";\n } else if (clampedMinPos > 95) {\n minValue.style.transform = \"translateX(-100%)\";\n } else {\n minValue.style.transform = \"translateX(-50%)\";\n }\n\n if (clampedMaxPos < 5) {\n maxValue.style.transform = \"translateX(0)\";\n } else if (clampedMaxPos > 95) {\n maxValue.style.transform = \"translateX(-100%)\";\n } else {\n maxValue.style.transform = \"translateX(-50%)\";\n }\n }\n\n // Also update the createMoveHandler to respect the padding\n createMoveHandler(elements, state, key, isMin) {\n this.afs.logger.debug(`Creating move handler for ${key}`);\n\n const { track } = elements;\n const PADDING = 5;\n\n return debounce((e) => {\n const clientX = e.touches ? e.touches[0].clientX : e.clientX;\n const rect = track.getBoundingClientRect();\n const totalWidth = rect.width;\n const paddingPixels = (PADDING / 100) * totalWidth;\n\n // Calculate percent with padding consideration\n const rawPercent =\n (clientX - rect.left - paddingPixels) /\n (totalWidth - 2 * paddingPixels);\n const percent = Math.min(Math.max(0, rawPercent), 1);\n\n // Calculate value considering the full range\n const value = state.min + (state.max - state.min) * percent;\n const stepped = Math.round(value / state.step) * state.step;\n\n if (isMin) {\n state.currentMin = Math.min(stepped, state.currentMax);\n } else {\n state.currentMax = Math.max(stepped, state.currentMin);\n }\n\n this.updateSliderUI(key);\n }, 16); // ~60fps\n }\n\n /**\n * Apply range filter\n * @private\n */\n applyFilter(key) {\n this.afs.logger.debug(`Applying range filter for ${key}`);\n\n const { state } = this.activeRanges.get(key);\n\n this.afs.items.forEach((item) => {\n const value =\n state.type === \"date\"\n ? new Date(item.dataset[key]).getTime()\n : parseFloat(item.dataset[key]);\n\n if (value >= state.currentMin && value <= state.currentMax) {\n this.afs.showItem(item);\n } else {\n this.afs.hideItem(item);\n }\n });\n\n this.afs.updateCounter();\n this.afs.urlManager.updateURL();\n this.afs.emit(\"rangeFilter\", {\n key,\n min: state.currentMin,\n max: state.currentMax,\n });\n }\n\n /**\n * Get current range values\n * @param {string} key - Range key\n * @returns {Object} Current range values\n */\n getRangeValues(key) {\n const range = this.activeRanges.get(key);\n if (!range) return null;\n\n return {\n min: range.state.currentMin,\n max: range.state.currentMax,\n type: range.state.type,\n };\n }\n\n /**\n * Set range values\n * @param {string} key - Range key\n * @param {number} min - Minimum value\n * @param {number} max - Maximum value\n */\n setRangeValues(key, min, max) {\n const range = this.activeRanges.get(key);\n if (!range) return;\n\n range.state.currentMin = min;\n range.state.currentMax = max;\n this.updateSliderUI(key);\n this.applyFilter(key);\n }\n\n /**\n * Remove range slider\n * @param {string} key - Range key\n */\n removeRangeSlider(key) {\n const range = this.activeRanges.get(key);\n if (!range) return;\n\n range.elements.slider.remove();\n this.activeRanges.delete(key);\n this.afs.logger.info(`Range slider removed for ${key}`);\n }\n}\n","/**\n * @fileoverview Date filter implementation for AFS\n */\n\nimport { debounce } from '../utils';\n\nexport class DateFilter {\n constructor(afs) {\n this.afs = afs;\n this.activeDateRanges = new Map();\n this.defaultFormat = this.afs.options.get('dateFormat') || 'YYYY-MM-DD';\n }\n\n /**\n * @typedef {Object} DateRangeOptions\n * @property {string} key - Data attribute key\n * @property {HTMLElement} container - Container element\n * @property {Date} [minDate] - Minimum date\n * @property {Date} [maxDate] - Maximum date\n * @property {string} [format] - Date format (default: YYYY-MM-DD)\n */\n\n /**\n * Add date range filter\n * @param {DateRangeOptions} options - Date range options\n */\n addDateRange({ key, container, minDate, maxDate, format = this.defaultFormat }) {\n this.afs.logger.debug(`Adding date range for ${key}`);\n\n if (!container) {\n this.afs.logger.error('Container element required for date range');\n return;\n }\n\n // Calculate min/max dates if not provided\n const dates = this.calculateMinMaxDates(key);\n minDate = minDate ?? dates.min;\n maxDate = maxDate ?? dates.max;\n\n // Create date picker elements\n const elements = this.createDateElements();\n const state = this.initializeState(minDate, maxDate, format);\n\n // Add elements to container\n this.appendElements(container, elements);\n\n // Setup event handlers\n this.setupEventHandlers(elements, state, key);\n\n // Store state\n this.activeDateRanges.set(key, { state, elements });\n\n // Initial update\n this.updateDateUI(key);\n\n this.afs.logger.info(`Date range added for ${key}`);\n }\n\n /**\n * Calculate min and max dates from items\n * @private\n */\n calculateMinMaxDates(key) {\n try {\n const validDates = Array.from(this.afs.items)\n .map(item => {\n if (!item || !item.dataset || !item.dataset[key]) {\n return null;\n }\n const date = new Date(item.dataset[key]);\n return isNaN(date.getTime()) ? null : date;\n })\n .filter(date => date !== null);\n \n if (validDates.length === 0) {\n // Return default date range if no valid dates found\n const today = new Date();\n return {\n min: new Date(today.getFullYear(), 0, 1), // January 1st of current year\n max: new Date(today.getFullYear(), 11, 31) // December 31st of current year\n };\n }\n \n return {\n min: new Date(Math.min(...validDates)),\n max: new Date(Math.max(...validDates))\n };\n } catch (error) {\n this.afs.logger.error('Error calculating date range:', error);\n // Return default date range on error\n const today = new Date();\n return {\n min: new Date(today.getFullYear(), 0, 1),\n max: new Date(today.getFullYear(), 11, 31)\n };\n }\n }\n\n /**\n * Create date picker elements\n * @private\n */\n createDateElements() {\n this.afs.logger.debug('Creating date picker elements');\n\n const container = document.createElement('div');\n container.className = 'afs-date-range-container';\n\n const startContainer = document.createElement('div');\n startContainer.className = 'afs-date-input-wrapper';\n \n const startLabel = document.createElement('label');\n startLabel.textContent = 'Start Date';\n \n const startInput = document.createElement('input');\n startInput.type = 'date';\n startInput.className = 'afs-date-input start-date';\n\n const endContainer = document.createElement('div');\n endContainer.className = 'afs-date-input-wrapper';\n \n const endLabel = document.createElement('label');\n endLabel.textContent = 'End Date';\n \n const endInput = document.createElement('input');\n endInput.type = 'date';\n endInput.className = 'afs-date-input end-date';\n\n startContainer.appendChild(startLabel);\n startContainer.appendChild(startInput);\n endContainer.appendChild(endLabel);\n endContainer.appendChild(endInput);\n\n container.appendChild(startContainer);\n container.appendChild(endContainer);\n\n return {\n container,\n startInput,\n endInput\n };\n }\n\n /**\n * Initialize date filter state\n * @private\n */\n initializeState(minDate, maxDate, format) {\n return {\n minDate,\n maxDate,\n currentStartDate: minDate,\n currentEndDate: maxDate,\n format\n };\n }\n\n /**\n * Append elements to container\n * @private\n */\n appendElements(container, elements) {\n container.appendChild(elements.container);\n }\n\n /**\n * Setup event handlers\n * @private\n */\n setupEventHandlers(elements, state, key) {\n this.afs.logger.debug(`Setting up event handlers for date range ${key}`);\n\n const { startInput, endInput } = elements;\n\n const handleDateChange = debounce(() => {\n const startDate = new Date(startInput.value);\n const endDate = new Date(endInput.value);\n\n if (!isNaN(startDate.getTime()) && !isNaN(endDate.getTime())) {\n state.currentStartDate = startDate;\n state.currentEndDate = endDate;\n this.applyDateFilter(key);\n }\n }, 300);\n\n startInput.addEventListener('change', handleDateChange);\n endInput.addEventListener('change', handleDateChange);\n }\n\n /**\n * Update date picker UI\n * @private\n */\n updateDateUI(key) {\n try {\n const { state, elements } = this.activeDateRanges.get(key);\n const { startInput, endInput } = elements;\n \n // Format dates for input\n const formatDate = date => {\n try {\n const d = new Date(date);\n if (isNaN(d.getTime())) {\n throw new Error('Invalid date');\n }\n return d.toISOString().split('T')[0];\n } catch (error) {\n this.afs.logger.error('Error formatting date:', error);\n return '';\n }\n };\n \n // Set min/max constraints\n startInput.min = formatDate(state.minDate);\n startInput.max = formatDate(state.maxDate);\n endInput.min = formatDate(state.minDate);\n endInput.max = formatDate(state.maxDate);\n \n // Set current values\n startInput.value = formatDate(state.currentStartDate);\n endInput.value = formatDate(state.currentEndDate);\n } catch (error) {\n this.afs.logger.error('Error updating date UI:', error);\n }\n }\n\n /**\n * Apply date filter\n * @private\n */\n applyDateFilter(key) {\n this.afs.logger.info(`Applying date filter for ${key}`);\n const { state } = this.activeDateRanges.get(key);\n \n this.afs.items.forEach(item => {\n try {\n // Check if item and dataset exist\n if (!item || !item.dataset || !item.dataset[key]) {\n this.afs.hideItem(item);\n return;\n }\n \n const itemDate = new Date(item.dataset[key]);\n \n // Check if date is valid\n if (isNaN(itemDate.getTime())) {\n this.afs.hideItem(item);\n return;\n }\n \n // Set time to midnight for consistent comparison\n const startDate = new Date(state.currentStartDate);\n startDate.setHours(0, 0, 0, 0);\n \n const endDate = new Date(state.currentEndDate);\n endDate.setHours(23, 59, 59, 999);\n \n const compareDate = new Date(itemDate);\n compareDate.setHours(0, 0, 0, 0);\n \n if (compareDate >= startDate && compareDate <= endDate) {\n this.afs.showItem(item);\n } else {\n this.afs.hideItem(item);\n }\n } catch (error) {\n this.afs.logger.error('Error filtering item by date:', error);\n this.afs.hideItem(item);\n }\n });\n \n this.afs.updateCounter();\n this.afs.urlManager.updateURL();\n this.afs.emit('dateFilter', {\n key,\n startDate: state.currentStartDate,\n endDate: state.currentEndDate\n });\n }\n\n /**\n * Get current date range\n * @param {string} key - Date range key\n * @returns {Object} Current date range\n */\n getDateRange(key) {\n const range = this.activeDateRanges.get(key);\n if (!range) return null;\n\n return {\n startDate: range.state.currentStartDate,\n endDate: range.state.currentEndDate\n };\n }\n\n /**\n * Set date range\n * @param {string} key - Date range key\n * @param {Date} startDate - Start date\n * @param {Date} endDate - End date\n */\n setDateRange(key, startDate, endDate) {\n const range = this.activeDateRanges.get(key);\n if (!range) return;\n\n range.state.currentStartDate = startDate;\n range.state.currentEndDate = endDate;\n this.updateDateUI(key);\n this.applyDateFilter(key);\n }\n\n /**\n * Remove date range\n * @param {string} key - Date range key\n */\n removeDateRange(key) {\n const range = this.activeDateRanges.get(key);\n if (!range) return;\n\n range.elements.container.remove();\n this.activeDateRanges.delete(key);\n this.afs.logger.info(`Date range removed for ${key}`);\n }\n}","/**\n * @fileoverview Advanced Filter System - Main Class\n */\nimport { Logger } from \"./core/Logger\";\nimport { Options } from \"./core/Options\";\nimport { State } from \"./core/State\";\nimport { StyleManager } from \"./styles/StyleManager\";\nimport { EventEmitter } from \"./core/EventEmitter\";\n\nimport { Filter } from \"./features/Filter\";\nimport { Search } from \"./features/Search\";\nimport { Sort } from \"./features/Sort\";\nimport { Pagination } from \"./features/Pagination\";\nimport { URLManager } from \"./features/URLManager\";\nimport { RangeFilter } from \"./features/RangeFilter\";\nimport { DateFilter } from \"./features/DateFilter\";\n\nimport { debounce } from \"./utils\";\n\n// Version\nexport const VERSION = '1.0.7';\n\nexport class AFS extends EventEmitter {\n /**\n * @param {Object} options - Configuration options\n */\n constructor(options = {}) {\n super();\n this.initializeCore(options);\n }\n\n /**\n * Initialize core components\n * @private\n */\n initializeCore(options) {\n try {\n this.options = new Options(options);\n this.logger = new Logger(\n this.options.get(\"debug\") || false,\n this.options.get(\"logLevel\") || \"info\",\n );\n this.state = new State();\n this.styleManager = new StyleManager(this.options);\n\n this.initializeDOM();\n this.initializeFeatures();\n this.setupLifecycle();\n } catch (error) {\n console.error(\"AFS initialization error:\", error);\n throw error;\n }\n }\n\n /**\n * Initialize DOM elements\n * @private\n */\n initializeDOM() {\n this.logger.debug(\"Initializing DOM elements\");\n\n this.container = document.querySelector(\n this.options.get(\"containerSelector\"),\n );\n if (!this.container) {\n throw new Error(\n `Container not found: ${this.options.get(\"containerSelector\")}`,\n );\n }\n\n this.items = this.container.querySelectorAll(\n this.options.get(\"itemSelector\"),\n );\n if (this.items.length === 0) {\n this.logger.warn(\"No items found in container\");\n }\n\n this.state.setState(\"items.total\", this.items.length);\n this.state.setState(\"items.visible\", new Set(this.items));\n }\n\n /**\n * Initialize features\n * @private\n */\n initializeFeatures() {\n this.logger.debug(\"Initializing features\");\n\n // Then initialize other features\n this.filter = new Filter(this);\n this.search = new Search(this);\n this.sort = new Sort(this);\n this.rangeFilter = new RangeFilter(this);\n this.urlManager = new URLManager(this);\n this.dateFilter = new DateFilter(this);\n this.pagination = new Pagination(this);\n\n // Apply styles\n this.styleManager.applyStyles();\n\n // Load initial state from URL\n this.urlManager.loadFromURL();\n }\n\n /**\n * Setup lifecycle events\n * @private\n */\n setupLifecycle() {\n if (this.options.get(\"responsive\")) {\n window.addEventListener(\"resize\", this.handleResize.bind(this));\n }\n\n if (this.options.get(\"preserveState\")) {\n document.addEventListener(\n \"visibilitychange\",\n this.handleVisibilityChange.bind(this),\n );\n }\n\n if (this.options.get(\"observeDOM\")) {\n this.setupMutationObserver();\n }\n\n this.emit(\"initialized\", {\n itemCount: this.items.length,\n options: this.options.export(),\n });\n }\n\n // Item Management Methods\n /**\n * Show item with animation\n * @public\n * @param {HTMLElement} item - Item to show\n */\n showItem(item) {\n // Update state first\n const visibleItems = this.state.getState().items.visible;\n visibleItems.add(item);\n this.state.setState(\"items.visible\", visibleItems);\n\n // Remove hidden class but keep opacity 0 initially\n item.classList.remove(this.options.get(\"hiddenClass\"));\n\n // Set initial animation state\n item.style.opacity = \"0\";\n item.style.transform = \"scale(0.95)\";\n item.style.display = \"\"; // Ensure item is not display: none\n\n // Force reflow before starting animation\n item.offsetHeight;\n\n // Add transition class if not present\n const transitionClass =\n this.options.get(\"transitionClass\") || \"afs-transition\";\n if (!item.classList.contains(transitionClass)) {\n item.classList.add(transitionClass);\n }\n\n // Start animation in next frame\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n // Double RAF for reliable animation\n item.style.opacity = \"1\";\n item.style.transform = \"scale(1)\";\n });\n });\n\n // Clean up after animation\n const duration = this.options.get(\"animationDuration\") || 300;\n setTimeout(() => {\n // Only clean up if item is still meant to be visible\n if (visibleItems.has(item)) {\n item.style.transform = \"\";\n item.style.opacity = \"\";\n }\n }, duration);\n }\n\n /**\n * Hide item with animation\n * @public\n * @param {HTMLElement} item - Item to hide\n */\n hideItem(item) {\n // Update state first\n const visibleItems = this.state.getState().items.visible;\n visibleItems.delete(item);\n this.state.setState(\"items.visible\", visibleItems);\n\n // Add transition class if not present\n const transitionClass =\n this.options.get(\"transitionClass\") || \"afs-transition\";\n if (!item.classList.contains(transitionClass)) {\n item.classList.add(transitionClass);\n }\n\n // Start hide animation\n requestAnimationFrame(() => {\n item.style.opacity = \"0\";\n item.style.transform = \"scale(0.95)\";\n });\n\n // Add hidden class and clean up after animation\n const duration = this.options.get(\"animationDuration\") || 300;\n setTimeout(() => {\n // Only hide if the item is still meant to be hidden\n if (!visibleItems.has(item)) {\n item.classList.add(this.options.get(\"hiddenClass\"));\n // Clean up styles\n item.style.transform = \"\";\n item.style.opacity = \"\";\n }\n }, duration);\n }\n\n /**\n * Add new items\n * @public\n */\n addItems(newItems) {\n const items = Array.isArray(newItems) ? newItems : [newItems];\n const fragment = document.createDocumentFragment();\n\n items.forEach((item) => {\n fragment.appendChild(item);\n this.state.getState().items.visible.add(item);\n });\n\n this.container.appendChild(fragment);\n this.items = this.container.querySelectorAll(\n this.options.get(\"itemSelector\"),\n );\n this.filter.applyFilters();\n }\n\n /**\n * Remove items\n * @public\n */\n removeItems(itemsToRemove) {\n const items = Array.isArray(itemsToRemove)\n ? itemsToRemove\n : [itemsToRemove];\n const visibleItems = this.state.getState().items.visible;\n\n items.forEach((item) => {\n visibleItems.delete(item);\n item.remove();\n });\n\n this.items = this.container.querySelectorAll(\n this.options.get(\"itemSelector\"),\n );\n this.updateCounter();\n }\n\n // State Management Methods\n /**\n * Save current state\n * @public\n */\n saveState() {\n if (!this.options.get(\"preserveState\")) return;\n\n const state = {\n filters: Array.from(this.filter.getActiveFilters()),\n search: this.search.getValue(),\n sort: this.sort.getCurrentSort(),\n pagination: this.pagination.getPageInfo(),\n timestamp: Date.now(),\n };\n\n localStorage.setItem(\"afs_state\", JSON.stringify(state));\n this.logger.debug(\"State saved\");\n }\n\n /**\n * Restore saved state\n * @public\n */\n restoreState() {\n if (!this.options.get(\"preserveState\")) return;\n\n try {\n const saved = localStorage.getItem(\"afs_state\");\n if (!saved) return;\n\n const state = JSON.parse(saved);\n if (Date.now() - state.timestamp > this.options.get(\"stateExpiry\")) {\n localStorage.removeItem(\"afs_state\");\n return;\n }\n\n this.setState(state);\n this.logger.debug(\"State restored\");\n } catch (error) {\n this.logger.error(\"Error restoring state:\", error);\n }\n }\n\n /**\n * Get current state\n * @public\n */\n getState() {\n return this.state.export();\n }\n\n /**\n * Set new state\n * @public\n */\n setState(newState) {\n this.state.import(newState);\n this.refresh();\n }\n\n // Update Methods\n /**\n * Update counter display\n * @public\n */\n updateCounter() {\n // Get counter element\n const counterElement = document.querySelector(\n this.options.get(\"counterSelector\"),\n );\n if (!counterElement) return;\n\n try {\n // Get count values\n const total = this.items.length;\n const visible = this.state.getState().items.visible.size;\n const filtered = total - visible;\n\n // Get counter options with defaults\n const counterOpts =\n this.options.get(\"counter\") || Options.defaults.counter;\n const template = counterOpts.template || \"Showing {visible} of {total}\";\n const formatter =\n counterOpts.formatter || ((num) => num.toLocaleString());\n\n // Format numbers\n const formattedVisible = formatter(visible);\n const formattedTotal = formatter(total);\n const formattedFiltered = formatter(filtered);\n\n // Build counter text\n let counterText = template\n .replace(\"{visible}\", formattedVisible)\n .replace(\"{total}\", formattedTotal)\n .replace(\"{filtered}\", formattedFiltered);\n\n // Add filtered count if enabled\n if (filtered > 0 && counterOpts.showFiltered) {\n const filteredTemplate =\n counterOpts.filteredTemplate || \"({filtered} filtered)\";\n counterText +=\n \" \" + filteredTemplate.replace(\"{filtered}\", formattedFiltered);\n }\n\n // Show no results message if applicable\n if (visible === 0 && counterOpts.noResultsTemplate) {\n counterText = counterOpts.noResultsTemplate;\n }\n\n // Update counter element\n counterElement.textContent = counterText;\n\n // Emit event\n this.emit(\"counterUpdated\", {\n total,\n visible,\n filtered,\n formattedTotal,\n formattedVisible,\n formattedFiltered,\n });\n } catch (error) {\n // Fallback to basic counter if anything fails\n this.logger.error(\"Error updating counter:\", error);\n counterElement.textContent = `${\n this.state.getState().items.visible.size\n }/${this.items.length}`;\n }\n }\n\n /**\n * Update options\n * @public\n */\n updateOptions(newOptions) {\n this.options.update(newOptions);\n this.styleManager.updateStyles(newOptions);\n this.refresh();\n }\n\n /**\n * Refresh system\n * @public\n */\n refresh() {\n this.logger.debug(\"Refreshing AFS\");\n\n this.items = this.container.querySelectorAll(\n this.options.get(\"itemSelector\"),\n );\n this.state.setState(\"items.total\", this.items.length);\n\n this.filter.applyFilters();\n this.search.search(this.search.getValue());\n this.pagination.update();\n\n this.emit(\"refreshed\", { itemCount: this.items.length });\n }\n\n // Event Handlers\n /**\n * Handle resize\n * @private\n */\n handleResize = debounce(() => {\n this.emit(\"resize\");\n this.refresh();\n }, 250);\n\n /**\n * Handle visibility change\n * @private\n */\n handleVisibilityChange() {\n if (document.hidden) {\n this.emit(\"hidden\");\n this.saveState();\n } else {\n this.emit(\"visible\");\n this.restoreState();\n }\n }\n\n /**\n * Setup mutation observer\n * @private\n */\n setupMutationObserver() {\n const observer = new MutationObserver((mutations) => {\n if (mutations.some((mutation) => mutation.type === \"childList\")) {\n this.refresh();\n }\n });\n\n observer.observe(this.container, {\n childList: true,\n subtree: true,\n });\n }\n\n // Utility Methods\n /**\n * Get version\n * @public\n */\n getVersion() {\n return VERSION;\n }\n\n /**\n * Check feature support\n * @public\n */\n isFeatureSupported(feature) {\n const supportedFeatures = {\n search: !!this.search,\n pagination: true,\n animation:\n typeof document.createElement(\"div\").style.transition !== \"undefined\",\n urlState: typeof window.history.pushState === \"function\",\n localStorage: (() => {\n try {\n localStorage.setItem(\"test\", \"test\");\n localStorage.removeItem(\"test\");\n return true;\n } catch (e) {\n return false;\n }\n })(),\n };\n\n return !!supportedFeatures[feature];\n }\n\n /**\n * Destroy instance\n * @public\n */\n destroy() {\n this.logger.debug(\"Destroying AFS instance\");\n\n // Remove event listeners\n window.removeEventListener(\"resize\", this.handleResize);\n document.removeEventListener(\n \"visibilitychange\",\n this.handleVisibilityChange,\n );\n\n // Destroy features\n this.filter.destroy();\n this.search.destroy();\n this.sort.destroy();\n this.pagination.destroy();\n this.rangeFilter.destroy();\n\n // Cleanup\n this.styleManager.removeStyles();\n this.state.reset();\n localStorage.removeItem(\"afs_state\");\n\n // Reset items\n this.items.forEach((item) => {\n item.style = \"\";\n item.classList.remove(\n this.options.get(\"hiddenClass\"),\n this.options.get(\"activeClass\"),\n );\n });\n\n this.emit(\"destroyed\");\n }\n}\n"],"names":["Logger","constructor","debug","arguments","length","undefined","logLevel","this","enabled","level","levels","error","warn","info","_log","currentLevelValue","timestamp","Date","toISOString","prefix","toUpperCase","_len","args","Array","_key","console","_len2","_key2","_len3","_key3","_len4","_key4","_len5","_key5","setDebugMode","hasOwnProperty","Options","static","containerSelector","itemSelector","filterButtonSelector","searchInputSelector","counterSelector","activeClass","hiddenClass","animationDuration","animationType","animationEasing","filterMode","searchKeys","debounceTime","dateFormat","counter","template","showFiltered","filteredTemplate","noResultsTemplate","formatter","num","toLocaleString","styles","slider","class","trackClass","thumbClass","valueClass","selectedClass","ui","showHistogram","bins","colors","primary","background","text","histogram","histogramActive","pagination","itemsPerPage","container","pageButtonClass","activePageClass","containerClass","scrollToTop","scrollOffset","scrollBehavior","userOptions","options","mergeOptions","defaults","initializeStyles","validate","defaultStyles","currentStyles","target","source","result","key","isArray","requiredSelectors","selector","Error","includes","get","path","split","reduce","obj","set","value","parts","last","pop","update","updates","reset","export","State","state","filters","current","Set","groups","Map","ranges","dateRanges","mode","groupMode","search","query","keys","sort","orders","items","visible","total","currentPage","totalPages","getState","setState","i","from","entries","import","importedState","StyleManager","styleElement","animation","duration","type","createBaseStyles","createRangeStyles","sliderStyles","createDateStyles","applyStyles","createPaginationStyles","createSearchStyles","textContent","document","createElement","head","appendChild","fallbackStyles","paginationOptions","buttonClass","searchClass","updateStyles","newOptions","removeStyles","remove","EventEmitter","events","onceEvents","on","eventName","callback","has","add","off","once","_this","onceWrapper","apply","delete","size","emit","forEach","removeAllListeners","clear","listenerCount","Animation","afs","animations","fade","in","opacity","transform","transitionTimingFunction","out","slide","scale","rotate","flip","zoom","bounce","blur","filter","skew","slideInLeft","slideInRight","fadeInUp","fadeInDown","bounceIn","applyShowAnimation","item","style","display","requestAnimationFrame","Object","assign","transition","applyHideAnimation","handleTransitionEnd","removeEventListener","addEventListener","setAnimation","Filter","filterButtons","activeFilters","currentFilters","filterGroups","sortOrders","setupFilters","logger","filterSelector","querySelectorAll","button","filterValue","dataset","bindFilterEvent","setLogic","logic","applyFilters","clearAllFilters","_","classList","allButton","findAllButton","urlManager","updateURL","resetFilters","toggleFilter","visibleItems","updateCounter","handleFilterClick","contains","previouslyVisible","itemMatchesFilters","emitFilterEvents","offsetHeight","itemCategories","categories","itemMatchesFilterGroups","itemMatchesAnyFilter","itemMatchesAllFilters","some","every","groupMatches","values","map","group","operator","matches","nowVisible","added","removed","addFilterGroup","groupId","validOperator","removeFilterGroup","setGroupMode","validMode","addFilter","removeFilter","setFilterMode","getActiveFilters","getFilterGroups","addFilterButton","sortWithOrder","newOrder","sortType","determineSortType","a","b","valueA","getSortValue","valueB","compareValues","reorderItems","order","shuffle","j","Math","floor","random","itemCount","isNaN","test","parseFloat","getTime","toLowerCase","comparison","fragment","createDocumentFragment","getCurrentSortOrder","clearSortOrders","checkbox","checked","setValue","refresh","removeFilterButton","destroy","debounce","func","wait","timeout","immediate","context","callNow","clearTimeout","setTimeout","later","Search","searchInput","minSearchLength","highlightClass","setupSearch","searchSelector","querySelector","bindSearchEvents","debouncedSearch","e","clearSearch","preventDefault","normalizedQuery","normalizeQuery","regex","createSearchRegex","searchText","getItemSearchText","showItem","highlightMatches","hideItem","removeHighlights","trim","replace","pattern","Boolean","word","join","RegExp","words","highlightedText","wordRegex","innerHTML","highlight","replaceWith","getValue","updateConfig","handleClear","handleEnter","Sort","sortButtons","setupSort","sortSelector","sortKey","direction","sortDirection","bindSortEvent","sortData","updateSortButtonState","btn","indicator","modifier","sortMultiple","criteria","sortWithComparator","comparator","data","getCurrentSort","addSortButton","removeSortButton","Pagination","setupPagination","log","className","itemsContainer","bindEvents","closest","page","goToPage","parseInt","max","ceil","currentState","updateVisibility","renderPagination","startIndex","endIndex","itemsToShow","slice","controls","createPaginationControls","showPrevNext","prevButton","createPageButton","disabled","active","range","calculatePageRange","start","createEllipsis","end","toString","nextButton","span","maxButtons","sideButtons","min","targetPage","previousPage","window","scrollTo","top","offsetTop","behavior","setPaginationMode","showAllItems","URLManager","defaultParams","URLSearchParams","setupPopStateHandler","loadFromURL","params","addFiltersToURL","addRangesToURL","addSearchToURL","addSortToURL","addPaginationToURL","pushState","filtersByType","_ref","currentMin","currentMax","queryString","newURL","location","pathname","href","history","filterParams","_ref2","isRegularFilter","_ref3","buttonFilter","searchQuery","sortParam","fromEntries","processFiltersFromURL","hasFilters","startsWith","processRangesFromURL","rangeKey","Number","str","processSearchFromURL","processSortFromURL","processPaginationFromURL","perPage","param","clearURL","getURLParams","hasParams","getParam","RangeFilter","activeRanges","styleManager","addRangeSlider","step","calculateMinMax","sliderUiOptions","histogramData","calculateHistogramData","counts","binEdges","elements","createSliderElements","initializeState","appendElements","setupEventHandlers","updateSliderUI","setupHistogramHighlight","track","createHistogramBars","selectedRange","minThumb","maxThumb","minValue","maxValue","createHistogram","index","bar","height","backgroundColor","binWidth","fill","binIndex","maxCount","count","round","bars","updateHistogram","minVal","maxVal","binStart","binEnd","isDragging","handleStart","isMin","moveHandler","moveEvent","evt","event","touches","createMoveHandler","stopHandler","applyFilter","passive","minPos","maxPos","clampedMinPos","clampedMaxPos","left","width","formatValue","toLocaleDateString","toFixed","clientX","rect","getBoundingClientRect","totalWidth","paddingPixels","PADDING","rawPercent","percent","stepped","getRangeValues","setRangeValues","removeRangeSlider","DateFilter","activeDateRanges","defaultFormat","addDateRange","minDate","maxDate","format","dates","calculateMinMaxDates","createDateElements","updateDateUI","validDates","date","today","getFullYear","startContainer","startLabel","startInput","endContainer","endLabel","endInput","currentStartDate","currentEndDate","handleDateChange","startDate","endDate","applyDateFilter","formatDate","d","itemDate","setHours","compareDate","getDateRange","setDateRange","removeDateRange","VERSION","super","initializeCore","initializeDOM","initializeFeatures","setupLifecycle","rangeFilter","dateFilter","handleResize","bind","handleVisibilityChange","setupMutationObserver","transitionClass","addItems","newItems","removeItems","itemsToRemove","saveState","getPageInfo","now","localStorage","setItem","JSON","stringify","restoreState","saved","getItem","parse","removeItem","newState","counterElement","filtered","counterOpts","formattedVisible","formattedTotal","formattedFiltered","counterText","updateOptions","hidden","MutationObserver","mutations","mutation","observe","childList","subtree","getVersion","isFeatureSupported","feature","urlState"],"mappings":"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"}
|