make packages for dart and npm

This commit is contained in:
Hamza-Ayed
2026-04-16 17:48:43 +03:00
parent 9f2a03a979
commit 34dd9ee35a
21 changed files with 1292 additions and 56 deletions
@@ -0,0 +1,16 @@
class IntaleqColors {
/// The signature Intaleq Blue color.
static const String primaryBlue = '#0D47A1';
/// Cyan used for remaining route lines.
static const String routeCyan = '#00e5ff';
/// Gray used for traveled paths or alternatives.
static const String softGray = '#BDBDBD';
/// Semi-transparent gray for polygon fills.
static const String fillGray = '#BDBDBD33'; // 20% opacity
/// Red for error or stop states.
static const String alertRed = '#ba1a1a';
}
@@ -0,0 +1,105 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:maplibre_gl/maplibre_gl.dart' hide CircleOptions;
import 'models/geometry.dart';
class IntaleqMapController {
final MaplibreMapController mapController;
final String apiKey;
IntaleqMapController({
required this.mapController,
required this.apiKey,
});
// --- API Integrations ---
/// Search for places using Intaleq Geocoding API
Future<List<dynamic>> search(String query) async {
final response = await http.get(
Uri.parse('https://map-saas.intaleq.com/v1/geocoding/search?q=$query&key=$apiKey'),
);
if (response.statusCode == 200) {
return json.decode(response.body);
}
throw Exception('Failed to search');
}
/// Get route using Intaleq Routing API
Future<Map<String, dynamic>> getRoute(LatLng start, LatLng end, {String profile = 'driving'}) async {
final response = await http.get(
Uri.parse(
'https://map-saas.intaleq.com/v1/routing/route?start=${start.longitude},${start.latitude}&end=${end.longitude},${end.latitude}&profile=$profile&key=$apiKey',
),
);
if (response.statusCode == 200) {
return json.decode(response.body);
}
throw Exception('Failed to fetch route');
}
// --- Friendly Abstractions (Transformation Layer) ---
/// Add a marker (friendly wrapper for addSymbol)
Future<Symbol> addMarker(MarkerOptions options) async {
return await mapController.addSymbol(options.toSymbolOptions());
}
/// Add multiple markers
Future<List<Symbol>> addMarkers(List<MarkerOptions> optionsList) async {
final symbols = <Symbol>[];
for (var options in optionsList) {
symbols.add(await addMarker(options));
}
return symbols;
}
/// Remove a marker
Future<void> removeMarker(Symbol marker) async {
await mapController.removeSymbol(marker);
}
/// Add a polyline (friendly wrapper for addLine)
Future<Line> addPolyline(PolylineOptions options) async {
return await mapController.addLine(options.toLineOptions());
}
/// Remove a polyline
Future<void> removePolyline(Line polyline) async {
await mapController.removeLine(polyline);
}
/// Add a circle
Future<Circle> addCircle(CircleOptions options) async {
return await mapController.addCircle(options.toMapLibreOptions());
}
/// Remove a circle
Future<void> removeCircle(Circle circle) async {
await mapController.removeCircle(circle);
}
/// Add a polygon (Fill)
Future<Fill> addPolygon(PolygonOptions options) async {
return await mapController.addFill(options.toFillOptions());
}
/// Remove a polygon
Future<void> removePolygon(Fill polygon) async {
await mapController.removeFill(polygon);
}
/// Clear all map objects
void clearAll() {
mapController.clearSymbols();
mapController.clearLines();
mapController.clearCircles();
mapController.clearFills();
}
// --- Camera Controls ---
void animateCameraTo(LatLng position, {double? zoom}) {
mapController.animateCamera(CameraUpdate.newLatLngZoom(position, zoom ?? mapController.cameraPosition?.zoom ?? 14.0));
}
}
@@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'intaleq_map_controller.dart';
import 'styles.dart';
typedef MapCreatedCallback = void Function(IntaleqMapController controller);
class IntaleqMap extends StatefulWidget {
final String apiKey;
final String? styleUrl;
final LatLng initialPosition;
final double initialZoom;
final MapCreatedCallback? onMapCreated;
final bool myLocationEnabled;
const IntaleqMap({
super.key,
required this.apiKey,
this.styleUrl,
this.initialPosition = const LatLng(33.5138, 36.2765),
this.initialZoom = 14.0,
this.onMapCreated,
this.myLocationEnabled = false,
});
@override
State<IntaleqMap> createState() => _IntaleqMapState();
}
class _IntaleqMapState extends State<IntaleqMap> {
IntaleqMapController? _intaleqController;
@override
Widget build(BuildContext context) {
final style = widget.styleUrl ?? IntaleqStyles.obsidian(widget.apiKey);
return MaplibreMap(
onMapCreated: (MaplibreMapController controller) {
_intaleqController = IntaleqMapController(
mapController: controller,
apiKey: widget.apiKey,
);
if (widget.onMapCreated != null) {
widget.onMapCreated!(_intaleqController!);
}
},
styleString: style,
initialCameraPosition: CameraPosition(
target: widget.initialPosition,
zoom: widget.initialZoom,
),
myLocationEnabled: widget.myLocationEnabled,
compassEnabled: false,
trackCameraPosition: true,
);
}
}
@@ -0,0 +1,110 @@
import 'dart:ui';
import 'package:maplibre_gl/maplibre_gl.dart' as maplibre;
import '../constants/colors.dart';
class MarkerOptions {
final maplibre.LatLng position;
final String? iconImage;
final double? iconSize;
final double? iconRotate;
final String? textField;
final double? textOffset;
MarkerOptions({
required this.position,
this.iconImage,
this.iconSize,
this.iconRotate,
this.textField,
this.textOffset,
});
maplibre.SymbolOptions toSymbolOptions() {
return maplibre.SymbolOptions(
geometry: position,
iconImage: iconImage,
iconSize: iconSize,
iconRotate: iconRotate,
textField: textField,
textOffset: textOffset != null ? Offset(0, textOffset!) : null,
);
}
}
class PolylineOptions {
final List<maplibre.LatLng> coordinates;
final String? color;
final double? width;
final double? opacity;
PolylineOptions({
required this.coordinates,
this.color,
this.width,
this.opacity,
});
maplibre.LineOptions toLineOptions() {
return maplibre.LineOptions(
geometry: coordinates,
lineColor: color ?? IntaleqColors.primaryBlue,
lineWidth: width ?? 5.0,
lineOpacity: opacity ?? 1.0,
lineJoin: 'round',
);
}
}
class CircleOptions {
final maplibre.LatLng position;
final double radius;
final String? color;
final double? opacity;
final String? strokeColor;
final double? strokeWidth;
CircleOptions({
required this.position,
required this.radius,
this.color,
this.opacity,
this.strokeColor,
this.strokeWidth,
});
maplibre.CircleOptions toMapLibreOptions() {
return maplibre.CircleOptions(
geometry: position,
circleRadius: radius,
circleColor: color ?? IntaleqColors.primaryBlue,
circleOpacity: opacity ?? 0.6,
circleStrokeColor: strokeColor,
circleStrokeWidth: strokeWidth,
);
}
}
class PolygonOptions {
/// The list of rings. The first ring is the outer boundary,
/// and subsequent rings are holes.
final List<List<maplibre.LatLng>> rings;
final String? fillColor;
final double? fillOpacity;
final String? outlineColor;
PolygonOptions({
required this.rings,
this.fillColor,
this.fillOpacity,
this.outlineColor,
});
maplibre.FillOptions toFillOptions() {
return maplibre.FillOptions(
geometry: rings,
fillColor: fillColor ?? IntaleqColors.fillGray,
fillOpacity: fillOpacity ?? 0.4,
fillOutlineColor: outlineColor ?? IntaleqColors.primaryBlue,
);
}
}
+13
View File
@@ -0,0 +1,13 @@
class IntaleqStyles {
/// Dark premium map style (The default for Intaleq)
static String obsidian(String apiKey) =>
'https://maps.intaleq.com/styles/obsidian/style.json?key=$apiKey';
/// Light premium map style
static String light(String apiKey) =>
'https://maps.intaleq.com/styles/light/style.json?key=$apiKey';
/// Satellite hybrid style
static String satellite(String apiKey) =>
'https://maps.intaleq.com/styles/satellite/style.json?key=$apiKey';
}
@@ -0,0 +1,34 @@
import 'package:maplibre_gl/maplibre_gl.dart';
class PolylineUtils {
/// Decode a Google-encoded polyline string into a list of LatLng coordinates.
static List<LatLng> decode(String encoded) {
List<LatLng> points = [];
int index = 0, len = encoded.length;
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.codeUnitAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.codeUnitAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
points.add(LatLng(lat / 1E5, lng / 1E5));
}
return points;
}
}