uzmaps_core
uzmaps_core is the foundation every UzMaps surface is built on: design tokens, the motion engine,
four-language strings (Uzbek Latin, Uzbek Cyrillic, Russian, English), geo and formatting helpers, async
plumbing and on-device stores. It has no third-party dependencies — the whole SDK is one Flutter
dependency, so your upgrade path never routes through anyone else's breaking change.
flutter pub add uzmaps_coreCurrent release: v{{PKG_VER:flutter-core}} · pub.dev: uzmaps_core ·
source: packages/uzmaps_core
UzColors — the brand palette#
Sampled from the UzMaps artwork. One source of truth per idea; the Material scheme bridge lives in
uzmaps_ui, so a palette change is a change in one file.
UzColors.blue // 0xFF2C9EF8 — the brand blue
UzColors.blueDeep // 0xFF1B6EF3 — pressed/gradient
UzColors.open // 0xFF2E9E5B — "open now" green
UzColors.closed // 0xFFD64545 — "closed" red
UzColors.bgLight // 0xFFF4F2ED — warm paper background
UzColors.bgDark // 0xFF15171C — near-black night surfaceEvery token exists in a light and a dark variant (surface, surfaceAlt, text, textMuted,
textFaint, line), so a theme switch never needs a hardcoded fallback.
UzMotion — durations and curves#
UzMotion.instant // 90 ms
UzMotion.fast // 160 ms
UzMotion.standard // 240 ms
UzMotion.slow // 360 ms
UzMotion.cinematic // 520 ms
UzMotion.decelerate // easeOutCubic
UzMotion.accelerate // easeInCubic
UzMotion.smooth // easeInOutCubic
UzMotion.emissive // easeOutBackThe motion widgets that ride on these live in uzmaps_ui (PressableScale, StaggeredList, Shimmer,
Skeleton, FadeThrough, CountUpText, PulseMarker) — re-exported there so apps import one package
for anything visual.
Strings — four languages, one static API#
S.t('search'); // localised in the app's current language
S.via('Toshkent'); // "via Toshkent"
S.closesAt('18:00'); // "Closes at 18:00"
S.stepsIn(12); // "12 steps"Language is set once via the app settings (AppSettings.mode: uz, uzc for Cyrillic, ru, en) and
every table follows. Tables are plain Dart maps — no codegen, no .arb plumbing, no context parameter.
Geo and formatting#
String formatDistance(double m, {bool imperial = false}); // 1234 → "1.2 km"
String formatDuration(double s); // 4500 → "1 h 15 min"
String formatDurationCompact(double s); // 4500 → "1:15"
String formatHm(int minutes); // 75 → "1:15"
String formatTripDate(DateTime at);Distances are metres and durations are seconds everywhere, matching the HTTP API conventions — the same
numbers that come out of uzmaps_api go straight in.
Async plumbing#
| Export | What it is |
|---|---|
Result / Ok / Err | Typed success/failure without exceptions across layer boundaries. |
Debouncer | Keystroke-rate limiting for autocomplete. |
retry() | Retry with backoff for flaky network calls. |
RetryPulse | A ChangeNotifier pulse while a retry loop waits, for progress UI. |
FrameCoalescer | Collapses bursty notifications into one per frame. |
Stores — saved places and the trip journal#
final saved = SavedPlaces(KVStore.io());
saved.add(SavedPlace(id: 123, name: 'Chorsu bozori', lat: 41.3111, lon: 69.2797));
saved.addListener(() => rebuildList());SavedPlaces, Trip, TripJournal and TripRecorder are ChangeNotifiers backed by a KVStore
interface. The default implementation is a tiny JSON file store (KVStore.io()); swap in anything else —
memory for tests, shared_preferences for a platform that demands it — and nothing above notices.
AppSettings#
Units (metric/imperial), theme mode (system/light/dark) and the UI language, persisted through the same
KVStore and observed by everything that cares. The settings screen in uzmaps_kit and the Navigator's
own settings both read and write it.