diff --git a/README.md b/README.md
index f3cbef4..e821143 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
## `vue-tg` - Telegram integration for Vue
[](https://vue-tg.deptyped.com/)
-[](https://core.telegram.org/bots/webapps#july-31-2024)
+[](https://core.telegram.org/bots/webapps#november-17-2024)
[](https://www.npmjs.com/package/vue-tg)
[](https://bundlephobia.com/result?p=vue-tg@latest)
@@ -15,9 +15,9 @@ A lightweight package for seamless integration of [Telegram Mini Apps](https://c
```
@@ -78,46 +78,66 @@ To connect your Mini App to the Telegram client, place the script `telegram-web-
| Field | Composable |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
-| initData | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| initDataUnsafe | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| version | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| platform | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| colorScheme | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| themeParams | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| isExpanded | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| viewportHeight | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| viewportStableHeight | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| headerColor | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| backgroundColor | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| isClosingConfirmationEnabled | [useWebAppClosingConfirmation](https://vue-tg.deptyped.com/mini-apps.html#usewebappclosingconfirmation) |
-| isVerticalSwipesEnabled | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| BackButton | [useWebAppBackButton](https://vue-tg.deptyped.com/mini-apps.html#usewebappbackbutton) |
-| MainButton | [useWebAppMainButton](https://vue-tg.deptyped.com/mini-apps.html#usewebappmainbutton) |
-| HapticFeedback | [useWebAppHapticFeedback](https://vue-tg.deptyped.com/mini-apps.html#usewebapphapticfeedback) |
-| BiometricManager | [useWebAppBiometricManager](https://vue-tg.deptyped.com/mini-apps.html#usewebappbiometricmanager) |
-| isVersionAtLeast | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| setHeaderColor | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| setBackgroundColor | [useWebAppTheme](https://vue-tg.deptyped.com/mini-apps.html#usewebapptheme) |
-| enableClosingConfirmation | [useWebAppClosingConfirmation](https://vue-tg.deptyped.com/mini-apps.html#usewebappclosingconfirmation) |
-| disableClosingConfirmation | [useWebAppClosingConfirmation](https://vue-tg.deptyped.com/mini-apps.html#usewebappclosingconfirmation) |
-| enableVerticalSwipes | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| disableVerticalSwipes | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| onEvent | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| offEvent | [Handled automagically 🪄](https://vue-tg.deptyped.com/mini-apps.html#managing-event-subscriptions) |
-| sendData | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| switchInlineQuery | [useWebAppNavigation](https://vue-tg.deptyped.com/mini-apps.html#usewebappnavigation) |
-| openLink | [useWebAppNavigation](https://vue-tg.deptyped.com/mini-apps.html#usewebappnavigation) |
-| openTelegramLink | [useWebAppNavigation](https://vue-tg.deptyped.com/mini-apps.html#usewebappnavigation) |
-| openInvoice | [useWebAppNavigation](https://vue-tg.deptyped.com/mini-apps.html#usewebappnavigation) |
-| shareToStory | [useWebAppShare](https://vue-tg.deptyped.com/mini-apps.html#usewebappshare) |
-| showPopup | [useWebAppPopup](https://vue-tg.deptyped.com/mini-apps.html#usewebapppopup) |
-| showAlert | [useWebAppPopup](https://vue-tg.deptyped.com/mini-apps.html#usewebapppopup) |
-| showConfirm | [useWebAppPopup](https://vue-tg.deptyped.com/mini-apps.html#usewebapppopup) |
-| showScanQrPopup | [useWebAppQrScanner](https://vue-tg.deptyped.com/mini-apps.html#usewebappqrscanner) |
-| closeScanQrPopup | [useWebAppQrScanner](https://vue-tg.deptyped.com/mini-apps.html#usewebappqrscanner) |
-| readTextFromClipboard | [useWebAppClipboard](https://vue-tg.deptyped.com/mini-apps.html#usewebappclipboard) |
-| requestWriteAccess | [useWebAppRequests](https://vue-tg.deptyped.com/mini-apps.html#usewebapprequests) |
-| requestContact | [useWebAppRequests](https://vue-tg.deptyped.com/mini-apps.html#usewebapprequests) |
-| ready | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
-| expand | [useWebAppViewport](https://vue-tg.deptyped.com/mini-apps.html#usewebappviewport) |
-| close | [useWebApp](https://vue-tg.deptyped.com/mini-apps.html#usewebapp) |
+| initData | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| initDataUnsafe | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| version | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| platform | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| colorScheme | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| themeParams | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| isActive | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| isExpanded | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| viewportHeight | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| viewportStableHeight | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| headerColor | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| backgroundColor | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| isClosingConfirmationEnabled | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| isVerticalSwipesEnabled | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| isFullscreen | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| isOrientationLocked | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| safeAreaInset | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| contentSafeAreaInset | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| BackButton | [useBackButton](https://vue-tg.deptyped.com/mini-apps.html#usebackbutton) |
+| MainButton | [useMainButton](https://vue-tg.deptyped.com/mini-apps.html#usemainbutton) |
+| HapticFeedback | [useHapticFeedback](https://vue-tg.deptyped.com/mini-apps.html#usehapticfeedback) |
+| BiometricManager | [useBiometricManager](https://vue-tg.deptyped.com/mini-apps.html#usebiometricmanager) |
+| Accelerometer | [useAccelerometer](https://vue-tg.deptyped.com/mini-apps.html#useaccelerometer) |
+| DeviceOrientation | [useDeviceOrientation](https://vue-tg.deptyped.com/mini-apps.html#usedeviceorientation) |
+| Gyroscope | [useGyroscope](https://vue-tg.deptyped.com/mini-apps.html#usegyroscope) |
+| LocationManager | [useLocationManager](https://vue-tg.deptyped.com/mini-apps.html#uselocationmanager) |
+| isVersionAtLeast | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| setHeaderColor | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| setBackgroundColor | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| setBottomBarColor | [useTheme](https://vue-tg.deptyped.com/mini-apps.html#usetheme) |
+| enableClosingConfirmation | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| disableClosingConfirmation | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| enableVerticalSwipes | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| disableVerticalSwipes | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| requestFullscreen | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| exitFullscreen | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| lockOrientation | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| unlockOrientation | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| addToHomeScreen | [useHomeScreen](https://vue-tg.deptyped.com/mini-apps.html#usehomescreen) |
+| checkHomeScreenStatus | [useHomeScreen](https://vue-tg.deptyped.com/mini-apps.html#usehomescreen) |
+| onEvent | [Event Handling](https://vue-tg.deptyped.com/mini-apps.html#event-handling) |
+| offEvent | [Managing Event Subscriptions](https://vue-tg.deptyped.com/mini-apps.html#managing-event-subscriptions) |
+| sendData | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| switchInlineQuery | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| openLink | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| openTelegramLink | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| openInvoice | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| shareToStory | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| shareMessage | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| setEmojiStatus | [useEmojiStatus](https://vue-tg.deptyped.com/mini-apps.html#useemojistatus) |
+| requestEmojiStatusAccess | [useEmojiStatus](https://vue-tg.deptyped.com/mini-apps.html#useemojistatus) |
+| downloadFile | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| showPopup | [usePopup](https://vue-tg.deptyped.com/mini-apps.html#usepopup) |
+| showAlert | [usePopup](https://vue-tg.deptyped.com/mini-apps.html#usepopup) |
+| showConfirm | [usePopup](https://vue-tg.deptyped.com/mini-apps.html#usepopup) |
+| showScanQrPopup | [useQrScanner](https://vue-tg.deptyped.com/mini-apps.html#useqrscanner) |
+| closeScanQrPopup | [useQrScanner](https://vue-tg.deptyped.com/mini-apps.html#useqrscanner) |
+| readTextFromClipboard | [useClipboard](https://vue-tg.deptyped.com/mini-apps.html#useclipboard) |
+| requestWriteAccess | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| requestContact | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| ready | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
+| expand | [useViewport](https://vue-tg.deptyped.com/mini-apps.html#useviewport) |
+| close | [useMiniApp](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) |
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 4af68fa..9ea9258 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -1,10 +1,10 @@
-import { defineConfig } from 'vitepress'
import { transformerTwoslash } from '@shikijs/vitepress-twoslash'
+import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
- title: "vue-tg",
- description: "Vue-Telegram Documentation",
+ title: 'vue-tg',
+ description: 'Vue-Telegram Documentation',
markdown: {
codeTransformers: [
transformerTwoslash({
@@ -13,13 +13,22 @@ export default defineConfig({
noErrorTruncation: true,
paths: {
'vue-tg': [
- './dist'
- ]
- }
- }
- }
- })
- ]
+ './dist',
+ ],
+ 'vue-tg/7.8': [
+ './dist/versions/7.8',
+ ],
+ 'vue-tg/8.0': [
+ './dist/versions/8.0',
+ ],
+ 'vue-tg/latest': [
+ './dist/versions/latest',
+ ],
+ },
+ },
+ },
+ }),
+ ],
},
themeConfig: {
search: {
@@ -27,33 +36,36 @@ export default defineConfig({
options: {
detailedView: true,
_render(src, env, md) {
- if (env.relativePath.startsWith('mini-apps/components')) return ''
- if (env.relativePath.startsWith('mini-apps/composables')) return ''
- if (env.relativePath.startsWith('widgets/')) return ''
+ if (env.relativePath.startsWith('mini-apps/components'))
+ return ''
+ if (env.relativePath.startsWith('mini-apps/composables'))
+ return ''
+ if (env.relativePath.startsWith('widgets/'))
+ return ''
return md.render(src, env)
- }
- }
+ },
+ },
},
// https://vitepress.dev/reference/default-theme-config
nav: [
{
text: 'Installation',
- link: "/installation",
+ link: '/installation',
},
{
text: 'Mini Apps',
- link: "/mini-apps",
+ link: '/mini-apps',
},
{
text: 'Widgets',
- link: "/widgets",
- }
+ link: '/widgets',
+ },
],
socialLinks: [
- { icon: 'github', link: 'https://github.com/deptyped/vue-telegram' }
- ]
- }
+ { icon: 'github', link: 'https://github.com/deptyped/vue-telegram' },
+ ],
+ },
})
diff --git a/docs/installation.md b/docs/installation.md
index 88ee5f8..8f5ba41 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -64,6 +64,7 @@ import { Alert } from 'vue-tg'
| [MainButton](/mini-apps#mainbutton) | `tg-main-button` |
| [Popup](/mini-apps#Popup) | `tg-popup` |
| [ScanQr](/mini-apps#scanqr) | `tg-scan-qr` |
+| [SecondaryButton](/mini-apps#secondarybutton) | `tg-secondary-button` |
| [SettingsButton](/mini-apps#settingsbutton) | `tg-settings-button` |
| [ShareWidget](/widgets#share-widget) | `tg-share-widget` |
| [PostWidget](/widgets#post-widget) | `tg-post-widget` |
diff --git a/docs/mini-apps.md b/docs/mini-apps.md
index c9d7ef4..1472f8c 100644
--- a/docs/mini-apps.md
+++ b/docs/mini-apps.md
@@ -11,94 +11,226 @@ outline: [2, 3]
| Field | Composable |
| ---------------------------- | ------------------------------------------------------------- |
-| initData | [useWebApp](#usewebapp) |
-| initDataUnsafe | [useWebApp](#usewebapp) |
-| version | [useWebApp](#usewebapp) |
-| platform | [useWebApp](#usewebapp) |
-| colorScheme | [useWebAppTheme](#usewebapptheme) |
-| themeParams | [useWebAppTheme](#usewebapptheme) |
-| isExpanded | [useWebAppViewport](#usewebappviewport) |
-| viewportHeight | [useWebAppViewport](#usewebappviewport) |
-| viewportStableHeight | [useWebAppViewport](#usewebappviewport) |
-| headerColor | [useWebAppTheme](#usewebapptheme) |
-| backgroundColor | [useWebAppTheme](#usewebapptheme) |
-| isClosingConfirmationEnabled | [useWebAppClosingConfirmation](#usewebappclosingconfirmation) |
-| isVerticalSwipesEnabled | [useWebAppViewport](#usewebappviewport) |
-| BackButton | [useWebAppBackButton](#usewebappbackbutton) |
-| MainButton | [useWebAppMainButton](#usewebappmainbutton) |
-| HapticFeedback | [useWebAppHapticFeedback](#usewebapphapticfeedback) |
-| BiometricManager | [useWebAppBiometricManager](#usewebappbiometricmanager) |
-| isVersionAtLeast | [useWebApp](#usewebapp) |
-| setHeaderColor | [useWebAppTheme](#usewebapptheme) |
-| setBackgroundColor | [useWebAppTheme](#usewebapptheme) |
-| enableClosingConfirmation | [useWebAppClosingConfirmation](#usewebappclosingconfirmation) |
-| disableClosingConfirmation | [useWebAppClosingConfirmation](#usewebappclosingconfirmation) |
-| enableVerticalSwipes | [useWebAppViewport](#usewebappviewport) |
-| disableVerticalSwipes | [useWebAppViewport](#usewebappviewport) |
-| onEvent | [useWebApp](#usewebapp) |
-| offEvent | [Handled automagically 🪄](#managing-event-subscriptions) |
-| sendData | [useWebApp](#usewebapp) |
-| switchInlineQuery | [useWebAppNavigation](#usewebappnavigation) |
-| openLink | [useWebAppNavigation](#usewebappnavigation) |
-| openTelegramLink | [useWebAppNavigation](#usewebappnavigation) |
-| openInvoice | [useWebAppNavigation](#usewebappnavigation) |
-| shareToStory | [useWebAppShare](#usewebappshare) |
-| showPopup | [useWebAppPopup](#usewebapppopup) |
-| showAlert | [useWebAppPopup](#usewebapppopup) |
-| showConfirm | [useWebAppPopup](#usewebapppopup) |
-| showScanQrPopup | [useWebAppQrScanner](#usewebappqrscanner) |
-| closeScanQrPopup | [useWebAppQrScanner](#usewebappqrscanner) |
-| readTextFromClipboard | [useWebAppClipboard](#usewebappclipboard) |
-| requestWriteAccess | [useWebAppRequests](#usewebapprequests) |
-| requestContact | [useWebAppRequests](#usewebapprequests) |
-| ready | [useWebApp](#usewebapp) |
-| expand | [useWebAppViewport](#usewebappviewport) |
-| close | [useWebApp](#usewebapp) |
-
-### Event Handling
-
-The package provides a set of functions for event handling. By convention, the name of the functions consists of the prefix `on` + the name of the Telegram event in camelCase. So `themeChanged` event turns into `onThemeChanged` and so on. [onEvent](#usewebapp) is also available if you prefer it instead.
+| initData | [useMiniApp](#useminiapp) |
+| initDataUnsafe | [useMiniApp](#useminiapp) |
+| version | [useMiniApp](#useminiapp) |
+| platform | [useMiniApp](#useminiapp) |
+| colorScheme | [useTheme](#usetheme) |
+| themeParams | [useTheme](#usetheme) |
+| isActive | [useMiniApp](#useminiapp) |
+| isExpanded | [useViewport](#useviewport) |
+| viewportHeight | [useViewport](#useviewport) |
+| viewportStableHeight | [useViewport](#useviewport) |
+| headerColor | [useTheme](#usetheme) |
+| backgroundColor | [useTheme](#usetheme) |
+| isClosingConfirmationEnabled | [useMiniApp](#useminiapp) |
+| isVerticalSwipesEnabled | [useViewport](#useviewport) |
+| isFullscreen | [useViewport](#useviewport) |
+| isOrientationLocked | [useViewport](#useviewport) |
+| safeAreaInset | [useViewport](#useviewport) |
+| contentSafeAreaInset | [useViewport](#useviewport) |
+| BackButton | [useBackButton](#usebackbutton) |
+| MainButton | [useMainButton](#usemainbutton) |
+| HapticFeedback | [useHapticFeedback](#usehapticfeedback) |
+| BiometricManager | [useBiometricManager](#usebiometricmanager) |
+| Accelerometer | [useAccelerometer](#useaccelerometer) |
+| DeviceOrientation | [useDeviceOrientation](#usedeviceorientation) |
+| Gyroscope | [useGyroscope](#usegyroscope) |
+| LocationManager | [useLocationManager](#uselocationmanager) |
+| isVersionAtLeast | [useMiniApp](#useminiapp) |
+| setHeaderColor | [useTheme](#usetheme) |
+| setBackgroundColor | [useTheme](#usetheme) |
+| setBottomBarColor | [useTheme](#usetheme) |
+| enableClosingConfirmation | [useMiniApp](#useminiapp) |
+| disableClosingConfirmation | [useMiniApp](#useminiapp) |
+| enableVerticalSwipes | [useViewport](#useviewport) |
+| disableVerticalSwipes | [useViewport](#useviewport) |
+| requestFullscreen | [useViewport](#useviewport) |
+| exitFullscreen | [useViewport](#useviewport) |
+| lockOrientation | [useViewport](#useviewport) |
+| unlockOrientation | [useViewport](#useviewport) |
+| addToHomeScreen | [useHomeScreen](#usehomescreen) |
+| checkHomeScreenStatus | [useHomeScreen](#usehomescreen) |
+| onEvent | [Event Handling](#event-handling) |
+| offEvent | [Managing Event Subscriptions](#managing-event-subscriptions) |
+| sendData | [useMiniApp](#useminiapp) |
+| switchInlineQuery | [useMiniApp](#useminiapp) |
+| openLink | [useMiniApp](#useminiapp) |
+| openTelegramLink | [useMiniApp](#useminiapp) |
+| openInvoice | [useMiniApp](#useminiapp) |
+| shareToStory | [useMiniApp](#useminiapp) |
+| shareMessage | [useMiniApp](#useminiapp) |
+| setEmojiStatus | [useEmojiStatus](#useemojistatus) |
+| requestEmojiStatusAccess | [useEmojiStatus](#useemojistatus) |
+| downloadFile | [useMiniApp](#useminiapp) |
+| showPopup | [usePopup](#usepopup) |
+| showAlert | [usePopup](#usepopup) |
+| showConfirm | [usePopup](#usepopup) |
+| showScanQrPopup | [useQrScanner](#useqrscanner) |
+| closeScanQrPopup | [useQrScanner](#useqrscanner) |
+| readTextFromClipboard | [useClipboard](#useclipboard) |
+| requestWriteAccess | [useMiniApp](#useminiapp) |
+| requestContact | [useMiniApp](#useminiapp) |
+| ready | [useMiniApp](#useminiapp) |
+| expand | [useViewport](#useviewport) |
+| close | [useMiniApp](#useminiapp) |
+
+## Version Check
+
+Features are introduced in specific versions of the Bot API, but users may not always use clients that support the latest version.
+Always verify version compatibility to ensure feature support.
+
+For example, `shareToStory` was introduced in version __7.8__:
+
+```ts twoslash
+import { useMiniApp } from 'vue-tg'
+
+const miniApp = useMiniApp()
+
+// error because this method was introduced in version 7.8
+// @errors: 2722
+miniApp.shareToStory("https://url-to-image")
+
+// first, ensure the version is 7.8 or higher
+if (miniApp.isVersionAtLeast('7.8')) {
+ miniApp.shareToStory("https://url-to-image") // no error
+}
+```
-```ts
-import { useWebAppTheme } from 'vue-tg'
+You can explicitly set the base version:
+
+```ts twoslash
+import { useMiniApp } from 'vue-tg/7.8'
+// ^^^
+
+const miniApp = useMiniApp()
+
+miniApp.shareToStory("https://url-to-image") // no error
+
+// error because this method was introduced in version 8.0
+// @errors: 2722
+miniApp.downloadFile({ url: "https://url-to-image", file_name: "kitten.png" })
+```
+
+To skip all version checks, use `latest`, which is an alias for the latest version.
+This is useful for prototyping but unreliable for production.
+**Use it only if you know what you are doing.**
+
+```ts twoslash
+import { useMiniApp } from 'vue-tg/latest'
+// ^^^^^^
+
+const miniApp = useMiniApp()
+
+miniApp.shareToStory("https://url-to-image") // no error
+```
+
+Specifying the version every time can be tedious.
+For convenience, create a file `telegram.ts` with following content:
-const { onThemeChanged } = useWebAppTheme()
+```ts twoslash
+import { isVersionAtLeast } from 'vue-tg'
+import { usePopup, useMiniApp } from 'vue-tg/latest'
+
+const popup = usePopup()
+const miniApp = useMiniApp()
+
+if (!isVersionAtLeast('8.0')) {
+ // ^^^
+ popup.showAlert(
+ "Please update Telegram to the latest version!",
+ miniApp.close
+ )
+}
+
+export * from 'vue-tg/8.0'
+// ^^^
+```
+
+Now, you can import composables from `telegram.ts` and be sure that the client supports the specified version (`8.0` in this case).
+
+## Event Handling
+
+Event-handling functions follow the naming convention `on` in camelCase.
+For example, the `themeChanged` event becomes `onThemeChanged`, and so on.
+A generic `onEvent` is also available if you prefer to use it instead.
+
+```ts
+import { onThemeChanged } from 'vue-tg'
onThemeChanged(() => {
// handle theme update
})
```
-#### Mapping
+You can also use composables for event handling:
-| Event name | Handler |
-| ----------------------- | ----------------------------------------------------------------------------------- |
-| themeChanged | [useWebAppTheme → onThemeChanged](#usewebapptheme) |
-| viewportChanged | [useWebAppViewport → onViewportChanged](#usewebappviewport) |
-| mainButtonClicked | [useWebAppMainButton → onMainButtonClicked](#usewebappmainbutton) |
-| backButtonClicked | [useWebAppBackButton → onBackButtonClicked](#usewebappbackbutton) |
-| settingsButtonClicked | [useWebAppSettingsButton → onSettingsButtonClicked](#usewebappsettingsbutton) |
-| invoiceClosed | [useWebAppNavigation → onInvoiceClosed](#usewebappnavigation) |
-| popupClosed | [useWebAppPopup → onPopupClosed](#usewebapppopup) |
-| qrTextReceived | [useWebAppQrScanner → onQrTextReceived](#usewebappqrscanner) |
-| scanQrPopupClosed | [useWebAppQrScanner → onScanQrPopupClosed](#usewebappqrscanner) |
-| clipboardTextReceived | [useWebAppClipboard → onClipboardTextReceived](#usewebappclipboard) |
-| writeAccessRequested | [useWebAppRequests → onWriteAccessRequested](#usewebapprequests) |
-| contactRequested | [useWebAppRequests → onContactRequested](#usewebapprequests) |
-| biometricManagerUpdated | [useWebAppBiometricManager → onBiometricManagerUpdated](#usewebappbiometricmanager) |
-| biometricAuthRequested | [useWebAppBiometricManager → onBiometricAuthRequested](#usewebappbiometricmanager) |
-| biometricTokenUpdated | [useWebAppBiometricManager → onBiometricTokenUpdated](#usewebappbiometricmanager) |
+```ts
+import { useTheme } from 'vue-tg'
+const theme = useTheme()
-#### Managing event subscriptions
+theme.onChange(() => {
+ // handle theme update
+})
+```
-By default, event handlers are automatically unsubscribed when the component is unmounted.
-But you can unsubscribe before that if you need to:
+::: details Event Mapping
+| Event name | Handler | Composable Alias |
+| -------------------------- | ---------------------------- | ------------------------------------------------------------------ |
+| activated | onActivated | [useMiniApp →
onActive](#useminiapp) |
+| deactivated | onDeactivated | [useMiniApp →
onDeactive](#useminiapp) |
+| themeChanged | onThemeChanged | [useTheme →
onChange](#usetheme) |
+| viewportChanged | onViewportChanged | [useViewport →
onChange](#useviewport) |
+| safeAreaChanged | onSafeAreaChanged | [useViewport →
onSafeAreaChange](#useviewport) |
+| contentSafeAreaChanged | onContentSafeAreaChanged | [useViewport →
onContentSafeAreaChange](#useviewport) |
+| mainButtonClicked | onMainButtonClicked | [useMainButton →
onClick](#usemainbutton) |
+| secondaryButtonClicked | onSecondaryButtonClicked | [useSecondaryButton →
onClick](#usesecondarybutton) |
+| backButtonClicked | onBackButtonClicked | [useBackButton →
onClick](#usebackbutton) |
+| settingsButtonClicked | onSettingsButtonClicked | [useSettingsButton →
onClick](#usesettingsbutton) |
+| invoiceClosed | onInvoiceClosed | [useMiniApp →
onInvoiceClose](#useminiapp) |
+| popupClosed | onPopupClosed | [usePopup →
onClose](#usepopup) |
+| qrTextReceived | onQrTextReceived | [useQrScanner →
onScan](#useqrscanner) |
+| scanQrPopupClosed | onScanQrPopupClosed | [useQrScanner →
onClose](#useqrscanner) |
+| clipboardTextReceived | onClipboardTextReceived | [useClipboard →
onRead](#useclipboard) |
+| writeAccessRequested | onWriteAccessRequested | [useMiniApp →
onWriteAccessRequest](#useminiapp) |
+| contactRequested | onContactRequested | [useMiniApp →
onContactRequest](#useminiapp) |
+| biometricManagerUpdated | onBiometricManagerUpdated | [useBiometricManager →
onManagerUpdate](#usebiometricmanager) |
+| biometricAuthRequested | onBiometricAuthRequested | [useBiometricManager →
onAuthRequest](#usebiometricmanager) |
+| biometricTokenUpdated | onBiometricTokenUpdated | [useBiometricManager →
onTokenUpdate](#usebiometricmanager) |
+| fullscreenChanged | onFullscreenChanged | [useViewport →
onFullscreenChange](#useviewport) |
+| fullscreenFailed | onFullscreenFailed | [useViewport →
onFullscreenFail](#useviewport) |
+| homeScreenAdded | onHomeScreenAdded | [useHomeScreen →
onShortcutAdd](#usehomescreen) |
+| homeScreenChecked | onHomeScreenChecked | [useHomeScreen →
onShortcutCheck](#usehomescreen) |
+| accelerometerStarted | onAccelerometerStarted | [useAccelerometer →
onStart](#useaccelerometer) |
+| accelerometerStopped | onAccelerometerStopped | [useAccelerometer →
onStop](#useaccelerometer) |
+| accelerometerChanged | onAccelerometerChanged | [useAccelerometer →
onChange](#useaccelerometer) |
+| accelerometerFailed | onAccelerometerFailed | [useAccelerometer →
onFail](#useaccelerometer) |
+| deviceOrientationStarted | onDeviceOrientationStarted | [useDeviceOrientation →
onStart](#usedeviceorientation) |
+| deviceOrientationStopped | onDeviceOrientationStopped | [useDeviceOrientation →
onStop](#usedeviceorientation) |
+| deviceOrientationChanged | onDeviceOrientationChanged | [useDeviceOrientation →
onChange](#usedeviceorientation) |
+| deviceOrientationFailed | onDeviceOrientationFailed | [useDeviceOrientation →
onFail](#usedeviceorientation) |
+| gyroscopeStarted | onGyroscopeStarted | [useGyroscope →
onStart](#usegyroscope) |
+| gyroscopeStopped | onGyroscopeStopped | [useGyroscope →
onStop](#usegyroscope) |
+| gyroscopeChanged | onGyroscopeChanged | [useGyroscope →
onChange](#usegyroscope) |
+| gyroscopeFailed | onGyroscopeFailed | [useGyroscope →
onFail](#usegyroscope) |
+| locationManagerUpdated | onLocationManagerUpdated | [useLocationManager →
onManagerUpdate](#uselocationmanager) |
+| locationRequested | onLocationRequested | [useLocationManager →
onRequest](#uselocationmanager) |
+| shareMessageSent | onShareMessageSent | [useMiniApp →
onShareMessageSent](#useminiapp) |
+| shareMessageFailed | onShareMessageFailed | [useMiniApp →
onShareMessageFail](#useminiapp) |
+| emojiStatusSet | onEmojiStatusSet | [useEmojiStatus →
onSet](#useemojistatus) |
+| emojiStatusAccessRequested | onEmojiStatusAccessRequested | [useEmojiStatus →
onAccessRequest](#useemojistatus) |
+| emojiStatusFailed | onEmojiStatusFailed | [useEmojiStatus →
onFail](#useemojistatus) |
+| fileDownloadRequested | onFileDownloadRequested | [useMiniApp →
onFileDownloadRequest](#useminiapp) |
+:::
+
+#### Managing Event Subscriptions
-```ts{9-10}
-import { useWebAppTheme } from 'vue-tg'
+Event handlers automatically unsubscribe when the component unmounts.
+However, you can unsubscribe earlier if needed:
-const { onThemeChanged } = useWebAppTheme()
+```ts{7-8}
+import { onThemeChanged } from 'vue-tg'
const handler = onThemeChanged(() => {
// handle theme update
@@ -108,12 +240,10 @@ const handler = onThemeChanged(() => {
handler.off()
```
-You can also disable automatic unsubscribing completely:
+To disable automatic unsubscribing, set manual mode:
-```ts{9,12-13}
-import { useWebAppTheme } from 'vue-tg'
-
-const { onThemeChanged } = useWebAppTheme()
+```ts
+import { onThemeChanged } from 'vue-tg'
const handler = onThemeChanged(
() => {
@@ -127,8 +257,8 @@ handler.off()
```
::: warning
-Please note that in `manual` mode, you are responsible for managing subscription.
-If subscription is not managed properly, it can lead to memory leaks and other issues.
+In `manual` mode, you are responsible for managing the subscription.
+Improper management may lead to memory leaks or other issues.
:::
## Components
@@ -151,38 +281,80 @@ If subscription is not managed properly, it can lead to memory leaks and other i
+
+
## Composables
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Composables (Legacy)
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/docs/mini-apps/components/main-button.md b/docs/mini-apps/components/main-button.md
index 31e28c9..a0f6b53 100644
--- a/docs/mini-apps/components/main-button.md
+++ b/docs/mini-apps/components/main-button.md
@@ -18,14 +18,15 @@ function handleMainButton() {
#### Props
-| Name | Type | Required | Description |
-| --------- | ------- | -------- | ------------------------------------------------------------ |
-| visible | boolean | false | Shows whether the button is visible. Set to true by default. |
-| disabled | boolean | false | Shows whether the button is disable. |
-| progress | boolean | false | Shows whether the button is displaying a loading indicator. |
-| text | string | false | Current button text. |
-| color | string | false | Current button color. |
-| textColor | string | false | Current button text color. |
+| Name | Type | Required | Description |
+| -------------- | ------- | -------- | ------------------------------------------------------------ |
+| visible | boolean | false | Shows whether the button is visible. Set to true by default. |
+| disabled | boolean | false | Shows whether the button is disable. |
+| progress | boolean | false | Shows whether the button is displaying a loading indicator. |
+| text | string | false | |
+| color | string | false | |
+| textColor | string | false | |
+| hasShineEffect | boolean | false | |
#### Events
diff --git a/docs/mini-apps/components/secondary-button.md b/docs/mini-apps/components/secondary-button.md
new file mode 100644
index 0000000..be13313
--- /dev/null
+++ b/docs/mini-apps/components/secondary-button.md
@@ -0,0 +1,36 @@
+### SecondaryButton
+
+A component that enables the secondary button when is rendered.
+
+```vue
+
+
+
+
+
+```
+
+#### Props
+
+| Name | Type | Required | Description |
+| -------------- | ------- | -------- | ------------------------------------------------------------ |
+| visible | boolean | false | Shows whether the button is visible. Set to true by default. |
+| disabled | boolean | false | Shows whether the button is disable. |
+| progress | boolean | false | Shows whether the button is displaying a loading indicator. |
+| text | string | false | |
+| color | string | false | |
+| textColor | string | false | |
+| hasShineEffect | boolean | false | |
+| position | string | false | |
+
+#### Events
+
+| Name | Type | Description |
+| ----- | ------------ | -------------------------------------- |
+| click | `() => void` | Emits when the main button is pressed. |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-back-button.md b/docs/mini-apps/composables-legacy/use-web-app-back-button.md
new file mode 100644
index 0000000..f3f3d2b
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-back-button.md
@@ -0,0 +1,16 @@
+### ~~useWebAppBackButton~~
+
+::: danger Deprecated
+Use [useBackButton](#usebackbutton) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppBackButton } from 'vue-tg'
+```
+
+| Name | Description |
+| :-------------------- | :-------------------------------------------------------------------------------------------------- |
+| `isBackButtonVisible` |
|
+| `showBackButton` | |
+| `hideBackButton` | |
diff --git a/docs/mini-apps/composables/use-web-app-biometric-manager.md b/docs/mini-apps/composables-legacy/use-web-app-biometric-manager.md
similarity index 89%
rename from docs/mini-apps/composables/use-web-app-biometric-manager.md
rename to docs/mini-apps/composables-legacy/use-web-app-biometric-manager.md
index dbc9708..3551628 100644
--- a/docs/mini-apps/composables/use-web-app-biometric-manager.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-biometric-manager.md
@@ -1,4 +1,8 @@
-### useWebAppBiometricManager
+### ~~useWebAppBiometricManager~~
+
+::: danger Deprecated
+Use [useBiometricManager](#usebiometricmanager) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -19,6 +23,6 @@ import { useWebAppBiometricManager } from 'vue-tg'
| `authenticateBiometric` | |
| `updateBiometricToken` | |
| `openBiometricSettings` | |
-| `onBiometricManagerUpdated` | A method that sets the `biometricManagerUpdated` [event handler](#event-handling). |
-| `onBiometricAuthRequested` | A method that sets the `biometricAuthRequested` [event handler](#event-handling). |
-| `onBiometricTokenUpdated` | A method that sets the `biometricTokenUpdated` [event handler](#event-handling). |
+| `onManagerUpdated` | A method that sets the `biometricManagerUpdated` [event handler](#event-handling). |
+| `onAuthRequested` | A method that sets the `biometricAuthRequested` [event handler](#event-handling). |
+| `onTokenUpdated` | A method that sets the `biometricTokenUpdated` [event handler](#event-handling). |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-clipboard.md b/docs/mini-apps/composables-legacy/use-web-app-clipboard.md
new file mode 100644
index 0000000..506c0ef
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-clipboard.md
@@ -0,0 +1,14 @@
+### ~~useWebAppClipboard~~
+
+::: danger Deprecated
+Use [useClipboard](#useclipboard) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppClipboard } from 'vue-tg'
+```
+
+| Name | Type |
+| :---------------------- | :------------------------------------------------------------ |
+| `readTextFromClipboard` | |
diff --git a/docs/mini-apps/composables/use-web-app-closing-confirmation.md b/docs/mini-apps/composables-legacy/use-web-app-closing-confirmation.md
similarity index 89%
rename from docs/mini-apps/composables/use-web-app-closing-confirmation.md
rename to docs/mini-apps/composables-legacy/use-web-app-closing-confirmation.md
index c95a28f..87a4054 100644
--- a/docs/mini-apps/composables/use-web-app-closing-confirmation.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-closing-confirmation.md
@@ -1,4 +1,8 @@
-### useWebAppClosingConfirmation
+### ~~useWebAppClosingConfirmation~~
+
+::: danger Deprecated
+Use [useMiniApp](#useminiapp) instead.
+:::
```ts twoslash
// Hover to inspect type
diff --git a/docs/mini-apps/composables/use-web-app-cloud-storage.md b/docs/mini-apps/composables-legacy/use-web-app-cloud-storage.md
similarity index 87%
rename from docs/mini-apps/composables/use-web-app-cloud-storage.md
rename to docs/mini-apps/composables-legacy/use-web-app-cloud-storage.md
index 99df7d8..df3c122 100644
--- a/docs/mini-apps/composables/use-web-app-cloud-storage.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-cloud-storage.md
@@ -1,4 +1,8 @@
-### useWebAppCloudStorage
+### ~~useWebAppCloudStorage~~
+
+::: danger Deprecated
+Use [useCloudStorage](#usecloudstorage) instead.
+:::
```ts twoslash
// Hover to inspect type
diff --git a/docs/mini-apps/composables/use-web-app-haptic-feedback.md b/docs/mini-apps/composables-legacy/use-web-app-haptic-feedback.md
similarity index 83%
rename from docs/mini-apps/composables/use-web-app-haptic-feedback.md
rename to docs/mini-apps/composables-legacy/use-web-app-haptic-feedback.md
index 217e049..e2c861b 100644
--- a/docs/mini-apps/composables/use-web-app-haptic-feedback.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-haptic-feedback.md
@@ -1,4 +1,8 @@
-### useWebAppHapticFeedback
+### ~~useWebAppHapticFeedback~~
+
+::: danger Deprecated
+Use [useHapticFeedback](#usehapticfeedback) instead.
+:::
```ts twoslash
// Hover to inspect type
diff --git a/docs/mini-apps/composables/use-web-app-main-button.md b/docs/mini-apps/composables-legacy/use-web-app-main-button.md
similarity index 93%
rename from docs/mini-apps/composables/use-web-app-main-button.md
rename to docs/mini-apps/composables-legacy/use-web-app-main-button.md
index 3749c52..3a065d3 100644
--- a/docs/mini-apps/composables/use-web-app-main-button.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-main-button.md
@@ -1,4 +1,8 @@
-### useWebAppMainButton
+### ~~useWebAppMainButton~~
+
+::: danger Deprecated
+Use [useMainButton](#usemainbutton) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -14,7 +18,6 @@ import { useWebAppMainButton } from 'vue-tg'
| `isMainButtonActive` |
|
| `isMainButtonProgressVisible` |
|
| `setMainButtonText` | |
-| `onMainButtonClicked` | A method that sets the `mainButtonClicked` [event handler](#event-handling). |
| `showMainButton` | |
| `hideMainButton` | |
| `enableMainButton` | |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-navigation.md b/docs/mini-apps/composables-legacy/use-web-app-navigation.md
new file mode 100644
index 0000000..8b66b3e
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-navigation.md
@@ -0,0 +1,17 @@
+### ~~useWebAppNavigation~~
+
+::: danger Deprecated
+Use [useMiniApp](#useminiapp) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppNavigation } from 'vue-tg'
+```
+
+| Name | Type |
+| :------------------ | :-------------------------------------------------------- |
+| `openInvoice` | |
+| `openLink` | |
+| `openTelegramLink` | |
+| `switchInlineQuery` | |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-popup.md b/docs/mini-apps/composables-legacy/use-web-app-popup.md
new file mode 100644
index 0000000..bf05d35
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-popup.md
@@ -0,0 +1,16 @@
+### ~~useWebAppPopup~~
+
+::: danger Deprecated
+Use [usePopup](#usepopup) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppPopup } from 'vue-tg'
+```
+
+| Name | Type |
+| :------------ | :-------------------------------------------------- |
+| `showAlert` | |
+| `showConfirm` | |
+| `showPopup` | |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-qr-scanner.md b/docs/mini-apps/composables-legacy/use-web-app-qr-scanner.md
new file mode 100644
index 0000000..13b2861
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-qr-scanner.md
@@ -0,0 +1,15 @@
+### ~~useWebAppQrScanner~~
+
+::: danger Deprecated
+Use [useQrScanner](#useqrscanner) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppQrScanner } from 'vue-tg'
+```
+
+| Name | Type |
+| :----------------- | :------------------------------------------------------- |
+| `showScanQrPopup` | |
+| `closeScanQrPopup` | |
diff --git a/docs/mini-apps/composables-legacy/use-web-app-requests.md b/docs/mini-apps/composables-legacy/use-web-app-requests.md
new file mode 100644
index 0000000..da81847
--- /dev/null
+++ b/docs/mini-apps/composables-legacy/use-web-app-requests.md
@@ -0,0 +1,15 @@
+### ~~useWebAppRequests~~
+
+::: danger Deprecated
+Use [useMiniApp](#useminiapp) instead.
+:::
+
+```ts twoslash
+// Hover to inspect type
+import { useWebAppRequests } from 'vue-tg'
+```
+
+| Name | Type |
+| :------------------- | :--------------------------------------------------------- |
+| `requestContact` | |
+| `requestWriteAccess` | |
diff --git a/docs/mini-apps/composables/use-web-app-settings-button.md b/docs/mini-apps/composables-legacy/use-web-app-settings-button.md
similarity index 69%
rename from docs/mini-apps/composables/use-web-app-settings-button.md
rename to docs/mini-apps/composables-legacy/use-web-app-settings-button.md
index 9233207..e782d9e 100644
--- a/docs/mini-apps/composables/use-web-app-settings-button.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-settings-button.md
@@ -1,13 +1,16 @@
-### useWebAppSettingsButton
+### ~~useWebAppSettingsButton~~
+
+::: danger Deprecated
+Use [useSettingsButton](#usesettingsbutton) instead.
+:::
```ts twoslash
// Hover to inspect type
import { useWebAppSettingsButton } from 'vue-tg'
```
-| Name | Type |
-| :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
-| `isSettingsButtonVisible` |
|
-| `onSettingsButtonClicked` | A method that sets the `settingsButtonClicked` [event handler](#event-handling). |
-| `showSettingsButton` | |
-| `hideSettingsButton` | |
+| Name | Type |
+| :------------------------ | :----------------------------------------------------------------------------------------------------- |
+| `isSettingsButtonVisible` |
|
+| `showSettingsButton` | |
+| `hideSettingsButton` | |
diff --git a/docs/mini-apps/composables/use-web-app-share.md b/docs/mini-apps/composables-legacy/use-web-app-share.md
similarity index 75%
rename from docs/mini-apps/composables/use-web-app-share.md
rename to docs/mini-apps/composables-legacy/use-web-app-share.md
index 358a96a..e9c52e2 100644
--- a/docs/mini-apps/composables/use-web-app-share.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-share.md
@@ -1,4 +1,8 @@
-### useWebAppShare
+### ~~useWebAppShare~~
+
+::: danger Deprecated
+Use [useMiniApp](#useminiapp) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -7,4 +11,4 @@ import { useWebAppShare } from 'vue-tg'
| Name | Type |
| :------------- | :--------------------------------------------------- |
-| `shareToStory` | |
\ No newline at end of file
+| `shareToStory` | |
diff --git a/docs/mini-apps/composables/use-web-app-theme.md b/docs/mini-apps/composables-legacy/use-web-app-theme.md
similarity index 88%
rename from docs/mini-apps/composables/use-web-app-theme.md
rename to docs/mini-apps/composables-legacy/use-web-app-theme.md
index 432288b..8c9c02d 100644
--- a/docs/mini-apps/composables/use-web-app-theme.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-theme.md
@@ -1,4 +1,8 @@
-### useWebAppTheme
+### ~~useWebAppTheme~~
+
+::: danger Deprecated
+Use [useTheme](#usetheme) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -13,4 +17,3 @@ import { useWebAppTheme } from 'vue-tg'
| `backgroundColor` |
|
| `setHeaderColor` | |
| `setBackgroundColor` | |
-| `onThemeChanged` | A method that sets the `themeParams` [event handler](#event-handling). |
diff --git a/docs/mini-apps/composables/use-web-app-viewport.md b/docs/mini-apps/composables-legacy/use-web-app-viewport.md
similarity index 89%
rename from docs/mini-apps/composables/use-web-app-viewport.md
rename to docs/mini-apps/composables-legacy/use-web-app-viewport.md
index d82a63d..601651b 100644
--- a/docs/mini-apps/composables/use-web-app-viewport.md
+++ b/docs/mini-apps/composables-legacy/use-web-app-viewport.md
@@ -1,4 +1,8 @@
-### useWebAppViewport
+### ~~useWebAppViewport~~
+
+::: danger Deprecated
+Use [useViewport](#useviewport) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -14,4 +18,3 @@ import { useWebAppViewport } from 'vue-tg'
| `expand` | |
| `enableVerticalSwipes` | |
| `disableVerticalSwipes` | |
-| `onViewportChanged` | A method that sets the `viewportChanged` [event handler](#event-handling). |
diff --git a/docs/mini-apps/composables/use-web-app.md b/docs/mini-apps/composables-legacy/use-web-app.md
similarity index 93%
rename from docs/mini-apps/composables/use-web-app.md
rename to docs/mini-apps/composables-legacy/use-web-app.md
index fac90a1..317b2ee 100644
--- a/docs/mini-apps/composables/use-web-app.md
+++ b/docs/mini-apps/composables-legacy/use-web-app.md
@@ -1,4 +1,8 @@
-### useWebApp
+### ~~useWebApp~~
+
+::: danger Deprecated
+Use [useMiniApp](#useminiapp) instead.
+:::
```ts twoslash
// Hover to inspect type
@@ -12,7 +16,6 @@ import { useWebApp } from 'vue-tg'
| `version` | |
| `platform` | |
| `isVersionAtLeast` | |
-| `onEvent` | |
| `sendData` | |
| `ready` | |
| `close` | |
diff --git a/docs/mini-apps/composables/use-accelerometer.md b/docs/mini-apps/composables/use-accelerometer.md
new file mode 100644
index 0000000..cdd634a
--- /dev/null
+++ b/docs/mini-apps/composables/use-accelerometer.md
@@ -0,0 +1,22 @@
+### useAccelerometer
+
+```ts
+import { useAccelerometer } from 'vue-tg'
+
+const accelerometer = useAccelerometer()
+```
+
+| Name | Description |
+| :----------------- | :--------------------------------------------------------------------------------------------------------------------------- |
+| `isStarted` |
|
+| `x` |
|
+| `y` |
|
+| `z` |
|
+| `start` |
|
+| `onStart` | A method that sets event handler. An alias for onAccelerometerStarted
. |
+| `onChange` | A method that sets event handler. An alias for onAccelerometerChanged
. |
+| `onFail` | A method that sets event handler. An alias for onAccelerometerFailed
. |
+| `stop` |
|
+| `onStop` | A method that sets event handler. An alias for onAccelerometerStopped
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-back-button.md b/docs/mini-apps/composables/use-back-button.md
new file mode 100644
index 0000000..aa809b6
--- /dev/null
+++ b/docs/mini-apps/composables/use-back-button.md
@@ -0,0 +1,16 @@
+### useBackButton
+
+```ts
+import { useBackButton } from 'vue-tg'
+
+const backButton = useBackButton()
+```
+
+| Name | Description |
+| :----------------- | :-------------------------------------------------------------------------------------------------- |
+| `isVisible` |
|
+| `show` | |
+| `hide` | |
+| `onClick` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-biometric-manager.md b/docs/mini-apps/composables/use-biometric-manager.md
new file mode 100644
index 0000000..24cb25e
--- /dev/null
+++ b/docs/mini-apps/composables/use-biometric-manager.md
@@ -0,0 +1,27 @@
+### useBiometricManager
+
+```ts
+import { useBiometricManager } from 'vue-tg'
+
+const biometricManager = useBiometricManager()
+```
+
+| Name | Type |
+| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `isInited` |
|
+| `isBiometricAvailable` |
|
+| `biometricType` |
|
+| `isAccessRequested` |
|
+| `isAccessGranted` |
|
+| `isBiometricTokenSaved` |
|
+| `deviceId` |
|
+| `init` |
|
+| `requestAccess` |
|
+| `onManagerUpdate` | A method that sets event handler. An alias for onBiometricManagerUpdated
. |
+| `authenticate` |
|
+| `onAuthRequest` | A method that sets event handler. An alias for onBiometricAuthRequested
. |
+| `updateToken` |
|
+| `onTokenUpdate` | A method that sets event handler. An alias for onBiometricTokenUpdated
. |
+| `openSettings` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-clipboard.md b/docs/mini-apps/composables/use-clipboard.md
new file mode 100644
index 0000000..14c4c82
--- /dev/null
+++ b/docs/mini-apps/composables/use-clipboard.md
@@ -0,0 +1,14 @@
+### useClipboard
+
+```ts
+import { useClipboard } from 'vue-tg'
+
+const clipboard = useClipboard()
+```
+
+| Name | Description |
+| :----------------- | :---------------------------------------------------------------------------------------------------------------------------- |
+| `readText` |
|
+| `onReadText` | A method that sets event handler. An alias for onClipboardTextReceived
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-cloud-storage.md b/docs/mini-apps/composables/use-cloud-storage.md
new file mode 100644
index 0000000..c13ac48
--- /dev/null
+++ b/docs/mini-apps/composables/use-cloud-storage.md
@@ -0,0 +1,18 @@
+### useCloudStorage
+
+```ts
+import { useCloudStorage } from 'vue-tg'
+
+const cloudStorage = useCloudStorage()
+```
+
+| Name | Type |
+| :----------------- | :------------------------------------------------------------------------------------------------- |
+| `setItem` |
|
+| `getItem` |
|
+| `getItems` |
|
+| `removeItem` |
|
+| `removeItems` |
|
+| `getKeys` |
|
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-device-orientation.md b/docs/mini-apps/composables/use-device-orientation.md
new file mode 100644
index 0000000..14583bb
--- /dev/null
+++ b/docs/mini-apps/composables/use-device-orientation.md
@@ -0,0 +1,23 @@
+### useDeviceOrientation
+
+```ts
+import { useDeviceOrientation } from 'vue-tg'
+
+const deviceOrientation = useDeviceOrientation()
+```
+
+| Name | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------- |
+| `isStarted` |
|
+| `absolute` |
|
+| `alpha` |
|
+| `beta` |
|
+| `gamma` |
|
+| `start` |
|
+| `onStart` | A method that sets event handler. An alias for onDeviceOrientationStarted
. |
+| `onChange` | A method that sets event handler. An alias for onDeviceOrientationChanged
. |
+| `onFail` | A method that sets event handler. An alias for onDeviceOrientationFailed
. |
+| `stop` |
|
+| `onStop` | A method that sets event handler. An alias for onDeviceOrientationStopped
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-emoji-status.md b/docs/mini-apps/composables/use-emoji-status.md
new file mode 100644
index 0000000..93003cf
--- /dev/null
+++ b/docs/mini-apps/composables/use-emoji-status.md
@@ -0,0 +1,17 @@
+### useEmojiStatus
+
+```ts
+import { useEmojiStatus } from 'vue-tg'
+
+const emojiStatus = useEmojiStatus()
+```
+
+| Name | Description |
+| :----------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
+| `set` |
|
+| `onSet` | A method that sets event handler. An alias for onEmojiStatusSet
. |
+| `onFail` | A method that sets event handler. An alias for onEmojiStatusFailed
. |
+| `requestAccess` |
|
+| `onAccessRequest` | A method that sets event handler. An alias for onEmojiStatusAccessRequested
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-gyroscope.md b/docs/mini-apps/composables/use-gyroscope.md
new file mode 100644
index 0000000..327d877
--- /dev/null
+++ b/docs/mini-apps/composables/use-gyroscope.md
@@ -0,0 +1,22 @@
+### useGyroscope
+
+```ts
+import { useGyroscope } from 'vue-tg'
+
+const gyroscope = useGyroscope()
+```
+
+| Name | Description |
+| :----------------- | :----------------------------------------------------------------------------------------------------------------------- |
+| `isStarted` |
|
+| `x` |
|
+| `y` |
|
+| `z` |
|
+| `start` |
|
+| `onStart` | A method that sets event handler. An alias for onGyroscopeStarted
. |
+| `onChange` | A method that sets event handler. An alias for onGyroscopeChanged
. |
+| `onFail` | A method that sets event handler. An alias for onGyroscopeFailed
. |
+| `stop` |
|
+| `onStop` | A method that sets event handler. An alias for onGyroscopeStopped
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-haptic-feedback.md b/docs/mini-apps/composables/use-haptic-feedback.md
new file mode 100644
index 0000000..11deb57
--- /dev/null
+++ b/docs/mini-apps/composables/use-haptic-feedback.md
@@ -0,0 +1,15 @@
+### useHapticFeedback
+
+```ts
+import { useHapticFeedback } from 'vue-tg'
+
+const hapticFeedback = useHapticFeedback()
+```
+
+| Name | Description |
+| :--------------------- | :------------------------------------------------------------------- |
+| `impactOccurred` | |
+| `notificationOccurred` | |
+| `selectionChanged` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-home-screen.md b/docs/mini-apps/composables/use-home-screen.md
new file mode 100644
index 0000000..859d687
--- /dev/null
+++ b/docs/mini-apps/composables/use-home-screen.md
@@ -0,0 +1,16 @@
+### useHomeScreen
+
+```ts
+import { useHomeScreen } from 'vue-tg'
+
+const homeScreen = useHomeScreen()
+```
+
+| Name | Type |
+| :-------------------- | :------------------------------------------------------------------------------------------------------------------------ |
+| `addShortcut` | |
+| `onShortcutAdd` | A method that sets event handler. An alias for onHomeScreenAdded
. |
+| `checkShortcutStatus` |
|
+| `onShortcutCheck` | A method that sets event handler. An alias for onHomeScreenChecked
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-location-manager.md b/docs/mini-apps/composables/use-location-manager.md
new file mode 100644
index 0000000..6e06437
--- /dev/null
+++ b/docs/mini-apps/composables/use-location-manager.md
@@ -0,0 +1,21 @@
+### useLocationManager
+
+```ts
+import { useLocationManager } from 'vue-tg'
+
+const locationManager = useLocationManager()
+```
+
+| Name | Description |
+| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
+| `isInited` |
|
+| `isLocationAvailable` |
|
+| `isAccessRequested` |
|
+| `isAccessGranted` |
|
+| `init` |
|
+| `onManagerUpdate` | A method that sets event handler. An alias for onLocationManagerUpdated
. |
+| `getLocation` |
|
+| `onRequest` | A method that sets event handler. An alias for onLocationRequested
. |
+| `openSettings` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-main-button.md b/docs/mini-apps/composables/use-main-button.md
new file mode 100644
index 0000000..e7efa84
--- /dev/null
+++ b/docs/mini-apps/composables/use-main-button.md
@@ -0,0 +1,27 @@
+### useMainButton
+
+```ts
+import { useMainButton } from 'vue-tg'
+
+const mainButton = useMainButton()
+```
+
+| Name | Description |
+| :------------------ | :-------------------------------------------------------------------------------------------------------- |
+| `text` |
|
+| `color` |
|
+| `textColor` |
|
+| `isVisible` |
|
+| `isActive` |
|
+| `isProgressVisible` |
|
+| `hasShineEffect` |
|
+| `show` | |
+| `hide` | |
+| `enable` | |
+| `disable` | |
+| `showProgress` | |
+| `hideProgress` | |
+| `setParams` | |
+| `onClick` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-mini-app.md b/docs/mini-apps/composables/use-mini-app.md
new file mode 100644
index 0000000..0420fac
--- /dev/null
+++ b/docs/mini-apps/composables/use-mini-app.md
@@ -0,0 +1,39 @@
+### useMiniApp
+
+```ts
+import { useMiniApp } from 'vue-tg'
+
+const miniApp = useMiniApp()
+```
+
+| Name | Description |
+| :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
+| `initData` | |
+| `initDataUnsafe` | |
+| `platform` | |
+| `isActive` |
|
+| `onActive` | A method that sets event handler. An alias for onActivated
. |
+| `onDeactive` | A method that sets event handler. An alias for onDeactivated
. |
+| `sendData` | |
+| `switchInlineQuery` | |
+| `openLink` | |
+| `openTelegramLink` | |
+| `openInvoice` |
|
+| `onInvoiceClose` | A method that sets event handler. An alias for onInvoiceClosed
. |
+| `shareToStory` | |
+| `shareMessage` |
|
+| `onShareMessageSent` | A method that sets event handler. An alias for onShareMessageSent
. |
+| `onShareMessageFail` | A method that sets event handler. An alias for shareMessageFailed
. |
+| `downloadFile` |
|
+| `onFileDownloadRequest` | A method that sets event handler. An alias for onFileDownloadRequested
. |
+| `requestWriteAccess` |
|
+| `onWriteAccessRequest` | A method that sets event handler. An alias for onWriteAccessRequested
. |
+| `requestContact` |
|
+| `onContactRequest` | A method that sets event handler. An alias for onContactRequested
. |
+| `isClosingConfirmationEnabled` |
|
+| `ready` | |
+| `close` | |
+| `isReady` | Boolean indicating if the app is ready.
|
+| `isPlatform` | Function to check if the app is running on a specified platform.
|
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-popup.md b/docs/mini-apps/composables/use-popup.md
new file mode 100644
index 0000000..baaa521
--- /dev/null
+++ b/docs/mini-apps/composables/use-popup.md
@@ -0,0 +1,16 @@
+### usePopup
+
+```ts
+import { usePopup } from 'vue-tg'
+
+const popup = usePopup()
+```
+
+| Name | Type |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------ |
+| `showConfirm` |
|
+| `showAlert` |
|
+| `showPopup` |
|
+| `onClose` | A method that sets event handler. An alias for onPopupClosed
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-qr-scanner.md b/docs/mini-apps/composables/use-qr-scanner.md
new file mode 100644
index 0000000..0995dc9
--- /dev/null
+++ b/docs/mini-apps/composables/use-qr-scanner.md
@@ -0,0 +1,16 @@
+### useQrScanner
+
+```ts
+import { useQrScanner } from 'vue-tg'
+
+const qrScanner = useQrScanner()
+```
+
+| Name | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------ |
+| `show` | |
+| `close` | |
+| `onScan` | A method that sets event handler. An alias for onQrTextReceived
. |
+| `onClose` | A method that sets event handler. An alias for onScanQrPopupClosed
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-secondary-button.md b/docs/mini-apps/composables/use-secondary-button.md
new file mode 100644
index 0000000..2a94307
--- /dev/null
+++ b/docs/mini-apps/composables/use-secondary-button.md
@@ -0,0 +1,28 @@
+### useSecondaryButton
+
+```ts
+import { useSecondaryButton } from 'vue-tg'
+
+const secondaryButton = useSecondaryButton()
+```
+
+| Name | Description |
+| :------------------ | :-------------------------------------------------------------------------------------------------------- |
+| `text` |
|
+| `color` |
|
+| `textColor` |
|
+| `isVisible` |
|
+| `isActive` |
|
+| `isProgressVisible` |
|
+| `hasShineEffect` |
|
+| `position` |
|
+| `show` | |
+| `hide` | |
+| `enable` | |
+| `disable` | |
+| `showProgress` | |
+| `hideProgress` | |
+| `setParams` | |
+| `onClick` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-settings-button.md b/docs/mini-apps/composables/use-settings-button.md
new file mode 100644
index 0000000..cfec170
--- /dev/null
+++ b/docs/mini-apps/composables/use-settings-button.md
@@ -0,0 +1,16 @@
+### useSettingsButton
+
+```ts
+import { useSettingsButton } from 'vue-tg'
+
+const settingsButton = useSettingsButton()
+```
+
+| Name | Description |
+| :----------------- | :---------------------------------------------------------------------------------------------------- |
+| `isVisible` |
|
+| `show` | |
+| `hide` | |
+| `onClick` | |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-theme.md b/docs/mini-apps/composables/use-theme.md
new file mode 100644
index 0000000..b19ba06
--- /dev/null
+++ b/docs/mini-apps/composables/use-theme.md
@@ -0,0 +1,18 @@
+### useTheme
+
+```ts
+import { useTheme } from 'vue-tg'
+
+const theme = useTheme()
+```
+
+| Name | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------- |
+| `colorScheme` |
|
+| `themeParams` |
|
+| `headerColor` |
|
+| `backgroundColor` |
|
+| `bottomBarColor` |
|
+| `onChange` | A method that sets event handler. An alias for onThemeChanged
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-viewport.md b/docs/mini-apps/composables/use-viewport.md
new file mode 100644
index 0000000..8cef545
--- /dev/null
+++ b/docs/mini-apps/composables/use-viewport.md
@@ -0,0 +1,26 @@
+### useViewport
+
+```ts
+import { useViewport } from 'vue-tg'
+
+const viewport = useViewport()
+```
+
+| Name | Description |
+| :------------------------ | :----------------------------------------------------------------------------------------------------------------------------- |
+| `isExpanded` |
|
+| `expand` | |
+| `viewportHeight` |
|
+| `viewportStableHeight` |
|
+| `onChange` | A method that sets event handler. An alias for onViewportChanged
. |
+| `isFullscreen` |
|
+| `onFullscreenChange` | A method that sets event handler. An alias for onFullscreenChanged
. |
+| `onFullscreenFail` | A method that sets event handler. An alias for onFullscreenFailed
. |
+| `isOrientationLocked` |
|
+| `isVerticalSwipesEnabled` |
|
+| `safeAreaInset` |
|
+| `onSafeAreaChange` | A method that sets event handler. An alias for onSafeAreaChanged
. |
+| `contentSafeAreaInset` |
|
+| `onContentSafeAreaChange` | A method that sets event handler. An alias for onContentSafeAreaChanged
. |
+| `version` | |
+| `isVersionAtLeast` | |
diff --git a/docs/mini-apps/composables/use-web-app-back-button.md b/docs/mini-apps/composables/use-web-app-back-button.md
deleted file mode 100644
index e361a3e..0000000
--- a/docs/mini-apps/composables/use-web-app-back-button.md
+++ /dev/null
@@ -1,13 +0,0 @@
-### useWebAppBackButton
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppBackButton } from 'vue-tg'
-```
-
-| Name | Description |
-| :-------------------- | :-------------------------------------------------------------------------------------------------------------------- |
-| `isBackButtonVisible` |
|
-| `onBackButtonClicked` | A method that sets the `backButtonClicked` [event handler](#event-handling). |
-| `showBackButton` | |
-| `hideBackButton` | |
diff --git a/docs/mini-apps/composables/use-web-app-clipboard.md b/docs/mini-apps/composables/use-web-app-clipboard.md
deleted file mode 100644
index 7271e46..0000000
--- a/docs/mini-apps/composables/use-web-app-clipboard.md
+++ /dev/null
@@ -1,11 +0,0 @@
-### useWebAppClipboard
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppClipboard } from 'vue-tg'
-```
-
-| Name | Type |
-| :------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
-| `onClipboardTextReceived` | A method that sets the `clipboardTextReceived` [event handler](#event-handling). |
-| `readTextFromClipboard` | |
diff --git a/docs/mini-apps/composables/use-web-app-navigation.md b/docs/mini-apps/composables/use-web-app-navigation.md
deleted file mode 100644
index 25153dd..0000000
--- a/docs/mini-apps/composables/use-web-app-navigation.md
+++ /dev/null
@@ -1,14 +0,0 @@
-### useWebAppNavigation
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppNavigation } from 'vue-tg'
-```
-
-| Name | Type |
-| :------------------ | :---------------------------------------------------------------------------------------------------------------- |
-| `onInvoiceClosed` | A method that sets the `invoiceClosed` [event handler](#event-handling). |
-| `openInvoice` | |
-| `openLink` | |
-| `openTelegramLink` | |
-| `switchInlineQuery` | |
diff --git a/docs/mini-apps/composables/use-web-app-popup.md b/docs/mini-apps/composables/use-web-app-popup.md
deleted file mode 100644
index 55f85fb..0000000
--- a/docs/mini-apps/composables/use-web-app-popup.md
+++ /dev/null
@@ -1,13 +0,0 @@
-### useWebAppPopup
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppPopup } from 'vue-tg'
-```
-
-| Name | Type |
-| :-------------- | :-------------------------------------------------------------------------------------------------------------- |
-| `onPopupClosed` | A method that sets the `popupClosed` [event handler](#event-handling). |
-| `showAlert` | |
-| `showConfirm` | |
-| `showPopup` | |
diff --git a/docs/mini-apps/composables/use-web-app-qr-scanner.md b/docs/mini-apps/composables/use-web-app-qr-scanner.md
deleted file mode 100644
index e02fab1..0000000
--- a/docs/mini-apps/composables/use-web-app-qr-scanner.md
+++ /dev/null
@@ -1,13 +0,0 @@
-### useWebAppQrScanner
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppQrScanner } from 'vue-tg'
-```
-
-| Name | Type |
-| :-------------------- | :-------------------------------------------------------------------------------------------------------------------- |
-| `showScanQrPopup` | |
-| `closeScanQrPopup` | |
-| `onQrTextReceived` | A method that sets the `qrTextReceived` [event handler](#event-handling). |
-| `onScanQrPopupClosed` | A method that sets the `scanQrPopupClosed` [event handler](#event-handling). |
diff --git a/docs/mini-apps/composables/use-web-app-requests.md b/docs/mini-apps/composables/use-web-app-requests.md
deleted file mode 100644
index c6f328e..0000000
--- a/docs/mini-apps/composables/use-web-app-requests.md
+++ /dev/null
@@ -1,13 +0,0 @@
-### useWebAppRequests
-
-```ts twoslash
-// Hover to inspect type
-import { useWebAppRequests } from 'vue-tg'
-```
-
-| Name | Type |
-| :----------------------- | :----------------------------------------------------------------------------------------------------------------------- |
-| `onContactRequested` | A method that sets the `contactRequested` [event handler](#event-handling). |
-| `onWriteAccessRequested` | A method that sets the `writeAccessRequested` [event handler](#event-handling). |
-| `requestContact` | |
-| `requestWriteAccess` | |
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 8de3dd7..a8d5bc8 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -2,6 +2,7 @@ import antfu from '@antfu/eslint-config'
export default antfu({
rules: {
+ 'ts/consistent-type-definitions': 'off',
'vue/valid-template-root': 'off',
'vue/require-component-is': 'off',
'vue/block-order': ['error', {
diff --git a/package-lock.json b/package-lock.json
index 3fe7af5..f3eaacb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,9 +8,6 @@
"name": "vue-tg",
"version": "0.8.0",
"license": "MIT",
- "dependencies": {
- "@types/telegram-web-app": "^7"
- },
"devDependencies": {
"@antfu/eslint-config": "^3.11.2",
"@shikijs/vitepress-twoslash": "^1.24.2",
@@ -2263,12 +2260,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/telegram-web-app": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@types/telegram-web-app/-/telegram-web-app-7.10.1.tgz",
- "integrity": "sha512-GKL659G6lnHRAt3Dt7L1Fa0dwvc+ZZQtJcYrJVJGwjvsbi/Rcp1qKs9pFwb34/KC04+J+TlQj4D7yKo10sBSEw==",
- "license": "MIT"
- },
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
diff --git a/package.json b/package.json
index f22e9be..8fba017 100644
--- a/package.json
+++ b/package.json
@@ -52,9 +52,6 @@
"peerDependencies": {
"vue": "^3"
},
- "dependencies": {
- "@types/telegram-web-app": "^7"
- },
"devDependencies": {
"@antfu/eslint-config": "^3.11.2",
"@shikijs/vitepress-twoslash": "^1.24.2",
diff --git a/scripts/generate-webapps-docs-snippets.ts b/scripts/generate-webapps-docs-snippets.ts
index cf4ca47..bddcf46 100644
--- a/scripts/generate-webapps-docs-snippets.ts
+++ b/scripts/generate-webapps-docs-snippets.ts
@@ -113,35 +113,55 @@ async function main() {
writeFileSync(`${OUTPUT_PATH}/WebApp-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const backButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(175)'))
+ const backButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(176)'))
for (const field of backButtonSection.fields) {
writeFileSync(`${OUTPUT_PATH}/BackButton-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const mainButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(179)'))
+ const mainButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(180)'))
for (const field of mainButtonSection.fields) {
writeFileSync(`${OUTPUT_PATH}/MainButton-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const settingsButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(183)'))
+ const settingsButtonSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(184)'))
for (const field of settingsButtonSection.fields) {
writeFileSync(`${OUTPUT_PATH}/SettingsButton-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const hapticFeedbackSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(187)'))
+ const hapticFeedbackSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(188)'))
for (const field of hapticFeedbackSection.fields) {
writeFileSync(`${OUTPUT_PATH}/HapticFeedback-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const cloudStorageSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(191)'))
+ const cloudStorageSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(192)'))
for (const field of cloudStorageSection.fields) {
writeFileSync(`${OUTPUT_PATH}/CloudStorage-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
- const biometricManagerSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(195)'))
+ const biometricManagerSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(196)'))
for (const field of biometricManagerSection.fields) {
writeFileSync(`${OUTPUT_PATH}/BiometricManager-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
}
+
+ const accelerometerSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(206)'))
+ for (const field of accelerometerSection.fields) {
+ writeFileSync(`${OUTPUT_PATH}/Accelerometer-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
+ }
+
+ const deviceOrientationSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(214)'))
+ for (const field of deviceOrientationSection.fields) {
+ writeFileSync(`${OUTPUT_PATH}/DeviceOrientation-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
+ }
+
+ const gyroscopeSection = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(222)'))
+ for (const field of gyroscopeSection.fields) {
+ writeFileSync(`${OUTPUT_PATH}/Gyroscope-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
+ }
+
+ const locationManager = parseSection(dom.window.document.querySelector('#dev_page_content > h4:nth-child(230)'))
+ for (const field of locationManager.fields) {
+ writeFileSync(`${OUTPUT_PATH}/LocationManager-${normalizeFieldName(field.name)}.md`, preprocessDescription(field.description))
+ }
}
main()
diff --git a/src/components/Alert.vue b/src/components/Alert.vue
index e19ff24..8b3e619 100644
--- a/src/components/Alert.vue
+++ b/src/components/Alert.vue
@@ -2,7 +2,7 @@
diff --git a/src/components/BackButton.vue b/src/components/BackButton.vue
index 31ebe05..90488dd 100644
--- a/src/components/BackButton.vue
+++ b/src/components/BackButton.vue
@@ -2,7 +2,7 @@
diff --git a/src/components/BiometricManager.vue b/src/components/BiometricManager.vue
index 73bba39..7655e1b 100644
--- a/src/components/BiometricManager.vue
+++ b/src/components/BiometricManager.vue
@@ -2,13 +2,15 @@
diff --git a/src/components/ClosingConfirmation.vue b/src/components/ClosingConfirmation.vue
index 96b58ed..c8b108c 100644
--- a/src/components/ClosingConfirmation.vue
+++ b/src/components/ClosingConfirmation.vue
@@ -2,12 +2,17 @@
diff --git a/src/components/Confirm.vue b/src/components/Confirm.vue
index 6fc8159..140b7f4 100644
--- a/src/components/Confirm.vue
+++ b/src/components/Confirm.vue
@@ -2,7 +2,7 @@
diff --git a/src/components/ExpandedViewport.vue b/src/components/ExpandedViewport.vue
index af8344c..afe2a4c 100644
--- a/src/components/ExpandedViewport.vue
+++ b/src/components/ExpandedViewport.vue
@@ -2,22 +2,21 @@
diff --git a/src/components/MainButton.vue b/src/components/MainButton.vue
index ea1f641..7218abe 100644
--- a/src/components/MainButton.vue
+++ b/src/components/MainButton.vue
@@ -2,7 +2,7 @@
diff --git a/src/components/Popup.vue b/src/components/Popup.vue
index 63da9f8..a953718 100644
--- a/src/components/Popup.vue
+++ b/src/components/Popup.vue
@@ -2,8 +2,9 @@
diff --git a/src/components/ScanQr.vue b/src/components/ScanQr.vue
index 553fcc0..22df0fe 100644
--- a/src/components/ScanQr.vue
+++ b/src/components/ScanQr.vue
@@ -2,7 +2,7 @@
diff --git a/src/components/SecondaryButton.vue b/src/components/SecondaryButton.vue
new file mode 100644
index 0000000..447ca32
--- /dev/null
+++ b/src/components/SecondaryButton.vue
@@ -0,0 +1,118 @@
+
+
+
diff --git a/src/components/SettingsButton.vue b/src/components/SettingsButton.vue
index 15d6dae..b098682 100644
--- a/src/components/SettingsButton.vue
+++ b/src/components/SettingsButton.vue
@@ -2,7 +2,7 @@
diff --git a/src/composables-legacy/index.ts b/src/composables-legacy/index.ts
new file mode 100644
index 0000000..1d2774d
--- /dev/null
+++ b/src/composables-legacy/index.ts
@@ -0,0 +1,17 @@
+export { useWebApp } from './useWebApp'
+export { useWebAppBackButton } from './useWebAppBackButton'
+export { useWebAppBiometricManager } from './useWebAppBiometricManager'
+export { useWebAppClipboard } from './useWebAppClipboard'
+export { useWebAppClosingConfirmation } from './useWebAppClosingConfirmation'
+export { useWebAppCloudStorage } from './useWebAppCloudStorage'
+export { useWebAppHapticFeedback } from './useWebAppHapticFeedback'
+export { useWebAppMainButton } from './useWebAppMainButton'
+export { useWebAppNavigation } from './useWebAppNavigation'
+export { useWebAppPopup } from './useWebAppPopup'
+export { useWebAppQrScanner } from './useWebAppQrScanner'
+export { useWebAppRequests } from './useWebAppRequests'
+export { useWebAppSendData } from './useWebAppSendData'
+export { useWebAppSettingsButton } from './useWebAppSettingsButton'
+export { useWebAppShare } from './useWebAppShare'
+export { useWebAppTheme } from './useWebAppTheme'
+export { useWebAppViewport } from './useWebAppViewport'
diff --git a/src/composables-legacy/useWebApp.ts b/src/composables-legacy/useWebApp.ts
new file mode 100644
index 0000000..409fdee
--- /dev/null
+++ b/src/composables-legacy/useWebApp.ts
@@ -0,0 +1,61 @@
+import { useMiniApp } from '../composables/useMiniApp'
+import { onEvent } from '../events'
+import { getWebApp } from '../sdk'
+
+const featureSupportVersion = {
+ ClosingConfirmation: '6.2',
+ CloudStorage: '6.9',
+ RequestWriteAccess: '6.9',
+ RequestContact: '6.9',
+ SettingsButton: '7.0',
+ BiometricManager: '7.2',
+ DisableVerticalSwipes: '7.7',
+}
+function isFeatureSupported(name: keyof typeof featureSupportVersion) {
+ return getWebApp().isVersionAtLeast(featureSupportVersion[name])
+}
+
+/**
+ * @deprecated Use [`useMiniApp`](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) instead
+ */
+export function useWebApp() {
+ const webApp = getWebApp()
+ const {
+ initData,
+ initDataUnsafe,
+ version,
+ isReady,
+ platform,
+ isPlatform,
+ sendData,
+ ready,
+ close,
+ } = useMiniApp({ version: '8.0' })
+
+ const isPlatformUnknown = isPlatform('unknown')
+
+ const canSendData = !isPlatformUnknown && initData === ''
+
+ return {
+ initData,
+ initDataUnsafe,
+ version,
+ platform,
+ isVersionAtLeast: webApp.isVersionAtLeast,
+ sendData,
+ ready,
+ close,
+ isReady,
+ isPlatform,
+ isPlatformUnknown,
+ isFeatureSupported,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onEvent,
+ /**
+ * @deprecated
+ */
+ canSendData,
+ }
+}
diff --git a/src/composables-legacy/useWebAppBackButton.ts b/src/composables-legacy/useWebAppBackButton.ts
new file mode 100644
index 0000000..a694a99
--- /dev/null
+++ b/src/composables-legacy/useWebAppBackButton.ts
@@ -0,0 +1,19 @@
+import { useBackButton } from '../composables/useBackButton'
+import { onBackButtonClicked } from '../events'
+
+/**
+ * @deprecated Use [`useBackButton`](https://vue-tg.deptyped.com/mini-apps.html#usebackbutton) instead
+ */
+export function useWebAppBackButton() {
+ const backButton = useBackButton({ version: '8.0' })
+
+ return {
+ isBackButtonVisible: backButton.isVisible,
+ showBackButton: backButton.show,
+ hideBackButton: backButton.hide,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onBackButtonClicked,
+ }
+}
diff --git a/src/composables-legacy/useWebAppBiometricManager.ts b/src/composables-legacy/useWebAppBiometricManager.ts
new file mode 100644
index 0000000..bac1251
--- /dev/null
+++ b/src/composables-legacy/useWebAppBiometricManager.ts
@@ -0,0 +1,49 @@
+import { useBiometricManager } from '../composables/useBiometricManager'
+import { onBiometricAuthRequested, onBiometricManagerUpdated, onBiometricTokenUpdated } from '../events'
+
+/**
+ * @deprecated Use [`useBiometricManager`](https://vue-tg.deptyped.com/mini-apps.html#usebiometricmanager) instead
+ */
+export function useWebAppBiometricManager() {
+ const {
+ isInited,
+ isBiometricAvailable,
+ biometricType,
+ isAccessRequested,
+ isAccessGranted,
+ deviceId,
+ isBiometricTokenSaved,
+ init,
+ authenticate,
+ requestAccess,
+ openSettings,
+ updateToken,
+ } = useBiometricManager({ version: '8.0' })
+
+ return {
+ isBiometricInited: isInited,
+ isBiometricAvailable,
+ biometricType,
+ isBiometricAccessRequested: isAccessRequested,
+ isBiometricAccessGranted: isAccessGranted,
+ isBiometricTokenSaved,
+ biometricDeviceId: deviceId,
+ initBiometric: init,
+ requestBiometricAccess: requestAccess,
+ authenticateBiometric: authenticate,
+ updateBiometricToken: updateToken,
+ openBiometricSettings: openSettings,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onBiometricManagerUpdated,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onBiometricAuthRequested,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onBiometricTokenUpdated,
+ }
+}
diff --git a/src/composables-legacy/useWebAppClipboard.ts b/src/composables-legacy/useWebAppClipboard.ts
new file mode 100644
index 0000000..bab2f40
--- /dev/null
+++ b/src/composables-legacy/useWebAppClipboard.ts
@@ -0,0 +1,17 @@
+import { useClipboard } from '../composables/useClipboard'
+import { onClipboardTextReceived } from '../events'
+
+/**
+ * @deprecated Use [`useClipboard`](https://vue-tg.deptyped.com/mini-apps.html#useclipboard) instead
+ */
+export function useWebAppClipboard() {
+ const { readText } = useClipboard({ version: '8.0' })
+
+ return {
+ readTextFromClipboard: readText,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onClipboardTextReceived,
+ }
+}
diff --git a/src/composables-legacy/useWebAppClosingConfirmation.ts b/src/composables-legacy/useWebAppClosingConfirmation.ts
new file mode 100644
index 0000000..56b02f0
--- /dev/null
+++ b/src/composables-legacy/useWebAppClosingConfirmation.ts
@@ -0,0 +1,18 @@
+import { useMiniApp } from '../composables/useMiniApp'
+
+/**
+ * @deprecated Use [`useClosingConfirmation`](https://vue-tg.deptyped.com/mini-apps.html#useclosingconfirmation) instead
+ */
+export function useWebAppClosingConfirmation() {
+ const { isClosingConfirmationEnabled } = useMiniApp({ version: '8.0' })
+
+ return {
+ isClosingConfirmationEnabled,
+ enableClosingConfirmation() {
+ isClosingConfirmationEnabled.value = true
+ },
+ disableClosingConfirmation() {
+ isClosingConfirmationEnabled.value = false
+ },
+ }
+}
diff --git a/src/composables-legacy/useWebAppCloudStorage.ts b/src/composables-legacy/useWebAppCloudStorage.ts
new file mode 100644
index 0000000..04f2019
--- /dev/null
+++ b/src/composables-legacy/useWebAppCloudStorage.ts
@@ -0,0 +1,17 @@
+import { useCloudStorage } from '../composables/useCloudStorage'
+
+/**
+ * @deprecated Use [`useCloudStorage`](https://vue-tg.deptyped.com/mini-apps.html#usecloudstorage) instead
+ */
+export function useWebAppCloudStorage() {
+ const cloudStorage = useCloudStorage({ version: '8.0' })
+
+ return {
+ setStorageItem: cloudStorage.setItem,
+ getStorageItem: cloudStorage.getItem,
+ getStorageItems: cloudStorage.getItems,
+ removeStorageItem: cloudStorage.removeItem,
+ removeStorageItems: cloudStorage.removeItems,
+ getStorageKeys: cloudStorage.getKeys,
+ }
+}
diff --git a/src/composables-legacy/useWebAppHapticFeedback.ts b/src/composables-legacy/useWebAppHapticFeedback.ts
new file mode 100644
index 0000000..4f4dceb
--- /dev/null
+++ b/src/composables-legacy/useWebAppHapticFeedback.ts
@@ -0,0 +1,14 @@
+import { useHapticFeedback } from '../composables/useHapticFeedback'
+
+/**
+ * @deprecated Use [`useHapticFeedback`](https://vue-tg.deptyped.com/mini-apps.html#usehapticfeedback) instead
+ */
+export function useWebAppHapticFeedback() {
+ const { impactOccurred, notificationOccurred, selectionChanged } = useHapticFeedback({ version: '8.0' })
+
+ return {
+ impactOccurred,
+ notificationOccurred,
+ selectionChanged,
+ }
+}
diff --git a/src/composables-legacy/useWebAppMainButton.ts b/src/composables-legacy/useWebAppMainButton.ts
new file mode 100644
index 0000000..f1359b8
--- /dev/null
+++ b/src/composables-legacy/useWebAppMainButton.ts
@@ -0,0 +1,33 @@
+import type { WebApp } from '../sdk'
+import { useMainButton } from '../composables/useMainButton'
+import { onMainButtonClicked } from '../events'
+
+/**
+ * @deprecated Use [`useMainButton`](https://vue-tg.deptyped.com/mini-apps.html#usemainbutton) instead
+ */
+export function useWebAppMainButton() {
+ const mainButton = useMainButton({ version: '8.0' })
+
+ return {
+ mainButtonText: mainButton.text,
+ mainButtonColor: mainButton.color,
+ mainButtonTextColor: mainButton.textColor,
+ isMainButtonVisible: mainButton.isVisible,
+ isMainButtonActive: mainButton.isActive,
+ isMainButtonProgressVisible: mainButton.isProgressVisible,
+ setMainButtonText(text: Parameters[0]) {
+ mainButton.text.value = text
+ },
+ showMainButton: mainButton.show,
+ hideMainButton: mainButton.hide,
+ enableMainButton: mainButton.enable,
+ disableMainButton: mainButton.disable,
+ showMainButtonProgress: mainButton.showProgress,
+ hideMainButtonProgress: mainButton.hideProgress,
+ setMainButtonParams: mainButton.setParams,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onMainButtonClicked,
+ }
+}
diff --git a/src/composables-legacy/useWebAppNavigation.ts b/src/composables-legacy/useWebAppNavigation.ts
new file mode 100644
index 0000000..2a3a107
--- /dev/null
+++ b/src/composables-legacy/useWebAppNavigation.ts
@@ -0,0 +1,20 @@
+import { useMiniApp } from '../composables/useMiniApp'
+import { onInvoiceClosed } from '../events'
+
+/**
+ * @deprecated Use [`useMiniApp`](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) instead
+ */
+export function useWebAppNavigation() {
+ const { switchInlineQuery, openLink, openTelegramLink, openInvoice } = useMiniApp({ version: '8.0' })
+
+ return {
+ switchInlineQuery,
+ openLink,
+ openTelegramLink,
+ openInvoice,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onInvoiceClosed,
+ }
+}
diff --git a/src/composables-legacy/useWebAppPopup.ts b/src/composables-legacy/useWebAppPopup.ts
new file mode 100644
index 0000000..0a98447
--- /dev/null
+++ b/src/composables-legacy/useWebAppPopup.ts
@@ -0,0 +1,19 @@
+import { usePopup } from '../composables/usePopup'
+import { onPopupClosed } from '../events'
+
+/**
+ * @deprecated Use [`usePopup`](https://vue-tg.deptyped.com/mini-apps.html#usepopup) instead
+ */
+export function useWebAppPopup() {
+ const { showPopup, showAlert, showConfirm } = usePopup({ version: '8.0' })
+
+ return {
+ showPopup,
+ showAlert,
+ showConfirm,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onPopupClosed,
+ }
+}
diff --git a/src/composables-legacy/useWebAppQrScanner.ts b/src/composables-legacy/useWebAppQrScanner.ts
new file mode 100644
index 0000000..ea827f6
--- /dev/null
+++ b/src/composables-legacy/useWebAppQrScanner.ts
@@ -0,0 +1,22 @@
+import { useQrScanner } from '../composables/useQrScanner'
+import { onQrTextReceived, onScanQrPopupClosed } from '../events'
+
+/**
+ * @deprecated Use [`useQrScanner`](https://vue-tg.deptyped.com/mini-apps.html#useqrscanner) instead
+ */
+export function useWebAppQrScanner() {
+ const qrScanner = useQrScanner({ version: '8.0' })
+
+ return {
+ showScanQrPopup: qrScanner.show,
+ closeScanQrPopup: qrScanner.close,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onQrTextReceived,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onScanQrPopupClosed,
+ }
+}
diff --git a/src/composables-legacy/useWebAppRequests.ts b/src/composables-legacy/useWebAppRequests.ts
new file mode 100644
index 0000000..c5c44e6
--- /dev/null
+++ b/src/composables-legacy/useWebAppRequests.ts
@@ -0,0 +1,22 @@
+import { useMiniApp } from '../composables/useMiniApp'
+import { onContactRequested, onWriteAccessRequested } from '../events'
+
+/**
+ * @deprecated Use [`useMiniApp`](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) instead
+ */
+export function useWebAppRequests() {
+ const { requestContact, requestWriteAccess } = useMiniApp({ version: '8.0' })
+
+ return {
+ requestContact,
+ requestWriteAccess,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onContactRequested,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onWriteAccessRequested,
+ }
+}
diff --git a/src/composables/useWebAppSendData.ts b/src/composables-legacy/useWebAppSendData.ts
similarity index 90%
rename from src/composables/useWebAppSendData.ts
rename to src/composables-legacy/useWebAppSendData.ts
index bd2f279..c81cc8d 100644
--- a/src/composables/useWebAppSendData.ts
+++ b/src/composables-legacy/useWebAppSendData.ts
@@ -1,5 +1,5 @@
import { ref } from 'vue'
-import { useWebApp } from './useWebApp'
+import { useMiniApp } from '../composables/useMiniApp'
/**
* @deprecated
@@ -20,7 +20,7 @@ export function useWebAppSendData(
const isLoading = ref(false)
- const { initData, initDataUnsafe, sendData, close } = useWebApp()
+ const { initData, initDataUnsafe, sendData, close } = useMiniApp({ version: '8.0' })
return {
error,
diff --git a/src/composables-legacy/useWebAppSettingsButton.ts b/src/composables-legacy/useWebAppSettingsButton.ts
new file mode 100644
index 0000000..a66f443
--- /dev/null
+++ b/src/composables-legacy/useWebAppSettingsButton.ts
@@ -0,0 +1,19 @@
+import { useSettingsButton } from '../composables/useSettingsButton'
+import { onSettingsButtonClicked } from '../events'
+
+/**
+ * @deprecated Use [`useSettingsButton`](https://vue-tg.deptyped.com/mini-apps.html#usesettingsbutton) instead
+ */
+export function useWebAppSettingsButton() {
+ const settingsButton = useSettingsButton({ version: '8.0' })
+
+ return {
+ isSettingsButtonVisible: settingsButton.isVisible,
+ showSettingsButton: settingsButton.show,
+ hideSettingsButton: settingsButton.hide,
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onSettingsButtonClicked,
+ }
+}
diff --git a/src/composables-legacy/useWebAppShare.ts b/src/composables-legacy/useWebAppShare.ts
new file mode 100644
index 0000000..cc5b82f
--- /dev/null
+++ b/src/composables-legacy/useWebAppShare.ts
@@ -0,0 +1,12 @@
+import { useMiniApp } from '../composables/useMiniApp'
+
+/**
+ * @deprecated Use [`useMiniApp`](https://vue-tg.deptyped.com/mini-apps.html#useminiapp) instead
+ */
+export function useWebAppShare() {
+ const { shareToStory } = useMiniApp({ version: '8.0' })
+
+ return {
+ shareToStory,
+ }
+}
diff --git a/src/composables-legacy/useWebAppTheme.ts b/src/composables-legacy/useWebAppTheme.ts
new file mode 100644
index 0000000..77b7ddb
--- /dev/null
+++ b/src/composables-legacy/useWebAppTheme.ts
@@ -0,0 +1,32 @@
+import type { WebApp } from '../sdk'
+import { useTheme } from '../composables/useTheme'
+import { onThemeChanged } from '../events'
+
+/**
+ * @deprecated Use [`useTheme`](https://vue-tg.deptyped.com/mini-apps.html#usetheme) instead
+ */
+export function useWebAppTheme() {
+ const {
+ colorScheme,
+ themeParams,
+ headerColor,
+ backgroundColor,
+ } = useTheme({ version: '8.0' })
+
+ return {
+ colorScheme,
+ themeParams,
+ headerColor,
+ backgroundColor,
+ setHeaderColor(color: Parameters[0]) {
+ headerColor.value = color
+ },
+ setBackgroundColor(color: Parameters[0]) {
+ backgroundColor.value = color
+ },
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onThemeChanged,
+ }
+}
diff --git a/src/composables-legacy/useWebAppViewport.ts b/src/composables-legacy/useWebAppViewport.ts
new file mode 100644
index 0000000..c49a0a0
--- /dev/null
+++ b/src/composables-legacy/useWebAppViewport.ts
@@ -0,0 +1,33 @@
+import { useViewport } from '../composables/useViewport'
+import { onViewportChanged } from '../events'
+
+/**
+ * @deprecated Use [`useViewport`](https://vue-tg.deptyped.com/mini-apps.html#useviewport) instead
+ */
+export function useWebAppViewport() {
+ const {
+ isExpanded,
+ expand,
+ viewportHeight,
+ viewportStableHeight,
+ isVerticalSwipesEnabled,
+ } = useViewport({ version: '8.0' })
+
+ return {
+ isExpanded,
+ viewportHeight,
+ viewportStableHeight,
+ expand,
+ isVerticalSwipesEnabled,
+ enableVerticalSwipes() {
+ isVerticalSwipesEnabled.value = true
+ },
+ disableVerticalSwipes() {
+ isVerticalSwipesEnabled.value = false
+ },
+ /**
+ * @deprecated import directly from `vue-tg` instead.
+ */
+ onViewportChanged,
+ }
+}
diff --git a/src/composables/useAccelerometer.ts b/src/composables/useAccelerometer.ts
new file mode 100644
index 0000000..7f6c2e6
--- /dev/null
+++ b/src/composables/useAccelerometer.ts
@@ -0,0 +1,126 @@
+import type { AccelerometerCallback, AccelerometerStartParams } from '../sdk'
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { readonly, ref } from 'vue'
+import { onAccelerometerChanged, onAccelerometerFailed, onAccelerometerStarted, onAccelerometerStopped } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type AccelerometerV60 = ReturnType
+type AccelerometerV80 = ReturnType
+
+type AccelerometerV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version } & AccelerometerV60
+ >;
+}
+
+type AccelerometerV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ AccelerometerV60to80['6.0'],
+ { version: version } & AccelerometerV80
+ >;
+}
+
+type Accelerometer =
+ & AccelerometerV60to80
+ & AccelerometerV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ const isStarted = ref(webApp.Accelerometer.isStarted)
+ const x = ref(webApp.Accelerometer.x)
+ const y = ref(webApp.Accelerometer.y)
+ const z = ref(webApp.Accelerometer.z)
+
+ const updateState = () => {
+ isStarted.value = webApp.Accelerometer.isStarted
+ x.value = webApp.Accelerometer.x
+ y.value = webApp.Accelerometer.y
+ z.value = webApp.Accelerometer.z
+ }
+
+ return {
+ webApp,
+ updateState,
+ isStarted,
+ x,
+ y,
+ z,
+ }
+})
+
+function useAccelerometer60() {
+ const {
+ isStarted,
+ x,
+ y,
+ z,
+ } = useStore()
+
+ return {
+ isStarted: readonly(isStarted),
+ x: readonly(x),
+ y: readonly(y),
+ z: readonly(z),
+ }
+}
+
+function useAccelerometer80() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const startAsync = promisify(webApp.Accelerometer.start)
+
+ function start(params: AccelerometerStartParams): ReturnType
+ function start(params: AccelerometerStartParams, callback?: AccelerometerCallback['start']): void
+ function start(params: AccelerometerStartParams, callback?: AccelerometerCallback['start']): ReturnType | void {
+ if (callback)
+ webApp.Accelerometer.start(params, callback)
+ else
+ return startAsync(params)
+ }
+
+ const stopAsync = promisify(webApp.Accelerometer.stop)
+
+ function stop(): ReturnType
+ function stop(callback?: AccelerometerCallback['stop']): void
+ function stop(callback?: AccelerometerCallback['stop']): ReturnType | void {
+ if (callback)
+ webApp.Accelerometer.stop(callback)
+ else
+ return stopAsync()
+ }
+
+ onAccelerometerChanged(updateState)
+ onAccelerometerFailed(updateState)
+
+ return {
+ start,
+ stop,
+ onStart: onAccelerometerStarted,
+ onStop: onAccelerometerStopped,
+ onChange: onAccelerometerChanged,
+ onFail: onAccelerometerFailed,
+ }
+}
+
+export function useAccelerometer(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useAccelerometer60(),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useAccelerometer80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useBackButton.ts b/src/composables/useBackButton.ts
new file mode 100644
index 0000000..906d44c
--- /dev/null
+++ b/src/composables/useBackButton.ts
@@ -0,0 +1,106 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onBackButtonClicked } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type BackButtonV60 = ReturnType
+type BackButtonV61 = ReturnType
+
+type BackButtonV60to61 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.1'>>]: Merge<
+ Partial,
+ { version: version } & BackButtonV60
+ >;
+}
+
+type BackButtonV61toLatest = {
+ [version in BotApiVersionRange<'6.1', LATEST_VERSION>]: Merge<
+ BackButtonV60to61['6.0'],
+ { version: version } & BackButtonV61
+ >;
+}
+
+type BackButton =
+ & BackButtonV60to61
+ & BackButtonV61toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const isVisible = ref(webApp.BackButton.isVisible)
+
+ const updateState = () => {
+ isVisible.value = webApp.BackButton.isVisible
+ }
+
+ return {
+ webApp,
+ isVisible,
+ updateState,
+ }
+})
+
+function useBackButton60() {
+ const {
+ isVisible,
+ } = useStore()
+
+ return {
+ isVisible: readonly(isVisible),
+ }
+}
+
+function useBackButton61() {
+ const {
+ webApp,
+ isVisible,
+ updateState,
+ } = useStore()
+
+ const show = wrapFunction(webApp.BackButton.show, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const hide = wrapFunction(webApp.BackButton.hide, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+
+ return {
+ isVisible: computed({
+ get() {
+ return isVisible.value
+ },
+ set(isVisible) {
+ if (isVisible)
+ show()
+ else
+ hide()
+ },
+ }),
+ show,
+ hide,
+ onClick: onBackButtonClicked,
+ }
+}
+
+export function useBackButton(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useBackButton60(),
+ ...(isVersionGreaterOrEqual(version, '6.1')
+ ? useBackButton61()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useBiometricManager.ts b/src/composables/useBiometricManager.ts
new file mode 100644
index 0000000..45b6df1
--- /dev/null
+++ b/src/composables/useBiometricManager.ts
@@ -0,0 +1,171 @@
+import type { BiometricAuthenticateParams, BiometricManagerCallback, BiometricRequestAccessParams } from '../sdk'
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { readonly, ref } from 'vue'
+import { onBiometricAuthRequested, onBiometricManagerUpdated, onBiometricTokenUpdated } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify, promisifyWithDataObject, promisifyWithNoData, wrapFunction } from '../utils'
+
+type BiometricManagerV60 = ReturnType
+type BiometricManagerV72 = ReturnType
+
+type BiometricManagerV60to72 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'7.2'>>]: Merge<
+ Partial,
+ { version: version } & BiometricManagerV60
+ >;
+}
+
+type BiometricManagerV72toLatest = {
+ [version in BotApiVersionRange<'7.2', LATEST_VERSION>]: Merge<
+ BiometricManagerV60to72['6.0'],
+ { version: version } & BiometricManagerV72
+ >;
+}
+
+type BiometricManager =
+ & BiometricManagerV60to72
+ & BiometricManagerV72toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ const isInited = ref(webApp.BiometricManager.isInited)
+ const isBiometricAvailable = ref(webApp.BiometricManager.isBiometricAvailable)
+ const biometricType = ref(webApp.BiometricManager.biometricType)
+ const isAccessRequested = ref(webApp.BiometricManager.isAccessRequested)
+ const isAccessGranted = ref(webApp.BiometricManager.isAccessGranted)
+ const isBiometricTokenSaved = ref(webApp.BiometricManager.isBiometricTokenSaved)
+ const deviceId = ref(webApp.BiometricManager.deviceId)
+
+ const updateState = () => {
+ isInited.value = webApp.BiometricManager.isInited
+ isBiometricAvailable.value = webApp.BiometricManager.isBiometricAvailable
+ biometricType.value = webApp.BiometricManager.biometricType
+ isAccessRequested.value = webApp.BiometricManager.isAccessRequested
+ isAccessGranted.value = webApp.BiometricManager.isAccessGranted
+ isBiometricTokenSaved.value = webApp.BiometricManager.isBiometricTokenSaved
+ deviceId.value = webApp.BiometricManager.deviceId
+ }
+
+ return {
+ webApp,
+ updateState,
+ isInited,
+ isBiometricAvailable,
+ biometricType,
+ isAccessRequested,
+ isAccessGranted,
+ isBiometricTokenSaved,
+ deviceId,
+ }
+})
+
+function useBiometricManager60() {
+ const {
+ isInited,
+ isBiometricAvailable,
+ biometricType,
+ isAccessRequested,
+ isAccessGranted,
+ isBiometricTokenSaved,
+ deviceId,
+ } = useStore()
+
+ return {
+ isInited: readonly(isInited),
+ isBiometricAvailable: readonly(isBiometricAvailable),
+ biometricType: readonly(biometricType),
+ isAccessRequested: readonly(isAccessRequested),
+ isAccessGranted: readonly(isAccessGranted),
+ isBiometricTokenSaved: readonly(isBiometricTokenSaved),
+ deviceId: readonly(deviceId),
+ }
+}
+
+function useBiometricManager72() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const initAsync = promisifyWithNoData(webApp.BiometricManager.init)
+
+ function init(): ReturnType
+ function init(callback?: BiometricManagerCallback['init']): void
+ function init(callback?: BiometricManagerCallback['init']): ReturnType | void {
+ if (callback)
+ webApp.BiometricManager.init(callback)
+ else
+ return initAsync()
+ }
+
+ const requestAccessAsync = promisify(webApp.BiometricManager.requestAccess)
+
+ function requestAccess(params: BiometricRequestAccessParams): ReturnType
+ function requestAccess(params: BiometricRequestAccessParams, callback?: BiometricManagerCallback['requestAccess']): void
+ function requestAccess(params: BiometricRequestAccessParams, callback?: BiometricManagerCallback['requestAccess']): ReturnType | void {
+ if (callback)
+ webApp.BiometricManager.requestAccess(params, callback)
+ else
+ return requestAccessAsync(params)
+ }
+
+ const authenticateAsync = promisifyWithDataObject(
+ webApp.BiometricManager.authenticate,
+ (isAuthenticated: boolean, token?: string) => ({ isAuthenticated, token }),
+ )
+
+ function authenticate(params: BiometricAuthenticateParams): ReturnType
+ function authenticate(params: BiometricAuthenticateParams, callback?: BiometricManagerCallback['authenticate']): void
+ function authenticate(params: BiometricAuthenticateParams, callback?: BiometricManagerCallback['authenticate']): ReturnType | void {
+ if (callback)
+ webApp.BiometricManager.authenticate(params, callback)
+ else
+ return authenticateAsync(params)
+ }
+
+ const updateBiometricTokenAsync = promisify(webApp.BiometricManager.updateBiometricToken)
+
+ function updateBiometricToken(token: string,): ReturnType
+ function updateBiometricToken(token: string, callback?: BiometricManagerCallback['updateBiometricToken']): void
+ function updateBiometricToken(token: string, callback?: BiometricManagerCallback['updateBiometricToken']): ReturnType | void {
+ if (callback)
+ webApp.BiometricManager.updateBiometricToken(token, callback)
+ else
+ return updateBiometricTokenAsync(token)
+ }
+
+ onBiometricManagerUpdated(updateState)
+ onBiometricAuthRequested(updateState)
+ onBiometricTokenUpdated(updateState)
+
+ return {
+ init,
+ requestAccess,
+ authenticate,
+ updateToken: updateBiometricToken,
+ openSettings: wrapFunction(webApp.BiometricManager.openSettings, {
+ omitReturn: true,
+ }),
+ onManagerUpdate: onBiometricManagerUpdated,
+ onAuthRequest: onBiometricAuthRequested,
+ onTokenUpdate: onBiometricTokenUpdated,
+ }
+}
+
+export function useBiometricManager(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useBiometricManager60(),
+ ...(isVersionGreaterOrEqual(version, '7.2')
+ ? useBiometricManager72()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useClipboard.ts b/src/composables/useClipboard.ts
new file mode 100644
index 0000000..58fbeb0
--- /dev/null
+++ b/src/composables/useClipboard.ts
@@ -0,0 +1,71 @@
+import type { WebAppCallback } from '../sdk'
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { onClipboardTextReceived } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type ClipboardV64 = ReturnType
+
+type ClipboardV60to64 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.4'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type ClipboardV64toLatest = {
+ [version in BotApiVersionRange<'6.4', LATEST_VERSION>]: Merge<
+ ClipboardV60to64['6.0'],
+ { version: version } & ClipboardV64
+ >;
+}
+
+type Clipboard =
+ & ClipboardV60to64
+ & ClipboardV64toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useClipboard64() {
+ const {
+ webApp,
+ } = useStore()
+
+ const readTextFromClipboardAsync = promisify(webApp.readTextFromClipboard)
+
+ function readTextFromClipboard(): ReturnType
+ function readTextFromClipboard(callback?: WebAppCallback['readTextFromClipboard']): void
+ function readTextFromClipboard(callback?: WebAppCallback['readTextFromClipboard']): ReturnType | void {
+ if (callback)
+ webApp.readTextFromClipboard(callback)
+ else
+ return readTextFromClipboardAsync()
+ }
+
+ return {
+ readText: readTextFromClipboard,
+ onReadText: onClipboardTextReceived,
+ }
+}
+
+export function useClipboard(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '6.4')
+ ? useClipboard64()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useCloudStorage.ts b/src/composables/useCloudStorage.ts
new file mode 100644
index 0000000..52fdb44
--- /dev/null
+++ b/src/composables/useCloudStorage.ts
@@ -0,0 +1,129 @@
+import type { CloudStorageCallback } from '../sdk'
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisifyWithError } from '../utils'
+
+type CloudStorageV69 = ReturnType
+
+type CloudStorageV60to69 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.9'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type CloudStorageV69toLatest = {
+ [version in BotApiVersionRange<'6.9', LATEST_VERSION>]: Merge<
+ CloudStorageV60to69['6.0'],
+ { version: version } & CloudStorageV69
+ >;
+}
+
+type CloudStorage =
+ & CloudStorageV60to69
+ & CloudStorageV69toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useCloudStorage69() {
+ const {
+ webApp,
+ } = useStore()
+
+ const setItemAsync = promisifyWithError(webApp.CloudStorage.setItem)
+
+ function setItem(key: string, value: string): ReturnType
+ function setItem(key: string, value: string, callback?: CloudStorageCallback['setItem']): void
+ function setItem(key: string, value: string, callback?: CloudStorageCallback['setItem']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.setItem(key, value, callback)
+ else
+ return setItemAsync(key, value)
+ }
+
+ const getItemAsync = promisifyWithError(webApp.CloudStorage.getItem)
+
+ function getItem(key: string): ReturnType
+ function getItem(key: string, callback?: CloudStorageCallback['getItem']): void
+ function getItem(key: string, callback?: CloudStorageCallback['getItem']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.getItem(key, callback)
+ else
+ return getItemAsync(key)
+ }
+
+ const getItemsAsync = promisifyWithError(webApp.CloudStorage.getItems)
+
+ function getItems(keys: string[]): ReturnType
+ function getItems(keys: string[], callback?: CloudStorageCallback['getItems']): void
+ function getItems(keys: string[], callback?: CloudStorageCallback['getItems']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.getItems(keys, callback)
+ else
+ return getItemsAsync(keys)
+ }
+
+ const removeItemAsync = promisifyWithError(webApp.CloudStorage.removeItem)
+
+ function removeItem(key: string): ReturnType
+ function removeItem(key: string, callback?: CloudStorageCallback['removeItem']): void
+ function removeItem(key: string, callback?: CloudStorageCallback['removeItem']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.removeItem(key, callback)
+ else
+ return removeItemAsync(key)
+ }
+
+ const removeItemsAsync = promisifyWithError(webApp.CloudStorage.removeItems)
+
+ function removeItems(keys: string[]): ReturnType
+ function removeItems(keys: string[], callback?: CloudStorageCallback['removeItems']): void
+ function removeItems(keys: string[], callback?: CloudStorageCallback['removeItems']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.removeItems(keys, callback)
+ else
+ return removeItemsAsync(keys)
+ }
+
+ const getKeysAsync = promisifyWithError(webApp.CloudStorage.getKeys)
+
+ function getKeys(): ReturnType
+ function getKeys(callback?: CloudStorageCallback['getKeys']): void
+ function getKeys(callback?: CloudStorageCallback['getKeys']): ReturnType | void {
+ if (callback)
+ webApp.CloudStorage.getKeys(callback)
+ else
+ return getKeysAsync()
+ }
+
+ return {
+ setItem,
+ getItem,
+ getItems,
+ removeItem,
+ removeItems,
+ getKeys,
+ }
+}
+
+export function useCloudStorage(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '6.9')
+ ? useCloudStorage69()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useDeviceOrientation.ts b/src/composables/useDeviceOrientation.ts
new file mode 100644
index 0000000..5827d15
--- /dev/null
+++ b/src/composables/useDeviceOrientation.ts
@@ -0,0 +1,138 @@
+import type { DeviceOrientationCallback, DeviceOrientationStartParams } from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { readonly, ref } from 'vue'
+import { onDeviceOrientationChanged, onDeviceOrientationFailed, onDeviceOrientationStarted, onDeviceOrientationStopped } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type DeviceOrientationV60 = ReturnType
+type DeviceOrientationV80 = ReturnType
+
+type DeviceOrientationV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version } & DeviceOrientationV60
+ >;
+}
+
+type DeviceOrientationV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ DeviceOrientationV60to80['6.0'],
+ { version: version } & DeviceOrientationV80
+ >;
+}
+
+type DeviceOrientation =
+ & DeviceOrientationV60to80
+ & DeviceOrientationV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ const isStarted = ref(webApp.DeviceOrientation.isStarted)
+ const absolute = ref(webApp.DeviceOrientation.absolute)
+ const alpha = ref(webApp.DeviceOrientation.alpha)
+ const beta = ref(webApp.DeviceOrientation.beta)
+ const gamma = ref(webApp.DeviceOrientation.gamma)
+
+ const updateState = () => {
+ isStarted.value = webApp.DeviceOrientation.isStarted
+ absolute.value = webApp.DeviceOrientation.absolute
+ alpha.value = webApp.DeviceOrientation.alpha
+ beta.value = webApp.DeviceOrientation.beta
+ gamma.value = webApp.DeviceOrientation.gamma
+ }
+
+ return {
+ webApp,
+ updateState,
+ isStarted,
+ absolute,
+ alpha,
+ beta,
+ gamma,
+ }
+})
+
+function useDeviceOrientation60() {
+ const {
+ isStarted,
+ absolute,
+ alpha,
+ beta,
+ gamma,
+ } = useStore()
+
+ return {
+ isStarted: readonly(isStarted),
+ absolute: readonly(absolute),
+ alpha: readonly(alpha),
+ beta: readonly(beta),
+ gamma: readonly(gamma),
+ }
+}
+
+function useDeviceOrientation80() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const startAsync = promisify(webApp.DeviceOrientation.start)
+
+ function start(params: DeviceOrientationStartParams): ReturnType
+ function start(params: DeviceOrientationStartParams, callback?: DeviceOrientationCallback['start']): void
+ function start(params: DeviceOrientationStartParams, callback?: DeviceOrientationCallback['start']): ReturnType | void {
+ if (callback)
+ webApp.DeviceOrientation.start(params, callback)
+ else
+ return startAsync(params)
+ }
+
+ const stopAsync = promisify(webApp.DeviceOrientation.stop)
+
+ function stop(): ReturnType
+ function stop(callback?: DeviceOrientationCallback['stop']): void
+ function stop(callback?: DeviceOrientationCallback['stop']): ReturnType | void {
+ if (callback)
+ webApp.DeviceOrientation.stop(callback)
+ else
+ return stopAsync()
+ }
+
+ onDeviceOrientationChanged(updateState)
+ onDeviceOrientationFailed(updateState)
+
+ return {
+ start,
+ stop,
+ onStart: onDeviceOrientationStarted,
+ onStop: onDeviceOrientationStopped,
+ onChange: onDeviceOrientationChanged,
+ onFail: onDeviceOrientationFailed,
+ }
+}
+
+export function useDeviceOrientation(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useDeviceOrientation60(),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useDeviceOrientation80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useEmojiStatus.ts b/src/composables/useEmojiStatus.ts
new file mode 100644
index 0000000..9f81906
--- /dev/null
+++ b/src/composables/useEmojiStatus.ts
@@ -0,0 +1,92 @@
+import type { EmojiStatusParams, WebAppCallback } from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { onEmojiStatusAccessRequested, onEmojiStatusFailed, onEmojiStatusSet } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type EmojiStatusV80 = ReturnType
+
+type EmojiStatusV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type EmojiStatusV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ EmojiStatusV60to80['6.0'],
+ { version: version } & EmojiStatusV80
+ >;
+}
+
+type EmojiStatus =
+ & EmojiStatusV60to80
+ & EmojiStatusV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useEmojiStatus80() {
+ const {
+ webApp,
+ } = useStore()
+
+ const setEmojiStatusAsync = promisify(webApp.setEmojiStatus)
+
+ function setEmojiStatus(custom_emoji_id: string, params: EmojiStatusParams): ReturnType
+ function setEmojiStatus(custom_emoji_id: string, params: EmojiStatusParams, callback?: WebAppCallback['setEmojiStatus']): void
+ function setEmojiStatus(custom_emoji_id: string, params: EmojiStatusParams, callback?: WebAppCallback['setEmojiStatus']): ReturnType | void {
+ if (callback)
+ webApp.setEmojiStatus(custom_emoji_id, params, callback)
+ else
+ return setEmojiStatusAsync(custom_emoji_id, params)
+ }
+
+ const requestEmojiStatusAccessAsync = promisify(webApp.requestEmojiStatusAccess)
+
+ function requestEmojiStatusAccess(): ReturnType
+ function requestEmojiStatusAccess(callback?: WebAppCallback['requestEmojiStatusAccess']): void
+ function requestEmojiStatusAccess(callback?: WebAppCallback['requestEmojiStatusAccess']): ReturnType | void {
+ if (callback)
+ webApp.requestEmojiStatusAccess(callback)
+ else
+ return requestEmojiStatusAccessAsync()
+ }
+
+ return {
+ set: setEmojiStatus,
+ requestAccess: requestEmojiStatusAccess,
+ onSet: onEmojiStatusSet,
+ onFail: onEmojiStatusFailed,
+ onAccessRequest: onEmojiStatusAccessRequested,
+ }
+}
+
+export function useEmojiStatus(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useEmojiStatus80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useGyroscope.ts b/src/composables/useGyroscope.ts
new file mode 100644
index 0000000..00ace81
--- /dev/null
+++ b/src/composables/useGyroscope.ts
@@ -0,0 +1,126 @@
+import type { GyroscopeCallback, GyroscopeStartParams } from '../sdk'
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { readonly, ref } from 'vue'
+import { onGyroscopeChanged, onGyroscopeFailed, onGyroscopeStarted, onGyroscopeStopped } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type GyroscopeV60 = ReturnType
+type GyroscopeV80 = ReturnType
+
+type GyroscopeV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version } & GyroscopeV60
+ >;
+}
+
+type GyroscopeV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ GyroscopeV60to80['6.0'],
+ { version: version } & GyroscopeV80
+ >;
+}
+
+type Gyroscope =
+ & GyroscopeV60to80
+ & GyroscopeV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ const isStarted = ref(webApp.Gyroscope.isStarted)
+ const x = ref(webApp.Gyroscope.x)
+ const y = ref(webApp.Gyroscope.y)
+ const z = ref(webApp.Gyroscope.z)
+
+ const updateState = () => {
+ isStarted.value = webApp.Gyroscope.isStarted
+ x.value = webApp.Gyroscope.x
+ y.value = webApp.Gyroscope.y
+ z.value = webApp.Gyroscope.z
+ }
+
+ return {
+ webApp,
+ updateState,
+ isStarted,
+ x,
+ y,
+ z,
+ }
+})
+
+function useGyroscope60() {
+ const {
+ isStarted,
+ x,
+ y,
+ z,
+ } = useStore()
+
+ return {
+ isStarted: readonly(isStarted),
+ x: readonly(x),
+ y: readonly(y),
+ z: readonly(z),
+ }
+}
+
+function useGyroscope80() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const startAsync = promisify(webApp.Gyroscope.start)
+
+ function start(params: GyroscopeStartParams): ReturnType
+ function start(params: GyroscopeStartParams, callback?: GyroscopeCallback['start']): void
+ function start(params: GyroscopeStartParams, callback?: GyroscopeCallback['start']): ReturnType | void {
+ if (callback)
+ webApp.Gyroscope.start(params, callback)
+ else
+ return startAsync(params)
+ }
+
+ const stopAsync = promisify(webApp.Gyroscope.stop)
+
+ function stop(): ReturnType
+ function stop(callback?: GyroscopeCallback['stop']): void
+ function stop(callback?: GyroscopeCallback['stop']): ReturnType | void {
+ if (callback)
+ webApp.Gyroscope.stop(callback)
+ else
+ return stopAsync()
+ }
+
+ onGyroscopeChanged(updateState)
+ onGyroscopeFailed(updateState)
+
+ return {
+ start,
+ stop,
+ onStart: onGyroscopeStarted,
+ onStop: onGyroscopeStopped,
+ onChange: onGyroscopeChanged,
+ onFail: onGyroscopeFailed,
+ }
+}
+
+export function useGyroscope(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useGyroscope60(),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useGyroscope80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useHapticFeedback.ts b/src/composables/useHapticFeedback.ts
new file mode 100644
index 0000000..f79a2d7
--- /dev/null
+++ b/src/composables/useHapticFeedback.ts
@@ -0,0 +1,69 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type HapticFeedbackV61 = ReturnType
+
+type HapticFeedbackV60to61 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.1'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type HapticFeedbackV61toLatest = {
+ [version in BotApiVersionRange<'6.1', LATEST_VERSION>]: Merge<
+ HapticFeedbackV60to61['6.0'],
+ { version: version } & HapticFeedbackV61
+ >;
+}
+
+type HapticFeedback =
+ & HapticFeedbackV60to61
+ & HapticFeedbackV61toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useHapticFeedback61() {
+ const {
+ webApp,
+ } = useStore()
+
+ const impactOccurred = wrapFunction(webApp.HapticFeedback.impactOccurred, {
+ omitReturn: true,
+ })
+ const notificationOccurred = wrapFunction(webApp.HapticFeedback.notificationOccurred, {
+ omitReturn: true,
+ })
+ const selectionChanged = wrapFunction(webApp.HapticFeedback.selectionChanged, {
+ omitReturn: true,
+ })
+
+ return {
+ impactOccurred,
+ notificationOccurred,
+ selectionChanged,
+ }
+}
+
+export function useHapticFeedback(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '6.1')
+ ? useHapticFeedback61()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useHomeScreen.ts b/src/composables/useHomeScreen.ts
new file mode 100644
index 0000000..0e38474
--- /dev/null
+++ b/src/composables/useHomeScreen.ts
@@ -0,0 +1,78 @@
+import type { WebAppCallback } from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { onHomeScreenAdded, onHomeScreenChecked } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify } from '../utils'
+
+type HomeScreenV80 = ReturnType
+
+type HomeScreenV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type HomeScreenV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ HomeScreenV60to80['6.0'],
+ { version: version } & HomeScreenV80
+ >;
+}
+
+type HomeScreen =
+ & HomeScreenV60to80
+ & HomeScreenV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useHomeScreen80() {
+ const {
+ webApp,
+ } = useStore()
+
+ const checkHomeScreenStatusAsync = promisify(webApp.checkHomeScreenStatus)
+
+ function checkHomeScreenStatus(): ReturnType
+ function checkHomeScreenStatus(callback?: WebAppCallback['checkHomeScreenStatus']): void
+ function checkHomeScreenStatus(callback?: WebAppCallback['checkHomeScreenStatus']): ReturnType | void {
+ if (callback)
+ webApp.checkHomeScreenStatus(callback)
+ else
+ return checkHomeScreenStatusAsync()
+ }
+
+ return {
+ addShortcut: webApp.addToHomeScreen,
+ checkShortcutStatus: checkHomeScreenStatus,
+ onShortcutAdd: onHomeScreenAdded,
+ onShortcutCheck: onHomeScreenChecked,
+ }
+}
+
+export function useHomeScreen<
+ Version extends BotApiVersion,
+>(options: { version: Version }) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useHomeScreen80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useLocationManager.ts b/src/composables/useLocationManager.ts
new file mode 100644
index 0000000..a3788f3
--- /dev/null
+++ b/src/composables/useLocationManager.ts
@@ -0,0 +1,134 @@
+import type { LocationManagerCallback } from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { readonly, ref } from 'vue'
+import { onLocationManagerUpdated, onLocationRequested } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify, promisifyWithNoData, wrapFunction } from '../utils'
+
+type LocationManagerV60 = ReturnType
+type LocationManagerV80 = ReturnType
+
+type LocationManagerV60to80 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'8.0'>>]: Merge<
+ Partial,
+ { version: version } & LocationManagerV60
+ >;
+}
+
+type LocationManagerV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ LocationManagerV60to80['6.0'],
+ { version: version } & LocationManagerV80
+ >;
+}
+
+type LocationManager =
+ & LocationManagerV60to80
+ & LocationManagerV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ const isInited = ref(webApp.LocationManager.isInited)
+ const isLocationAvailable = ref(webApp.LocationManager.isLocationAvailable)
+ const isAccessRequested = ref(webApp.LocationManager.isAccessRequested)
+ const isAccessGranted = ref(webApp.LocationManager.isAccessGranted)
+
+ const updateState = () => {
+ isInited.value = webApp.LocationManager.isInited
+ isLocationAvailable.value = webApp.LocationManager.isLocationAvailable
+ isAccessRequested.value = webApp.LocationManager.isAccessRequested
+ isAccessGranted.value = webApp.LocationManager.isAccessGranted
+ }
+
+ return {
+ webApp,
+ updateState,
+ isInited,
+ isLocationAvailable,
+ isAccessRequested,
+ isAccessGranted,
+ }
+})
+
+function useLocationManager60() {
+ const {
+ isInited,
+ isLocationAvailable,
+ isAccessRequested,
+ isAccessGranted,
+ } = useStore()
+
+ return {
+ isInited: readonly(isInited),
+ isLocationAvailable: readonly(isLocationAvailable),
+ isAccessRequested: readonly(isAccessRequested),
+ isAccessGranted: readonly(isAccessGranted),
+ }
+}
+
+function useLocationManager80() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const initAsync = promisifyWithNoData(webApp.LocationManager.init)
+
+ function init(): ReturnType
+ function init(callback?: LocationManagerCallback['init']): void
+ function init(callback?: LocationManagerCallback['init']): ReturnType | void {
+ if (callback)
+ webApp.LocationManager.init(callback)
+ else
+ return initAsync()
+ }
+
+ const getLocationAsync = promisify(webApp.LocationManager.getLocation)
+
+ function getLocation(): ReturnType
+ function getLocation(callback?: LocationManagerCallback['getLocation']): void
+ function getLocation(callback?: LocationManagerCallback['getLocation']): ReturnType | void {
+ if (callback)
+ webApp.LocationManager.getLocation(callback)
+ else
+ return getLocationAsync()
+ }
+
+ onLocationManagerUpdated(updateState)
+ onLocationRequested(updateState)
+
+ return {
+ init,
+ getLocation,
+ openSettings: wrapFunction(webApp.LocationManager.openSettings, {
+ omitReturn: true,
+ }),
+ onManagerUpdate: onLocationManagerUpdated,
+ onRequest: onLocationRequested,
+ }
+}
+
+export function useLocationManager(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useLocationManager60(),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useLocationManager80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useMainButton.ts b/src/composables/useMainButton.ts
new file mode 100644
index 0000000..a6cf0bd
--- /dev/null
+++ b/src/composables/useMainButton.ts
@@ -0,0 +1,225 @@
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onMainButtonClicked } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type MainButtonV60 = ReturnType
+type MainButtonV710 = ReturnType
+
+type MainButtonV60to710 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'7.10'>>]: Merge<
+ Partial,
+ { version: version } & MainButtonV60
+ >;
+}
+
+type MainButtonV710toLatest = {
+ [version in BotApiVersionRange<'7.10', LATEST_VERSION>]: Merge<
+ MainButtonV60to710['6.0'],
+ { version: version } & MainButtonV710
+ >;
+}
+
+type MainButton =
+ & MainButtonV60to710
+ & MainButtonV710toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const text = ref(webApp.MainButton.text)
+ const color = ref(webApp.MainButton.color)
+ const textColor = ref(webApp.MainButton.textColor)
+ const isVisible = ref(webApp.MainButton.isVisible)
+ const isActive = ref(webApp.MainButton.isActive)
+ const isProgressVisible = ref(webApp.MainButton.isProgressVisible)
+ const hasShineEffect = ref(webApp.MainButton.hasShineEffect)
+
+ const updateState = () => {
+ text.value = webApp.MainButton.text
+ color.value = webApp.MainButton.color
+ textColor.value = webApp.MainButton.textColor
+ isVisible.value = webApp.MainButton.isVisible
+ isActive.value = webApp.MainButton.isActive
+ isProgressVisible.value = webApp.MainButton.isProgressVisible
+ hasShineEffect.value = webApp.MainButton.hasShineEffect
+ }
+
+ return {
+ webApp,
+ updateState,
+ text,
+ color,
+ textColor,
+ isVisible,
+ isActive,
+ isProgressVisible,
+ hasShineEffect,
+ }
+})
+
+function useMainButton60() {
+ const {
+ webApp,
+ updateState,
+ text,
+ color,
+ textColor,
+ isVisible,
+ isActive,
+ isProgressVisible,
+ hasShineEffect,
+ } = useStore()
+
+ const showProgress = wrapFunction(webApp.MainButton.showProgress, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const hideProgress = wrapFunction(webApp.MainButton.hideProgress, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const setParams = wrapFunction(webApp.MainButton.setParams, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+
+ return {
+ text: computed({
+ get() {
+ return text.value
+ },
+ set(text) {
+ setParams({ text })
+ },
+ }),
+ color: computed({
+ get() {
+ return color.value
+ },
+ set(color) {
+ setParams({ color })
+ },
+ }),
+ textColor: computed({
+ get() {
+ return textColor.value
+ },
+ set(textColor) {
+ setParams({ text_color: textColor })
+ },
+ }),
+ isVisible: computed({
+ get() {
+ return isVisible.value
+ },
+ set(isVisible) {
+ setParams({ is_visible: isVisible })
+ },
+ }),
+ isActive: computed({
+ get() {
+ return isActive.value
+ },
+ set(isActive) {
+ setParams({ is_active: isActive })
+ },
+ }),
+ isProgressVisible: computed({
+ get() {
+ return isProgressVisible.value
+ },
+ set(isProgressVisible) {
+ if (isProgressVisible)
+ showProgress()
+ else
+ hideProgress()
+ },
+ }),
+ hasShineEffect: readonly(hasShineEffect),
+ show: wrapFunction(webApp.MainButton.show, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ hide: wrapFunction(webApp.MainButton.hide, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ enable: wrapFunction(webApp.MainButton.enable, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ disable: wrapFunction(webApp.MainButton.disable, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ showProgress,
+ hideProgress,
+ setParams,
+ onClick: onMainButtonClicked,
+ }
+}
+
+function useMainButton710() {
+ const {
+ webApp,
+ updateState,
+ hasShineEffect,
+ } = useStore()
+
+ const setParams = wrapFunction(webApp.MainButton.setParams, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+
+ return {
+ hasShineEffect: computed({
+ get() {
+ return hasShineEffect.value
+ },
+ set(hasShineEffect) {
+ setParams({ has_shine_effect: hasShineEffect })
+ },
+ }),
+ }
+}
+
+export function useMainButton(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useMainButton60(),
+ ...(isVersionGreaterOrEqual(version, '7.10')
+ ? useMainButton710()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useMiniApp.ts b/src/composables/useMiniApp.ts
new file mode 100644
index 0000000..78dc592
--- /dev/null
+++ b/src/composables/useMiniApp.ts
@@ -0,0 +1,325 @@
+import type {
+ DownloadFileParams,
+ WebAppCallback,
+} from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onActivated, onContactRequested, onDeactivated, onFileDownloadRequested, onInvoiceClosed, onShareMessageFailed, onShareMessageSent, onWriteAccessRequested } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify, wrapFunction } from '../utils'
+
+type MiniAppV60 = ReturnType
+type MiniAppV61 = ReturnType
+type MiniAppV62 = ReturnType
+type MiniAppV67 = ReturnType
+type MiniAppV69 = ReturnType
+type MiniAppV78 = ReturnType
+type MiniAppV80 = ReturnType
+
+type MiniAppV60to61 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.1'>>]: Merge<
+ Partial<
+ & MiniAppV61
+ & MiniAppV62
+ & MiniAppV67
+ & MiniAppV69
+ & MiniAppV78
+ & MiniAppV80
+ >,
+ { version: version } & MiniAppV60
+ >;
+}
+
+type MiniAppV61to62 = {
+ [version in BotApiVersionRange<'6.1', BotApiPrevVersion<'6.2'>>]: Merge<
+ MiniAppV60to61['6.0'],
+ { version: version } & MiniAppV61
+ >;
+}
+
+type MiniAppV62to67 = {
+ [version in BotApiVersionRange<'6.2', BotApiPrevVersion<'6.7'>>]: Merge<
+ MiniAppV61to62['6.1'],
+ { version: version } & MiniAppV62
+ >;
+}
+
+type MiniAppV67to69 = {
+ [version in BotApiVersionRange<'6.7', BotApiPrevVersion<'6.9'>>]: Merge<
+ MiniAppV62to67['6.2'],
+ { version: version } & MiniAppV67
+ >;
+}
+
+type MiniAppV69to78 = {
+ [version in BotApiVersionRange<'6.9', BotApiPrevVersion<'7.8'>>]: Merge<
+ MiniAppV67to69['6.7'],
+ { version: version } & MiniAppV69
+ >;
+}
+
+type MiniAppV78to80 = {
+ [version in BotApiVersionRange<'7.8', BotApiPrevVersion<'8.0'>>]: Merge<
+ MiniAppV69to78['6.9'],
+ { version: version } & MiniAppV78
+ >;
+}
+
+type MiniAppV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ MiniAppV78to80['7.8'],
+ { version: version } & MiniAppV80
+ >;
+}
+
+type MiniApp =
+ & MiniAppV60to61
+ & MiniAppV61to62
+ & MiniAppV62to67
+ & MiniAppV67to69
+ & MiniAppV69to78
+ & MiniAppV78to80
+ & MiniAppV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const isReady = ref(false)
+ const isClosingConfirmationEnabled = ref(webApp.isClosingConfirmationEnabled)
+ const isActive = ref(webApp.isActive)
+
+ const updateState = () => {
+ isActive.value = webApp.isActive
+ isClosingConfirmationEnabled.value = webApp.isClosingConfirmationEnabled
+ }
+
+ return {
+ webApp,
+ updateState,
+ isReady,
+ isActive,
+ isClosingConfirmationEnabled,
+ }
+})
+
+function useMiniApp60() {
+ const {
+ webApp,
+ isReady,
+ isActive,
+ isClosingConfirmationEnabled,
+ } = useStore()
+
+ return {
+ initData: webApp.initData,
+ initDataUnsafe: webApp.initDataUnsafe,
+ platform: webApp.platform,
+ sendData: webApp.sendData,
+ openLink: webApp.openLink,
+ openTelegramLink: webApp.openTelegramLink,
+ ready: wrapFunction(webApp.ready, {
+ hooks: {
+ after: () => {
+ isReady.value = true
+ },
+ },
+ }),
+ close: webApp.close,
+ isClosingConfirmationEnabled: readonly(isClosingConfirmationEnabled),
+ isActive: readonly(isActive),
+ isReady: readonly(isReady),
+ isPlatform,
+ }
+}
+
+function useMiniApp61() {
+ const { webApp } = useStore()
+
+ const openInvoiceAsync = promisify(webApp.openInvoice)
+
+ function openInvoice(url: string): ReturnType
+ function openInvoice(url: string, callback?: WebAppCallback['openInvoice']): void
+ function openInvoice(url: string, callback?: WebAppCallback['openInvoice']): ReturnType | void {
+ if (callback)
+ webApp.openInvoice(url, callback)
+ else
+ return openInvoiceAsync(url)
+ }
+
+ return {
+ openInvoice,
+ onInvoiceClose: onInvoiceClosed,
+ }
+}
+
+function useMiniApp62() {
+ const {
+ webApp,
+ updateState,
+ isClosingConfirmationEnabled,
+ } = useStore()
+
+ const enableClosingConfirmation = wrapFunction(webApp.enableClosingConfirmation, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const disableClosingConfirmation = wrapFunction(webApp.disableClosingConfirmation, {
+ hooks: {
+ after: updateState,
+ },
+ })
+
+ return {
+ isClosingConfirmationEnabled: computed({
+ get() {
+ return isClosingConfirmationEnabled.value
+ },
+ set(isEnabled) {
+ if (isEnabled)
+ enableClosingConfirmation()
+ else
+ disableClosingConfirmation()
+ },
+ }),
+ }
+}
+
+function useMiniApp67() {
+ const { webApp } = useStore()
+
+ return {
+ switchInlineQuery: webApp.switchInlineQuery,
+ }
+}
+
+function useMiniApp69() {
+ const { webApp } = useStore()
+
+ const requestContactAsync = promisify(webApp.requestContact)
+
+ function requestContact(): ReturnType
+ function requestContact(callback?: WebAppCallback['requestContact']): void
+ function requestContact(callback?: WebAppCallback['requestContact']): ReturnType | void {
+ if (callback)
+ webApp.requestContact(callback)
+ else
+ return requestContactAsync()
+ }
+
+ const requestWriteAccessAsync = promisify(webApp.requestWriteAccess)
+
+ function requestWriteAccess(): ReturnType
+ function requestWriteAccess(callback?: WebAppCallback['requestWriteAccess']): void
+ function requestWriteAccess(callback?: WebAppCallback['requestWriteAccess']): ReturnType | void {
+ if (callback)
+ webApp.requestWriteAccess(callback)
+ else
+ return requestWriteAccessAsync()
+ }
+
+ return {
+ requestContact,
+ requestWriteAccess,
+ onContactRequest: onContactRequested,
+ onWriteAccessRequest: onWriteAccessRequested,
+ }
+}
+
+function useMiniApp78() {
+ const { webApp } = useStore()
+
+ return {
+ shareToStory: webApp.shareToStory,
+ }
+}
+
+function useMiniApp80() {
+ const {
+ webApp,
+ updateState,
+ } = useStore()
+
+ const shareMessageAsync = promisify(webApp.shareMessage)
+
+ function shareMessage(msg_id: string): ReturnType
+ function shareMessage(msg_id: string, callback?: WebAppCallback['shareMessage']): void
+ function shareMessage(msg_id: string, callback?: WebAppCallback['shareMessage']): ReturnType | void {
+ if (callback)
+ webApp.shareMessage(msg_id, callback)
+ else
+ return shareMessageAsync(msg_id)
+ }
+
+ const downloadFileAsync = promisify(webApp.downloadFile)
+
+ function downloadFile(params: DownloadFileParams): ReturnType
+ function downloadFile(params: DownloadFileParams, callback?: WebAppCallback['downloadFile']): void
+ function downloadFile(params: DownloadFileParams, callback?: WebAppCallback['downloadFile']): ReturnType | void {
+ if (callback)
+ webApp.downloadFile(params, callback)
+ else
+ return downloadFileAsync(params)
+ }
+
+ onActivated(updateState)
+ onDeactivated(updateState)
+
+ return {
+ shareMessage,
+ downloadFile,
+ onActive: onActivated,
+ onDeactive: onDeactivated,
+ onShareMessageSent,
+ onShareMessageFail: onShareMessageFailed,
+ onFileDownloadRequest: onFileDownloadRequested,
+ }
+}
+
+export function useMiniApp(
+ options: {
+ version: Version
+ },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useMiniApp60(),
+ ...(isVersionGreaterOrEqual(version, '6.1') && useMiniApp61()),
+ ...(isVersionGreaterOrEqual(version, '6.2') && useMiniApp62()),
+ ...(isVersionGreaterOrEqual(version, '6.7') && useMiniApp67()),
+ ...(isVersionGreaterOrEqual(version, '6.9') && useMiniApp69()),
+ ...(isVersionGreaterOrEqual(version, '7.8') && useMiniApp78()),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useMiniApp80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
+
+export function isVersionAtLeast(version: BotApiVersion) {
+ return isVersionGreaterOrEqual(version, getWebApp().version)
+}
+
+function isPlatform(
+ name:
+ | (string & Record)
+ | 'unknown'
+ | 'android'
+ | 'android_x'
+ | 'ios'
+ | 'macos'
+ | 'tdesktop'
+ | 'weba'
+ | 'webk'
+ | 'unigram',
+) {
+ return getWebApp().platform === name
+}
diff --git a/src/composables/usePopup.ts b/src/composables/usePopup.ts
new file mode 100644
index 0000000..13bfb3f
--- /dev/null
+++ b/src/composables/usePopup.ts
@@ -0,0 +1,98 @@
+import type { PopupParams, WebAppCallback } from '../sdk'
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { onPopupClosed } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, promisify, promisifyWithNoData } from '../utils'
+
+type Popup62 = ReturnType
+
+type PopupV60 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.2'>>]: Merge<
+ Partial,
+ { version: version }
+ >;
+}
+
+type PopupV62toLatest = {
+ [version in BotApiVersionRange<'6.2', LATEST_VERSION>]: Merge<
+ PopupV60['6.0'],
+ { version: version } & Popup62
+ >;
+}
+
+type Popup =
+ & PopupV60
+ & PopupV62toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function usePopup62() {
+ const {
+ webApp,
+ } = useStore()
+
+ const showConfirmAsync = promisify(webApp.showConfirm)
+
+ function showConfirm(message: string): ReturnType
+ function showConfirm(message: string, callback?: WebAppCallback['showConfirm']): void
+ function showConfirm(message: string, callback?: WebAppCallback['showConfirm']): ReturnType | void {
+ if (callback)
+ webApp.showConfirm(message, callback)
+ else
+ return showConfirmAsync(message)
+ }
+
+ const showAlertAsync = promisifyWithNoData(webApp.showAlert)
+
+ function showAlert(message: string): ReturnType
+ function showAlert(message: string, callback?: WebAppCallback['showAlert']): void
+ function showAlert(message: string, callback?: WebAppCallback['showAlert']): ReturnType | void {
+ if (callback)
+ webApp.showAlert(message, callback)
+ else
+ return showAlertAsync(message)
+ }
+
+ const showPopupAsync = promisify(webApp.showPopup)
+
+ function showPopup(params: PopupParams): ReturnType
+ function showPopup(params: PopupParams, callback?: WebAppCallback['showPopup']): void
+ function showPopup(params: PopupParams, callback?: WebAppCallback['showPopup']): ReturnType | void {
+ if (callback)
+ webApp.showPopup(params, callback)
+ else
+ return showPopupAsync(params)
+ }
+
+ return {
+ showConfirm,
+ showAlert,
+ showPopup,
+ onClose: onPopupClosed,
+ }
+}
+
+export function usePopup(options?: { version?: Version }) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '6.2')
+ ? usePopup62()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useQrScanner.ts b/src/composables/useQrScanner.ts
new file mode 100644
index 0000000..e92c097
--- /dev/null
+++ b/src/composables/useQrScanner.ts
@@ -0,0 +1,73 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { onQrTextReceived, onScanQrPopupClosed } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual } from '../utils'
+
+type QrScannerV64 = ReturnType
+type QrScannerV77 = ReturnType
+
+type QrScannerV60to64 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.4'>>]: Merge<
+ & Partial,
+ { version: version }
+ >;
+}
+
+type QrScannerV64to77 = {
+ [version in BotApiVersionRange<'6.4', BotApiPrevVersion<'7.7'>>]: Merge<
+ QrScannerV60to64['6.0'],
+ { version: version } & QrScannerV64
+ >;
+}
+type QrScannerV77toLatest = {
+ [version in BotApiVersionRange<'7.7', LATEST_VERSION>]: Merge<
+ QrScannerV64to77['6.4'],
+ { version: version } & QrScannerV77
+ >;
+}
+
+type QrScanner =
+ & QrScannerV60to64
+ & QrScannerV64to77
+ & QrScannerV77toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+
+ return {
+ webApp,
+ }
+})
+
+function useQrScanner64() {
+ const {
+ webApp,
+ } = useStore()
+
+ return {
+ show: webApp.showScanQrPopup,
+ close: webApp.closeScanQrPopup,
+ onScan: onQrTextReceived,
+ }
+}
+
+function useQrScanner77() {
+ return {
+ onClose: onScanQrPopupClosed,
+ }
+}
+
+export function useQrScanner(
+ options?: { version?: Version },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...(isVersionGreaterOrEqual(version, '6.4') && useQrScanner64()),
+ ...(isVersionGreaterOrEqual(version, '7.7')
+ ? useQrScanner77()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useSecondaryButton.ts b/src/composables/useSecondaryButton.ts
new file mode 100644
index 0000000..5d1efb8
--- /dev/null
+++ b/src/composables/useSecondaryButton.ts
@@ -0,0 +1,233 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onSecondaryButtonClicked } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type SecondaryButtonV60 = ReturnType
+type SecondaryButtonV710 = ReturnType
+
+type SecondaryButtonV60to710 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'7.10'>>]: Merge<
+ & Partial,
+ { version: version } & SecondaryButtonV60
+ >;
+}
+
+type SecondaryButtonV710toLatest = {
+ [version in BotApiVersionRange<'7.10', LATEST_VERSION>]: Merge<
+ SecondaryButtonV60to710['6.0'],
+ { version: version } & SecondaryButtonV710
+ >;
+}
+
+type SecondaryButton =
+ & SecondaryButtonV60to710
+ & SecondaryButtonV710toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const text = ref(webApp.SecondaryButton.text)
+ const color = ref(webApp.SecondaryButton.color)
+ const textColor = ref(webApp.SecondaryButton.textColor)
+ const isVisible = ref(webApp.SecondaryButton.isVisible)
+ const isActive = ref(webApp.SecondaryButton.isActive)
+ const isProgressVisible = ref(webApp.SecondaryButton.isProgressVisible)
+ const hasShineEffect = ref(webApp.SecondaryButton.hasShineEffect)
+ const position = ref(webApp.SecondaryButton.position)
+
+ const updateState = () => {
+ text.value = webApp.SecondaryButton.text
+ color.value = webApp.SecondaryButton.color
+ textColor.value = webApp.SecondaryButton.textColor
+ isVisible.value = webApp.SecondaryButton.isVisible
+ isActive.value = webApp.SecondaryButton.isActive
+ isProgressVisible.value = webApp.SecondaryButton.isProgressVisible
+ hasShineEffect.value = webApp.SecondaryButton.hasShineEffect
+ position.value = webApp.SecondaryButton.position
+ }
+
+ return {
+ webApp,
+ updateState,
+ text,
+ color,
+ textColor,
+ isVisible,
+ isActive,
+ isProgressVisible,
+ hasShineEffect,
+ position,
+ }
+})
+
+function useSecondaryButton60() {
+ const {
+ text,
+ color,
+ textColor,
+ isVisible,
+ isActive,
+ isProgressVisible,
+ hasShineEffect,
+ position,
+ } = useStore()
+
+ return {
+ text: readonly(text),
+ color: readonly(color),
+ textColor: readonly(textColor),
+ isVisible: readonly(isVisible),
+ isActive: readonly(isActive),
+ isProgressVisible: readonly(isProgressVisible),
+ hasShineEffect: readonly(hasShineEffect),
+ position: readonly(position),
+ }
+}
+
+function useSecondaryButton710() {
+ const {
+ webApp,
+ text,
+ color,
+ textColor,
+ isVisible,
+ isActive,
+ isProgressVisible,
+ hasShineEffect,
+ position,
+ updateState,
+ } = useStore()
+
+ const showProgress = wrapFunction(webApp.SecondaryButton.showProgress, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const hideProgress = wrapFunction(webApp.SecondaryButton.hideProgress, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const setParams = wrapFunction(webApp.SecondaryButton.setParams, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+
+ return {
+ text: computed({
+ get() {
+ return text.value
+ },
+ set(text) {
+ setParams({ text })
+ },
+ }),
+ color: computed({
+ get() {
+ return color.value
+ },
+ set(color) {
+ setParams({ color })
+ },
+ }),
+ textColor: computed({
+ get() {
+ return textColor.value
+ },
+ set(textColor) {
+ setParams({ text_color: textColor })
+ },
+ }),
+ isVisible: computed({
+ get() {
+ return isVisible.value
+ },
+ set(isVisible) {
+ setParams({ is_visible: isVisible })
+ },
+ }),
+ isActive: computed({
+ get() {
+ return isActive.value
+ },
+ set(isActive) {
+ setParams({ is_active: isActive })
+ },
+ }),
+ isProgressVisible: computed({
+ get() {
+ return isProgressVisible.value
+ },
+ set(isProgressVisible) {
+ if (isProgressVisible)
+ showProgress()
+ else
+ hideProgress()
+ },
+ }),
+ hasShineEffect: computed({
+ get() {
+ return hasShineEffect.value
+ },
+ set(hasShineEffect) {
+ setParams({ has_shine_effect: hasShineEffect })
+ },
+ }),
+ position: computed({
+ get() {
+ return position.value
+ },
+ set(position) {
+ setParams({ position })
+ },
+ }),
+ show: wrapFunction(webApp.SecondaryButton.show, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ hide: wrapFunction(webApp.SecondaryButton.hide, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ enable: wrapFunction(webApp.SecondaryButton.enable, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ disable: wrapFunction(webApp.SecondaryButton.disable, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ }),
+ showProgress,
+ hideProgress,
+ setParams,
+ onClick: onSecondaryButtonClicked,
+ }
+}
+
+export function useSecondaryButton(
+ options?: { version?: Version },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useSecondaryButton60(),
+ ...(isVersionGreaterOrEqual(version, '7.10')
+ ? useSecondaryButton710()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useSettingsButton.ts b/src/composables/useSettingsButton.ts
new file mode 100644
index 0000000..21d9729
--- /dev/null
+++ b/src/composables/useSettingsButton.ts
@@ -0,0 +1,111 @@
+import type {
+ BotApiPrevVersion,
+ BotApiVersion,
+ BotApiVersionRange,
+ LATEST_VERSION,
+ Merge,
+ VersionedReturnType,
+} from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onSettingsButtonClicked } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type SettingsButtonV60 = ReturnType
+type SettingsButtonV70 = ReturnType
+
+type SettingsButtonV60to70 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'7.0'>>]: Merge<
+ & Partial,
+ { version: version } & SettingsButtonV60
+ >;
+}
+
+type SettingsButtonV70toLatest = {
+ [version in BotApiVersionRange<'7.0', LATEST_VERSION>]: Merge<
+ SettingsButtonV60to70['6.0'],
+ { version: version } & SettingsButtonV70
+ >;
+}
+
+type SettingsButton =
+ & SettingsButtonV60to70
+ & SettingsButtonV70toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const isVisible = ref(webApp.SettingsButton.isVisible)
+
+ const updateState = () => {
+ isVisible.value = webApp.SettingsButton.isVisible
+ }
+
+ return {
+ webApp,
+ isVisible,
+ updateState,
+ }
+})
+
+function useSettingsButton60() {
+ const {
+ isVisible,
+ } = useStore()
+
+ return {
+ isVisible: readonly(isVisible),
+ }
+}
+
+function useSettingsButton70() {
+ const {
+ webApp,
+ isVisible,
+ updateState,
+ } = useStore()
+
+ const show = wrapFunction(webApp.SettingsButton.show, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+ const hide = wrapFunction(webApp.SettingsButton.hide, {
+ hooks: {
+ after: updateState,
+ },
+ omitReturn: true,
+ })
+
+ return {
+ isVisible: computed({
+ get() {
+ return isVisible.value
+ },
+ set(isVisible) {
+ if (isVisible)
+ show()
+ else
+ hide()
+ },
+ }),
+ show,
+ hide,
+ onClick: onSettingsButtonClicked,
+ }
+}
+
+export function useSettingsButton(
+ options?: { version?: Version },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useSettingsButton60(),
+ ...(isVersionGreaterOrEqual(version, '7.0')
+ ? useSettingsButton70()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts
new file mode 100644
index 0000000..91f8fd6
--- /dev/null
+++ b/src/composables/useTheme.ts
@@ -0,0 +1,166 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onThemeChanged } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type ThemeV60 = ReturnType
+type ThemeV61 = ReturnType
+type ThemeV710 = ReturnType
+
+type ThemeV60to61 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'6.1'>>]: Merge<
+ Partial & Partial,
+ { version: version } & ThemeV60
+ >;
+}
+
+type ThemeV61to710 = {
+ [version in BotApiVersionRange<'6.1', BotApiPrevVersion<'7.10'>>]: Merge<
+ ThemeV60to61['6.0'],
+ { version: version } & ThemeV61
+ >;
+}
+
+type ThemeV710toLatest = {
+ [version in BotApiVersionRange<'7.10', LATEST_VERSION>]: Merge<
+ ThemeV61to710['6.1'],
+ { version: version } & ThemeV710
+ >;
+}
+
+type Theme =
+ & ThemeV60to61
+ & ThemeV61to710
+ & ThemeV710toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const colorScheme = ref(webApp.colorScheme)
+ const themeParams = ref(webApp.themeParams)
+ const headerColor = ref(webApp.headerColor)
+ const backgroundColor = ref(webApp.backgroundColor)
+ const bottomBarColor = ref(webApp.bottomBarColor)
+
+ const updateState = () => {
+ colorScheme.value = webApp.colorScheme
+ themeParams.value = {
+ ...webApp.themeParams,
+ }
+ headerColor.value = webApp.headerColor
+ backgroundColor.value = webApp.backgroundColor
+ bottomBarColor.value = webApp.bottomBarColor
+ }
+
+ return {
+ webApp,
+ updateState,
+ colorScheme,
+ themeParams,
+ headerColor,
+ backgroundColor,
+ bottomBarColor,
+ }
+})
+
+function useTheme60() {
+ const {
+ colorScheme,
+ themeParams,
+ headerColor,
+ backgroundColor,
+ bottomBarColor,
+ updateState,
+ } = useStore()
+
+ onThemeChanged(updateState)
+
+ return {
+ colorScheme: readonly(colorScheme),
+ themeParams: readonly(themeParams),
+ headerColor: readonly(headerColor),
+ backgroundColor: readonly(backgroundColor),
+ bottomBarColor: readonly(bottomBarColor),
+ onChange: onThemeChanged,
+ }
+}
+
+function useTheme61() {
+ const {
+ webApp,
+ headerColor,
+ backgroundColor,
+ updateState,
+ } = useStore()
+
+ const setHeaderColor = wrapFunction(webApp.setHeaderColor, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const setBackgroundColor = wrapFunction(webApp.setBackgroundColor, {
+ hooks: {
+ after: updateState,
+ },
+ })
+
+ return {
+ headerColor: computed({
+ get() {
+ return headerColor.value
+ },
+ set(newColor: Parameters[0]) {
+ setHeaderColor(newColor)
+ },
+ }),
+ backgroundColor: computed({
+ get() {
+ return backgroundColor.value
+ },
+ set(newColor: Parameters[0]) {
+ setBackgroundColor(newColor)
+ },
+ }),
+ }
+}
+
+function useTheme710() {
+ const {
+ webApp,
+ bottomBarColor,
+ updateState,
+ } = useStore()
+
+ const setBottomBarColor = wrapFunction(webApp.setBottomBarColor, {
+ hooks: {
+ after: updateState,
+ },
+ })
+
+ return {
+ bottomBarColor: computed({
+ get() {
+ return bottomBarColor.value
+ },
+ set(newColor: Parameters[0]) {
+ setBottomBarColor(newColor)
+ },
+ }),
+ }
+}
+
+export function useTheme(
+ options?: { version?: Version },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useTheme60(),
+ ...(isVersionGreaterOrEqual(version, '6.1') && useTheme61()),
+ ...(isVersionGreaterOrEqual(version, '7.10')
+ ? useTheme710()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useViewport.ts b/src/composables/useViewport.ts
new file mode 100644
index 0000000..7b22f42
--- /dev/null
+++ b/src/composables/useViewport.ts
@@ -0,0 +1,218 @@
+import type { BotApiPrevVersion, BotApiVersion, BotApiVersionRange, LATEST_VERSION, Merge, VersionedReturnType } from '../types'
+import { computed, readonly, ref } from 'vue'
+import { onContentSafeAreaChanged, onFullscreenChanged, onFullscreenFailed, onSafeAreaChanged, onViewportChanged } from '../events'
+import { getWebApp } from '../sdk'
+import { defineStore, isVersionGreaterOrEqual, wrapFunction } from '../utils'
+
+type ViewportV60 = ReturnType
+type ViewportV77 = ReturnType
+type ViewportV80 = ReturnType
+
+type ViewportV60to77 = {
+ [version in BotApiVersionRange<'6.0', BotApiPrevVersion<'7.7'>>]: Merge<
+ & Partial
+ & Partial,
+ { version: version } & ViewportV60
+ >;
+}
+
+type ViewportV77to80 = {
+ [version in BotApiVersionRange<'7.7', BotApiPrevVersion<'8.0'>>]: Merge<
+ ViewportV60to77['6.0'],
+ { version: version } & ViewportV77
+ >;
+}
+
+type ViewportV80toLatest = {
+ [version in BotApiVersionRange<'8.0', LATEST_VERSION>]: Merge<
+ ViewportV77to80['7.7'],
+ { version: version } & ViewportV80
+ >;
+}
+
+type Viewport =
+ & ViewportV60to77
+ & ViewportV77to80
+ & ViewportV80toLatest
+
+const useStore = defineStore(() => {
+ const webApp = getWebApp()
+ const isExpanded = ref(webApp.isExpanded)
+ const viewportHeight = ref(webApp.viewportHeight)
+ const viewportStableHeight = ref(webApp.viewportStableHeight)
+ const isFullscreen = ref(webApp.isFullscreen)
+ const isOrientationLocked = ref(webApp.isOrientationLocked)
+ const isVerticalSwipesEnabled = ref(webApp.isVerticalSwipesEnabled)
+ const safeAreaInset = ref(webApp.safeAreaInset)
+ const contentSafeAreaInset = ref(webApp.contentSafeAreaInset)
+
+ const updateState = () => {
+ isExpanded.value = webApp.isExpanded
+ viewportHeight.value = webApp.viewportHeight
+ viewportStableHeight.value = webApp.viewportStableHeight
+ isFullscreen.value = webApp.isFullscreen
+ isOrientationLocked.value = webApp.isOrientationLocked
+ isVerticalSwipesEnabled.value = webApp.isVerticalSwipesEnabled
+ safeAreaInset.value = {
+ ...webApp.safeAreaInset,
+ }
+ contentSafeAreaInset.value = {
+ ...webApp.contentSafeAreaInset,
+ }
+ }
+
+ return {
+ webApp,
+ updateState,
+ isExpanded,
+ viewportHeight,
+ viewportStableHeight,
+ isFullscreen,
+ isOrientationLocked,
+ isVerticalSwipesEnabled,
+ safeAreaInset,
+ contentSafeAreaInset,
+ }
+})
+
+function useViewport60() {
+ const {
+ webApp,
+ updateState,
+ isExpanded,
+ viewportHeight,
+ viewportStableHeight,
+ isFullscreen,
+ isOrientationLocked,
+ isVerticalSwipesEnabled,
+ safeAreaInset,
+ contentSafeAreaInset,
+ } = useStore()
+
+ onViewportChanged(updateState)
+
+ return {
+ expand: wrapFunction(webApp.expand, {
+ hooks: {
+ after: updateState,
+ },
+ }),
+ isExpanded: readonly(isExpanded),
+ viewportHeight: readonly(viewportHeight),
+ viewportStableHeight: readonly(viewportStableHeight),
+ isFullscreen: readonly(isFullscreen),
+ isOrientationLocked: readonly(isOrientationLocked),
+ isVerticalSwipesEnabled: readonly(isVerticalSwipesEnabled),
+ safeAreaInset: readonly(safeAreaInset),
+ contentSafeAreaInset: readonly(contentSafeAreaInset),
+ onChange: onViewportChanged,
+ }
+}
+
+function useViewport77() {
+ const {
+ webApp,
+ isVerticalSwipesEnabled,
+ updateState,
+ } = useStore()
+
+ const enableVerticalSwipes = wrapFunction(webApp.enableVerticalSwipes, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const disableVerticalSwipes = wrapFunction(webApp.disableVerticalSwipes, {
+ hooks: {
+ after: updateState,
+ },
+ })
+
+ return {
+ isVerticalSwipesEnabled: computed({
+ get() {
+ return isVerticalSwipesEnabled.value
+ },
+ set(isEnabled) {
+ if (isEnabled)
+ enableVerticalSwipes()
+ else
+ disableVerticalSwipes()
+ },
+ }),
+ }
+}
+
+function useViewport80() {
+ const {
+ webApp,
+ isFullscreen,
+ isOrientationLocked,
+ updateState,
+ } = useStore()
+
+ const requestFullscreen = wrapFunction(webApp.requestFullscreen, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const exitFullscreen = wrapFunction(webApp.exitFullscreen, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const lockOrientation = wrapFunction(webApp.lockOrientation, {
+ hooks: {
+ after: updateState,
+ },
+ })
+ const unlockOrientation = wrapFunction(webApp.unlockOrientation, {
+ hooks: {
+ after: updateState,
+ },
+ })
+
+ return {
+ isFullscreen: computed({
+ get() {
+ return isFullscreen.value
+ },
+ set(isEnabled) {
+ if (isEnabled)
+ requestFullscreen()
+ else
+ exitFullscreen()
+ },
+ }),
+ isOrientationLocked: computed({
+ get() {
+ return isOrientationLocked.value
+ },
+ set(isEnabled) {
+ if (isEnabled)
+ lockOrientation()
+ else
+ unlockOrientation()
+ },
+ }),
+ onSafeAreaChange: onSafeAreaChanged,
+ onContentSafeAreaChange: onContentSafeAreaChanged,
+ onFullscreenChange: onFullscreenChanged,
+ onFullscreenFail: onFullscreenFailed,
+ }
+}
+
+export function useViewport(
+ options?: { version?: Version },
+) {
+ const { webApp } = useStore()
+ const version = options?.version ?? webApp.version
+
+ return {
+ version: webApp.version,
+ ...useViewport60(),
+ ...(isVersionGreaterOrEqual(version, '7.7') && useViewport77()),
+ ...(isVersionGreaterOrEqual(version, '8.0')
+ ? useViewport80()
+ : { isVersionAtLeast: webApp.isVersionAtLeast }),
+ } as VersionedReturnType
+}
diff --git a/src/composables/useWebApp.ts b/src/composables/useWebApp.ts
deleted file mode 100644
index f99cafc..0000000
--- a/src/composables/useWebApp.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import type { OnEventOptions, OnEventWithOptions } from '../types'
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
-
-const isReady = ref(false)
-
-const ready: typeof Telegram.WebApp.ready = (...params) => {
- Telegram.WebApp.ready(...params)
- isReady.value = true
-}
-
-function isPlatform(name:
- | (string & Record)
- | 'unknown'
- | 'android'
- | 'android_x'
- | 'ios'
- | 'macos'
- | 'tdesktop'
- | 'weba'
- | 'webk'
- | 'unigram') {
- return Telegram.WebApp.platform === name
-}
-
-const featureSupportVersion = {
- ClosingConfirmation: '6.2',
- CloudStorage: '6.9',
- RequestWriteAccess: '6.9',
- RequestContact: '6.9',
- SettingsButton: '7.0',
- BiometricManager: '7.2',
- DisableVerticalSwipes: '7.7',
-}
-function isFeatureSupported(name: keyof typeof featureSupportVersion) {
- return Telegram.WebApp.isVersionAtLeast(featureSupportVersion[name])
-}
-
-export function useWebApp() {
- const onEvent: OnEventWithOptions = (
- eventType,
- eventHandler,
- options = { manual: false },
- ) => {
- const { manual } = options
-
- const on = () => {
- Telegram.WebApp.onEvent(
- ...([eventType, eventHandler] as Parameters<
- typeof Telegram.WebApp.onEvent
- >),
- )
- }
- const off = () => {
- Telegram.WebApp.offEvent(
- ...([eventType, eventHandler] as Parameters<
- typeof Telegram.WebApp.offEvent
- >),
- )
- }
-
- if (manual) {
- on()
- }
- else {
- onMounted(on)
- onUnmounted(off)
- }
-
- return {
- off,
- }
- }
-
- const {
- initData,
- initDataUnsafe,
- version,
- platform,
- isVersionAtLeast,
- sendData,
- close,
- } = Telegram.WebApp
-
- const isPlatformUnknown = isPlatform('unknown')
-
- const canSendData = !isPlatformUnknown && initData === ''
-
- return {
- initData,
- initDataUnsafe,
- version,
- platform,
- isVersionAtLeast,
- onEvent,
- sendData,
- ready,
- close,
- isReady: readonly(isReady),
- isPlatform,
- isPlatformUnknown,
- isFeatureSupported,
- /**
- * @deprecated
- */
- canSendData,
- }
-}
diff --git a/src/composables/useWebAppBackButton.ts b/src/composables/useWebAppBackButton.ts
deleted file mode 100644
index 7276ea8..0000000
--- a/src/composables/useWebAppBackButton.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { computed, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const isBackButtonVisible = ref(Telegram.WebApp.BackButton.isVisible)
-
- function updateState() {
- isBackButtonVisible.value = Telegram.WebApp.BackButton.isVisible
- }
-
- function showBackButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.BackButton.show(...params)
- updateState()
- }
-
- function hideBackButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.BackButton.hide(...params)
- updateState()
- }
-
- return { isBackButtonVisible, showBackButton, hideBackButton }
-})
-
-export function useWebAppBackButton() {
- const { isBackButtonVisible, showBackButton, hideBackButton } = useStore()
-
- const { onEvent } = useWebApp()
-
- const onBackButtonClicked = (
- eventHandler: BackButtonClickedCallback,
- options?: OnEventOptions,
- ) => onEvent('backButtonClicked', eventHandler, options)
-
- return {
- isBackButtonVisible: computed({
- get() {
- return isBackButtonVisible.value
- },
- set(isVisible) {
- isVisible ? showBackButton() : hideBackButton()
- },
- }),
- onBackButtonClicked,
- showBackButton,
- hideBackButton,
- }
-}
diff --git a/src/composables/useWebAppBiometricManager.ts b/src/composables/useWebAppBiometricManager.ts
deleted file mode 100644
index d3f8fa8..0000000
--- a/src/composables/useWebAppBiometricManager.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { readonly, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const isBiometricInited = ref(Telegram.WebApp.BiometricManager.isInited)
- const isBiometricAvailable = ref(
- Telegram.WebApp.BiometricManager.isBiometricAvailable,
- )
- const biometricType = ref(Telegram.WebApp.BiometricManager.biometricType)
- const isBiometricAccessRequested = ref(
- Telegram.WebApp.BiometricManager.isAccessRequested,
- )
- const isBiometricAccessGranted = ref(
- Telegram.WebApp.BiometricManager.isAccessGranted,
- )
- const isBiometricTokenSaved = ref(
- Telegram.WebApp.BiometricManager.isAccessGranted,
- )
- const biometricDeviceId = ref(Telegram.WebApp.BiometricManager.deviceId)
-
- function updateState() {
- isBiometricInited.value = Telegram.WebApp.BiometricManager.isInited
- isBiometricAvailable.value
- = Telegram.WebApp.BiometricManager.isBiometricAvailable
- biometricType.value = Telegram.WebApp.BiometricManager.biometricType
- isBiometricAccessRequested.value
- = Telegram.WebApp.BiometricManager.isAccessRequested
- isBiometricAccessGranted.value
- = Telegram.WebApp.BiometricManager.isAccessGranted
- biometricDeviceId.value = Telegram.WebApp.BiometricManager.deviceId
- isBiometricTokenSaved.value
- = Telegram.WebApp.BiometricManager.isBiometricTokenSaved
- }
-
- return {
- isBiometricInited,
- isBiometricAvailable,
- biometricType,
- isBiometricAccessRequested,
- isBiometricAccessGranted,
- biometricDeviceId,
- isBiometricTokenSaved,
- updateState,
- }
-})
-
-export function useWebAppBiometricManager() {
- const {
- isBiometricInited,
- isBiometricAvailable,
- biometricType,
- isBiometricAccessRequested,
- isBiometricAccessGranted,
- biometricDeviceId,
- isBiometricTokenSaved,
- updateState,
- } = useStore()
-
- const { onEvent } = useWebApp()
-
- const onBiometricManagerUpdated = (
- eventHandler: () => void,
- options?: OnEventOptions,
- ) => onEvent('biometricManagerUpdated', eventHandler, options)
- const onBiometricAuthRequested = (
- eventHandler: BiometricAuthRequestedCallback,
- options?: OnEventOptions,
- ) => onEvent('biometricAuthRequested', eventHandler, options)
- const onBiometricTokenUpdated = (
- eventHandler: BiometricTokenUpdatedCallback,
- options?: OnEventOptions,
- ) => onEvent('biometricTokenUpdated', eventHandler, options)
-
- onBiometricManagerUpdated(updateState)
-
- const {
- init,
- requestAccess,
- authenticate,
- updateBiometricToken,
- openSettings,
- } = Telegram.WebApp.BiometricManager
-
- return {
- isBiometricInited: readonly(isBiometricInited),
- isBiometricAvailable: readonly(isBiometricAvailable),
- biometricType: readonly(biometricType),
- isBiometricAccessRequested: readonly(isBiometricAccessRequested),
- isBiometricAccessGranted: readonly(isBiometricAccessGranted),
- isBiometricTokenSaved: readonly(isBiometricTokenSaved),
- biometricDeviceId: readonly(biometricDeviceId),
- initBiometric: init,
- requestBiometricAccess: requestAccess,
- authenticateBiometric: authenticate,
- updateBiometricToken,
- openBiometricSettings: openSettings,
- onBiometricManagerUpdated,
- onBiometricAuthRequested,
- onBiometricTokenUpdated,
- }
-}
diff --git a/src/composables/useWebAppClipboard.ts b/src/composables/useWebAppClipboard.ts
deleted file mode 100644
index bf47555..0000000
--- a/src/composables/useWebAppClipboard.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { useWebApp } from './useWebApp'
-
-export function useWebAppClipboard() {
- const { onEvent } = useWebApp()
-
- const onClipboardTextReceived = (
- eventHandler: ClipboardTextReceivedCallback,
- options?: OnEventOptions,
- ) => onEvent('clipboardTextReceived', eventHandler, options)
-
- const { readTextFromClipboard } = Telegram.WebApp
-
- return {
- readTextFromClipboard,
- onClipboardTextReceived,
- }
-}
diff --git a/src/composables/useWebAppClosingConfirmation.ts b/src/composables/useWebAppClosingConfirmation.ts
deleted file mode 100644
index 567f730..0000000
--- a/src/composables/useWebAppClosingConfirmation.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { computed, ref } from 'vue'
-import { defineStore } from '../utils'
-
-const useStore = defineStore(() => {
- const isClosingConfirmationEnabled = ref(
- Telegram.WebApp.isClosingConfirmationEnabled,
- )
-
- function updateStatus() {
- isClosingConfirmationEnabled.value
- = Telegram.WebApp.isClosingConfirmationEnabled
- }
-
- function enableClosingConfirmation(
- ...params: Parameters
- ) {
- Telegram.WebApp.enableClosingConfirmation(...params)
- updateStatus()
- }
-
- function disableClosingConfirmation(
- ...params: Parameters
- ) {
- Telegram.WebApp.disableClosingConfirmation(...params)
- updateStatus()
- }
-
- return {
- isClosingConfirmationEnabled,
- updateStatus,
- enableClosingConfirmation,
- disableClosingConfirmation,
- }
-})
-
-export function useWebAppClosingConfirmation() {
- const {
- isClosingConfirmationEnabled,
- enableClosingConfirmation,
- disableClosingConfirmation,
- } = useStore()
-
- return {
- isClosingConfirmationEnabled: computed({
- get() {
- return isClosingConfirmationEnabled.value
- },
- set(isEnabled) {
- isEnabled ? enableClosingConfirmation() : disableClosingConfirmation()
- },
- }),
- enableClosingConfirmation,
- disableClosingConfirmation,
- }
-}
diff --git a/src/composables/useWebAppCloudStorage.ts b/src/composables/useWebAppCloudStorage.ts
deleted file mode 100644
index 5e8fad8..0000000
--- a/src/composables/useWebAppCloudStorage.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-type SetItemResult = Parameters<
- NonNullable<
- NonNullable>[2]
- >
->[1]
-
-function setStorageItem(key: string, value: string) {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.setItem(key, value, (error, ok) => {
- if (error)
- reject(error)
-
- resolve(ok)
- })
- })
-}
-
-type GetItemResult = Parameters<
- NonNullable<
- NonNullable>[1]
- >
->[1]
-
-function getStorageItem(key: string) {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.getItem(key, (error, value) => {
- if (error)
- reject(error)
-
- resolve(value)
- })
- })
-}
-
-type GetItemsResult = NonNullable<
- Parameters<
- NonNullable<
- NonNullable>[1]
- >
- >[1]
->
-
-function getStorageItems(keys: string[]) {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.getItems(keys, (error, values) => {
- if (error)
- reject(error)
-
- resolve(values as GetItemsResult)
- })
- })
-}
-
-type RemoveItemResult = Parameters<
- NonNullable<
- NonNullable>[1]
- >
->[1]
-
-function removeStorageItem(key: string) {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.removeItem(key, (error, ok) => {
- if (error)
- reject(error)
-
- resolve(ok)
- })
- })
-}
-
-type RemoveItemsResult = Parameters<
- NonNullable<
- NonNullable>[1]
- >
->[1]
-
-function removeStorageItems(keys: string[]) {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.removeItems(keys, (error, ok) => {
- if (error)
- reject(error)
-
- resolve(ok)
- })
- })
-}
-
-type GetKeysResult = NonNullable<
- Parameters<
- NonNullable<
- NonNullable>[0]
- >
- >[1]
->
-
-function getStorageKeys() {
- return new Promise((resolve, reject) => {
- Telegram.WebApp.CloudStorage.getKeys((error, values) => {
- if (error)
- reject(error)
-
- resolve(values as GetKeysResult)
- })
- })
-}
-
-export function useWebAppCloudStorage() {
- return {
- setStorageItem,
- getStorageItem,
- getStorageItems,
- removeStorageItem,
- removeStorageItems,
- getStorageKeys,
- }
-}
diff --git a/src/composables/useWebAppHapticFeedback.ts b/src/composables/useWebAppHapticFeedback.ts
deleted file mode 100644
index 81b7106..0000000
--- a/src/composables/useWebAppHapticFeedback.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export function useWebAppHapticFeedback() {
- const { impactOccurred, notificationOccurred, selectionChanged }
- = Telegram.WebApp.HapticFeedback
-
- return {
- impactOccurred,
- notificationOccurred,
- selectionChanged,
- }
-}
diff --git a/src/composables/useWebAppMainButton.ts b/src/composables/useWebAppMainButton.ts
deleted file mode 100644
index e5ee2ff..0000000
--- a/src/composables/useWebAppMainButton.ts
+++ /dev/null
@@ -1,188 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { computed, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const mainButtonText = ref(Telegram.WebApp.MainButton.text)
- const mainButtonColor = ref(Telegram.WebApp.MainButton.color)
- const mainButtonTextColor = ref(Telegram.WebApp.MainButton.textColor)
- const isMainButtonVisible = ref(Telegram.WebApp.MainButton.isVisible)
- const isMainButtonActive = ref(Telegram.WebApp.MainButton.isActive)
- const isMainButtonProgressVisible = ref(
- Telegram.WebApp.MainButton.isProgressVisible,
- )
-
- function updateState() {
- mainButtonText.value = Telegram.WebApp.MainButton.text
- mainButtonColor.value = Telegram.WebApp.MainButton.color
- mainButtonTextColor.value = Telegram.WebApp.MainButton.textColor
- isMainButtonVisible.value = Telegram.WebApp.MainButton.isVisible
- isMainButtonActive.value = Telegram.WebApp.MainButton.isActive
- isMainButtonProgressVisible.value
- = Telegram.WebApp.MainButton.isProgressVisible
- }
-
- function setMainButtonText(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.setText(...params)
- updateState()
- }
-
- function showMainButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.show(...params)
- updateState()
- }
-
- function hideMainButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.hide(...params)
- updateState()
- }
-
- function enableMainButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.enable(...params)
- updateState()
- }
-
- function disableMainButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.disable(...params)
- updateState()
- }
-
- function showMainButtonProgress(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.showProgress(...params)
- updateState()
- }
-
- function hideMainButtonProgress(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.hideProgress(...params)
- updateState()
- }
-
- function setMainButtonParams(
- ...params: Parameters
- ) {
- Telegram.WebApp.MainButton.setParams(...params)
- updateState()
- }
-
- return {
- mainButtonText,
- mainButtonColor,
- mainButtonTextColor,
- isMainButtonVisible,
- isMainButtonActive,
- isMainButtonProgressVisible,
- setMainButtonText,
- showMainButton,
- hideMainButton,
- enableMainButton,
- disableMainButton,
- showMainButtonProgress,
- hideMainButtonProgress,
- setMainButtonParams,
- }
-})
-
-export function useWebAppMainButton() {
- const {
- mainButtonText,
- mainButtonColor,
- mainButtonTextColor,
- isMainButtonVisible,
- isMainButtonActive,
- isMainButtonProgressVisible,
- setMainButtonText,
- showMainButton,
- hideMainButton,
- enableMainButton,
- disableMainButton,
- showMainButtonProgress,
- hideMainButtonProgress,
- setMainButtonParams,
- } = useStore()
-
- const { onEvent } = useWebApp()
-
- const onMainButtonClicked = (
- eventHandler: MainButtonClickedCallback,
- options?: OnEventOptions,
- ) => onEvent('mainButtonClicked', eventHandler, options)
-
- return {
- mainButtonText: computed({
- get() {
- return mainButtonText.value
- },
- set(text) {
- setMainButtonText(text)
- },
- }),
- mainButtonColor: computed({
- get() {
- return mainButtonColor.value
- },
- set(color) {
- setMainButtonParams({
- color,
- })
- },
- }),
- mainButtonTextColor: computed({
- get() {
- return mainButtonTextColor.value
- },
- set(color) {
- setMainButtonParams({
- text_color: color,
- })
- },
- }),
- isMainButtonVisible: computed({
- get() {
- return isMainButtonVisible.value
- },
- set(isVisible) {
- isVisible ? showMainButton() : hideMainButton()
- },
- }),
- isMainButtonActive: computed({
- get() {
- return isMainButtonActive.value
- },
- set(isActive) {
- isActive ? enableMainButton() : disableMainButton()
- },
- }),
- isMainButtonProgressVisible: computed({
- get() {
- return isMainButtonProgressVisible.value
- },
- set(isProgressVisible) {
- isProgressVisible ? showMainButtonProgress() : hideMainButtonProgress()
- },
- }),
- setMainButtonText,
- onMainButtonClicked,
- showMainButton,
- hideMainButton,
- enableMainButton,
- disableMainButton,
- showMainButtonProgress,
- hideMainButtonProgress,
- setMainButtonParams,
- }
-}
diff --git a/src/composables/useWebAppNavigation.ts b/src/composables/useWebAppNavigation.ts
deleted file mode 100644
index e818db3..0000000
--- a/src/composables/useWebAppNavigation.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { useWebApp } from './useWebApp'
-
-export function useWebAppNavigation() {
- const { onEvent } = useWebApp()
-
- const onInvoiceClosed = (
- eventHandler: InvoiceClosedCallback,
- options?: OnEventOptions,
- ) => onEvent('invoiceClosed', eventHandler, options)
-
- const { switchInlineQuery, openLink, openTelegramLink, openInvoice }
- = Telegram.WebApp
-
- return {
- switchInlineQuery,
- openLink,
- openTelegramLink,
- openInvoice,
- onInvoiceClosed,
- }
-}
diff --git a/src/composables/useWebAppPopup.ts b/src/composables/useWebAppPopup.ts
deleted file mode 100644
index 35bf63d..0000000
--- a/src/composables/useWebAppPopup.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { useWebApp } from './useWebApp'
-
-export function useWebAppPopup() {
- const { onEvent } = useWebApp()
-
- const onPopupClosed = (
- eventHandler: PopupClosedCallback,
- options?: OnEventOptions,
- ) => onEvent('popupClosed', eventHandler, options)
-
- const { showPopup, showAlert, showConfirm } = Telegram.WebApp
-
- return {
- showPopup,
- showAlert,
- showConfirm,
- onPopupClosed,
- }
-}
diff --git a/src/composables/useWebAppQrScanner.ts b/src/composables/useWebAppQrScanner.ts
deleted file mode 100644
index 91483c6..0000000
--- a/src/composables/useWebAppQrScanner.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { useWebApp } from './useWebApp'
-
-export function useWebAppQrScanner() {
- const { onEvent } = useWebApp()
-
- const onQrTextReceived = (
- eventHandler: QrTextReceivedCallback,
- options?: OnEventOptions,
- ) => onEvent('qrTextReceived', eventHandler, options)
-
- const onScanQrPopupClosed = (
- eventHandler: ScanQrPopupClosedCallback,
- options?: OnEventOptions,
- ) => onEvent('scanQrPopupClosed', eventHandler, options)
-
- const { showScanQrPopup, closeScanQrPopup } = Telegram.WebApp
-
- return {
- showScanQrPopup,
- closeScanQrPopup,
- onQrTextReceived,
- onScanQrPopupClosed,
- }
-}
diff --git a/src/composables/useWebAppRequests.ts b/src/composables/useWebAppRequests.ts
deleted file mode 100644
index 1fb921d..0000000
--- a/src/composables/useWebAppRequests.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { useWebApp } from './useWebApp'
-
-export function useWebAppRequests() {
- const { onEvent } = useWebApp()
-
- const onWriteAccessRequested = (
- eventHandler: WriteAccessRequestedCallback,
- options?: OnEventOptions,
- ) => onEvent('writeAccessRequested', eventHandler, options)
-
- const onContactRequested = (
- eventHandler: ContactRequestedCallback,
- options?: OnEventOptions,
- ) => onEvent('contactRequested', eventHandler, options)
-
- const { requestContact, requestWriteAccess } = Telegram.WebApp
-
- return {
- requestContact,
- onContactRequested,
- requestWriteAccess,
- onWriteAccessRequested,
- }
-}
diff --git a/src/composables/useWebAppSettingsButton.ts b/src/composables/useWebAppSettingsButton.ts
deleted file mode 100644
index 317c796..0000000
--- a/src/composables/useWebAppSettingsButton.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { computed, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const isSettingsButtonVisible = ref(Telegram.WebApp.SettingsButton.isVisible)
-
- function showSettingsButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.SettingsButton.show(...params)
- isSettingsButtonVisible.value = true
- }
-
- function hideSettingsButton(
- ...params: Parameters
- ) {
- Telegram.WebApp.SettingsButton.hide(...params)
- isSettingsButtonVisible.value = false
- }
-
- return {
- isSettingsButtonVisible,
- showSettingsButton,
- hideSettingsButton,
- }
-})
-
-export function useWebAppSettingsButton() {
- const { isSettingsButtonVisible, showSettingsButton, hideSettingsButton }
- = useStore()
-
- const { onEvent } = useWebApp()
-
- const onSettingsButtonClicked = (
- eventHandler: SettingsButtonClickedCallback,
- options?: OnEventOptions,
- ) => onEvent('settingsButtonClicked', eventHandler, options)
-
- return {
- isSettingsButtonVisible: computed({
- get() {
- return isSettingsButtonVisible.value
- },
- set(isVisible) {
- isVisible ? showSettingsButton() : hideSettingsButton()
- },
- }),
- onSettingsButtonClicked,
- showSettingsButton,
- hideSettingsButton,
- }
-}
diff --git a/src/composables/useWebAppShare.ts b/src/composables/useWebAppShare.ts
deleted file mode 100644
index 7bca780..0000000
--- a/src/composables/useWebAppShare.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-interface StoryWidgetLink {
- url: string
- name?: string
-}
-
-interface StoryShareParams {
- text?: string
- widgetLink?: StoryWidgetLink
-}
-
-function shareToStory(mediaUrl: string, params?: StoryShareParams) {
- Telegram.WebApp.shareToStory(mediaUrl, params)
-}
-
-export function useWebAppShare() {
- return {
- shareToStory,
- }
-}
diff --git a/src/composables/useWebAppTheme.ts b/src/composables/useWebAppTheme.ts
deleted file mode 100644
index 832a7ff..0000000
--- a/src/composables/useWebAppTheme.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { computed, readonly, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const colorScheme = ref(Telegram.WebApp.colorScheme)
- const themeParams = ref(Telegram.WebApp.themeParams)
- const headerColor = ref(Telegram.WebApp.headerColor)
- const backgroundColor = ref(Telegram.WebApp.backgroundColor)
-
- function updateState() {
- colorScheme.value = Telegram.WebApp.colorScheme
- themeParams.value = {
- ...Telegram.WebApp.themeParams,
- }
- headerColor.value = Telegram.WebApp.headerColor
- backgroundColor.value = Telegram.WebApp.backgroundColor
- }
-
- function setHeaderColor(
- ...params: Parameters
- ) {
- Telegram.WebApp.setHeaderColor(...params)
- updateState()
- }
-
- function setBackgroundColor(
- ...params: Parameters
- ) {
- Telegram.WebApp.setBackgroundColor(...params)
- updateState()
- }
-
- return {
- colorScheme,
- themeParams,
- headerColor,
- backgroundColor,
- updateState,
- setHeaderColor,
- setBackgroundColor,
- }
-})
-
-export function useWebAppTheme() {
- const {
- colorScheme,
- themeParams,
- headerColor,
- backgroundColor,
- updateState,
- setHeaderColor,
- setBackgroundColor,
- } = useStore()
-
- const { onEvent } = useWebApp()
-
- const onThemeChanged = (eventHandler: () => void, options?: OnEventOptions) =>
- onEvent('themeChanged', eventHandler, options)
-
- onThemeChanged(updateState)
-
- return {
- colorScheme: readonly(colorScheme),
- themeParams: readonly(themeParams),
- headerColor: computed({
- get() {
- return headerColor.value
- },
- set(newValue) {
- setHeaderColor(newValue)
- },
- }),
- backgroundColor: computed({
- get() {
- return backgroundColor.value
- },
- set(newValue) {
- setBackgroundColor(newValue)
- },
- }),
- setHeaderColor,
- setBackgroundColor,
- onThemeChanged,
- }
-}
diff --git a/src/composables/useWebAppViewport.ts b/src/composables/useWebAppViewport.ts
deleted file mode 100644
index 5c967a1..0000000
--- a/src/composables/useWebAppViewport.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type { OnEventOptions } from '../types'
-import { computed, readonly, ref } from 'vue'
-import { defineStore } from '../utils'
-import { useWebApp } from './useWebApp'
-
-const useStore = defineStore(() => {
- const isExpanded = ref(Telegram.WebApp.isExpanded)
- const viewportHeight = ref(Telegram.WebApp.viewportHeight)
- const viewportStableHeight = ref(Telegram.WebApp.viewportStableHeight)
- const isVerticalSwipesEnabled = ref(Telegram.WebApp.isVerticalSwipesEnabled)
-
- function updateState() {
- isExpanded.value = Telegram.WebApp.isExpanded
- viewportHeight.value = Telegram.WebApp.viewportHeight
- viewportStableHeight.value = Telegram.WebApp.viewportStableHeight
- isVerticalSwipesEnabled.value = Telegram.WebApp.isVerticalSwipesEnabled
- }
-
- function expand(...params: Parameters) {
- Telegram.WebApp.expand(...params)
- updateState()
- }
-
- const enableVerticalSwipes: typeof Telegram.WebApp.enableVerticalSwipes = (
- ...params
- ) => {
- Telegram.WebApp.enableVerticalSwipes(...params)
- updateState()
- }
-
- const disableVerticalSwipes: typeof Telegram.WebApp.disableVerticalSwipes = (
- ...params
- ) => {
- Telegram.WebApp.disableVerticalSwipes(...params)
- updateState()
- }
-
- return {
- isExpanded,
- viewportHeight,
- viewportStableHeight,
- isVerticalSwipesEnabled,
- updateState,
- expand,
- enableVerticalSwipes,
- disableVerticalSwipes,
- }
-})
-
-export function useWebAppViewport() {
- const {
- isExpanded,
- viewportHeight,
- viewportStableHeight,
- isVerticalSwipesEnabled,
- updateState,
- expand,
- enableVerticalSwipes,
- disableVerticalSwipes,
- } = useStore()
-
- const { onEvent } = useWebApp()
-
- const onViewportChanged = (
- eventHandler: ViewportChangedCallback,
- options?: OnEventOptions,
- ) => onEvent('viewportChanged', eventHandler, options)
-
- onViewportChanged(updateState)
-
- return {
- isExpanded: readonly(isExpanded),
- viewportHeight: readonly(viewportHeight),
- viewportStableHeight: readonly(viewportStableHeight),
- expand,
- onViewportChanged,
- isVerticalSwipesEnabled: computed({
- get() {
- return isVerticalSwipesEnabled.value
- },
- set(isEnabled) {
- isEnabled ? enableVerticalSwipes() : disableVerticalSwipes()
- },
- }),
- enableVerticalSwipes,
- disableVerticalSwipes,
- }
-}
diff --git a/src/events.ts b/src/events.ts
new file mode 100644
index 0000000..fb56b30
--- /dev/null
+++ b/src/events.ts
@@ -0,0 +1,206 @@
+import type { EventCallback } from './sdk'
+import type { OnEventOptions, OnEventWithOptions } from './types'
+import { onMounted, onUnmounted } from 'vue'
+import { getWebApp } from './sdk'
+
+export const onEvent: OnEventWithOptions = (
+ eventType,
+ eventHandler,
+ options = { manual: false },
+) => {
+ const { manual } = options
+ const webApp = getWebApp()
+
+ const on = () =>
+ webApp.onEvent(eventType, eventHandler)
+ const off = () =>
+ webApp.offEvent(eventType, eventHandler)
+
+ if (manual) {
+ on()
+ }
+ else {
+ onMounted(on)
+ onUnmounted(off)
+ }
+
+ return {
+ off,
+ }
+}
+
+export function onActivated(eventHandler: EventCallback['activated'], options?: OnEventOptions) {
+ return onEvent('activated', eventHandler, options)
+}
+
+export function onDeactivated(eventHandler: EventCallback['deactivated'], options?: OnEventOptions) {
+ return onEvent('deactivated', eventHandler, options)
+}
+
+export function onThemeChanged(eventHandler: EventCallback['themeChanged'], options?: OnEventOptions) {
+ return onEvent('themeChanged', eventHandler, options)
+}
+
+export function onViewportChanged(eventHandler: EventCallback['viewportChanged'], options?: OnEventOptions) {
+ return onEvent('viewportChanged', eventHandler, options)
+}
+
+export function onSafeAreaChanged(eventHandler: EventCallback['safeAreaChanged'], options?: OnEventOptions) {
+ return onEvent('safeAreaChanged', eventHandler, options)
+}
+
+export function onContentSafeAreaChanged(eventHandler: EventCallback['contentSafeAreaChanged'], options?: OnEventOptions) {
+ return onEvent('contentSafeAreaChanged', eventHandler, options)
+}
+
+export function onMainButtonClicked(eventHandler: EventCallback['mainButtonClicked'], options?: OnEventOptions) {
+ return onEvent('mainButtonClicked', eventHandler, options)
+}
+
+export function onSecondaryButtonClicked(eventHandler: EventCallback['secondaryButtonClicked'], options?: OnEventOptions) {
+ return onEvent('secondaryButtonClicked', eventHandler, options)
+}
+
+export function onBackButtonClicked(eventHandler: EventCallback['backButtonClicked'], options?: OnEventOptions) {
+ return onEvent('backButtonClicked', eventHandler, options)
+}
+
+export function onSettingsButtonClicked(eventHandler: EventCallback['settingsButtonClicked'], options?: OnEventOptions) {
+ return onEvent('settingsButtonClicked', eventHandler, options)
+}
+
+export function onInvoiceClosed(eventHandler: EventCallback['invoiceClosed'], options?: OnEventOptions) {
+ return onEvent('invoiceClosed', eventHandler, options)
+}
+
+export function onPopupClosed(eventHandler: EventCallback['popupClosed'], options?: OnEventOptions) {
+ return onEvent('popupClosed', eventHandler, options)
+}
+
+export function onQrTextReceived(eventHandler: EventCallback['qrTextReceived'], options?: OnEventOptions) {
+ return onEvent('qrTextReceived', eventHandler, options)
+}
+
+export function onScanQrPopupClosed(eventHandler: EventCallback['scanQrPopupClosed'], options?: OnEventOptions) {
+ return onEvent('scanQrPopupClosed', eventHandler, options)
+}
+
+export function onClipboardTextReceived(eventHandler: EventCallback['clipboardTextReceived'], options?: OnEventOptions) {
+ return onEvent('clipboardTextReceived', eventHandler, options)
+}
+
+export function onWriteAccessRequested(eventHandler: EventCallback['writeAccessRequested'], options?: OnEventOptions) {
+ return onEvent('writeAccessRequested', eventHandler, options)
+}
+
+export function onContactRequested(eventHandler: EventCallback['contactRequested'], options?: OnEventOptions) {
+ return onEvent('contactRequested', eventHandler, options)
+}
+
+export function onBiometricManagerUpdated(eventHandler: EventCallback['biometricManagerUpdated'], options?: OnEventOptions) {
+ return onEvent('biometricManagerUpdated', eventHandler, options)
+}
+
+export function onBiometricAuthRequested(eventHandler: EventCallback['biometricAuthRequested'], options?: OnEventOptions) {
+ return onEvent('biometricAuthRequested', eventHandler, options)
+}
+
+export function onBiometricTokenUpdated(eventHandler: EventCallback['biometricTokenUpdated'], options?: OnEventOptions) {
+ return onEvent('biometricTokenUpdated', eventHandler, options)
+}
+
+export function onFullscreenChanged(eventHandler: EventCallback['fullscreenChanged'], options?: OnEventOptions) {
+ return onEvent('fullscreenChanged', eventHandler, options)
+}
+
+export function onFullscreenFailed(eventHandler: EventCallback['fullscreenFailed'], options?: OnEventOptions) {
+ return onEvent('fullscreenFailed', eventHandler, options)
+}
+
+export function onHomeScreenAdded(eventHandler: EventCallback['homeScreenAdded'], options?: OnEventOptions) {
+ return onEvent('homeScreenAdded', eventHandler, options)
+}
+
+export function onHomeScreenChecked(eventHandler: EventCallback['homeScreenChecked'], options?: OnEventOptions) {
+ return onEvent('homeScreenChecked', eventHandler, options)
+}
+
+export function onAccelerometerStarted(eventHandler: EventCallback['accelerometerStarted'], options?: OnEventOptions) {
+ return onEvent('accelerometerStarted', eventHandler, options)
+}
+
+export function onAccelerometerStopped(eventHandler: EventCallback['accelerometerStopped'], options?: OnEventOptions) {
+ return onEvent('accelerometerStopped', eventHandler, options)
+}
+
+export function onAccelerometerChanged(eventHandler: EventCallback['accelerometerChanged'], options?: OnEventOptions) {
+ return onEvent('accelerometerChanged', eventHandler, options)
+}
+
+export function onAccelerometerFailed(eventHandler: EventCallback['accelerometerFailed'], options?: OnEventOptions) {
+ return onEvent('accelerometerFailed', eventHandler, options)
+}
+
+export function onDeviceOrientationStarted(eventHandler: EventCallback['deviceOrientationStarted'], options?: OnEventOptions) {
+ return onEvent('deviceOrientationStarted', eventHandler, options)
+}
+
+export function onDeviceOrientationStopped(eventHandler: EventCallback['deviceOrientationStopped'], options?: OnEventOptions) {
+ return onEvent('deviceOrientationStopped', eventHandler, options)
+}
+
+export function onDeviceOrientationChanged(eventHandler: EventCallback['deviceOrientationChanged'], options?: OnEventOptions) {
+ return onEvent('deviceOrientationChanged', eventHandler, options)
+}
+
+export function onDeviceOrientationFailed(eventHandler: EventCallback['deviceOrientationFailed'], options?: OnEventOptions) {
+ return onEvent('deviceOrientationFailed', eventHandler, options)
+}
+
+export function onGyroscopeStarted(eventHandler: EventCallback['gyroscopeStarted'], options?: OnEventOptions) {
+ return onEvent('gyroscopeStarted', eventHandler, options)
+}
+
+export function onGyroscopeStopped(eventHandler: EventCallback['gyroscopeStopped'], options?: OnEventOptions) {
+ return onEvent('gyroscopeStopped', eventHandler, options)
+}
+
+export function onGyroscopeChanged(eventHandler: EventCallback['gyroscopeChanged'], options?: OnEventOptions) {
+ return onEvent('gyroscopeChanged', eventHandler, options)
+}
+
+export function onGyroscopeFailed(eventHandler: EventCallback['gyroscopeFailed'], options?: OnEventOptions) {
+ return onEvent('gyroscopeFailed', eventHandler, options)
+}
+
+export function onLocationManagerUpdated(eventHandler: EventCallback['locationManagerUpdated'], options?: OnEventOptions) {
+ return onEvent('locationManagerUpdated', eventHandler, options)
+}
+
+export function onLocationRequested(eventHandler: EventCallback['locationRequested'], options?: OnEventOptions) {
+ return onEvent('locationRequested', eventHandler, options)
+}
+
+export function onShareMessageSent(eventHandler: EventCallback['shareMessageSent'], options?: OnEventOptions) {
+ return onEvent('shareMessageSent', eventHandler, options)
+}
+
+export function onShareMessageFailed(eventHandler: EventCallback['shareMessageFailed'], options?: OnEventOptions) {
+ return onEvent('shareMessageFailed', eventHandler, options)
+}
+
+export function onEmojiStatusSet(eventHandler: EventCallback['emojiStatusSet'], options?: OnEventOptions) {
+ return onEvent('emojiStatusSet', eventHandler, options)
+}
+
+export function onEmojiStatusFailed(eventHandler: EventCallback['emojiStatusFailed'], options?: OnEventOptions) {
+ return onEvent('emojiStatusFailed', eventHandler, options)
+}
+
+export function onEmojiStatusAccessRequested(eventHandler: EventCallback['emojiStatusAccessRequested'], options?: OnEventOptions) {
+ return onEvent('emojiStatusAccessRequested', eventHandler, options)
+}
+
+export function onFileDownloadRequested(eventHandler: EventCallback['fileDownloadRequested'], options?: OnEventOptions) {
+ return onEvent('fileDownloadRequested', eventHandler, options)
+}
diff --git a/src/index.ts b/src/index.ts
index ffddaf6..288bab0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -9,12 +9,41 @@ import ExpandedViewport from './components/ExpandedViewport.vue'
import MainButton from './components/MainButton.vue'
import Popup from './components/Popup.vue'
import ScanQr from './components/ScanQr.vue'
+import SecondaryButton from './components/SecondaryButton.vue'
import SettingsButton from './components/SettingsButton.vue'
+import { createComposablesWithVersion } from './versions/helpers'
import DiscussionWidget from './widgets/DiscussionWidget.vue'
import LoginWidget from './widgets/LoginWidget.vue'
import PostWidget from './widgets/PostWidget.vue'
import ShareWidget from './widgets/ShareWidget.vue'
+export * from './composables-legacy'
+export { isVersionAtLeast } from './composables/useMiniApp'
+export * from './events'
+export type { LoginWidgetUser } from './types'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.0')
+
export {
Alert,
BackButton,
@@ -28,30 +57,11 @@ export {
Popup,
PostWidget,
ScanQr,
+ SecondaryButton,
SettingsButton,
ShareWidget,
}
-export { useWebApp } from './composables/useWebApp'
-
-export { useWebAppBackButton } from './composables/useWebAppBackButton'
-export { useWebAppBiometricManager } from './composables/useWebAppBiometricManager'
-export { useWebAppClipboard } from './composables/useWebAppClipboard'
-export { useWebAppClosingConfirmation } from './composables/useWebAppClosingConfirmation'
-export { useWebAppCloudStorage } from './composables/useWebAppCloudStorage'
-export { useWebAppHapticFeedback } from './composables/useWebAppHapticFeedback'
-export { useWebAppMainButton } from './composables/useWebAppMainButton'
-export { useWebAppNavigation } from './composables/useWebAppNavigation'
-export { useWebAppPopup } from './composables/useWebAppPopup'
-export { useWebAppQrScanner } from './composables/useWebAppQrScanner'
-export { useWebAppRequests } from './composables/useWebAppRequests'
-export { useWebAppSendData } from './composables/useWebAppSendData'
-export { useWebAppSettingsButton } from './composables/useWebAppSettingsButton'
-export { useWebAppShare } from './composables/useWebAppShare'
-export { useWebAppTheme } from './composables/useWebAppTheme'
-export { useWebAppViewport } from './composables/useWebAppViewport'
-export type { LoginWidgetUser } from './types'
-
const plugin = {
install(Vue: App) {
Vue.component('TgAlert', Alert)
@@ -63,6 +73,7 @@ const plugin = {
Vue.component('TgMainButton', MainButton)
Vue.component('TgPopup', Popup)
Vue.component('TgScanQr', ScanQr)
+ Vue.component('TgSecondaryButton', SecondaryButton)
Vue.component('TgSettingsButton', SettingsButton)
Vue.component('TgShareWidget', ShareWidget)
Vue.component('TgPostWidget', PostWidget)
@@ -82,6 +93,7 @@ declare module '@vue/runtime-core' {
TgMainButton: typeof MainButton
TgPopup: typeof Popup
TgScanQr: typeof ScanQr
+ TgSecondaryButton: typeof SecondaryButton
TgSettingsButton: typeof SettingsButton
TgShareWidget: typeof ShareWidget
TgPostWidget: typeof PostWidget
diff --git a/src/sdk/accelerometer.ts b/src/sdk/accelerometer.ts
new file mode 100644
index 0000000..7ad9e59
--- /dev/null
+++ b/src/sdk/accelerometer.ts
@@ -0,0 +1,20 @@
+export type Accelerometer = {
+ isStarted: boolean
+ x: number
+ y: number
+ z: number
+ start: (
+ params: AccelerometerStartParams,
+ callback?: AccelerometerCallback['start']
+ ) => Accelerometer
+ stop: (callback?: AccelerometerCallback['stop']) => Accelerometer
+}
+
+export type AccelerometerStartParams = {
+ refresh_rate?: number
+}
+
+export type AccelerometerCallback = {
+ start: (success: boolean) => void
+ stop: (success: boolean) => void
+}
diff --git a/src/sdk/back-button.ts b/src/sdk/back-button.ts
new file mode 100644
index 0000000..c984b48
--- /dev/null
+++ b/src/sdk/back-button.ts
@@ -0,0 +1,9 @@
+import type { EventCallback } from './events'
+
+export type BackButton = {
+ isVisible: boolean
+ onClick: (callback: EventCallback['backButtonClicked']) => BackButton
+ offClick: (callback: EventCallback['backButtonClicked']) => BackButton
+ show: () => BackButton
+ hide: () => BackButton
+}
diff --git a/src/sdk/biometric-manager.ts b/src/sdk/biometric-manager.ts
new file mode 100644
index 0000000..b64409b
--- /dev/null
+++ b/src/sdk/biometric-manager.ts
@@ -0,0 +1,38 @@
+export type BiometricManager = {
+ isInited: boolean
+ isBiometricAvailable: boolean
+ biometricType: 'finger' | 'face' | 'unknown'
+ isAccessRequested: boolean
+ isAccessGranted: boolean
+ isBiometricTokenSaved: boolean
+ deviceId: string
+ init: (callback?: BiometricManagerCallback['init']) => BiometricManager
+ requestAccess: (
+ params: BiometricRequestAccessParams,
+ callback?: BiometricManagerCallback['requestAccess']
+ ) => BiometricManager
+ authenticate: (
+ params: BiometricAuthenticateParams,
+ callback?: BiometricManagerCallback['authenticate']
+ ) => BiometricManager
+ updateBiometricToken: (
+ token: string,
+ callback?: BiometricManagerCallback['updateBiometricToken']
+ ) => BiometricManager
+ openSettings: () => BiometricManager
+}
+
+export type BiometricManagerCallback = {
+ init: () => void
+ requestAccess: (isGranted: boolean) => void
+ authenticate: (isAuthenticated: boolean, token?: string) => void
+ updateBiometricToken: (isUpdated: boolean) => void
+}
+
+export type BiometricRequestAccessParams = {
+ reason?: string
+}
+
+export type BiometricAuthenticateParams = {
+ reason?: string
+}
diff --git a/src/sdk/bottom-button.ts b/src/sdk/bottom-button.ts
new file mode 100644
index 0000000..c5ce01f
--- /dev/null
+++ b/src/sdk/bottom-button.ts
@@ -0,0 +1,31 @@
+import type { EventCallback } from './events'
+
+export type BottomButton = {
+ readonly type: 'main' | 'secondary'
+ text: string
+ color: string
+ textColor: string
+ isVisible: boolean
+ isActive: boolean
+ hasShineEffect: boolean
+ position?: 'left' | 'right' | 'top' | 'bottom'
+ readonly isProgressVisible: boolean
+ setText: (text: string) => BottomButton
+ onClick: (callback: EventCallback['mainButtonClicked']) => BottomButton
+ offClick: (callback: EventCallback['mainButtonClicked']) => BottomButton
+ show: () => BottomButton
+ hide: () => BottomButton
+ enable: () => BottomButton
+ disable: () => BottomButton
+ showProgress: (leaveActive?: boolean) => BottomButton
+ hideProgress: () => BottomButton
+ setParams: (params: {
+ text?: string
+ color?: string
+ text_color?: string
+ has_shine_effect?: boolean
+ position?: 'left' | 'right' | 'top' | 'bottom'
+ is_active?: boolean
+ is_visible?: boolean
+ }) => BottomButton
+}
diff --git a/src/sdk/cloud-storage.ts b/src/sdk/cloud-storage.ts
new file mode 100644
index 0000000..50d2b63
--- /dev/null
+++ b/src/sdk/cloud-storage.ts
@@ -0,0 +1,17 @@
+export type CloudStorage = {
+ setItem: (key: string, value: string, callback?: CloudStorageCallback['setItem']) => CloudStorage
+ getItem: (key: string, callback: CloudStorageCallback['getItem']) => CloudStorage
+ getItems: (keys: string[], callback: CloudStorageCallback['getItems']) => CloudStorage
+ removeItem: (key: string, callback?: CloudStorageCallback['removeItem']) => CloudStorage
+ removeItems: (keys: string[], callback?: CloudStorageCallback['removeItems']) => CloudStorage
+ getKeys: (callback: CloudStorageCallback['getKeys']) => CloudStorage
+}
+
+export type CloudStorageCallback = {
+ setItem: (error: string | null, success: null | true) => void
+ getItem: (error: string | null, value: null | string) => void
+ getItems: (error: string | null, values: null | Record) => void
+ removeItem: (error: string | null, success: null | true) => void
+ removeItems: (error: string | null, success: null | true) => void
+ getKeys: (error: string | null, keys: null | string[]) => void
+}
diff --git a/src/sdk/device-orientation.ts b/src/sdk/device-orientation.ts
new file mode 100644
index 0000000..69300e2
--- /dev/null
+++ b/src/sdk/device-orientation.ts
@@ -0,0 +1,22 @@
+export type DeviceOrientation = {
+ isStarted: boolean
+ absolute: boolean
+ alpha: number
+ beta: number
+ gamma: number
+ start: (
+ params: DeviceOrientationStartParams,
+ callback?: DeviceOrientationCallback['start']
+ ) => DeviceOrientation
+ stop: (callback?: DeviceOrientationCallback['stop']) => DeviceOrientation
+}
+
+export type DeviceOrientationCallback = {
+ start: (success: boolean) => void
+ stop: (success: boolean) => void
+}
+
+export type DeviceOrientationStartParams = {
+ refresh_rate?: number
+ need_absolute?: boolean
+}
diff --git a/src/sdk/events.ts b/src/sdk/events.ts
new file mode 100644
index 0000000..2fedd70
--- /dev/null
+++ b/src/sdk/events.ts
@@ -0,0 +1,93 @@
+import type { LocationData } from './location-manager'
+
+type RequestContactResponseSent = {
+ status: 'sent'
+ response: string
+ responseUnsafe: {
+ auth_date: string
+ contact: {
+ first_name: string
+ last_name?: string
+ phone_number: string
+ user_id: number
+ }
+ hash: string
+ }
+}
+
+type RequestContactResponseCancelled = {
+ status: 'cancelled'
+}
+
+export type EventData = {
+ viewportChanged: { isStateStable: boolean }
+ invoiceClosed: { url: string, status: 'paid' | 'cancelled' | 'failed' | 'pending' }
+ popupClosed: { button_id: string | null }
+ qrTextReceived: { data: string }
+ clipboardTextReceived: { data: string | null }
+ writeAccessRequested: { status: 'allowed' | 'cancelled' }
+ contactRequested: RequestContactResponseSent | RequestContactResponseCancelled
+ biometricAuthRequested: { isAuthenticated: boolean, biometricToken?: string }
+ biometricTokenUpdated: { isUpdated: boolean }
+ fullscreenFailed: { error: 'UNSUPPORTED' | 'ALREADY_FULLSCREEN' }
+ homeScreenChecked: { status: 'unsupported' | 'unknown' | 'added' | 'missed' }
+ accelerometerFailed: { error: 'UNSUPPORTED' }
+ deviceOrientationFailed: { error: 'UNSUPPORTED' }
+ gyroscopeFailed: { error: 'UNSUPPORTED' }
+ locationRequested: { locationData: LocationData }
+ shareMessageFailed: { error: 'UNSUPPORTED' | 'MESSAGE_EXPIRED' | 'MESSAGE_SEND_FAILED' | 'USER_DECLINED' | 'UNKNOWN_ERROR' }
+ emojiStatusFailed: { error: 'UNSUPPORTED' | 'SUGGESTED_EMOJI_INVALID' | 'DURATION_INVALID' | 'USER_DECLINED' | 'SERVER_ERROR' | 'UNKNOWN_ERROR' }
+ emojiStatusAccessRequested: { status: 'allowed' | 'cancelled' }
+ fileDownloadRequested: { status: 'downloading' | 'cancelled' }
+}
+
+export type EventCallback = {
+ activated: () => void
+ deactivated: () => void
+ themeChanged: () => void
+ viewportChanged: (eventData: EventData['viewportChanged']) => void
+ safeAreaChanged: () => void
+ contentSafeAreaChanged: () => void
+ mainButtonClicked: () => void
+ secondaryButtonClicked: () => void
+ backButtonClicked: () => void
+ settingsButtonClicked: () => void
+ invoiceClosed: (eventData: EventData['invoiceClosed']) => void
+ popupClosed: (eventData: EventData['popupClosed']) => void
+ qrTextReceived: (eventData: EventData['qrTextReceived']) => void
+ scanQrPopupClosed: () => void
+ clipboardTextReceived: (eventData: EventData['clipboardTextReceived']) => void
+ writeAccessRequested: (eventData: EventData['writeAccessRequested']) => void
+ contactRequested: (eventData: EventData['contactRequested']) => void
+ biometricManagerUpdated: () => void
+ biometricAuthRequested: (eventData: EventData['biometricAuthRequested']) => void
+ biometricTokenUpdated: (eventData: EventData['biometricTokenUpdated']) => void
+ fullscreenChanged: () => void
+ fullscreenFailed: (event: EventData['fullscreenFailed']) => void
+ homeScreenAdded: () => void
+ homeScreenChecked: (event: EventData['homeScreenChecked']) => void
+ accelerometerStarted: () => void
+ accelerometerStopped: () => void
+ accelerometerChanged: () => void
+ accelerometerFailed: (event: EventData['accelerometerFailed']) => void
+ deviceOrientationStarted: () => void
+ deviceOrientationStopped: () => void
+ deviceOrientationChanged: () => void
+ deviceOrientationFailed: (event: EventData['deviceOrientationFailed']) => void
+ gyroscopeStarted: () => void
+ gyroscopeStopped: () => void
+ gyroscopeChanged: () => void
+ gyroscopeFailed: (event: EventData['gyroscopeFailed']) => void
+ locationManagerUpdated: () => void
+ locationRequested: (event: EventData['locationRequested']) => void
+ shareMessageSent: () => void
+ shareMessageFailed: (event: EventData['shareMessageFailed']) => void
+ emojiStatusSet: () => void
+ emojiStatusFailed: (event: EventData['emojiStatusFailed']) => void
+ emojiStatusAccessRequested: (event: EventData['emojiStatusAccessRequested']) => void
+ fileDownloadRequested: (event: EventData['fileDownloadRequested']) => void
+}
+
+export type EventHandler = {
+ (eventType: T, eventHandler: EventCallback[T]): void
+}
diff --git a/src/sdk/gyroscope.ts b/src/sdk/gyroscope.ts
new file mode 100644
index 0000000..24ea825
--- /dev/null
+++ b/src/sdk/gyroscope.ts
@@ -0,0 +1,20 @@
+export type Gyroscope = {
+ isStarted: boolean
+ x: number
+ y: number
+ z: number
+ start: (
+ params: GyroscopeStartParams,
+ callback?: GyroscopeCallback['start']
+ ) => Gyroscope
+ stop: (callback?: GyroscopeCallback['stop']) => Gyroscope
+}
+
+export type GyroscopeCallback = {
+ start: (success: boolean) => void
+ stop: (success: boolean) => void
+}
+
+export type GyroscopeStartParams = {
+ refresh_rate?: number
+}
diff --git a/src/sdk/haptic-feedback.ts b/src/sdk/haptic-feedback.ts
new file mode 100644
index 0000000..ebd88ef
--- /dev/null
+++ b/src/sdk/haptic-feedback.ts
@@ -0,0 +1,9 @@
+export type HapticFeedback = {
+ impactOccurred: (
+ style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft'
+ ) => HapticFeedback
+ notificationOccurred: (
+ type: 'error' | 'success' | 'warning'
+ ) => HapticFeedback
+ selectionChanged: () => HapticFeedback
+}
diff --git a/src/sdk/index.ts b/src/sdk/index.ts
new file mode 100644
index 0000000..2476af8
--- /dev/null
+++ b/src/sdk/index.ts
@@ -0,0 +1,25 @@
+import type { WebApp } from './webapp'
+
+export * from './accelerometer'
+export * from './back-button'
+export * from './biometric-manager'
+export * from './bottom-button'
+export * from './cloud-storage'
+export * from './device-orientation'
+export * from './events'
+export * from './gyroscope'
+export * from './haptic-feedback'
+export * from './location-manager'
+export * from './popup'
+export * from './qr-scanner'
+export * from './settings-button'
+export * from './theme'
+export * from './viewport'
+export * from './webapp'
+
+export function getWebApp() {
+ if (!('Telegram' in window))
+ throw new Error('Telegram SDK not found. Make sure https://telegram.org/js/telegram-web-app.js script is installed.')
+ // @ts-expect-error not typed
+ return window?.Telegram?.WebApp as WebApp
+}
diff --git a/src/sdk/location-manager.ts b/src/sdk/location-manager.ts
new file mode 100644
index 0000000..4f3aff5
--- /dev/null
+++ b/src/sdk/location-manager.ts
@@ -0,0 +1,26 @@
+export type LocationManager = {
+ isInited: boolean
+ isLocationAvailable: boolean
+ isAccessRequested: boolean
+ isAccessGranted: boolean
+ init: (callback?: LocationManagerCallback['init']) => LocationManager
+ getLocation: (callback: LocationManagerCallback['getLocation']) => LocationManager
+ openSettings: () => LocationManager
+}
+
+export type LocationManagerCallback = {
+ init: () => void
+ getLocation: (data: LocationData | null) => void
+}
+
+export type LocationData = {
+ latitude: number
+ longitude: number
+ altitude: number | null
+ course: number | null
+ speed: number | null
+ horizontal_accuracy: number | null
+ vertical_accuracy: number | null
+ course_accuracy: number | null
+ speed_accuracy: number | null
+}
diff --git a/src/sdk/popup.ts b/src/sdk/popup.ts
new file mode 100644
index 0000000..15f75fc
--- /dev/null
+++ b/src/sdk/popup.ts
@@ -0,0 +1,11 @@
+export type PopupButton = {
+ id?: string
+ type?: 'default' | 'ok' | 'close' | 'cancel' | 'destructive'
+ text?: string
+}
+
+export type PopupParams = {
+ title?: string
+ message: string
+ buttons?: PopupButton[]
+}
diff --git a/src/sdk/qr-scanner.ts b/src/sdk/qr-scanner.ts
new file mode 100644
index 0000000..90212cb
--- /dev/null
+++ b/src/sdk/qr-scanner.ts
@@ -0,0 +1,3 @@
+export type ScanQrPopupParams = {
+ text?: string
+}
diff --git a/src/sdk/settings-button.ts b/src/sdk/settings-button.ts
new file mode 100644
index 0000000..d91b0f8
--- /dev/null
+++ b/src/sdk/settings-button.ts
@@ -0,0 +1,9 @@
+import type { EventCallback } from './events'
+
+export type SettingsButton = {
+ isVisible: boolean
+ onClick: (callback: EventCallback['settingsButtonClicked']) => SettingsButton
+ offClick: (callback: EventCallback['settingsButtonClicked']) => SettingsButton
+ show: () => SettingsButton
+ hide: () => SettingsButton
+}
diff --git a/src/sdk/theme.ts b/src/sdk/theme.ts
new file mode 100644
index 0000000..d1af3ce
--- /dev/null
+++ b/src/sdk/theme.ts
@@ -0,0 +1,17 @@
+export type ThemeParams = {
+ bg_color?: string
+ text_color?: string
+ hint_color?: string
+ link_color?: string
+ button_color?: string
+ button_text_color?: string
+ secondary_bg_color?: string
+ header_bg_color?: string
+ bottom_bar_bg_color?: string
+ accent_text_color?: string
+ section_bg_color?: string
+ section_header_text_color?: string
+ section_separator_color?: string
+ subtitle_text_color?: string
+ destructive_text_color?: string
+}
diff --git a/src/sdk/viewport.ts b/src/sdk/viewport.ts
new file mode 100644
index 0000000..161db97
--- /dev/null
+++ b/src/sdk/viewport.ts
@@ -0,0 +1,13 @@
+export type SafeAreaInset = {
+ top: number
+ bottom: number
+ left: number
+ right: number
+}
+
+export type ContentSafeAreaInset = {
+ top: number
+ bottom: number
+ left: number
+ right: number
+}
diff --git a/src/sdk/webapp.ts b/src/sdk/webapp.ts
new file mode 100644
index 0000000..cff7454
--- /dev/null
+++ b/src/sdk/webapp.ts
@@ -0,0 +1,161 @@
+import type { Accelerometer, AccelerometerCallback } from './accelerometer'
+import type { BackButton } from './back-button'
+import type { BiometricManager, BiometricManagerCallback } from './biometric-manager'
+import type { BottomButton } from './bottom-button'
+import type { CloudStorage, CloudStorageCallback } from './cloud-storage'
+import type { DeviceOrientation, DeviceOrientationCallback } from './device-orientation'
+import type { EventData, EventHandler } from './events'
+import type { Gyroscope, GyroscopeCallback } from './gyroscope'
+import type { HapticFeedback } from './haptic-feedback'
+import type { LocationManager, LocationManagerCallback } from './location-manager'
+import type { PopupParams } from './popup'
+import type { ScanQrPopupParams } from './qr-scanner'
+import type { SettingsButton } from './settings-button'
+import type { ThemeParams } from './theme'
+import type { ContentSafeAreaInset, SafeAreaInset } from './viewport'
+
+export type WebApp = {
+ initData: string
+ initDataUnsafe: WebAppInitData
+ version: string
+ platform: string
+ colorScheme: string
+ themeParams: ThemeParams
+ isActive: boolean
+ isExpanded: boolean
+ viewportHeight: number
+ viewportStableHeight: number
+ headerColor: string
+ backgroundColor: string
+ bottomBarColor: string
+ isClosingConfirmationEnabled: boolean
+ isVerticalSwipesEnabled: boolean
+ isFullscreen: boolean
+ isOrientationLocked: boolean
+ safeAreaInset: SafeAreaInset
+ contentSafeAreaInset: ContentSafeAreaInset
+ BackButton: BackButton
+ MainButton: BottomButton
+ SecondaryButton: BottomButton
+ SettingsButton: SettingsButton
+ HapticFeedback: HapticFeedback
+ CloudStorage: CloudStorage
+ BiometricManager: BiometricManager
+ Accelerometer: Accelerometer
+ DeviceOrientation: DeviceOrientation
+ Gyroscope: Gyroscope
+ LocationManager: LocationManager
+ isVersionAtLeast: (version: string) => boolean
+ setHeaderColor: (color: 'bg_color' | 'secondary_bg_color' | (string & {})) => void
+ setBackgroundColor: (color: 'bg_color' | 'secondary_bg_color' | (string & {})) => void
+ setBottomBarColor: (color: 'bg_color' | 'secondary_bg_color' | 'bottom_bar_bg_color' | (string & {})) => void
+ enableClosingConfirmation: () => void
+ disableClosingConfirmation: () => void
+ enableVerticalSwipes: () => void
+ disableVerticalSwipes: () => void
+ requestFullscreen: () => void
+ exitFullscreen: () => void
+ lockOrientation: () => void
+ unlockOrientation: () => void
+ addToHomeScreen: () => void
+ checkHomeScreenStatus: (callback?: WebAppCallback['checkHomeScreenStatus']) => void
+ onEvent: EventHandler
+ offEvent: EventHandler
+ sendData: (data: string) => void
+ switchInlineQuery: (query: string, choose_chat_types?: string[]) => void
+ openLink: (url: string, options?: { try_instant_view: boolean }) => void
+ openTelegramLink: (url: string) => void
+ openInvoice: (url: string, callback?: WebAppCallback['openInvoice']) => void
+ shareToStory: (media_url: string, params?: StoryShareParams) => void
+ shareMessage: (msg_id: string, callback?: WebAppCallback['shareMessage']) => void
+ setEmojiStatus: (custom_emoji_id: string, params?: EmojiStatusParams, callback?: WebAppCallback['setEmojiStatus']) => void
+ requestEmojiStatusAccess: (callback?: WebAppCallback['requestEmojiStatusAccess']) => void
+ downloadFile: (params: DownloadFileParams, callback?: WebAppCallback['downloadFile']) => void
+ showPopup: (params: PopupParams, callback?: WebAppCallback['showPopup']) => void
+ showAlert: (message: string, callback?: WebAppCallback['showAlert']) => void
+ showConfirm: (message: string, callback?: WebAppCallback['showConfirm']) => void
+ showScanQrPopup: (params: ScanQrPopupParams, callback?: WebAppCallback['showScanQrPopup']) => void
+ closeScanQrPopup: () => void
+ readTextFromClipboard: (callback?: WebAppCallback['readTextFromClipboard']) => void
+ requestWriteAccess: (callback?: WebAppCallback['requestWriteAccess']) => void
+ requestContact: (callback?: WebAppCallback['requestContact']) => void
+ ready: () => void
+ expand: () => void
+ close: () => void
+}
+
+export type WebAppCallback = {
+ checkHomeScreenStatus: (status: EventData['homeScreenChecked']['status']) => void
+ openInvoice: (status: EventData['invoiceClosed']['status']) => void
+ shareMessage: (success: boolean) => void
+ setEmojiStatus: (success: boolean) => void
+ requestEmojiStatusAccess: (granted: boolean) => void
+ downloadFile: (success: boolean) => void
+ showPopup: (buttonId: string) => void
+ showAlert: () => void
+ showConfirm: (isConfirmed: boolean) => void
+ showScanQrPopup: (text: string) => void
+ readTextFromClipboard: (text: string) => void
+ requestWriteAccess: (granted: boolean) => void
+ requestContact: (granted: boolean) => void
+ BiometricManager: BiometricManagerCallback
+ CloudStorage: CloudStorageCallback
+ Accelerometer: AccelerometerCallback
+ DeviceOrientation: DeviceOrientationCallback
+ Gyroscope: GyroscopeCallback
+ LocationManager: LocationManagerCallback
+}
+
+export type StoryShareParams = {
+ text?: string
+ widget_link?: StoryWidgetLink
+}
+
+export type StoryWidgetLink = {
+ url: string
+ name?: string
+}
+
+export type EmojiStatusParams = {
+ duration?: number
+}
+
+export type DownloadFileParams = {
+ url: string
+ file_name: string
+}
+
+export type WebAppInitData = {
+ query_id?: string
+ user?: WebAppUser
+ receiver?: WebAppUser
+ chat?: WebAppChat
+ chat_type?: string
+ chat_instance?: string
+ start_param?: string
+ can_send_after?: number
+ auth_date: number
+ hash: string
+ signature: string
+}
+
+export type WebAppUser = {
+ id: number
+ is_bot?: boolean
+ first_name: string
+ last_name?: string
+ username?: string
+ language_code?: string
+ is_premium?: true
+ added_to_attachment_menu?: true
+ allows_write_to_pm?: true
+ photo_url?: string
+}
+
+export type WebAppChat = {
+ id: number
+ type: string
+ title: string
+ username?: string
+ photo_url?: string
+}
diff --git a/src/types.ts b/src/types.ts
index b9a1a04..4bdddab 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,12 +1,74 @@
+import type { EventCallback, WebAppInitData, WebAppUser } from './sdk'
+
+type BOT_API_VERSIONS = [
+ '6.0',
+ '6.1',
+ '6.2',
+ '6.4',
+ '6.7',
+ '6.9',
+ '7.0',
+ '7.2',
+ '7.6',
+ '7.7',
+ '7.8',
+ '7.10',
+ '8.0',
+]
+
+export type LATEST_VERSION = '8.0'
+
+type Reverse = T extends [infer First, ...infer Rest]
+ ? [...Reverse, First]
+ : []
+
+type Equals = X extends Y ? (Y extends X ? true : false) : false
+
+export type Merge = Omit & U
+
+export type BotApiVersion = BOT_API_VERSIONS[number]
+
+type VersionMap =
+ T extends readonly [infer First extends BotApiVersion, infer Second extends BotApiVersion, ...infer Rest extends BotApiVersion[]]
+ ? VersionMap<[Second, ...Rest], R & { [K in First]: Second }>
+ : R
+
+type BotApiNextVersionMap = VersionMap
+export type BotApiNextVersion = V extends keyof BotApiNextVersionMap
+ ? BotApiNextVersionMap[V]
+ : never
+
+type BotApiPrevVersionMap = VersionMap>
+export type BotApiPrevVersion = V extends keyof BotApiPrevVersionMap
+ ? BotApiPrevVersionMap[V]
+ : never
+
+export type BotApiVersionRange =
+ Equals extends true
+ ? Start
+ : Start | BotApiVersionRange, End>
+
+export type VersionedReturnType<
+ Schema extends Record,
+ Version extends BotApiVersion,
+ SuggestedVersions extends BotApiVersion,
+> =
+ & Extract }>
+ & (Exclude> extends never
+ ? object
+ : {
+ isVersionAtLeast: >>(version: V) => this is { version: BotApiVersionRange }
+ })
+
/**
* Mini Apps
*/
-export interface OnEventReturn {
+export type OnEventReturn = {
off: () => void
}
-export interface OnEventOptions {
+export type OnEventOptions = {
/**
* Disables automatic subscription management; you need to call the returned function `off` to unsubscribe.
*
@@ -15,81 +77,11 @@ export interface OnEventOptions {
manual?: boolean
}
-export interface OnEventWithOptions {
- (
- eventType: 'themeChanged',
- eventHandler: ThemeChangedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'mainButtonClicked',
- eventHandler: MainButtonClickedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'backButtonClicked',
- eventHandler: BackButtonClickedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'settingsButtonClicked',
- eventHandler: SettingsButtonClickedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'popupClosed',
- eventHandler: PopupClosedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'viewportChanged',
- eventHandler: ViewportChangedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'invoiceClosed',
- eventHandler: InvoiceClosedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'qrTextReceived',
- eventHandler: QrTextReceivedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'scanQrPopupClosed',
- eventHandler: ScanQrPopupClosedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'clipboardTextReceived',
- eventHandler: ClipboardTextReceivedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'writeAccessRequested',
- eventHandler: WriteAccessRequestedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'contactRequested',
- eventHandler: ContactRequestedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'biometricManagerUpdated',
- eventHandler: BiometricManagerUpdatedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'biometricAuthRequested',
- eventHandler: BiometricAuthRequestedCallback,
- options?: O,
- ): OnEventReturn
- (
- eventType: 'biometricTokenUpdated',
- eventHandler: BiometricTokenUpdatedCallback,
- options?: O,
+export type OnEventWithOptions = {
+ (
+ eventType: T,
+ eventHandler: EventCallback[T],
+ options?: O
): OnEventReturn
}
@@ -97,8 +89,6 @@ export interface OnEventWithOptions {
* Widgets
*/
-export type LoginWidgetUser = Pick<
- WebAppUser,
- 'id' | 'first_name' | 'last_name' | 'username' | 'photo_url'
-> &
-Pick
+export type LoginWidgetUser =
+ & Pick
+ & Pick
diff --git a/src/utils/functions.ts b/src/utils/functions.ts
new file mode 100644
index 0000000..276f75f
--- /dev/null
+++ b/src/utils/functions.ts
@@ -0,0 +1,74 @@
+interface HookObject {
+ before?: (args: TArgs) => void
+ after?: (args: TArgs, result: TResult) => void
+}
+
+export function wrapFunction<
+ TFunction extends (...args: any[]) => any,
+ TOmitReturn extends boolean = false,
+>(
+ fn: TFunction,
+ options?: {
+ hooks?: HookObject, ReturnType>
+ omitReturn?: TOmitReturn
+ },
+): (...args: Parameters) => TOmitReturn extends true ? void : ReturnType {
+ return (...args: Parameters) => {
+ const { hooks, omitReturn } = options || {}
+ if (hooks?.before)
+ hooks.before(args)
+
+ const result = fn(...args)
+
+ if (hooks?.after)
+ hooks.after(args, result)
+
+ if (!omitReturn)
+ return result
+ }
+}
+
+type Callback = (data: T) => void
+
+export function promisify(
+ func: (...args: [...A, Callback]) => void,
+): (...args: A) => Promise {
+ return (...args: A) =>
+ new Promise(resolve => func(...args, resolve))
+}
+
+type CallbackWithNoData = () => void
+
+export function promisifyWithNoData(
+ func: (...args: [...A, CallbackWithNoData]) => void,
+): (...args: A) => Promise {
+ return (...args: A) =>
+ new Promise(resolve => func(...args, resolve))
+}
+
+type CallbackWithError = (err: string | null, data: T | null) => void
+
+export function promisifyWithError(
+ func: (...args: [...A, CallbackWithError]) => void,
+): (...args: A) => Promise {
+ return (...args: A) =>
+ new Promise((resolve, reject) =>
+ func(...args, (err, data) => (err ? reject(err) : resolve(data as T))),
+ )
+}
+
+type CallbackWithMultipleData = (...data: T) => void
+
+export function promisifyWithDataObject<
+ T extends any[],
+ R extends Record,
+ A extends any[],
+>(
+ func: (...args: [...A, CallbackWithMultipleData]) => void,
+ mapToObject: (...data: T) => R,
+): (...args: A) => Promise {
+ return (...args: A) =>
+ new Promise(resolve =>
+ func(...args, (...data: T) => resolve(mapToObject(...data))),
+ )
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 16c8633..f39e9b5 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1 +1,3 @@
+export * from './functions'
export * from './store'
+export * from './version'
diff --git a/src/utils/version.ts b/src/utils/version.ts
new file mode 100644
index 0000000..b13c33e
--- /dev/null
+++ b/src/utils/version.ts
@@ -0,0 +1,18 @@
+function compareVersions(version1: string, version2: string) {
+ const parts1 = (version1 || '').trim().split('.').map(Number)
+ const parts2 = (version2 || '').trim().split('.').map(Number)
+ const maxLength = Math.max(parts1.length, parts2.length)
+
+ for (let i = 0; i < maxLength; i++) {
+ const p1 = parts1[i] || 0
+ const p2 = parts2[i] || 0
+ if (p1 !== p2)
+ return p1 > p2 ? 1 : -1
+ }
+
+ return 0
+}
+
+export function isVersionGreaterOrEqual(version1: string, version2: string) {
+ return compareVersions(version1, version2) >= 0
+}
diff --git a/src/versions/6.0.ts b/src/versions/6.0.ts
new file mode 100644
index 0000000..d4f0f4d
--- /dev/null
+++ b/src/versions/6.0.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.0')
diff --git a/src/versions/6.1.ts b/src/versions/6.1.ts
new file mode 100644
index 0000000..d21b50f
--- /dev/null
+++ b/src/versions/6.1.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.1')
diff --git a/src/versions/6.2.ts b/src/versions/6.2.ts
new file mode 100644
index 0000000..cb4f657
--- /dev/null
+++ b/src/versions/6.2.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.2')
diff --git a/src/versions/6.4.ts b/src/versions/6.4.ts
new file mode 100644
index 0000000..d88d69a
--- /dev/null
+++ b/src/versions/6.4.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.4')
diff --git a/src/versions/6.7.ts b/src/versions/6.7.ts
new file mode 100644
index 0000000..093cc98
--- /dev/null
+++ b/src/versions/6.7.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.7')
diff --git a/src/versions/6.9.ts b/src/versions/6.9.ts
new file mode 100644
index 0000000..ba10f25
--- /dev/null
+++ b/src/versions/6.9.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('6.9')
diff --git a/src/versions/7.0.ts b/src/versions/7.0.ts
new file mode 100644
index 0000000..b3d855e
--- /dev/null
+++ b/src/versions/7.0.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.0')
diff --git a/src/versions/7.10.ts b/src/versions/7.10.ts
new file mode 100644
index 0000000..4567d66
--- /dev/null
+++ b/src/versions/7.10.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.10')
diff --git a/src/versions/7.2.ts b/src/versions/7.2.ts
new file mode 100644
index 0000000..9ae0e90
--- /dev/null
+++ b/src/versions/7.2.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.2')
diff --git a/src/versions/7.6.ts b/src/versions/7.6.ts
new file mode 100644
index 0000000..ba9fccc
--- /dev/null
+++ b/src/versions/7.6.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.6')
diff --git a/src/versions/7.7.ts b/src/versions/7.7.ts
new file mode 100644
index 0000000..ce54060
--- /dev/null
+++ b/src/versions/7.7.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.7')
diff --git a/src/versions/7.8.ts b/src/versions/7.8.ts
new file mode 100644
index 0000000..4c43648
--- /dev/null
+++ b/src/versions/7.8.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('7.8')
diff --git a/src/versions/8.0.ts b/src/versions/8.0.ts
new file mode 100644
index 0000000..9034e04
--- /dev/null
+++ b/src/versions/8.0.ts
@@ -0,0 +1,23 @@
+import { createComposablesWithVersion } from './helpers'
+
+export const {
+ useAccelerometer,
+ useBackButton,
+ useBiometricManager,
+ useClipboard,
+ useCloudStorage,
+ useDeviceOrientation,
+ useEmojiStatus,
+ useGyroscope,
+ useHapticFeedback,
+ useHomeScreen,
+ useLocationManager,
+ useMainButton,
+ useMiniApp,
+ usePopup,
+ useQrScanner,
+ useSecondaryButton,
+ useSettingsButton,
+ useTheme,
+ useViewport,
+} = createComposablesWithVersion('8.0')
diff --git a/src/versions/helpers.ts b/src/versions/helpers.ts
new file mode 100644
index 0000000..efd2f08
--- /dev/null
+++ b/src/versions/helpers.ts
@@ -0,0 +1,44 @@
+import type { BotApiVersion } from '../types'
+import { useAccelerometer as _useAccelerometer } from '../composables/useAccelerometer'
+import { useBackButton as _useBackButton } from '../composables/useBackButton'
+import { useBiometricManager as _useBiometricManager } from '../composables/useBiometricManager'
+import { useClipboard as _useClipboard } from '../composables/useClipboard'
+import { useCloudStorage as _useCloudStorage } from '../composables/useCloudStorage'
+import { useDeviceOrientation as _useDeviceOrientation } from '../composables/useDeviceOrientation'
+import { useEmojiStatus as _useEmojiStatus } from '../composables/useEmojiStatus'
+import { useGyroscope as _useGyroscope } from '../composables/useGyroscope'
+import { useHapticFeedback as _useHapticFeedback } from '../composables/useHapticFeedback'
+import { useHomeScreen as _useHomeScreen } from '../composables/useHomeScreen'
+import { useLocationManager as _useLocationManager } from '../composables/useLocationManager'
+import { useMainButton as _useMainButton } from '../composables/useMainButton'
+import { useMiniApp as _useMiniApp } from '../composables/useMiniApp'
+import { usePopup as _usePopup } from '../composables/usePopup'
+import { useQrScanner as _useQrScanner } from '../composables/useQrScanner'
+import { useSecondaryButton as _useSecondaryButton } from '../composables/useSecondaryButton'
+import { useSettingsButton as _useSettingsButton } from '../composables/useSettingsButton'
+import { useTheme as _useTheme } from '../composables/useTheme'
+import { useViewport as _useViewport } from '../composables/useViewport'
+
+export function createComposablesWithVersion(version: T) {
+ return {
+ useAccelerometer: () => _useAccelerometer({ version }),
+ useBackButton: () => _useBackButton({ version }),
+ useBiometricManager: () => _useBiometricManager({ version }),
+ useClipboard: () => _useClipboard({ version }),
+ useCloudStorage: () => _useCloudStorage({ version }),
+ useDeviceOrientation: () => _useDeviceOrientation({ version }),
+ useEmojiStatus: () => _useEmojiStatus({ version }),
+ useGyroscope: () => _useGyroscope({ version }),
+ useHapticFeedback: () => _useHapticFeedback({ version }),
+ useHomeScreen: () => _useHomeScreen({ version }),
+ useLocationManager: () => _useLocationManager({ version }),
+ useMainButton: () => _useMainButton({ version }),
+ useMiniApp: () => _useMiniApp({ version }),
+ usePopup: () => _usePopup({ version }),
+ useQrScanner: () => _useQrScanner({ version }),
+ useSecondaryButton: () => _useSecondaryButton({ version }),
+ useSettingsButton: () => _useSettingsButton({ version }),
+ useTheme: () => _useTheme({ version }),
+ useViewport: () => _useViewport({ version }),
+ }
+}
diff --git a/src/versions/latest.ts b/src/versions/latest.ts
new file mode 100644
index 0000000..a21dce1
--- /dev/null
+++ b/src/versions/latest.ts
@@ -0,0 +1 @@
+export * from './8.0'
diff --git a/tsconfig.json b/tsconfig.json
index 72fed94..c649f64 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,7 +3,6 @@
"incremental": false,
"target": "ESNext",
"lib": ["DOM", "ESNext"],
- "baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
diff --git a/vite.config.mts b/vite.config.mts
index 0db3c39..9a61d02 100644
--- a/vite.config.mts
+++ b/vite.config.mts
@@ -1,3 +1,4 @@
+import { resolve } from 'node:path'
import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
@@ -12,9 +13,30 @@ export default defineConfig({
],
build: {
lib: {
- entry: './src/index.ts',
+ entry: [
+ resolve(__dirname, 'src/index.ts'),
+ resolve(__dirname, 'src/versions/6.0.ts'),
+ resolve(__dirname, 'src/versions/6.1.ts'),
+ resolve(__dirname, 'src/versions/6.2.ts'),
+ resolve(__dirname, 'src/versions/6.4.ts'),
+ resolve(__dirname, 'src/versions/6.7.ts'),
+ resolve(__dirname, 'src/versions/6.9.ts'),
+ resolve(__dirname, 'src/versions/7.0.ts'),
+ resolve(__dirname, 'src/versions/7.2.ts'),
+ resolve(__dirname, 'src/versions/7.6.ts'),
+ resolve(__dirname, 'src/versions/7.7.ts'),
+ resolve(__dirname, 'src/versions/7.8.ts'),
+ resolve(__dirname, 'src/versions/7.10.ts'),
+ resolve(__dirname, 'src/versions/8.0.ts'),
+ resolve(__dirname, 'src/versions/latest.ts'),
+ ],
name: pkg.name,
- fileName: format => `index.${format}.js`,
+ fileName(format, name) {
+ if (format === 'es') {
+ return `${name}.js`
+ }
+ return `${name}.${format}`
+ },
},
rollupOptions: {
external: ['vue'],