@mr-m/telegram-webapp-kit 2.0.0 β†’ 2.0.1

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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +706 -137
  3. package/package.json +1 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mr-m-apps
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,25 +1,68 @@
1
- # telegram-webapp-kit
1
+ # πŸ“± Telegram WebApp Kit
2
2
 
3
- Full-featured Telegram Mini App SDK for React / Next.js.
4
- Types Β· Hooks Β· Providers Β· Utilities β€” zero dependencies beyond React.
3
+ **Full-featured SDK for building Telegram Mini Apps with React & Next.js**
4
+
5
+ A zero-dependency React library that provides complete access to the Telegram WebApp API with type-safe hooks, providers, and utilities.
6
+
7
+ [![NPM Version](https://img.shields.io/npm/v/@mr-m/telegram-webapp-kit)](https://www.npmjs.com/package/@mr-m/telegram-webapp-kit)
8
+ [![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
+ [![React](https://img.shields.io/badge/react-18%2B-blue.svg)](#peerDependencies)
10
+
11
+ ---
12
+
13
+ ## ⚑ Features
14
+
15
+ βœ… **Complete TypeScript Support** β€” Fully typed hooks, providers, and utilities
16
+ βœ… **Zero Dependencies** β€” Only requires React (no extra packages)
17
+ βœ… **React & Next.js Ready** β€” Works with both App Router and Pages Router
18
+ βœ… **Safe Areas Handling** β€” Built-in support for notches and safe areas
19
+ βœ… **Haptic Feedback** β€” Impact, notification, and selection feedback
20
+ βœ… **Device Integration** β€” Accelerometer, gyroscope, device orientation
21
+ βœ… **Biometric Authentication** β€” Face ID / fingerprint support
22
+ βœ… **Location & Geolocation** β€” Get user location with proper permissions
23
+ βœ… **Cloud Storage** β€” Promise-based cloud storage wrapper
24
+ βœ… **Button Management** β€” Main, secondary, back, and settings buttons
25
+ βœ… **Theme & Color Scheme** β€” Dark/light mode detection
26
+ βœ… **Event Subscriptions** β€” Subscribe to any Telegram WebApp event
27
+ βœ… **Development Bypass** β€” Test locally without Telegram
5
28
 
6
29
  ---
7
30
 
8
- ## Install
31
+ ## πŸ“¦ Installation
9
32
 
33
+ ### npm
10
34
  ```bash
11
35
  npm install @mr-m/telegram-webapp-kit
12
- # or
36
+ ```
37
+
38
+ ### pnpm
39
+ ```bash
13
40
  pnpm add @mr-m/telegram-webapp-kit
14
41
  ```
15
42
 
16
- Add the Telegram script to your `layout.tsx` or `_document.tsx`:
43
+ ### yarn
44
+ ```bash
45
+ yarn add @mr-m/telegram-webapp-kit
46
+ ```
47
+
48
+ ### bun
49
+ ```bash
50
+ bun add @mr-m/telegram-webapp-kit
51
+ ```
52
+
53
+ ---
54
+
55
+ ## πŸš€ Quick Start
56
+
57
+ ### 1. Add Telegram Script
58
+
59
+ Add the official Telegram WebApp script to your `layout.tsx` (Next.js App Router):
17
60
 
18
61
  ```tsx
19
- // Next.js App Router β€” layout.tsx
62
+ // app/layout.tsx
20
63
  import Script from 'next/script';
21
64
 
22
- export default function RootLayout({ children }) {
65
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
23
66
  return (
24
67
  <html>
25
68
  <head>
@@ -34,11 +77,9 @@ export default function RootLayout({ children }) {
34
77
  }
35
78
  ```
36
79
 
37
- ---
38
-
39
- ## Setup Providers
80
+ ### 2. Wrap App with Providers
40
81
 
41
- Wrap your app with the providers you need:
82
+ Create a providers component and wrap your app:
42
83
 
43
84
  ```tsx
44
85
  // app/providers.tsx
@@ -50,16 +91,14 @@ import {
50
91
  } from '@mr-m/telegram-webapp-kit';
51
92
 
52
93
  const telegramOptions: TelegramProviderOptions = {
53
- langStorageKey: 'my-app-lang', // localStorage key for saved language
54
94
  onUserReady: (user) => {
55
- // sync user to your backend
95
+ // Called when user data is loaded
96
+ console.log('User ready:', user);
97
+ // Sync user to your backend
56
98
  fetch('/api/user', { method: 'POST', body: JSON.stringify(user) });
57
99
  },
58
- onLanguageChange: (lang) => {
59
- // e.g. i18n.changeLanguage(lang)
60
- },
61
- loadingComponent: <div>Loading…</div>,
62
- notInTelegramComponent: <div>Open in Telegram</div>,
100
+ loadingComponent: <div className="p-4">Loading Mini App...</div>,
101
+ notInTelegramComponent: <div className="p-4">Please open in Telegram</div>,
63
102
  };
64
103
 
65
104
  export function Providers({ children }: { children: React.ReactNode }) {
@@ -73,218 +112,528 @@ export function Providers({ children }: { children: React.ReactNode }) {
73
112
  }
74
113
  ```
75
114
 
76
- ---
115
+ Use providers in layout:
77
116
 
78
- ## Hooks Reference
117
+ ```tsx
118
+ // app/layout.tsx
119
+ import { Providers } from './providers';
120
+ import './globals.css';
79
121
 
80
- ### `useTelegram()`
81
- Main context hook β€” gives you everything from the provider.
122
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
123
+ return (
124
+ <html>
125
+ <body>
126
+ <Providers>
127
+ <div className="app-container">
128
+ {children}
129
+ </div>
130
+ </Providers>
131
+ </body>
132
+ </html>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ### 3. Use Hooks
138
+
139
+ Access Telegram features in your components:
82
140
 
83
141
  ```tsx
84
- const {
85
- ready, // boolean β€” is the SDK initialized?
86
- inTelegram, // boolean β€” running inside Telegram?
87
- bypass, // boolean β€” dev bypass mode?
88
- webApp, // TgWebApp | null β€” raw WebApp instance
89
- user, // TgUser | null
90
- language, // 'en-US' (TMDB-style locale)
91
- uiLang, // 'en' (short code)
92
- colorScheme, // 'light' | 'dark'
93
- startParam, // string | null
94
- isRtl, // boolean
95
- changeLanguage,// (lang: string) => void
96
- } = useTelegram();
142
+ 'use client';
143
+ import { useTelegram, useTelegramMainButton } from '@mr-m/telegram-webapp-kit';
144
+
145
+ export default function Home() {
146
+ const { user, colorScheme, ready } = useTelegram();
147
+
148
+ useTelegramMainButton({
149
+ text: 'Continue',
150
+ onClick: () => console.log('Clicked!'),
151
+ isVisible: ready,
152
+ });
153
+
154
+ return (
155
+ <div>
156
+ <h1>Hello {user?.first_name}!</h1>
157
+ <p>Theme: {colorScheme}</p>
158
+ </div>
159
+ );
160
+ }
97
161
  ```
98
162
 
99
163
  ---
100
164
 
101
- ### `useTelegramBackButton()`
102
- Auto-manages the Back Button based on the current route.
165
+ ## 🎯 Core Concepts
166
+
167
+ ### Safe Areas & Fullscreen
168
+
169
+ The `FullscreenProvider` automatically injects CSS variables for notches and safe areas:
170
+
171
+ ```css
172
+ :root {
173
+ /* Safe area (includes notch, keyboard, etc.) */
174
+ --tg-safe-area-inset-top: 0px;
175
+ --tg-safe-area-inset-bottom: 0px;
176
+ --tg-safe-area-inset-left: 0px;
177
+ --tg-safe-area-inset-right: 0px;
178
+
179
+ /* Content safe area (keyboard, etc. but not notch) */
180
+ --tg-content-safe-area-inset-top: 0px;
181
+ --tg-content-safe-area-inset-bottom: 0px;
182
+ --tg-content-safe-area-inset-left: 0px;
183
+ --tg-content-safe-area-inset-right: 0px;
184
+ }
185
+ ```
186
+
187
+ ### App Container
188
+
189
+ Wrap your main content with `.app-container` to handle safe areas automatically:
190
+
191
+ ```css
192
+ .app-container {
193
+ position: relative;
194
+ min-height: 100vh;
195
+ padding-top: calc(var(--tg-safe-area-inset-top, 0px) + var(--tg-content-safe-area-inset-top, 0px));
196
+ padding-bottom: calc(var(--tg-safe-area-inset-bottom, 0px) + var(--tg-content-safe-area-inset-bottom, 0px));
197
+ padding-left: calc(var(--tg-safe-area-inset-left, 0px) + var(--tg-content-safe-area-inset-left, 0px));
198
+ padding-right: calc(var(--tg-safe-area-inset-right, 0px) + var(--tg-content-safe-area-inset-right, 0px));
199
+ }
200
+ ```
201
+
202
+ ### Fixed Elements
203
+
204
+ For headers, footers, or floating buttons:
205
+
206
+ ```css
207
+ /* Fixed header with safe area */
208
+ .fixed-header {
209
+ position: fixed;
210
+ top: 0;
211
+ left: 0;
212
+ right: 0;
213
+ padding-top: var(--tg-safe-area-inset-top, 0px);
214
+ z-index: 100;
215
+ }
216
+
217
+ /* Fixed bottom navigation */
218
+ .bottom-nav {
219
+ position: fixed;
220
+ bottom: 0;
221
+ left: 0;
222
+ right: 0;
223
+ padding-bottom: var(--tg-safe-area-inset-bottom, 0px);
224
+ z-index: 100;
225
+ }
226
+
227
+ /* Floating action button */
228
+ .fab {
229
+ position: fixed;
230
+ bottom: calc(20px + var(--tg-safe-area-inset-bottom, 0px));
231
+ right: calc(20px + var(--tg-safe-area-inset-right, 0px));
232
+ z-index: 50;
233
+ }
234
+
235
+ /* Fullscreen content */
236
+ .fullscreen-content {
237
+ position: fixed;
238
+ top: var(--tg-safe-area-inset-top, 0px);
239
+ left: var(--tg-safe-area-inset-left, 0px);
240
+ right: var(--tg-safe-area-inset-right, 0px);
241
+ bottom: var(--tg-safe-area-inset-bottom, 0px);
242
+ }
243
+ ```
244
+
245
+ ---
246
+
247
+ ## πŸͺ Hooks API
248
+
249
+ ### useTelegram()
250
+
251
+ Main hook for Telegram context and WebApp instance:
103
252
 
104
253
  ```tsx
105
- import { useTelegramBackButton } from '@mr-m/telegram-webapp-kit';
254
+ const {
255
+ ready, // boolean β€” SDK initialized?
256
+ inTelegram, // boolean β€” Running in Telegram?
257
+ bypass, // boolean β€” Dev bypass mode active?
258
+ webApp, // TgWebApp | null β€” Raw WebApp instance
259
+ user, // TgUser | null β€” Current user
260
+ colorScheme, // 'light' | 'dark' β€” User's theme preference
261
+ startParam, // string | null β€” Deep link parameter
262
+ } = useTelegram();
263
+ ```
106
264
 
107
- // Basic β€” uses browser history.back()
108
- useTelegramBackButton({ pathname });
265
+ **Example:**
266
+ ```tsx
267
+ const { user, ready, inTelegram } = useTelegram();
109
268
 
110
- // Custom back handler
111
- useTelegramBackButton({
112
- pathname,
113
- onBack: () => router.push('/'),
114
- hideOnRoot: true, // default: true
115
- });
269
+ if (!ready) return <div>Loading...</div>;
270
+ if (!inTelegram) return <div>Open this in Telegram</div>;
271
+
272
+ return <h1>Welcome {user?.first_name}</h1>;
116
273
  ```
117
274
 
118
275
  ---
119
276
 
120
- ### `useTelegramMainButton()`
121
- Declarative Main Button control.
277
+ ### useTelegramMainButton()
278
+
279
+ Control the main action button at the bottom:
122
280
 
123
281
  ```tsx
124
282
  useTelegramMainButton({
125
- text: 'Continue',
126
- onClick: handleSubmit,
127
- isVisible: formIsValid,
128
- isActive: !isLoading,
129
- showProgress: isLoading,
130
- color: '#2481cc',
131
- hasShineEffect: true,
283
+ text: 'Continue', // Button label
284
+ onClick: handleClick, // Click handler
285
+ isVisible: true, // Show/hide button
286
+ isActive: !isLoading, // Enable/disable
287
+ showProgress: isLoading, // Show loading indicator
288
+ color: '#2481cc', // Button color (optional)
289
+ hasShineEffect: true, // Shine animation (optional)
290
+ });
291
+ ```
292
+
293
+ **Example:**
294
+ ```tsx
295
+ const [isSubmitting, setIsSubmitting] = useState(false);
296
+
297
+ useTelegramMainButton({
298
+ text: 'Submit Form',
299
+ onClick: async () => {
300
+ setIsSubmitting(true);
301
+ await submitForm();
302
+ setIsSubmitting(false);
303
+ },
304
+ isActive: !isSubmitting,
305
+ showProgress: isSubmitting,
132
306
  });
133
307
  ```
134
308
 
135
309
  ---
136
310
 
137
- ### `useTelegramSecondaryButton()`
311
+ ### useTelegramSecondaryButton()
312
+
313
+ Secondary button (often on the left):
314
+
138
315
  ```tsx
139
316
  useTelegramSecondaryButton({
140
317
  text: 'Cancel',
141
318
  onClick: handleCancel,
142
- position: 'left',
319
+ position: 'left', // 'left' | 'right'
143
320
  isVisible: true,
144
321
  });
145
322
  ```
146
323
 
147
324
  ---
148
325
 
149
- ### `useTelegramSettingsButton()`
326
+ ### useTelegramBackButton()
327
+
328
+ Auto-manages back button based on route:
329
+
150
330
  ```tsx
151
- useTelegramSettingsButton(() => router.push('/settings'));
331
+ import { useRouter } from 'next/navigation';
332
+ import { useTelegramBackButton } from '@mr-m/telegram-webapp-kit';
333
+
334
+ export default function Page() {
335
+ const router = useRouter();
336
+
337
+ useTelegramBackButton({
338
+ pathname: '/current-page',
339
+ onBack: () => router.back(),
340
+ hideOnRoot: true, // Hide on home page
341
+ });
342
+
343
+ return <div>Your content</div>;
344
+ }
152
345
  ```
153
346
 
154
347
  ---
155
348
 
156
- ### `useHapticFeedback()`
349
+ ### useTelegramSettingsButton()
350
+
351
+ Handle settings button click:
352
+
353
+ ```tsx
354
+ import { useRouter } from 'next/navigation';
355
+ import { useTelegramSettingsButton } from '@mr-m/telegram-webapp-kit';
356
+
357
+ export default function Page() {
358
+ const router = useRouter();
359
+
360
+ useTelegramSettingsButton(() => {
361
+ router.push('/settings');
362
+ });
363
+
364
+ return <div>Your content</div>;
365
+ }
366
+ ```
367
+
368
+ ---
369
+
370
+ ### useHapticFeedback()
371
+
372
+ Trigger haptic feedback (vibration):
373
+
157
374
  ```tsx
158
375
  const haptic = useHapticFeedback();
159
376
 
160
- haptic.impact('medium'); // 'light' | 'medium' | 'heavy' | 'rigid' | 'soft'
161
- haptic.notification('success');// 'error' | 'success' | 'warning'
162
- haptic.selectionChanged();
377
+ // Impact vibrations
378
+ haptic.impact('light'); // Light tap
379
+ haptic.impact('medium'); // Medium tap
380
+ haptic.impact('heavy'); // Strong tap
381
+ haptic.impact('rigid'); // Rigid tap
382
+ haptic.impact('soft'); // Soft tap
383
+
384
+ // Notifications
385
+ haptic.notification('success'); // Success pattern
386
+ haptic.notification('warning'); // Warning pattern
387
+ haptic.notification('error'); // Error pattern
388
+
389
+ // Selection
390
+ haptic.selectionChanged(); // Selection feedback
163
391
  ```
164
392
 
165
- Or use the static shortcut:
393
+ **Or use static methods:**
166
394
  ```tsx
167
395
  import { haptic } from '@mr-m/telegram-webapp-kit';
396
+
168
397
  haptic.success();
398
+ haptic.error();
399
+ haptic.warning();
169
400
  ```
170
401
 
171
402
  ---
172
403
 
173
- ### `useTelegramTheme()`
404
+ ### useTelegramTheme()
405
+
406
+ Get theme and color information:
407
+
174
408
  ```tsx
175
409
  const { colorScheme, themeParams, isDark } = useTelegramTheme();
410
+
411
+ console.log(isDark ? 'Dark mode' : 'Light mode');
412
+ console.log('Primary color:', themeParams?.button_color);
176
413
  ```
177
414
 
178
415
  ---
179
416
 
180
- ### `useTelegramViewport()`
417
+ ### useTelegramViewport()
418
+
419
+ Manage WebApp viewport:
420
+
181
421
  ```tsx
182
422
  const { height, stableHeight, isExpanded, expand } = useTelegramViewport();
423
+
424
+ // Expand webview to fill available height
425
+ expand();
183
426
  ```
184
427
 
185
428
  ---
186
429
 
187
- ### `useTelegramFullscreen()`
430
+ ### useTelegramFullscreen()
431
+
432
+ Control fullscreen mode:
433
+
188
434
  ```tsx
189
435
  const { isFullscreen, isSupported, enter, exit, toggle, error } = useTelegramFullscreen();
436
+
437
+ if (isSupported) {
438
+ toggle(); // Toggle fullscreen
439
+ }
190
440
  ```
191
441
 
192
- Or use `useFullscreen()` from the `FullscreenProvider` for the full context including safe areas.
442
+ ---
443
+
444
+ ### useFullscreen()
445
+
446
+ Extended fullscreen from `FullscreenProvider` (includes safe areas):
447
+
448
+ ```tsx
449
+ const { isFullscreen, error, safeArea } = useFullscreen();
450
+ ```
193
451
 
194
452
  ---
195
453
 
196
- ### `useSafeArea()`
454
+ ### useSafeArea()
455
+
456
+ Get safe area values and CSS variables:
457
+
197
458
  ```tsx
198
459
  const { safeArea, contentSafeArea } = useSafeArea();
199
- // safeArea.top, .bottom, .left, .right β€” in pixels
200
460
 
201
- // CSS variables are also set automatically:
202
- // --tg-safe-area-inset-top, --tg-content-safe-area-inset-bottom, etc.
461
+ console.log(safeArea.top); // Top inset (includes notch)
462
+ console.log(contentSafeArea.bottom); // Bottom inset (keyboard safe)
203
463
  ```
204
464
 
205
465
  ---
206
466
 
207
- ### `useCloudStorage()`
208
- Promise-based wrappers over Telegram CloudStorage.
467
+ ### useCloudStorage()
468
+
469
+ Promise-based cloud storage (persists across devices):
209
470
 
210
471
  ```tsx
211
472
  const storage = useCloudStorage();
212
473
 
213
- await storage.setItem('key', 'value');
214
- const val = await storage.getItem('key');
215
- const all = await storage.getItems(['a', 'b']);
216
- await storage.removeItem('key');
217
- const keys = await storage.getKeys();
474
+ // Set value
475
+ await storage.setItem('user-settings', JSON.stringify({ theme: 'dark' }));
476
+
477
+ // Get value
478
+ const settings = await storage.getItem('user-settings');
479
+
480
+ // Get multiple values
481
+ const [val1, val2] = await storage.getItems(['key1', 'key2']);
482
+
483
+ // Remove value
484
+ await storage.removeItem('key1');
485
+
486
+ // Get all keys
487
+ const allKeys = await storage.getKeys();
218
488
  ```
219
489
 
220
490
  ---
221
491
 
222
- ### `useAccelerometer()` / `useGyroscope()` / `useDeviceOrientation()`
492
+ ### useAccelerometer()
493
+
494
+ Device accelerometer (motion sensor):
495
+
223
496
  ```tsx
224
497
  const { x, y, z, isStarted, start, stop } = useAccelerometer({
225
- refreshRate: 50,
498
+ refreshRate: 50, // Hz
499
+ autoStart: true, // Start automatically
500
+ });
501
+
502
+ // Manual control
503
+ start();
504
+ stop();
505
+ ```
506
+
507
+ ---
508
+
509
+ ### useGyroscope()
510
+
511
+ Device gyroscope (rotation sensor):
512
+
513
+ ```tsx
514
+ const { x, y, z, isStarted, start, stop } = useGyroscope({
226
515
  autoStart: true,
227
516
  });
517
+ ```
228
518
 
229
- const { x, y, z } = useGyroscope({ autoStart: true });
519
+ ---
230
520
 
231
- const { alpha, beta, gamma, absolute } = useDeviceOrientation({
521
+ ### useDeviceOrientation()
522
+
523
+ Device orientation (compass):
524
+
525
+ ```tsx
526
+ const { alpha, beta, gamma, absolute, isStarted, start, stop } = useDeviceOrientation({
232
527
  needAbsolute: true,
233
528
  autoStart: true,
234
529
  });
530
+
531
+ // alpha: 0-360Β° (compass bearing)
532
+ // beta: -180 to 180Β° (tilt front/back)
533
+ // gamma: -90 to 90Β° (tilt left/right)
235
534
  ```
236
535
 
237
536
  ---
238
537
 
239
- ### `useBiometric()`
538
+ ### useBiometric()
539
+
540
+ Biometric authentication (Face ID / Fingerprint):
541
+
240
542
  ```tsx
241
543
  const { isAvailable, biometricType, init, requestAccess, authenticate } = useBiometric();
242
544
 
545
+ // Initialize
243
546
  await init();
244
- const granted = await requestAccess('Authenticate to continue');
245
- const { authenticated, token } = await authenticate('Confirm your identity');
547
+
548
+ // Request permission
549
+ const granted = await requestAccess('Authenticate to unlock premium features');
550
+
551
+ // Authenticate
552
+ if (granted) {
553
+ const { authenticated, token } = await authenticate('Confirm your identity');
554
+ if (authenticated) {
555
+ console.log('Auth token:', token);
556
+ }
557
+ }
246
558
  ```
247
559
 
248
560
  ---
249
561
 
250
- ### `useLocation()`
562
+ ### useLocation()
563
+
564
+ Get user location:
565
+
251
566
  ```tsx
252
567
  const { isAvailable, isGranted, init, getLocation, openSettings } = useLocation();
253
568
 
569
+ // Initialize permission
254
570
  await init();
255
- const loc = await getLocation();
256
- // loc.latitude, loc.longitude, loc.altitude, etc.
571
+
572
+ // Request permission
573
+ if (isGranted) {
574
+ const location = await getLocation();
575
+ console.log('Latitude:', location.latitude);
576
+ console.log('Longitude:', location.longitude);
577
+ }
578
+
579
+ // Open settings to grant permission
580
+ openSettings();
257
581
  ```
258
582
 
259
583
  ---
260
584
 
261
- ### `useHomeScreen()`
585
+ ### useHomeScreen()
586
+
587
+ Add app to home screen:
588
+
262
589
  ```tsx
263
590
  const { addToHomeScreen, checkStatus } = useHomeScreen();
264
- const status = await checkStatus(); // 'added' | 'missed' | 'unknown' | 'unsupported'
591
+
592
+ const status = await checkStatus();
593
+ if (status === 'ok') {
594
+ await addToHomeScreen(); // Shows system dialog
595
+ }
265
596
  ```
266
597
 
267
598
  ---
268
599
 
269
- ### `useIsActive()`
270
- Tracks whether the Mini App is currently active (foreground).
600
+ ### useIsActive()
601
+
602
+ Track if Mini App is in foreground:
603
+
271
604
  ```tsx
272
605
  const isActive = useIsActive();
606
+
607
+ useEffect(() => {
608
+ if (isActive) {
609
+ console.log('App is visible');
610
+ } else {
611
+ console.log('App is backgrounded');
612
+ }
613
+ }, [isActive]);
273
614
  ```
274
615
 
275
616
  ---
276
617
 
277
- ### `useTelegramEvent()`
278
- Subscribe to any raw Telegram event.
618
+ ### useTelegramEvent()
619
+
620
+ Subscribe to raw Telegram events:
621
+
279
622
  ```tsx
280
623
  useTelegramEvent('themeChanged', () => {
281
- console.log('Theme changed!');
624
+ console.log('User switched theme!');
625
+ });
626
+
627
+ useTelegramEvent('viewportChanged', () => {
628
+ console.log('Viewport height changed');
282
629
  });
283
630
  ```
284
631
 
285
632
  ---
286
633
 
287
- ## Utility Functions
634
+ ## πŸ›  Utility Functions
635
+
636
+ Standalone utilities (no hooks required):
288
637
 
289
638
  ```tsx
290
639
  import {
@@ -298,79 +647,299 @@ import {
298
647
  getRawUserData,
299
648
  openExternalLink,
300
649
  openTelegramLink,
301
- tgLangToTmdb,
302
- tgLangToUi,
303
- isRtlLang,
304
- SUPPORTED_LANGS,
305
650
  haptic,
306
- cloudStorage, // Promise-based static helpers
307
- dialog, // Promise-based alert/confirm/popup
651
+ cloudStorage,
652
+ dialog,
308
653
  readClipboard,
309
654
  openInvoice,
310
655
  scanQr,
311
- biometric, // Static promise helpers
312
- location, // Static promise helpers
656
+ biometric,
657
+ location,
313
658
  } from '@mr-m/telegram-webapp-kit';
314
659
 
315
- // Examples
316
- const wa = getWebApp();
317
- const user = getRawUserData();
318
- const { displayName, avatarUrl } = getUserInfoWithAvatar();
660
+ // Get raw WebApp instance
661
+ const webApp = getWebApp();
662
+
663
+ // Check if running in Telegram
664
+ if (isInTelegram()) {
665
+ console.log('In Telegram!');
666
+ }
667
+
668
+ // Check WebApp version
669
+ if (isVersionAtLeast('6.0')) {
670
+ console.log('Version 6.0+');
671
+ }
319
672
 
320
- await dialog.alert('Hello!');
673
+ // Get user info
674
+ const displayName = getUserDisplayName();
675
+ const avatarUrl = getUserAvatarUrl();
676
+ const info = getUserInfoWithAvatar();
677
+
678
+ // Open links
679
+ openExternalLink('https://example.com');
680
+ openTelegramLink('https://t.me/username');
681
+
682
+ // Dialog
683
+ await dialog.alert('Alert message');
321
684
  const confirmed = await dialog.confirm('Are you sure?');
322
- const buttonId = await dialog.popup({ message: 'Choose', buttons: [{ id: 'a', text: 'Option A' }] });
685
+ const buttonId = await dialog.popup({
686
+ message: 'Choose an option',
687
+ buttons: [
688
+ { id: 'option-a', text: 'Option A' },
689
+ { id: 'option-b', text: 'Option B' },
690
+ ],
691
+ });
692
+
693
+ // Clipboard
694
+ const clipboardText = await readClipboard();
323
695
 
324
- const status = await openInvoice('https://...');
325
- const qrText = await scanQr('Scan the code');
326
- const clipboard = await readClipboard();
696
+ // Invoice / Payment
697
+ const status = await openInvoice('https://t.me/invoice_link');
698
+
699
+ // QR Code Scanner
700
+ const qrResult = await scanQr('Scan QR code');
701
+
702
+ // Biometric
703
+ await biometric.init();
704
+
705
+ // Location
706
+ const location = await location.getLocation();
327
707
  ```
328
708
 
329
709
  ---
330
710
 
331
- ## Start Param Routing
711
+ ## 🌐 Deep Links & Start Parameters
332
712
 
333
- If you want to handle deep links via `start_param`, use `useTelegramStartParam`:
713
+ Handle deep links via `startParam`:
334
714
 
335
715
  ```tsx
336
- import { useTelegramStartParam } from '@mr-m/telegram-webapp-kit';
716
+ 'use client';
717
+ import { useTelegram } from '@mr-m/telegram-webapp-kit';
718
+ import { useRouter } from 'next/navigation';
719
+ import { useEffect } from 'react';
720
+
721
+ export default function Page() {
722
+ const { startParam, ready } = useTelegram();
723
+ const router = useRouter();
337
724
 
338
- function App() {
339
- const startParam = useTelegramStartParam();
340
-
341
725
  useEffect(() => {
342
- if (startParam === 'premium') router.push('/upgrade');
343
- }, [startParam]);
726
+ if (!ready) return;
727
+
728
+ switch (startParam) {
729
+ case 'premium':
730
+ router.push('/upgrade');
731
+ break;
732
+ case 'invite':
733
+ router.push('/invite');
734
+ break;
735
+ default:
736
+ router.push('/home');
737
+ }
738
+ }, [startParam, ready, router]);
739
+
740
+ return <div>Redirecting...</div>;
344
741
  }
345
742
  ```
346
743
 
347
744
  ---
348
745
 
349
- ## TypeScript
746
+ ## 🎨 Type Definitions
350
747
 
351
- All interfaces are exported. The most useful ones:
748
+ All types are exported for TypeScript projects:
352
749
 
353
750
  ```tsx
354
751
  import type {
355
- TgUser,
356
- TgWebApp,
357
- TgThemeParams,
358
- SafeAreaInset,
359
- LocationData,
360
- WebAppEventType,
361
- PopupParams,
362
- TelegramContextValue,
363
- TelegramProviderOptions,
752
+ TgUser, // User object
753
+ TgWebApp, // WebApp instance
754
+ TgThemeParams, // Theme colors
755
+ SafeAreaInset, // Safe area values
756
+ LocationData, // Location coordinates
757
+ WebAppEventType, // Event types
758
+ PopupParams, // Dialog parameters
759
+ TelegramContextValue, // Context type
760
+ TelegramProviderOptions, // Provider options
364
761
  } from '@mr-m/telegram-webapp-kit';
365
762
  ```
366
763
 
367
764
  ---
368
765
 
369
- ## Dev Bypass
766
+ ## πŸ”§ Development & Testing
767
+
768
+ ### Dev Bypass Mode
370
769
 
371
- Outside Telegram, the provider shows `notInTelegramComponent`.
372
- In `development` or when `?bypass` is in the URL, it renders normally so you can develop locally.
770
+ Test your Mini App outside Telegram:
373
771
 
374
772
  ```bash
773
+ # Add ?bypass to URL
375
774
  http://localhost:3000?bypass
376
775
  ```
776
+
777
+ This will:
778
+ - Skip Telegram availability check
779
+ - Render normally without Telegram script
780
+ - Allow local testing and debugging
781
+
782
+ ### Fallback UI
783
+
784
+ Customize what users see when not in Telegram:
785
+
786
+ ```tsx
787
+ const telegramOptions: TelegramProviderOptions = {
788
+ notInTelegramComponent: (
789
+ <div className="flex flex-col items-center justify-center min-h-screen">
790
+ <p className="text-lg">πŸ“± Open this app in Telegram</p>
791
+ <a href="https://t.me/YourBot?startapp=..." className="mt-4">
792
+ Launch Mini App
793
+ </a>
794
+ </div>
795
+ ),
796
+ };
797
+ ```
798
+
799
+ ---
800
+
801
+ ## πŸ“š Complete Example
802
+
803
+ Here's a complete Mini App example:
804
+
805
+ ```tsx
806
+ // app/layout.tsx
807
+ import Script from 'next/script';
808
+ import { Providers } from './providers';
809
+ import './globals.css';
810
+
811
+ export const metadata = {
812
+ title: 'My Mini App',
813
+ description: 'Built with telegram-webapp-kit',
814
+ };
815
+
816
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
817
+ return (
818
+ <html>
819
+ <head>
820
+ <Script
821
+ src="https://telegram.org/js/telegram-web-app.js"
822
+ strategy="beforeInteractive"
823
+ />
824
+ </head>
825
+ <body>
826
+ <Providers>
827
+ <div className="app-container">
828
+ {children}
829
+ </div>
830
+ </Providers>
831
+ </body>
832
+ </html>
833
+ );
834
+ }
835
+ ```
836
+
837
+ ```tsx
838
+ // app/providers.tsx
839
+ 'use client';
840
+ import {
841
+ TelegramProvider,
842
+ FullscreenProvider,
843
+ type TelegramProviderOptions,
844
+ } from '@mr-m/telegram-webapp-kit';
845
+
846
+ const telegramOptions: TelegramProviderOptions = {
847
+ onUserReady: (user) => {
848
+ fetch('/api/user', {
849
+ method: 'POST',
850
+ body: JSON.stringify(user),
851
+ });
852
+ },
853
+ loadingComponent: <div className="p-4 text-center">Loading...</div>,
854
+ notInTelegramComponent: (
855
+ <div className="p-4 text-center">
856
+ Open this app in Telegram
857
+ </div>
858
+ ),
859
+ };
860
+
861
+ export function Providers({ children }: { children: React.ReactNode }) {
862
+ return (
863
+ <FullscreenProvider options={{ persistPreference: true }}>
864
+ <TelegramProvider options={telegramOptions}>
865
+ {children}
866
+ </TelegramProvider>
867
+ </FullscreenProvider>
868
+ );
869
+ }
870
+ ```
871
+
872
+ ```tsx
873
+ // app/page.tsx
874
+ 'use client';
875
+ import { useTelegram, useTelegramMainButton, useHapticFeedback } from '@mr-m/telegram-webapp-kit';
876
+ import { useState } from 'react';
877
+
878
+ export default function Home() {
879
+ const { user, colorScheme, ready } = useTelegram();
880
+ const haptic = useHapticFeedback();
881
+ const [count, setCount] = useState(0);
882
+
883
+ useTelegramMainButton({
884
+ text: 'Increment',
885
+ onClick: () => {
886
+ setCount(c => c + 1);
887
+ haptic.impact('light');
888
+ },
889
+ isVisible: ready,
890
+ });
891
+
892
+ if (!ready) {
893
+ return <div className="p-4">Loading...</div>;
894
+ }
895
+
896
+ return (
897
+ <div className="p-4 max-w-md mx-auto">
898
+ <h1 className="text-2xl font-bold">Welcome {user?.first_name}</h1>
899
+ <p className="mt-2 text-gray-600">Theme: {colorScheme}</p>
900
+ <div className="mt-6 text-4xl font-bold text-center">{count}</div>
901
+ </div>
902
+ );
903
+ }
904
+ ```
905
+
906
+ ---
907
+
908
+ ## πŸ› Troubleshooting
909
+
910
+ **Q: Hooks return null or undefined**
911
+ A: Make sure you've wrapped your component with both `TelegramProvider` and `FullscreenProvider`.
912
+
913
+ **Q: Buttons don't appear**
914
+ A: Wait for `ready === true` before rendering button controls.
915
+
916
+ **Q: Safe areas not working**
917
+ A: Ensure `.app-container` has the correct CSS and safe area CSS variables are set.
918
+
919
+ **Q: Getting "not in Telegram" message**
920
+ A: Add `?bypass` to your URL for local testing, or open the app through Telegram.
921
+
922
+ ---
923
+
924
+ ## πŸ“– Resources
925
+
926
+ - [Telegram WebApp Documentation](https://core.telegram.org/bots/webapps)
927
+ - [Telegram Bot API](https://core.telegram.org/bots/api)
928
+ - [Next.js Documentation](https://nextjs.org/docs)
929
+ - [React Documentation](https://react.dev)
930
+
931
+ ---
932
+
933
+ ## πŸ“„ License
934
+
935
+ MIT Β© [mr-m-apps](https://github.com/mr-m-apps)
936
+
937
+ ---
938
+
939
+ ## 🀝 Contributing
940
+
941
+ Found a bug or have a feature request? Open an issue on [GitHub](https://github.com/mr-m-apps/telegram-webapp-kit/issues).
942
+
943
+ ---
944
+
945
+ **Built with ❀️ for Telegram Mini Apps**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mr-m/telegram-webapp-kit",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Full-featured Telegram Web App SDK for React / Next.js β€” types, hooks, providers, and utilities",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",