@quantaroute/checkout 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +389 -0
- package/dist/lib/index.d.ts +257 -0
- package/dist/lib/quantaroute-checkout.es.js +18549 -0
- package/dist/lib/quantaroute-checkout.umd.js +5035 -0
- package/dist/lib/style.css +1 -0
- package/package.json +89 -0
package/README.md
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# @quantaroute/checkout
|
|
2
|
+
|
|
3
|
+
> **DigiPin-powered smart address checkout widget for Indian e-commerce.**
|
|
4
|
+
> Two-step: Map pin โ Auto-filled form. Works in any React/Next.js/Nuxt/Vite app.
|
|
5
|
+
|
|
6
|
+
[](https://quantaroute.com)
|
|
7
|
+
[](https://www.indiapost.gov.in)
|
|
8
|
+
[-green)](https://carto.com)
|
|
9
|
+
[](./LICENSE)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Replaces your broken Indian address form with a two-step Uber-style flow:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Step 1 โ Map Pin Step 2 โ Auto-fill + Details
|
|
19
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
20
|
+
โ [DigiPin: 39J-438-TJC7] โ โ ๐ Auto-detected โ
|
|
21
|
+
โ โ โ State: Delhi โ
|
|
22
|
+
โ ๐บ Carto Positron map โ โโโบ โ District: New Delhi โ
|
|
23
|
+
โ ๐ โ drag โ โ Pincode: 110011 โ
|
|
24
|
+
โ โ โ โ Deliverable โ
|
|
25
|
+
โ [๐ก Locate Me] โ โ ๐ Add details โ
|
|
26
|
+
โ [Confirm Location โ] โ โ Flat No: [_________] โ
|
|
27
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ [โ Adjust] [Save โ] โ
|
|
28
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Key features:**
|
|
32
|
+
|
|
33
|
+
- DigiPin shown **offline** in real-time as the user drags the pin (~4mร4m precision)
|
|
34
|
+
- **No Google Maps.** Free Carto Positron vector basemap (MapLibre GL JS)
|
|
35
|
+
- Auto-fills State, District, Locality, Pincode, Delivery status from QuantaRoute API
|
|
36
|
+
- Manual fields: Flat no., Floor, Building (OSM-pre-filled), Street/Area (OSM-pre-filled)
|
|
37
|
+
- Mobile-first (full-screen on phones, card on desktop)
|
|
38
|
+
- Dark mode, reduced-motion, keyboard navigation, ARIA labels
|
|
39
|
+
- TypeScript, zero runtime deps beyond MapLibre + React
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
### 0 ยท Get an API key
|
|
46
|
+
|
|
47
|
+
1. Sign up at **[developers.quantaroute.com](https://developers.quantaroute.com)**
|
|
48
|
+
2. Create a project โ copy your **API key**
|
|
49
|
+
3. Store it as an environment variable in your app:
|
|
50
|
+
|
|
51
|
+
| Framework | Variable name convention |
|
|
52
|
+
|-----------|--------------------------|
|
|
53
|
+
| Next.js | `NEXT_PUBLIC_QUANTAROUTE_KEY` in `.env.local` |
|
|
54
|
+
| Vite | `VITE_QR_API_KEY` in `.env` |
|
|
55
|
+
| Nuxt | `NUXT_PUBLIC_QR_API_KEY` in `.env` |
|
|
56
|
+
| Node/Express backend | `QUANTAROUTE_KEY` (server-side only) |
|
|
57
|
+
|
|
58
|
+
> **Never hard-code or commit API keys to git.**
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 1 ยท Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @quantaroute/checkout maplibre-gl
|
|
66
|
+
# or
|
|
67
|
+
yarn add @quantaroute/checkout maplibre-gl
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2 ยท Import CSS
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// In your app's entry file (main.tsx / _app.tsx / nuxt.config.ts, etc.)
|
|
74
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
75
|
+
import '@quantaroute/checkout/dist/style.css';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3 ยท Drop it in
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { CheckoutWidget } from '@quantaroute/checkout';
|
|
82
|
+
|
|
83
|
+
export default function CheckoutPage() {
|
|
84
|
+
return (
|
|
85
|
+
<CheckoutWidget
|
|
86
|
+
apiKey={process.env.NEXT_PUBLIC_QUANTAROUTE_KEY!} {/* never hard-code keys */}
|
|
87
|
+
onComplete={(address) => {
|
|
88
|
+
console.log(address.digipin); // "39J-438-TJC7"
|
|
89
|
+
console.log(address.pincode); // "110011"
|
|
90
|
+
console.log(address.formattedAddress); // "Flat 4B, Floor 3rd, ..."
|
|
91
|
+
// โ send to your backend / payment gateway
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
> **Get your API key** (free tier: 25,000 requests/month) โ
|
|
99
|
+
> **[developers.quantaroute.com](https://developers.quantaroute.com)**
|
|
100
|
+
>
|
|
101
|
+
> Store it as an environment variable โ **never commit API keys to source control**.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Props
|
|
106
|
+
|
|
107
|
+
| Prop | Type | Default | Description |
|
|
108
|
+
|------|------|---------|-------------|
|
|
109
|
+
| `apiKey` | `string` | **required** | QuantaRoute API key |
|
|
110
|
+
| `onComplete` | `(addr: CompleteAddress) => void` | **required** | Fired after user saves address |
|
|
111
|
+
| `apiBaseUrl` | `string` | `https://api.quantaroute.com` | Custom API URL (self-hosted) |
|
|
112
|
+
| `onError` | `(err: Error) => void` | โ | Optional error handler |
|
|
113
|
+
| `defaultLat` | `number` | India center | Pre-center the map here |
|
|
114
|
+
| `defaultLng` | `number` | India center | Pre-center the map here |
|
|
115
|
+
| `theme` | `'light' \| 'dark'` | `'light'` | Color theme |
|
|
116
|
+
| `mapHeight` | `string` | `'380px'` | CSS height of the map area |
|
|
117
|
+
| `title` | `string` | `'Add Delivery Address'` | Widget header text |
|
|
118
|
+
| `className` | `string` | โ | Extra class on root element |
|
|
119
|
+
| `style` | `CSSProperties` | โ | Inline styles on root element |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## `CompleteAddress` output
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
interface CompleteAddress {
|
|
127
|
+
digipin: string; // "39J-438-TJC7"
|
|
128
|
+
lat: number; // 28.61390
|
|
129
|
+
lng: number; // 77.20900
|
|
130
|
+
|
|
131
|
+
// Auto-filled from QuantaRoute API
|
|
132
|
+
state: string; // "Delhi"
|
|
133
|
+
district: string; // "New Delhi"
|
|
134
|
+
division: string; // "New Delhi Central"
|
|
135
|
+
locality: string; // "Nirman Bhawan SO"
|
|
136
|
+
pincode: string; // "110011"
|
|
137
|
+
delivery: string; // "Delivery" | "Non Delivery"
|
|
138
|
+
country: string; // "India"
|
|
139
|
+
|
|
140
|
+
// Manual entry by user
|
|
141
|
+
flatNumber: string; // "4B"
|
|
142
|
+
floorNumber: string; // "3rd"
|
|
143
|
+
buildingName: string; // "Sunshine Apartments" (pre-filled from Nominatim OSM)
|
|
144
|
+
streetName: string; // "MG Road, Action Area I" (pre-filled from road + suburb)
|
|
145
|
+
|
|
146
|
+
formattedAddress: string; // "4B, 3rd Floor, Sunshine Apartments, MG Road, ..."
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Framework integration guides
|
|
153
|
+
|
|
154
|
+
### Next.js (App Router)
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
// app/checkout/page.tsx
|
|
158
|
+
'use client'; // โ required (MapLibre is browser-only)
|
|
159
|
+
|
|
160
|
+
import dynamic from 'next/dynamic';
|
|
161
|
+
|
|
162
|
+
const CheckoutWidget = dynamic(
|
|
163
|
+
() => import('@quantaroute/checkout').then((m) => m.CheckoutWidget),
|
|
164
|
+
{ ssr: false } // โ required (no SSR for map)
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
export default function CheckoutPage() {
|
|
168
|
+
return (
|
|
169
|
+
<main className="max-w-lg mx-auto p-4">
|
|
170
|
+
<CheckoutWidget
|
|
171
|
+
apiKey={process.env.NEXT_PUBLIC_QUANTAROUTE_KEY!} {/* set in .env.local */}
|
|
172
|
+
onComplete={(addr) => console.log(addr)}
|
|
173
|
+
/>
|
|
174
|
+
</main>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Add CSS imports to `app/layout.tsx`:
|
|
180
|
+
```tsx
|
|
181
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
182
|
+
import '@quantaroute/checkout/dist/style.css';
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### Next.js (Pages Router)
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
// pages/checkout.tsx
|
|
191
|
+
import dynamic from 'next/dynamic';
|
|
192
|
+
const CheckoutWidget = dynamic(() => import('@quantaroute/checkout'), { ssr: false });
|
|
193
|
+
|
|
194
|
+
export default function CheckoutPage() {
|
|
195
|
+
return (
|
|
196
|
+
<CheckoutWidget
|
|
197
|
+
apiKey={process.env.NEXT_PUBLIC_QUANTAROUTE_KEY!} {/* .env.local */}
|
|
198
|
+
onComplete={(a) => console.log(a)}
|
|
199
|
+
/>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### Nuxt 3
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
// nuxt.config.ts
|
|
210
|
+
export default defineNuxtConfig({
|
|
211
|
+
css: [
|
|
212
|
+
'maplibre-gl/dist/maplibre-gl.css',
|
|
213
|
+
'@quantaroute/checkout/dist/style.css',
|
|
214
|
+
],
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
```vue
|
|
219
|
+
<!-- components/AddressWidget.client.vue -->
|
|
220
|
+
<!-- The .client suffix ensures this only renders on the client -->
|
|
221
|
+
<script setup lang="ts">
|
|
222
|
+
import { CheckoutWidget } from '@quantaroute/checkout';
|
|
223
|
+
|
|
224
|
+
function handleComplete(address) {
|
|
225
|
+
console.log(address.digipin, address.formattedAddress);
|
|
226
|
+
}
|
|
227
|
+
</script>
|
|
228
|
+
|
|
229
|
+
<template>
|
|
230
|
+
<!-- API key via runtimeConfig โ useRuntimeConfig().public.qrApiKey -->
|
|
231
|
+
<CheckoutWidget
|
|
232
|
+
:api-key="runtimeConfig.public.qrApiKey"
|
|
233
|
+
map-height="360px"
|
|
234
|
+
@complete="handleComplete"
|
|
235
|
+
/>
|
|
236
|
+
</template>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### Vite + React
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
// src/App.tsx
|
|
245
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
246
|
+
import '@quantaroute/checkout/dist/style.css';
|
|
247
|
+
import { CheckoutWidget } from '@quantaroute/checkout';
|
|
248
|
+
|
|
249
|
+
function App() {
|
|
250
|
+
return (
|
|
251
|
+
<div style={{ padding: '20px' }}>
|
|
252
|
+
<CheckoutWidget
|
|
253
|
+
apiKey={import.meta.env.VITE_QR_API_KEY}
|
|
254
|
+
onComplete={(addr) => console.log('Saved:', addr)}
|
|
255
|
+
/>
|
|
256
|
+
</div>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Vanilla JS (UMD / Script tag)
|
|
264
|
+
|
|
265
|
+
```html
|
|
266
|
+
<!DOCTYPE html>
|
|
267
|
+
<html>
|
|
268
|
+
<head>
|
|
269
|
+
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" />
|
|
270
|
+
<link rel="stylesheet" href="https://unpkg.com/@quantaroute/checkout/dist/style.css" />
|
|
271
|
+
</head>
|
|
272
|
+
<body>
|
|
273
|
+
<div id="checkout-root"></div>
|
|
274
|
+
|
|
275
|
+
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
276
|
+
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
277
|
+
<script src="https://unpkg.com/@quantaroute/checkout/dist/lib/quantaroute-checkout.umd.js"></script>
|
|
278
|
+
<script>
|
|
279
|
+
const { createRoot } = ReactDOM;
|
|
280
|
+
const { CheckoutWidget } = QuantaRouteCheckout;
|
|
281
|
+
|
|
282
|
+
// Replace window.__QR_API_KEY__ with your key from developers.quantaroute.com
|
|
283
|
+
// In production, inject this via server-side template or env variable.
|
|
284
|
+
createRoot(document.getElementById('checkout-root')).render(
|
|
285
|
+
React.createElement(CheckoutWidget, {
|
|
286
|
+
apiKey: window.__QR_API_KEY__ || '',
|
|
287
|
+
onComplete: (addr) => console.log('Done:', addr),
|
|
288
|
+
})
|
|
289
|
+
);
|
|
290
|
+
</script>
|
|
291
|
+
</body>
|
|
292
|
+
</html>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### React Native (coming soon)
|
|
298
|
+
|
|
299
|
+
A React Native version is planned that will use `react-native-maps` + the same offline DigiPin algorithm and QuantaRoute API. Track progress in issues.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Advanced usage
|
|
304
|
+
|
|
305
|
+
### Use sub-components individually
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
import { MapPinSelector, AddressForm, getDigiPin, isWithinIndia } from '@quantaroute/checkout';
|
|
309
|
+
|
|
310
|
+
// Offline DigiPin (no API call needed)
|
|
311
|
+
const dp = getDigiPin(28.6139, 77.2090); // "39J-438-TJC7"
|
|
312
|
+
const valid = isWithinIndia(28.6139, 77.2090); // true
|
|
313
|
+
|
|
314
|
+
// Custom two-step flow
|
|
315
|
+
function MyCheckout() {
|
|
316
|
+
const [loc, setLoc] = useState(null);
|
|
317
|
+
|
|
318
|
+
return loc == null
|
|
319
|
+
? <MapPinSelector onLocationConfirm={(lat, lng, dp) => setLoc({ lat, lng, dp })} />
|
|
320
|
+
: <AddressForm {...loc} digipin={loc.dp} apiKey="..." onAddressComplete={...} onBack={...} />;
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Custom theme with CSS variables
|
|
325
|
+
|
|
326
|
+
```css
|
|
327
|
+
/* Override the design tokens in your global CSS */
|
|
328
|
+
.qr-checkout {
|
|
329
|
+
--qr-primary: #6366f1; /* indigo */
|
|
330
|
+
--qr-primary-dark: #4f46e5;
|
|
331
|
+
--qr-radius: 8px;
|
|
332
|
+
--qr-font: 'Poppins', sans-serif;
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Map tile license
|
|
339
|
+
|
|
340
|
+
This widget uses **Carto Positron** vector tiles via MapLibre GL JS.
|
|
341
|
+
|
|
342
|
+
- Free for commercial use (attribution required)
|
|
343
|
+
- Attribution: `ยฉ OpenStreetMap contributors ยฉ CARTO`
|
|
344
|
+
- Does **not** use Google Maps, Mapbox, or OSM raster tiles
|
|
345
|
+
- No API key required for Carto basemaps
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## DigiPin license
|
|
350
|
+
|
|
351
|
+
The offline DigiPin algorithm is the official India Post implementation:
|
|
352
|
+
|
|
353
|
+
- **Source:** [github.com/INDIAPOST-gov/digipin](https://github.com/INDIAPOST-gov/digipin)
|
|
354
|
+
- **Developed by:** India Post, IIT Hyderabad, ISRO NRSC
|
|
355
|
+
- **License:** Apache 2.0
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Development
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
git clone https://github.com/quantaroute/checkout.git
|
|
363
|
+
cd quantaroute-checkout
|
|
364
|
+
|
|
365
|
+
npm install
|
|
366
|
+
npm run dev # Dev server at http://localhost:5173
|
|
367
|
+
|
|
368
|
+
npm run type-check # TypeScript check
|
|
369
|
+
npm run build # Build demo
|
|
370
|
+
npm run build:lib # Build library (dist/lib/)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Changelog
|
|
376
|
+
|
|
377
|
+
### v1.0.0
|
|
378
|
+
|
|
379
|
+
- Initial release
|
|
380
|
+
- MapLibre GL + Carto Positron (free, no API key)
|
|
381
|
+
- Offline DigiPin generation (real-time on pin drag)
|
|
382
|
+
- QuantaRoute location lookup API integration
|
|
383
|
+
- Mobile-first responsive design
|
|
384
|
+
- Dark mode, reduced-motion, keyboard accessible
|
|
385
|
+
- React / Next.js / Nuxt / Vite / Vanilla JS support
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
**Made with โค๏ธ in India ยท Powered by [QuantaRoute](https://quantaroute.com)**
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { default as default_2 } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Address components from Nominatim/OpenStreetMap (via reverse geocoding).
|
|
6
|
+
*/
|
|
7
|
+
export declare interface AddressComponents {
|
|
8
|
+
house_number?: string;
|
|
9
|
+
road?: string;
|
|
10
|
+
neighbourhood?: string;
|
|
11
|
+
suburb?: string;
|
|
12
|
+
city?: string;
|
|
13
|
+
state?: string;
|
|
14
|
+
postcode?: string;
|
|
15
|
+
country?: string;
|
|
16
|
+
country_code?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
addr_housename?: string;
|
|
19
|
+
addr_place?: string;
|
|
20
|
+
building?: string;
|
|
21
|
+
building_name?: string;
|
|
22
|
+
[key: string]: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare const AddressForm: default_2.FC<AddressFormProps>;
|
|
26
|
+
|
|
27
|
+
export declare interface AddressFormProps {
|
|
28
|
+
digipin: string;
|
|
29
|
+
lat: number;
|
|
30
|
+
lng: number;
|
|
31
|
+
apiKey: string;
|
|
32
|
+
apiBaseUrl?: string;
|
|
33
|
+
onAddressComplete: (address: CompleteAddress) => void;
|
|
34
|
+
onBack: () => void;
|
|
35
|
+
onError?: (error: Error) => void;
|
|
36
|
+
theme?: 'light' | 'dark';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export declare interface AdministrativeInfo {
|
|
40
|
+
country?: string;
|
|
41
|
+
state: string;
|
|
42
|
+
division: string;
|
|
43
|
+
locality: string;
|
|
44
|
+
pincode: string;
|
|
45
|
+
delivery: string;
|
|
46
|
+
district: string;
|
|
47
|
+
mean_population_density?: number;
|
|
48
|
+
min_population_density?: number;
|
|
49
|
+
max_population_density?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* QuantaRoute Checkout Widget
|
|
54
|
+
*
|
|
55
|
+
* A two-step, mobile-first address collection component:
|
|
56
|
+
* Step 1 โ Map: user pins their exact location (DigiPin shown offline, real-time)
|
|
57
|
+
* Step 2 โ Form: auto-filled address + manual flat/building details
|
|
58
|
+
*
|
|
59
|
+
* Works in React, Next.js, Nuxt (via nuxt-module), Vite, etc.
|
|
60
|
+
* Embed as a script tag (vanilla JS) via the UMD build.
|
|
61
|
+
*/
|
|
62
|
+
declare const CheckoutWidget: default_2.FC<CheckoutWidgetProps>;
|
|
63
|
+
export { CheckoutWidget }
|
|
64
|
+
export default CheckoutWidget;
|
|
65
|
+
|
|
66
|
+
export declare interface CheckoutWidgetProps {
|
|
67
|
+
/**
|
|
68
|
+
* Your QuantaRoute API key.
|
|
69
|
+
* Get one free at https://quantaroute.com
|
|
70
|
+
*/
|
|
71
|
+
apiKey: string;
|
|
72
|
+
/** API base URL. Defaults to https://api.quantaroute.com */
|
|
73
|
+
apiBaseUrl?: string;
|
|
74
|
+
/** Callback fired when user completes the full address entry. */
|
|
75
|
+
onComplete: (address: CompleteAddress) => void;
|
|
76
|
+
/** Optional error handler. */
|
|
77
|
+
onError?: (error: Error) => void;
|
|
78
|
+
/** Default map latitude (center). If provided, map opens at this location. */
|
|
79
|
+
defaultLat?: number;
|
|
80
|
+
/** Default map longitude (center). */
|
|
81
|
+
defaultLng?: number;
|
|
82
|
+
/** Color theme. Defaults to 'light'. */
|
|
83
|
+
theme?: 'light' | 'dark';
|
|
84
|
+
/** CSS class name(s) to add to the root element. */
|
|
85
|
+
className?: string;
|
|
86
|
+
/** Inline styles for the root element. */
|
|
87
|
+
style?: CSSProperties;
|
|
88
|
+
/** Map area height. Defaults to '380px'. */
|
|
89
|
+
mapHeight?: string;
|
|
90
|
+
/** Widget header title. Defaults to 'Add Delivery Address'. */
|
|
91
|
+
title?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export declare interface CompleteAddress {
|
|
95
|
+
/** Official India Post DigiPin code for this location (~4m x 4m precision) */
|
|
96
|
+
digipin: string;
|
|
97
|
+
/** Latitude of the confirmed pin location */
|
|
98
|
+
lat: number;
|
|
99
|
+
/** Longitude of the confirmed pin location */
|
|
100
|
+
lng: number;
|
|
101
|
+
/** Auto-filled: State */
|
|
102
|
+
state: string;
|
|
103
|
+
/** Auto-filled: District */
|
|
104
|
+
district: string;
|
|
105
|
+
/** Auto-filled: Postal division */
|
|
106
|
+
division: string;
|
|
107
|
+
/** Auto-filled: Locality / Post Office area */
|
|
108
|
+
locality: string;
|
|
109
|
+
/** Auto-filled: 6-digit pincode */
|
|
110
|
+
pincode: string;
|
|
111
|
+
/** Auto-filled: Delivery status ("Delivery" | "Non Delivery") */
|
|
112
|
+
delivery: string;
|
|
113
|
+
/** Auto-filled: Country */
|
|
114
|
+
country: string;
|
|
115
|
+
/** Manual: Flat / House number */
|
|
116
|
+
flatNumber: string;
|
|
117
|
+
/** Manual: Floor number */
|
|
118
|
+
floorNumber: string;
|
|
119
|
+
/** Manual: Building / Society name */
|
|
120
|
+
buildingName: string;
|
|
121
|
+
/** Manual: Street / Area */
|
|
122
|
+
streetName: string;
|
|
123
|
+
/** Combined formatted address string */
|
|
124
|
+
formattedAddress: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export declare interface Coordinates {
|
|
128
|
+
lat: number;
|
|
129
|
+
lng: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Geographic bounds for India */
|
|
133
|
+
export declare const DIGIPIN_BOUNDS: {
|
|
134
|
+
minLat: number;
|
|
135
|
+
maxLat: number;
|
|
136
|
+
minLon: number;
|
|
137
|
+
maxLon: number;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
declare interface DigiPinCoordinates {
|
|
141
|
+
latitude: string;
|
|
142
|
+
longitude: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Convert lat/lng coordinates to a DigiPin code.
|
|
147
|
+
* @throws if coordinates are outside India's bounds
|
|
148
|
+
*/
|
|
149
|
+
export declare function getDigiPin(lat: number, lon: number): string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Decode a DigiPin code back to center-point coordinates.
|
|
153
|
+
* @throws if the DigiPin format is invalid
|
|
154
|
+
*/
|
|
155
|
+
export declare function getLatLngFromDigiPin(digiPin: string): DigiPinCoordinates;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Validate a DigiPin string (format + character check).
|
|
159
|
+
*/
|
|
160
|
+
export declare function isValidDigiPin(digiPin: string): boolean;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Check if a lat/lng point is within India's DigiPin coverage area.
|
|
164
|
+
*/
|
|
165
|
+
export declare function isWithinIndia(lat: number, lon: number): boolean;
|
|
166
|
+
|
|
167
|
+
export declare interface LocationAlternative {
|
|
168
|
+
pincode: string;
|
|
169
|
+
name: string;
|
|
170
|
+
branchType: string;
|
|
171
|
+
deliveryStatus: string;
|
|
172
|
+
district: string;
|
|
173
|
+
state: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
declare interface LocationLookupData {
|
|
177
|
+
coordinates: {
|
|
178
|
+
latitude: number;
|
|
179
|
+
longitude: number;
|
|
180
|
+
};
|
|
181
|
+
digipin: string;
|
|
182
|
+
administrative_info: AdministrativeInfo;
|
|
183
|
+
alternatives?: LocationAlternative[];
|
|
184
|
+
confidence: number;
|
|
185
|
+
source: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export declare interface LocationLookupResponse {
|
|
189
|
+
success: boolean;
|
|
190
|
+
data: LocationLookupData;
|
|
191
|
+
error?: string;
|
|
192
|
+
message?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Call QuantaRoute's Location Lookup API.
|
|
197
|
+
* Converts lat/lng โ full Indian administrative address + DigiPin.
|
|
198
|
+
*/
|
|
199
|
+
export declare function lookupLocation(lat: number, lng: number, apiKey: string, baseUrl?: string): Promise<LocationLookupResponse>;
|
|
200
|
+
|
|
201
|
+
export declare const MapPinSelector: default_2.FC<MapPinSelectorProps>;
|
|
202
|
+
|
|
203
|
+
export declare interface MapPinSelectorProps {
|
|
204
|
+
onLocationConfirm: (lat: number, lng: number, digipin: string) => void;
|
|
205
|
+
defaultLat?: number;
|
|
206
|
+
defaultLng?: number;
|
|
207
|
+
mapHeight?: string;
|
|
208
|
+
theme?: 'light' | 'dark';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Call QuantaRoute's Reverse Geocoding API.
|
|
213
|
+
* Converts DigiPin โ address components from Nominatim/OpenStreetMap.
|
|
214
|
+
*/
|
|
215
|
+
export declare function reverseGeocode(digipin: string, apiKey: string, baseUrl?: string): Promise<ReverseGeocodeResponse>;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Response from /v1/digipin/reverse endpoint.
|
|
219
|
+
*/
|
|
220
|
+
export declare interface ReverseGeocodeResponse {
|
|
221
|
+
success: boolean;
|
|
222
|
+
data: {
|
|
223
|
+
digipin: string;
|
|
224
|
+
address: string;
|
|
225
|
+
coordinates: {
|
|
226
|
+
latitude: number;
|
|
227
|
+
longitude: number;
|
|
228
|
+
};
|
|
229
|
+
confidence: number;
|
|
230
|
+
displayName: string;
|
|
231
|
+
addressComponents: AddressComponents;
|
|
232
|
+
};
|
|
233
|
+
error?: string;
|
|
234
|
+
message?: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Compute a DigiPin code from lat/lng entirely offline (no API call).
|
|
239
|
+
* Returns null if coordinates are outside India's bounds.
|
|
240
|
+
*
|
|
241
|
+
* The calculation is pure math (~0.1ms), so no debouncing is needed
|
|
242
|
+
* even when called on every marker drag event.
|
|
243
|
+
*/
|
|
244
|
+
export declare function useDigiPin(lat: number, lng: number): string | null;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Hook to imperatively request the user's current GPS position.
|
|
248
|
+
* Returns a `locate(onSuccess)` callback to trigger the permission prompt.
|
|
249
|
+
*/
|
|
250
|
+
export declare function useGeolocation(): {
|
|
251
|
+
locate: (onSuccess: (lat: number, lng: number) => void) => void;
|
|
252
|
+
clearError: () => void;
|
|
253
|
+
loading: boolean;
|
|
254
|
+
error: string | null;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
export { }
|