smart_auto_suggest_box 0.7.3 copy "smart_auto_suggest_box: ^0.7.3" to clipboard
smart_auto_suggest_box: ^0.7.3 copied to clipboard

A highly customizable auto-suggest text field with smart dropdown positioning that adapts to available screen space.

Smart Auto Suggest Box #

A highly customizable auto-suggest (autocomplete) Flutter package offering two widgets:

  • SmartAutoSuggestBox — floating overlay dropdown
  • SmartAutoSuggestView — inline suggestion list embedded in the widget tree

Both share the same SmartAutoSuggestDataSource API and item model.

pub package

Features #

  • Two display modes — floating overlay (SmartAutoSuggestBox) or inline list (SmartAutoSuggestView)
  • Unified data sourceSmartAutoSuggestDataSource with sync initialList and async onSearch
  • Smart overlay positioning — auto-repositions to the opposite side if insufficient space (SmartAutoSuggestBox only)
  • 4-direction supporttop, bottom, start, end with RTL awareness
  • Search modesonNoLocalResults (default) or always (every keystroke)
  • Configurable debounce — control search trigger timing
  • Keyboard navigation — ↑ ↓ Enter Escape
  • Form supportSmartAutoSuggestBox.form() and SmartAutoSuggestView.form() with validation
  • Scrollbar — visible scrollbar thumb when the suggestion list overflows
  • Custom builders — item, no-results, loading state, selected item display
  • ThemingSmartAutoSuggestTheme (ThemeExtension) with light/dark defaults
  • BottomSheet readySmartAutoSuggestView works inside showModalBottomSheet
  • Internationalization — built-in i18n

Getting Started #

dependencies:
  smart_auto_suggest_box: ^0.7.0

# localization (optional, but recommended)
  flutter_localizations:
    sdk: flutter
flutter pub get

Localization setup #

To enable localizations, add the following to your MaterialApp:

import 'package:smart_auto_suggest_box/smart_auto_suggest_box.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; // for GlobalMaterialLocalizations

/*
... other MaterialApp properties
*/

localizationsDelegates: const [
  SmartAutoSuggestBoxLocalizations.delegate,
  // ...app's other delegates (e.g. GlobalMaterialLocalizations.delegate)
],
supportedLocales:[
  // Add your app's supported locales here,like:
  const Locale('ar'), // Arabic
  const Locale('fa'), // Persian
  const Locale('en'), // English
  // ...other locales
],

Usage #

SmartAutoSuggestBox (floating overlay) #

SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (context, value) => SmartAutoSuggestItem(
      value: value,
      label: value[0].toUpperCase() + value.substring(1),
    ),
    initialList: (context) => ['apple', 'banana'],
  ),
  decoration: const InputDecoration(
    labelText: 'Search fruits',
    border: OutlineInputBorder(),
  ),
  onSelected: (item) => print(item?.label),
);

SmartAutoSuggestView (inline list) #

SmartAutoSuggestView<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (context, value) => SmartAutoSuggestItem(
      value: value,
      label: value[0].toUpperCase() + value.substring(1),
    ),
    initialList: (context) => ['apple', 'banana'],
  ),
  showListWhenEmpty: true,   // show list even when text field is empty
  listMaxHeight: 300,
  decoration: const InputDecoration(
    labelText: 'Search',
    border: OutlineInputBorder(),
  ),
  onSelected: (item) => print(item?.label),
);
SmartAutoSuggestBox<String>(   // or SmartAutoSuggestView
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (context, value) => SmartAutoSuggestItem(
      value: value,
      label: value,
    ),
    initialList: (context) => [],
    onSearch: (context, currentItems, searchText) async {
      return await api.search(searchText);
    },
    debounce: const Duration(milliseconds: 500),
  ),
  onSelected: (item) {},
);

searchMode.always #

Call onSearch on every keystroke (after debounce):

SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (context, value) => SmartAutoSuggestItem(
      value: value,
      label: value,
    ),
    initialList: (context) => localItems,
    onSearch: (context, current, searchText) async {
      return await api.search(searchText);
    },
    searchMode: SmartAutoSuggestSearchMode.always,
    debounce: const Duration(milliseconds: 600),
  ),
  onSelected: (item) {},
);
SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (c, v) => SmartAutoSuggestItem(value: v, label: v),
    initialList: (c) => items,
  ),
  direction: SmartAutoSuggestBoxDirection.top,   // falls back if no space
  onSelected: (item) {},
);
Direction Description
bottom Below the text field. Falls back to top.
top Above the text field. Falls back to bottom.
start Start side (left in LTR). Falls back to end.
end End side (right in LTR). Falls back to start.

SmartAutoSuggestView in BottomSheet #

showModalBottomSheet(
  context: context,
  isScrollControlled: true,
  useSafeArea: true,
  builder: (context) => DraggableScrollableSheet(
    expand: false,
    builder: (context, scrollController) => Column(
      children: [
        // ... drag handle, title ...
        Expanded(
          child: SmartAutoSuggestView<String>(
            dataSource: SmartAutoSuggestDataSource(
              itemBuilder: (context, value) => SmartAutoSuggestItem(
                value: value,
                label: value,
              ),
              initialList: (context) => myItems,
            ),
            showListWhenEmpty: true,
            listMaxHeight: double.infinity,
            onSelected: (item) => Navigator.pop(context),
          ),
        ),
      ],
    ),
  ),
);

Custom No-Results View #

SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (c, v) => SmartAutoSuggestItem(value: v, label: v),
    initialList: (c) => items,
  ),
  noResultsFoundBuilder: (context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Icon(Icons.search_off, size: 40),
        const Text('No matching results'),
        OutlinedButton.icon(
          onPressed: () { /* add new item */ },
          icon: const Icon(Icons.add),
          label: const Text('Add new'),
        ),
      ],
    );
  },
  onSelected: (item) {},
);

Custom Item Builder #

SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (c, v) => SmartAutoSuggestItem(value: v, label: v),
    initialList: (c) => items,
  ),
  tileHeight: 72,
  itemBuilder: (context, item) {
    return ListTile(
      leading: CircleAvatar(child: Text(item.label[0])),
      title: Text(item.label),
      subtitle: Text('Value: ${item.value}'),
      trailing: Chip(label: Text('${item.label.length}')),
    );
  },
  onSelected: (item) {},
);

Form Validation #

SmartAutoSuggestView.form(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: (c, v) => SmartAutoSuggestItem(value: v, label: v),
    initialList: (c) => items,
  ),
  validator: (value) {
    if (value == null || value.isEmpty) return 'Required';
    return null;
  },
  autovalidateMode: AutovalidateMode.onUserInteraction,
  onSelected: (item) {},
);

Highlight Matching Text #

By default, suggestion labels highlight the matching portion in bold with the theme's primary color using SmartAutoSuggestHighlightText. You can also use it directly:

SmartAutoSuggestHighlightText(
  text: 'Apple Pie',
  query: 'app',
  // optional: baseStyle, matchStyle
)

Item Builder with Focus #

Use SmartAutoSuggestItem.builder instead of the deprecated child to build custom item widgets. The builder receives the current searchText for highlighting, and the widget is automatically wrapped in Focus for keyboard navigation:

SmartAutoSuggestItem(
  key: 'apple',
  value: 'apple',
  label: 'Apple',
  builder: (context, searchText) {
    return ListTile(
      title: SmartAutoSuggestHighlightText(
        text: 'Apple',
        query: searchText,
      ),
    );
  },
)

SmartAutoSuggestController #

Use SmartAutoSuggestController<T> to access the text input and observe the selected item from outside the widget:

final controller = SmartAutoSuggestController<String>();

// Pass to widget
SmartAutoSuggestBox<String>(
  smartController: controller,
  dataSource: SmartAutoSuggestDataSource(...),
)

// Listen to selection changes
controller.selectedItem.addListener(() {
  print('Selected: ${controller.selectedItem.value?.label}');
});

// Clear programmatically
controller.clearSelection();

// Don't forget to dispose
controller.dispose();

Note: The old controller: TextEditingController? parameter is deprecated — use smartController instead.

Selected Item Display #

By default, the selected item's label is placed into the TextField as text. Use selectedItemBuilder to show a custom widget instead:

SmartAutoSuggestBox<String>(
  dataSource: SmartAutoSuggestDataSource(
    itemBuilder: fruitItemBuilder,
    initialList: (context) => fruits,
  ),
  selectedItemBuilder: (context, item) {
    return InputDecorator(
      decoration: const InputDecoration(border: OutlineInputBorder()),
      child: Chip(
        label: Text(item.label),
        onDeleted: () {}, // tap anywhere to dismiss
      ),
    );
  },
)

Tapping the custom widget clears the selection and restores the TextField. To clear programmatically, use SmartAutoSuggestBoxState.clearSelection().

Theming #

Use SmartAutoSuggestTheme (a ThemeExtension) to customise colours, shadows, border radii, text styles, and more.

MaterialApp(
  theme: ThemeData.light().copyWith(
    extensions: [SmartAutoSuggestTheme.light()],
  ),
  darkTheme: ThemeData.dark().copyWith(
    extensions: [SmartAutoSuggestTheme.dark()],
  ),
)

Per-widget override #

SmartAutoSuggestBox<String>(
  theme: SmartAutoSuggestTheme.light().copyWith(
    overlayBorderRadius: BorderRadius.circular(12),
    selectedTileColor: Colors.amber.shade100,
  ),
  // ...
)

SmartAutoSuggestDataSource API #

Property Type Default Description
itemBuilder SmartAutoSuggestItem<T> Function(BuildContext, T) required Converts raw T to SmartAutoSuggestItem<T>
initialList List<T> Function(BuildContext)? null Sync initial items (raw values)
onSearch Future<List<T>> Function(BuildContext, List<T>, String?)? null Async search (returns raw values)
searchMode SmartAutoSuggestSearchMode onNoLocalResults When to trigger onSearch
debounce Duration 400ms Debounce before calling onSearch

SmartAutoSuggestView unique parameters #

Parameter Type Default Description
listMaxHeight double 380 Max height of the inline suggestion list
showListWhenEmpty bool true Show list when text field is empty

Migration from 0.1.x #

All old type names are kept as deprecated typedef aliases — no code changes required. Rename at your own pace:

Old New
SmartAutoSuggestBoxItem SmartAutoSuggestItem
SmartAutoSuggestBoxDataSource SmartAutoSuggestDataSource
SmartAutoSuggestBoxSearchMode SmartAutoSuggestSearchMode
SmartAutoSuggestBoxSorter SmartAutoSuggestSorter
SmartAutoSuggestBoxItemBuilder SmartAutoSuggestItemBuilder

Additional Information #

  • Example app — complete demo with both widgets
  • CHANGELOG — version history
  • File issues on GitHub
1
likes
0
points
511
downloads

Publisher

unverified uploader

Weekly Downloads

A highly customizable auto-suggest text field with smart dropdown positioning that adapts to available screen space.

License

unknown (license)

Dependencies

flutter, gap, intl

More

Packages that depend on smart_auto_suggest_box