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
4
likes
160
points
73
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