smart_search_list 0.8.0 copy "smart_search_list: ^0.8.0" to clipboard
smart_search_list: ^0.8.0 copied to clipboard

Searchable list and grid widget for Flutter. Offline filtering, async loading, pagination, fuzzy search, grouped lists and grids, and multi-select. Zero dependencies.

0.8.0 - 2026-02-14 #

GridView support: search, filter, sort, pagination, grouping, and multi-select in grid layouts.

New Features #

  • SmartSearchGrid: Searchable grid widget with three constructors — SmartSearchGrid() (offline), .async() (server-driven), .controller() (external controller)
  • SliverSmartSearchGrid: Sliver variant for CustomScrollView integration, with sticky group headers
  • GridConfiguration: Layout configuration class for grid delegate, padding, physics, and scroll behavior
  • Grouped grids: Section headers with SliverToBoxAdapter (box) or SliverPersistentHeader (sliver, sticky) per group
  • Shared base: SmartSearchWidgetBase and SmartSearchStateMixin eliminate duplicated lifecycle code across all 4 widgets (internal, not exported)

Breaking Changes #

  • onRefresh removed from SliverSmartSearchList: Sliver widgets cannot contain a RefreshIndicator. Wrap your CustomScrollView with RefreshIndicator and call controller.refresh() directly instead
  • onSearchChanged on SliverSmartSearchList is no longer silently ignored: Previously the parameter was accepted but the callback was never called. It now fires post-debounce when the controller's query value changes. If you passed a callback that assumed it would not be invoked, remove it or update it

Improvements #

  • Grid examples: 5 new demos (grid, async grid, grouped grid, sliver grid, controller grid) — 19 total
  • Search highlighting in grid: SearchHighlightText demonstrated in grid example

Tests #

  • 499 tests (up from 312), including grid widget tests, grid controller swap tests, and addTearDown adoption for test isolation

Backward Compatibility #

  • All existing SmartSearchList and SliverSmartSearchList code compiles without changes, except for the two breaking changes noted above

0.7.5 - 2026-02-13 #

Fix 3 widget lifecycle bugs and 1 cache crash, add 89 edge case and property-based tests (312 total).

Bug Fixes #

  • Scroll controller swap: SmartSearchList.didUpdateWidget now handles scrollController prop changes — moves pagination and keyboard-dismiss listeners to the new controller, disposes internally-created ones, and tracks ownership correctly
  • Accessibility toggle: Changing searchSemanticsEnabled mid-lifecycle (without swapping the controller) now correctly adds or removes the announcement listener in both SmartSearchList and SliverSmartSearchList
  • Cache crash: maxCacheSize=0 with cacheResults=true no longer throws RangeError — the eviction guard now checks _cacheKeys.isNotEmpty before removing, and maxCacheSize=0 skips cache storage entirely

Internal #

  • Debug assertions: Added 49 assert() statements across 6 lib/ files for earlier detection of invalid state in debug mode — no impact in release builds

0.7.4 - 2026-02-13 #

Fix stale notification bug in async mode, improve pub.dev discoverability, and add disposal safety to README examples.

Bug Fixes #

  • Stale async notification: Superseded async search requests no longer fire a redundant notifyListeners() from _performSearch — eliminates one unnecessary widget rebuild per superseded request

Documentation #

  • README: Controller example now shows dispose() in a StatefulWidget context, consistent with the package's disposal safety emphasis

Metadata #

  • pub.dev topics: Replaced generic widget and pagination with fuzzy-search and accessibility — both are unique differentiators with low competition for better discoverability

0.7.3 - 2026-02-13 #

Fix cache corruption bug in pagination and sort cache invalidation, plus edge-case test coverage.

Bug Fixes #

  • Cache corruption fix: loadMore no longer corrupts cached first-page results — cache reads now use a defensive copy to prevent addAll from mutating cached entries
  • Sort cache invalidation: setSortBy now clears the cache before re-searching, matching the documented behavior and the pattern used by setFilter, updateCaseSensitive, and other config-change methods
  • Scroll listener leak: dispose() now unconditionally removes scroll listeners, preventing a leak when pagination or keyboard config changed between initState and dispose

Documentation #

  • README: Replaced print() in multi-select example with actionable setState pattern
  • Example app: Removed misleading caseSensitive/minSearchLength from searchConfig in .controller() mode advanced config example

0.7.2 - 2026-02-12 #

Pre-publish polish: migration guide, SearchHighlightText test coverage, and pub.dev archive optimization.

Documentation #

  • Migration guide: Added "Upgrading from v0.6.x" section to README with constructor migration instructions
  • GIF exclusion: Added doc/images/*.gif to .pubignore to save ~2.3 MB from pub.dev archive (GIFs load from GitHub raw URLs)
  • Example README: Replaced boilerplate with table listing all 14 demos

0.7.1 - 2026-02-12 #

README rewrite for pub.dev readiness with problem-solution opening, vertical GIF layout, and .controller() example.

Documentation #

  • README overhaul: Rewrote for pub.dev -- problem-solution opening paragraph, vertical GIF layout with captions at 320px, simplified installation to flutter pub add
  • Controller example: Added .controller() Quick Start section showing external filter, sort, and setItems usage
  • Removed badges: Deferred pub.dev badges until after first publish to avoid broken shield images
  • Removed Platform Support section: Folded "all platforms" into Features list (pub.dev shows this in sidebar)
  • Added Example App section: Prominent link to the 14-demo example app

Bug Fixes #

  • Spanish localization typo: Fixed 'Borrar busqueda' to 'Borrar búsqueda' in README and accessibility example

0.7.0 - 2026-02-12 #

Named constructors replace nullable params and runtime assertions with compile-time mode enforcement.

Breaking Changes #

  • Named constructors: SmartSearchList and SliverSmartSearchList now use three constructors:
    • SmartSearchList(items:, searchableFields:, ...) -- offline mode with client-side search
    • SmartSearchList.async(asyncLoader:, ...) -- async mode where the server handles search
    • SmartSearchList.controller(controller:, ...) -- fully controller-driven rendering
  • controller parameter removed from default and .async() constructors: External controllers are now exclusive to .controller(). This enforces clean mode separation -- each constructor serves exactly one data pattern.
  • cacheResults and maxCacheSize removed from .controller(): These only apply to internally-created controllers. Configure caching on your controller directly.
  • SmartSearchController.searchableFields: Changed from required to optional (nullable). Required only for offline search mode.
  • Removed assertions: The two runtime assertions ("Provide either items OR asyncLoader" and "Provide items, asyncLoader, or a controller") are removed. The compiler now enforces these constraints.

Migration #

  • Offline mode (items + searchableFields): No change required. The default constructor signature is identical.
  • Offline + external controller (items + controller): Change to .controller(controller: ..., and call controller.setItems(...) yourself. Pass searchableFields to the controller constructor. Pass debounceDelay, caseSensitive, minSearchLength, fuzzySearchEnabled, and fuzzyThreshold to the controller constructor instead of searchConfig.
  • Async mode (asyncLoader): Change SmartSearchList(asyncLoader: ..., searchableFields: ..., to SmartSearchList.async(asyncLoader: ..., and remove searchableFields:.
  • Async + external controller (asyncLoader + controller): Change to .controller(controller: ..., and call controller.setAsyncLoader(...) yourself. You must also call controller.search('') to trigger the initial load — the widget no longer does this automatically for external controllers.
  • Controller-only mode (controller without items/asyncLoader): Change to SmartSearchList.controller(controller: ..., and remove searchableFields:.
  • SmartSearchController: If you were passing searchableFields in async-only usage, you can now omit it.

Documentation #

  • README GIFs: Added basic search, fuzzy search, and async pagination demo GIFs

Backward Compatibility #

  • The default constructor signature is unchanged for offline mode -- existing offline code compiles without modification.
  • This is a breaking change for async, controller, and mixed-mode usage patterns.

0.6.1 - 2026-02-10 #

Dartdoc overhaul, bug fixes, and sliver test coverage.

Bug Fixes #

  • RichText replaced with Text.rich: SearchHighlightText now uses Text.rich for proper SelectionArea participation and textScaler accessibility support
  • Scroll listener leak: SmartSearchList now always removes scroll listeners before disposal, not just for external controllers
  • Controller swap safety: didUpdateWidget in both widgets now correctly handles external-to-null and null-to-external controller transitions without dangling references
  • Assertion consistency: SmartSearchList constructor assertions now match SliverSmartSearchList — rejects items + asyncLoader simultaneously even when controller is provided
  • _searchTerms performance: SliverSmartSearchList now computes search terms once per build instead of once per item

Documentation #

  • Complete dartdoc audit: ~70 missing doc comments added across all public classes, methods, fields, and typedefs
  • Effective Dart compliance: fragment summaries converted to complete sentences, third-person verb forms, redundant docs trimmed
  • Cross-references converted to bracket refs with imports for clickable pub.dev links
  • Filter/sort async vs offline behavior clarified, ItemBuilder.searchTerms lifecycle documented
  • Aligned SliverSmartSearchList docs with SmartSearchList for asyncLoader, groupBy, and accessibilityConfig

0.6.0 - 2026-02-10 #

Bug fixes and widget tests. Widgets now react to prop changes, cache key correctness fix, and first widget-level test coverage.

Bug Fixes #

  • didUpdateWidget support: SmartSearchList and SliverSmartSearchList now react to parent rebuilds — changing items, asyncLoader, caseSensitive, minSearchLength, fuzzySearchEnabled, fuzzyThreshold, or swapping an external controller after initial build now works correctly
  • Cache key fix: Calling setFilter with the same key but a different predicate no longer returns stale cached results — cache key now includes a filter predicate version counter

0.5.1 - 2026-02-01 #

Improved screen reader announcements for more reliable TalkBack/VoiceOver support.

Improvements #

  • Screen reader announcements: Replaced Semantics(liveRegion: true) with SemanticsService.sendAnnouncement() for more reliable TalkBack and VoiceOver feedback
  • Removed live region widget: Result count announcements no longer require an extra SizedBox in the widget tree

Requirements #

  • Minimum Flutter version bumped from 3.13.0 to 3.35.0 (required for SemanticsService.sendAnnouncement)

0.5.0 - 2026-02-01 #

Accessibility support with TalkBack/VoiceOver and full localization control.

New Features #

  • AccessibilityConfiguration: New configuration class for semantic labels and screen reader behavior
    • searchFieldLabel — custom label for the search text field
    • clearButtonLabel — custom tooltip for the clear button (default: 'Clear search')
    • searchButtonLabel — custom tooltip for the search button in onSubmit mode (default: 'Search')
    • resultsAnnouncementBuilder — customizable announcement text for result count changes (supports localization)
    • searchSemanticsEnabled — opt-out flag to disable all automatic semantics
  • Live Region Announcements: Result count changes are announced to screen readers via Semantics(liveRegion: true) — compatible with Android 16+ (which deprecated imperative SemanticsService.announce)
  • Semantic Headers: DefaultGroupHeader now includes Semantics(header: true) for proper screen reader navigation
  • Icon Tooltips: Clear and search IconButtons in DefaultSearchField now have tooltips for assistive technology

API Changes #

  • SmartSearchList gains accessibilityConfig parameter (default: const AccessibilityConfiguration())
  • SliverSmartSearchList gains accessibilityConfig parameter
  • DefaultSearchField gains accessibilityConfig parameter
  • New export: AccessibilityConfiguration

Example Updates #

  • New Accessibility example demonstrating localized labels and custom announcement text

0.4.0 - 2026-02-01 #

Fuzzy search with typo-tolerant matching, scored ranking, and built-in highlight widget.

New Features #

  • Fuzzy Search: Zero-dependency 3-phase matching algorithm for offline lists
    • Phase 1 — Exact substring (score 1.0): standard indexOf fast path
    • Phase 2 — Ordered subsequence (score 0.01–0.99): handles missing characters ("apl" → "Apple", "bnna" → "Banana") with consecutive-run scoring
    • Phase 3 — Bounded Levenshtein (score 0.01–0.59): handles extra/wrong characters and transpositions ("apole" → "Apple", "appel" → "Apple") with maxEditDistance = 2
    • Score-and-sort pipeline: exact matches always rank first, fuzzy matches scored by consecutive runs, density, position, and word boundaries
    • Configurable via SearchConfiguration.fuzzySearchEnabled (default: false) and SearchConfiguration.fuzzyThreshold (default: 0.3)
  • SearchHighlightText Widget: Built-in widget for highlighting matched characters
    • Works with both exact substring and fuzzy matching
    • Accepts text + searchTerms, renders highlighted TextSpan
    • Customizable matchStyle, highlightColor, maxLines, overflow
  • FuzzyMatcher: Public utility class for custom fuzzy matching
    • FuzzyMatcher.match(query, text) — returns score + match indices
    • FuzzyMatcher.matchFields(query, fields) — best score across multiple fields
    • FuzzyMatchResult with score and matchIndices for highlighting

API Changes #

  • SearchConfiguration gains fuzzySearchEnabled and fuzzyThreshold parameters
  • SmartSearchController gains fuzzySearchEnabled, fuzzyThreshold fields and updateFuzzySearchEnabled(), updateFuzzyThreshold() methods
  • New export: FuzzyMatcher, FuzzyMatchResult, SearchHighlightText

Performance Note #

  • Fuzzy search (especially Phase 3) is computationally heavier than plain substring search
  • For lists > 5,000 items, test performance on target devices or increase fuzzyThreshold to 0.6+ to skip expensive edit-distance matches
  • Subsequence matching (Phase 2) is O(m+n) per item and fast for any list size
  • Edit-distance fallback (Phase 3) only runs when Phases 1 and 2 fail — gibberish queries are rejected quickly by length and ratio guards

Example Updates #

  • New Fuzzy Search example: toggle fuzzy on/off, adjust threshold, SearchHighlightText demo

0.3.0 - 2026-01-31 #

Progress indicator builder and consistent state builder naming.

New Features #

  • Progress Indicator Builder: New progressIndicatorBuilder parameter on SmartSearchList
    • Shows an inline widget (e.g., thin progress bar, shimmer) below the search field during async operations
    • Unlike loadingStateBuilder (which replaces the entire list), this renders alongside existing content
    • Receives (BuildContext context, bool isLoading) — return SizedBox.shrink() when not loading
  • New ProgressIndicatorBuilder typedef

Bug Fixes #

  • Sliver searchTerms fix: SliverSmartSearchList now correctly forwards searchTerms to itemBuilder in grouped mode — previously, items inside grouped slivers received empty search terms, breaking highlighting

Improvements #

  • Cleaned up package description and documentation tone

Breaking Changes #

All state builders renamed for consistency — the *StateBuilder suffix now clearly indicates builders that replace the entire list area:

  • loadingBuilderloadingStateBuilder
  • errorBuildererrorStateBuilder
  • emptyBuilderemptyStateBuilder
  • emptySearchBuilderemptySearchStateBuilder
  • LoadingBuilderLoadingStateBuilder
  • ErrorBuilderErrorStateBuilder
  • EmptyBuilderEmptyStateBuilder
  • EmptySearchBuilderEmptySearchStateBuilder

Migration #

Find-and-replace in your code:

  • loadingBuilder:loadingStateBuilder:
  • errorBuilder:errorStateBuilder:
  • emptyBuilder:emptyStateBuilder:
  • emptySearchBuilder:emptySearchStateBuilder:

0.2.0 - 2026-01-31 #

Multi-select, grouped lists, and search trigger modes.

New Features #

  • Multi-Select Support: Select/deselect items with checkboxes via SelectionConfiguration
    • Controller methods: toggleSelection(), selectAll(), deselectAll(), selectWhere(), isSelected()
    • Configurable checkbox position (leading/trailing) and visibility
    • onSelectionChanged callback for reacting to selection changes
  • Grouped Lists: Group items into sections with headers via groupBy function
    • Automatic grouping — provide a groupBy: (item) => item.category function
    • DefaultGroupHeader with group name and item count
    • Custom groupHeaderBuilder for full control
    • groupComparator for ordering groups
    • Empty groups auto-removed after search/filter
    • Sticky headers in SliverSmartSearchList via SliverMainAxisGroup
  • Search Trigger Modes: Control when search fires via SearchTriggerMode enum
    • onEdit (default): debounced search on every keystroke
    • onSubmit: search only on keyboard submit or search button tap
    • searchImmediate() method for bypassing debounce programmatically

API Changes #

  • New SearchTriggerMode enum: { onEdit, onSubmit }
  • New SelectionConfiguration class with enabled, showCheckbox, position
  • New CheckboxPosition enum: { leading, trailing }
  • New GroupHeaderBuilder typedef
  • SearchConfiguration gains triggerMode parameter
  • SmartSearchList gains selectionConfig, groupBy, groupHeaderBuilder, groupComparator, onSelectionChanged
  • SliverSmartSearchList gains the same plus groupHeaderExtent for sticky header size
  • SmartSearchController gains multi-select methods and searchImmediate()
  • DefaultSearchField gains onSubmitted callback for submit mode

Breaking Changes #

  • Minimum Flutter version bumped from 3.10.0 to 3.13.0 (required for SliverMainAxisGroup)

Example Updates #

  • New Multi-Select example: checkbox list with select all/deselect all
  • New Grouped List example: products grouped by category with search

0.1.1 - 2026-01-31 #

Search term highlighting support and below-search widget slot.

New Features #

  • Search Term Highlighting: ItemBuilder now receives searchTerms parameter for highlighting matched text
  • Below Search Widget: New belowSearchWidget parameter for filters, chips, or custom controls
  • Pull to Refresh Examples: All example pages now demonstrate pull-to-refresh functionality

API Changes #

  • ItemBuilder<T> now includes optional searchTerms parameter:
    itemBuilder: (context, item, index, {searchTerms = const []}) {
      // Use searchTerms for highlighting
    }
    
  • Added belowSearchWidget parameter to SmartSearchList

Example Updates #

  • All examples updated with search terms highlighting support
  • Pull-to-refresh enabled across all example pages
  • Improved user experience with better visual feedback

0.1.0 - 2026-01-31 #

Initial release. A high-performance, zero-dependency searchable list package for Flutter.

Features #

  • High Performance: Tested with 10,000+ items at 60 FPS
  • Memory Safe: Proper disposal patterns, no memory leaks
  • Two Empty States: Different messages for "no data" vs "no search results"
  • Fully Customizable: Builder patterns for all UI components
  • Async Support: Built-in pagination and pull-to-refresh
  • Zero Dependencies: Only uses Flutter SDK

Core Components #

  • SmartSearchList<T> — Main widget with offline and async modes
  • SmartSearchController<T> — Robust controller with disposal safety
  • SearchConfiguration — Flexible search behavior configuration
  • ListConfiguration — List appearance and behavior options
  • PaginationConfiguration — Pagination settings

Reliability #

  • Race condition prevention with request IDs
  • Debounced search (300ms default)
  • Proper _isDisposed checks throughout
  • Automatic cleanup of timers and listeners

Builder Patterns #

All UI components are customizable:

  • searchFieldBuilder — Custom search field
  • itemBuilder — List item rendering (required)
  • loadingStateBuilder — Loading state
  • errorStateBuilder — Error state with retry
  • emptyStateBuilder — Empty state (no data)
  • emptySearchStateBuilder — Empty search results
  • separatorBuilder — List separators

Example App #

Complete example app with 7 demonstrations:

  • Basic offline list with configuration options
  • E-commerce products with filters/sorting
  • Async API loading with pagination
  • Empty states (no data vs no search results)
  • Sliver integration for CustomScrollView
  • Advanced configuration with external controller
  • Performance test with 10K items
12
likes
160
points
245
downloads

Publisher

unverified uploader

Weekly Downloads

Searchable list and grid widget for Flutter. Offline filtering, async loading, pagination, fuzzy search, grouped lists and grids, and multi-select. Zero dependencies.

Repository (GitHub)
View/report issues

Topics

#search #listview #gridview #fuzzy-search #accessibility

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on smart_search_list