Skip to main content

super_auto_suggestion_box 1.7.0 copy "super_auto_suggestion_box: ^1.7.0" to clipboard
super_auto_suggestion_box: ^1.7.0 copied to clipboard

Super Auto Suggestion Box is a GeniusLink Flutter package providing a typeahead/combobox with local and remote sources, fuzzy matching, single or multi-select, free-text entry, progressive fallback, i [...]

super_auto_suggestion_box #

Pub style: flutter_lints

A Flutter typeahead / combobox for local and remote data with rich suggestion rows, fuzzy matching, single or multi-select, advanced search, validation, recents, inline creation, paging, shadow-hint completion, and controller-driven ERP form workflows.

SuperAutoSuggestionsBox<T> keeps domain data as raw T values. A SuperAutoSuggestionBuilder<T> converts each value into searchable and renderable SuperAutoSuggestionsItem<T> metadata at the presentation boundary.

Current package version: 1.6.0.

Table of contents

Features #

  • Local, asynchronous, hybrid, remote-fallback, and paged suggestion sources.
  • contains, prefix, words, and fuzzy matching strategies.
  • Relevance-ranked fuzzy results and matched-text highlighting.
  • Single-select and multi-select workflows using raw domain values.
  • Rich rows with title, description, trailing metadata, icons, groups, keywords, enabled state, and custom widgets.
  • BuildContext-aware SuperAutoSuggestionBuilder<T> for theme, localization, MediaQuery, and inherited design-system values.
  • Inline text-box search, Advanced Search, or both search surfaces.
  • Recent suggestions with caller-controlled persistence callbacks.
  • Server-side zero-based paging and infinite-scroll support.
  • Inline creation for missing values with synchronous or asynchronous creation.
  • Shadow-hint completion with keyboard-first Tab acceptance.
  • Form integration, required validation, custom validators, and configurable validation placement.
  • Read-only, disabled, fixed, bare/embed, and record-binding-friendly states.
  • Keyboard, focus, formatter, directionality, and text-input configuration for ERP identifiers and general text entry.
  • English and Arabic package localization, LTR/RTL support, and shared GeniusLink theming through super_core.

Getting started #

Install #

Add the package to pubspec.yaml:

dependencies:
  super_auto_suggestion_box: ^1.7.0

Then resolve dependencies using your normal Flutter workflow.

Import #

import 'package:super_auto_suggestion_box/super_auto_suggestion_box.dart';

The package barrel exports the suggestion box feature, localization, super_form_field integration types used by the widget, and the shared super_core foundation used by the component.

Localization #

Register the package localization delegate when the package-owned strings should follow the application's locale:

MaterialApp(
  localizationsDelegates: const [
    SuperAutoSuggestionLocalization.delegate,
  ],
  supportedLocales: SuperAutoSuggestionLocalization.supportedLocales,
);

The package also has a safe English fallback when its delegate is not installed.

Basic usage #

A source and a suggestion builder are required. The source owns raw data; the builder owns searchable and visual metadata.

final units = <String>['Each', 'Box', 'Carton'];

SuperAutoSuggestionsItem<String> unitSuggestion(
  BuildContext context,
  List<String> items,
  int index,
  String unit,
) {
  return SuperAutoSuggestionsItem<String>(
    value: unit,
    titleText: unit,
  );
}

SuperAutoSuggestionsBox<String>(
  source: SuperAutoSuggestionSources.list<String>(units),
  suggestionBuilder: unitSuggestion,
  hintText: 'Type or pick...',
  onSelectionChanged: (selected) {
    final value = selected.isEmpty ? null : selected.last;
    debugPrint('Selected: $value');
  },
);

A controller is optional. Use one when the host needs imperative selection, focus, form, recents, query, or paging state.

Suggestion builder #

Since 1.6.0, the canonical builder is:

typedef SuperAutoSuggestionBuilder<T> =
    SuperAutoSuggestionsItem<T> Function(
      BuildContext context,
      List<T> items,
      int index,
      T element,
    );

The active BuildContext can safely read inherited presentation values:

SuperAutoSuggestionsItem<Account> accountSuggestion(
  BuildContext context,
  List<Account> items,
  int index,
  Account account,
) {
  final colors = Theme.of(context).colorScheme;

  return SuperAutoSuggestionsItem<Account>(
    value: account,
    titleText: account.name,
    descriptionText: account.code,
    trailingText: account.balanceText,
    icon: Icon(Icons.account_balance_outlined, color: colors.primary),
    keywords: [account.code],
  );
}

titleText is the canonical searchable, displayed, and committed title. keywords extend the searchable haystack without changing the visible title.

Suggestion sources #

Context-aware fetch callbacks #

Starting with 1.7.0, remote fetch callbacks receive the active BuildContext before the query arguments. This lets the request read inherited values such as locale or application-scoped configuration at the moment the request starts.

final source = SuperAutoSuggestionSources.async<Account>(
  (context, query) async {
    final locale = Localizations.localeOf(context);
    return repository.searchAccounts(query, locale: locale);
  },
);

Hybrid and remote-fallback sources use fetch: (context, query). Paged sources use (context, query, page). Local list, strings, and fuzzy sources remain synchronous.

Use SuperAutoSuggestionSources for normal source construction.

Factory Use case Concrete source
list In-memory data SuperAutoListSuggestionsSource<T>
strings In-memory String values SuperAutoListSuggestionsSource<String>
fuzzy Ranked fuzzy in-memory search SuperAutoListSuggestionsSource<T>
async Remote or repository search SuperAutoAsyncSuggestionsSource<T>
hybrid Local results plus remote expansion SuperAutoHybridSuggestionsSource<T>
remoteFallback Local-first search with sparse-result fallback SuperAutoRemoteFallbackSuggestionsSource<T>
paged Server-side paging / infinite scroll SuperAutoPagedSuggestionsSource<T>

Local list #

final source = SuperAutoSuggestionSources.list<Account>(
  accounts,
  match: AutoSuggestionMatch.contains,
  caseSensitive: false,
);

For plain strings:

final source = SuperAutoSuggestionSources.strings(
  ['Aden', 'Amman', 'Cairo', 'Dubai'],
  match: AutoSuggestionMatch.prefix,
);

The widget still receives a suggestionBuilder, including when strings() is used.

Fuzzy #

final source = SuperAutoSuggestionSources.fuzzy<Account>(accounts);

Fuzzy results are ranked by match quality rather than preserving only insertion order.

Async #

final source = SuperAutoSuggestionSources.async<Account>(
  (context, query) => repository.searchAccounts(query),
  initialItems: initiallyKnownAccounts,
);

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  debounce: const Duration(milliseconds: 300),
);

initialItems seed value resolution; they are not automatically returned as the result of every async query.

Hybrid #

Hybrid search always lets local matches contribute to the final result and fetches remotely when the local result count is below the configured threshold.

final source = SuperAutoSuggestionSources.hybrid<Account>(
  initialItems: recentAccounts,
  fetch: repository.searchAccounts,
  remoteThreshold: 3,
  remoteMinChars: 2,
);

The remote condition is localMatches.length < remoteThreshold.

When the source is used by SuperAutoSuggestionsBox, prefer the widget's minResult to control the progressive remote-fetch threshold. remoteThreshold remains relevant to direct source query/progressive calls.

Remote fallback #

Use remoteFallback when remote data should primarily extend sparse local results:

final source = SuperAutoSuggestionSources.remoteFallback<Account>(
  initialItems: recentAccounts,
  fetch: repository.searchAccounts,
  remoteThreshold: 5,
  remoteMinChars: 2,
);

The remote condition is inclusive: localMatches.length <= remoteThreshold.

Inside SuperAutoSuggestionsBox, minResult is the widget-level inclusive threshold for progressive remote fetching. The source-level remoteThreshold is retained for direct source calls.

Paged #

The page callback uses zero-based page indexes. Page 0 is the first page.

final source = SuperAutoSuggestionSources.paged<Account>(
  (context, query, page) async {
    final response = await repository.searchAccountsPage(
      query: query,
      page: page,
    );

    return SuperSuggestionsPage<Account>(
      items: response.items,
      hasMore: response.hasMore,
    );
  },
  resolveFrom: initiallySelectedAccounts,
);

Fetched pages are retained for value resolution. The paged source does not de-duplicate rows across pages, so APIs that can repeat rows should be normalized in the repository or fetch callback.

Matching strategies #

AutoSuggestionMatch supports:

Strategy Behavior
contains Query appears anywhere in the searchable text.
prefix Searchable text starts with the query.
words Every whitespace-separated query token must appear.
fuzzy Query characters appear in order with gaps allowed.

Example:

final source = SuperAutoSuggestionSources.list<Account>(
  accounts,
  match: AutoSuggestionMatch.words,
);

Use the box's highlightMatch and highlightMatches options to control row highlighting behavior.

Search modes #

SuperAutoSuggestionsMode controls which search surface is exposed:

  • textBox: editable field with anchored suggestions.
  • advanceView: field-like launcher for the Advanced Search view.
  • both: editable field plus Advanced Search access.
SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  mode: SuperAutoSuggestionsMode.both,
);

When mode is omitted, desktop platforms default to textBox; Android, iOS, and Fuchsia default to advanceView.

A custom Advanced Search surface can be supplied with advancedSearchBuilder.

Multi-select #

Initial selected values belong to the controller. Multi-select behavior belongs to the widget.

final controller = SuperAutoSuggestionsController<Account>(
  initialSelected: initialAccounts,
);

SuperAutoSuggestionsBox<Account>(
  controller: controller,
  source: source,
  suggestionBuilder: accountSuggestion,
  multiSelect: true,
  onSelectionChanged: (selected) {
    debugPrint('Selected ${selected.length} accounts');
  },
);

Read the current values from controller.selectedItems.

Recent suggestions #

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  showRecents: true,
  maxRecents: 8,
  initialRecents: persistedRecents,
  onRecentsChanged: persistRecents,
);

Recents are most-recent-first. The package owns runtime ordering while the host can persist changes through onRecentsChanged.

Inline create #

When onCreate is set and a non-empty query has no match, the component can show a create action in both inline and Advanced Search surfaces.

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  onCreate: (query) async {
    return repository.createAccount(name: query);
  },
  createLabelBuilder: (query) => 'Create "$query"',
);

Return the created raw T to commit it, or null to cancel creation.

Shadow-hint completion #

Shadow hints render the untyped suffix of the highlighted prefix match without changing the actual editable value.

SuperAutoSuggestionsBox<String>(
  source: source,
  suggestionBuilder: referenceSuggestion,
  showShadowHint: true,
  completeShadowHintOnTab: true,
);

Forward Tab accepts a visible shadow hint. Shift+Tab keeps reverse focus traversal. If no shadow hint is visible, Tab keeps normal focus traversal or uses onTabNext when supplied.

Forms and validation #

SuperAutoSuggestionsBox<T> participates in Flutter forms with the committed raw T? value.

final formKey = GlobalKey<FormState>();
final fieldKey = GlobalKey<FormFieldState<Account>>();

final controller = SuperAutoSuggestionsController<Account>(
  formFieldKey: fieldKey,
);

Form(
  key: formKey,
  child: SuperAutoSuggestionsBox<Account>(
    controller: controller,
    source: source,
    suggestionBuilder: accountSuggestion,
    required: true,
    validator: (account) {
      if (account != null && account.isBlocked) {
        return 'Blocked accounts cannot be selected';
      }
      return null;
    },
    autovalidateMode: AutovalidateMode.onUserInteraction,
    validationPosition: ValidationPosition.underBox,
  ),
);

Validation is selection-driven. Use FormState.validate() for form-level validation and controller state for the selected value.

If autovalidateMode is omitted, the field inherits the nearest Form setting and otherwise defaults to AutovalidateMode.disabled.

Debounce and minResult #

Local matching is never debounced. On every query change, data that is already available in memory is matched immediately and can be rendered without waiting for the debounce window.

SuperAutoSuggestionsBox.debounce applies only to work that reaches an external source: remote fetch callbacks, progressive loadMore work, and the first request of a paged source. Version 1.7.0 uses easy_debounce, so rapid keystrokes reset only the pending remote request.

SuperAutoSuggestionsBox<Account>(
  source: SuperAutoSuggestionSources.async<Account>(
    (context, query) => repository.searchAccounts(query),
    initialItems: cachedAccounts,
  ),
  debounce: const Duration(milliseconds: 300),
  minResult: 0,
  suggestionBuilder: accountSuggestion,
);

In this example, cachedAccounts are matched immediately. If the local match count allows remote loading, the repository request starts after 300ms. Changing the debounce duration never delays local filtering.

The built-in sources behave as follows:

  • list / strings / fuzzy: local-only matching; debounce is ignored.
  • async: initialItems and previously cached results are matched immediately; remote fetch is debounced when more data is needed.
  • hybrid / remoteFallback: local matching is immediate; only the remote augmentation step is debounced.
  • paged: page requests are external work and remain debounced; resolveFrom continues to be a resolution cache rather than a local search collection.

SuperAutoSuggestionSources.async accepts match and caseSensitive for its local cache matching:

final source = SuperAutoSuggestionSources.async<Account>(
  (context, query) => repository.searchAccounts(query),
  initialItems: cachedAccounts,
  match: AutoSuggestionMatch.contains,
  caseSensitive: false,
);

Use Duration.zero when remote requests should start immediately. Values such as 300ms or 800ms reduce external request churn without making local search feel slower.

minResult #

minResult is evaluated against the immediate local result count. Remote work is eligible when the local count is less than or equal to minResult. The default is 0, so a remote request is needed only when local matching returns no rows.

SuperAutoSuggestionsBox<Account>(
  source: SuperAutoSuggestionSources.hybrid<Account>(
    initialItems: recentAccounts,
    fetch: (context, query) => repository.searchAccounts(query),
    remoteMinChars: 2,
  ),
  minResult: 3,
  debounce: const Duration(milliseconds: 300),
  suggestionBuilder: accountSuggestion,
);

With minResult: 3, 0, 1, 2, or 3 local rows are shown immediately and the remote fetch is then scheduled through debounce. With 4 or more local matches, no remote request is started. Source-specific minimum query-length rules still apply.

A pure async source with an empty local cache naturally has 0 local results, so its remote fetch proceeds after debounce. As remote results are cached, later queries can match those cached values immediately before deciding whether another external request is necessary.

Controller #

Create a SuperAutoSuggestionsController<T> when the host needs direct state or commands:

final controller = SuperAutoSuggestionsController<Account>(
  initialValue: initialAccount,
  allowFreeText: false,
  focusNode: accountFocusNode,
);

Common reads:

controller.query;
controller.results;
controller.suggestions;
controller.selected;
controller.selectedItems;
controller.recents;
controller.isOpen;
controller.isLoading;
controller.isLoadingMore;
controller.isPaged;
controller.hasMore;
controller.error;

Common commands:

controller.open();
controller.close();
controller.toggle();
controller.setText('1001');
controller.refresh();
controller.selectByValue(account);
controller.setSelectedItems(accounts);
controller.clearSelection();
controller.setRecents(accounts);
controller.clearRecents();
controller.loadNextPage();
controller.clear();

The widget owns the source, builder, query timing, recents configuration, result limit, and multi-select configuration; the controller is the runtime state/command surface.

Rich and custom rows #

Use SuperAutoSuggestionsItem<T> for default rich rows:

SuperAutoSuggestionsItem<Account>(
  value: account,
  titleText: account.name,
  descriptionText: account.code,
  trailingText: account.balanceText,
  group: account.typeLabel,
  iconData: Icons.account_balance_outlined,
  keywords: [account.code, account.alias],
  enabled: account.isActive,
);

Custom supporting widgets can be supplied directly:

SuperAutoSuggestionsItem<Account>(
  value: account,
  titleText: account.name,
  description: Text(account.code),
  trailing: Chip(label: Text(account.statusLabel)),
  icon: const Icon(Icons.account_balance_outlined),
);

For complete row control, use itemBuilder:

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  itemBuilder: (context, account, suggestion, highlighted) {
    return ListTile(
      selected: highlighted,
      title: Text(suggestion.displayText),
      subtitle: Text(account.code),
    );
  },
);

Other presentation hooks include emptyBuilder and loadingBuilder.

Field states and embedding #

The box supports several distinct states:

  • enabled: false: disables the standard field interaction.
  • disabled: true: dims the field and suppresses interaction and validation.
  • readOnly: true: keeps normal contrast while blocking editing and opening.
  • allowFixed: true: exposes a lock/unlock action backed by controller.isFixed.
  • bare: true: removes the outer border/fill and tightens padding for embedded surfaces such as editable table cells.

Keyboard-oriented embedders can use onEscape, onTabNext, and onTabPrev. Use restoreOnBlur to control whether uncommitted typing reverts to the last committed selection.

Input configuration #

The widget exposes Flutter text-input controls needed for ERP and structured identifiers, including:

  • keyboardType, textInputAction, and textCapitalization.
  • inputFormatters, maxLength, and maxLengthEnforcement.
  • textDirection, textAlign, and textAlignVertical.
  • autocorrect, enableSuggestions, and enableIMEPersonalizedLearning.
  • autofillHints, smart dashes/quotes, cursor options, and selection controls.
  • focusNode, autofocus, canRequestFocus, and scrollOnFocus.

Example for an exact numeric account code:

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  keyboardType: TextInputType.number,
  enableSuggestions: false,
  autocorrect: false,
  inputFormatters: [FilteringTextInputFormatter.digitsOnly],
  textDirection: TextDirection.ltr,
);

Theming #

Use SuperAutoSuggestionsBoxThemeData for component styling and SuperAutoSuggestionsBoxFocusedStyle for focused-state overrides.

A field-level theme can override the ambient package theme:

SuperAutoSuggestionsBox<Account>(
  source: source,
  suggestionBuilder: accountSuggestion,
  theme: SuperAutoSuggestionsBoxThemeData.light.copyWith(
    borderFocus: Colors.indigo,
  ),
);

The package integrates with the shared GeniusLink design-system foundation from super_core, including light/dark themes, spacing, typography, and RTL-aware presentation.

Documentation #

The example/ application contains runnable scenarios for local and remote search, Advanced Search modes, validation placement, autovalidation, rich rows, and newer package behavior.

Changelog #

See CHANGELOG.md for new features, fixes, and breaking changes.

Issues #

Use the GitHub issue tracker for bug reports and feature requests.

1
likes
150
points
461
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Super Auto Suggestion Box is a GeniusLink Flutter package providing a typeahead/combobox with local and remote sources, fuzzy matching, single or multi-select, free-text entry, progressive fallback, infinite scroll, recent suggestions, inline creation, shadow-hint completion, record binding, read-only and fixable modes, controller-driven focus/form wiring, advanced search, bare embedding, and shared core theming. Supports light/dark themes, LTR, and RTL.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #widget #autocomplete #typeahead #combobox

License

MIT (license)

Dependencies

easy_debounce, flutter, flutter_localizations, intl, super_core, super_form_field

More

Packages that depend on super_auto_suggestion_box