[
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@2.2.0/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \"commit\": false,\n  \"fixed\": [],\n  \"linked\": [],\n  \"access\": \"restricted\",\n  \"baseBranch\": \"master\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": []\n}\n"
  },
  {
    "path": ".eslintignore",
    "content": "/tests/**/*.*\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n    \"root\": true,\n    \"env\": {\n        \"browser\": true,\n        \"es2021\": true\n    },\n    \"extends\": [\n        \"eslint:recommended\",\n        \"plugin:@typescript-eslint/recommended\",\n        \"plugin:react/recommended\",\n        \"plugin:react-hooks/recommended\"\n    ],\n    \"parser\": \"@typescript-eslint/parser\",\n    \"parserOptions\": {\n        \"ecmaVersion\": \"latest\",\n        \"sourceType\": \"module\"\n    },\n    \"plugins\": [\n        \"@typescript-eslint\",\n        \"react\"\n    ],\n    \"rules\": {\n        \"react-hooks/rules-of-hooks\": \"error\",\n        \"react-hooks/exhaustive-deps\": \"error\",\n        \"@typescript-eslint/no-explicit-any\": [\"warn\", { \"ignoreRestArgs\": true }]\n    }\n}\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n<!--\n  Please provide a clear and concise description of what the bug is. Include\n  screenshots if needed. Please test using the latest version of the relevant\n  @vkruglikov/react-telegram-web-app package to make sure your issue has not already been fixed.\n-->\n\nPackage version: \nReact version: \nTelegram.WebApp version: <!--If the error occurs in the WebApp -->\n\n## Steps To Reproduce\n\n1.\n2.\n\n<!--\n  Your bug will get fixed much faster if we can run your code and it doesn't\n  have dependencies other than React. Issues without reproduction steps or\n  code examples may be immediately closed as not actionable.\n-->\n\nLink to code example: \n\n<!--\n  Please provide a CodeSandbox (https://codesandbox.io/s/new), a link to a\n  repository on GitHub, or provide a minimal code example that reproduces the\n  problem. You may provide a screenshot of the application if you think it is\n  relevant to your bug report. Here are some tips for providing a minimal\n  example: https://stackoverflow.com/help/mcve.\n-->\n\n## The current behavior\n\n\n## The expected behavior\n"
  },
  {
    "path": ".github/workflows/contributing.yml",
    "content": "name: Generate Contributors Images\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Generate Contributors Images\n        uses: jaywcjlove/github-action-contributors@main\n        id: contributors\n        with:\n          filter-author: (renovate\\[bot\\]|renovate-bot|dependabot\\[bot\\])\n          avatarSize: 42\n\n      - name: Modify README.md\n        uses: jaywcjlove/github-action-modify-file-content@main\n        with:\n          path: README.md\n          body: '${{steps.contributors.outputs.htmlList}}'"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release package\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - demo/**\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@master\n        with:\n          # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits\n          fetch-depth: 0\n\n      - name: Use Node.js 16.x\n        uses: actions/setup-node@v3\n        with:\n          node-version: 16.x\n\n      - name: Install Dependencies\n        run: npm install\n\n      - name: Publish\n        uses: changesets/action@master\n        with:\n          # This expects you to have a script called release which does a build for your packages and calls changeset publish\n          publish: npm run release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/static.yml",
    "content": "# Simple workflow for deploying static content to GitHub Pages\nname: Deploy static content to Pages\n\non:\n  # Runs on pushes targeting the default branch\n  push:\n    branches: ['master']\n    paths:\n      - demo/**\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\n# Allow one concurrent deployment\nconcurrency:\n  group: 'pages'\n  cancel-in-progress: true\n\njobs:\n  # Single deploy job since we're just deploying\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Use Node.js 16.x\n        uses: actions/setup-node@v3\n        with:\n          node-version: 16.x\n      - name: Install Dependencies and Build\n        working-directory: './demo'\n        run: npm install && npm run build\n\n      - name: Setup Pages\n        uses: actions/configure-pages@v2\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v1\n        with:\n          path: './demo/build/.'\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v1\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: Run tests\non:\n  push:\n    paths:\n      - src/**\n      - tests/**\n      - jest.config.json\njobs:\n  test:\n    runs-on: ubuntu-latest\n    name: Run tests\n\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@master\n        with:\n          # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits\n          fetch-depth: 0\n\n      - name: Use Node.js 16.x\n        uses: actions/setup-node@v3\n        with:\n          node-version: 16.x\n\n      - name: Install Dependencies\n        run: npm install\n\n      - name: Run tests\n        run: npm run test:all\n\n      - name: Run package tests\n        run: npm run build && npm run test:package\n"
  },
  {
    "path": ".gitignore",
    "content": "/lib\nnode_modules\n.idea\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpx lint-staged\n"
  },
  {
    "path": ".nvmrc",
    "content": "v16.14.2"
  },
  {
    "path": ".prettierignore",
    "content": "lib\ndemo/build\npackage.json\npackage-lock.json"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"useTabs\": false,\n  \"arrowParens\": \"avoid\",\n  \"overrides\": [\n    {\n      \"files\": \"package.json\",\n      \"options\": {\n        \"useTabs\": false,\n        \"parser\": \"json-stringify\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# @vkruglikov/react-telegram-web-app\n\n## 2.2.0\n\n### Minor Changes\n\n- e3bcaf0: Add SettingsButton\n\n## 2.1.9\n\n### Patch Changes\n\n- 5f49e9b: test fix\n\n## 2.1.8\n\n### Patch Changes\n\n- f187824: test fix\n\n## 2.1.7\n\n### Patch Changes\n\n- 94b5e28: Added experimental `async` mode\n\n## 2.1.6\n\n### Patch Changes\n\n- 6631ede: useInitData returns undefined if window is unavailable\n\n## 2.1.5\n\n### Patch Changes\n\n- 1e3beb1: Update docs\n\n## 2.1.4\n\n### Patch Changes\n\n- f705506: Fix signature bug\n\n## 2.1.3\n\n### Patch Changes\n\n- e4b17fb: Fix types\n\n## 2.1.2\n\n### Patch Changes\n\n- e856e14: Fix bug with types\n\n## 2.3.0\n\n### Minor Changes\n\n- c28cc2e: useWebApp hook\n\n## 2.2.0\n\n### Minor Changes\n\n- 0339c94: Added `useCloudStorage` that provides `CloudStorage` object as Promise functions\n- 1589011: Added useInitData hook\n\n## 2.1.1\n\n### Patch Changes\n\n- 54f5400: Fix smoothButtonsTransition restore state after refresh page\n\n## 2.1.0\n\n### Minor Changes\n\n- bcf3a0e: Added props `disabled` to MainButton component. It is just an alias on the `MainButtonProps.disable`\n  Props `disable` marked as deprecated and will be removed\n\n### Patch Changes\n\n- 05d7b34: - Reduced default value for `smoothButtonsTransitionMs`\n\n## 2.0.1\n\n### Patch Changes\n\n- 24545c3: Fix package missed export types\n\n## 2.0.0\n\n### Major Changes\n\n- 4084742: - Have added unnecessary provider `WebAppProvider`\n  - Fixed all components to works inside `WebAppProvider`\n  - Fix incorrect types `useExpand`\n  - Added `smoothButtonsTransition` options to `WebAppProvider`\n\n### Patch Changes\n\n- 3221966: Support dynamic webApp in context\n- 5e82b6c: Fix documentation format\n- 0bc91cf: Fix structure and types context\n- c402a76: Added documentation for WebAppProvider\n- 4f18299: Describe all WebApp types\n- 111549b: Added jest tests for package and public api\n\n## 1.11.0\n\n### Minor Changes\n\n- af6ccfb: Added useExpand hook, that hook provided isExpanded state, and expand() handle. Remove unsafe_useExpand\n\n## 1.10.1\n\n### Patch Changes\n\n- ef7d3e9: Change readme\n\n## 1.10.0\n\n### Minor Changes\n\n- 8af00e3: Added unsafe_useExpand hook\n\n## 1.9.1\n\n### Patch Changes\n\n- dd8ab05: Update readme\n\n## 1.9.0\n\n### Minor Changes\n\n- 5b1f85f: Added hook useReadTextFromClipboard, that provide function that read text from clipboard\n- 2e16b48: Added hook useSwitchInlineQuery\n\n## 1.8.0\n\n### Minor Changes\n\n- 458e93d: Added docs and demo, describes work useScanQrPopup hook\n\n## 1.7.0\n\n### Minor Changes\n\n- c8b49cf: Added useScanQrPopup hook. This hook provide functions showScanQrPopup, closeScanQrPopup\n\n## 1.6.0\n\n### Minor Changes\n\n- 9ed6405: Add useThemeParams hook\n\n## 1.5.4\n\n### Patch Changes\n\n- 5a248e3: Fix .npmignore paths\n\n## 1.5.3\n\n### Patch Changes\n\n- 7a5106c: Fix MainButton uniq effects\n\n## 1.5.2\n\n### Patch Changes\n\n- 2006b71: Add docst and example with useHapticFeedback\n\n## 1.5.1\n\n### Patch Changes\n\n- 92a21c9: Change interfeces\n\n## 1.5.0\n\n### Minor Changes\n\n- dd146bc: Add useHapticFeedback hook\n\n## 1.4.1\n\n### Patch Changes\n\n- 6a7c5b4: Add CRA demo webapp\n\n## 1.4.0\n\n### Minor Changes\n\n- fdbfcc8: Fix window typed error\n\n## 1.3.0\n\n### Minor Changes\n\n- 28c08e4: Add useShowPopup hook\n\n## 1.2.0\n\n### Minor Changes\n\n- b7bfbcb: Add BackButton component\n\n## 1.1.2\n\n### Patch Changes\n\n- 4e36d80: Update documentation\n\n## 1.1.1\n\n### Patch Changes\n\n- 395c91f: Documentation fix\n\n## 1.1.0\n\n### Minor Changes\n\n- 3f5bd48: Changes types, add documentation\n\n## 1.0.3\n\n### Patch Changes\n\n- 81546ee: Add docs pages\n\n## 1.0.2\n\n### Patch Changes\n\n- 6e8043f: Fix ci files, add README and LICENCE\n\n## 1.0.1\n\n### Patch Changes\n\n- ea7807b: Inited project and added MainButton component\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n- Demonstrating empathy and kindness toward other people\n- Being respectful of differing opinions, viewpoints, and experiences\n- Giving and gracefully accepting constructive feedback\n- Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n- Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n- Trolling, insulting or derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\n.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nHi there! Interested in contributing to `react-telegram-web-app`? We'd love your help\n\n## Goals\n\nThe main goal of the project is to make it convenient to use Telegram Mini Apps in react applications\n\n## Ways to contribute\n\n- [Install package](./README.md#-installation--get-started) and kick the tires. Does it work? Does it do what you'd expect? If not, [open an issue](https://github.com/vkruglikov/react-telegram-web-app/issues) and let us know.\n- Comment on some of the project's [open issues](https://github.com/vkruglikov/react-telegram-web-app/issues). Have you experienced the same problem? Know a workaround? Do you have a suggestion for how the feature could be better?\n- Browse through the [discussions](https://github.com/vkruglikov/react-telegram-web-app/discussions), and lend a hand answering questions. There's a good chance you've already experienced what another user is experiencing.\n\n## Submitting a pull request\n\n### Before you create pull request\n\n- Make sure your changes meet the project's goals\n- Before you do something, make sure that other members of the community really need it\n- Do not change the basic logic of Telegram Mini Apps, even if there are errors in it. Instead you need to open an issue at https://bugs.telegram.org/\n\n### Pull requests generally\n\n- The smaller the proposed change, the better. If you'd like to propose two unrelated changes, submit two pull requests.\n- The more information, the better. Make judicious use of the pull request body. Describe what changes were made, why you made them, and what impact they will have for users.\n- If this is your first pull request, it may help to [understand GitHub Flow](https://guides.github.com/introduction/flow/).\n\n## Proposing updates to the documentation\n\nDocumentation is generated using [typedoc](https://typedoc.org/guides/overview/).\nLook at the examples and describe the documentation sufficiently fully\n\n## Respect the work of other developers\n\n- Don't change the basic styling settings without a good reason\n- Do not change basic project settings such as title and personal links\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 Kruglikov Valentin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# React components for Telegram MiniApp\n\n[![npm](https://img.shields.io/npm/v/@vkruglikov/react-telegram-web-app.svg)](https://www.npmjs.com/package/@vkruglikov/react-telegram-web-app)\n[![types](https://badgen.net/npm/types/@vkruglikov/react-telegram-web-app)](https://npmjs.org/package/@vkruglikov/react-telegram-web-app)\n[![GitHub Actions CI](https://github.com/vkruglikov/react-telegram-web-app/actions/workflows/release.yml/badge.svg)](https://github.com/vkruglikov/react-telegram-web-app/actions/workflows/release.yml)\n[![License](https://badgen.net/github/license/vkruglikov/react-telegram-web-app)](https://github.com/vkruglikov/react-telegram-web-app/blob/master/LICENSE)\n![Tests](https://github.com/vkruglikov/react-telegram-web-app/actions/workflows/tests.yml/badge.svg)\n\n## 🔴 Live Demo & Code Examples\n\nYou can try open demo telegram bot with React WebApp [@react_telegram_web_app_bot](https://t.me/react_telegram_web_app_bot/demo).\n\nAlso, you can look demo [source code](./demo/src).\n\n## 🔧 Installation & Get started\n\n1️⃣ &nbsp;**Foremost**, you have to do [initializing web apps](https://core.telegram.org/bots/webapps#initializing-mini-apps) step, because package has dependency of Telegram Web App context.\n\n2️⃣ &nbsp;**Install** by running: `npm i @vkruglikov/react-telegram-web-app --save`. Today we support React^18.\n\n3️⃣ &nbsp;**Try it out** by writing code.\n\n```jsx\nimport { MainButton, useShowPopup } from '@vkruglikov/react-telegram-web-app';\n\nconst Content = () => {\n  const showPopup = useShowPopup();\n\n  const handleClick = () =>\n    showPopup({\n      message: 'Hello, I am popup',\n    });\n\n  return <MainButton text=\"SHOW POPUP\" onClick={handleClick} />;\n};\n```\n\n## ✨ Short Documentation\n\n### Components\n\n- [MainButton](./docs/README.md#mainbutton) -\n  The component controls the main button, which is displayed at the bottom of the Web App in the Telegram interface.\n\n- [BackButton](./docs/README.md#backbutton) -\n  This component controls the back button, which can be displayed in the header of the Web App in the Telegram interface.\n\n- [WebAppProvider](./docs/README.md#webappprovider) -\n  WebAppProvider provide context with WebApp for components and hooks.\n  You can try to pass an object with options\n- [SettingsButton](./docs/README.md#settingsbutton) Settings button (mvp)\n\n  ```jsx\n  import { WebAppProvider, MainButton, BackButton } from '@vkruglikov/react-telegram-web-app';\n\n  <WebAppProvider\n    options={{\n      smoothButtonsTransition: true,\n    }}\n  >\n    {/** Use components inside provider */}\n    <MainButton {...} />\n    <BackButton {...} />\n  </WebAppProvider>\n  ```\n\n### Hooks\n\n- [useShowPopup](./docs/README.md#useshowpopup) -\n  This hook provides `showPopup` function that shows a native popup.\n- [useHapticFeedback](./docs/README.md#usehapticfeedback) -\n  This hook provides `impactOccurred`, `notificationOccurred` and `selectionChanged` functions that controls haptic feedback.\n- [useThemeParams](./docs/README.md#usethemeparams) -\n  This hook provides `colorScheme` and `themeParams` object.\n- [useScanQrPopup](./docs/README.md#usescanqrpopup) -\n  This hook provides `showScanQrPopup` and `closeScanQrPopup` functions.\n- [useReadTextFromClipboard](./docs/README.md#usereadtextfromclipboard) -\n  This hook provides `readTextFromClipboard` function.\n- [useSwitchInlineQuery](./docs/README.md#useswitchinlinequery) -\n  This hook provides `switchInlineQuery` function.\n- [useExpand](./docs/README.md#useexpand) -\n  This hook provides `isExpanded` state, and `expand()` handle.\n- [useCloudStorage](./docs/README.md#usecloudstorage) -\n  This hook provides `CloudStorage` object as Promise functions\n- [useInitData](./docs/README.md#useinitdata) -\n  This hook provides `InitDataUnsafe` and `InitData` object\n- [useWebApp](./docs/README.md#usewebapp) -\n  This hook just provides native `WebApp` object\n\n## 🛣 Roadmap\n\nHere's what's coming up:\n\n- [ ] In the future, We would like to use us components also in Web application, without Telegram context.\n- [ ] All Telegram WebApp feature support\n- [x] Main Telegram WebApp feature support\n\n## Contributors\n\nAs always, thanks to our amazing contributors!\n\n<!--GAMFC--><a href=\"https://github.com/vkruglikov\" title=\"Valentin\"><img src=\"https://avatars.githubusercontent.com/u/9719024?v=4\" width=\"42;\" alt=\"Valentin\"/></a>\n<a href=\"https://github.com/xsa-dev\" title=\"Alxy Savin\"><img src=\"https://avatars.githubusercontent.com/u/16959353?v=4\" width=\"42;\" alt=\"Alxy Savin\"/></a>\n<a href=\"https://github.com/New-dev0\" title=\"Devesh Pal\"><img src=\"https://avatars.githubusercontent.com/u/69723581?v=4\" width=\"42;\" alt=\"Devesh Pal\"/></a>\n<a href=\"https://github.com/alexgoto\" title=\"Alexandr Gotovtsev\"><img src=\"https://avatars.githubusercontent.com/u/43707500?v=4\" width=\"42;\" alt=\"Alexandr Gotovtsev\"/></a><!--GAMFC-END-->\n\nMade with [contributors](https://github.com/jaywcjlove/github-action-contributors).\n\n## Contributing\n\n- Read up about its [🛣 Roadmap](#-roadmap) and [official documentation](https://core.telegram.org/bots/webapps) Telegram Mini Apps\n- Have questions? Check out our [examples](#-live-demo--code-examples), [duscussions](https://github.com/vkruglikov/react-telegram-web-app/discussions) and [issues](https://github.com/vkruglikov/react-telegram-web-app/discussions)\n- [Fork](https://github.com/vkruglikov/react-telegram-web-app/fork) and [Contribute](./CONTRIBUTING.md) your own modifications\n\n## 🥂 License\n\n[MIT](./LICENSE)\n\n## 💻👞🙊📚 Join to discussions\n\nCreate discussions, ask questions, share experiences and discuss ideas with everyone together\n\nhttps://github.com/vkruglikov/react-telegram-web-app/discussions\n"
  },
  {
    "path": "demo/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n/*.pem\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "demo/README.md",
    "content": "## install\n\nInstall certificate\n\n```bash\nmkcert react-telegram-web-app.domain\n```\n\nAdd domain to /etc/hosts as 127.0.0.1\n\n## OR you can edit .env file, and will configure how you want\n"
  },
  {
    "path": "demo/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"0.1.0\",\n  \"private\": false,\n  \"dependencies\": {\n    \"@types/node\": \"^16.18.3\",\n    \"@types/react\": \"^18.0.25\",\n    \"@types/react-dom\": \"^18.0.9\",\n    \"@vkruglikov/react-telegram-web-app\": \"^2.1.1\",\n    \"antd\": \"^5.0.1\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-scripts\": \"5.0.1\",\n    \"typescript\": \"^4.9.3\"\n  },\n  \"scripts\": {\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": [\n      \"react-app\"\n    ]\n  },\n  \"homepage\": \"./\",\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  }\n}\n"
  },
  {
    "path": "demo/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\"\n    />\n    <title>react-telegram-web-app</title>\n    <script src=\"https://telegram.org/js/telegram-web-app.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "demo/src/BackButtonDemo.tsx",
    "content": "import { Button, Form, Typography } from 'antd';\nimport { FC, useState } from 'react';\nimport { BackButton, useShowPopup } from '@vkruglikov/react-telegram-web-app';\n\nconst BackButtonDemo: FC = () => {\n  const [buttonState, setButtonState] = useState<{\n    show: boolean;\n  }>();\n  const showPopup = useShowPopup();\n\n  return (\n    <>\n      <Typography.Title level={3}>BackButton</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"BackButtonDemo\"\n        layout=\"horizontal\"\n        autoComplete=\"off\"\n      >\n        <Form.Item>\n          <Button\n            block\n            type=\"primary\"\n            onClick={() =>\n              setButtonState({\n                show: !buttonState?.show,\n              })\n            }\n          >\n            {buttonState?.show ? 'Hide BackButton' : 'Show BackButton'}\n          </Button>\n        </Form.Item>\n      </Form>\n      <div>\n        {buttonState?.show && (\n          <BackButton\n            onClick={() => {\n              showPopup({\n                message: 'back button click',\n              });\n            }}\n          />\n        )}\n      </div>\n    </>\n  );\n};\nexport default BackButtonDemo;\n"
  },
  {
    "path": "demo/src/ExpandDemo.tsx",
    "content": "import { Button, Form, Typography } from 'antd';\nimport { useExpand } from '@vkruglikov/react-telegram-web-app';\n\nconst ExpandDemo = () => {\n  const [isExpanded, expand] = useExpand();\n\n  return (\n    <>\n      <Typography.Title level={3}>useExpand</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"ExpandDemo\"\n        layout=\"horizontal\"\n        autoComplete=\"off\"\n      >\n        <Form.Item name=\"isExpanded\">\n          <Typography.Text>isExpanded: {`${isExpanded}`}</Typography.Text>\n        </Form.Item>\n        <Form.Item>\n          <Button block type=\"primary\" onClick={expand}>\n            {`isExpanded: ${isExpanded}, call expand()`}\n          </Button>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\n\nexport default ExpandDemo;\n"
  },
  {
    "path": "demo/src/HapticFeedbackDemo.tsx",
    "content": "import { Button, Form, Typography, Select } from 'antd';\nimport { FC, useState } from 'react';\nimport {\n  ImpactOccurredFunction,\n  NotificationOccurredFunction,\n  useHapticFeedback,\n} from '@vkruglikov/react-telegram-web-app';\n\nconst HapticFeedbackDemo: FC = () => {\n  const [impactOccurred, notificationOccurred, selectionChanged] =\n    useHapticFeedback();\n  const [style, setStyle] =\n    useState<Parameters<ImpactOccurredFunction>[0]>('light');\n  const [type, setType] =\n    useState<Parameters<NotificationOccurredFunction>[0]>('error');\n\n  return (\n    <>\n      <Typography.Title level={3}>useHapticFeedback</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"HapticFeedbackDemo\"\n        layout=\"horizontal\"\n        autoComplete=\"off\"\n      >\n        <Form.Item label=\"style\">\n          <Select value={style} onChange={value => setStyle(value)}>\n            <Select.Option value=\"light\">light</Select.Option>\n            <Select.Option value=\"medium\">medium</Select.Option>\n            <Select.Option value=\"heavy\">heavy</Select.Option>\n            <Select.Option value=\"rigid\">rigid</Select.Option>\n            <Select.Option value=\"soft\">soft</Select.Option>\n          </Select>\n        </Form.Item>\n        <Form.Item>\n          <Button block type=\"primary\" onClick={() => impactOccurred(style)}>\n            impactOccurred\n          </Button>\n        </Form.Item>\n        <Form.Item label=\"type\">\n          <Select value={type} onChange={value => setType(value)}>\n            <Select.Option value=\"error\">error</Select.Option>\n            <Select.Option value=\"success\">success</Select.Option>\n            <Select.Option value=\"warning\">warning</Select.Option>\n          </Select>\n        </Form.Item>\n        <Form.Item>\n          <Button\n            block\n            type=\"primary\"\n            onClick={() => notificationOccurred(type)}\n          >\n            notificationOccurred\n          </Button>\n        </Form.Item>\n        <Form.Item>\n          <Button block type=\"primary\" onClick={() => selectionChanged()}>\n            selectionChanged\n          </Button>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\nexport default HapticFeedbackDemo;\n"
  },
  {
    "path": "demo/src/MainButtonDemo.tsx",
    "content": "import { Button, Form, Input, Typography, Switch } from 'antd';\nimport { FC, useState } from 'react';\nimport {\n  MainButton,\n  MainButtonProps,\n} from '@vkruglikov/react-telegram-web-app';\n\nconst MainButtonDemo: FC<{\n  initialValues?: Partial<MainButtonProps> & { show?: boolean };\n}> = ({ initialValues }) => {\n  const [buttonState, setButtonState] = useState<\n    {\n      show: boolean;\n    } & Pick<MainButtonProps, 'text' | 'progress' | 'disable'>\n  >({\n    text: 'BUTTON TEXT',\n    show: false,\n    progress: false,\n    disable: false,\n    ...initialValues,\n  });\n  const onFinish = (values: any) => setButtonState(values);\n\n  return (\n    <>\n      <Typography.Title level={3}>MainButton</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"MainButtonDemo\"\n        layout=\"horizontal\"\n        initialValues={buttonState}\n        onFinish={onFinish}\n        autoComplete=\"off\"\n      >\n        <Form.Item label=\"Text\" name=\"text\">\n          <Input disabled />\n        </Form.Item>\n        <Form.Item name=\"progress\" label=\"progress\" valuePropName=\"checked\">\n          <Switch\n            onChange={value =>\n              setButtonState({\n                ...buttonState,\n                progress: value,\n              })\n            }\n          />\n        </Form.Item>\n        <Form.Item name=\"disable\" label=\"disable\" valuePropName=\"checked\">\n          <Switch\n            onChange={value =>\n              setButtonState({\n                ...buttonState,\n                disable: value,\n              })\n            }\n          />\n        </Form.Item>\n        <Form.Item>\n          <Button\n            block\n            type=\"primary\"\n            onClick={() =>\n              setButtonState({\n                ...buttonState,\n                show: !buttonState?.show,\n              })\n            }\n          >\n            {buttonState?.show ? 'Hide MainButton' : 'Show MainButton'}\n          </Button>\n        </Form.Item>\n      </Form>\n      <div>{buttonState?.show && <MainButton {...buttonState} />}</div>\n    </>\n  );\n};\nexport default MainButtonDemo;\n"
  },
  {
    "path": "demo/src/ScanQrPopupDemo.tsx",
    "content": "import { Button, Form, Typography } from 'antd';\nimport {\n  useScanQrPopup,\n  useShowPopup,\n} from '@vkruglikov/react-telegram-web-app';\n\nconst ScanQrPopupDemo = () => {\n  const [showQrPopup, closeQrPopup] = useScanQrPopup();\n  const showPopup = useShowPopup();\n\n  return (\n    <>\n      <Typography.Title level={3}>useScanQrPopup</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"ScanQrPopupDemo\"\n        layout=\"horizontal\"\n        autoComplete=\"off\"\n      >\n        <Form.Item>\n          <Button\n            block\n            type=\"primary\"\n            htmlType=\"button\"\n            onClick={() =>\n              showQrPopup(\n                {\n                  text: 'Привет друг',\n                },\n                text => {\n                  closeQrPopup();\n                  showPopup({\n                    message: text,\n                  });\n                },\n              )\n            }\n          >\n            showScanQrPopup\n          </Button>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\n\nexport default ScanQrPopupDemo;\n"
  },
  {
    "path": "demo/src/ShowPopupDemo.tsx",
    "content": "import { Button, Form, Input, Typography } from 'antd';\nimport { FC, useState } from 'react';\nimport {\n  ShowPopupParams,\n  useShowPopup,\n} from '@vkruglikov/react-telegram-web-app';\n\nconst ShowPopupDemo: FC = () => {\n  const showPopup = useShowPopup();\n  const [popupState, setPopupState] = useState<\n    Pick<ShowPopupParams, 'title' | 'message'>\n  >({\n    title: 'title',\n    message: 'message',\n  });\n  const onFinish = (values: any) => {\n    setPopupState(values);\n    showPopup({\n      ...values,\n      buttons: [\n        {\n          type: 'ok',\n        },\n        {\n          type: 'close',\n        },\n        {\n          type: 'destructive',\n          text: 'destructive',\n        },\n      ],\n    }).catch(e => {\n      showPopup({\n        title: 'error',\n        message: e,\n      });\n    });\n  };\n\n  return (\n    <>\n      <Typography.Title level={3}>useShowPopup</Typography.Title>\n      <Form\n        labelCol={{ span: 6 }}\n        name=\"ShowPopupDemo\"\n        layout=\"horizontal\"\n        initialValues={popupState}\n        onFinish={onFinish}\n        autoComplete=\"off\"\n      >\n        <Form.Item label=\"title\" name=\"title\">\n          <Input />\n        </Form.Item>\n        <Form.Item label=\"message\" name=\"message\">\n          <Input />\n        </Form.Item>\n        <Form.Item label=\"buttons\" name=\"buttons\">\n          <Typography.Text>\n            {JSON.stringify([\n              {\n                type: 'ok',\n              },\n              {\n                type: 'close',\n              },\n              {\n                type: 'destructive',\n                text: 'destructive',\n              },\n            ])}\n          </Typography.Text>\n        </Form.Item>\n        <Form.Item>\n          <Button block type=\"primary\" htmlType=\"submit\">\n            Show popup\n          </Button>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\nexport default ShowPopupDemo;\n"
  },
  {
    "path": "demo/src/index.css",
    "content": ":root {\n  --tg-theme-bg-color: #fff;\n  --tg-theme-text-color: #0a0a0a;\n  --tg-theme-hint-color: #929292;\n  --tg-theme-link-color: #207ae4;\n  --tg-theme-button-color: #5bc8fb;\n  --tg-theme-button-text-color: #fffeec;\n  --tg-theme-secondary-bg-color: #f3f2f9;\n\n  --default-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n    Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',\n    'Segoe UI Symbol';\n}\n\nbody {\n  background: var(--tg-theme-secondary-bg-color);\n  padding: 20px 20px;\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n    monospace;\n}\n\n.App-logo {\n  height: 40vmin;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n  .App-logo {\n    animation: App-logo-spin infinite 20s linear;\n  }\n}\n\n.betaVersion {\n  padding: 10px 10px;\n  margin-bottom: 20px;\n  border: 1px solid #1777ff;\n}\n\n.App-header {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  font-size: calc(10px + 2vmin);\n  color: white;\n}\n\n.contentWrapper {\n  background: var(--tg-theme-bg-color);\n  color: var(--tg-theme-text-color) !important;\n  border-radius: 10px;\n  margin: 5px 0;\n  padding: 20px;\n  box-sizing: border-box;\n}\n\n.ant-input,\n.ant-select,\n.ant-select-item {\n  background-color: unset !important;\n}\n\n@keyframes App-logo-spin {\n  from {\n    transform: rotate(0deg);\n  }\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "demo/src/index.tsx",
    "content": "import React, { DispatchWithoutAction, FC, useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport {\n  useThemeParams,\n  WebAppProvider,\n} from '@vkruglikov/react-telegram-web-app';\nimport { ConfigProvider, theme } from 'antd';\nimport 'antd/dist/reset.css';\n\nimport './index.css';\nimport logo from './logo.svg';\n\nimport MainButtonDemo from './MainButtonDemo';\nimport BackButtonDemo from './BackButtonDemo';\nimport ShowPopupDemo from './ShowPopupDemo';\nimport HapticFeedbackDemo from './HapticFeedbackDemo';\nimport ScanQrPopupDemo from './ScanQrPopupDemo';\nimport ExpandDemo from './ExpandDemo';\nimport useBetaVersion from './useBetaVersion';\n\nconst DemoApp: FC<{\n  onChangeTransition: DispatchWithoutAction;\n}> = ({ onChangeTransition }) => {\n  const [colorScheme, themeParams] = useThemeParams();\n  const [isBetaVersion, handleRequestBeta] = useBetaVersion(false);\n  const [activeBtn, setActiveBtn] = useState(true);\n\n  return (\n    <div>\n      <ConfigProvider\n        theme={\n          themeParams.text_color\n            ? {\n                algorithm:\n                  colorScheme === 'dark'\n                    ? theme.darkAlgorithm\n                    : theme.defaultAlgorithm,\n                token: {\n                  colorText: themeParams.text_color,\n                  colorPrimary: themeParams.button_color,\n                  colorBgBase: themeParams.bg_color,\n                },\n              }\n            : undefined\n        }\n      >\n        <header className=\"App-header\">\n          <img\n            onClick={handleRequestBeta}\n            src={logo}\n            className=\"App-logo\"\n            alt=\"logo\"\n          />\n        </header>\n        <div className=\"contentWrapper\">\n          {isBetaVersion && (\n            <div className=\"betaVersion\">\n              <h3>WARNING: BETA VERSION</h3>\n              <button onClick={() => setActiveBtn(state => !state)}>\n                change button\n              </button>\n              <button onClick={onChangeTransition}>change </button>\n            </div>\n          )}\n          <ExpandDemo />\n          {!activeBtn ? (\n            <MainButtonDemo\n              initialValues={{\n                show: isBetaVersion,\n                text: 'SECOND BUTTON',\n                progress: true,\n              }}\n              key=\"1\"\n            />\n          ) : (\n            <MainButtonDemo\n              key=\"2\"\n              initialValues={{\n                show: isBetaVersion,\n              }}\n            />\n          )}\n          <BackButtonDemo />\n          <ShowPopupDemo />\n          <HapticFeedbackDemo />\n          <ScanQrPopupDemo />\n        </div>\n      </ConfigProvider>\n    </div>\n  );\n};\n\nconst root = ReactDOM.createRoot(\n  document.getElementById('root') as HTMLElement,\n);\n\nconst App = () => {\n  const [smoothButtonsTransition, setSmoothButtonsTransition] = useState(false);\n\n  return (\n    <WebAppProvider options={{ smoothButtonsTransition }}>\n      <DemoApp\n        onChangeTransition={() => setSmoothButtonsTransition(state => !state)}\n      />\n    </WebAppProvider>\n  );\n};\n\nroot.render(<App />);\n"
  },
  {
    "path": "demo/src/react-app-env.d.ts",
    "content": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "demo/src/spy.mjs",
    "content": "// @ts-ignore\nconst WebView = window.Telegram.WebView;\n\nconst postEvent = WebView.postEvent;\nconst receiveEvent = WebView.postEvent;\nconst element = document.createElement('div');\n\nWebView.postEvent = (...args) => {\n  const [eventType, callback, eventData] = args;\n\n  const asd = document.createElement('div');\n  asd.innerHTML = `${eventType} -> ${JSON.stringify(eventData)}`\n\n  element.appendChild(asd)\n  element.scrollTop = element.scrollHeight;\n  return postEvent(...args);\n};\nWebView.receiveEvent = (...args) => {\n  const [eventType, callback, eventData] = args;\n\n  console.log('--ФЫВ------------', eventType, callback, eventData);\n  return receiveEvent(...args);\n};\n\nelement.setAttribute(\n  'style',\n  'position:fixed;top:0;left:0;right:0;z-index:1000;background:#fff;height:80px;border-bottom:2px solid red;overflow: auto;',\n);\n\ndocument.body.appendChild(element);\n"
  },
  {
    "path": "demo/src/useBetaVersion.ts",
    "content": "import {\n  useHapticFeedback,\n  useShowPopup,\n} from '@vkruglikov/react-telegram-web-app';\nimport { useRef, useState } from 'react';\n\nconst useBetaVersion = (initialState = false) => {\n  const showPopup = useShowPopup();\n  const [, notification] = useHapticFeedback();\n\n  const [isBeta, setIsBeta] = useState(\n    initialState || process.env.NODE_ENV === 'development',\n  );\n  const isDevModeCounter = useRef(0);\n  const handleRequestBeta = () => {\n    if (++isDevModeCounter.current >= 10) {\n      setIsBeta(!isBeta);\n      isDevModeCounter.current = 0;\n\n      showPopup({ message: `isDevMode: ${!isBeta}` });\n      notification('success');\n    }\n\n    if (isDevModeCounter.current > 7) {\n      showPopup({\n        message: `${10 - isDevModeCounter.current}`,\n      });\n    }\n  };\n\n  return [isBeta, handleRequestBeta] as const;\n};\n\nexport default useBetaVersion;\n"
  },
  {
    "path": "demo/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "docs/.nojekyll",
    "content": "TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false."
  },
  {
    "path": "docs/README.md",
    "content": "@vkruglikov/react-telegram-web-app\n\n# @vkruglikov/react-telegram-web-app\n\n## Table of contents\n\n### Interfaces\n\n- [BackButtonProps](interfaces/BackButtonProps.md)\n- [MainButtonProps](interfaces/MainButtonProps.md)\n- [ScanQrPopupParams](interfaces/ScanQrPopupParams.md)\n- [SettingsButtonProps](interfaces/SettingsButtonProps.md)\n- [ShowPopupButton](interfaces/ShowPopupButton.md)\n- [ShowPopupParams](interfaces/ShowPopupParams.md)\n- [ThemeParams](interfaces/ThemeParams.md)\n\n### Type Aliases\n\n- [CloseScanQrPopupFunction](README.md#closescanqrpopupfunction)\n- [ColorScheme](README.md#colorscheme)\n- [GetItemFunction](README.md#getitemfunction)\n- [GetItemsFunction](README.md#getitemsfunction)\n- [GetKeysFunction](README.md#getkeysfunction)\n- [ImpactOccurredFunction](README.md#impactoccurredfunction)\n- [InitData](README.md#initdata)\n- [InitDataUnsafe](README.md#initdataunsafe)\n- [NotificationOccurredFunction](README.md#notificationoccurredfunction)\n- [Options](README.md#options)\n- [ReadTextFromClipboardFunction](README.md#readtextfromclipboardfunction)\n- [RemoveItemFunction](README.md#removeitemfunction)\n- [RemoveItemsFunction](README.md#removeitemsfunction)\n- [ScanQrPopupCallback](README.md#scanqrpopupcallback)\n- [SelectionChangedFunction](README.md#selectionchangedfunction)\n- [SetItemFunction](README.md#setitemfunction)\n- [ShowPopupFunction](README.md#showpopupfunction)\n- [ShowScanQrPopupFunction](README.md#showscanqrpopupfunction)\n- [SwitchInlineQueryFunction](README.md#switchinlinequeryfunction)\n- [WebAppChat](README.md#webappchat)\n- [WebAppProviderProps](README.md#webappproviderprops)\n- [WebAppUser](README.md#webappuser)\n\n### Hooks\n\n- [useCloudStorage](README.md#usecloudstorage)\n- [useExpand](README.md#useexpand)\n- [useHapticFeedback](README.md#usehapticfeedback)\n- [useInitData](README.md#useinitdata)\n- [useReadTextFromClipboard](README.md#usereadtextfromclipboard)\n- [useScanQrPopup](README.md#usescanqrpopup)\n- [useShowPopup](README.md#useshowpopup)\n- [useSwitchInlineQuery](README.md#useswitchinlinequery)\n- [useThemeParams](README.md#usethemeparams)\n- [useWebApp](README.md#usewebapp)\n\n### React Components\n\n- [BackButton](README.md#backbutton)\n- [MainButton](README.md#mainbutton)\n- [SettingsButton](README.md#settingsbutton)\n- [WebAppProvider](README.md#webappprovider)\n\n## Type Aliases\n\n### CloseScanQrPopupFunction\n\nƬ **CloseScanQrPopupFunction**: () => `void`\n\n#### Type declaration\n\n▸ (): `void`\n\nA method that closes the native popup for scanning a QR code opened with the showScanQrPopup method\n\n##### Returns\n\n`void`\n\n---\n\n### ColorScheme\n\nƬ **ColorScheme**: `\"light\"` \\| `\"dark\"` \\| `undefined`\n\nThe color scheme currently used in the Telegram app. Either “light” or “dark”.\nCan `undefined`, if `window` is undefined.\n\n---\n\n### GetItemFunction\n\nƬ **GetItemFunction**: (`key`: `string`) => `Promise`<`string`\\>\n\n#### Type declaration\n\n▸ (`key`): `Promise`<`string`\\>\n\nThis function provides `getItem` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Parameters\n\n| Name  | Type     |\n| :---- | :------- |\n| `key` | `string` |\n\n##### Returns\n\n`Promise`<`string`\\>\n\n---\n\n### GetItemsFunction\n\nƬ **GetItemsFunction**: (`keys`: `string`[]) => `Promise`<`string`[]\\>\n\n#### Type declaration\n\n▸ (`keys`): `Promise`<`string`[]\\>\n\nThis function provides `getItems` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Parameters\n\n| Name   | Type       |\n| :----- | :--------- |\n| `keys` | `string`[] |\n\n##### Returns\n\n`Promise`<`string`[]\\>\n\n---\n\n### GetKeysFunction\n\nƬ **GetKeysFunction**: () => `Promise`<`string`[]\\>\n\n#### Type declaration\n\n▸ (): `Promise`<`string`[]\\>\n\nThis function provides `getKeys` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Returns\n\n`Promise`<`string`[]\\>\n\n---\n\n### ImpactOccurredFunction\n\nƬ **ImpactOccurredFunction**: (`style`: `\"light\"` \\| `\"medium\"` \\| `\"heavy\"` \\| `\"rigid\"` \\| `\"soft\"`) => `void`\n\n#### Type declaration\n\n▸ (`style`): `void`\n\nA method tells that an impact occurred. The Telegram app may play the appropriate haptics based on style value passed. Style can be one of these values:\n\n- light, indicates a collision between small or lightweight UI objects,\n- medium, indicates a collision between medium-sized or medium-weight UI objects,\n- heavy, indicates a collision between large or heavyweight UI objects,\n- rigid, indicates a collision between hard or inflexible UI objects,\n- soft, indicates a collision between soft or flexible UI objects.\n  [telegram!HapticFeedback](https://core.telegram.org/bots/webapps#hapticfeedback)\n\n##### Parameters\n\n| Name    | Type                                                          |\n| :------ | :------------------------------------------------------------ |\n| `style` | `\"light\"` \\| `\"medium\"` \\| `\"heavy\"` \\| `\"rigid\"` \\| `\"soft\"` |\n\n##### Returns\n\n`void`\n\n---\n\n### InitData\n\nƬ **InitData**: `string`\n\n---\n\n### InitDataUnsafe\n\nƬ **InitDataUnsafe**: `Object`\n\n[telegram!WebAppInitData](https://core.telegram.org/bots/webapps#webappinitdata)\n\n#### Type declaration\n\n| Name              | Type                                                                    |\n| :---------------- | :---------------------------------------------------------------------- |\n| `auth_date`       | `number`                                                                |\n| `can_send_after?` | `number`                                                                |\n| `chat?`           | [`WebAppChat`](README.md#webappchat)                                    |\n| `chat_instance?`  | `string`                                                                |\n| `chat_type?`      | `\"sender\"` \\| `\"private\"` \\| `\"group\"` \\| `\"supergroup\"` \\| `\"channel\"` |\n| `hash`            | `string`                                                                |\n| `query_id?`       | `string`                                                                |\n| `receiver?`       | [`WebAppUser`](README.md#webappuser)                                    |\n| `start_param?`    | `string`                                                                |\n| `user?`           | [`WebAppUser`](README.md#webappuser)                                    |\n\n---\n\n### NotificationOccurredFunction\n\nƬ **NotificationOccurredFunction**: (`type`: `\"error\"` \\| `\"success\"` \\| `\"warning\"`) => `void`\n\n#### Type declaration\n\n▸ (`type`): `void`\n\nA method tells that a task or action has succeeded, failed, or produced a warning. The Telegram app may play the appropriate haptics based on type value passed. Type can be one of these values:\n\n- error, indicates that a task or action has failed,\n- success, indicates that a task or action has completed successfully,\n- warning, indicates that a task or action produced a warning.\n  [telegram!HapticFeedback](https://core.telegram.org/bots/webapps#hapticfeedback)\n\n##### Parameters\n\n| Name   | Type                                    |\n| :----- | :-------------------------------------- |\n| `type` | `\"error\"` \\| `\"success\"` \\| `\"warning\"` |\n\n##### Returns\n\n`void`\n\n---\n\n### Options\n\nƬ **Options**: `Object`\n\nThis object describe options be able to set through WebAppProvider\n\n#### Type declaration\n\n| Name                         | Type      | Description                                                                                                                                                                                                                                   |\n| :--------------------------- | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `async?`                     | `boolean` | -                                                                                                                                                                                                                                             |\n| `smoothButtonsTransition?`   | `boolean` | When is `true`, we can smooth button transitions due to show(), hide() calls. So when you use MainButton or BackButton on multiple pages, there will be no noticeable flickering of the button during transitions **`Default Value`** `false` |\n| `smoothButtonsTransitionMs?` | `number`  | **`Default Value`** `10` **`Remarks`**                                                                                                                                                                                                        |\n\n---\n\n### ReadTextFromClipboardFunction\n\nƬ **ReadTextFromClipboardFunction**: () => `Promise`<`string`\\>\n\n#### Type declaration\n\n▸ (): `Promise`<`string`\\>\n\nThis function provided Promise function that read text from clipboard\n\n##### Returns\n\n`Promise`<`string`\\>\n\n---\n\n### RemoveItemFunction\n\nƬ **RemoveItemFunction**: (`key`: `string`) => `Promise`<`void`\\>\n\n#### Type declaration\n\n▸ (`key`): `Promise`<`void`\\>\n\nThis function provides `removeItem` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Parameters\n\n| Name  | Type     |\n| :---- | :------- |\n| `key` | `string` |\n\n##### Returns\n\n`Promise`<`void`\\>\n\n---\n\n### RemoveItemsFunction\n\nƬ **RemoveItemsFunction**: (`key`: `string`[]) => `Promise`<`void`\\>\n\n#### Type declaration\n\n▸ (`key`): `Promise`<`void`\\>\n\nThis function provides `removeItems` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Parameters\n\n| Name  | Type       |\n| :---- | :--------- |\n| `key` | `string`[] |\n\n##### Returns\n\n`Promise`<`void`\\>\n\n---\n\n### ScanQrPopupCallback\n\nƬ **ScanQrPopupCallback**: (`text`: `string`) => `true` \\| `void`\n\n#### Type declaration\n\n▸ (`text`): `true` \\| `void`\n\nIf an optional callback parameter was passed, the callback function will be called and the text from the QR\ncode will be passed as the first argument.\nReturning true inside this callback function causes the popup to be closed.\n\n##### Parameters\n\n| Name   | Type     |\n| :----- | :------- |\n| `text` | `string` |\n\n##### Returns\n\n`true` \\| `void`\n\n---\n\n### SelectionChangedFunction\n\nƬ **SelectionChangedFunction**: () => `void`\n\n#### Type declaration\n\n▸ (): `void`\n\nA method tells that the user has changed a selection. The Telegram app may play the appropriate haptics.\n[telegram!HapticFeedback](https://core.telegram.org/bots/webapps#hapticfeedback)\n\n##### Returns\n\n`void`\n\n---\n\n### SetItemFunction\n\nƬ **SetItemFunction**: (`key`: `string`, `value`: `string`) => `Promise`<`void`\\>\n\n#### Type declaration\n\n▸ (`key`, `value`): `Promise`<`void`\\>\n\nThis function provides `setItem` method from [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) as Promise\n\n**`Throws`**\n\n##### Parameters\n\n| Name    | Type     |\n| :------ | :------- |\n| `key`   | `string` |\n| `value` | `string` |\n\n##### Returns\n\n`Promise`<`void`\\>\n\n---\n\n### ShowPopupFunction\n\nƬ **ShowPopupFunction**: (`params`: [`ShowPopupParams`](interfaces/ShowPopupParams.md)) => `Promise`<`string`\\>\n\n#### Type declaration\n\n▸ (`params`): `Promise`<`string`\\>\n\nThis function provides Promise, and resolve the field id of the pressed button will be passed.\n\n**`Throws`**\n\n##### Parameters\n\n| Name     | Type                                               |\n| :------- | :------------------------------------------------- |\n| `params` | [`ShowPopupParams`](interfaces/ShowPopupParams.md) |\n\n##### Returns\n\n`Promise`<`string`\\>\n\nButton id as string, it was described by [ShowPopupButton](interfaces/ShowPopupButton.md)\n\n---\n\n### ShowScanQrPopupFunction\n\nƬ **ShowScanQrPopupFunction**: (`params`: [`ScanQrPopupParams`](interfaces/ScanQrPopupParams.md), `callback?`: [`ScanQrPopupCallback`](README.md#scanqrpopupcallback)) => `void`\n\n#### Type declaration\n\n▸ (`params`, `callback?`): `void`\n\nA method that shows a native popup for scanning a QR code described\nby the params argument of the type [ScanQrPopupParams](interfaces/ScanQrPopupParams.md).\n\n##### Parameters\n\n| Name        | Type                                                   |\n| :---------- | :----------------------------------------------------- |\n| `params`    | [`ScanQrPopupParams`](interfaces/ScanQrPopupParams.md) |\n| `callback?` | [`ScanQrPopupCallback`](README.md#scanqrpopupcallback) |\n\n##### Returns\n\n`void`\n\n---\n\n### SwitchInlineQueryFunction\n\nƬ **SwitchInlineQueryFunction**: (`query`: `string`, `chatType?`: (`\"users\"` \\| `\"bots\"` \\| `\"groups\"` \\| `\"channels\"`)[]) => `void`\n\n#### Type declaration\n\n▸ (`query`, `chatType?`): `void`\n\nThis function that inserts the bot's username and the specified inline query in the current chat's input field\nYou have to look original description switchInlineQuery in [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps) for more information\n\n##### Parameters\n\n| Name        | Type                                                    |\n| :---------- | :------------------------------------------------------ |\n| `query`     | `string`                                                |\n| `chatType?` | (`\"users\"` \\| `\"bots\"` \\| `\"groups\"` \\| `\"channels\"`)[] |\n\n##### Returns\n\n`void`\n\n---\n\n### WebAppChat\n\nƬ **WebAppChat**: `Object`\n\n[telegram!WebAppChat](https://core.telegram.org/bots/webapps#webappchat)\n\n#### Type declaration\n\n| Name         | Type                                       |\n| :----------- | :----------------------------------------- |\n| `id`         | `number`                                   |\n| `photo_url?` | `string`                                   |\n| `title`      | `string`                                   |\n| `type`       | `\"group\"` \\| `\"supergroup\"` \\| `\"channel\"` |\n| `username?`  | `string`                                   |\n\n---\n\n### WebAppProviderProps\n\nƬ **WebAppProviderProps**: `PropsWithChildren`<{ `options?`: [`Options`](README.md#options) }\\>\n\n---\n\n### WebAppUser\n\nƬ **WebAppUser**: `Object`\n\n[telegram!WebAppUser](https://core.telegram.org/bots/webapps#webappuser)\n\n#### Type declaration\n\n| Name                        | Type      |\n| :-------------------------- | :-------- |\n| `added_to_attachment_menu?` | `true`    |\n| `allows_write_to_pm?`       | `true`    |\n| `first_name`                | `string`  |\n| `id`                        | `number`  |\n| `is_bot?`                   | `boolean` |\n| `is_premium?`               | `boolean` |\n| `language_code?`            | `string`  |\n| `last_name?`                | `string`  |\n| `photo_url?`                | `string`  |\n| `username?`                 | `string`  |\n\n## Hooks\n\n### useCloudStorage\n\n▸ **useCloudStorage**(): `Object`\n\nThis hook provides [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage) object with promises functions,\nso you don't have to pass `callback` argument\nYou have to look original description CloudStorage object in [telegram!CloudStorage](https://core.telegram.org/bots/webapps#cloudstorage)\n\n#### Returns\n\n`Object`\n\n| Name         | Type                                                 |\n| :----------- | :--------------------------------------------------- |\n| `getItem`    | [`GetItemFunction`](README.md#getitemfunction)       |\n| `getItems`   | [`GetItemsFunction`](README.md#getitemsfunction)     |\n| `getKeys`    | [`GetKeysFunction`](README.md#getkeysfunction)       |\n| `removeItem` | [`RemoveItemFunction`](README.md#removeitemfunction) |\n| `setItem`    | [`SetItemFunction`](README.md#setitemfunction)       |\n\n---\n\n### useExpand\n\n▸ **useExpand**(): readonly [`undefined` \\| `boolean`, `DispatchWithoutAction`]\n\nThis hook provided isExpanded state, and expand() handle\nYou have to look original description in [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps) for more information\n\n`isExpanded` can be `undefined`\n\n```tsx\nimport { useExpand } from \"@vkruglikov/react-telegram-web-app\";\n\nconst [isExpanded, expand] = useExpand();\nconst handleClick = () => !isExpanded && expand();\n\n<button onClick={handleClick}>\n    {showTextWhenScreenExpanded && 'expanded' : 'to expand'}\n</button>\n```\n\n#### Returns\n\nreadonly [`undefined` \\| `boolean`, `DispatchWithoutAction`]\n\n---\n\n### useHapticFeedback\n\n▸ **useHapticFeedback**(): readonly [[`ImpactOccurredFunction`](README.md#impactoccurredfunction), [`NotificationOccurredFunction`](README.md#notificationoccurredfunction), [`SelectionChangedFunction`](README.md#selectionchangedfunction)]\n\nThis hook that provided [ImpactOccurredFunction](README.md#impactoccurredfunction), [NotificationOccurredFunction](README.md#notificationoccurredfunction) and [SelectionChangedFunction](README.md#selectionchangedfunction) functions that controls haptic feedback.\nYou have to look original telegram description [telegram!HapticFeedback](https://core.telegram.org/bots/webapps#hapticfeedback), because it Hook implementing his.\n\n```tsx\nimport { useHapticFeedback } from '@vkruglikov/react-telegram-web-app';\n\nconst [impactOccurred, notificationOccurred, selectionChanged] =\n  useHapticFeedback();\n// const [,notificationOccurred] = useHapticFeedback();\n\nimpactOccurred('heavy');\nnotificationOccurred('success');\n```\n\n#### Returns\n\nreadonly [[`ImpactOccurredFunction`](README.md#impactoccurredfunction), [`NotificationOccurredFunction`](README.md#notificationoccurredfunction), [`SelectionChangedFunction`](README.md#selectionchangedfunction)]\n\n---\n\n### useInitData\n\n▸ **useInitData**(): readonly [`undefined` \\| [`InitDataUnsafe`](README.md#initdataunsafe), `undefined` \\| `string`]\n\nThis hook provides `initDataUnsafe` and `initData`\nYou have to look original description in [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps), because hook just return this.\n\n```tsx\nimport { useInitData } from '@vkruglikov/react-telegram-web-app';\n\nconst [initDataUnsafe] = useInitData();\nconst [initDataUnsafe, initData] = useInitData();\n```\n\n#### Returns\n\nreadonly [`undefined` \\| [`InitDataUnsafe`](README.md#initdataunsafe), `undefined` \\| `string`]\n\n---\n\n### useReadTextFromClipboard\n\n▸ **useReadTextFromClipboard**(): [`ReadTextFromClipboardFunction`](README.md#readtextfromclipboardfunction)\n\nThis hook that provided [ReadTextFromClipboardFunction](README.md#readtextfromclipboardfunction) Promise function that read text from clipboard.\nYou have to look original description readTextFromClipboard in [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps), because hook just implements his.\n\n```tsx\nimport { useReadTextFromClipboard } from '@vkruglikov/react-telegram-web-app';\n\nconst readText = useReadTextFromClipboard();\n\nreadText().then(console.log);\n// or\nawait readText();\n```\n\n#### Returns\n\n[`ReadTextFromClipboardFunction`](README.md#readtextfromclipboardfunction)\n\n---\n\n### useScanQrPopup\n\n▸ **useScanQrPopup**(): readonly [[`ShowScanQrPopupFunction`](README.md#showscanqrpopupfunction), [`CloseScanQrPopupFunction`](README.md#closescanqrpopupfunction)]\n\nThe hook provided showScanQrPopup function of the type [ShowScanQrPopupFunction](README.md#showscanqrpopupfunction) and closeScanQrPopup [CloseScanQrPopupFunction](README.md#closescanqrpopupfunction).\n\n#### Returns\n\nreadonly [[`ShowScanQrPopupFunction`](README.md#showscanqrpopupfunction), [`CloseScanQrPopupFunction`](README.md#closescanqrpopupfunction)]\n\n---\n\n### useShowPopup\n\n▸ **useShowPopup**(): [`ShowPopupFunction`](README.md#showpopupfunction)\n\nThe hook provided showPopup function of the type [ShowPopupFunction](README.md#showpopupfunction).\nThe function that shows a native popup described by the params argument of the type [ShowPopupParams](interfaces/ShowPopupParams.md).\n\n```tsx\nimport { useShowPopup } from '@vkruglikov/react-telegram-web-app';\n\nconst showPopup = useShowPopup();\n\nshowPopup({ message: 'Hello world' }).then(buttonId => console.log(buttonId));\n```\n\n#### Returns\n\n[`ShowPopupFunction`](README.md#showpopupfunction)\n\n---\n\n### useSwitchInlineQuery\n\n▸ **useSwitchInlineQuery**(): [`SwitchInlineQueryFunction`](README.md#switchinlinequeryfunction)\n\nThis hook that provided [SwitchInlineQueryFunction](README.md#switchinlinequeryfunction)\nYou have to look original description switchInlineQuery in [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps), because hook just implements his.\n\n#### Returns\n\n[`SwitchInlineQueryFunction`](README.md#switchinlinequeryfunction)\n\n---\n\n### useThemeParams\n\n▸ **useThemeParams**(): readonly [[`ColorScheme`](README.md#colorscheme), [`ThemeParams`](interfaces/ThemeParams.md)]\n\nThe hook provided colorScheme and themeParams values of the type [ColorScheme](README.md#colorscheme) and [ThemeParams](interfaces/ThemeParams.md).\n\n```tsx\nimport { useThemeParams } from '@vkruglikov/react-telegram-web-app';\n\nconst [colorScheme, themeParams] = useThemeParams();\n\nconsole.log(colorScheme === 'dark');\nconsole.log({\n  text_color: themeParams.text_color,\n  button_color: themeParams.button_color,\n  bg_color: themeParams.bg_color,\n});\n```\n\n#### Returns\n\nreadonly [[`ColorScheme`](README.md#colorscheme), [`ThemeParams`](interfaces/ThemeParams.md)]\n\n---\n\n### useWebApp\n\n▸ **useWebApp**(): `any`\n\nThis hook just provides native [telegram!WebApp](https://core.telegram.org/bots/webapps#initializing-mini-apps) object\n\n```tsx\nimport { useWebApp } from '@vkruglikov/react-telegram-web-app';\n\nconst WebApp = useWebApp();\n\nconsole.log(WebApp.version);\n```\n\n#### Returns\n\n`any`\n\n## React Components\n\n### BackButton\n\n▸ **BackButton**(`props`): `null`\n\nRenders a [telegram!BackButton](https://core.telegram.org/bots/webapps#backbutton) component in React app as [react!Component](https://reactjs.org/docs/react-component.html)\n\n```tsx\nimport { BackButton } from '@vkruglikov/react-telegram-web-app';\n\n<BackButton onClick={() => console.log('Hello, I am back button!')} />;\n```\n\n#### Parameters\n\n| Name    | Type                                               |\n| :------ | :------------------------------------------------- |\n| `props` | [`BackButtonProps`](interfaces/BackButtonProps.md) |\n\n#### Returns\n\n`null`\n\n---\n\n### MainButton\n\n▸ **MainButton**(`props`): `null`\n\nRenders a [telegram!MainButton](https://core.telegram.org/bots/webapps#mainbutton) component in React app as [react!Component](https://reactjs.org/docs/react-component.html)\n\n```tsx\nimport { MainButton } from '@vkruglikov/react-telegram-web-app';\n\n<MainButton\n  text=\"CLICK ME\"\n  onClick={() => console.log('Hello, I am button!')}\n/>;\n```\n\n#### Parameters\n\n| Name    | Type                                               |\n| :------ | :------------------------------------------------- |\n| `props` | [`MainButtonProps`](interfaces/MainButtonProps.md) |\n\n#### Returns\n\n`null`\n\n---\n\n### SettingsButton\n\n▸ **SettingsButton**(`props`): `null`\n\nRenders a [telegram!SettingsButton](https://core.telegram.org/bots/webapps#settingsbutton) component in React app as [react!Component](https://reactjs.org/docs/react-component.html)\n\n```tsx\nimport { SettingsButton } from '@vkruglikov/react-telegram-web-app';\n\n<SettingsButton onClick={() => console.log('Hello, I am settings button!')} />;\n```\n\n#### Parameters\n\n| Name    | Type                                                       |\n| :------ | :--------------------------------------------------------- |\n| `props` | [`SettingsButtonProps`](interfaces/SettingsButtonProps.md) |\n\n#### Returns\n\n`null`\n\n---\n\n### WebAppProvider\n\n▸ **WebAppProvider**(`props`): `ReactElement`<`any`, `string` \\| `JSXElementConstructor`<`any`\\>\\>\n\nWebAppProvider provide context with WebApp for components and hooks.\nNecessary to use only if you want to override `options`\n\n```tsx\nimport { WebAppProvider } from \"@vkruglikov/react-telegram-web-app\";\n\n<WebAppProvider>\n  <YourAppComponent />\n</WebAppProvider>\n\n// You can pass options {@link Options}\n<WebAppProvider\n  options={{\n    smoothButtonsTransition: true\n  }}\n>\n  <YourAppComponent />\n</WebAppProvider>\n```\n\n#### Parameters\n\n| Name    | Type                                                   |\n| :------ | :----------------------------------------------------- |\n| `props` | [`WebAppProviderProps`](README.md#webappproviderprops) |\n\n#### Returns\n\n`ReactElement`<`any`, `string` \\| `JSXElementConstructor`<`any`\\>\\>\n"
  },
  {
    "path": "docs/interfaces/BackButtonProps.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / BackButtonProps\n\n# Interface: BackButtonProps\n\nThe props type of [`BackButton`](../README.md#backbutton).\n\n## Table of contents\n\n### Properties\n\n- [onClick](BackButtonProps.md#onclick)\n\n## Properties\n\n### onClick\n\n• `Optional` **onClick**: () => `void`\n\n#### Type declaration\n\n▸ (): `void`\n\nThe back button press event handler\n\n##### Returns\n\n`void`\n"
  },
  {
    "path": "docs/interfaces/MainButtonProps.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / MainButtonProps\n\n# Interface: MainButtonProps\n\nThe props type of [`MainButton`](../README.md#mainbutton).\n\n## Table of contents\n\n### Properties\n\n- [color](MainButtonProps.md#color)\n- [disabled](MainButtonProps.md#disabled)\n- [onClick](MainButtonProps.md#onclick)\n- [progress](MainButtonProps.md#progress)\n- [text](MainButtonProps.md#text)\n- [textColor](MainButtonProps.md#textcolor)\n\n## Properties\n\n### color\n\n• `Optional` **color**: `string`\n\nCurrent button color.\n\n**`Default Value`**\n\nSet to themeParams.button_color by default\n\n---\n\n### disabled\n\n• `Optional` **disabled**: `boolean`\n\nThe button disable state.\n\n**`Default Value`**\n\nSet to `false` y defaults\n\n---\n\n### onClick\n\n• `Optional` **onClick**: () => `void`\n\n#### Type declaration\n\n▸ (): `void`\n\nThe button press event handler\n\n##### Returns\n\n`void`\n\n---\n\n### progress\n\n• `Optional` **progress**: `boolean`\n\nThe button progress state indicator.\n\n**`Default Value`**\n\nSet to `false` by default\n\n---\n\n### text\n\n• `Optional` **text**: `string`\n\nCurrent button text\n\n**`Default Value`**\n\nSet to `CONTINUE` by default\n\n---\n\n### textColor\n\n• `Optional` **textColor**: `string`\n\nCurrent button text color\n\n**`Default Value`**\n\nSet to themeParams.button_text_color by default\n"
  },
  {
    "path": "docs/interfaces/ScanQrPopupParams.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / ScanQrPopupParams\n\n# Interface: ScanQrPopupParams\n\nThis object describes the native popup for scanning QR codes.\nYou have to see original interface [telegram!ScanQrPopupParams](https://core.telegram.org/bots/webapps#scanqrpopupparams).\n\n## Table of contents\n\n### Properties\n\n- [text](ScanQrPopupParams.md#text)\n\n## Properties\n\n### text\n\n• **text**: `string`\n\nThe text to be displayed under the 'Scan QR' heading, 0-64 characters.\n"
  },
  {
    "path": "docs/interfaces/SettingsButtonProps.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / SettingsButtonProps\n\n# Interface: SettingsButtonProps\n\nThe props type of [`SettingsButton`](../README.md#settingsbutton).\n\n## Table of contents\n\n### Properties\n\n- [onClick](SettingsButtonProps.md#onclick)\n\n## Properties\n\n### onClick\n\n• `Optional` **onClick**: () => `void`\n\n#### Type declaration\n\n▸ (): `void`\n\n##### Returns\n\n`void`\n"
  },
  {
    "path": "docs/interfaces/ShowPopupButton.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / ShowPopupButton\n\n# Interface: ShowPopupButton\n\nYou have to see original interface [telegram!PopupButton](https://core.telegram.org/bots/webapps#popupbutton).\n\n## Hierarchy\n\n- `Record`<`string`, `unknown`\\>\n\n  ↳ **`ShowPopupButton`**\n\n## Table of contents\n\n### Properties\n\n- [id](ShowPopupButton.md#id)\n- [text](ShowPopupButton.md#text)\n- [type](ShowPopupButton.md#type)\n\n## Properties\n\n### id\n\n• `Optional` **id**: `string`\n\nOptional. Identifier of the button, 0-64 characters.\nSet to empty string by default.\nIf the button is pressed, its id is returned in the callback and the popupClosed event.\n\n---\n\n### text\n\n• `Optional` **text**: `string`\n\nOptional. The text to be displayed on the button, 0-64 characters.\nRequired if type is default or destructive.\nIrrelevant for other types.\n\n---\n\n### type\n\n• `Optional` **type**: `string`\n\nOptional. Type of the button.\nSet to default by default.\n"
  },
  {
    "path": "docs/interfaces/ShowPopupParams.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / ShowPopupParams\n\n# Interface: ShowPopupParams\n\nYou have to see original interface [telegram!PopupParams](https://core.telegram.org/bots/webapps#popupparams).\n\n## Hierarchy\n\n- `Record`<`string`, `unknown`\\>\n\n  ↳ **`ShowPopupParams`**\n\n## Table of contents\n\n### Properties\n\n- [buttons](ShowPopupParams.md#buttons)\n- [message](ShowPopupParams.md#message)\n- [title](ShowPopupParams.md#title)\n\n## Properties\n\n### buttons\n\n• `Optional` **buttons**: [`ShowPopupButton`](ShowPopupButton.md)[]\n\nOptional. List of buttons to be displayed in the popup, 1-3 buttons\n\n---\n\n### message\n\n• **message**: `string`\n\nThe message to be displayed in the body of the popup, 1-256 characters.\n\n---\n\n### title\n\n• `Optional` **title**: `string`\n\nOptional. The text to be displayed in the popup title, 0-64 characters.\n"
  },
  {
    "path": "docs/interfaces/ThemeParams.md",
    "content": "[@vkruglikov/react-telegram-web-app](../README.md) / ThemeParams\n\n# Interface: ThemeParams\n\nThis object contains the user's current theme settings.\nThis object implement original Telegram WebApp type of [telegram!ThemeParams](https://core.telegram.org/bots/webapps#themeparams)\n\n## Table of contents\n\n### Properties\n\n- [bg_color](ThemeParams.md#bg_color)\n- [button_color](ThemeParams.md#button_color)\n- [button_text_color](ThemeParams.md#button_text_color)\n- [hint_color](ThemeParams.md#hint_color)\n- [link_color](ThemeParams.md#link_color)\n- [secondary_bg_color](ThemeParams.md#secondary_bg_color)\n- [text_color](ThemeParams.md#text_color)\n\n## Properties\n\n### bg_color\n\n• `Optional` **bg_color**: `string`\n\nBackground color in the #RRGGBB format.\n\n---\n\n### button_color\n\n• `Optional` **button_color**: `string`\n\nButton color in the #RRGGBB format.\n\n---\n\n### button_text_color\n\n• `Optional` **button_text_color**: `string`\n\nButton text color in the #RRGGBB format.\n\n---\n\n### hint_color\n\n• `Optional` **hint_color**: `string`\n\nHint text color in the #RRGGBB format.\n\n---\n\n### link_color\n\n• `Optional` **link_color**: `string`\n\nLink color in the #RRGGBB format.\n\n---\n\n### secondary_bg_color\n\n• `Optional` **secondary_bg_color**: `string`\n\nSecondary background color in the #RRGGBB format.\n\n---\n\n### text_color\n\n• `Optional` **text_color**: `string`\n\nMain text color in the #RRGGBB format.\n"
  },
  {
    "path": "global.d.ts",
    "content": "import { WebApp } from './src/core/twa-types';\n\ndeclare global {\n  interface Window {\n    Telegram?: {\n      WebApp: WebApp;\n    };\n    TelegramWebviewProxy?: any;\n  }\n}\n"
  },
  {
    "path": "jest.config.json",
    "content": "{\n  \"transform\": {\n    \"\\\\.[jt]sx?$\": \"ts-jest\"\n  },\n  \"testEnvironment\": \"jsdom\",\n  \"setupFilesAfterEnv\": [\"./tests/setupTests.ts\"]\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@vkruglikov/react-telegram-web-app\",\n  \"version\": \"2.2.0\",\n  \"description\": \"React components for Telegram WebApp\",\n  \"source\": \"./src/index.ts\",\n  \"type\": \"module\",\n  \"keywords\": [\n    \"react\",\n    \"telegram\",\n    \"telegram-bot\"\n  ],\n  \"exports\": {\n    \"types\": \"./lib/index.d.ts\",\n    \"require\": \"./lib/react-telegram-web-app.cjs\",\n    \"default\": \"./lib/react-telegram-web-app.modern.js\"\n  },\n  \"files\": [\n    \"/lib\"\n  ],\n  \"main\": \"lib/react-telegram-web-app.cjs\",\n  \"module\": \"lib/react-telegram-web-app.module.js\",\n  \"unpkg\": \"lib/react-telegram-web-app.umd.js\",\n  \"types\": \"lib/index.d.ts\",\n  \"scripts\": {\n    \"build\": \"rm -rf ./lib/*; microbundle build --sourcemap=false && cp -R src/core/twa-types lib/core/twa-types\",\n    \"dev\": \"npm run build && microbundle watch --compress=false\",\n    \"prepare\": \"husky install\",\n    \"changeset\": \"changeset\",\n    \"docs\": \"typedoc && prettier --write ./docs\",\n    \"release\": \"npm run test:all && npm run build && npm run test:package && changeset publish\",\n    \"format\": \"prettier --write .\",\n    \"eslint\": \"npx eslint src\",\n    \"test\": \"NODE_ENV=test jest\",\n    \"test:all\": \"NODE_ENV=test jest --testPathIgnorePatterns package\",\n    \"test:package\": \"NODE_ENV=test jest  package\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vkruglikov/react-telegram-web-app.git\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"author\": \"Valentin Kruglikov dev.n@bk.ru\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vkruglikov/react-telegram-web-app/issues\"\n  },\n  \"homepage\": \"https://github.com/vkruglikov/react-telegram-web-app#readme\",\n  \"devDependencies\": {\n    \"@changesets/cli\": \"^2.25.2\",\n    \"@testing-library/react\": \"^14.0.0\",\n    \"@types/jest\": \"^29.5.2\",\n    \"@types/react\": \"^18\",\n    \"@types/react-test-renderer\": \"^18.0.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.1.0\",\n    \"@typescript-eslint/parser\": \"^6.1.0\",\n    \"eslint\": \"^8.45.0\",\n    \"eslint-plugin-react\": \"^7.32.2\",\n    \"eslint-plugin-react-hooks\": \"^4.6.0\",\n    \"husky\": \"^8.0.2\",\n    \"jest\": \"^29.6.1\",\n    \"jest-environment-jsdom\": \"^29.6.1\",\n    \"lint-staged\": \"^13.0.3\",\n    \"microbundle\": \"^0.15.1\",\n    \"prettier\": \"2.8.0\",\n    \"react-test-renderer\": \"^18.2.0\",\n    \"ts-jest\": \"^29.1.1\",\n    \"typedoc\": \"^0.24.8\",\n    \"typedoc-plugin-markdown\": \"^3.15.3\",\n    \"typescript\": \"^5.1.6\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^18\",\n    \"react-dom\": \"^18\"\n  },\n  \"lint-staged\": {\n    \"*.(tsx|ts)\": [\n      \"eslint\",\n      \"prettier --write\"\n    ],\n    \"*.md\": [\n      \"prettier --write\"\n    ]\n  }\n}\n"
  },
  {
    "path": "src/BackButton.tsx",
    "content": "import { useContext, useEffect, useId } from 'react';\nimport { useWebApp, useSmoothButtonsTransition, systemContext } from './core';\n\n/**\n * The props type of {@link BackButton | `BackButton`}.\n */\nexport interface BackButtonProps {\n  /** The back button press event handler */\n  onClick?: () => void;\n}\n\n/**\n * Renders a {@link telegram!BackButton} component in React app as {@link react!Component}\n *\n * ```tsx\n * import { BackButton } from \"@vkruglikov/react-telegram-web-app\";\n *\n * <BackButton\n *     onClick={() => console.log('Hello, I am back button!')}\n * />\n * ```\n * @param props\n * @group React Components\n */\nconst BackButton = ({ onClick }: BackButtonProps): null => {\n  const system = useContext(systemContext);\n  const buttonId = useId();\n  const WebApp = useWebApp();\n  const BackButton = WebApp?.BackButton;\n\n  useEffect(() => {\n    if (!onClick || !BackButton) {\n      return;\n    }\n\n    BackButton.onClick(onClick);\n    return () => {\n      BackButton.offClick(onClick);\n    };\n  }, [onClick, BackButton]);\n\n  useSmoothButtonsTransition({\n    show: BackButton?.show,\n    hide: BackButton?.hide,\n    currentShowedIdRef: system.BackButton,\n    id: buttonId,\n  });\n\n  return null;\n};\n\nexport default BackButton;\n"
  },
  {
    "path": "src/MainButton.tsx",
    "content": "import { useContext, useEffect, useId } from 'react';\nimport { useWebApp, useSmoothButtonsTransition, systemContext } from './core';\n\n/**\n * The props type of {@link MainButton | `MainButton`}.\n */\nexport interface MainButtonProps {\n  /**\n   * Current button text\n   * @defaultValue Set to `CONTINUE` by default\n   */\n  text?: string;\n  /**\n   * The button progress state indicator.\n   * @defaultValue  Set to `false` by default\n   */\n  progress?: boolean;\n  /**\n   * Just an alias on the {@link MainButtonProps.disabled}\n   * @deprecated Use {@link MainButtonProps.disabled} instead, will be removed\n   * @ignore\n   */\n  disable?: boolean;\n  /**\n   * The button disable state.\n   * @defaultValue Set to `false` y defaults\n   */\n  disabled?: boolean;\n  /** The button press event handler */\n  onClick?: () => void;\n  /**\n   * Current button color.\n   * @defaultValue Set to themeParams.button_color by default\n   */\n  color?: string;\n  /**\n   * Current button text color\n   * @defaultValue Set to themeParams.button_text_color by default\n   */\n  textColor?: string;\n}\n\n/**\n * Renders a {@link telegram!MainButton} component in React app as {@link react!Component}\n *\n * ```tsx\n * import { MainButton } from \"@vkruglikov/react-telegram-web-app\";\n *\n * <MainButton\n *     text=\"CLICK ME\"\n *     onClick={() => console.log('Hello, I am button!')}\n * />\n * ```\n * @param props\n * @group React Components\n */\nconst MainButton = ({\n  text = 'CONTINUE',\n  progress = false,\n  disable: disable_old,\n  disabled: disable_new = false,\n  color,\n  textColor,\n  onClick,\n}: MainButtonProps): null => {\n  const system = useContext(systemContext);\n  const buttonId = useId();\n  const WebApp = useWebApp();\n  const MainButton = WebApp?.MainButton;\n  const themeParams = WebApp?.themeParams;\n  const disabled = disable_old || disable_new;\n\n  useEffect(() => {\n    MainButton?.setParams({\n      color: color || themeParams?.button_color || '#fff',\n    });\n  }, [color, themeParams, MainButton]);\n\n  useEffect(() => {\n    MainButton?.setParams({\n      text_color: textColor || themeParams?.button_text_color || '#000',\n    });\n  }, [MainButton, themeParams, textColor]);\n\n  useEffect(() => {\n    MainButton?.setText(text);\n  }, [text, MainButton]);\n\n  useEffect(() => {\n    if (disabled) {\n      MainButton?.disable();\n    } else if (!disabled) {\n      MainButton?.enable();\n    }\n  }, [disabled, MainButton]);\n\n  useEffect(() => {\n    if (progress) {\n      MainButton?.showProgress(false);\n    } else if (!progress) {\n      MainButton?.hideProgress();\n    }\n  }, [progress, MainButton]);\n\n  useEffect(() => {\n    if (!onClick) {\n      return;\n    }\n\n    MainButton?.onClick(onClick);\n    return () => {\n      MainButton?.offClick(onClick);\n    };\n  }, [onClick, MainButton]);\n\n  useSmoothButtonsTransition({\n    show: MainButton?.show,\n    hide: MainButton?.hide,\n    currentShowedIdRef: system.MainButton,\n    id: buttonId,\n  });\n\n  return null;\n};\n\nexport default MainButton;\n"
  },
  {
    "path": "src/SettingsButton.tsx",
    "content": "import { useEffect } from 'react';\nimport { useWebApp } from './core';\n\n/**\n * The props type of {@link SettingsButton | `SettingsButton`}.\n */\nexport interface SettingsButtonProps {\n  onClick?: () => void;\n}\n\n/**\n * Renders a {@link telegram!SettingsButton} component in React app as {@link react!Component}\n *\n * ```tsx\n * import { SettingsButton } from \"@vkruglikov/react-telegram-web-app\";\n *\n * <SettingsButton\n *     onClick={() => console.log('Hello, I am settings button!')}\n * />\n * ```\n * @param props\n * @group React Components\n */\nconst SettingsButton = ({ onClick }: SettingsButtonProps): null => {\n  const WebApp = useWebApp();\n\n  useEffect(() => {\n    if (!onClick || !WebApp?.SettingsButton) {\n      return;\n    }\n\n    WebApp.SettingsButton.onClick(onClick);\n    return () => {\n      WebApp.SettingsButton.offClick(onClick);\n    };\n  }, [onClick, WebApp]);\n\n  useEffect(() => {\n    if (!WebApp?.SettingsButton) {\n      return;\n    }\n\n    WebApp.SettingsButton.show?.();\n\n    return () => {\n      WebApp.SettingsButton.hide?.();\n    };\n  }, [WebApp]);\n\n  return null;\n};\n\nexport default SettingsButton;\n"
  },
  {
    "path": "src/WebAppProvider.tsx",
    "content": "import React, {\n  PropsWithChildren,\n  ReactElement,\n  useEffect,\n  useMemo,\n} from 'react';\nimport {\n  webAppContext,\n  optionsContext,\n  systemContext,\n  Options,\n  DEFAULT_OPTIONS,\n  createSystemContextValue,\n  getWebAppFromGlobal,\n  useAsyncMode,\n} from './core';\n\nexport type WebAppProviderProps = PropsWithChildren<{\n  options?: Options;\n}>;\n\n/**\n * WebAppProvider provide context with WebApp for components and hooks.\n * Necessary to use only if you want to override `options`\n *\n * ```tsx\n * import { WebAppProvider } from \"@vkruglikov/react-telegram-web-app\";\n *\n * <WebAppProvider>\n *   <YourAppComponent />\n * </WebAppProvider>\n *\n * // You can pass options {@link Options}\n * <WebAppProvider\n *   options={{\n *     smoothButtonsTransition: true\n *   }}\n * >\n *   <YourAppComponent />\n * </WebAppProvider>\n * ```\n * @param props\n * @group React Components\n */\nconst WebAppProvider = ({\n  children,\n  options,\n}: WebAppProviderProps): ReactElement => {\n  const isLoadedWithAsyncMode = useAsyncMode(!!options?.async);\n  const mergedOptions = useMemo(\n    () => ({\n      ...DEFAULT_OPTIONS,\n      ...options,\n    }),\n    [options],\n  );\n  const systemValue = useMemo(createSystemContextValue, []);\n  const globalWebApp = useMemo(getWebAppFromGlobal, [isLoadedWithAsyncMode]);\n\n  useEffect(() => {\n    if (!options?.smoothButtonsTransition) return;\n    const forceHideButtons = () => {\n      globalWebApp?.MainButton?.hide();\n      globalWebApp?.BackButton?.hide();\n      globalWebApp?.SettingsButton?.hide();\n    };\n\n    window.addEventListener('beforeunload', forceHideButtons);\n    return () => window.removeEventListener('beforeunload', forceHideButtons);\n  }, [globalWebApp, options?.smoothButtonsTransition]);\n\n  return (\n    <systemContext.Provider value={systemValue}>\n      <webAppContext.Provider value={globalWebApp}>\n        <optionsContext.Provider value={mergedOptions}>\n          {children}\n        </optionsContext.Provider>\n      </webAppContext.Provider>\n    </systemContext.Provider>\n  );\n};\nexport default WebAppProvider;\n"
  },
  {
    "path": "src/core/context.ts",
    "content": "import { createContext, MutableRefObject } from 'react';\n\nexport const getWebAppFromGlobal = () =>\n  typeof window !== 'undefined' && window?.Telegram?.WebApp\n    ? window.Telegram.WebApp\n    : null;\n\nexport const webAppContext = createContext<\n  ReturnType<typeof getWebAppFromGlobal>\n>(getWebAppFromGlobal());\n\n/**\n * This object describe options be able to set through WebAppProvider\n */\nexport type Options = {\n  /**\n   * When is `true`, we can smooth button transitions due to show(), hide() calls.\n   * So when you use MainButton or BackButton on multiple pages, there will be\n   * no noticeable flickering of the button during transitions\n   * @defaultValue `false`\n   */\n  smoothButtonsTransition?: boolean;\n  async?: boolean;\n  /**\n   * @defaultValue `10`\n   * @remarks\n   */\n  smoothButtonsTransitionMs?: number;\n};\n\nexport const DEFAULT_OPTIONS: Options = {\n  smoothButtonsTransition: false,\n  smoothButtonsTransitionMs: 10,\n};\n\nexport const optionsContext = createContext<Options>(DEFAULT_OPTIONS);\n\ntype SystemContext = {\n  MainButton: MutableRefObject<null | string>;\n  BackButton: MutableRefObject<null | string>;\n};\n\nexport const createSystemContextValue = () => ({\n  MainButton: { current: null },\n  BackButton: { current: null },\n});\n\nexport const systemContext = createContext<SystemContext>(\n  createSystemContextValue(),\n);\n"
  },
  {
    "path": "src/core/index.ts",
    "content": "export { default as useSmoothButtonsTransition } from './useSmoothButtonsTransition';\nexport { default as useWebApp } from './useWebApp';\nexport { default as useAsyncMode } from './useAsyncMode';\nexport * from './context';\n"
  },
  {
    "path": "src/core/twa-types/WebApp.d.ts",
    "content": "export declare namespace TelegramWebApp {\n  /**\n   * {@link https://core.telegram.org/bots/webapps#themeparams}\n   */\n  interface ThemeParams {\n    bg_color?: string;\n    text_color?: string;\n    hint_color?: string;\n    link_color?: string;\n    button_color?: string;\n    button_text_color?: string;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#mainbutton}\n   */\n  interface MainButton {\n    text: string;\n    color: string;\n    textColor: string;\n    isVisible: boolean;\n    isActive: boolean;\n    readonly isProgressVisible: boolean;\n\n    setText(text: string): MainButton;\n\n    show(): MainButton;\n\n    hide(): MainButton;\n\n    enable(): MainButton;\n\n    disable(): MainButton;\n\n    showProgress(leaveActive?: boolean): MainButton;\n\n    hideProgress(): MainButton;\n    onClick(callback: () => void);\n\n    setParams(params: {\n      text?: MainButton['text'];\n      color?: MainButton['color'];\n      text_color?: MainButton['textColor'];\n      is_active?: MainButton['isActive'];\n      is_visible?: MainButton['isVisible'];\n    }): MainButton;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#webappuser}\n   */\n  interface WebAppUser {\n    id: number;\n    is_bot?: boolean;\n    first_name: string;\n    last_name?: string;\n    username?: string;\n    language_code?: string;\n    photo_url?: string;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#webappinitdata}\n   */\n  interface WebAppInitData {\n    query_id?: string;\n    user?: WebAppUser;\n    receiver?: WebAppUser;\n    chat_type?: 'sender' | 'private' | 'group' | 'supergroup' | 'channel';\n    chat_instance?: string;\n    start_param?: string;\n    auth_date: number;\n    hash: string;\n  }\n\n  interface Event {\n    onEvent(\n      eventType: 'viewportChanged',\n      eventHandler: (payload: { isStateStable: boolean }) => void,\n    );\n\n    onEvent(\n      eventType: 'themeChanged' | 'mainButtonClicked',\n      eventHandler: () => void,\n    );\n\n    offEvent(\n      eventType: 'viewportChanged' | 'themeChanged' | 'mainButtonClicked',\n      eventHandler: (...args: any[]) => void,\n    );\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#initializing-web-apps}\n   */\n  interface WebApp extends Event {\n    initData: string;\n    initDataUnsafe: WebAppInitData;\n    platform: string;\n    colorScheme: 'dark' | 'light';\n    themeParams: ThemeParams;\n    isExpanded: boolean;\n    viewportHeight: number;\n    viewportStableHeight: number;\n    MainButton: MainButton;\n\n    sendData(data: unknown);\n\n    ready();\n\n    expand();\n\n    close();\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_6.1.d.ts",
    "content": "import { TelegramWebApp } from './WebApp';\n\nexport declare namespace TelegramWebAppVersion6_1 {\n  interface ThemeParams extends TelegramWebApp.ThemeParams {\n    secondary_bg_color?: string;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#backbutton}\n   */\n  interface BackButton {\n    isVisible: boolean;\n\n    onClick(cb: () => void): BackButton;\n\n    offClick(cb: () => void): BackButton;\n\n    show(): BackButton;\n\n    hide(): BackButton;\n  }\n\n  interface MainButton extends TelegramWebApp.MainButton {\n    offClick(text: () => void): MainButton;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#webappchat}\n   */\n  interface WebAppChat {\n    id: number;\n    type: 'group' | 'supergroup' | 'channel';\n    title: string;\n    username?: string;\n    photo_url?: string;\n  }\n\n  interface WebAppInitData extends TelegramWebApp.WebAppInitData {\n    chat?: WebAppChat;\n    can_send_after?: number;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#hapticfeedback}\n   */\n  interface HapticFeedback {\n    impactOccurred(\n      style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft',\n    ): HapticFeedback;\n\n    notificationOccurred(type: 'error' | 'success' | 'warning'): HapticFeedback;\n\n    selectionChanged(): HapticFeedback;\n  }\n\n  interface Event {\n    onEvent(\n      eventType: 'backButtonClicked' | 'settingsButtonClicked',\n      eventHandler: () => void,\n    );\n\n    onEvent(\n      eventType: 'invoiceClosed',\n      eventHandler: (payload: {\n        url: string;\n        status: 'paid' | 'cancelled' | 'failed' | 'pending';\n      }) => void,\n    );\n\n    offEvent(\n      eventType:\n        | 'backButtonClicked'\n        | 'settingsButtonClicked'\n        | 'invoiceClosed',\n      eventHandler: (...args: any[]) => void,\n    );\n  }\n\n  interface WebApp extends TelegramWebApp.WebApp, Event {\n    themeParams: ThemeParams;\n    initDataUnsafe: WebAppInitData;\n    MainButton: MainButton;\n    version: string;\n    headerColor: string;\n    backgroundColor: string;\n    BackButton: BackButton;\n    HapticFeedback: HapticFeedback;\n    isVersionAtLeast(version: string | number): boolean;\n    setHeaderColor(color: 'bg_color' | 'secondary_bg_color' | string);\n    setBackgroundColor(color: 'bg_color' | 'secondary_bg_color' | string);\n    openLink(url: string);\n    openTelegramLink(url: string);\n    openInvoice(\n      url: string,\n      callback?: (status: 'paid' | 'cancelled' | 'failed' | 'pending') => void,\n    );\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_6.2.d.ts",
    "content": "import { TelegramWebAppVersion6_1 } from './WebAppVersion_6.1';\nimport { TelegramWebApp } from './WebApp';\n\nexport declare namespace TelegramWebAppVersion6_2 {\n  /**\n   * {@link https://core.telegram.org/bots/webapps#webappuser}\n   */\n  interface WebAppUser extends TelegramWebApp.WebAppUser {\n    is_premium?: true;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#webappinitdata}\n   */\n  interface WebAppInitData extends TelegramWebAppVersion6_1.WebAppInitData {\n    user?: WebAppUser;\n    receiver?: WebAppUser;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#popupbutton}\n   */\n  interface PopupButton {\n    id?: string;\n    type?: string;\n    text?: string;\n  }\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#popupparams}\n   */\n  interface PopupParams {\n    title?: string;\n    message: string;\n    buttons?: PopupButton[];\n  }\n\n  interface Event {\n    onEvent(\n      eventType: 'popupClosed',\n      eventHandler: (payload: { button_id: string }) => void,\n    );\n\n    offEvent(eventType: 'popupClosed', eventHandler: (...args: any[]) => void);\n  }\n\n  interface WebApp extends TelegramWebAppVersion6_1.WebApp, Event {\n    initDataUnsafe: WebAppInitData;\n    isClosingConfirmationEnabled: string;\n    enableClosingConfirmation();\n    disableClosingConfirmation();\n    showPopup(params: PopupParams, callback?: (id: string) => void);\n    showAlert(message: string, callback?: () => void);\n    showConfirm(message: string, callback?: (isOk: boolean) => void);\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_6.4.d.ts",
    "content": "import { TelegramWebAppVersion6_2 } from './WebAppVersion_6.2';\n\nexport declare namespace TelegramWebAppVersion6_4 {\n  /**\n   * {@link https://core.telegram.org/bots/webapps#scanqrpopupparams}\n   */\n  interface ScanQrPopupParams {\n    text?: string;\n  }\n\n  interface Event {\n    onEvent(eventType: 'qrTextReceived', eventHandler: (data: string) => void);\n\n    onEvent(\n      eventType: 'clipboardTextReceived',\n      eventHandler: (payload: { data: string | null }) => void,\n    );\n\n    offEvent(\n      eventType: 'qrTextReceived' | 'clipboardTextReceived',\n      eventHandler: (...args: any[]) => void,\n    );\n  }\n\n  interface WebApp extends TelegramWebAppVersion6_2.WebApp, Event {\n    openLink(url: string, options?: { try_instant_view: true });\n\n    platform: string;\n    showScanQrPopup(\n      params: ScanQrPopupParams,\n      callback?: (data: string) => void | boolean,\n    );\n    closeScanQrPopup();\n    readTextFromClipboard(callback?: (data: string) => void);\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_6.7.d.ts",
    "content": "import { TelegramWebAppVersion6_4 } from './WebAppVersion_6.4';\n\nexport declare namespace TelegramWebAppVersion6_7 {\n  interface WebApp extends TelegramWebAppVersion6_4.WebApp {\n    switchInlineQuery(query: string, choose_chat_types?: unknown);\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_6.9.d.ts",
    "content": "import { TelegramWebAppVersion6_7 } from './WebAppVersion_6.7';\nimport { TelegramWebAppVersion6_2 } from './WebAppVersion_6.2';\n\nexport declare namespace TelegramWebAppVersion6_9 {\n  interface WebAppUser extends TelegramWebAppVersion6_2.WebAppUser {\n    added_to_attachment_menu?: true;\n    allows_write_to_pm?: true;\n  }\n\n  interface Event {\n    onEvent(\n      eventType: 'writeAccessRequested',\n      eventHandler: (data: { status: 'allowed' | 'cancelled' }) => void,\n    );\n\n    onEvent(\n      eventType: 'contactRequested',\n      eventHandler: (payload: { data: 'sent' | 'cancelled' }) => void,\n    );\n\n    offEvent(\n      eventType: 'writeAccessRequested' | 'contactRequested',\n      eventHandler: (...args: any[]) => void,\n    );\n  }\n\n  type StorageKey = string;\n  type CloudStorageCallback<T> =\n    | ((error: Error) => void)\n    | ((error: null, result: T) => void);\n\n  /**\n   * {@link https://core.telegram.org/bots/webapps#cloudstorage}\n   */\n  interface CloudStorage {\n    setItem(\n      key: StorageKey,\n      value: string,\n      callback?: CloudStorageCallback<boolean>,\n    ): void;\n    getItem(key: StorageKey, callback: CloudStorageCallback<string>): void;\n    getItems(\n      keys: StorageKey[],\n      callback: CloudStorageCallback<string[]>,\n    ): void;\n    removeItem(key: StorageKey, callback?: CloudStorageCallback<boolean>): void;\n    removeItems(\n      keys: StorageKey[],\n      callback?: CloudStorageCallback<boolean>,\n    ): void;\n    getKeys(callback: CloudStorageCallback<string[]>): void;\n  }\n\n  interface WebApp extends TelegramWebAppVersion6_7.WebApp, Event {\n    CloudStorage: CloudStorage;\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/WebAppVersion_7.0.d.ts",
    "content": "export declare namespace TelegramWebAppVersion7_0 {\n  interface WebApp extends TelegramWebAppVersion6_9.WebApp {\n    // TODO Fix types SettingsButton\n    SettingsButton?: any;\n  }\n}\n"
  },
  {
    "path": "src/core/twa-types/index.d.ts",
    "content": "import { TelegramWebApp } from './WebApp';\nimport { TelegramWebAppVersion6_1 } from './WebAppVersion_6.1';\nimport { TelegramWebAppVersion6_2 } from './WebAppVersion_6.2';\nimport { TelegramWebAppVersion6_4 } from './WebAppVersion_6.4';\nimport { TelegramWebAppVersion6_7 } from './WebAppVersion_6.7';\nimport { TelegramWebAppVersion6_9 } from './WebAppVersion_6.9';\nimport { TelegramWebAppVersion7_0 } from './WebAppVersion_7.0';\n\nexport type WebApp = TelegramWebApp.WebApp &\n  Partial<TelegramWebAppVersion6_1.WebApp> &\n  Partial<TelegramWebAppVersion6_2.WebApp> &\n  Partial<TelegramWebAppVersion6_4.WebApp> &\n  Partial<TelegramWebAppVersion6_7.WebApp> &\n  Partial<TelegramWebAppVersion6_9.WebApp> &\n  Partial<TelegramWebAppVersion7_0.WebApp>;\n"
  },
  {
    "path": "src/core/useAsyncMode.ts",
    "content": "import { useEffect, useState } from 'react';\n\nconst useAsyncMode = (enabled: boolean) => {\n  const [isLoaded, setIsLoaded] = useState(false);\n\n  useEffect(() => {\n    if (!enabled) return;\n\n    if (window.Telegram?.WebApp) {\n      setIsLoaded(true);\n      return;\n    }\n\n    const nativeProxyPostHandle =\n      typeof window !== 'undefined' &&\n      window.TelegramWebviewProxy &&\n      window.TelegramWebviewProxy.postEvent;\n\n    if (window.TelegramWebviewProxy) {\n      window.TelegramWebviewProxy.postEvent = (...args: any[]) => {\n        nativeProxyPostHandle?.(...args);\n\n        if (window.Telegram?.WebApp) {\n          setIsLoaded(true);\n          window.TelegramWebviewProxy.postEvent = nativeProxyPostHandle;\n        }\n      };\n    } else {\n      window.TelegramWebviewProxy = {\n        postEvent: (...args: any[]) => {\n          nativeProxyPostHandle?.(...args);\n          if (window.Telegram?.WebApp) {\n            setIsLoaded(true);\n            delete window.TelegramWebviewProxy;\n          }\n        },\n      };\n    }\n  }, [enabled]);\n\n  return isLoaded;\n};\n\nexport default useAsyncMode;\n"
  },
  {
    "path": "src/core/useSmoothButtonsTransition.ts",
    "content": "import { MutableRefObject, useContext, useEffect } from 'react';\nimport { optionsContext } from './context';\n\nconst _noop = () => {};\n\nconst useSmoothButtonsTransition = ({\n  id,\n  show = _noop,\n  hide = _noop,\n  currentShowedIdRef,\n}: {\n  id: string;\n  show: typeof _noop | undefined;\n  hide: typeof _noop | undefined;\n  currentShowedIdRef: MutableRefObject<string | null>;\n}) => {\n  const { smoothButtonsTransition, smoothButtonsTransitionMs } =\n    useContext(optionsContext);\n\n  useEffect(() => {\n    show();\n    currentShowedIdRef.current = id;\n\n    return () => {\n      if (smoothButtonsTransition) {\n        currentShowedIdRef.current = null;\n        setTimeout(() => {\n          if (currentShowedIdRef.current) return;\n\n          hide();\n        }, smoothButtonsTransitionMs);\n      } else {\n        hide();\n        currentShowedIdRef.current = null;\n      }\n    };\n  }, [\n    hide,\n    id,\n    currentShowedIdRef,\n    show,\n    smoothButtonsTransition,\n    smoothButtonsTransitionMs,\n  ]);\n};\n\nexport default useSmoothButtonsTransition;\n"
  },
  {
    "path": "src/core/useWebApp.ts",
    "content": "import { useContext } from 'react';\nimport { webAppContext } from './context';\n\n/**\n * @private\n * @ignore\n */\nconst useWebApp = () => {\n  const context = useContext(webAppContext);\n\n  return context;\n};\n\nexport default useWebApp;\n"
  },
  {
    "path": "src/index.ts",
    "content": "export { default as MainButton, MainButtonProps } from './MainButton';\nexport { default as BackButton, BackButtonProps } from './BackButton';\nexport {\n  default as SettingsButton,\n  SettingsButtonProps,\n} from './SettingsButton';\nexport {\n  default as useShowPopup,\n  ShowPopupFunction,\n  ShowPopupParams,\n  ShowPopupButton,\n} from './useShowPopup';\nexport {\n  default as useHapticFeedback,\n  ImpactOccurredFunction,\n  NotificationOccurredFunction,\n  SelectionChangedFunction,\n} from './useHapticFeedback';\nexport {\n  default as useThemeParams,\n  ThemeParams,\n  ColorScheme,\n} from './useThemeParams';\nexport {\n  default as useScanQrPopup,\n  ScanQrPopupCallback,\n  ScanQrPopupParams,\n  ShowScanQrPopupFunction,\n  CloseScanQrPopupFunction,\n} from './useScanQrPopup';\nexport {\n  default as useReadTextFromClipboard,\n  ReadTextFromClipboardFunction,\n} from './useReadTextFromClipboard';\nexport {\n  default as useSwitchInlineQuery,\n  SwitchInlineQueryFunction,\n} from './useSwitchInlineQuery';\nexport { default as useExpand } from './useExpand';\nexport {\n  default as useCloudStorage,\n  GetKeysFunction,\n  GetItemFunction,\n  GetItemsFunction,\n  RemoveItemFunction,\n  SetItemFunction,\n  RemoveItemsFunction,\n} from './useCloudStorage';\nexport {\n  default as WebAppProvider,\n  WebAppProviderProps,\n} from './WebAppProvider';\nexport {\n  default as useInitData,\n  WebAppChat,\n  WebAppUser,\n  InitData,\n  InitDataUnsafe,\n} from './useInitData';\nexport type { Options } from './core';\nexport { default as useWebApp } from './useWebApp';\n"
  },
  {
    "path": "src/useCloudStorage.ts",
    "content": "import { useWebApp } from './core';\nimport { useCallback, useMemo } from 'react';\n\n/**\n * This function provides `getItem` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type GetItemFunction = (key: string) => Promise<string>;\n\n/**\n * This function provides `setItem` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type SetItemFunction = (key: string, value: string) => Promise<void>;\n\n/**\n * This function provides `getItems` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type GetItemsFunction = (keys: string[]) => Promise<string[]>;\n\n/**\n * This function provides `removeItem` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type RemoveItemFunction = (key: string) => Promise<void>;\n\n/**\n * This function provides `removeItems` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type RemoveItemsFunction = (key: string[]) => Promise<void>;\n\n/**\n * This function provides `getKeys` method from {@link telegram!CloudStorage} as Promise\n * @throws\n */\nexport type GetKeysFunction = () => Promise<string[]>;\n\n/**\n * This hook provides {@link telegram!CloudStorage} object with promises functions,\n * so you don't have to pass `callback` argument\n * You have to look original description CloudStorage object in {@link telegram!CloudStorage}\n * @group Hooks\n */\nconst useCloudStorage = (): {\n  getItem: GetItemFunction;\n  setItem: SetItemFunction;\n  getItems: GetItemsFunction;\n  removeItem: RemoveItemFunction;\n  getKeys: GetKeysFunction;\n} => {\n  const cloudStorage = useWebApp()?.CloudStorage;\n\n  const getItem: GetItemFunction = useCallback(\n    key =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.getItem(key, (error, value) => {\n          if (!error) {\n            resolve(value);\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n  const setItem: SetItemFunction = useCallback(\n    (key, value) =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.setItem(key, value, (error, state) => {\n          if (!error && state) {\n            resolve();\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n  const getItems: GetItemsFunction = useCallback(\n    key =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.getItems(key, (error, value) => {\n          if (!error && value) {\n            resolve(value);\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n  const removeItem: RemoveItemFunction = useCallback(\n    key =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.removeItem(key, (error, state) => {\n          if (!error && state) {\n            resolve();\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n  const removeItems: RemoveItemsFunction = useCallback(\n    key =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.removeItems(key, (error, state) => {\n          if (!error && state) {\n            resolve();\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n  const getKeys: GetKeysFunction = useCallback(\n    () =>\n      new Promise((resolve, reject) => {\n        cloudStorage?.getKeys((error, state) => {\n          if (!error && state) {\n            resolve(state);\n          } else {\n            reject(error);\n          }\n        });\n      }),\n    [cloudStorage],\n  );\n\n  return useMemo(\n    () => ({\n      getItem,\n      setItem,\n      getItems,\n      removeItem,\n      removeItems,\n      getKeys,\n    }),\n    // Осознанно в зависимостях только cloudStorage\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [cloudStorage],\n  );\n};\n\nexport default useCloudStorage;\n"
  },
  {
    "path": "src/useExpand.ts",
    "content": "import { DispatchWithoutAction, useCallback, useEffect, useState } from 'react';\nimport { useWebApp } from './core';\n\n/**\n * This hook provided isExpanded state, and expand() handle\n * You have to look original description in {@link telegram!WebApp} for more information\n *\n * `isExpanded` can be `undefined`\n *\n * ```tsx\n * import { useExpand } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const [isExpanded, expand] = useExpand();\n * const handleClick = () => !isExpanded && expand();\n *\n * <button onClick={handleClick}>\n *     {showTextWhenScreenExpanded && 'expanded' : 'to expand'}\n * </button>\n * ```\n *\n * @privateRemarks\n * Api doesn't provide event for listening isExpanded, so we use\n * viewportChanged, but it is an unsafe way\n *\n * @group Hooks\n */\nconst useExpand = (): readonly [boolean | undefined, DispatchWithoutAction] => {\n  const WebApp = useWebApp();\n  const [isExpanded, setIsExpanded] = useState(WebApp?.isExpanded);\n\n  useEffect(() => {\n    if (!WebApp) return;\n    const handleEvent = (payload: { isStateStable: boolean }) => {\n      if (payload.isStateStable) {\n        setIsExpanded(WebApp.isExpanded);\n      }\n    };\n\n    WebApp.onEvent('viewportChanged', handleEvent);\n    return () => WebApp.offEvent('viewportChanged', handleEvent);\n  }, [WebApp]);\n\n  const handleExpand = useCallback(() => WebApp?.expand?.(), [WebApp]);\n\n  return [isExpanded, handleExpand] as const;\n};\n\nexport default useExpand;\n"
  },
  {
    "path": "src/useHapticFeedback.ts",
    "content": "import { useWebApp } from './core';\nimport { useCallback } from 'react';\n\n/**\n * A method tells that an impact occurred. The Telegram app may play the appropriate haptics based on style value passed. Style can be one of these values:\n * - light, indicates a collision between small or lightweight UI objects,\n * - medium, indicates a collision between medium-sized or medium-weight UI objects,\n * - heavy, indicates a collision between large or heavyweight UI objects,\n * - rigid, indicates a collision between hard or inflexible UI objects,\n * - soft, indicates a collision between soft or flexible UI objects.\n * {@link telegram!HapticFeedback}\n */\nexport type ImpactOccurredFunction = (\n  style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft',\n) => void;\n\n/**\n * A method tells that a task or action has succeeded, failed, or produced a warning. The Telegram app may play the appropriate haptics based on type value passed. Type can be one of these values:\n * - error, indicates that a task or action has failed,\n * - success, indicates that a task or action has completed successfully,\n * - warning, indicates that a task or action produced a warning.\n * {@link telegram!HapticFeedback}\n */\nexport type NotificationOccurredFunction = (\n  type: 'error' | 'success' | 'warning',\n) => void;\n\n/**\n * A method tells that the user has changed a selection. The Telegram app may play the appropriate haptics.\n * {@link telegram!HapticFeedback}\n */\nexport type SelectionChangedFunction = () => void;\n\n/**\n * This hook that provided {@link ImpactOccurredFunction}, {@link NotificationOccurredFunction} and {@link SelectionChangedFunction} functions that controls haptic feedback.\n * You have to look original telegram description {@link telegram!HapticFeedback}, because it Hook implementing his.\n *\n * ```tsx\n * import { useHapticFeedback } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const [impactOccurred, notificationOccurred, selectionChanged] =\n *     useHapticFeedback();\n * // const [,notificationOccurred] = useHapticFeedback();\n *\n * impactOccurred('heavy');\n * notificationOccurred('success');\n * ```\n *\n * @group Hooks\n */\nconst useHapticFeedback = (): readonly [\n  ImpactOccurredFunction,\n  NotificationOccurredFunction,\n  SelectionChangedFunction,\n] => {\n  const WebApp = useWebApp();\n  const HapticFeedback = WebApp?.HapticFeedback;\n\n  const impactOccurred: ImpactOccurredFunction = useCallback(\n    (...args) => HapticFeedback?.impactOccurred(...args),\n    [HapticFeedback],\n  );\n  const notificationOccurred: NotificationOccurredFunction = useCallback(\n    (...args) => HapticFeedback?.notificationOccurred(...args),\n    [HapticFeedback],\n  );\n  const selectionChanged: SelectionChangedFunction = useCallback(\n    (...args) => HapticFeedback?.selectionChanged(...args),\n    [HapticFeedback],\n  );\n\n  return [impactOccurred, notificationOccurred, selectionChanged] as const;\n};\n\nexport default useHapticFeedback;\n"
  },
  {
    "path": "src/useInitData.ts",
    "content": "import { useWebApp } from './core';\n\n/**\n * {@link telegram!WebAppChat}\n */\nexport type WebAppChat = {\n  id: number;\n  type: 'group' | 'supergroup' | 'channel';\n  title: string;\n  username?: string;\n  photo_url?: string;\n};\n\n/**\n * {@link telegram!WebAppUser}\n */\nexport type WebAppUser = {\n  id: number;\n  is_bot?: boolean;\n  first_name: string;\n  last_name?: string;\n  username?: string;\n  language_code?: string;\n  photo_url?: string;\n  is_premium?: boolean;\n  added_to_attachment_menu?: true;\n  allows_write_to_pm?: true;\n};\n\nexport type InitData = string;\n\n/**\n * {@link telegram!WebAppInitData}\n */\nexport type InitDataUnsafe = {\n  query_id?: string;\n  user?: WebAppUser;\n  receiver?: WebAppUser;\n  chat_type?: 'sender' | 'private' | 'group' | 'supergroup' | 'channel';\n  chat_instance?: string;\n  start_param?: string;\n  auth_date: number;\n  hash: string;\n  chat?: WebAppChat;\n  can_send_after?: number;\n};\n\n/**\n * This hook provides `initDataUnsafe` and `initData`\n * You have to look original description in {@link telegram!WebApp}, because hook just return this.\n *\n * ```tsx\n * import { useInitData } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const [initDataUnsafe] = useInitData();\n * const [initDataUnsafe, initData] = useInitData();\n *\n * ```\n * @group Hooks\n */\nconst useInitData = (): readonly [\n  InitDataUnsafe | undefined,\n  InitData | undefined,\n] => {\n  const WebApp = useWebApp();\n\n  return [WebApp?.initDataUnsafe, WebApp?.initData] as const;\n};\n\nexport default useInitData;\n"
  },
  {
    "path": "src/useReadTextFromClipboard.ts",
    "content": "import { useCallback } from 'react';\nimport { useWebApp } from './core';\n\n/**\n * This function provided Promise function that read text from clipboard\n * @return {Promise<string>}\n */\nexport type ReadTextFromClipboardFunction = () => Promise<string>;\n\n/**\n * This hook that provided {@link ReadTextFromClipboardFunction} Promise function that read text from clipboard.\n * You have to look original description readTextFromClipboard in {@link telegram!WebApp}, because hook just implements his.\n *\n * ```tsx\n * import { useReadTextFromClipboard } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const readText = useReadTextFromClipboard();\n *\n * readText().then(console.log);\n * // or\n * await readText()\n * ```\n *\n * @return {ReadTextFromClipboardFunction}\n * @group Hooks\n */\nconst useReadTextFromClipboard = (): ReadTextFromClipboardFunction => {\n  const WebApp = useWebApp();\n\n  return useCallback(\n    () =>\n      new Promise(resolve => {\n        WebApp?.readTextFromClipboard?.(resolve);\n      }),\n    [WebApp],\n  );\n};\n\nexport default useReadTextFromClipboard;\n"
  },
  {
    "path": "src/useScanQrPopup.ts",
    "content": "import { useWebApp } from './core';\nimport { useCallback } from 'react';\n\n/**\n * If an optional callback parameter was passed, the callback function will be called and the text from the QR\n * code will be passed as the first argument.\n * Returning true inside this callback function causes the popup to be closed.\n */\nexport type ScanQrPopupCallback = (text: string) => true | void;\n\n/**\n * This object describes the native popup for scanning QR codes.\n * You have to see original interface {@link telegram!ScanQrPopupParams}.\n */\nexport interface ScanQrPopupParams {\n  /**\n   * The text to be displayed under the 'Scan QR' heading, 0-64 characters.\n   */\n  text: string;\n}\n\n/**\n * A method that shows a native popup for scanning a QR code described\n * by the params argument of the type {@link ScanQrPopupParams}.\n */\nexport type ShowScanQrPopupFunction = (\n  params: ScanQrPopupParams,\n  callback?: ScanQrPopupCallback,\n) => void;\n\n/**\n * A method that closes the native popup for scanning a QR code opened with the showScanQrPopup method\n */\nexport type CloseScanQrPopupFunction = () => void;\n\n/**\n * The hook provided showScanQrPopup function of the type {@link ShowScanQrPopupFunction} and closeScanQrPopup {@link CloseScanQrPopupFunction}.\n * @group Hooks\n */\nconst useScanQrPopup = (): readonly [\n  ShowScanQrPopupFunction,\n  CloseScanQrPopupFunction,\n] => {\n  const WebApp = useWebApp();\n\n  const showScanQrPopup: ShowScanQrPopupFunction = useCallback(\n    (...args) => WebApp?.showScanQrPopup?.(...args),\n    [WebApp],\n  );\n  const closeScanQrPopup: CloseScanQrPopupFunction = useCallback(\n    () => WebApp?.closeScanQrPopup?.(),\n    [WebApp],\n  );\n\n  return [showScanQrPopup, closeScanQrPopup] as const;\n};\n\nexport default useScanQrPopup;\n"
  },
  {
    "path": "src/useShowPopup.ts",
    "content": "import { useCallback } from 'react';\nimport { useWebApp } from './core';\n\n/**\n * You have to see original interface {@link telegram!PopupButton}.\n */\nexport interface ShowPopupButton extends Record<string, unknown> {\n  /**\n   * Optional. Identifier of the button, 0-64 characters.\n   * Set to empty string by default.\n   * If the button is pressed, its id is returned in the callback and the popupClosed event.\n   */\n  id?: string;\n  /**\n   * Optional. Type of the button.\n   * Set to default by default.\n   */\n  type?: 'default' | 'ok' | 'close' | 'cancel' | 'destructive' | string;\n  /**\n   * Optional. The text to be displayed on the button, 0-64 characters.\n   * Required if type is default or destructive.\n   * Irrelevant for other types.\n   */\n  text?: string;\n}\n\n/**\n * You have to see original interface {@link telegram!PopupParams}.\n */\nexport interface ShowPopupParams extends Record<string, unknown> {\n  /**\n   * Optional. The text to be displayed in the popup title, 0-64 characters.\n   */\n  title?: string;\n  /**\n   * The message to be displayed in the body of the popup, 1-256 characters.\n   */\n  message: string;\n  /**\n   * Optional. List of buttons to be displayed in the popup, 1-3 buttons\n   */\n  buttons?: ShowPopupButton[];\n}\n\n/**\n * This function provides Promise, and resolve the field id of the pressed button will be passed.\n * @return Button id as string, it was described by {@link ShowPopupButton}\n * @throws\n */\nexport type ShowPopupFunction = (params: ShowPopupParams) => Promise<string>;\n\n/**\n * The hook provided showPopup function of the type {@link ShowPopupFunction}.\n * The function that shows a native popup described by the params argument of the type {@link ShowPopupParams}.\n *\n * ```tsx\n * import { useShowPopup } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const showPopup = useShowPopup();\n *\n * showPopup({ message: 'Hello world' }).then((buttonId) => console.log(buttonId));\n * ```\n *\n * @group Hooks\n */\nconst useShowPopup: () => ShowPopupFunction = () => {\n  const WebApp = useWebApp();\n\n  return useCallback(\n    params =>\n      new Promise((resolve, reject) => {\n        try {\n          WebApp?.showPopup?.(params, (buttonId: string) => {\n            resolve(buttonId);\n          });\n        } catch (e) {\n          reject(e);\n        }\n      }),\n    [WebApp],\n  );\n};\n\nexport default useShowPopup;\n"
  },
  {
    "path": "src/useSwitchInlineQuery.ts",
    "content": "import { useWebApp } from './core';\nimport { useCallback } from 'react';\n\n/**\n * This function that inserts the bot's username and the specified inline query in the current chat's input field\n * You have to look original description switchInlineQuery in {@link telegram!WebApp} for more information\n */\nexport type SwitchInlineQueryFunction = (\n  query: string,\n  chatType?: ('users' | 'bots' | 'groups' | 'channels')[],\n) => void;\n\n/**\n * This hook that provided {@link SwitchInlineQueryFunction}\n * You have to look original description switchInlineQuery in {@link telegram!WebApp}, because hook just implements his.\n * @return {SwitchInlineQueryFunction}\n * @group Hooks\n */\nconst useSwitchInlineQuery = (): SwitchInlineQueryFunction => {\n  const WebApp = useWebApp();\n\n  return useCallback(\n    (...args) => WebApp?.switchInlineQuery?.(...args),\n    [WebApp],\n  );\n};\n\nexport default useSwitchInlineQuery;\n"
  },
  {
    "path": "src/useThemeParams.ts",
    "content": "import { useEffect, useState } from 'react';\nimport { useWebApp } from './core';\n\n/**\n * This object contains the user's current theme settings.\n * This object implement original Telegram WebApp type of {@link telegram!ThemeParams}\n */\nexport interface ThemeParams {\n  /**\n   * Background color in the #RRGGBB format.\n   */\n  bg_color?: string;\n  /**\n   * Main text color in the #RRGGBB format.\n   */\n  text_color?: string;\n  /**\n   * Hint text color in the #RRGGBB format.\n   */\n  hint_color?: string;\n  /**\n   * Link color in the #RRGGBB format.\n   */\n  link_color?: string;\n  /**\n   * Button color in the #RRGGBB format.\n   */\n  button_color?: string;\n  /**\n   * Button text color in the #RRGGBB format.\n   */\n  button_text_color?: string;\n  /**\n   * Secondary background color in the #RRGGBB format.\n   */\n  secondary_bg_color?: string;\n}\n\n/**\n * The color scheme currently used in the Telegram app. Either “light” or “dark”.\n * Can `undefined`, if `window` is undefined.\n */\nexport type ColorScheme = 'light' | 'dark' | undefined;\n\n/**\n * The hook provided colorScheme and themeParams values of the type {@link ColorScheme} and {@link ThemeParams}.\n *\n * ```tsx\n * import { useThemeParams } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const [colorScheme, themeParams] = useThemeParams();\n *\n * console.log(colorScheme === 'dark');\n * console.log({\n *     text_color: themeParams.text_color,\n *     button_color: themeParams.button_color,\n *     bg_color: themeParams.bg_color,\n * });\n * ```\n * @group Hooks\n */\nconst useThemeParams: () => readonly [ColorScheme, ThemeParams] = () => {\n  const WebApp = useWebApp();\n  const [colorScheme, setColor] = useState<ColorScheme>(WebApp?.colorScheme);\n  const [themeParams, setThemeParams] = useState<ThemeParams>(\n    WebApp?.themeParams || {},\n  );\n\n  useEffect(() => {\n    if (!WebApp) return;\n    const eventHandler = () => {\n      setColor(WebApp.colorScheme);\n      setThemeParams(WebApp.themeParams);\n    };\n\n    WebApp.onEvent('themeChanged', eventHandler);\n    return () => {\n      WebApp.offEvent('themeChanged', eventHandler);\n    };\n  }, [WebApp]);\n\n  return [colorScheme, themeParams] as const;\n};\n\nexport default useThemeParams;\n"
  },
  {
    "path": "src/useWebApp.ts",
    "content": "import { useWebApp as _useWebApp } from './core';\n\n/**\n * This hook just provides native {@link telegram!WebApp} object\n *\n * ```tsx\n * import { useWebApp } from \"@vkruglikov/react-telegram-web-app\";\n *\n * const WebApp = useWebApp();\n *\n * console.log(WebApp.version);\n * ```\n * @group Hooks\n */\nconst useWebApp = () => _useWebApp() as any;\n\nexport default useWebApp;\n"
  },
  {
    "path": "tests/BackButton.test.tsx",
    "content": "import * as React from 'react';\n\nimport BackButton from '../src/BackButton';\nimport { useWebApp } from '../src/core';\nimport { renderComponentTree } from './utils';\n\ndescribe('BackButton', () => {\n  it('checks call show(), hide() WebApp.BackButton api', () => {\n    const WebApp = useWebApp();\n\n    renderComponentTree(() => <BackButton />);\n\n    expect(WebApp?.BackButton?.show).toBeCalledTimes(1);\n    expect(WebApp?.BackButton?.hide).toBeCalledTimes(1);\n  });\n\n  it('checks correct bind cached onClick', () => {\n    const WebApp = useWebApp();\n    const handleClick = jest.fn();\n\n    renderComponentTree(() => <BackButton onClick={handleClick} />);\n\n    expect(WebApp?.BackButton?.onClick).toBeCalledTimes(1);\n    expect(WebApp?.BackButton?.offClick).toBeCalledTimes(1);\n\n    expect(WebApp?.BackButton?.onClick).toBeCalledWith(handleClick);\n    expect(WebApp?.BackButton?.offClick).toBeCalledWith(handleClick);\n  });\n\n  it('checks correct bind uncached onClick', () => {\n    const WebApp = useWebApp();\n\n    renderComponentTree(() => <BackButton onClick={jest.fn()} />);\n\n    expect(WebApp?.BackButton?.onClick).toBeCalledTimes(3);\n    expect(WebApp?.BackButton?.offClick).toBeCalledTimes(3);\n  });\n});\n"
  },
  {
    "path": "tests/MainButton.test.tsx",
    "content": "import * as React from 'react';\n\nimport MainButton from '../src/MainButton';\nimport { useWebApp } from '../src/core';\nimport { renderComponentTree } from './utils';\n\ndescribe('MainButton', () => {\n  it('checks call show(), hide() WebApp.MainButton api', () => {\n    const WebApp = useWebApp();\n\n    renderComponentTree(() => <MainButton />);\n\n    expect(WebApp?.MainButton.show).toBeCalledTimes(1);\n    expect(WebApp?.MainButton.hide).toBeCalledTimes(1);\n  });\n\n  it('checks correct bind cached onClick', () => {\n    const WebApp = useWebApp();\n    const handleClick = jest.fn();\n\n    renderComponentTree(() => <MainButton onClick={handleClick} />);\n\n    expect(WebApp?.MainButton.onClick).toBeCalledTimes(1);\n    expect(WebApp?.MainButton.offClick).toBeCalledTimes(1);\n\n    expect(WebApp?.MainButton.onClick).toBeCalledWith(handleClick);\n    expect(WebApp?.MainButton.offClick).toBeCalledWith(handleClick);\n  });\n\n  it('checks correct bind uncached onClick', () => {\n    const WebApp = useWebApp();\n\n    renderComponentTree(() => <MainButton onClick={jest.fn()} />);\n\n    expect(WebApp?.MainButton.onClick).toBeCalledTimes(3);\n    expect(WebApp?.MainButton.offClick).toBeCalledTimes(3);\n  });\n\n  it('checks call showProgress(), hideProgress() WebApp.MainButton api', () => {\n    const WebApp = useWebApp();\n    const updates = [\n      <MainButton progress />,\n      <MainButton />,\n      <MainButton progress />,\n    ];\n\n    renderComponentTree(() => updates.shift() || <MainButton progress />);\n\n    expect(WebApp?.MainButton.showProgress).toBeCalledTimes(2);\n    expect(WebApp?.MainButton.hideProgress).toBeCalledTimes(1);\n  });\n\n  it('checks call disable(), enable() WebApp.MainButton api', () => {\n    const WebApp = useWebApp();\n    const updates = [\n      <MainButton disable />,\n      <MainButton />,\n      <MainButton disable />,\n    ];\n\n    renderComponentTree(() => updates.shift() || <MainButton disable />);\n\n    expect(WebApp?.MainButton.disable).toBeCalledTimes(2);\n    expect(WebApp?.MainButton.enable).toBeCalledTimes(1);\n  });\n\n  it('checks call setText() WebApp.MainButton api', () => {\n    const WebApp = useWebApp();\n    const updates = [\n      <MainButton text=\"Hello\" />,\n      <MainButton />,\n      <MainButton text=\"My friend\" />,\n    ];\n\n    renderComponentTree(() => updates.shift() || <MainButton />);\n\n    expect((WebApp?.MainButton.setText as jest.Mock).mock.calls).toEqual([\n      ['Hello'],\n      ['CONTINUE'],\n      ['My friend'],\n    ]);\n  });\n\n  it('checks textColor props', () => {\n    const WebApp = useWebApp();\n    const updates = [\n      <MainButton textColor=\"#fff\" />,\n      <MainButton />,\n      <MainButton textColor=\"#0f0\" />,\n    ];\n\n    renderComponentTree(() => updates.shift() || <MainButton />);\n\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        text_color: '#fff',\n      }),\n    );\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        text_color: '#000',\n      }),\n    );\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        text_color: '#0f0',\n      }),\n    );\n  });\n\n  it('checks color props', () => {\n    const WebApp = useWebApp();\n    const updates = [\n      <MainButton color=\"#f0f\" />,\n      <MainButton />,\n      <MainButton color=\"#0f0\" />,\n    ];\n\n    renderComponentTree(() => updates.shift() || <MainButton />);\n\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        color: '#f0f',\n      }),\n    );\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        color: '#fff',\n      }),\n    );\n    expect(WebApp?.MainButton.setParams).toBeCalledWith(\n      expect.objectContaining({\n        color: '#0f0',\n      }),\n    );\n  });\n});\n"
  },
  {
    "path": "tests/__snapshots__/package.test.ts.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Package /lib should have correct /lib structure 1`] = `\n[\n  \"/BackButton.d.ts\",\n  \"/MainButton.d.ts\",\n  \"/SettingsButton.d.ts\",\n  \"/WebAppProvider.d.ts\",\n  [\n    \"/core/context.d.ts\",\n    \"/core/index.d.ts\",\n    [\n      \"/core/twa-types/WebApp.d.ts\",\n      \"/core/twa-types/WebAppVersion_6.1.d.ts\",\n      \"/core/twa-types/WebAppVersion_6.2.d.ts\",\n      \"/core/twa-types/WebAppVersion_6.4.d.ts\",\n      \"/core/twa-types/WebAppVersion_6.7.d.ts\",\n      \"/core/twa-types/WebAppVersion_6.9.d.ts\",\n      \"/core/twa-types/WebAppVersion_7.0.d.ts\",\n      \"/core/twa-types/index.d.ts\",\n    ],\n    \"/core/useAsyncMode.d.ts\",\n    \"/core/useSmoothButtonsTransition.d.ts\",\n    \"/core/useWebApp.d.ts\",\n  ],\n  \"/index.d.ts\",\n  \"/react-telegram-web-app.cjs\",\n  \"/react-telegram-web-app.modern.js\",\n  \"/react-telegram-web-app.module.js\",\n  \"/react-telegram-web-app.umd.js\",\n  \"/useCloudStorage.d.ts\",\n  \"/useExpand.d.ts\",\n  \"/useHapticFeedback.d.ts\",\n  \"/useInitData.d.ts\",\n  \"/useReadTextFromClipboard.d.ts\",\n  \"/useScanQrPopup.d.ts\",\n  \"/useShowPopup.d.ts\",\n  \"/useSwitchInlineQuery.d.ts\",\n  \"/useThemeParams.d.ts\",\n  \"/useWebApp.d.ts\",\n]\n`;\n\nexports[`Package /lib should have exports from modules 1`] = `\n{\n  \"BackButton\": [Function],\n  \"MainButton\": [Function],\n  \"SettingsButton\": [Function],\n  \"WebAppProvider\": [Function],\n  \"useCloudStorage\": [Function],\n  \"useExpand\": [Function],\n  \"useHapticFeedback\": [Function],\n  \"useInitData\": [Function],\n  \"useReadTextFromClipboard\": [Function],\n  \"useScanQrPopup\": [Function],\n  \"useShowPopup\": [Function],\n  \"useSwitchInlineQuery\": [Function],\n  \"useThemeParams\": [Function],\n  \"useWebApp\": [Function],\n}\n`;\n"
  },
  {
    "path": "tests/core/__mocks__/useWebApp.ts",
    "content": "const instance = {\n  BackButton: {\n    show: jest.fn(),\n    hide: jest.fn(),\n    onClick: jest.fn(),\n    offClick: jest.fn(),\n  },\n  MainButton: {\n    show: jest.fn(),\n    hide: jest.fn(),\n    setParams: jest.fn(),\n    setText: jest.fn(),\n    disable: jest.fn(),\n    enable: jest.fn(),\n    onClick: jest.fn(),\n    offClick: jest.fn(),\n    showProgress: jest.fn(),\n    hideProgress: jest.fn(),\n  },\n  HapticFeedback: {\n    impactOccurred: jest.fn(),\n    selectionChanged: jest.fn(),\n    notificationOccurred: jest.fn(),\n  },\n  themeParams: {},\n  onEvent: jest.fn(),\n  offEvent: jest.fn(),\n  isExpanded: undefined,\n  expand: jest.fn(),\n  readTextFromClipboard: jest.fn(),\n  showScanQrPopup: jest.fn(),\n  closeScanQrPopup: jest.fn(),\n  showPopup: jest.fn(),\n  switchInlineQuery: jest.fn(),\n  colorScheme: undefined,\n};\n\nexport default () => instance;\n"
  },
  {
    "path": "tests/core/useSmoothButtonsTransition.test.ts",
    "content": "import { useSmoothButtonsTransition } from '../../src/core';\nimport { act, renderHook } from '@testing-library/react';\n\ndescribe('useSmoothButtonsTransition', () => {\n  afterEach(() => {\n    jest.useRealTimers();\n  });\n\n  it.each([\n    [{ smoothButtonsTransition: false, smoothButtonsTransitionMs: undefined }],\n    [{ smoothButtonsTransition: true, smoothButtonsTransitionMs: 50 }],\n    [{ smoothButtonsTransition: true, smoothButtonsTransitionMs: 100 }],\n    [{ smoothButtonsTransition: false, smoothButtonsTransitionMs: 100 }],\n    [{ smoothButtonsTransition: undefined, smoothButtonsTransitionMs: 100 }],\n  ])(\n    'checks correct call show(),hide() with options %p',\n    ({ smoothButtonsTransition, smoothButtonsTransitionMs }) => {\n      jest.spyOn(require('react'), 'useContext').mockImplementation(() => ({\n        smoothButtonsTransition,\n        smoothButtonsTransitionMs,\n      }));\n\n      const setTimeoutSpy = jest\n        .spyOn(global, 'setTimeout')\n        .mockImplementation(handler => {\n          handler();\n          return undefined as unknown as ReturnType<typeof setTimeout>;\n        });\n\n      const initialProps = {\n        show: jest.fn(),\n        hide: jest.fn(),\n        currentShowedIdRef: {\n          current: null,\n        },\n        id: 'idButton',\n      };\n\n      const { rerender, unmount } = renderHook(useSmoothButtonsTransition, {\n        initialProps,\n      });\n      expect(initialProps.show).toBeCalledTimes(1);\n      expect(initialProps.hide).toBeCalledTimes(0);\n\n      expect(initialProps.currentShowedIdRef.current).toBe('idButton');\n\n      act(() => {\n        rerender(initialProps);\n      });\n      expect(initialProps.currentShowedIdRef.current).toBe('idButton');\n\n      act(() => {\n        rerender(initialProps);\n      });\n      unmount();\n      expect(initialProps.currentShowedIdRef.current).toBe(null);\n\n      expect(initialProps.show).toBeCalledTimes(1);\n      expect(initialProps.hide).toBeCalledTimes(1);\n\n      expect(setTimeoutSpy).toBeCalledTimes(smoothButtonsTransition ? 1 : 0);\n      if (smoothButtonsTransition) {\n        expect(setTimeoutSpy).toBeCalledWith(\n          expect.any(Function),\n          smoothButtonsTransitionMs,\n        );\n      }\n    },\n  );\n});\n"
  },
  {
    "path": "tests/package.test.ts",
    "content": "import * as fsAsync from 'fs/promises';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nconst BUILD_PATH = path.resolve(__dirname, '../lib');\nconst COMMON_JS_MODULE = 'react-telegram-web-app.cjs';\n\nconst walk = async (dirPath: string): Promise<any> =>\n  Promise.all(\n    await fsAsync.readdir(dirPath, { withFileTypes: true }).then(entries =>\n      entries.map(entry => {\n        const childPath = path.join(dirPath, entry.name);\n        return entry.isDirectory()\n          ? walk(childPath)\n          : childPath.replace(BUILD_PATH, '');\n      }),\n    ),\n  );\n\ndescribe('Package /lib', () => {\n  beforeEach(() => {\n    jest.resetModules();\n  });\n\n  it('should have correct /lib structure', async () => {\n    expect(await walk(BUILD_PATH)).toMatchSnapshot();\n  });\n\n  it('should have exports from modules', () => {\n    const indexModule = require(path.join(BUILD_PATH, COMMON_JS_MODULE));\n\n    expect(indexModule).toMatchSnapshot();\n  });\n});\n\ndescribe('Public API documentation', () => {\n  it('should have describe in README.md', () => {\n    const indexModule = Object.keys(\n      require(path.join(BUILD_PATH, COMMON_JS_MODULE)),\n    );\n\n    const mdFile = fs.readFileSync(\n      path.resolve(__dirname, '../README.md'),\n      'utf8',\n    );\n\n    expect(\n      indexModule\n        .map(name => `[${name}](./docs/README.md#${name.toLowerCase()})`)\n        .filter(name => !mdFile.includes(name)),\n    ).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "tests/setupTests.ts",
    "content": "jest.mock(\n  '../src/core/useWebApp',\n  () => require('./core/__mocks__/useWebApp').default,\n);\n\nglobal.beforeEach(() => {\n  jest.clearAllMocks();\n  jest.restoreAllMocks();\n});\n"
  },
  {
    "path": "tests/useCloudStorage.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\nimport useCloudStorage from '../src/useCloudStorage';\n\n// TODO Написать юниты на хук\ndescribe('useCloudStorage', () => {\n  it('TODO', () => {\n    renderHook(useCloudStorage);\n  });\n});\n"
  },
  {
    "path": "tests/useExpand.test.tsx",
    "content": "import { act, renderHook } from '@testing-library/react';\n\nimport { useWebApp } from '../src/core';\nimport { WebApp } from '../src/core/twa-types';\nimport useExpand from '../src/useExpand';\n\ndescribe('useExpand', () => {\n  it.each([\n    [true, true],\n    [false, false],\n    [undefined, undefined],\n  ])(\n    'checks WebApp.isExpanded = %p hook return isExpanded default value = %p',\n    (isExpanded, expectedIsExpanded) => {\n      jest.replaceProperty(\n        useWebApp() as WebApp,\n        'isExpanded',\n        isExpanded as boolean,\n      );\n\n      const { result } = renderHook(useExpand);\n\n      act(() => {\n        expect(result.current[0]).toBe(expectedIsExpanded);\n      });\n    },\n  );\n\n  /**\n   * TODO перенести тест перебинда в тест useWebApp\n   */\n  it('checks correct rebind event handler', () => {\n    const { rerender, unmount } = renderHook(useExpand);\n\n    act(() => {\n      rerender();\n    });\n\n    /**\n     * After one rerender, should be called onEvent once\n     */\n    expect(useWebApp()?.onEvent).toBeCalledTimes(1);\n    expect(useWebApp()?.offEvent).toBeCalledTimes(0);\n    expect(useWebApp()?.onEvent).toBeCalledWith(\n      'viewportChanged',\n      expect.any(Function),\n    );\n\n    (useWebApp()?.onEvent as jest.Mock).mockClear();\n\n    act(() => {\n      rerender();\n    });\n    expect(useWebApp()?.onEvent).toBeCalledTimes(0);\n    expect(useWebApp()?.offEvent).toBeCalledTimes(0);\n    (useWebApp()?.offEvent as jest.Mock).mockClear();\n\n    act(() => {\n      unmount();\n    });\n\n    expect(useWebApp()?.onEvent).toBeCalledTimes(0);\n    expect(useWebApp()?.offEvent).toBeCalledTimes(1);\n\n    expect(useWebApp()?.offEvent).toBeCalledWith(\n      'viewportChanged',\n      expect.any(Function),\n    );\n  });\n\n  it('checks correct change state isExpanded', () => {\n    jest.replaceProperty(useWebApp() as WebApp, 'isExpanded', true);\n    const fireEventHandler = (state: boolean) => {\n      jest.replaceProperty(useWebApp() as WebApp, 'isExpanded', state);\n\n      act(() => {\n        (useWebApp()?.onEvent as jest.Mock).mock.lastCall?.[1]?.({\n          isStateStable: true,\n        });\n        rerender();\n      });\n    };\n\n    const { result, rerender } = renderHook(useExpand);\n\n    act(() => {\n      expect(result.current[0]).toBe(true);\n    });\n\n    fireEventHandler(false);\n    expect(result.current[0]).toBe(false);\n\n    fireEventHandler(true);\n    expect(result.current[0]).toBe(true);\n  });\n\n  it('checks correct call WebApp.expand() from hook', () => {\n    const { result } = renderHook(useExpand);\n\n    act(() => {\n      result.current[1]();\n    });\n\n    expect(useWebApp()?.expand as jest.Mock).toBeCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "tests/useHapticFeedback.test.ts",
    "content": "import { act, renderHook } from '@testing-library/react';\nimport useHapticFeedback from '../src/useHapticFeedback';\nimport { useWebApp } from '../src/core';\n\ndescribe('useHapticFeedback', () => {\n  it('checks correct call WebApp.HapticFeedback api', () => {\n    const { result } = renderHook(useHapticFeedback);\n    const [impactOccurred, notificationOccurred, selectionChanged] =\n      result.current;\n\n    act(() => {\n      impactOccurred('soft');\n      notificationOccurred('warning');\n      selectionChanged();\n    });\n\n    expect(useWebApp()?.HapticFeedback?.impactOccurred).toBeCalledTimes(1);\n    expect(useWebApp()?.HapticFeedback?.impactOccurred).toBeCalledWith('soft');\n\n    expect(useWebApp()?.HapticFeedback?.notificationOccurred).toBeCalledTimes(\n      1,\n    );\n    expect(useWebApp()?.HapticFeedback?.notificationOccurred).toBeCalledWith(\n      'warning',\n    );\n\n    expect(useWebApp()?.HapticFeedback?.selectionChanged).toBeCalledTimes(1);\n    expect(useWebApp()?.HapticFeedback?.selectionChanged).toBeCalledWith();\n  });\n});\n"
  },
  {
    "path": "tests/useInitData.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\nimport useCloudStorage from '../src/useCloudStorage';\n\n// TODO Написать юниты на хук\ndescribe('useInitData', () => {\n  it('TODO', () => {\n    renderHook(useCloudStorage);\n  });\n});\n"
  },
  {
    "path": "tests/useReadTextFromClipboard.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\nimport useReadTextFromClipboard from '../src/useReadTextFromClipboard';\nimport { useWebApp } from '../src/core';\nimport { WebApp } from '../src/core/twa-types';\n\ndescribe('useReadTextFromClipboard', () => {\n  it('checks correct call WebApp.readTextFromClipboard api', async () => {\n    const { result } = renderHook(useReadTextFromClipboard);\n    const readTextFromClickBoard = result.current;\n\n    jest\n      .spyOn(useWebApp() as WebApp, 'readTextFromClipboard')\n      .mockImplementation(resolve => {\n        resolve!('TEST_CLICK');\n      });\n    const text = await readTextFromClickBoard();\n\n    expect(text).toBe('TEST_CLICK');\n  });\n});\n"
  },
  {
    "path": "tests/useScanQrPopup.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\nimport useScanQrPopup from '../src/useScanQrPopup';\nimport { useWebApp } from '../src/core';\n\ndescribe('useScanQrPopup', () => {\n  it('checks correct call WebApp.showScanQrPopup api', () => {\n    const { result } = renderHook(useScanQrPopup);\n    const [show] = result.current;\n\n    show({\n      text: 'Text under QR',\n    });\n\n    expect(useWebApp()?.showScanQrPopup).toBeCalledTimes(1);\n    expect(useWebApp()?.showScanQrPopup).toBeCalledWith({\n      text: 'Text under QR',\n    });\n  });\n\n  it('checks correct call WebApp.closeScanQrPopup api', () => {\n    const { result } = renderHook(useScanQrPopup);\n    const [_, close] = result.current;\n\n    close();\n\n    expect(useWebApp()?.closeScanQrPopup).toBeCalledTimes(1);\n    expect(useWebApp()?.closeScanQrPopup).toBeCalledWith();\n  });\n});\n"
  },
  {
    "path": "tests/useShowPopup.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\nimport useShowPopup from '../src/useShowPopup';\nimport { useWebApp } from '../src/core';\nimport { WebApp } from '../src/core/twa-types';\n\ndescribe('useShowPopup', () => {\n  it('checks correct call WebApp.showPopup api', async () => {\n    const { result } = renderHook(useShowPopup);\n    const showPopup = result.current;\n\n    const spyShowPopup = jest\n      .spyOn(useWebApp() as WebApp, 'showPopup')\n      .mockImplementation((_, callback) => {\n        callback!('buttonId');\n      });\n\n    const params = {\n      title: 'title',\n      message: 'message',\n      buttons: [\n        {\n          id: 'buttonId',\n          type: 'cancel',\n          text: 'textButton',\n        },\n      ],\n    };\n    const button = await showPopup(params);\n\n    expect(spyShowPopup).toBeCalledWith(params, expect.any(Function));\n    expect(button).toBe('buttonId');\n  });\n});\n"
  },
  {
    "path": "tests/useSwitchInlineQuery.test.ts",
    "content": "import { renderHook } from '@testing-library/react';\n\nimport { useWebApp } from '../src/core';\nimport useSwitchInlineQuery from '../src/useSwitchInlineQuery';\n\ndescribe('useSwitchInlineQuery', () => {\n  it('checks correct call WebApp.switchInlineQuery api', () => {\n    const { result } = renderHook(useSwitchInlineQuery);\n    const switchInlineQuery = result.current;\n\n    switchInlineQuery('Test string');\n    expect(useWebApp()!.switchInlineQuery).toBeCalledWith('Test string');\n\n    switchInlineQuery('Test string 2', ['groups']);\n    expect(useWebApp()!.switchInlineQuery).toBeCalledWith('Test string 2', [\n      'groups',\n    ]);\n\n    expect(useWebApp()!.switchInlineQuery).toBeCalledTimes(2);\n  });\n});\n"
  },
  {
    "path": "tests/useThemeParams.test.ts",
    "content": "import { act, renderHook } from '@testing-library/react';\n\nimport { useWebApp } from '../src/core';\nimport { WebApp } from '../src/core/twa-types';\nimport useThemeParams from '../src/useThemeParams';\n\ndescribe('useThemeParams', () => {\n  it('checks is correct initial value return', () => {\n    jest.replaceProperty(useWebApp() as WebApp, 'colorScheme', 'dark');\n    jest.replaceProperty(useWebApp() as WebApp, 'themeParams', {\n      bg_color: '#fff',\n    });\n\n    const { result } = renderHook(useThemeParams);\n    const [colorScheme, themeParams] = result.current;\n\n    expect(colorScheme).toBe('dark');\n    expect(themeParams).toEqual({\n      bg_color: '#fff',\n    });\n  });\n\n  it('checks correct return value after fire onEvent', function () {\n    let handleOnEvent = () => {};\n    jest\n      .spyOn(useWebApp() as WebApp, 'onEvent')\n      .mockImplementation((_, handler) => {\n        handleOnEvent = handler;\n      });\n\n    const { result } = renderHook(useThemeParams);\n    expect(result.current[0]).toBe(undefined);\n    expect(result.current[1]).toEqual({});\n\n    expect(useWebApp()?.onEvent).toBeCalledWith(\n      'themeChanged',\n      expect.any(Function),\n    );\n    expect(useWebApp()?.onEvent).toBeCalledTimes(1);\n\n    jest.replaceProperty(useWebApp() as WebApp, 'colorScheme', 'dark');\n    jest.replaceProperty(useWebApp() as WebApp, 'themeParams', {\n      bg_color: '#000',\n    });\n    act(() => {\n      handleOnEvent();\n    });\n\n    act(() => {\n      expect(result.current[0]).toBe('dark');\n      expect(result.current[1]).toEqual({\n        bg_color: '#000',\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "tests/utils.ts",
    "content": "import * as React from 'react';\nimport { ReactTestRenderer } from 'react-test-renderer';\nimport * as renderer from 'react-test-renderer';\n\nexport const renderComponentTree = (fabric: () => React.ReactElement) => {\n  let tree: ReactTestRenderer | undefined = undefined;\n\n  renderer.act(() => {\n    tree = renderer.create(fabric());\n  });\n  renderer.act(() => {\n    tree!.update(fabric());\n  });\n  renderer.act(() => {\n    tree!.update(fabric());\n  });\n  renderer.act(() => {\n    tree!.unmount();\n  });\n\n  return tree as unknown as ReactTestRenderer;\n};\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"include\": [\"src\", \"global.d.ts\"],\n  \"exclude\": [\"tests\"],\n  \"compilerOptions\": {\n    \"skipLibCheck\": true,\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"React.createElement\",\n    \"jsxFragmentFactory\": \"React.Fragment\",\n    \"noImplicitReturns\": true,\n    \"noImplicitThis\": true,\n    \"noImplicitAny\": true,\n    \"noUncheckedIndexedAccess\": true,\n    \"importHelpers\": true,\n    \"strictNullChecks\": true\n  }\n}\n"
  },
  {
    "path": "typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"],\n  \"githubPages\": true,\n  \"plugin\": [\"typedoc-plugin-markdown\"],\n  \"out\": \"docs\",\n  \"readme\": \"none\",\n  \"disableSources\": true,\n  \"externalSymbolLinkMappings\": {\n    \"telegram\": {\n      \"CloudStorage\": \"https://core.telegram.org/bots/webapps#cloudstorage\",\n      \"MainButton\": \"https://core.telegram.org/bots/webapps#mainbutton\",\n      \"SettingsButton\": \"https://core.telegram.org/bots/webapps#settingsbutton\",\n      \"ScanQrPopupParams\": \"https://core.telegram.org/bots/webapps#scanqrpopupparams\",\n      \"BackButton\": \"https://core.telegram.org/bots/webapps#backbutton\",\n      \"PopupParams\": \"https://core.telegram.org/bots/webapps#popupparams\",\n      \"PopupButton\": \"https://core.telegram.org/bots/webapps#popupbutton\",\n      \"HapticFeedback\": \"https://core.telegram.org/bots/webapps#hapticfeedback\",\n      \"ThemeParams\": \"https://core.telegram.org/bots/webapps#themeparams\",\n      \"WebApp\": \"https://core.telegram.org/bots/webapps#initializing-mini-apps\",\n      \"WebAppInitData\": \"https://core.telegram.org/bots/webapps#webappinitdata\",\n      \"WebAppUser\": \"https://core.telegram.org/bots/webapps#webappuser\",\n      \"WebAppChat\": \"https://core.telegram.org/bots/webapps#webappchat\"\n    },\n    \"react\": {\n      \"Component\": \"https://reactjs.org/docs/react-component.html\"\n    }\n  }\n}\n"
  }
]