diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0686037..b3ca942 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,9 +23,9 @@ The [example app](/example/) demonstrates usage of the library. You need to run It is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app. -If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/YamapLiteExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-yamap-lite`. +If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/YamapLiteExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > @atc/react-native-yamap-lite`. -To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-yamap-lite` under `Android`. +To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `@atc/react-native-yamap-lite` under `Android`. You can use various commands from the root directory to work with the project. diff --git a/README.md b/README.md index 6306821..32f43fc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,42 @@ -# React Native Yandex Maps Lite (Яндекс Карты Lite) +
-Легковесная библиотека для интеграции Yandex Maps (Яндекс Карт) в React Native. Lite версия без маршрутов, геокодера и поиска. +@atc/react-native-yamap-lite + +# @atc/react-native-yamap-lite + +**Легковесная библиотека для интеграции Yandex Maps (Яндекс Карт) в React Native.** + +Yandex Maps · React Native · Fabric + +[![npm](https://img.shields.io/npm/v/@atc/react-native-yamap-lite.svg)](https://www.npmjs.com/package/@atc/react-native-yamap-lite) +[![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android-blue.svg)](#требования) +[![New Architecture](https://img.shields.io/badge/New%20Architecture-Fabric-success.svg)](#требования) +[![tests](https://img.shields.io/badge/tests-Jest%20%2B%20Harness-brightgreen.svg)](#тесты) +[![license](https://img.shields.io/npm/l/@atc/react-native-yamap-lite.svg)](./LICENSE) + +
+ +--- + +Lite-обёртка над [Yandex MapKit SDK](https://yandex.ru/dev/maps/mapkit/) — карты, маркеры, +круги, полигоны, полилинии и кластеризация без лишнего веса: в ней нет маршрутов, +геокодера и поиска, только то, что нужно для отображения карты в приложении. + +Библиотека собрана целиком на **новой архитектуре React Native** (**Fabric** + +**TurboModules**), что даёт нативную скорость рендеринга на iOS и Android. + +## ✨ Возможности + +- 🗺️ **Карты Yandex** — типы `map` / `satellite` / `hybrid`, ночной режим, кастомные стили MapKit. +- 📍 **Маркеры** — локальные (`require`) и удалённые (`{ uri }`) изображения, якорь, масштаб, z-index. +- ⭕ **Круги, полигоны, полилинии** — оверлеи с настраиваемыми цветами заливки и обводки. +- 🔗 **Кластеризация** — компонент `ClusteredYamap` для автоматической группировки маркеров. +- 📱 **Позиция пользователя** — отслеживание геолокации, кастомная иконка и зона точности. +- 🎯 **Управление камерой** — `setCenter`, `setZoom`, `fitAllMarkers`, чтение позиции и видимой области через `ref`. +- 🎨 **Жесты и UI** — гибкая настройка жестов, частоты кадров и позиции логотипа Яндекса. + +> 💡 Знакомы с [`react-native-yamap`](https://github.com/volga-volga/react-native-yamap)? +> API близок по духу — миграция требует минимальных изменений. ## Требования @@ -11,13 +47,13 @@ ## Установка ```sh -yarn add react-native-yamap-lite +yarn add @atc/react-native-yamap-lite ``` или ```sh -npm install react-native-yamap-lite --save +npm install @atc/react-native-yamap-lite --save ``` ### iOS @@ -30,64 +66,35 @@ cd ios && pod install && cd .. ## Инициализация карт -### iOS - -**Обязательно** инициализировать MapKit в функции `didFinishLaunchingWithOptions` в `AppDelegate.swift`: - -```swift -import YandexMapsMobile +Инициализация выполняется **полностью из JavaScript** — не нужно править +`AppDelegate.swift` или `MainApplication`. Достаточно один раз вызвать +`YamapUtils.init(apiKey)` до того, как карта отрендерится (например, в `index.js` +или в корне `App.tsx`). Этот вызов сам устанавливает API-ключ и запускает MapKit +на обеих платформах. -func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil -) -> Bool { +```js +// index.js +import { AppRegistry } from 'react-native'; +import { YamapUtils } from '@atc/react-native-yamap-lite'; +import App from './App'; +import { name as appName } from './app.json'; - reactNativeDelegate = delegate - reactNativeFactory = factory +// Замените на ваш API-ключ от Yandex MapKit +YamapUtils.init('YOUR_API_KEY').catch((error) => { + console.warn('YamapUtils.init failed:', error); +}); - // Инициализуйте SDK Yandex Maps перед стартом React Native - YMKMapKit.setLocale("ru_RU") - YMKMapKit.setApiKey("YOUR_API_KEY") - YMKMapKit.initialize() - - window = UIWindow(frame: UIScreen.main.bounds) +// (необязательно) язык интерфейса карты +YamapUtils.setLocale('ru_RU'); - // ... остальной код инициализации - - return true -} +AppRegistry.registerComponent(appName, () => App); ``` -### Android - -Инициализируйте MapKit в методе `onCreate` класса `MainApplication`: +> 💡 `init` возвращает `Promise` — карту можно рендерить сразу, она дождётся +> завершения инициализации. Метод идемпотентен: повторные вызовы безопасны. -**ВАЖНО:** Замените `YOUR_API_KEY` на ваш API ключ от Yandex MapKit. - -```kotlin -import com.yandex.mapkit.MapKitFactory - -class MainApplication : Application() { - override fun onCreate() { - super.onCreate() - - MapKitFactory.setLocale("ru_RU") - MapKitFactory.setApiKey("YOUR_API_KEY") - MapKitFactory.initialize(applicationContext) - - // ... остальной код инициализации - } -} -``` - -Добавьте в вашем проекте зависимость в `android/app/build.gradle` - -```gradle -dependencies { - implementation('com.yandex.android:maps.mobile:4.24.0-lite') - ... -} -``` +> ℹ️ Android-зависимость MapKit (`com.yandex.android:maps.mobile`) уже входит в +> библиотеку — добавлять её в `android/app/build.gradle` вручную не нужно. ## Использование @@ -95,7 +102,7 @@ dependencies { ```jsx import React from 'react'; -import { YaMap, Marker, Circle } from 'react-native-yamap-lite'; +import { YaMap, Marker, Circle } from '@atc/react-native-yamap-lite'; const Map = () => { return ( @@ -232,6 +239,10 @@ interface YaMapRef { animation?: 'LINEAR' | 'SMOOTH' ) => void; fitAllMarkers: () => void; + getMapObjectCount: () => Promise; + getVisibleRegion: () => Promise; + getScreenPoints: (points: Point[]) => Promise; + getWorldPoints: (points: ScreenPoint[]) => Promise; } ``` @@ -239,7 +250,7 @@ interface YaMapRef { ```jsx import React, { useRef } from 'react'; -import { YaMap } from 'react-native-yamap-lite'; +import { YaMap } from '@atc/react-native-yamap-lite'; const Map = () => { const mapRef = useRef(null); @@ -341,7 +352,7 @@ const Map = () => { Компонент для отображения кластеризованных маркеров: ```jsx -import { ClusteredYamap, Marker } from 'react-native-yamap-lite'; +import { ClusteredYamap, Marker } from '@atc/react-native-yamap-lite'; | null} */ diff --git a/example/harness/helpers.tsx b/example/harness/helpers.tsx index 9b78489..53d88c5 100644 --- a/example/harness/helpers.tsx +++ b/example/harness/helpers.tsx @@ -7,7 +7,7 @@ import { type InitialRegion, type YaMapProps, type YaMapRef, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { INITIAL_REGION, MAP_LOAD_TIMEOUT } from './constants'; import { ensureMapKitInitialized } from './ensureMapKitInit'; diff --git a/example/harness/tests/Circle.harness.tsx b/example/harness/tests/Circle.harness.tsx index 2b46e93..71828c1 100644 --- a/example/harness/tests/Circle.harness.tsx +++ b/example/harness/tests/Circle.harness.tsx @@ -1,5 +1,5 @@ import { describe, test, expect } from 'react-native-harness'; -import { Circle } from 'react-native-yamap-lite'; +import { Circle } from '@atc/react-native-yamap-lite'; import { MOSCOW } from '../constants'; import { renderMapWithOverlays, renderUpdatingOverlays } from '../helpers'; diff --git a/example/harness/tests/ClusteredYamap.harness.tsx b/example/harness/tests/ClusteredYamap.harness.tsx index 78c1631..ddb0d1e 100644 --- a/example/harness/tests/ClusteredYamap.harness.tsx +++ b/example/harness/tests/ClusteredYamap.harness.tsx @@ -12,7 +12,7 @@ import { Marker, type ClusteredYamapProps, type YaMapRef, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { CAMERA_ANIMATION_TIMEOUT, INITIAL_REGION, MOSCOW } from '../constants'; import { ensureMapKitInitialized } from '../ensureMapKitInit'; import { waitForMapReady, expectNear } from '../helpers'; diff --git a/example/harness/tests/MapEvents.harness.tsx b/example/harness/tests/MapEvents.harness.tsx index f6f661f..d8da6e0 100644 --- a/example/harness/tests/MapEvents.harness.tsx +++ b/example/harness/tests/MapEvents.harness.tsx @@ -12,7 +12,7 @@ import { type YaMapRef, type CameraPosition, type MapLoaded, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { INITIAL_REGION, MOSCOW, diff --git a/example/harness/tests/Marker.harness.tsx b/example/harness/tests/Marker.harness.tsx index 2db4f05..8444df9 100644 --- a/example/harness/tests/Marker.harness.tsx +++ b/example/harness/tests/Marker.harness.tsx @@ -4,7 +4,7 @@ import { YaMap, type MarkerRef, type YaMapRef, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { StyleSheet, View } from 'react-native'; import { INITIAL_REGION, MOSCOW } from '../constants'; import { ensureMapKitInitialized } from '../ensureMapKitInit'; diff --git a/example/harness/tests/Polygon.harness.tsx b/example/harness/tests/Polygon.harness.tsx index 4d02b89..a2a5605 100644 --- a/example/harness/tests/Polygon.harness.tsx +++ b/example/harness/tests/Polygon.harness.tsx @@ -1,5 +1,5 @@ import { describe, test, expect } from 'react-native-harness'; -import { Polygon } from 'react-native-yamap-lite'; +import { Polygon } from '@atc/react-native-yamap-lite'; import { MOSCOW } from '../constants'; import { renderMapWithOverlays, renderUpdatingOverlays } from '../helpers'; diff --git a/example/harness/tests/Polyline.harness.tsx b/example/harness/tests/Polyline.harness.tsx index d8b0cd9..b31b593 100644 --- a/example/harness/tests/Polyline.harness.tsx +++ b/example/harness/tests/Polyline.harness.tsx @@ -1,5 +1,5 @@ import { describe, test, expect } from 'react-native-harness'; -import { Polyline } from 'react-native-yamap-lite'; +import { Polyline } from '@atc/react-native-yamap-lite'; import { MOSCOW } from '../constants'; import { renderMapWithOverlays, renderUpdatingOverlays } from '../helpers'; diff --git a/example/harness/tests/Regression.harness.tsx b/example/harness/tests/Regression.harness.tsx index ee28a0d..b4c9648 100644 --- a/example/harness/tests/Regression.harness.tsx +++ b/example/harness/tests/Regression.harness.tsx @@ -17,7 +17,7 @@ import { YaMap, YamapUtils, type YaMapRef, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { CAMERA_ANIMATION_TIMEOUT, INITIAL_REGION, diff --git a/example/harness/tests/UI.harness.tsx b/example/harness/tests/UI.harness.tsx index 4abafa5..9ca6bdc 100644 --- a/example/harness/tests/UI.harness.tsx +++ b/example/harness/tests/UI.harness.tsx @@ -20,7 +20,7 @@ import { Marker, YaMap, type YaMapRef, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { INITIAL_REGION, MOSCOW } from '../constants'; import { ensureMapKitInitialized } from '../ensureMapKitInit'; import { waitForMapReady, expectNear } from '../helpers'; diff --git a/example/harness/tests/YaMap.harness.tsx b/example/harness/tests/YaMap.harness.tsx index 29dea6a..ec8ad59 100644 --- a/example/harness/tests/YaMap.harness.tsx +++ b/example/harness/tests/YaMap.harness.tsx @@ -7,7 +7,7 @@ import { } from 'react-native-harness'; import { useEffect, useState } from 'react'; import { StyleSheet, View } from 'react-native'; -import { YaMap, type YaMapRef } from 'react-native-yamap-lite'; +import { YaMap, type YaMapRef } from '@atc/react-native-yamap-lite'; import { CAMERA_ANIMATION_TIMEOUT, INITIAL_REGION, MOSCOW } from '../constants'; import { ensureMapKitInitialized } from '../ensureMapKitInit'; import { expectNear, renderMap, waitForMapReady } from '../helpers'; diff --git a/example/harness/tests/YamapUtils.harness.ts b/example/harness/tests/YamapUtils.harness.ts index 7157243..0b05f7f 100644 --- a/example/harness/tests/YamapUtils.harness.ts +++ b/example/harness/tests/YamapUtils.harness.ts @@ -6,7 +6,7 @@ import { afterEach, } from 'react-native-harness'; import { Platform } from 'react-native'; -import { YamapUtils } from 'react-native-yamap-lite'; +import { YamapUtils } from '@atc/react-native-yamap-lite'; import { YAMAP_API_KEY } from '../constants'; describe('YamapUtils', () => { diff --git a/example/package.json b/example/package.json index cbf5e59..7e01cd8 100644 --- a/example/package.json +++ b/example/package.json @@ -13,9 +13,9 @@ "test:harness:android": "NODE_OPTIONS='--experimental-require-module' react-native-harness --harnessRunner android" }, "dependencies": { + "@atc/react-native-yamap-lite": "link:..", "react": "19.0.0", - "react-native": "0.79.2", - "react-native-yamap-lite": "link:.." + "react-native": "0.79.2" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/example/src/App.tsx b/example/src/App.tsx index e7ab9ca..a7e1605 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -7,7 +7,7 @@ import { Circle, Polygon, Polyline, -} from 'react-native-yamap-lite'; +} from '@atc/react-native-yamap-lite'; import { ensureMapKitInitialized } from '../harness/ensureMapKitInit'; import { markers } from './constants/markers'; import { diff --git a/images/banner.png b/images/banner.png new file mode 100644 index 0000000..83c28ed Binary files /dev/null and b/images/banner.png differ diff --git a/package.json b/package.json index 41a40d8..1c35793 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "react-native-yamap-lite", - "version": "1.0.1", + "name": "@atc/react-native-yamap-lite", + "version": "1.0.0", "description": "A lightweight wrapper for the Yandex MapKit SDK", "main": "./src/index.tsx", "types": "./src/index.tsx", @@ -70,7 +70,8 @@ }, "homepage": "https://github.com/hydromoll/react-native-yamap-lite#readme", "publishConfig": { - "registry": "https://registry.npmjs.org/" + "registry": "https://registry.npmjs.org/", + "access": "public" }, "devDependencies": { "@commitlint/config-conventional": "^19.6.0", diff --git a/src/Utils/YamapUtils.ts b/src/Utils/YamapUtils.ts index a377bd9..4ade370 100644 --- a/src/Utils/YamapUtils.ts +++ b/src/Utils/YamapUtils.ts @@ -1,7 +1,7 @@ import { Platform, NativeModules } from 'react-native'; const LINKING_ERROR = - `The package 'react-native-yamap-lite' doesn't seem to be linked. Make sure: \n\n` + + `The package '@atc/react-native-yamap-lite' doesn't seem to be linked. Make sure: \n\n` + Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n'; diff --git a/tsconfig.json b/tsconfig.json index 6584195..5b73023 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "rootDir": ".", "paths": { - "react-native-yamap-lite": ["./src/index"] + "@atc/react-native-yamap-lite": ["./src/index"] }, "allowUnreachableCode": false, "allowUnusedLabels": false, diff --git a/yarn.lock b/yarn.lock index 7a96eb4..d295445 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,6 +30,48 @@ __metadata: languageName: node linkType: hard +"@atc/react-native-yamap-lite@link:..::locator=react-native-yamap-lite-example%40workspace%3Aexample": + version: 0.0.0-use.local + resolution: "@atc/react-native-yamap-lite@link:..::locator=react-native-yamap-lite-example%40workspace%3Aexample" + languageName: node + linkType: soft + +"@atc/react-native-yamap-lite@workspace:.": + version: 0.0.0-use.local + resolution: "@atc/react-native-yamap-lite@workspace:." + dependencies: + "@commitlint/config-conventional": ^19.6.0 + "@eslint/compat": ^1.2.7 + "@eslint/eslintrc": ^3.3.0 + "@eslint/js": ^9.22.0 + "@evilmartians/lefthook": ^1.5.0 + "@react-native-community/cli": 15.0.0-alpha.2 + "@react-native/babel-preset": 0.79.2 + "@react-native/eslint-config": ^0.78.0 + "@release-it/conventional-changelog": ^9.0.2 + "@types/jest": ^29.5.5 + "@types/react": ^19.0.0 + "@types/react-test-renderer": ^19.1.0 + commitlint: ^19.6.1 + del-cli: ^5.1.0 + eslint: ^9.22.0 + eslint-config-prettier: ^10.1.1 + eslint-plugin-prettier: ^5.2.3 + jest: ^29.7.0 + prettier: ^3.0.3 + react: 19.0.0 + react-native: 0.79.2 + react-native-builder-bob: ^0.40.11 + react-test-renderer: 19.0.0 + release-it: ^17.10.0 + turbo: ^1.10.7 + typescript: ^5.8.3 + peerDependencies: + react: "*" + react-native: "*" + languageName: unknown + linkType: soft + "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7, @babel/code-frame@npm:^7.26.2, @babel/code-frame@npm:^7.27.1": version: 7.27.1 resolution: "@babel/code-frame@npm:7.27.1" @@ -12911,6 +12953,7 @@ __metadata: version: 0.0.0-use.local resolution: "react-native-yamap-lite-example@workspace:example" dependencies: + "@atc/react-native-yamap-lite": "link:.." "@babel/core": ^7.25.2 "@babel/preset-env": ^7.25.3 "@babel/runtime": ^7.25.0 @@ -12931,49 +12974,6 @@ __metadata: react-native-dotenv: ^3.4.11 react-native-harness: 1.2.0 react-native-monorepo-config: ^0.1.9 - react-native-yamap-lite: "link:.." - languageName: unknown - linkType: soft - -"react-native-yamap-lite@link:..::locator=react-native-yamap-lite-example%40workspace%3Aexample": - version: 0.0.0-use.local - resolution: "react-native-yamap-lite@link:..::locator=react-native-yamap-lite-example%40workspace%3Aexample" - languageName: node - linkType: soft - -"react-native-yamap-lite@workspace:.": - version: 0.0.0-use.local - resolution: "react-native-yamap-lite@workspace:." - dependencies: - "@commitlint/config-conventional": ^19.6.0 - "@eslint/compat": ^1.2.7 - "@eslint/eslintrc": ^3.3.0 - "@eslint/js": ^9.22.0 - "@evilmartians/lefthook": ^1.5.0 - "@react-native-community/cli": 15.0.0-alpha.2 - "@react-native/babel-preset": 0.79.2 - "@react-native/eslint-config": ^0.78.0 - "@release-it/conventional-changelog": ^9.0.2 - "@types/jest": ^29.5.5 - "@types/react": ^19.0.0 - "@types/react-test-renderer": ^19.1.0 - commitlint: ^19.6.1 - del-cli: ^5.1.0 - eslint: ^9.22.0 - eslint-config-prettier: ^10.1.1 - eslint-plugin-prettier: ^5.2.3 - jest: ^29.7.0 - prettier: ^3.0.3 - react: 19.0.0 - react-native: 0.79.2 - react-native-builder-bob: ^0.40.11 - react-test-renderer: 19.0.0 - release-it: ^17.10.0 - turbo: ^1.10.7 - typescript: ^5.8.3 - peerDependencies: - react: "*" - react-native: "*" languageName: unknown linkType: soft