Skip to content

Commit

Permalink
Initial version (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
fujidaiti authored Jan 11, 2025
1 parent 1b39e43 commit 496b653
Show file tree
Hide file tree
Showing 34 changed files with 4,613 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.mocks.dart linguist-generated=true

18 changes: 16 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@
"version": "0.1.0",
"configurations": [
{
"name": "Resizable Navigator Example",
"name": "Minimal Example",
"request": "launch",
"type": "dart",
"program": "lib/main.dart",
"program": "lib/minimal_example.dart",
"cwd": "./example"
},
{
"name": "Declarative Example",
"request": "launch",
"type": "dart",
"program": "lib/declarative_example.dart",
"cwd": "./example"
},
{
"name": "Imperative Example",
"request": "launch",
"type": "dart",
"program": "lib/imperative_example.dart",
"cwd": "./example"
},
]
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"dart.flutterSdkPath": ".fvm/versions/3.27.1"
}
}
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Changelog

## 0.1.0
## 1.0.0

Initial release.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,46 @@
# Resizable Navigator
# NavigatorResizable

[![GitHub Repo stars](https://img.shields.io/github/stars/fujidaiti/navigator_resizable)](https://github.com/fujidaiti/navigator_resizable) [![GitHub last commit (branch)](https://img.shields.io/github/last-commit/fujidaiti/navigator_resizable/main?logo=git)](https://github.com/fujidaiti/navigator_resizable/commits/main/) [![Pub Version](https://img.shields.io/pub/v/navigator_resizable)](https://pub.dev/packages/navigator_resizable) ![Pub Likes](https://img.shields.io/pub/likes/navigator_resizable) ![Pub Points](https://img.shields.io/pub/points/navigator_resizable) ![Pub Monthly Downloads](https://img.shields.io/pub/dm/navigator_resizable)

A thin wrapper around `Navigator` that *visually* resizes the child navigator to match the size of the content displayed in the current route. All standard navigation APIs, such as `Navigator.push`, `Navigator.pop`, [named routes](https://api.flutter.dev/flutter/widgets/Navigator-class.html#:~:text=Using%20named%20navigator%20routes), and the [Pages API](https://api.flutter.dev/flutter/widgets/Navigator-class.html#:~:text=the%20current%20page.-,Using%20the%20Pages%20API,-The%20Navigator%20will) (e.g., [go_router](https://pub.dev/packages/go_router), [auto_route](https://pub.dev/packages/auto_route)), can be used with `NavigatorResizable`, just as with the regular navigator.

<br/>

<img src="art/demo_clip_minimal_example.gif" width="300" width="300"/> <img src="art/demo_clip_practical_example.gif" width="300" width="300"/>

<br/>

## Resources

- See [/example](https://github.com/fujidaiti/navigator_resizable/tree/main/example/lib) for the basic usage and practical examples.
- See the [API documentation](https://pub.dev/documentation/navigator_resizable/latest/navigator_resizable/NavigatorResizable-class.html) for the detailed description of the `NavigatorResizable` widget.

<br/>

## Questions

If you have any questions, feel free to ask them on the [discussions page](https://github.com/fujidaiti/navigator_resizable/discussions).

<br/>

## Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

<br/>

## Links

- [API Documentation](https://pub.dev/documentation/navigator_resizable/latest/)
- [pub.dev](https://pub.dev/packages/navigator_resizable)
- [norelease.dev](https://pub.dev/publishers/norelease.dev/packages)

<br/>
Binary file added art/demo_clip_minimal_example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/demo_clip_practical_example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
204 changes: 204 additions & 0 deletions example/lib/declarative_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import 'package:example/src/form_page.dart';
import 'package:example/src/multi_page_dialog.dart';
import 'package:example/src/portal_page.dart';
import 'package:example/src/variable_height_page.dart';
import 'package:example/src/welcome_page.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:navigator_resizable/navigator_resizable.dart';

void main() {
runApp(MaterialApp.router(routerConfig: _router));
}

final _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const Home(),
routes: [
ShellRoute(
pageBuilder: (context, state, child) => MultiPageDialogPage(
key: state.pageKey,
navigator: child,
),
routes: [
GoRoute(
path: 'a',
pageBuilder: (context, state) => ResizableMaterialPage(
key: state.pageKey,
child: WelcomePage(
onNext: () => context.go('/a/b'),
onJumpToLast: () => context.go('/x'),
),
),
routes: [
GoRoute(
path: 'b',
pageBuilder: (context, state) => ResizableMaterialPage(
key: state.pageKey,
child: VariableHeightPage(
onNext: () => context.go('/a/b/c'),
),
),
routes: [
GoRoute(
path: 'c',
pageBuilder: (context, state) => ResizableMaterialPage(
key: state.pageKey,
child: FormPage(
autoFocus: false,
submitButton: FilledButton(
onPressed: () => context.go('/a/b/c/d'),
child: Text('Next'),
),
),
),
routes: [
GoRoute(
path: 'd',
pageBuilder: (context, state) =>
ResizableMaterialPage(
key: state.pageKey,
child: FormPage(
autoFocus: true,
submitButton: FilledButton(
onPressed: () => context.go('/a/b/c/d/e'),
child: Text('Next'),
),
),
),
routes: [
GoRoute(
path: 'e',
pageBuilder: (context, state) =>
ResizableMaterialPage(
key: state.pageKey,
child: PortalPage(
destinations: [
'/a/b/c/d',
'/a/b/c',
'/a/b',
'/a',
],
onGoToDestination: (destination) =>
context.go(destination),
),
),
),
],
),
],
),
],
),
],
),
GoRoute(
path: 'x',
pageBuilder: (context, state) => ResizableMaterialPage(
key: state.pageKey,
child: PortalPage(
destinations: [
'/a/b/c/d',
'/a/b/c',
'/a/b',
'/a',
],
onGoToDestination: (destination) => context.go(destination),
),
),
),
],
),
],
),
],
);

class Home extends StatelessWidget {
const Home({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: () => context.go('/A'),
child: const Text('Open Dialog'),
),
),
);
}
}

/// A declarative version of [showDialog].
///
/// Because the SDK does not provide [Page] for dialog widgets,
/// we need to define one ourselves.
class MultiPageDialogPage extends Page {
const MultiPageDialogPage({
super.key,
required this.navigator,
});

final Widget navigator;

@override
Route createRoute(BuildContext context) {
return PageBasedMultiPageDialogRoute(page: this);
}
}

class PageBasedMultiPageDialogRoute extends PageRoute<void> {
PageBasedMultiPageDialogRoute({
required MultiPageDialogPage page,
}) : super(settings: page);

MultiPageDialogPage get page => settings as MultiPageDialogPage;

@override
Color? get barrierColor => Colors.black45;

@override
String? get barrierLabel => null;

@override
bool get barrierDismissible => true;

@override
bool get maintainState => true;

@override
Duration get transitionDuration => const Duration(milliseconds: 200);

@override
Duration get reverseTransitionDuration => const Duration(milliseconds: 150);

@override
bool get opaque => false;

@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return MultiPageDialog(
navigator: page.navigator,
);
}

@override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return FadeTransition(
opacity: animation,
child: child,
);
}
}
89 changes: 89 additions & 0 deletions example/lib/imperative_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:example/src/form_page.dart';
import 'package:example/src/multi_page_dialog.dart';
import 'package:example/src/variable_height_page.dart';
import 'package:example/src/welcome_page.dart';
import 'package:flutter/material.dart';
import 'package:navigator_resizable/navigator_resizable.dart';

void main() {
runApp(const MaterialApp(home: Home()));
}

class Home extends StatelessWidget {
const Home({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: () => showMultiPageDialog(context),
child: const Text('Open Dialog'),
),
),
);
}
}

void showMultiPageDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return MultiPageDialog(
navigator: Navigator(
onGenerateInitialRoutes: (_, __) {
return [
ResizableMaterialPageRoute(
builder: (context) => WelcomePage(
onNext: () => pushVariableHeightPage(context),
onJumpToLast: () {},
),
),
];
},
),
);
},
);
}

void pushVariableHeightPage(BuildContext context) {
Navigator.push(
context,
ResizableMaterialPageRoute(
builder: (context) => VariableHeightPage(
onNext: () => pushFormPage(context),
),
),
);
}

void pushFormPage(BuildContext context) {
Navigator.push(
context,
ResizableMaterialPageRoute(
builder: (context) => FormPage(
autoFocus: false,
submitButton: FilledButton(
onPressed: () => pushFormPageWithAutoFocus(context),
child: Text('Next'),
),
),
),
);
}

void pushFormPageWithAutoFocus(BuildContext context) {
Navigator.push(
context,
ResizableMaterialPageRoute(
builder: (_) => FormPage(
autoFocus: true,
submitButton: FilledButton(
onPressed: () => Navigator.of(context, rootNavigator: true).pop(),
child: Text('Submit'),
),
),
),
);
}
Loading

0 comments on commit 496b653

Please sign in to comment.