super_auto_suggestion_box 1.3.1 copy "super_auto_suggestion_box: ^1.3.1" to clipboard
super_auto_suggestion_box: ^1.3.1 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 #

style: flutter_lints

super_auto_suggestion_box provides the GeniusLink SuperAutoSuggestionsBox<T>: a themed typeahead / combobox with local and remote sources, fuzzy matching, single- and multi-select, free-text entry, progressive remote fallback, server-side paging, recents, inline create, shadow-hint completion, record binding, read-only/fixable states, advanced search, validation, and bare embedding.

Version 1.3.1 keeps raw T values as the public data model, consolidates suggestion row construction into SuperAutoSuggestionsItem<T>(...), and finishes the Super prefix migration for public presentation/widget classes. The validator still receives the selected raw T?, and onSelectionChanged remains the selection callback for both select and de-select operations.

Every SuperAutoSuggestionsBox<T> requires a SuperAutoSuggestionsSource<T>. Use SuperAutoSuggestionSources.list<T>(values) for a local collection. Initial multi-select values belong to SuperAutoSuggestionsController.initialSelected; query, recents, and multi-select configuration belong to the widget.

SuperAutoSuggestionsItem<T> suggestionBuilder(
  List<T> items,
  int index,
  T element,
)

SuperAutoSuggestionsItem<T> remains public because builders return it, but callers no longer wrap every collection item, fetch result, selected item, recent item, or created item in SuperAutoSuggestionsItem<T>.

Setup #

dependencies:
  super_auto_suggestion_box: ^1.3.1
import 'package:super_auto_suggestion_box/super_auto_suggestion_box.dart';

final typography = SuperTextTheme();

MaterialApp(
  theme: SuperMaterialThemeData.light(
    textTheme: typography,
    primaryTextTheme: typography,
  ),
  darkTheme: SuperMaterialThemeData.dark(
    textTheme: typography,
    primaryTextTheme: typography,
  ),
  localizationsDelegates: const [
        // ...
        SuperAutoSuggestionsTranslation.delegate,
      ],
  supportedLocales:
      SuperAutoSuggestionsTranslation.delegate.supportedLocales,
);

Basic Usage #

final units = ['each', 'box', 'carton'];

SuperAutoSuggestionsItem<String> unitSuggestion(
  List<String> items,
  int index,
  String unit,
) => SuperAutoSuggestionsItem<String>(
  value: unit,
  titleText: unit,
);

final box = SuperAutoSuggestionsController<String>(
  allowFreeText: true,
);

SuperAutoSuggestionsBox<String>(
  controller: box,
  source: SuperAutoSuggestionSources.list<String>(units),
  suggestionBuilder: unitSuggestion,
  hintText: 'Type or pick...',
  onSelectionChanged: (selected) {
    final unit = selected.isEmpty ? null : selected.last;
    // unit is the selected raw String?, or null after de-selection.
  },
);

You can omit the controller, but the source remains required:

SuperAutoSuggestionsBox<String>(
  source: SuperAutoSuggestionSources.list<String>(units),
  suggestionBuilder: unitSuggestion,
  onSelectionChanged: (selected) {},
);

Rich Rows #

Keep domain data raw and derive row metadata in the builder:

final accounts = ['1010', '1020', '4000'];

SuperAutoSuggestionsItem<String> accountSuggestion(
  List<String> items,
  int index,
  String code,
) => SuperAutoSuggestionsItem<String>(
  value: code,
  titleText: switch (code) {
    '1010' => 'Cash on Hand',
    '1020' => 'Bank - Operating',
    '4000' => 'Sales Revenue',
    _ => code,
  },
  descriptionText: 'Account $code',
  trailingText: code == '1020' ? '285,120.50' : null,
  group: code.startsWith('1') ? 'Assets' : 'Income',
  iconData: Icons.account_balance_outlined,
  keywords: [code],
);

Custom rows receive both the raw item and the built suggestion:

SuperAutoSuggestionsBox<String>(
  source: SuperAutoSuggestionSources.list<String>(accounts),
  suggestionBuilder: accountSuggestion,
  itemBuilder: (context, code, suggestion, highlighted) {
    return Text('${suggestion.displayText} ($code)');
  },
);

Custom supporting widgets now use the same constructor. titleText remains the canonical searchable and committed title:

SuperAutoSuggestionsItem<String>(
  value: '1020',
  titleText: 'Bank - Operating',
  description: const Text('1020 - Current Assets'),
  trailing: const Chip(label: Text('Active')),
  icon: const Icon(Icons.account_balance_outlined),
);

descriptionText, trailingText, and iconData remain available when custom widgets are not needed. Suggestions can also carry an optional Stream? enabledSnapshot alongside the immediate enabled boolean.

Suggestion Sources #

All built-in sources accept raw values and source-specific matching or fetch configuration only. Pass suggestionBuilder to SuperAutoSuggestionsBox; it owns the conversion to SuperAutoSuggestionsItem<T> for both widget-created and external controllers.

final staticSource = SuperAutoSuggestionSources.list<String>(accounts);

final fuzzySource = SuperAutoSuggestionSources.fuzzy<String>(accounts);

final asyncSource = SuperAutoSuggestionSources.async<String>(
  (query) => api.searchAccounts(query), // Future<List<String>>
  initialItems: accounts.take(5).toList(),
);

final hybridSource = SuperAutoSuggestionSources.hybrid<String>(
  initialItems: accounts,
  fetch: (query) => api.searchAccounts(query), // Future<List<String>>
  remoteThreshold: 1,
  remoteMinChars: 2,
);

final remoteFallbackSource = SuperAutoSuggestionSources.remoteFallback<String>(
  initialItems: accounts,
  fetch: (query) => api.searchAccounts(query), // Future<List<String>>
  remoteThreshold: 5,
  remoteMinChars: 1,
);

final pagedSource = SuperAutoSuggestionSources.paged<String>(
  (query, page) async {
    final response = await api.searchAccountsPage(query, page);
    return SuperSuggestionsPage<String>(
      items: response.codes,
      hasMore: response.hasMore,
    );
  },
  resolveFrom: accounts,
);

SuperAutoSuggestionSources.strings(values) is still available for the simple label-equals-value case. The source itself does not take a builder; the widget owns the suggestionBuilder.

Concrete Source Classes #

The factory methods above return these public implementations:

Factory Concrete source
list / strings / fuzzy SuperAutoListSuggestionsSource<T>
async SuperAutoAsyncSuggestionsSource<T>
hybrid SuperAutoHybridSuggestionsSource<T>
remoteFallback SuperAutoRemoteFallbackSuggestionsSource<T>
paged SuperAutoPagedSuggestionsSource<T>

Prefer SuperAutoSuggestionSources for normal construction. Instantiate a concrete source directly only when its public source-specific API is needed. The pre-1.2.0 concrete class names are no longer canonical.

Presentation Widget Names #

The canonical public presentation/widget types now all use the Super prefix: SuperAutoSuggestionsBoxThemeData, SuperAutoSuggestionsBoxFocusedStyle, SuperAutoSuggestionsHighlight, and SuperAutoSuggestionsPanel<T>. Deprecated typedefs preserve the 1.2.x names during migration.

Controller API #

Controller selections, result lists, recents, and callbacks use raw values:

final controller = SuperAutoSuggestionsController<String>(
  initialValue: '1020',
  initialSelected: const ['1010'],
);

controller.selected;          // String?
controller.results;           // List<String>
controller.selectedItems;     // List<String>
controller.selectedValues;    // List<String>, compatibility alias
controller.recents;           // List<String>

controller.select('1010');
controller.toggleSelected('4000');
controller.setSelectedItems(['1010', '4000']);
controller.setRecents(['1020']);
controller.selectByValue('4000');

When using an external controller, provide the source and builder on the widget. The controller owns interaction state, not suggestion data or row presentation:

SuperAutoSuggestionsBox<String>(
  controller: controller,
  source: staticSource,
  suggestionBuilder: accountSuggestion,
  showRecents: true,
  initialRecents: const ['4000'],
  onRecentsChanged: (recentCodes) {},
);

After the controller is attached to an SuperAutoSuggestionsBox, UI metadata is available through the render-facing accessors:

controller.suggestions;            // List<SuperAutoSuggestionsItem<String>>
controller.suggestionAt(0);        // SuperAutoSuggestionsItem<String>
controller.highlightedSuggestion;  // SuperAutoSuggestionsItem<String>?
controller.selectedSuggestion;     // SuperAutoSuggestionsItem<String>?

Selection Callback #

onSelectionChanged fires after every selection mutation. Single-select emits [item] on selection and [] on de-selection; multi-select emits the complete selected list.

SuperAutoSuggestionsBox<String>(
  source: SuperAutoSuggestionSources.list<String>(accounts),
  suggestionBuilder: accountSuggestion,
  multiSelect: true,
  onSelectionChanged: (codes) {},
);

Inline create returns a raw value:

SuperAutoSuggestionsBox<String>(
  source: SuperAutoSuggestionSources.list<String>(vendors),
  suggestionBuilder: vendorSuggestion,
  onCreate: (query) async {
    final vendor = await api.createVendor(query);
    return vendor.id; // raw String
  },
  onSelectionChanged: (vendorIds) {},
);

ERP Input And Validation #

SuperAutoSuggestionsBox<T> participates in an enclosing Form through FormField<T>. Its validator receives the selected raw T?, not the query text. Keep a controller when form submission needs to read the selected value.

final documentController = SuperAutoSuggestionsController<String>();

Form(
  key: formKey,
  child: SuperAutoSuggestionsBox<String>(
    controller: documentController,
    source: SuperAutoSuggestionSources.list<String>(documentReferences),
    suggestionBuilder: documentSuggestion,
    decoration: const InputDecoration(
      labelText: 'Document Reference',
      helperText: 'Pick a document reference',
    ),
    keyboardType: TextInputType.text,
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9-]')),
      LengthLimitingTextInputFormatter(16),
    ],
    textDirection: TextDirection.ltr,
    textInputAction: TextInputAction.done,
    showShadowHint: true,
    completeShadowHintOnTab: true,
    required: true,
    validator: (value) {
      if (value == null) return null; // `required` handles the empty selection.
      return documentReferences.contains(value)
          ? null
          : 'Pick a document from the list';
    },
    onSelectionChanged: (selected) {},
  ),
);

if (formKey.currentState!.validate()) {
  final savedDocumentReference = documentController.selected;
}

Validation errors surface through the suffix error badge tooltip, matching the GeniusLink form-field convention. For direct form-field access, controller formFieldKey is now GlobalKey<FormFieldState<T>>?.

For keyboard traversal, a single-select field with textInputAction: TextInputAction.next moves focus to the next focusable field immediately after an item is selected. Multi-select fields keep focus in the current suggestions field.

States And Embedding #

  • disabled: dims and blocks interaction.
  • readOnly: blocks interaction but keeps full contrast for posted/review states.
  • allowFixed: shows a lock/unlock action backed by controller.isFixed.
  • advancedSearch: opens a larger search surface with Ctrl/Cmd + F.
  • bare: removes outer chrome for table cells and compact host surfaces.
  • restoreOnBlur: restores the last committed raw value when the user leaves without picking.

Migration #

See migration_1.1.0_to_1.2.0.md for the generic validator, FormField<T> integration, removed callbacks, source-name migrations, localization, TextInputAction.next, and onSelectionChanged behavior. For earlier migrations, see migration_1.0.0_to_1.1.0.md and migration_0.14.0_to_1.0.0.md.

Localization #

The package ships English and Arabic translations using flutter_localizations, intl, and generated intl_utils delegates. Register the package helpers on your app:

MaterialApp(
  localizationsDelegates: const [
        // ...
        SuperAutoSuggestionsTranslation.delegate,
      ],
  supportedLocales:
      SuperAutoSuggestionsTranslation.delegate.supportedLocales,
)

Built-in package strings such as the required-field message, loading/search states, Recent group label, inline-create text, fixed/unfixed tooltips, and Advanced Search chrome follow the active locale. Explicit custom strings passed to the widget continue to take precedence. Registration is optional: when no SuperAutoSuggestionsTranslation is available in the widget tree, package widgets fall back to the built-in English localization.

1
likes
140
points
881
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

flutter, flutter_localizations, intl, super_core, super_form_field

More

Packages that depend on super_auto_suggestion_box