native_adaptive_toolbox 0.1.0 copy "native_adaptive_toolbox: ^0.1.0" to clipboard
native_adaptive_toolbox: ^0.1.0 copied to clipboard

Native text-selection menus and custom-painted handles, foundation-only.

native_adaptive_toolbox #

Native text-selection menus and custom-painted selection handles for Flutter, using only the foundation, services, widgets, and rendering layers. No Material, no Cupertino, no custom-drawn menu, no fallback.

What it does #

Platform Menu Handles Manually tested
Android Native floating ActionMode toolbar Custom-painted grip
iOS UIEditMenuInteraction / UIMenuController Custom-painted grip
macOS NSMenu none (desktop)
Windows TrackPopupMenu none (desktop)
Linux GTK menu none (desktop)
Web Browser-owned native menu

The menu is the platform's own. Flutter computes the anchor — the selection bounds, or the exact right-click point for context menus — keeps it inside the visible area (never under the IME), and hands it to the platform over the native_adaptive_toolbox/menu channel. Context menus keep the click point at the menu's corner: top-left normally, top-right for RTL or when the menu would overflow the window's edge (measured with the menu's real size, like web). There is no custom-drawn menu anywhere; a platform without an implementation returns false from showMenu and no menu appears.

Usage #

Native context menu at a point #

import 'package:native_adaptive_toolbox/native_adaptive_toolbox.dart';

final (anchor, topRight) = NativeToolboxPositioner.resolvePointAnchor(
  clickPosition,            // global logical coordinates
  visibleBounds,            // screen minus IME insets minus padding
  rtl: false,
);

final shown = await NativeToolboxMenu.showMenu(
  anchorRect: Rect.fromPoints(anchor, anchor),
  actions: const [
    NativeToolboxAction(id: 'copy', label: 'Copy'),
    NativeToolboxAction(id: 'cut', label: 'Cut'),
    NativeToolboxAction(id: 'paste', label: 'Paste'),
    NativeToolboxAction(id: 'selectAll', label: 'Select all'),
  ],
  selectionMode: true,
  topRight: topRight,
);
if (!shown) {
  // No platform implementation on this device.
}

NativeToolboxMenu.onAction.listen((index) {
  // index into the actions list; the platform already dismissed the menu.
});
NativeToolboxMenu.onDismiss.listen((_) {
  // The user dismissed the menu without choosing an action.
});

Selection menu anchored to a selection #

final anchor = NativeToolboxPositioner.resolveAnchor(
  selectionBounds,          // the selection rect in global logical coordinates
  visibleBounds,
);
await NativeToolboxMenu.showMenu(
  anchorRect: anchor,
  actions: actions,
  selectionMode: true,
);

Foundation-only selection handles #

NativeToolboxSelectionControls implements the widgets-layer TextSelectionControls contract with custom-painted grips (Android 22×22, iOS 24×24, desktop none), so any custom text surface can plug them in:

final controls = NativeToolboxSelectionControls(
  platform: defaultTargetPlatform,
  handleBuilder: (context, type, lineHeight) => myCustomHandle(context),
);

A host handle builder replaces only the visual; geometry, hit targets, and dragging stay with the caller's selection overlay.

Positioning #

  • resolveAnchor(selectionBounds, visibleBounds) — clamps the selection rect into the visible bounds.
  • resolvePointAnchor(point, visibleBounds, rtl:) — clamps a context-menu point; returns whether the menu should extend leftward (RTL). The near-the-edge flip is decided per platform with the menu's real size.

The anchor is in FlutterView-global logical coordinates; the channel payload carries physical pixels plus the view offset so each platform converts into its own window coordinate space.

Development #

dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test
cd example && flutter test
cd example && flutter build web --release
dart pub publish --dry-run

Device acceptance for each platform: long-press or right-click a selection, verify the native menu appears at the anchor, actions execute once, dismissal is reported, and the menu stays above the IME.

See CONTRIBUTING.md and the MIT LICENSE.

1
likes
160
points
149
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Native text-selection menus and custom-painted handles, foundation-only.

Repository (GitLab)
View/report issues
Contributing

License

MIT (license)

Dependencies

flutter, flutter_web_plugins

More

Packages that depend on native_adaptive_toolbox

Packages that implement native_adaptive_toolbox