interactive_timeline 0.1.0
interactive_timeline: ^0.1.0 copied to clipboard
A performant, reusable horizontal timeline widget with LOD ticks, panning, and anchored zoom.
interactive_timeline #
A performant, reusable horizontal timeline widget for Flutter with:
- Anchored zoom (mouse wheel, trackpad, Magic Mouse, pinch) around the cursor/focal point
- Smooth horizontal panning
- Auto-LOD ticks (hours → months → years → decades → centuries → millennia)
- Double-tap to center on events midpoint (or initial center)
- Event markers with tap callback
- Parent scroll suppression (prevents ancestor scrollables from hijacking gestures)
Screenshot #
[Interactive timeline demo]
Installation (local path in a monorepo) #
Add a path dependency in your app's pubspec.yaml:
dependencies:
interactive_timeline:
path: packages/interactive_timeline
Import it:
import 'package:interactive_timeline/interactive_timeline.dart';
Quick start #
final now = DateTime.now().toUtc();
final events = <TimelineEvent>[
TimelineEvent(date: now.subtract(const Duration(days: 365 * 2)), title: 'Two years ago'),
TimelineEvent(date: now.subtract(const Duration(days: 30)), title: 'Last month'),
TimelineEvent(date: now, title: 'Today'),
TimelineEvent(date: now.add(const Duration(days: 30)), title: 'Next month'),
TimelineEvent(date: now.add(const Duration(days: 365)), title: 'Next year'),
];
SizedBox(
height: 140,
child: TimelineWidget(
height: 120,
events: events,
minZoomLOD: TimeScaleLOD.month,
maxZoomLOD: TimeScaleLOD.century,
tickLabelColor: const Color(0xFF444444),
axisThickness: 2,
majorTickThickness: 2,
minorTickThickness: 1,
minorTickColor: Colors.grey,
labelStride: 1,
labelStyleByLOD: const {
TimeScaleLOD.year: TextStyle(fontSize: 12, fontWeight: FontWeight.w600),
TimeScaleLOD.decade: TextStyle(fontSize: 12),
},
onZoomChanged: (z) => debugPrint('zoom: $z'),
onEventTap: (e) => debugPrint('Tapped: ${e.title}'),
),
)
API (selected) #
- Data:
events(TimelineEvent) - Size:
height - Zoom/scale:
initialZoom,minZoom,maxZoom,minZoomLOD,maxZoomLOD,basePixelsPerMillisecond - Styling:
timelineColor,eventColor,backgroundColor,tickLabelColor,axisThickness,majorTickThickness,minorTickThickness,minorTickColor,labelStride,labelStyleByLOD - Callbacks:
onZoomChanged(double),onEventTap(TimelineEvent) - Behavior: anchored zoom, double-tap to center, suppress ancestor pointer events
Example app (in this repo) #
An example is included at packages/interactive_timeline/example. Run it directly:
cd example
flutter run
The example demonstrates:
- Anchored zoom via wheel/trackpad/pinch
- Horizontal panning
- Double-tap to center on events midpoint
- Event tap callback (shows a SnackBar)
Publish to pub.dev #
- Ensure
pubspec.yamlhasname,description,version,homepage,repository,issue_trackerand a proper SDK/Flutter constraint. - Include a
LICENSEandCHANGELOG.md(both are present in this repo). - Add screenshots/GIFs to your README (optional but recommended).
- Run:
Fix any issues it reports.flutter pub publish --dry-run - Publish:
flutter pub publish - Consumers can depend on it with:
dependencies: interactive_timeline: ^0.1.0
Notes #
- Anchored zoom keeps content under pointer fixed while zooming
- Pooled tick manager for performance
- Deep-time beyond
DateTimepossible with a custom epoch in future
Contributing #
- Fork the repo and create a feature branch from
main. - Development setup:
- Flutter SDK 3.16+ (Dart 3)
- Format and analyze before committing:
dart format .flutter analyze
- Run tests (add more as you contribute):
flutter test
- Example app for manual testing:
cd example && flutter run
- Coding style: keep code clear and well-named; prefer small, readable functions. Follow the included
flutter_lintsrules. - Commits: conventional messages are appreciated (feat:, fix:, docs:, chore:, refactor:, test:).
- Pull Requests: include a brief description, screenshots/GIFs if UI changes, and a changelog entry suggestion.
Releasing and Publishing (pub.dev) #
- Update
CHANGELOG.mdwith a new entry. - Bump
version:inpubspec.yaml(semver). - Verify
README.md,LICENSE, andpubspec.yamlmetadata (homepage,repository,issue_tracker,topics). - Ensure screenshots referenced in the README (e.g.,
demo1.png) are checked in. - Dry run:
dart format . flutter pub get flutter pub publish --dry-run - If clean, publish:
flutter pub publish - Tag the release (optional but recommended):
git tag v<version> git push --tags
Republishing / Hotfixes #
pub.dev does not allow re-uploading the same version. For any fix, bump the version (usually patch):
- Update
CHANGELOG.md(e.g., “0.1.1 – Fix label style precedence”). - Bump
version:inpubspec.yamlto the next patch/minor. - Re-run the publish steps above (dry-run, then publish).
- If you accidentally published a broken version, you can retract it from the pub.dev UI (Manage Versions → Retract). Consumers on that exact version will be warned.
GitHub Pages website #
- A minimal site is available under
docs/and can be enabled via GitHub Pages (branch:main, folder:/docs). - After it’s live, consider setting
homepage:inpubspec.yamlto the Pages URL. - If you prefer, move
demo1.pngintodocs/(e.g.,docs/assets/) and update links accordingly. Keeping it at the repo root also works for pub.dev README rendering.