├── references.d.ts ├── .github ├── FUNDING.yml └── workflows │ └── release.yml ├── pnpm-workspace.yaml ├── .prettierignore ├── packages └── ui-mapbox │ ├── .npmignore │ ├── nativescript.config.ts │ ├── platforms │ ├── ios │ │ ├── Resources │ │ │ └── default_pin.png │ │ ├── Podfile │ │ ├── Info.plist │ │ └── src │ │ │ ├── NativeExpressionParser.swift │ │ │ └── NativeLayerFactory.swift │ └── android │ │ ├── AndroidManifest.xml │ │ ├── buildscript.gradle │ │ ├── res │ │ └── drawable │ │ │ └── ic_red_marker.xml │ │ ├── include.gradle │ │ └── java │ │ └── com │ │ └── nativescript │ │ └── mapbox │ │ └── Utils.kt │ ├── tsconfig.json │ └── package.json ├── images ├── preview.png ├── mapbox_logo.png ├── ios-xml-declared.png └── ios-demoapp-slice.png ├── .yarnrc.yml ├── config.json ├── eslint.config.mjs ├── src └── ui-mapbox │ ├── typings │ ├── Mapbox.ios.d.ts │ └── index.android.d.ts │ ├── expression │ ├── expression-parser.d.ts │ ├── expression-parser.android.ts │ └── expression-parser.ios.ts │ ├── layers │ ├── parser │ │ ├── property-parser.d.ts │ │ ├── property-parser.ios.ts │ │ └── property-parser.android.ts │ ├── layer-factory.d.ts │ └── layer-factory.ios.ts │ ├── README.md │ ├── references.d.ts │ ├── geo.utils.ts │ └── markers │ ├── Marker.common.ts │ └── Marker.android.ts ├── docs ├── .nojekyll ├── assets │ ├── hierarchy.js │ ├── navigation.js │ └── highlight.css ├── variables │ ├── MapboxTraceCategory.html │ ├── delayProperty.html │ ├── hideLogoProperty.html │ ├── latitudeProperty.html │ ├── mapStyleProperty.html │ ├── longitudeProperty.html │ ├── telemetryProperty.html │ ├── zoomLevelProperty.html │ ├── accessTokenProperty.html │ ├── disableTiltProperty.html │ ├── disableZoomProperty.html │ ├── hideCompassProperty.html │ ├── disableScrollProperty.html │ ├── disableRotationProperty.html │ ├── hideAttributionProperty.html │ ├── showUserLocationProperty.html │ ├── logoPositionProperty.html │ ├── locationComponentOptionsProperty.html │ ├── compassPositionProperty.html │ ├── attributionPositionProperty.html │ └── mapReadyProperty.html └── types │ ├── AddSourceOptions.html │ ├── UpdateSourceOptions.html │ ├── UserTrackingMode.html │ ├── SupportedLayerType.html │ └── UserLocationCameraMode.html ├── demo-snippets ├── ng │ ├── mapbox-token.ts │ ├── mapbox-demo2 │ │ ├── mapbox-demo2.component.html │ │ └── mapbox-demo2.component.ts │ ├── mapbox-demo3 │ │ ├── mapbox-demo3.component.html │ │ ├── mapbox-demo3.module.ts │ │ └── mapbox-demo3.component.ts │ ├── basic-map │ │ ├── basic-map.component.ts │ │ └── basic-map.component.html │ ├── mapbox-footer │ │ └── mapbox-footer.component.ts │ ├── mapbox-demo │ │ ├── mapbox-demo.component.html │ │ └── mapbox-demo.component.ts │ ├── install.module.ts │ └── mapbox-header │ │ └── mapbox-header.component.html ├── package.json ├── CHANGELOG.md └── vue │ └── install.ts ├── tsconfig.json ├── tsconfig.vue3.json ├── .npmrc ├── .gitmodules ├── mapbox_config.ts ├── .prettierrc.js ├── svelte.config.js ├── lerna.json ├── .gitignore ├── .vscode └── settings.json └── package.json /references.d.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [farfromrefug] 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - demo-* -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules/ 3 | plugin/ 4 | docs/ 5 | -------------------------------------------------------------------------------- /packages/ui-mapbox/.npmignore: -------------------------------------------------------------------------------- 1 | *.map 2 | *.ts 3 | !*.d.ts 4 | tsconfig.json 5 | references.d.ts 6 | -------------------------------------------------------------------------------- /images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nativescript-community/ui-mapbox/HEAD/images/preview.png -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | nmHoistingLimits: workspaces 4 | 5 | nodeLinker: node-modules 6 | -------------------------------------------------------------------------------- /images/mapbox_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nativescript-community/ui-mapbox/HEAD/images/mapbox_logo.png -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "readme": true, 3 | "angular": false, 4 | "demos": [ 5 | "ng" 6 | ] 7 | } -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import defaultConfig from './tools/eslint.config.mjs'; 2 | 3 | export default defaultConfig; 4 | -------------------------------------------------------------------------------- /images/ios-xml-declared.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nativescript-community/ui-mapbox/HEAD/images/ios-xml-declared.png -------------------------------------------------------------------------------- /images/ios-demoapp-slice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nativescript-community/ui-mapbox/HEAD/images/ios-demoapp-slice.png -------------------------------------------------------------------------------- /packages/ui-mapbox/nativescript.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | ios: { 3 | SPMPackages: [ 4 | 5 | ], 6 | }, 7 | } -------------------------------------------------------------------------------- /src/ui-mapbox/typings/Mapbox.ios.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare class MapView extends UIView { 3 | } 4 | 5 | declare class MapboxMap extends NSObject { 6 | } 7 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-token.ts: -------------------------------------------------------------------------------- 1 | export const MAPBOX_ACCESS_TOKEN = 'sk.eyJ1IjoiYWt5bGFzIiwiYSI6ImNtaGE5bzNhYzA2d3oyanNkenpmc3hrMXQifQ.YD-yEwSOtf85XnfH3Ku0OQ'; 2 | -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/ios/Resources/default_pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nativescript-community/ui-mapbox/HEAD/packages/ui-mapbox/platforms/ios/Resources/default_pin.png -------------------------------------------------------------------------------- /src/ui-mapbox/expression/expression-parser.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ExpressionParser { 2 | static parseJson(json: any[]): any; 3 | static toJson(filter: any): any[]; 4 | } 5 | -------------------------------------------------------------------------------- /src/ui-mapbox/layers/parser/property-parser.d.ts: -------------------------------------------------------------------------------- 1 | export declare class PropertyParser { 2 | // static parsePropertiesForLayer(propertiesObject: any): any; 3 | static propertyValueFromLayer(layer, key: string): any; 4 | } 5 | -------------------------------------------------------------------------------- /demo-snippets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@nativescript-community/template-snippet", 4 | "version": "0.0.1", 5 | "dependencies": { 6 | "@nativescript-community/ui-mapbox": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tools/tsconfig", 3 | "compilerOptions": { 4 | "paths": { 5 | "@nativescript-community/ui-mapbox": ["src/ui-mapbox"], 6 | "@nativescript-community/ui-mapbox/*": ["src/ui-mapbox/*"] 7 | }, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.vue3.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "paths": { 6 | "nativescript-vue": ["./node_modules/nativescript-vue3"] 7 | } 8 | }, 9 | "include": [ 10 | "./demo-snippets/vue3" 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/ios/Podfile: -------------------------------------------------------------------------------- 1 | # see https://github.com/CocoaPods/CocoaPods/issues/11867 for why i use podspec 2 | # pod 'Mapbox-iOS-SDK', :podspec => 'https://raw.githubusercontent.com/nativescript-community/mapbox-gl-native-ios/refs/heads/main/Mapbox-iOS-SDK.podspec' 3 | platform :ios, '14.0' 4 | pod 'MapboxMaps', '11.16.0' -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | public-hoist-pattern[]=*eslint* 3 | public-hoist-pattern[]=source-map-support 4 | public-hoist-pattern[]=ts-patch 5 | public-hoist-pattern[]=typescript 6 | public-hoist-pattern[]=cpy-cli 7 | strict-peer-dependencies=false 8 | shell-emulator=true 9 | auto-install-peers=false 10 | loglevel=error 11 | engine-strict=true 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tools"] 2 | path = tools 3 | url = https://github.com/nativescript-community/plugin-seed-tools.git 4 | [submodule "demo-ng"] 5 | path = demo-ng 6 | url = https://github.com/nativescript-community/plugin-seed-demo-ng.git 7 | [submodule "demo-vue"] 8 | path = demo-vue 9 | url = git@github.com:nativescript-community/plugin-seed-demo-vue.git 10 | -------------------------------------------------------------------------------- /demo-snippets/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [6.2.20](https://github.com/nativescript-community/ui-mapbox/compare/v6.2.19...v6.2.20) (2023-09-06) 7 | 8 | **Note:** Version bump only for package @nativescript-community/template-snippet 9 | -------------------------------------------------------------------------------- /mapbox_config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Config settings 3 | * 4 | * Set the Mapbox style and access token here. 5 | */ 6 | 7 | export const SETTINGS: any = { 8 | mapbox_access_token: 'YOUR_ACCESS_TOKEN', 9 | 10 | // The style here can either be one of the standard mapbox styles or it can be a URL pointing to self hosted tile server. 11 | 12 | mapbox_style: 'light', 13 | }; 14 | 15 | // END 16 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['prettier-plugin-svelte'], 3 | overrides: [{ files: '*.svelte', options: { parser: 'svelte' } }], 4 | printWidth: 200, 5 | semi: true, 6 | tabWidth: 4, 7 | trailingComma: 'none', 8 | singleQuote: true, 9 | svelteSortOrder: 'options-styles-scripts-markup', 10 | svelteStrictMode: false, 11 | svelteBracketNewLine: false, 12 | svelteIndentScriptAndStyle: true 13 | }; 14 | -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/ios/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MGLMapboxMetricsEnabledSettingShownInApp 6 | 7 | NSLocationWhenInUseUsageDescription 8 | We use your location to show where you are on the map in our app. 9 | 10 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | const sveltePreprocess = require('svelte-preprocess'); 2 | // const svelteNativePreprocessor = require('svelte-native-preprocessor'); 3 | 4 | module.exports = { 5 | compilerOptions: { 6 | namespace: 'foreign' 7 | }, 8 | preprocess: [ 9 | sveltePreprocess({ 10 | typescript: { 11 | compilerOptions: { 12 | target: 'es2020' 13 | } 14 | } 15 | }) 16 | // svelteNativePreprocessor() 17 | ] 18 | }; 19 | -------------------------------------------------------------------------------- /demo-snippets/vue/install.ts: -------------------------------------------------------------------------------- 1 | import { Trace } from '@nativescript/core'; 2 | import Vue from 'nativescript-vue'; 3 | import Basic from './Basic.vue'; 4 | import { MapboxTraceCategory, MapboxView } from '@nativescript-community/ui-mapbox'; 5 | 6 | export function installPlugin() { 7 | Vue.registerElement('MapboxView', () => MapboxView); 8 | } 9 | 10 | export const demos = [{ name: 'Basic', path: 'Basic', component: Basic }]; 11 | 12 | Trace.addCategories(MapboxTraceCategory); 13 | // Trace.addCategories(Trace.categories.Layout); 14 | Trace.enable(); 15 | -------------------------------------------------------------------------------- /packages/ui-mapbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "../../src/ui-mapbox", 5 | "outDir": "./", 6 | "paths": { 7 | "tns-core-modules": ["./node_modules/@nativescript/core"], 8 | "tns-core-modules/*": ["./node_modules/@nativescript/core/*"] 9 | } 10 | }, 11 | "include": ["../../src/ui-mapbox/**/*.ts", "../../references.d.ts", "../../tools/references.d.ts", "../../src/references.d.ts"], 12 | "exclude": ["../../src/ui-mapbox/angular/**"] 13 | } -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo2/mapbox-demo2.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo3/mapbox-demo3.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/assets/hierarchy.js: -------------------------------------------------------------------------------- 1 | window.hierarchyData = "eJydlV9P2zAUxb+Ln82Infpf3hiTJiGgEki8TDyY9hYiUruyjdiE+t0nx1txaGkcXhIpOT6/e0984zfkrA0eNb8Y51iSGsuaYVlXmBDKsagZ5lLcY+Rg1cEitNZ41LyhWbwYvQbUoCu9ebC/71p4RRg9t2aJGkIlRi+uQw1adNp78Kfvqm9PYd0hnN6gBgW/PInLTtKDLUaUyT3/ce9xX8Z55nupw6V53PlSxv/7tiaAW+kF+NMk+tR6p4wvn9pu6cDEMBXFvKL3kaloxryFcA5xzXyTsjxO/ygvqGOLEa/oXnxX2j2DG8Hl0kKUFHl39sX1URztqRdNTZSrCnMlsahETJWrKuPeaB/AFdFzaWGLKt+Md7AItgyVS8tQosrT/An24nZ+XcQaaAthNctg89Wqaw3cwGNrzQhsoJ36IQUj8QMKRjL6D/tqOquXA+eyETm2tCwISerBX+EPuHO7Xo/GkCmnhkCEUjEFWVd7k5oczzZt0bDu1JNLIGmS5GAbJNNS+BewlMlIjfRPOh//0Y9knh4cplJ+8OAqbfifdnLWNek3fbwf5KeOvmsPZUfou35KCoTNUhlsdriM8gKmomc9Vyj1cdKO4XrB2Km+3f4FhQ3eyA==" -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/android/buildscript.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | def MAPBOX_DOWNLOADS_TOKEN = "$System.env.MAPBOX_DOWNLOADS_TOKEN" 4 | maven { 5 | url 'https://api.mapbox.com/downloads/v2/releases/maven' 6 | authentication { 7 | basic(BasicAuthentication) 8 | } 9 | credentials { 10 | // Do not change the username below. 11 | // This should always be `mapbox` (not your username). 12 | username = 'mapbox' 13 | // Use the secret token you stored in gradle.properties as the password 14 | password = MAPBOX_DOWNLOADS_TOKEN 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /demo-snippets/ng/basic-map/basic-map.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { RouterExtensions } from '@nativescript/angular'; 3 | import { MAPBOX_ACCESS_TOKEN } from '../mapbox-token'; 4 | 5 | @Component({ 6 | selector: 'ns-basic-map', 7 | templateUrl: './basic-map.component.html' 8 | }) 9 | export class BasicMapComponent implements OnInit { 10 | constructor(private router: RouterExtensions) {} 11 | MAPBOX_ACCESS_TOKEN = MAPBOX_ACCESS_TOKEN; 12 | 13 | ngOnInit(): void {} 14 | 15 | goBack(): void { 16 | this.router.back(); 17 | } 18 | 19 | onMapReady(args: any): void { 20 | console.log('map is ready'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ui-mapbox/layers/layer-factory.d.ts: -------------------------------------------------------------------------------- 1 | import { LayerCommon, LayerType } from '../common'; 2 | 3 | declare class LayerFactory { 4 | static createLayer(style, source): Promise; 5 | static applyLayerProperties(layer: any, properties: Record); 6 | } 7 | 8 | export declare class Layer implements LayerCommon { 9 | id: string; 10 | private instance; 11 | constructor(instance: any); 12 | visibility(): boolean; 13 | show(): void; 14 | hide(): void; 15 | getNativeInstance(): any; 16 | setFilter(filter: any[]): void; 17 | getFilter(): any[]; 18 | setProperty(name: string, value: any): void; 19 | getProperty(name: string): any; 20 | type(): LayerType; 21 | } 22 | -------------------------------------------------------------------------------- /src/ui-mapbox/README.md: -------------------------------------------------------------------------------- 1 | # iOS builds errors 2 | 3 | If you get can't find symbol MGLMapView and the like remove node_modules and platforms 4 | from your project and rebuild. 5 | 6 | For reasons I have yet to figure out, linking to the src directory from a 7 | project's package.json cause all kinds of errors. 8 | 9 | So build the plugin from the src directory using 10 | 11 | ``` 12 | npm run build.dist 13 | ``` 14 | 15 | and the reference 16 | 17 | ``` 18 | file:/nativescript-mapbox-fbs/publish/dist/package 19 | ``` 20 | 21 | in your project's package.json. 22 | 23 | # Typings 24 | 25 | When upgrading the underlying libraries the typings have to be re-generated. 26 | 27 | Remember to update the pod respositories list in case it's unable to find the 28 | updated pod file. 29 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "7.0.12", 3 | "$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json", 4 | "packages": [ 5 | "packages/*" 6 | ], 7 | "npmClient": "yarn", 8 | "useWorkspaces": true, 9 | "command": { 10 | "publish": { 11 | "cleanupTempFiles": true 12 | } 13 | }, 14 | "npmClientArgs": [ 15 | "--no-package-lock" 16 | ], 17 | "commitHooks": false, 18 | "createRelease": "github", 19 | "conventionalCommits": true, 20 | "private": false, 21 | "message": "chore(release): publish new version %v", 22 | "changelogPreset": "conventional-changelog-conventionalcommits", 23 | "ignoreChanges": [ 24 | "**/__fixtures__/**", 25 | "**/__tests__/**", 26 | "**/*.md" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/ui-mapbox/expression/expression-parser.android.ts: -------------------------------------------------------------------------------- 1 | const Expression = com.mapbox.maps.extension.style.expressions.generated.Expression; 2 | 3 | export class ExpressionParser { 4 | static parseJson(json: any[]): com.mapbox.maps.extension.style.expressions.generated.Expression { 5 | const expression = Expression.fromRaw(JSON.stringify(json)); 6 | return expression; 7 | } 8 | static toJson(filter: com.mapbox.maps.extension.style.expressions.generated.Expression): any[] { 9 | if (!filter) { 10 | return null; 11 | } 12 | 13 | if (!(filter instanceof com.mapbox.maps.extension.style.expressions.generated.Expression)) { 14 | throw new Error('Filter must be a Expression.'); 15 | } 16 | 17 | return JSON.parse(filter.toJson()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo-snippets/ng/basic-map/basic-map.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-footer/mapbox-footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'; 2 | import { RouterExtensions } from '@nativescript/angular'; 3 | 4 | @Component({ 5 | selector: 'app-mapbox-footer', 6 | template: ` 7 | 8 | 9 | 10 | `, 11 | schemas: [NO_ERRORS_SCHEMA] 12 | }) 13 | export class MapboxFooterComponent { 14 | router: RouterExtensions = inject(RouterExtensions); 15 | 16 | goToMapbox(route: string) { 17 | this.router.navigate([route]).then((r) => { 18 | console.log(`Navigation to ${route} successful: `, r); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo3/mapbox-demo3.module.ts: -------------------------------------------------------------------------------- 1 | import { MapboxDemo3Component } from './mapbox-demo3.component'; 2 | import { NO_ERRORS_SCHEMA, NgModule } from '@angular/core'; 3 | import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular'; 4 | import { Routes } from '@angular/router'; 5 | 6 | import { MapboxHeaderComponent } from '../mapbox-header/mapbox-header.component'; 7 | import { MAPBOX_ACCESS_TOKEN } from '../mapbox-token'; 8 | import { MapboxFooterComponent } from '../mapbox-footer/mapbox-footer.component'; 9 | 10 | const routes: Routes = [{ path: '', component: MapboxDemo3Component }]; 11 | 12 | @NgModule({ 13 | declarations: [MapboxDemo3Component], 14 | imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild(routes), MapboxHeaderComponent, MapboxFooterComponent], 15 | exports: [NativeScriptCommonModule], 16 | providers: [], 17 | schemas: [NO_ERRORS_SCHEMA] 18 | }) 19 | export class MapboxDemo3Module {} 20 | -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/android/res/drawable/ic_red_marker.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /src/ui-mapbox/references.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | /// 6 | /// 7 | /// 8 | 9 | // declare namespace com { 10 | // export namespace mapbox { 11 | // export namespace maps { 12 | // interface MapboxMap extends plugin.animation.CameraAnimationsPlugin, plugin.annotation.AnnotationPlugin {} 13 | // interface Style extends extension.style.StyleContract.StyleExtension {} 14 | // } 15 | // } 16 | // } 17 | // declare namespace com { 18 | // export namespace mapbox { 19 | // export namespace maps { 20 | // interface MapboxOptions extends common.MapboxOptions {} 21 | // } 22 | // } 23 | // } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # NativeScript 2 | hooks/ 3 | node_modules/ 4 | platforms 5 | 6 | # NativeScript Template 7 | *.js.map 8 | !ngcc.config.js 9 | !webpack.config.js 10 | 11 | # Logs 12 | logs 13 | *.log 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # General 19 | .DS_Store 20 | .AppleDouble 21 | .LSOverride 22 | .idea 23 | .cloud 24 | .gradle 25 | .project 26 | .yarn 27 | .cxx 28 | tmp/ 29 | 30 | !.eslintrc.js 31 | !.prettierrc.js 32 | 33 | !e2e/*.js 34 | !detox.config.js 35 | devices.js 36 | 37 | *.framework 38 | *.xcframework 39 | **/*.js.map 40 | src/**/*.js 41 | packages/**/*.js 42 | packages/**/*.d.ts 43 | bin 44 | build 45 | Pods 46 | !packages/*/platforms 47 | /packages/**/*.aar 48 | /packages/**/*.framework 49 | /packages/**/*.xcframework 50 | /demo-snippets/**/*.aar 51 | *.xcuserdatad 52 | /packages/README.md 53 | packages/**/*js.map 54 | packages/**/*js 55 | packages/typings 56 | packages/**/angular 57 | packages/**/*.ngsummary.json 58 | packages/**/*.metadata.json 59 | 60 | /blueprint.md 61 | 62 | *.tsbuildinfo -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo/mapbox-demo.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/ui-mapbox/geo.utils.ts: -------------------------------------------------------------------------------- 1 | export class GeoUtils { 2 | /** 3 | * Is the current location within the given circle? 4 | * 5 | * @param {number} longitude to check 6 | * @param {number} latitude to check 7 | * @param {number} longitude center of circle 8 | * @param {number} latitude center of circle 9 | * @param {number} radius of circle in meters 10 | * 11 | * @return {boolean} true if the point is within the given geofence. 12 | * 13 | * @link https://stackoverflow.com/questions/24680247/check-if-a-latitude-and-longitude-is-within-a-circle-google-maps 14 | */ 15 | 16 | static isLocationInCircle(lng, lat, circleLng, circleLat, circleRadius) { 17 | const ky = 40000 / 360; 18 | const kx = Math.cos((Math.PI * circleLat) / 180.0) * ky; 19 | const dx = Math.abs(circleLng - lng) * kx; 20 | const dy = Math.abs(circleLat - lat) * ky; 21 | 22 | const distance = Math.sqrt(dx * dx + dy * dy); 23 | 24 | if (distance < circleRadius / 1000) { 25 | return true; 26 | } 27 | 28 | return false; 29 | } 30 | } // END 31 | -------------------------------------------------------------------------------- /docs/assets/navigation.js: -------------------------------------------------------------------------------- 1 | window.navigationData = "eJyN2E1z2zYQBuD/wrOnatwmbX1z1CQzHalWJTuHZnKAyTWFMYjlAGBstpP/noFISQAF7PLKffcBSIKfX/4vHLy64qZYrrC+71uwxVXRCrcvbgrQXWMXp8JPe9eo4qp4lroqbn7/fnXuRe0Mqg1a6STqCyEu5521aHeuVzAFjtvznR9eWwPWStQbYSyYs1AqYS3YxTQRW2+uQ+0T4IOTyl4qxwrVvRJ9agKHzWzfR1E6NH2mfaxSylq0j/h62T9s5zuX2DThKYz7hyqvfJbwkjN8bZ7wXligFF+fJw3z5rxzilI3Blswrs+ttLhOSbdV9eHVmc6vyrvWXxvBkpPagXkSJdhFIhez12/fxewnwL8s6qXqrAMDFaNn4swghyXJyGGG4Tao+po9EHFqBqmkhhlmECNRLRvhYCkaMIJkE0EKfo+drtLUUKKa/wQFDu6envxebKFm1lM+Tg6CL1qhqOYPQzTMGWhjsPb3bBI/hijwIwjXGUg6Y41q91fH7u7vHXamTCNRgqJWwq10nTSGEt3cg5nenyPhVCcZaV10Six1ErNpaojhlnrbyiR5qvLEeEcimDExgzocGHpOpwzPrYV5Jic2BHjIP3joWY0JiorOUJKKEhT1Twem34Ku/INgvDrIFUI1sAMNl8zsYZJxapCt8KuDuHTDAAXtwC3Bt1FznIYY8F4qx3BBhMH8KmnRcOAkxqD/IjYr+AaKUac5kt3jC8md6zOZtTC15LUxxqFbsJ1yWWwok0h+tfHr7N6I8vnB0utsGqJAH1thKVzuzhAGKOgz+I8PYufCAAmNSzCNjEXmzW4Y5eIYOf+hupjWJ9bPf/z25u319MHqv3Gn0KnACbuu9ZOGKktdJjjzoa2EA3JHExFWDc728HK6xupitunUHPuwNKWuc2pY5zxRlmDtPT6DPn5UnclvwkjxqMAuErFY/iVCnTPysfN7dvwjQeL5ODGI/2mS0vx2oq3EphXWzplXJkrgFSjRU2QUoCBpfcMWneBmmYny+K40qNQMOg7ysH+gzmDDGI/6x98MNIwR6F5WcBssOwLORBl8Oa4dBp7EGHSFNXJimCE4JZx0XQUUN81Q3PFGhk2LGvTx3YfkmR5yuBrnXMGpHMnqmj8q0xABDh8X/n4MS+Ggjn47nslEjEAb0W5BVOR9ZpqhucOfX4aLMgRn9/gSPtooNpcleAcKGnCG3PuLEAH+d3ytpsCLEHUAwK2wPqTP1FOny8PiXgTlGHn36/evPwDYondG" -------------------------------------------------------------------------------- /src/ui-mapbox/markers/Marker.common.ts: -------------------------------------------------------------------------------- 1 | import { Application, Color, Label, StackLayout, Utils } from '@nativescript/core'; 2 | const MARKER_PADDING_PX = 10; 3 | 4 | export function createInfoWindowView(title, snippet) { 5 | const view = new StackLayout(); 6 | view.className = 'mapbox-info-window'; 7 | view.padding = MARKER_PADDING_PX; 8 | view.backgroundColor = 'white'; 9 | view.width = 'auto'; // WRAP_CONTENT 10 | view.height = 'auto'; // WRAP_CONTENT 11 | view.borderRadius = 12; 12 | view.color = new Color('#555'); 13 | view['shadowColor'] = '#000'; 14 | view['shadowOpacity'] = 0.25; 15 | view['shadowRadius'] = 8; 16 | 17 | const titleLabel = new Label(); 18 | titleLabel.id = 'title'; 19 | titleLabel.text = title; 20 | titleLabel.className = 'mapbox-info-window-title'; 21 | titleLabel.fontSize = 16; 22 | titleLabel.fontWeight = 'bold'; 23 | view.addChild(titleLabel); 24 | 25 | const subtitle = new Label(); 26 | subtitle.id = 'subtitle'; 27 | subtitle.text = snippet; 28 | subtitle.className = 'mapbox-info-window-snippet'; 29 | subtitle.fontSize = 14; 30 | // subtitle.visibility = snippet ? 'visible' : 'collapse'; 31 | subtitle.color = new Color('#555'); 32 | view.addChild(subtitle); 33 | 34 | return view; 35 | } 36 | -------------------------------------------------------------------------------- /src/ui-mapbox/expression/expression-parser.ios.ts: -------------------------------------------------------------------------------- 1 | // src/ui-mapbox/expression-parser.ios.ts 2 | // TypeScript shim that exports ExpressionParser (TS API) while delegating to native NativeExpressionParser when available. 3 | 4 | export class ExpressionParser { 5 | // Return native predicate object (opaque) if native parser available, otherwise return the expression JSON. 6 | static parseJson(json: any[]): any { 7 | try { 8 | if ((global as any).NativeExpressionParser && (global as any).NativeExpressionParser.parseJson) { 9 | const res = (global as any).NativeExpressionParser.parseJson(json); 10 | if (res) return res; 11 | } 12 | } catch (e) { 13 | // ignore and fallback 14 | } 15 | return json; 16 | } 17 | 18 | // Try to convert native predicate back to JSON expression. Returns array or null. 19 | static toJson(filter: any): any[] | null { 20 | try { 21 | if (!filter) return null; 22 | if (Array.isArray(filter)) return filter; 23 | if ((global as any).NativeExpressionParser && (global as any).NativeExpressionParser.toJson) { 24 | const res = (global as any).NativeExpressionParser.toJson(filter); 25 | if (res) return res; 26 | } 27 | } catch (e) { 28 | // ignore 29 | } 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /demo-snippets/ng/install.module.ts: -------------------------------------------------------------------------------- 1 | import { NO_ERRORS_SCHEMA, NgModule } from '@angular/core'; 2 | 3 | import { registerElement } from '@nativescript/angular'; 4 | registerElement('Mapbox', () => require('@nativescript-community/ui-mapbox').MapboxView); 5 | 6 | import { BasicMapComponent } from './basic-map/basic-map.component'; 7 | 8 | import { MapboxDemoComponent } from './mapbox-demo/mapbox-demo.component'; 9 | import { MapboxDemo2Component } from './mapbox-demo2/mapbox-demo2.component'; 10 | import { Trace } from '@nativescript/core'; 11 | import { MapboxTraceCategory } from '@nativescript-community/ui-mapbox'; 12 | 13 | export const COMPONENTS = [BasicMapComponent, MapboxDemoComponent, MapboxDemo2Component]; 14 | @NgModule({ 15 | imports: [], 16 | exports: [], 17 | schemas: [NO_ERRORS_SCHEMA] 18 | }) 19 | export class InstallModule {} 20 | 21 | export function installPlugin() {} 22 | 23 | export const demos = [ 24 | { name: 'Basic Map', path: 'basic-map', component: BasicMapComponent }, 25 | { name: 'Demo1', path: 'demo-map', component: MapboxDemoComponent }, 26 | { name: 'Demo2', path: 'demo2-map', component: MapboxDemo2Component } 27 | // { 28 | // path: 'mapbox3', 29 | // loadChildren: () => import('./mapbox-demo3/mapbox-demo3.module').then((m) => m.MapboxDemo3Module) 30 | // } 31 | ]; 32 | 33 | Trace.addCategories(MapboxTraceCategory); 34 | // Trace.addCategories(Trace.categories.Layout); 35 | Trace.enable(); 36 | -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/ios/src/NativeExpressionParser.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import MapboxMaps 3 | 4 | @objcMembers 5 | public class NativeExpressionParser: NSObject { 6 | 7 | /// Parse a Mapbox-style expression provided as a JSON string into a native Expression instance. 8 | /// - Parameter jsonString: NSString containing the JSON array for the expression (e.g. '["==", ["get","foo"], "bar"]') 9 | /// - Returns: an opaque native Expression (as Any) on success, or nil on failure. 10 | @objc public static func parseJson(_ jsonString: NSString) -> Any? { 11 | // Convert string -> Data -> JSON object (NSArray expected) 12 | guard let data = (jsonString as String).data(using: .utf8) else { return nil } 13 | do { 14 | return try JSONDecoder().decode(Exp.self, from: data) 15 | } catch { 16 | // parsing or Expression init failed 17 | return nil 18 | } 19 | } 20 | 21 | /// Convert a native Expression (opaque) back into a JSON string. 22 | /// - Parameter expression: the native Expression (as returned by parseJson) or nil 23 | /// - Returns: NSString containing the JSON array representation, or nil on failure. 24 | @objc public static func toJson(_ expression: Any?) -> NSString? { 25 | guard let expr = expression as? Exp else { return nil } 26 | do { 27 | let data = try JSONEncoder().encode(expr) 28 | return String(data: data, encoding: .utf8) as NSString? 29 | } catch { 30 | return nil 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-header/mapbox-header.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "svelte.plugin.svelte.compilerWarnings": { 4 | "missing-declaration": "ignore", 5 | "a11y-aria-attributes": "ignore", 6 | "a11y-incorrect-aria-attribute-type": "ignore", 7 | "a11y-unknown-aria-attribute": "ignore", 8 | "a11y-hidden": "ignore", 9 | "a11y-misplaced-role": "ignore", 10 | "a11y-unknown-role": "ignore", 11 | "a11y-no-abstract-role": "ignore", 12 | "a11y-no-redundant-roles": "ignore", 13 | "a11y-role-has-required-aria-props": "ignore", 14 | "a11y-accesskey": "ignore", 15 | "a11y-autofocus": "ignore", 16 | "a11y-misplaced-scope": "ignore", 17 | "a11y-positive-tabindex": "ignore", 18 | "a11y-invalid-attribute": "ignore", 19 | "a11y-missing-attribute": "ignore", 20 | "a11y-img-redundant-alt": "ignore", 21 | "a11y-label-has-associated-control": "ignore", 22 | "a11y-media-has-caption": "ignore", 23 | "a11y-distracting-elements": "ignore", 24 | "a11y-structure": "ignore", 25 | "a11y-mouse-events-have-key-events": "ignore", 26 | "a11y-missing-content": "ignore", 27 | "illegal-attribute-character": "ignore" 28 | }, 29 | "scss.lint.validProperties": [ 30 | "max-font-size", 31 | "min-font-size", 32 | "ios-a11y-adjusts-font-size", 33 | "status-bar-style", 34 | "navigation-bar-color", 35 | "status-bar-color", 36 | "ripple-color", 37 | "stroke-color", 38 | "fill-color", 39 | "on-check-color", 40 | "on-tint-color", 41 | "shape", 42 | "elevation", 43 | "horizontal-align", 44 | "horizontal-alignment", 45 | "vertical-text-alignment", 46 | "floating", 47 | "vertical-alignment", 48 | "placeholder-color", 49 | "variant" 50 | ] 51 | } -------------------------------------------------------------------------------- /src/ui-mapbox/layers/parser/property-parser.ios.ts: -------------------------------------------------------------------------------- 1 | import { Color } from '@nativescript/core'; 2 | 3 | export class PropertyParser { 4 | // static parsePropertiesForLayer(propertiesObject) { 5 | // const nProperties = {}; 6 | // if (propertiesObject) { 7 | // Object.keys(propertiesObject).forEach((k) => { 8 | // const actualKey = keysMap[k] || toCamelCase(k); 9 | // const value = propertiesObject[k]; 10 | // const rValue = transformValue(k, value, styleExtras[k]?.iosType); 11 | // if (Array.isArray(value)) { 12 | // nProperties[actualKey] = (NSExpression as any).expressionWithMGLJSONObject(rValue); 13 | // } else { 14 | // nProperties[actualKey] = NSExpression.expressionForConstantValue(rValue); 15 | // } 16 | // }); 17 | // } 18 | // return nProperties; 19 | // } 20 | // static propertyValueFromLayer(layer, key: string): any { 21 | // const actualKey = keysMap[key] || toCamelCase(key); 22 | // const nValue: NSExpression = layer[actualKey]; 23 | // if (!nValue) { 24 | // return null; 25 | // } 26 | // if (nValue.expressionType === NSExpressionType.ConstantValueExpressionType) { 27 | // if (nValue.constantValue instanceof UIColor) { 28 | // return Color.fromIosColor(nValue.constantValue); 29 | // } else { 30 | // return nValue.constantValue; 31 | // } 32 | // } else { 33 | // const expressionObj = (nValue as any).mgl_jsonExpressionObject; 34 | // const data = NSJSONSerialization.dataWithJSONObjectOptionsError(expressionObj, 0 as any); 35 | // const expression: any = NSString.alloc().initWithDataEncoding(data, NSUTF8StringEncoding); 36 | // return JSON.parse(expression); 37 | // } 38 | // } 39 | } 40 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo/mapbox-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, NO_ERRORS_SCHEMA, OnDestroy, OnInit, inject } from '@angular/core'; 2 | import { ActionBarComponent, NavigationButtonDirective, RouterExtensions, registerElement } from '@nativescript/angular'; 3 | import { LatLng, MapboxApi, MapboxTraceCategory, MapboxView, MapboxViewApi } from '@nativescript-community/ui-mapbox'; 4 | import { Trace } from '@nativescript/core'; 5 | import { MapboxHeaderComponent } from '../mapbox-header/mapbox-header.component'; 6 | import { MAPBOX_ACCESS_TOKEN } from '../mapbox-token'; 7 | import { MapboxFooterComponent } from '../mapbox-footer/mapbox-footer.component'; 8 | 9 | registerElement('Mapbox', () => require('@nativescript-community/ui-mapbox').MapboxView); 10 | 11 | @Component({ 12 | selector: 'app-mapbox-demo', 13 | templateUrl: './mapbox-demo.component.html', 14 | schemas: [NO_ERRORS_SCHEMA], 15 | imports: [ActionBarComponent, NavigationButtonDirective, MapboxHeaderComponent, MapboxFooterComponent] 16 | }) 17 | export class MapboxDemoComponent implements OnInit, OnDestroy { 18 | router: RouterExtensions = inject(RouterExtensions); 19 | 20 | mapboxView: MapboxView | undefined; 21 | mapbox: MapboxApi | undefined; 22 | 23 | MAPBOX_ACCESS_TOKEN = MAPBOX_ACCESS_TOKEN; 24 | 25 | ngOnInit() { 26 | console.log('MapboxDemoComponent initialized'); 27 | Trace.addCategories(MapboxTraceCategory); 28 | // Trace.enable() 29 | } 30 | 31 | goBack(): void { 32 | this.router.back(); 33 | } 34 | 35 | onMapReady(args: any): void { 36 | console.log('map is ready: ', args.map); 37 | 38 | this.mapboxView = args.map; 39 | this.mapbox = this.mapboxView?.getMapboxApi(); 40 | 41 | console.log('mapboxView map is ready:', this.mapboxView); 42 | } 43 | 44 | ngOnDestroy(): void { 45 | if (this.mapbox) { 46 | this.mapbox.destroy(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/ui-mapbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nativescript-community/ui-mapbox", 3 | "version": "7.0.12", 4 | "description": "Interactive, thoroughly customizable maps powered by vector tiles and OpenGL.", 5 | "main": "index", 6 | "typings": "index.d.ts", 7 | "scripts": { 8 | "build": "npm run tsc && npm run readme", 9 | "readme": "readme generate -c ../../tools/readme/blueprint.json", 10 | "tsc": "cpy '**/*.d.ts' '../../packages/ui-mapbox' --parents --cwd=../../src/ui-mapbox && tsc --build", 11 | "clean": "bin/rimraf ./*.d.ts ./*.js ./*.js.map ./*.tsbuildinfo ./*.mjs ./*.mjs.map ./angular ./svelte ./vue* ./react", 12 | "build.all": "npm run build" 13 | }, 14 | "nativescript": { 15 | "platforms": { 16 | "android": "3.0.0", 17 | "ios": "3.0.0" 18 | } 19 | }, 20 | "keywords": [ 21 | "NativeScript", 22 | "Map", 23 | "Maps", 24 | "Native Maps", 25 | "Mapbox", 26 | "iOS", 27 | "Android", 28 | "Angular", 29 | "preview|https://raw.githubusercontent.com/nativescript-community/ui-mapbox/master/images/preview.png" 30 | ], 31 | "author": { 32 | "name": "Yermo Lamers", 33 | "email": "yml@yml.com", 34 | "url": "https://miles-by-motorcycle.com/flyingbricksoftware/about" 35 | }, 36 | "contributors": [ 37 | { 38 | "name": "Eddy Verbruggen - Original Author", 39 | "email": "eddyverbruggen@gmail.com" 40 | }, 41 | { 42 | "name": "Alex Wells", 43 | "email": "autaut03@gmail.com" 44 | } 45 | ], 46 | "license": "MIT", 47 | "bugs": { 48 | "url": "https://github.com/nativescript-community/ui-mapbox/issues" 49 | }, 50 | "repository": { 51 | "type": "git", 52 | "url": "https://github.com/nativescript-community/ui-mapbox" 53 | }, 54 | "readmeFilename": "README.md", 55 | "dependencies": { 56 | "@nativescript-community/perms": "^3.0.4" 57 | }, 58 | "gitHead": "89403ea15d2e03759bdf8d04087d58236efc971a" 59 | } 60 | -------------------------------------------------------------------------------- /packages/ui-mapbox/platforms/android/include.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | def MAPBOX_DOWNLOADS_TOKEN = project.hasProperty("MAPBOX_DOWNLOADS_TOKEN") ? project.MAPBOX_DOWNLOADS_TOKEN : "$System.env.MAPBOX_DOWNLOADS_TOKEN" 4 | maven { 5 | url 'https://api.mapbox.com/downloads/v2/releases/maven' 6 | authentication { 7 | basic(BasicAuthentication) 8 | } 9 | credentials { 10 | // Do not change the username below. 11 | // This should always be `mapbox` (not your username). 12 | username = 'mapbox' 13 | // Use the secret token you stored in gradle.properties as the password 14 | password = MAPBOX_DOWNLOADS_TOKEN 15 | } 16 | } 17 | } 18 | 19 | // see https://www.mapbox.com/android-sdk/ 20 | dependencies { 21 | def mapboxVersion = project.hasProperty("mapboxVersion") ? project.mapboxVersion : "11.16.2" 22 | def mapboxServicesVersion = project.hasProperty("mapboxServicesVersion") ? project.mapboxServicesVersion : "7.8.0" 23 | def mapboxPluginsVersion = project.hasProperty("mapboxPluginsVersion") ? project.mapboxPluginsVersion : "v9" 24 | def mapboxAnnotationPluginVersion = project.hasProperty("mapboxAnnotationPluginVersion") ? project.mapboxAnnotationPluginVersion : "0.9.0" 25 | def okHttpVersion = project.hasProperty("okHttpVersion") ? project.okHttpVersion : "4.9.0" 26 | 27 | println "com.mapbox.maps:android:$mapboxVersion" 28 | 29 | // Core Mapbox Maps SDK v11+. For now use ndk27 to support 16Kb 30 | implementation "com.mapbox.maps:android-ndk27:$mapboxVersion" 31 | 32 | // GeoJSON / Annotations support (choose correct module name & version) 33 | implementation "com.mapbox.mapboxsdk:mapbox-sdk-geojson:$mapboxServicesVersion" // example version 34 | // implementation "com.mapbox.plugin:maps-annotation:$mapboxVersion" // plugin example 35 | 36 | // Additional plugins: e.g., location component, gestures, etc. 37 | // implementation "com.mapbox.plugin:maps-locationcomponent:$mapboxVersion" 38 | // implementation "com.mapbox.plugin:maps-gestures:$mapboxVersion" 39 | 40 | implementation "com.squareup.okhttp3:okhttp:$okHttpVersion" 41 | 42 | // If you need Mapbox Search or Navigation SDKs, add here 43 | // implementation "com.mapbox.search:autofill:1.0.0-beta.39" 44 | // implementation "com.mapbox.navigation:android:3.0.0" 45 | 46 | } 47 | 48 | android { 49 | compileOptions { 50 | sourceCompatibility JavaVersion.VERSION_1_8 51 | targetCompatibility JavaVersion.VERSION_1_8 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/ui-mapbox/layers/parser/property-parser.android.ts: -------------------------------------------------------------------------------- 1 | import { Color } from '@nativescript/core'; 2 | 3 | export function toCamelCase(s) { 4 | return s.replace(/([-_][a-z])/gi, ($1) => $1.toUpperCase().replace('-', '').replace('_', '')); 5 | } 6 | 7 | export function toPascalCase(s) { 8 | return s.replace(/(^[a-z]|[-_][a-z])/gi, ($1) => $1.toUpperCase().replace('-', '').replace('_', '')); 9 | } 10 | 11 | const Expression = com.mapbox.maps.extension.style.expressions.generated.Expression; 12 | export function transformValue(key, value) { 13 | let nValue = value; 14 | if (Array.isArray(value)) { 15 | nValue = Expression.fromRaw(JSON.stringify(value)); 16 | } 17 | if (key.indexOf('-color') !== -1 && !Array.isArray(value)) { 18 | const color = value instanceof Color ? value : new Color(value); 19 | nValue = color.android; 20 | } else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { 21 | nValue = Expression.literal(value as any); 22 | } else if (Array.isArray(value)) { 23 | // assume it's a JSON-style expression 24 | nValue = Expression.fromRaw(JSON.stringify(value)); 25 | } 26 | return nValue; 27 | } 28 | export class PropertyParser { 29 | // static parsePropertiesForLayer(propertiesObject) { 30 | // const nProperties = []; 31 | 32 | // const PropertyFactory = com.mapbox.maps.extension.style.layers.PropertyFactory; 33 | // if (propertiesObject) { 34 | // Object.keys(propertiesObject).forEach((k) => { 35 | // const actualKey = toCamelCase(k); 36 | // const value = propertiesObject[k]; 37 | // const nValue = transformValue(k, value); 38 | // nProperties.push(PropertyFactory[actualKey](nValue)); 39 | // }); 40 | // } 41 | 42 | // return nProperties; 43 | // } 44 | 45 | static propertyValueFromLayer(layer, key: string): any { 46 | const getterMethodName = `get${toPascalCase(key)}`; 47 | 48 | let nValue: com.mapbox.maps.extension.style.layers.properties.PropertyValue; 49 | try { 50 | nValue = layer[getterMethodName](); 51 | } catch (e) { 52 | // native method seems not exist 53 | return null; 54 | } 55 | 56 | if (nValue === null || nValue === undefined) { 57 | return null; 58 | } 59 | 60 | if (nValue.isExpression()) { 61 | return JSON.parse(nValue.toString()); 62 | } else if (!!nValue.getColorInt()) { 63 | return new Color(nValue.getColorInt().intValue()); 64 | } else { 65 | return nValue.getValue(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ui-mapbox/layers/layer-factory.ios.ts: -------------------------------------------------------------------------------- 1 | // src/ui-mapbox/layer-factory.ios.ts 2 | // TypeScript shim that exports LayerFactory (TS API) while delegating to native NativeLayerFactory when available. 3 | // This preserves the TS export name 'LayerFactory' as requested. 4 | 5 | import { Trace } from '@nativescript/core'; 6 | import { CLog, CLogTypes, LayerCommon, LayerType } from '../common'; 7 | 8 | export class Layer implements LayerCommon { 9 | constructor( 10 | public mapboxView: MapView, 11 | public id: string 12 | ) {} 13 | 14 | visibility(): boolean { 15 | return true; 16 | } 17 | 18 | show(): void { 19 | NativeLayerFactory.setLayerVisibility(this.mapboxView, this.id, true); 20 | } 21 | 22 | hide(): void { 23 | NativeLayerFactory.setLayerVisibility(this.mapboxView, this.id, false); 24 | } 25 | 26 | getNativeInstance(): any { 27 | return null; 28 | } 29 | 30 | setFilter(filter: any[]): void { 31 | // Not implemented here - recommend using addLayer with JSON via Mapbox.addLayer 32 | } 33 | 34 | getFilter(): any[] { 35 | return null; 36 | } 37 | 38 | setProperty(name: string, value: any): void { 39 | NativeLayerFactory.setLayerProperty(this.mapboxView, this.id, name, value); 40 | } 41 | 42 | getProperty(name: string): any { 43 | return NativeLayerFactory.getLayerProperty(this.mapboxView, this.id, name); 44 | } 45 | type(): LayerType { 46 | return NativeLayerFactory.getLayerType(this.mapboxView, this.id) as LayerType; 47 | } 48 | } 49 | 50 | // Export a TS LayerFactory that matches the old TS API but delegates to NativeLayerFactory 51 | export class LayerFactory { 52 | static async createLayer(mapboxView: MapView, style: any, belowLayerId: string): Promise { 53 | const styleJson = typeof style === 'string' ? style : JSON.stringify(style); 54 | if (Trace.isEnabled()) { 55 | CLog(CLogTypes.info, 'createLayer:', belowLayerId, JSON.stringify(style)); 56 | } 57 | const id = style.id || 'layer_' + Date.now(); 58 | if (NativeLayerFactory.createLayer(mapboxView, id, styleJson, belowLayerId)) { 59 | return new Layer(mapboxView, id); 60 | } else { 61 | throw new Error('failed to create layer'); 62 | } 63 | } 64 | 65 | static applyLayerProperties(mapboxView: MapView, layer: any, properties: Record) { 66 | try { 67 | // NativeLayerFactory.applyLayerProperties(layer.id, properties); 68 | // if ((global as any).NativeLayerFactory && (global as any).NativeLayerFactory.setLayerProperty) { 69 | for (const k of Object.keys(properties)) { 70 | NativeLayerFactory.setLayerProperty(mapboxView, layer.id, k, properties[k]); 71 | } 72 | // } 73 | } catch (e) {} 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "description": "A Nativescript plugin for Mapbox Native Maps.", 4 | "scripts": { 5 | "setup": "npm run submodules && ts-patch install", 6 | "sync": "node ./tools/sync.mjs", 7 | "build": "lerna run build", 8 | "build.all": "npm run build", 9 | "clean": "rimraf -g 'packages/**/*.d.ts' 'packages/**/*.tsbuildinfo' 'packages/**/*.js' 'packages/**/*.mjs' 'packages/**/*.js.map' 'packages/**/*.mjs.map' 'packages/**/*.metada' 'packages/**/angular/ng-package.json'", 10 | "commitmsg": "commitlint -e $GIT_PARAMS", 11 | "demo.ng.android": "cd ./demo-ng && ns run android --no-hmr --env.watchNodeModules", 12 | "demo.ng.clean": "cd ./demo-ng && ns clean", 13 | "demo.ng.ios": "cd ./demo-ng && ns run ios --no-hmr --env.watchNodeModules", 14 | "publish": "npm run setup && npm run clean && npm run build.all && npm run readme && npm run doc && npm run commit_readme_doc_changes && lerna publish", 15 | "postinstall": "npm run setup", 16 | "readme": "lerna run readme && node ./tools/readme.js", 17 | "start": "./node_modules/.bin/ntl -A -s 15 -o", 18 | "submodules": "git submodule update --init", 19 | "update": "node ./tools/update.js", 20 | "doc": "node tools/builddoc.mjs", 21 | "fullclean": "npm run clean && rimraf -g 'packages/**/node_modules' 'demo-*/hooks' 'demo-*/node_modules' 'package-lock.json' 'pnpm-lock.yaml' 'node_modules'", 22 | "commit_readme_doc_changes": "git add docs/** *.md ; git commit -m \"readme/doc\" ; echo \"commit readme doc done\"" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/nativescript-community/ui-mapbox.git" 27 | }, 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/nativescript-community/ui-mapbox/issues" 31 | }, 32 | "homepage": "https://github.com/nativescript-community/ui-mapbox", 33 | "readmeFilename": "README.md", 34 | "dependencies": { 35 | "@nativescript-community/perms": "^3.0.4", 36 | "@nativescript-community/plugin-seed-tools": "portal:tools" 37 | }, 38 | "ntl": { 39 | "descriptions": { 40 | "build": "Build the plugin", 41 | "build.all": "Build the plugin for all platforms", 42 | "clean": "Clean the local environment.", 43 | "demo.ng.android": "Runs the Angular demo on Android.", 44 | "demo.ng.ios": "Runs the Angular demo on iOS.", 45 | "watch": "Watch for changes in the plugin source and re-build." 46 | } 47 | }, 48 | "dependenciesMeta": { 49 | "@nativescript-community/plugin-seed-tools": {} 50 | }, 51 | "engines": { 52 | "npm": "please use yarn or pnpm", 53 | "yarn": ">=1.19.1", 54 | "pnpm": ">=7.0.0", 55 | "node": "^14.20.0 || ^16.13.0 || >=18.10.0" 56 | }, 57 | "workspaces": [ 58 | "packages/*", 59 | "demo*" 60 | ], 61 | "packageManager": "yarn@4.10.2" 62 | } 63 | -------------------------------------------------------------------------------- /demo-snippets/ng/mapbox-demo3/mapbox-demo3.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; 2 | import { RouterExtensions, registerElement } from '@nativescript/angular'; 3 | import { MapStyle, MapboxApi, MapboxMarker, MapboxTraceCategory, MapboxView } from '@nativescript-community/ui-mapbox'; 4 | import { ContentView, EventData, Trace } from '@nativescript/core'; 5 | 6 | import { MapboxHeaderComponent } from '../mapbox-header/mapbox-header.component'; 7 | import { MAPBOX_ACCESS_TOKEN } from '../mapbox-token'; 8 | import { MapboxFooterComponent } from '../mapbox-footer/mapbox-footer.component'; 9 | 10 | registerElement('Mapbox', () => require('@nativescript-community/ui-mapbox').MapboxView); 11 | 12 | @Component({ 13 | selector: 'app-mapbox-demo3', 14 | templateUrl: './mapbox-demo3.component.html', 15 | standalone: false 16 | }) 17 | export class MapboxDemo3Component implements OnInit, OnDestroy { 18 | router: RouterExtensions = inject(RouterExtensions); 19 | cd: ChangeDetectorRef = inject(ChangeDetectorRef); 20 | 21 | mapContainer: ContentView; 22 | mapboxView: MapboxView; 23 | mapbox: MapboxApi; 24 | 25 | markers: MapboxMarker[] = []; 26 | 27 | ngOnInit() { 28 | console.log('----- MapboxDemo2Component initialized'); 29 | Trace.addCategories(MapboxTraceCategory); 30 | Trace.enable(); 31 | } 32 | 33 | loadedMap(args: EventData) { 34 | this.mapContainer = args.object as ContentView; 35 | const settings = { 36 | container: this.mapContainer, 37 | accessToken: MAPBOX_ACCESS_TOKEN, 38 | style: MapStyle.TRAFFIC_DAY, 39 | center: { 40 | lat: 50.681466, 41 | lng: 17.8687037 42 | }, 43 | zoomLevel: 12, // 0 (most of the world) to 20, default 0 44 | showUserLocation: false, // default false 45 | hideAttribution: true, // default false 46 | hideLogo: true, // default false 47 | hideCompass: false, // default false 48 | disableRotation: false, // default false 49 | disableScroll: false, // default false 50 | disableZoom: false, // default false 51 | disableTilt: false // default false 52 | }; 53 | 54 | const mapView = new MapboxView(); 55 | mapView.setConfig(settings); 56 | this.mapContainer.content = mapView; 57 | this.mapReady(mapView); 58 | } 59 | 60 | mapReady(mapView: MapboxView): void { 61 | mapView.on('mapReady', (args: any) => { 62 | this.mapboxView = args.map; 63 | this.mapbox = this.mapboxView.getMapboxApi(); 64 | this.cd.detectChanges(); 65 | console.log('mapboxView map is ready:', this.mapboxView); 66 | }); 67 | } 68 | 69 | goBack(): void { 70 | this.router.back(); 71 | } 72 | 73 | ngOnDestroy(): void { 74 | if (this.mapbox) { 75 | this.mapbox.destroy(); 76 | } 77 | } 78 | 79 | goToMapbox(route: string) { 80 | this.router.navigate([route]).then((r) => { 81 | console.log(`Navigation to ${route} successful: `, r); 82 | }); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ui-mapbox/markers/Marker.android.ts: -------------------------------------------------------------------------------- 1 | import { Application, Color, Label, StackLayout, Trace, Utils } from '@nativescript/core'; 2 | import { CLog, CLogTypes } from '../common'; 3 | 4 | /** 5 | * Hybrid Marker — uses native Mapbox annotation APIs, but NativeScript view for info window. 6 | */ 7 | export class AndroidMarker { 8 | position: com.mapbox.geojson.Point; 9 | icon: android.graphics.Bitmap; 10 | title?: string; 11 | snippet?: string; 12 | id?: string | number; 13 | 14 | pointAnnotation: com.mapbox.maps.plugin.annotation.generated.PointAnnotation; 15 | viewAnnotation: android.view.View; 16 | view: StackLayout; 17 | anchor: com.mapbox.maps.ViewAnnotationAnchorConfig; 18 | layerId: string; 19 | 20 | constructor(opts: { id: string | number; position: com.mapbox.geojson.Point; icon: android.graphics.Bitmap; title?: string; snippet?: string }) { 21 | 22 | this.position = opts.position; 23 | this.id = opts.id; 24 | this.icon = opts.icon; 25 | this.title = opts.title; 26 | this.snippet = opts.snippet; 27 | } 28 | 29 | /** 30 | * Create the native PointAnnotation 31 | */ 32 | prepareAnnotationMarker(pointAnnotationManager: com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager, layerId: string) { 33 | const IconAnchor = com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor; 34 | const PointAnnotationOptions = com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions; 35 | 36 | this.pointAnnotation = pointAnnotationManager.create( 37 | new PointAnnotationOptions().withPoint(this.position).withIconAnchor(IconAnchor.valueOf('BOTTOM')).withIconImage(this.icon) 38 | ) as com.mapbox.maps.plugin.annotation.generated.PointAnnotation; 39 | this.layerId = layerId; 40 | if (Trace.isEnabled()) { 41 | CLog(CLogTypes.log, 'MarkerManager prepareAnnotationMarker: ' + layerId, this.id, this.pointAnnotation); 42 | } 43 | } 44 | 45 | update(pointAnnotationManager: com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager) { 46 | if (!this.pointAnnotation) { 47 | return; 48 | } 49 | // const PointAnnotationOptions = com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions; 50 | // const IconAnchor = com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor; 51 | this.pointAnnotation.setGeometry(this.position); 52 | // this.pointAnnotation.setIconAnchor(IconAnchor.BOTTOM); 53 | this.pointAnnotation.setIconImageBitmap(this.icon); 54 | // 2. Update the annotation via the manager 55 | pointAnnotationManager.update(this.pointAnnotation); 56 | if (this.view) { 57 | const title = this.view.getViewById