native_kit 0.1.0
native_kit: ^0.1.0 copied to clipboard
One Dart call invokes the real OS-native UI on iOS and Android - system sheets, alerts, zero-permission pickers, scanners, share, print and haptics.
example/lib/main.dart
// A minimal, self-contained tour of native_kit.
//
// The full interactive showcase (all 30 components in 6 tabs, live theme
// switching and a result log) lives in the repository's `example/` app.
import 'package:flutter/material.dart';
import 'package:native_kit/native_kit.dart';
void main() => runApp(const NativeKitExampleApp());
/// Example app root.
class NativeKitExampleApp extends StatelessWidget {
/// Creates the example app.
const NativeKitExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(colorSchemeSeed: Colors.indigo),
darkTheme: ThemeData(
colorSchemeSeed: Colors.indigo,
brightness: Brightness.dark,
),
home: const ExampleHome(),
);
}
}
/// A few native_kit calls, each logging its typed result.
class ExampleHome extends StatefulWidget {
/// Creates the home screen.
const ExampleHome({super.key});
@override
State<ExampleHome> createState() => _ExampleHomeState();
}
class _ExampleHomeState extends State<ExampleHome> {
String _last = 'Tap a button to open the real native UI.';
Future<void> _run(Future<Object?> Function() call) async {
try {
final Object? result = await call();
setState(() => _last = '$result');
} on NativeKitException catch (error) {
setState(() => _last = '$error');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('native_kit')),
body: ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Text(_last, style: Theme.of(context).textTheme.bodyLarge),
const SizedBox(height: 16),
Builder(
builder: (BuildContext button) => FilledButton(
onPressed: () => _run(
() => NativeKit.showActionSheet(
context: button,
title: 'Photo',
items: const <NativeMenuItem>[
NativeMenuItem(
id: 'share',
title: 'Share',
iosSymbol: 'square.and.arrow.up',
),
NativeMenuItem(
id: 'delete',
title: 'Delete',
style: NativeActionStyle.destructive,
),
],
),
),
child: const Text('Action sheet'),
),
),
FilledButton.tonal(
onPressed: () => _run(
() => NativeKit.showAlert(
context: context,
title: 'Rename',
actions: const <NativeAlertAction>[
NativeAlertAction.cancel(id: 'cancel', title: 'Cancel'),
NativeAlertAction(id: 'ok', title: 'Rename'),
],
textFields: const <NativeAlertTextField>[
NativeAlertTextField(placeholder: 'New name'),
],
),
),
child: const Text('Alert with text field'),
),
FilledButton.tonal(
onPressed: () =>
_run(() => NativeKit.pickDateTime(context: context)),
child: const Text('Date & time picker'),
),
FilledButton.tonal(
onPressed: () => _run(() => NativeKit.pickColor(context: context)),
child: const Text('Color picker'),
),
FilledButton.tonal(
onPressed: () => _run(
() => NativeKit.pickMedia(
type: NativeMediaType.images,
selectionLimit: 3,
),
),
child: const Text('Photo picker (no permission)'),
),
FilledButton.tonal(
onPressed: () => _run(() => NativeKit.scanCode(context: context)),
child: const Text('Scan a QR code'),
),
FilledButton.tonal(
onPressed: () => _run(
() => NativeKit.share(
text: 'Hello from native_kit',
url: Uri.parse('https://pub.dev'),
),
),
child: const Text('Share sheet'),
),
FilledButton.tonal(
onPressed: () =>
_run(() => NativeKit.authenticate(reason: 'Confirm it is you')),
child: const Text('Biometrics'),
),
FilledButton.tonal(
onPressed: () => _run(
() => NativeKit.triggerHaptic(
HapticType.success,
).then((_) => 'Haptic played'),
),
child: const Text('Haptic feedback'),
),
],
),
);
}
}