advanced-filter-system 1.0.7 → 1.0.9

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.
@@ -1 +1 @@
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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"}
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/InputRangeFilter.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: \".afs-filter-container\",\n itemSelector: \".afs-filter-item\",\n filterButtonSelector: \".afs-btn-filter\",\n searchInputSelector: \".afs-filter-search\",\n counterSelector: \".afs-filter-counter\",\n\n // Classes\n activeClass: \"active\",\n hiddenClass: \"hidden\",\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 // Add new UI options\n ui: {\n showHistogram: false,\n bins: 10, // Number of bins for histogram\n track: {\n radius: \"0\", // Button radius\n background: \"#e5e7eb\", // Track color\n },\n thumb: {\n radius: \"50%\", // Button radius\n size: \"16px\", // Button size\n background: \"#000\", // Button color\n },\n histogram: {\n background: \"#e5e7eb\", // Histogram background\n bar: {\n background: \"#000\", // Bar color\n },\n },\n },\n },\n pagination: {\n ui: {\n button: {\n background: \"transparent\",\n border: \"1px solid #000\",\n borderRadius: \"4px\",\n padding: \"8px 12px\",\n color: \"#000\",\n active: {\n background: \"#000\",\n color: \"#fff\",\n },\n hover: {\n background: \"#000\",\n color: \"#fff\",\n },\n },\n },\n },\n colors: {\n primary: \"#000\",\n background: \"#e5e7eb\",\n text: \"#000\",\n },\n },\n\n // Slider\n slider: {\n containerClass: \"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\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 // Animation\n animation: {\n type: \"fade\",\n duration: 300,\n easing: \"ease-out\",\n inClass: \"afs-animation-enter\",\n outClass: \"afs-animation-leave\",\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 (\n source[key] !== null &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\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 (\n typeof this.options.animation.duration !== \"number\" ||\n this.options.animation.duration < 0\n ) {\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 (\n !Array.isArray(this.options.searchKeys) ||\n this.options.searchKeys.length === 0\n ) {\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","/**\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 }\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\") || \".afs-filter-item\";\n const filterButtonSelector = this.options.get(\"filterButtonSelector\") || \".afs-btn-filter\";\n const activeClass = this.options.get(\"activeClass\") || \"active\";\n const animationDuration = this.options.get(\"animation.duration\") || '300ms';\n const animationEasing = this.options.get(\"animation.easing\") || '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\");\n const sliderOptions = this.options.get(\"slider\") || {};\n const sliderStyles = styles.slider;\n const colors = styles.colors;\n\n const containerClass = sliderOptions.containerClass || \"afs-range-slider\";\n const trackClass = sliderOptions.trackClass || \"afs-range-track\";\n const thumbClass = sliderOptions.thumbClass || \"afs-range-thumb\";\n const valueClass = sliderOptions.valueClass || \"afs-range-value\";\n const selectedClass = sliderOptions.selectedClass || \"afs-range-selected\";\n\n return `\n /* Range Slider Styles */\n .${containerClass} {\n position: relative;\n width: auto;\n height: 40px;\n margin: 10px 0;\n padding: 0 8px;\n }\n\n .${trackClass} {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 100%;\n height: 4px;\n background: ${sliderStyles.ui.track.background || colors.background};\n border-radius: ${sliderStyles.ui.track.radius || \"0\"};\n }\n\n .${thumbClass} {\n position: absolute;\n top: 50%;\n width: ${sliderStyles.ui.thumb.size || \"16px\"};\n height: ${sliderStyles.ui.thumb.size || \"16px\"};\n background: ${sliderStyles.ui.thumb.background || colors.primary};\n border-radius: ${sliderStyles.ui.thumb.radius || \"50%\"};\n transform: translate(-50%, -50%);\n cursor: pointer;\n z-index: 2;\n }\n\n .${valueClass} {\n position: absolute;\n top: -20px;\n transform: translateX(-50%);\n font-size: 10px;\n color: ${colors.text};\n }\n\n .${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: ${sliderStyles.ui.histogram.background ||colors.background};\n min-height: 4px;\n transition: background-color 0.2s ease;\n }\n\n .afs-histogram-bar.active {\n background-color: ${sliderStyles.ui.histogram.bar.background || 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\").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 * Create date filter styles\n * @private\n * @returns {string} CSS styles\n */\n createInputRangeStyles() {\n const colors = this.options.get(\"styles\").colors;\n return `\n .afs-input-range-container {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 10px 0;\n }\n\n .afs-input-wrapper {\n flex: 1;\n }\n\n .afs-input-label {\n display: block;\n font-size: 0.875rem;\n color: ${colors.text};\n margin-bottom: 0.5rem;\n }\n\n .afs-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-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 /* Input range styles */\n ${this.createInputRangeStyles()}\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 styles = this.options.get(\"styles\");\n const paginationOptions = this.options.get(\"pagination\") || {};\n const colors = this.options.get(\"styles\").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 const paginationStyles = styles.pagination;\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: ${paginationStyles.ui.button.padding || '8px 12px'};\n border: ${paginationStyles.ui.button.border || '1px solid ' + colors.primary};\n border-radius: ${paginationStyles.ui.button.borderRadius || '4px'};\n cursor: pointer;\n transition: all 200ms ease-out;\n background: ${paginationStyles.ui.button.background || 'transparent' };\n color: ${paginationStyles.ui.button.color || colors.primary};\n }\n\n .${buttonClass}:hover {\n background: ${paginationStyles.ui.button.hover.background || colors.primary};\n color: ${paginationStyles.ui.button.hover.color || 'white'};\n }\n\n .${buttonClass}.${activeClass} {\n background: ${paginationStyles.ui.button.active.background || colors.primary};\n color: ${paginationStyles.ui.button.active.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\").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('animation.duration') || '300ms';\n const animation = this.animations[animationType]?.in || this.animations.fade.in;\n \n // Ensure display is set\n item.style.display = 'block';\n item.style.opacity = '0'; // Start with opacity 0\n \n // Apply animation in next frame\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('animation.duration') || '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('animation.type', 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 // Create a promise to track animations\n const animationPromises = [];\n \n // Show all items with animation\n this.afs.items.forEach(item => {\n const promise = new Promise(resolve => {\n item.classList.remove(this.afs.options.get('hiddenClass'));\n item.style.display = 'block'; // Ensure item is visible\n \n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(item, this.afs.options.get(\"animation.type\"));\n // Resolve after animation duration\n setTimeout(resolve, this.afs.options.get(\"animation.duration\") || 300);\n });\n });\n animationPromises.push(promise);\n });\n \n // Update state after all items are visible\n const visibleItems = new Set(this.afs.items);\n this.afs.state.setState(\"items.visible\", visibleItems);\n \n // Wait for all animations to complete\n Promise.all(animationPromises).then(() => {\n // Update counter\n this.afs.updateCounter();\n \n // Update URL\n this.afs.urlManager.updateURL();\n \n // Emit event\n this.afs.emit(\"filtersReset\");\n });\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 const activeFilters = Array.from(this.activeFilters);\n this.afs.logger.debug(\"Active filters:\", activeFilters);\n\n const previouslyVisible = new Set(this.afs.state.getState().items.visible);\n const visibleItems = new Set();\n\n // First determine visibility\n this.afs.items.forEach(item => {\n if (this.activeFilters.has(\"*\") || this.itemMatchesFilters(item)) {\n visibleItems.add(item);\n }\n });\n\n // Update state before animations\n this.afs.state.setState(\"items.visible\", visibleItems);\n\n // Track animation promises\n const animationPromises = [];\n\n // Apply animations\n this.afs.items.forEach(item => {\n const promise = new Promise(resolve => {\n if (visibleItems.has(item)) {\n // Show item\n item.classList.remove(this.afs.options.get('hiddenClass'));\n requestAnimationFrame(() => {\n this.animation.applyShowAnimation(item, this.afs.options.get(\"animation.type\"));\n setTimeout(resolve, parseFloat(this.afs.options.get(\"animation.duration\")) || 300);\n });\n } else {\n // Hide item\n requestAnimationFrame(() => {\n this.animation.applyHideAnimation(item, this.afs.options.get(\"animation.type\"));\n setTimeout(resolve, parseFloat(this.afs.options.get(\"animation.duration\")) || 300);\n });\n }\n });\n animationPromises.push(promise);\n });\n\n // Handle completion\n Promise.all(animationPromises).then(() => {\n // Ensure visible items remain visible\n visibleItems.forEach(item => {\n item.style.display = 'block';\n item.style.opacity = '1';\n });\n\n // Update UI\n this.afs.updateCounter();\n this.afs.urlManager.updateURL();\n\n this.afs.emit(\"filtersApplied\", {\n activeFilters,\n visibleItems: visibleItems.size,\n });\n });\n\n // Emit visibility change events\n this.emitFilterEvents(previouslyVisible, visibleItems);\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 Input range filter implementation for AFS\n */\n\nimport { debounce } from '../utils';\n\nexport class InputRangeFilter {\n constructor(afs) {\n this.afs = afs;\n this.activeRanges = new Map();\n }\n\n /**\n * @typedef {Object} InputRangeOptions\n * @property {string} key - Data attribute key\n * @property {HTMLElement} container - Container element\n * @property {number} [min] - Minimum value\n * @property {number} [max] - Maximum value\n * @property {number} [step] - Step value\n * @property {string} [label] - Label for the input range\n */\n\n /**\n * Add input range filter\n * @param {InputRangeOptions} options - Input range options\n */\n addInputRange({ key, container, min, max, step = 1, label = '' }) {\n this.afs.logger.debug(`Adding input range for ${key}`);\n\n if (!container) {\n this.afs.logger.error('Container element required for input range');\n return;\n }\n\n // Calculate min/max if not provided\n const values = this.calculateMinMax(key);\n min = min ?? values.min;\n max = max ?? values.max;\n\n // Create input elements\n const elements = this.createInputElements(label);\n const state = this.initializeState(min, max, step);\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.updateInputUI(key);\n\n this.afs.logger.info(`Input range added for ${key}`);\n }\n\n /**\n * Calculate min and max values from items\n * @private\n */\n calculateMinMax(key) {\n try {\n const values = Array.from(this.afs.items)\n .map(item => {\n if (!item || !item.dataset || !item.dataset[key]) {\n return null;\n }\n const value = parseFloat(item.dataset[key]);\n return isNaN(value) ? null : value;\n })\n .filter(value => value !== null);\n\n if (values.length === 0) {\n return {\n min: 0,\n max: 100\n };\n }\n\n return {\n min: Math.min(...values),\n max: Math.max(...values)\n };\n } catch (error) {\n this.afs.logger.error('Error calculating range:', error);\n return {\n min: 0,\n max: 100\n };\n }\n }\n\n /**\n * Create input elements\n * @private\n */\n /**\n * Create input elements\n * @private\n */\ncreateInputElements(label) {\n const container = document.createElement('div');\n container.className = 'afs-input-range-container';\n\n if (label) {\n const labelElement = document.createElement('div');\n labelElement.className = 'afs-input-range-label';\n labelElement.textContent = label;\n container.appendChild(labelElement);\n }\n\n // Min input wrapper\n const minWrapper = document.createElement('div');\n minWrapper.className = 'afs-input-wrapper';\n \n const minLabel = document.createElement('label');\n minLabel.textContent = 'Min';\n minLabel.className = 'afs-input-label';\n \n const minInput = document.createElement('input');\n minInput.type = 'number';\n minInput.className = 'afs-input min';\n\n minWrapper.appendChild(minLabel);\n minWrapper.appendChild(minInput);\n\n // Max input wrapper\n const maxWrapper = document.createElement('div');\n maxWrapper.className = 'afs-input-wrapper';\n \n const maxLabel = document.createElement('label');\n maxLabel.textContent = 'Max';\n maxLabel.className = 'afs-input-label';\n \n const maxInput = document.createElement('input');\n maxInput.type = 'number';\n maxInput.className = 'afs-input max';\n\n maxWrapper.appendChild(maxLabel);\n maxWrapper.appendChild(maxInput);\n\n container.appendChild(minWrapper);\n container.appendChild(maxWrapper);\n\n return {\n container,\n minInput,\n maxInput\n };\n}\n\n /**\n * Initialize input range state\n * @private\n */\n initializeState(min, max, step) {\n return {\n min,\n max,\n step,\n currentMin: min,\n currentMax: max\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 const { minInput, maxInput } = elements;\n\n const handleInputChange = debounce(() => {\n const minValue = parseFloat(minInput.value);\n const maxValue = parseFloat(maxInput.value);\n\n if (!isNaN(minValue) && !isNaN(maxValue)) {\n state.currentMin = Math.max(state.min, Math.min(maxValue, minValue));\n state.currentMax = Math.min(state.max, Math.max(minValue, maxValue));\n this.updateInputUI(key);\n this.applyFilter(key);\n }\n }, 300);\n\n minInput.addEventListener('input', handleInputChange);\n maxInput.addEventListener('input', handleInputChange);\n }\n\n /**\n * Update input UI\n * @private\n */\n updateInputUI(key) {\n try {\n const { state, elements } = this.activeRanges.get(key);\n const { minInput, maxInput } = elements;\n\n // Set constraints\n minInput.min = state.min;\n minInput.max = state.max;\n minInput.step = state.step;\n maxInput.min = state.min;\n maxInput.max = state.max;\n maxInput.step = state.step;\n\n // Set current values\n minInput.value = state.currentMin;\n maxInput.value = state.currentMax;\n } catch (error) {\n this.afs.logger.error('Error updating input UI:', error);\n }\n }\n\n /**\n * Apply filter\n * @private\n */\n applyFilter(key) {\n this.afs.logger.info(`Applying input filter for ${key}`);\n const { state } = this.activeRanges.get(key);\n\n this.afs.items.forEach(item => {\n try {\n if (!item || !item.dataset || !item.dataset[key]) {\n this.afs.hideItem(item);\n return;\n }\n\n const itemValue = parseFloat(item.dataset[key]);\n if (isNaN(itemValue)) {\n this.afs.hideItem(item);\n return;\n }\n\n if (itemValue >= state.currentMin && itemValue <= state.currentMax) {\n this.afs.showItem(item);\n } else {\n this.afs.hideItem(item);\n }\n } catch (error) {\n this.afs.logger.error('Error filtering item:', error);\n this.afs.hideItem(item);\n }\n });\n\n this.afs.updateCounter();\n this.afs.urlManager.updateURL();\n this.afs.emit('inputRangeFilter', {\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 getRange(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 };\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 setRange(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.updateInputUI(key);\n this.applyFilter(key);\n }\n\n /**\n * Remove input range\n * @param {string} key - Range key\n */\n removeInputRange(key) {\n const range = this.activeRanges.get(key);\n if (!range) return;\n\n range.elements.container.remove();\n this.activeRanges.delete(key);\n this.afs.logger.info(`Input range removed for ${key}`);\n }\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\n if (!this.afs.options.get('pagination.enabled')) {\n return;\n }\n\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 this.options = this.afs.options.get(\"slider\");\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 colors = styles.colors || this.afs.styleManager.defaultStyles.colors;\n const sliderOptions = this.afs.options.get(\"slider\") || {};\n\n const container = document.createElement(\"div\");\n container.className = \"afs-range-container\";\n\n const slider = document.createElement(\"div\");\n slider.className = sliderOptions.containerClass;\n\n const track = document.createElement(\"div\");\n track.className = sliderOptions.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 = sliderOptions.selectedClass;\n\n const minThumb = document.createElement(\"div\");\n minThumb.className = sliderOptions.thumbClass;\n\n const maxThumb = document.createElement(\"div\");\n maxThumb.className = sliderOptions.thumbClass;\n\n const minValue = document.createElement(\"div\");\n minValue.className = sliderOptions.valueClass;\n\n const maxValue = document.createElement(\"div\");\n maxValue.className = sliderOptions.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 { InputRangeFilter } from \"./features/InputRangeFilter\";\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.9';\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 this.inputRangeFilter = new InputRangeFilter(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","filterMode","searchKeys","debounceTime","dateFormat","counter","template","showFiltered","filteredTemplate","noResultsTemplate","formatter","num","toLocaleString","styles","slider","ui","showHistogram","bins","track","radius","background","thumb","size","histogram","bar","pagination","button","border","borderRadius","padding","color","active","hover","colors","primary","text","containerClass","trackClass","thumbClass","valueClass","selectedClass","itemsPerPage","container","pageButtonClass","activePageClass","scrollToTop","scrollOffset","scrollBehavior","animation","type","duration","easing","inClass","outClass","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","createBaseStyles","animationDuration","animationEasing","createRangeStyles","sliderOptions","sliderStyles","createDateStyles","createInputRangeStyles","applyStyles","createPaginationStyles","createSearchStyles","textContent","document","createElement","head","appendChild","fallbackStyles","paginationOptions","buttonClass","paginationStyles","searchClass","updateStyles","newOptions","removeStyles","remove","EventEmitter","events","onceEvents","on","eventName","callback","has","add","off","once","_this","onceWrapper","apply","delete","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","animationType","style","display","requestAnimationFrame","Object","assign","transition","applyHideAnimation","handleTransitionEnd","removeEventListener","addEventListener","setAnimation","Filter","filterButtons","activeFilters","currentFilters","filterGroups","sortOrders","setupFilters","logger","filterSelector","querySelectorAll","filterValue","dataset","bindFilterEvent","setLogic","logic","applyFilters","clearAllFilters","_","classList","allButton","findAllButton","urlManager","updateURL","resetFilters","toggleFilter","animationPromises","promise","Promise","resolve","setTimeout","push","visibleItems","all","then","updateCounter","handleFilterClick","contains","previouslyVisible","itemMatchesFilters","parseFloat","emitFilterEvents","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","getTime","toLowerCase","comparison","fragment","createDocumentFragment","getCurrentSortOrder","clearSortOrders","checkbox","checked","setValue","refresh","removeFilterButton","destroy","debounce","func","wait","timeout","immediate","context","callNow","clearTimeout","later","InputRangeFilter","activeRanges","addInputRange","_ref","min","max","step","label","calculateMinMax","elements","createInputElements","initializeState","appendElements","setupEventHandlers","updateInputUI","className","labelElement","minWrapper","minLabel","minInput","maxWrapper","maxLabel","maxInput","currentMin","currentMax","handleInputChange","minValue","maxValue","applyFilter","hideItem","itemValue","showItem","getRange","range","setRange","removeInputRange","Search","searchInput","minSearchLength","highlightClass","setupSearch","searchSelector","querySelector","bindSearchEvents","debouncedSearch","e","clearSearch","preventDefault","normalizedQuery","normalizeQuery","regex","createSearchRegex","searchText","getItemSearchText","highlightMatches","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","itemsContainer","bindEvents","closest","page","goToPage","parseInt","ceil","currentState","updateVisibility","renderPagination","startIndex","endIndex","itemsToShow","slice","controls","createPaginationControls","showPrevNext","prevButton","createPageButton","disabled","class","calculatePageRange","start","createEllipsis","end","toString","nextButton","span","maxButtons","sideButtons","targetPage","offsetHeight","previousPage","window","scrollTo","top","offsetTop","behavior","setPaginationMode","showAllItems","URLManager","defaultParams","URLSearchParams","setupPopStateHandler","loadFromURL","params","addFiltersToURL","addRangesToURL","addSearchToURL","addSortToURL","addPaginationToURL","pushState","filtersByType","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","styleManager","addRangeSlider","sliderUiOptions","histogramData","calculateHistogramData","counts","binEdges","createSliderElements","updateSliderUI","setupHistogramHighlight","createHistogramBars","selectedRange","minThumb","maxThumb","createHistogram","index","height","backgroundColor","binWidth","fill","binIndex","maxCount","count","round","bars","updateHistogram","minVal","maxVal","binStart","binEnd","isDragging","handleStart","isMin","moveHandler","moveEvent","evt","event","touches","createMoveHandler","stopHandler","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","inputRangeFilter","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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"}