├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── LICENSE ├── README.md ├── app ├── .eslintrc.js ├── README.md ├── _internal │ └── tgs.loader.ts ├── index.html ├── package.json ├── public │ ├── favicon.ico │ └── robots.txt ├── src │ ├── App.vue │ ├── assets │ │ ├── icons │ │ │ ├── guide.svg │ │ │ ├── star.svg │ │ │ ├── time.svg │ │ │ └── track.svg │ │ ├── img │ │ │ ├── durov.webp │ │ │ └── spongebob_poster.webp │ │ ├── stickers │ │ │ ├── duck_cool.tgs │ │ │ ├── duck_hello.tgs │ │ │ ├── duck_juggling.tgs │ │ │ ├── duck_knife.tgs │ │ │ ├── duck_love.tgs │ │ │ ├── duck_money.tgs │ │ │ ├── duck_spy.tgs │ │ │ └── duck_xray.tgs │ │ └── videos │ │ │ └── spongebob.mp4 │ ├── config.ts │ ├── main.ts │ └── styles.scss ├── tsconfig.json ├── types │ └── tgs.d.ts └── vite.config.ts ├── bot ├── bot.py ├── example.env ├── package.json └── requirements.txt ├── configuration-guide.md ├── docs └── images │ ├── form.png │ ├── form_date.png │ ├── paywall.png │ ├── paywall_links.png │ ├── paywall_popup_buttons.png │ ├── paywall_popup_buttons_media.png │ ├── paywall_popup_message.png │ ├── paywall_popup_title.png │ ├── paywall_popup_web.png │ ├── paywall_price.png │ ├── paywall_row.png │ ├── paywall_row_multiple.png │ ├── paywall_row_page.png │ ├── paywall_single.png │ ├── paywall_single_media.png │ ├── slide_align.png │ ├── slide_background.png │ ├── slide_center_pagination.png │ ├── slide_list.png │ ├── slide_list_media.png │ ├── slide_media.png │ ├── slide_pagination.png │ ├── slide_rounded.png │ ├── slide_square.png │ ├── slide_stacked.png │ ├── slide_title.png │ ├── slide_title_button.png │ └── slide_title_description_button.png ├── examples ├── ai │ ├── .eslintrc.js │ ├── README.md │ ├── _internal │ │ └── tgs.loader.ts │ ├── index.html │ ├── package.json │ ├── public │ │ ├── _redirects │ │ ├── favicon.ico │ │ └── robots.txt │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── icons │ │ │ │ ├── check.svg │ │ │ │ └── wind.svg │ │ │ └── img │ │ │ │ ├── 1_init.webp │ │ │ │ ├── 1_res.webp │ │ │ │ ├── 2_init.webp │ │ │ │ ├── 2_res.webp │ │ │ │ ├── 3_init.webp │ │ │ │ ├── 3_res.webp │ │ │ │ ├── paywall.png │ │ │ │ └── paywall.webp │ │ ├── config.ts │ │ ├── custom │ │ │ └── ActionSlide.vue │ │ ├── main.ts │ │ └── styles.scss │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── vite.config.ts ├── chatgpt │ ├── .eslintrc.js │ ├── README.md │ ├── _internal │ │ └── tgs.loader.ts │ ├── index.html │ ├── package.json │ ├── public │ │ ├── _redirects │ │ ├── favicon.ico │ │ └── robots.txt │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── img │ │ │ │ ├── chatgpt_1_poster.webp │ │ │ │ └── chatgpt_2_poster.webp │ │ │ ├── stickers │ │ │ │ ├── yoda_heart.tgs │ │ │ │ └── yoda_thinking.tgs │ │ │ └── videos │ │ │ │ ├── chatgpt_1.mp4 │ │ │ │ └── chatgpt_2.mp4 │ │ ├── config.ts │ │ ├── main.ts │ │ └── styles.scss │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── vite.config.ts ├── meditation │ ├── .eslintrc.js │ ├── README.md │ ├── _internal │ │ └── tgs.loader.ts │ ├── index.html │ ├── package.json │ ├── public │ │ ├── _redirects │ │ ├── favicon.ico │ │ └── robots.txt │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── icons │ │ │ │ ├── guide.svg │ │ │ │ ├── language.svg │ │ │ │ ├── night.svg │ │ │ │ ├── star.svg │ │ │ │ ├── time.svg │ │ │ │ └── track.svg │ │ │ └── img │ │ │ │ ├── 1.webp │ │ │ │ ├── 2.webp │ │ │ │ ├── 3.webp │ │ │ │ ├── 4.webp │ │ │ │ └── 5.webp │ │ ├── config.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── ru.json │ │ ├── main.ts │ │ └── styles.scss │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── vite.config.ts ├── tales │ ├── .eslintrc.js │ ├── README.md │ ├── _internal │ │ └── tgs.loader.ts │ ├── index.html │ ├── package.json │ ├── public │ │ ├── _redirects │ │ ├── favicon.ico │ │ └── robots.txt │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── icons │ │ │ │ ├── book.svg │ │ │ │ ├── brain.svg │ │ │ │ ├── count_1.svg │ │ │ │ ├── count_2.svg │ │ │ │ ├── count_3.svg │ │ │ │ ├── lang.svg │ │ │ │ ├── learn.svg │ │ │ │ ├── paint.svg │ │ │ │ ├── play.svg │ │ │ │ ├── review.svg │ │ │ │ ├── smile.svg │ │ │ │ ├── star.svg │ │ │ │ ├── story.jpg │ │ │ │ ├── time.svg │ │ │ │ └── wing.svg │ │ │ ├── img │ │ │ │ ├── background.png │ │ │ │ ├── background.webp │ │ │ │ ├── colorful.png │ │ │ │ ├── colorful.webp │ │ │ │ ├── main.png │ │ │ │ ├── main.webp │ │ │ │ ├── unicorn.png │ │ │ │ └── unicorn.webp │ │ │ └── stickers │ │ │ │ ├── shpooky_easy.tgs │ │ │ │ ├── shpooky_love.tgs │ │ │ │ ├── shpooky_party.tgs │ │ │ │ └── shpooky_speed.tgs │ │ ├── config.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── ru.json │ │ ├── main.ts │ │ ├── story │ │ │ ├── StoryExample.vue │ │ │ ├── assets │ │ │ │ ├── 1.png │ │ │ │ ├── 1.webp │ │ │ │ ├── 2.png │ │ │ │ ├── 2.webp │ │ │ │ ├── 3.png │ │ │ │ ├── 3.webp │ │ │ │ ├── 4.png │ │ │ │ ├── 4.webp │ │ │ │ ├── 5.png │ │ │ │ ├── 5.webp │ │ │ │ ├── 6.png │ │ │ │ └── 6.webp │ │ │ ├── components │ │ │ │ ├── EndPage.vue │ │ │ │ ├── StartPage.vue │ │ │ │ └── StoryPage.vue │ │ │ └── story.stub.ts │ │ └── styles.scss │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── vite.config.ts └── vpn │ ├── .eslintrc.js │ ├── README.md │ ├── _internal │ └── tgs.loader.ts │ ├── index.html │ ├── package.json │ ├── public │ ├── _redirects │ ├── favicon.ico │ └── robots.txt │ ├── src │ ├── App.vue │ ├── assets │ │ ├── img │ │ │ └── hands_up.webp │ │ └── stickers │ │ │ ├── fish_hello.tgs │ │ │ ├── fish_love.tgs │ │ │ └── lock.tgs │ ├── config.ts │ ├── main.ts │ └── styles.scss │ ├── tsconfig.json │ ├── types │ └── tgs.d.ts │ └── vite.config.ts ├── package-lock.json ├── package.json ├── packages ├── compress │ ├── .gitignore │ ├── README.md │ ├── compress.mjs │ └── package.json ├── eslint-config │ ├── README.md │ ├── index.js │ └── package.json ├── generation │ ├── .eslintrc.js │ ├── README.md │ ├── Root.vue │ ├── bootstrap.ts │ ├── components │ │ ├── DrawPreset │ │ │ ├── DrawPreset.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── ListItem │ │ │ ├── ListItem.props.ts │ │ │ ├── ListItem.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── Media │ │ │ ├── Emodji.vue │ │ │ ├── Icon.vue │ │ │ ├── Image.vue │ │ │ ├── Media.preset.props.ts │ │ │ ├── Media.preset.vue │ │ │ ├── README.md │ │ │ ├── Sticker.vue │ │ │ ├── VideoPreset.vue │ │ │ ├── index.ts │ │ │ └── useLoadedImage.ts │ │ ├── PaywallPopup │ │ │ ├── PaywallPopup.props.ts │ │ │ ├── PaywallPopup.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── PrimitivePaywall │ │ │ ├── PrimitivePaywall.props.ts │ │ │ ├── PrimitivePaywall.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── PrimitiveSlide │ │ │ ├── PrimitiveSlide.props.ts │ │ │ ├── PrimitiveSlide.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ └── README.md │ ├── defineConfig.ts │ ├── index.ts │ ├── package.json │ ├── plugins │ │ ├── README.md │ │ ├── definePresets │ │ │ ├── DefinePresets.plugin.ts │ │ │ └── index.ts │ │ ├── formState │ │ │ ├── FormState.plugin.ts │ │ │ └── index.ts │ │ └── theme │ │ │ ├── Theme.plugin.ts │ │ │ └── index.ts │ ├── presets │ │ ├── README.md │ │ ├── Route.vue │ │ ├── base │ │ │ ├── README.md │ │ │ ├── base.preset.props.ts │ │ │ ├── base.preset.vue │ │ │ └── index.ts │ │ ├── form │ │ │ ├── README.md │ │ │ ├── form.preset.props.ts │ │ │ ├── form.preset.vue │ │ │ └── index.ts │ │ ├── paywall │ │ │ ├── BaseProduct.vue │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── paywall.preset.props.ts │ │ │ └── paywall.preset.vue │ │ ├── paywall_row │ │ │ ├── Product.vue │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── paywall_row.preset.props.ts │ │ │ └── paywall_row.preset.vue │ │ ├── paywall_single │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── paywall_single.preset.props.ts │ │ │ └── paywall_single.preset.vue │ │ └── slide │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── slide.preset.props.ts │ │ │ └── slide.preset.vue │ ├── tokens │ │ ├── README.md │ │ ├── definedPresets.token.ts │ │ ├── formState.token.ts │ │ ├── index.ts │ │ ├── theme.token.ts │ │ └── wasInteraction.token.ts │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── use │ │ ├── README.md │ │ └── carousel │ │ └── index.ts ├── i18n │ ├── .eslintrc.js │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── plugins │ │ └── index.ts │ ├── tsconfig.json │ └── use │ │ ├── index.ts │ │ └── useI18n.ts ├── telegram-ui │ ├── .eslintrc.js │ ├── README.md │ ├── components │ │ ├── BackButton │ │ │ ├── BackButton.props.ts │ │ │ ├── BackButton.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── MainButton │ │ │ ├── MainButton.props.ts │ │ │ ├── MainButton.vue │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── Sticker │ │ │ ├── README.md │ │ │ ├── Sticker.props.ts │ │ │ ├── Sticker.vue │ │ │ └── index.ts │ │ └── TelegramPopup │ │ │ ├── README.md │ │ │ ├── TelegramPopup.props.ts │ │ │ ├── TelegramPopup.vue │ │ │ ├── TelegramPopupButton.vue │ │ │ └── index.ts │ ├── package.json │ ├── tsconfig.json │ ├── types │ │ └── tgs.d.ts │ └── use │ │ ├── sdk │ │ └── index.ts │ │ └── theme │ │ ├── index.ts │ │ └── useTheme.ts ├── tsconfig │ ├── README.md │ ├── package.json │ └── tsconfig.base.json └── ui │ ├── .eslintrc.js │ ├── README.md │ ├── components │ ├── Alert │ │ ├── Alert.props.ts │ │ ├── Alert.vue │ │ ├── README.md │ │ └── index.ts │ ├── Carousel │ │ ├── Carousel.props.ts │ │ ├── Carousel.vue │ │ ├── README.md │ │ ├── carousel-scroll.directive.ts │ │ └── index.ts │ ├── CheckboxBlock │ │ ├── CheckboxBlock.props.ts │ │ ├── CheckboxBlock.vue │ │ ├── README.md │ │ └── index.ts │ ├── FlatButton │ │ ├── FlatButton.props.ts │ │ ├── FlatButton.vue │ │ ├── README.md │ │ └── index.ts │ ├── InputText │ │ ├── InputText.props.ts │ │ ├── InputText.vue │ │ ├── README.md │ │ └── index.ts │ ├── Link │ │ ├── Link.props.ts │ │ ├── Link.vue │ │ ├── README.md │ │ └── index.ts │ ├── Money │ │ ├── Money.props.ts │ │ ├── Money.vue │ │ ├── README.md │ │ └── index.ts │ ├── Pagination │ │ ├── Pagination.props.ts │ │ ├── Pagination.vue │ │ ├── README.md │ │ └── index.ts │ ├── Popup │ │ ├── Popup.props.ts │ │ ├── Popup.vue │ │ ├── README.md │ │ └── index.ts │ ├── Portal │ │ ├── Portal.props.ts │ │ ├── Portal.vue │ │ ├── README.md │ │ └── index.ts │ ├── PrimitiveCheckbox │ │ ├── PrimitiveCheckbox.props.ts │ │ ├── PrimitiveCheckbox.vue │ │ ├── README.md │ │ └── index.ts │ ├── PrimitiveRadio │ │ ├── PrimitiveRadio.props.ts │ │ ├── PrimitiveRadio.vue │ │ ├── README.md │ │ └── index.ts │ ├── README.md │ ├── Root │ │ ├── AlertsHost.vue │ │ ├── PopupsHost.vue │ │ ├── README.md │ │ ├── Root.props.ts │ │ ├── Root.vue │ │ └── index.ts │ ├── SvgIcon │ │ ├── README.md │ │ ├── SvgIcon.props.ts │ │ ├── SvgIcon.vue │ │ ├── icons │ │ │ ├── arrow-left.svg │ │ │ ├── arrow-right.svg │ │ │ ├── checkmark-fill.svg │ │ │ ├── checkmark.svg │ │ │ ├── close.svg │ │ │ ├── spinner.svg │ │ │ └── warning-fill.svg │ │ └── index.ts │ └── Toggle │ │ ├── README.md │ │ ├── Toggle.props.ts │ │ ├── Toggle.vue │ │ └── index.ts │ ├── consts │ ├── chars.ts │ └── index.ts │ ├── directives │ ├── README.md │ ├── dragdrop │ │ ├── dragDrop.directive.ts │ │ └── index.ts │ ├── intersection │ │ ├── index.ts │ │ └── intersection.directive.ts │ ├── ripple │ │ ├── index.ts │ │ └── ripple.ts │ └── swipe │ │ ├── index.ts │ │ └── swipe.directive.ts │ ├── dom │ ├── README.md │ ├── focus │ │ ├── blurNativeFocused.ts │ │ ├── getNativeFocused.ts │ │ ├── index.ts │ │ └── setNativeFocused.ts │ ├── index.ts │ └── platform │ │ └── index.ts │ ├── package.json │ ├── plugins │ ├── README.md │ ├── alerts │ │ ├── Alerts.plugin.ts │ │ └── index.ts │ └── currency │ │ ├── currency.plugin.ts │ │ └── index.ts │ ├── styles │ ├── README.md │ ├── global.scss │ ├── local.scss │ └── main │ │ └── reset.scss │ ├── tokens │ ├── AlertsHost.token.ts │ ├── CurrencyOptions.token.ts │ ├── CustomIcons.token.ts │ ├── PopupsHost.token.ts │ ├── README.md │ └── index.ts │ ├── tsconfig.json │ ├── types │ ├── README.md │ ├── index.ts │ └── maybeRef.type.ts │ ├── use │ ├── README.md │ ├── alerts │ │ ├── README.md │ │ ├── index.ts │ │ └── useAlerts.ts │ ├── focused │ │ ├── README.md │ │ ├── index.ts │ │ └── useFocused.ts │ └── money │ │ ├── README.md │ │ ├── currency │ │ ├── currency.enum.ts │ │ ├── currency.ts │ │ ├── getCurrencySymbol.ts │ │ └── index.ts │ │ ├── formatMoney.ts │ │ ├── index.ts │ │ └── useMoney.ts │ └── utility │ ├── README.md │ ├── clamp.ts │ ├── formatNumber.ts │ ├── getElementId.ts │ ├── noop.ts │ └── tryOnBeforeUnmount.ts └── turbo.json /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | 7 | # Allows you to run this workflow manually from the Actions tab 8 | workflow_dispatch: 9 | 10 | # Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages 11 | permissions: 12 | contents: read 13 | pages: write 14 | id-token: write 15 | 16 | # Allow one concurrent deployment 17 | concurrency: 18 | group: 'pages' 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | # Single deploy job since we're just deploying 23 | deploy: 24 | environment: 25 | name: github-pages 26 | url: ${{ steps.deployment.outputs.page_url }} 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v3 31 | - name: Set up Node 32 | uses: actions/setup-node@v3 33 | with: 34 | node-version: 18 35 | cache: 'npm' 36 | - name: Install dependencies 37 | run: npm install 38 | - name: Build 39 | # We need to pass the repository name directly to the Vite build command 40 | # as the "base" parameter. 41 | # This is necessary because it aligns with how GitHub Pages functions. 42 | # Here's how you can achieve this: 43 | run: npm run build -- -- --base /${{ github.event.repository.name }} 44 | - name: Create 404.html 45 | run: cp ./app/dist/index.html ./app/dist/404.html 46 | - name: Setup Pages 47 | uses: actions/configure-pages@v3 48 | - name: Upload artifact 49 | uses: actions/upload-pages-artifact@v1 50 | with: 51 | # Upload dist repository 52 | path: './app/dist' 53 | - name: Deploy to GitHub Pages 54 | id: deployment 55 | uses: actions/deploy-pages@v1 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | .expo-shared 8 | 9 | .vscode 10 | 11 | # testing 12 | coverage 13 | 14 | # next.js 15 | .next/ 16 | .swc/ 17 | out/ 18 | build 19 | 20 | # expo 21 | .expo 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | dist 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | 33 | # local env files 34 | .env.local 35 | .env.development.local 36 | .env.test.local 37 | .env.production.local 38 | 39 | # turbo 40 | .turbo 41 | 42 | # bot 43 | bot/.env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | # Hi! 2 | -------------------------------------------------------------------------------- /app/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/app", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3000 --open", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/tsconfig": "*", 15 | "@tok/eslint-config": "*" 16 | } 17 | } -------------------------------------------------------------------------------- /app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/public/favicon.ico -------------------------------------------------------------------------------- /app/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /app/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/assets/icons/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/assets/icons/time.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/icons/track.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/assets/img/durov.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/img/durov.webp -------------------------------------------------------------------------------- /app/src/assets/img/spongebob_poster.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/img/spongebob_poster.webp -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_cool.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_cool.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_hello.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_hello.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_juggling.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_juggling.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_knife.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_knife.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_love.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_love.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_money.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_money.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_spy.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_spy.tgs -------------------------------------------------------------------------------- /app/src/assets/stickers/duck_xray.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/stickers/duck_xray.tgs -------------------------------------------------------------------------------- /app/src/assets/videos/spongebob.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/app/src/assets/videos/spongebob.mp4 -------------------------------------------------------------------------------- /app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /app/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root { 5 | } 6 | 7 | html[data-theme='dark'] { 8 | } 9 | -------------------------------------------------------------------------------- /app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /app/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /app/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /bot/example.env: -------------------------------------------------------------------------------- 1 | BOT_TOKEN="" # (required) Telegram bot token from @BotFather 2 | TELEGRAM_PAYMENTS_TOKEN="" # (optional) Telegram Payments token from @BotFather. If not specified, Telegram Payments method will not work 3 | WALLET_PAY_TOKEN="" # (optional) Token for Wallet Pay from pay.wallet.tg. If not specified, Wallet Pay method will not work -------------------------------------------------------------------------------- /bot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/bot", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "python -m pip install -r requirements.txt && python ./bot.py" 6 | } 7 | } -------------------------------------------------------------------------------- /bot/requirements.txt: -------------------------------------------------------------------------------- 1 | python-telegram-bot==20.5 2 | python-dotenv==0.21.0 3 | -------------------------------------------------------------------------------- /docs/images/form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/form.png -------------------------------------------------------------------------------- /docs/images/form_date.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/form_date.png -------------------------------------------------------------------------------- /docs/images/paywall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall.png -------------------------------------------------------------------------------- /docs/images/paywall_links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_links.png -------------------------------------------------------------------------------- /docs/images/paywall_popup_buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_popup_buttons.png -------------------------------------------------------------------------------- /docs/images/paywall_popup_buttons_media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_popup_buttons_media.png -------------------------------------------------------------------------------- /docs/images/paywall_popup_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_popup_message.png -------------------------------------------------------------------------------- /docs/images/paywall_popup_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_popup_title.png -------------------------------------------------------------------------------- /docs/images/paywall_popup_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_popup_web.png -------------------------------------------------------------------------------- /docs/images/paywall_price.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_price.png -------------------------------------------------------------------------------- /docs/images/paywall_row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_row.png -------------------------------------------------------------------------------- /docs/images/paywall_row_multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_row_multiple.png -------------------------------------------------------------------------------- /docs/images/paywall_row_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_row_page.png -------------------------------------------------------------------------------- /docs/images/paywall_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_single.png -------------------------------------------------------------------------------- /docs/images/paywall_single_media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/paywall_single_media.png -------------------------------------------------------------------------------- /docs/images/slide_align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_align.png -------------------------------------------------------------------------------- /docs/images/slide_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_background.png -------------------------------------------------------------------------------- /docs/images/slide_center_pagination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_center_pagination.png -------------------------------------------------------------------------------- /docs/images/slide_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_list.png -------------------------------------------------------------------------------- /docs/images/slide_list_media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_list_media.png -------------------------------------------------------------------------------- /docs/images/slide_media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_media.png -------------------------------------------------------------------------------- /docs/images/slide_pagination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_pagination.png -------------------------------------------------------------------------------- /docs/images/slide_rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_rounded.png -------------------------------------------------------------------------------- /docs/images/slide_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_square.png -------------------------------------------------------------------------------- /docs/images/slide_stacked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_stacked.png -------------------------------------------------------------------------------- /docs/images/slide_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_title.png -------------------------------------------------------------------------------- /docs/images/slide_title_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_title_button.png -------------------------------------------------------------------------------- /docs/images/slide_title_description_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/docs/images/slide_title_description_button.png -------------------------------------------------------------------------------- /examples/ai/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /examples/ai/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/README.md -------------------------------------------------------------------------------- /examples/ai/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /examples/ai/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/ai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/ai", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3001 --open", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "@tok/i18n": "^0.0.0", 11 | "vue": "^3.3.4", 12 | "vue-router": "^4.2.5" 13 | }, 14 | "devDependencies": { 15 | "@tok/eslint-config": "*", 16 | "@tok/tsconfig": "*" 17 | } 18 | } -------------------------------------------------------------------------------- /examples/ai/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /examples/ai/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/public/favicon.ico -------------------------------------------------------------------------------- /examples/ai/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/ai/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /examples/ai/src/assets/icons/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/ai/src/assets/img/1_init.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/1_init.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/1_res.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/1_res.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/2_init.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/2_init.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/2_res.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/2_res.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/3_init.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/3_init.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/3_res.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/3_res.webp -------------------------------------------------------------------------------- /examples/ai/src/assets/img/paywall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/paywall.png -------------------------------------------------------------------------------- /examples/ai/src/assets/img/paywall.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/ai/src/assets/img/paywall.webp -------------------------------------------------------------------------------- /examples/ai/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /examples/ai/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root { 5 | --tok-padding-l: 1.5rem; 6 | 7 | --tok-primary: #e3ff2b; 8 | --tok-primary-text: var(--tok-dark); 9 | } 10 | 11 | html[data-theme='dark'] { 12 | --tok-primary: #e3ff2b; 13 | --tok-primary-text: var(--tok-dark); 14 | } 15 | -------------------------------------------------------------------------------- /examples/ai/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /examples/ai/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /examples/ai/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /examples/chatgpt/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /examples/chatgpt/README.md: -------------------------------------------------------------------------------- 1 | # Hi! 2 | -------------------------------------------------------------------------------- /examples/chatgpt/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /examples/chatgpt/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/chatgpt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/chatgpt", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3004 --open", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/tsconfig": "*", 15 | "@tok/eslint-config": "*" 16 | } 17 | } -------------------------------------------------------------------------------- /examples/chatgpt/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /examples/chatgpt/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/public/favicon.ico -------------------------------------------------------------------------------- /examples/chatgpt/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/chatgpt/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/img/chatgpt_1_poster.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/img/chatgpt_1_poster.webp -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/img/chatgpt_2_poster.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/img/chatgpt_2_poster.webp -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/stickers/yoda_heart.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/stickers/yoda_heart.tgs -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/stickers/yoda_thinking.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/stickers/yoda_thinking.tgs -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/videos/chatgpt_1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/videos/chatgpt_1.mp4 -------------------------------------------------------------------------------- /examples/chatgpt/src/assets/videos/chatgpt_2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/chatgpt/src/assets/videos/chatgpt_2.mp4 -------------------------------------------------------------------------------- /examples/chatgpt/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /examples/chatgpt/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root { 5 | } 6 | 7 | html[data-theme='dark'] { 8 | } 9 | -------------------------------------------------------------------------------- /examples/chatgpt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /examples/chatgpt/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /examples/chatgpt/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /examples/meditation/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /examples/meditation/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/README.md -------------------------------------------------------------------------------- /examples/meditation/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /examples/meditation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/meditation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/meditation", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3002 --host", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/tsconfig": "*", 15 | "@tok/eslint-config": "*" 16 | } 17 | } -------------------------------------------------------------------------------- /examples/meditation/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /examples/meditation/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/public/favicon.ico -------------------------------------------------------------------------------- /examples/meditation/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/meditation/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/icons/language.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/icons/night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/icons/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/icons/time.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/icons/track.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/meditation/src/assets/img/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/src/assets/img/1.webp -------------------------------------------------------------------------------- /examples/meditation/src/assets/img/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/src/assets/img/2.webp -------------------------------------------------------------------------------- /examples/meditation/src/assets/img/3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/src/assets/img/3.webp -------------------------------------------------------------------------------- /examples/meditation/src/assets/img/4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/src/assets/img/4.webp -------------------------------------------------------------------------------- /examples/meditation/src/assets/img/5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/meditation/src/assets/img/5.webp -------------------------------------------------------------------------------- /examples/meditation/src/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "_s1": { 3 | "title": "Welcome to the world of meditation!", 4 | "description": "Find your inner peace and harmony with our app", 5 | "button": "Next" 6 | }, 7 | "_s2": { 8 | "title": "Tell about yourself", 9 | "description": "It will help us build your health roadmap", 10 | "namePlaceholder": "Your name", 11 | "agePlaceholder": "Your age" 12 | }, 13 | "_s3": { 14 | "title": "What type of meditation do you prefer?", 15 | "guided": "Guided Meditation", 16 | "mind": "Mindfulness Meditation", 17 | "trans": "Transcendental Meditation", 18 | "yoga": "Yoga Meditation", 19 | "other": "Other" 20 | }, 21 | "_s4": { 22 | "title": "Explore what works for you", 23 | "list1": "Extensive collection of guided meditations", 24 | "list2": "Meditations in multiple languages", 25 | "list3": "Set reminders for regular practice", 26 | "list4": "Night mode for pre-sleep meditation", 27 | "list5": "Track your progress", 28 | "button": "Start the health way" 29 | }, 30 | "_paywall": { 31 | "title": "Unlock the Full Experience!", 32 | "description": "Get unlimited access to all our premium features and meditations", 33 | "product": { 34 | "title": "Lifetime Access", 35 | "description": "One-time payment for unlimited access.
Dive deep into a world of relaxation and mindfulness" 36 | }, 37 | "policy": "Privacy policy", 38 | "policy_href": "https://google.com", 39 | "terms": "Terms of use", 40 | "terms_href": "https://google.com", 41 | "main": "Buy for {price}", 42 | "popup": { 43 | "title": "Choose the payment method", 44 | "telegram_payments": "Bank Card", 45 | "wallet_pay": "Wallet Pay" 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /examples/meditation/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /examples/meditation/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root, 5 | html[data-theme='dark'] { 6 | --tok-primary: #5734bc; 7 | --tok-primary-text: var(--tok-white); 8 | } 9 | -------------------------------------------------------------------------------- /examples/meditation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /examples/meditation/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /examples/meditation/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /examples/tales/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /examples/tales/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/README.md -------------------------------------------------------------------------------- /examples/tales/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /examples/tales/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/tales/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/tales", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3003 --open", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/tsconfig": "*", 15 | "@tok/eslint-config": "*" 16 | } 17 | } -------------------------------------------------------------------------------- /examples/tales/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /examples/tales/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/public/favicon.ico -------------------------------------------------------------------------------- /examples/tales/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/tales/src/App.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 42 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/book.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/count_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/count_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/learn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/smile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/tales/src/assets/icons/story.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/icons/story.jpg -------------------------------------------------------------------------------- /examples/tales/src/assets/img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/background.png -------------------------------------------------------------------------------- /examples/tales/src/assets/img/background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/background.webp -------------------------------------------------------------------------------- /examples/tales/src/assets/img/colorful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/colorful.png -------------------------------------------------------------------------------- /examples/tales/src/assets/img/colorful.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/colorful.webp -------------------------------------------------------------------------------- /examples/tales/src/assets/img/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/main.png -------------------------------------------------------------------------------- /examples/tales/src/assets/img/main.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/main.webp -------------------------------------------------------------------------------- /examples/tales/src/assets/img/unicorn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/unicorn.png -------------------------------------------------------------------------------- /examples/tales/src/assets/img/unicorn.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/img/unicorn.webp -------------------------------------------------------------------------------- /examples/tales/src/assets/stickers/shpooky_easy.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/stickers/shpooky_easy.tgs -------------------------------------------------------------------------------- /examples/tales/src/assets/stickers/shpooky_love.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/stickers/shpooky_love.tgs -------------------------------------------------------------------------------- /examples/tales/src/assets/stickers/shpooky_party.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/stickers/shpooky_party.tgs -------------------------------------------------------------------------------- /examples/tales/src/assets/stickers/shpooky_speed.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/assets/stickers/shpooky_speed.tgs -------------------------------------------------------------------------------- /examples/tales/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /examples/tales/src/story/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/1.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/1.webp -------------------------------------------------------------------------------- /examples/tales/src/story/assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/2.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/2.webp -------------------------------------------------------------------------------- /examples/tales/src/story/assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/3.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/3.webp -------------------------------------------------------------------------------- /examples/tales/src/story/assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/4.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/4.webp -------------------------------------------------------------------------------- /examples/tales/src/story/assets/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/5.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/5.webp -------------------------------------------------------------------------------- /examples/tales/src/story/assets/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/6.png -------------------------------------------------------------------------------- /examples/tales/src/story/assets/6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/tales/src/story/assets/6.webp -------------------------------------------------------------------------------- /examples/tales/src/story/components/StartPage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 34 | -------------------------------------------------------------------------------- /examples/tales/src/story/story.stub.ts: -------------------------------------------------------------------------------- 1 | import first from './assets/1.png'; 2 | import firstWebp from './assets/1.webp'; 3 | import second from './assets/2.png'; 4 | import secondWebp from './assets/2.webp'; 5 | import third from './assets/3.png'; 6 | import thirdWebp from './assets/3.webp'; 7 | import fourth from './assets/4.png'; 8 | import fourthWebp from './assets/4.webp'; 9 | import fifth from './assets/5.png'; 10 | import fifthWebp from './assets/5.webp'; 11 | import sixth from './assets/6.png'; 12 | import sixthWebp from './assets/6.webp'; 13 | 14 | export const storyStub = [ 15 | { 16 | text: '_story.page1', 17 | image: first, 18 | webp: firstWebp, 19 | }, 20 | { 21 | text: '_story.page2', 22 | image: second, 23 | webp: secondWebp, 24 | }, 25 | { 26 | text: '_story.page3', 27 | image: third, 28 | webp: thirdWebp, 29 | }, 30 | { 31 | text: '_story.page4', 32 | image: fourth, 33 | webp: fourthWebp, 34 | }, 35 | { 36 | text: '_story.page5', 37 | image: fifth, 38 | webp: fifthWebp, 39 | }, 40 | { 41 | text: '_story.page6', 42 | image: sixth, 43 | webp: sixthWebp, 44 | }, 45 | ]; 46 | -------------------------------------------------------------------------------- /examples/tales/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root { 5 | font-size: 18px; 6 | } 7 | 8 | html[data-theme='dark'] { 9 | --tok-background-color-base: 66, 68, 86; 10 | 11 | --tok-slide-background: transparent; 12 | 13 | --tok-primary: #c962a9; 14 | --tok-primary-text: var(--tok-white); 15 | } 16 | 17 | .wt-background { 18 | position: absolute; 19 | top: 0; 20 | right: 0; 21 | height: 100vh; 22 | width: 100vw; 23 | object-fit: cover; 24 | z-index: -1; 25 | } 26 | 27 | .wt-shadow { 28 | position: absolute; 29 | left: 0; 30 | top: 0; 31 | width: 100%; 32 | height: 100%; 33 | pointer-events: none; 34 | background-color: rgba(0, 0, 0, 0.52); 35 | z-index: -1; 36 | } 37 | 38 | .wt-link-button { 39 | position: fixed; 40 | top: 0; 41 | right: 0; 42 | } 43 | -------------------------------------------------------------------------------- /examples/tales/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /examples/tales/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /examples/tales/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /examples/vpn/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /examples/vpn/README.md: -------------------------------------------------------------------------------- 1 | # Hi! 2 | -------------------------------------------------------------------------------- /examples/vpn/_internal/tgs.loader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { ungzip } from 'pako'; 3 | import type { Plugin } from 'vite'; 4 | 5 | // find the way to import it as a component 6 | const tgsRegexp = /\.tgs$/; 7 | 8 | export function telegramStickerLoader(): Plugin { 9 | return { 10 | name: 'telegram-sticker-loader', 11 | enforce: 'pre', 12 | load(id: string) { 13 | if (!id.match(tgsRegexp)) { 14 | return; 15 | } 16 | 17 | const [path, importType = 'json'] = id.split('?', 2) as [string, 'json']; 18 | 19 | let decodedTgs; 20 | 21 | try { 22 | const fileBuffer = fs.readFileSync(path); 23 | 24 | decodedTgs = new TextDecoder('utf-8').decode(ungzip(fileBuffer)); 25 | } catch (e) { 26 | console.error(`\n${id} couldn't be loaded by telegramStickerLoader \n`); 27 | 28 | return; 29 | } 30 | 31 | if (importType === 'json') { 32 | // https://v8.dev/blog/cost-of-javascript-2019#json 33 | return `export default JSON.parse(${JSON.stringify(decodedTgs)})`; 34 | } 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /examples/vpn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Onboarding | Tok 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/vpn/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/vpn", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite --port 3004 --open", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@tok/generation": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/tsconfig": "*", 15 | "@tok/eslint-config": "*" 16 | } 17 | } -------------------------------------------------------------------------------- /examples/vpn/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /examples/vpn/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/vpn/public/favicon.ico -------------------------------------------------------------------------------- /examples/vpn/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /examples/vpn/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /examples/vpn/src/assets/img/hands_up.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/vpn/src/assets/img/hands_up.webp -------------------------------------------------------------------------------- /examples/vpn/src/assets/stickers/fish_hello.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/vpn/src/assets/stickers/fish_hello.tgs -------------------------------------------------------------------------------- /examples/vpn/src/assets/stickers/fish_love.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/vpn/src/assets/stickers/fish_love.tgs -------------------------------------------------------------------------------- /examples/vpn/src/assets/stickers/lock.tgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Easterok/telegram-onboarding-kit/bda5c585bdf617d8dcb04ca5f61ecd0f199295b6/examples/vpn/src/assets/stickers/lock.tgs -------------------------------------------------------------------------------- /examples/vpn/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@tok/generation'; 2 | 3 | import App from './App.vue'; 4 | import { default as config } from './config'; 5 | 6 | bootstrap(App, config); 7 | -------------------------------------------------------------------------------- /examples/vpn/src/styles.scss: -------------------------------------------------------------------------------- 1 | // See https://github.com/Easterok/telegram-onboarding-kit/tree/main/packages/ui/styles 2 | // on how to override global CSS parameters 3 | 4 | :root { 5 | } 6 | 7 | html[data-theme='dark'] { 8 | } 9 | -------------------------------------------------------------------------------- /examples/vpn/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /examples/vpn/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /examples/vpn/vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue'; 2 | import { defineConfig } from 'vite'; 3 | import svgLoader from 'vite-svg-loader'; 4 | 5 | import { telegramStickerLoader } from './_internal/tgs.loader'; 6 | 7 | export default defineConfig({ 8 | plugins: [ 9 | telegramStickerLoader(), 10 | vue(), 11 | svgLoader({ 12 | defaultImport: 'component', 13 | svgoConfig: { 14 | plugins: [ 15 | { 16 | name: 'cleanupIds', 17 | params: { 18 | remove: false, 19 | minify: false, 20 | }, 21 | }, 22 | ], 23 | }, 24 | }), 25 | ], 26 | build: { 27 | assetsInlineLimit: 0, 28 | minify: true, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/telegram-onboarding-kit", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "*** Your app ***": "", 6 | "dev": "turbo run dev --scope @tok/app", 7 | "build": "turbo run build --scope @tok/app", 8 | "*********************************************": "", 9 | "*** ai ***": "", 10 | "dev:ai": "turbo run dev --scope @tok/ai", 11 | "build:ai": "turbo run build --scope @tok/ai", 12 | "*** meditation ***": "", 13 | "dev:meditation": "turbo run dev --scope @tok/meditation", 14 | "build:meditation": "turbo run build --scope @tok/meditation", 15 | "*** tales ***": "", 16 | "dev:tales": "turbo run dev --scope @tok/tales", 17 | "build:tales": "turbo run build --scope @tok/tales", 18 | "*** vpn ***": "", 19 | "dev:vpn": "turbo run dev --scope @tok/vpn", 20 | "build:vpn": "turbo run build --scope @tok/vpn", 21 | "*** chatgpt ***": "", 22 | "dev:chatgpt": "turbo run dev --scope @tok/chatgpt", 23 | "build:chatgpt": "turbo run build --scope @tok/chatgpt", 24 | "*** bot *** ": "", 25 | "dev:bot": "turbo run dev --scope @tok/bot", 26 | "*** other *** ": "", 27 | "build:all": "turbo run build", 28 | "compress": "turbo run compress --scope @tok/compress" 29 | }, 30 | "devDependencies": { 31 | "prettier": "^2.7.1", 32 | "turbo": "^1.10.14", 33 | "typescript": "5.2.2" 34 | }, 35 | "packageManager": "npm@9.5.1", 36 | "workspaces": [ 37 | "app", 38 | "bot", 39 | "examples/*", 40 | "packages/*" 41 | ] 42 | } -------------------------------------------------------------------------------- /packages/compress/.gitignore: -------------------------------------------------------------------------------- 1 | input 2 | output -------------------------------------------------------------------------------- /packages/compress/README.md: -------------------------------------------------------------------------------- 1 | # @tok/compress 2 | 3 | Node-based solution for image compression. It efficiently processes PNG, JPG, and JPEG files, reducing their size and converting them into WEBP, PNG, JPG, or JPEG formats. 4 | 5 | ## Usage 6 | 7 | 1. Place your images inside the `input` folder. 8 | 2. Run the following command: 9 | 10 | ```bash 11 | npm run compress 12 | ``` 13 | 14 | 3. The compressed images will be generated and stored in the `output` folder, available in various compression sizes [40/60/80/100]. 15 | 4. Select the compressed images that best suit your needs and replace the original ones with the optimized versions. 16 | -------------------------------------------------------------------------------- /packages/compress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/compress", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "compress": "node compress.mjs" 6 | }, 7 | "devDependencies": { 8 | "sharp": "0.32.0" 9 | } 10 | } -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # @tok/eslint-config 2 | 3 | Basic eslint-config for your applications 4 | 5 | ## Usage 6 | 7 | 1. Run the following command: 8 | 9 | ```bash 10 | npm i @tok/eslint-config --save-dev --workspace= 11 | ``` 12 | 13 | 2. Create a `.eslintrc.js` file within your app. 14 | 15 | 3. Add the following default configuration to the `.eslintrc.js` file: 16 | 17 | ```js 18 | module.exports = { 19 | root: true, 20 | extends: ['@tok/eslint-config'], 21 | parserOptions: { tsconfigRootDir: __dirname }, 22 | }; 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/eslint-config", 3 | "version": "0.0.0", 4 | "main": "index.js", 5 | "dependencies": { 6 | "@typescript-eslint/eslint-plugin": "^5.59.0", 7 | "@typescript-eslint/parser": "^5.59.0", 8 | "@vue/eslint-config-prettier": "^7.1.0", 9 | "@vue/eslint-config-typescript": "^11.0.2", 10 | "eslint": "^8.39.0", 11 | "eslint-config-prettier": "^8.5.0", 12 | "eslint-plugin-prettier": "^4.2.1", 13 | "eslint-plugin-simple-import-sort": "^10.0.0", 14 | "eslint-plugin-unused-imports": "^2.0.0", 15 | "eslint-plugin-vue": "^9.3.0", 16 | "prettier": "^2.8.7", 17 | "vue-eslint-parser": "^9.1.1" 18 | } 19 | } -------------------------------------------------------------------------------- /packages/generation/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/generation/components/DrawPreset/DrawPreset.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /packages/generation/components/DrawPreset/README.md: -------------------------------------------------------------------------------- 1 | # DrawPreset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | This component can draw a preset which was defined via [DefinedPresets.token](../../tokens/README.md) 7 | -------------------------------------------------------------------------------- /packages/generation/components/DrawPreset/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DrawPreset } from './DrawPreset.vue'; 2 | -------------------------------------------------------------------------------- /packages/generation/components/ListItem/ListItem.props.ts: -------------------------------------------------------------------------------- 1 | import { MediaPresetProps } from '@tok/generation/components/Media'; 2 | 3 | export type ListItemProps = { 4 | text: string; 5 | media?: MediaPresetProps; 6 | }; 7 | 8 | export const ListItemDefaultProps = { 9 | text: '', 10 | } as const; 11 | -------------------------------------------------------------------------------- /packages/generation/components/ListItem/ListItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 24 | 25 | 39 | -------------------------------------------------------------------------------- /packages/generation/components/ListItem/README.md: -------------------------------------------------------------------------------- 1 | # ListItem 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | This component can render a list item (li) with [Media](../Media/README.md) if media is provided 7 | 8 | ## Props 9 | 10 | All available props see in [ListItem.props.ts](./ListItem.props.ts) 11 | 12 | ## i18n 13 | 14 | The component natively supports [i18n](../../../i18n/README.md) for text values. 15 | 16 | You can provide a text as a locale token, and it will be dynamically translated 17 | -------------------------------------------------------------------------------- /packages/generation/components/ListItem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListItem.props'; 2 | export { default as ListItem } from './ListItem.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/components/Media/Emodji.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 42 | 43 | 63 | -------------------------------------------------------------------------------- /packages/generation/components/Media/Icon.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 60 | -------------------------------------------------------------------------------- /packages/generation/components/Media/Image.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 42 | -------------------------------------------------------------------------------- /packages/generation/components/Media/Media.preset.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /packages/generation/components/Media/README.md: -------------------------------------------------------------------------------- 1 | # Media 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | This component supports 5 different types of media: 7 | 8 | 1. [Video](./VideoPreset.vue) 9 | 2. [Image](./Image.vue) 10 | 3. [Icon](./Icon.vue) 11 | 4. [Emodji](./Emodji.vue) 12 | 5. [Sticker](./Sticker.vue) 13 | 14 | Sticker will be loaded asynchronously 15 | 16 | ## Props 17 | 18 | All available props see in [Media.props.ts](./Media.props.ts) 19 | -------------------------------------------------------------------------------- /packages/generation/components/Media/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Media.preset.props'; 2 | export { default as MediaPreset } from './Media.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/components/Media/useLoadedImage.ts: -------------------------------------------------------------------------------- 1 | import { MaybeComputedRef, resolveRef } from '@tok/ui/types'; 2 | import { computed, ref, watch } from 'vue'; 3 | 4 | import { _MediaLoader } from './Media.preset.props'; 5 | 6 | export function useLoadedImage( 7 | src: MaybeComputedRef<_MediaLoader | string | undefined> = '' 8 | ) { 9 | const srcRef = resolveRef(src); 10 | 11 | const onlySrcLoader = computed(() => { 12 | const value = srcRef.value; 13 | 14 | return value && typeof value === 'object' && 'then' in value ? value : null; 15 | }); 16 | 17 | const loadedImage = ref(); 18 | 19 | const loadImage = (value: _MediaLoader) => { 20 | value.then((m) => { 21 | loadedImage.value = m.default; 22 | }); 23 | }; 24 | 25 | watch( 26 | onlySrcLoader, 27 | (value) => { 28 | if (value) { 29 | loadImage(value); 30 | } 31 | }, 32 | { immediate: true } 33 | ); 34 | 35 | return loadedImage; 36 | } 37 | -------------------------------------------------------------------------------- /packages/generation/components/PaywallPopup/PaywallPopup.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationPaywallPopup } from '@tok/generation/defineConfig'; 2 | 3 | export type PaywallPopupProps = _GenerationPaywallPopup & { 4 | opened: boolean; 5 | }; 6 | 7 | export type PaywallPopupEmits = { 8 | (e: 'update:opened', value: boolean): void; 9 | (e: 'onSelect', value: string | undefined): void; 10 | }; 11 | 12 | const defaultButtons = [ 13 | { 14 | id: 'telegram_payments', 15 | media: { 16 | type: 'emodji' as const, 17 | src: '💳', 18 | }, 19 | type: 'default' as const, 20 | text: 'Bank card', 21 | }, 22 | { 23 | id: 'wallet_pay', 24 | media: { 25 | type: 'emodji' as const, 26 | src: '👛', 27 | }, 28 | type: 'default' as const, 29 | text: 'Wallet pay', 30 | }, 31 | ]; 32 | 33 | export const PaywallPopupDefaultProps = { 34 | type: 'telegram', 35 | title: 'Choose the payment method', 36 | message: '', 37 | buttons: () => defaultButtons, 38 | } as const; 39 | -------------------------------------------------------------------------------- /packages/generation/components/PaywallPopup/README.md: -------------------------------------------------------------------------------- 1 | # PaywallPopup 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | A wrapper around [TelegramPopup](../../../telegram-ui/components/TelegramPopup/README.md) with the ability to display a button-icon inside the web `Popup` component as specified in the [Media.preset](../Media/README.md). 7 | 8 | ## Props 9 | 10 | All available props see in [PaywallPopup.props.ts](./PaywallPopup.props.ts) 11 | 12 | ## i18n 13 | 14 | The component natively supports [i18n](../../../i18n/README.md) for text values inside buttons. 15 | 16 | You can provide a text as a locale token, and it will be dynamically translated 17 | -------------------------------------------------------------------------------- /packages/generation/components/PaywallPopup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PaywallPopup.props'; 2 | export { default as PaywallPopup } from './PaywallPopup.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitivePaywall/PrimitivePaywall.props.ts: -------------------------------------------------------------------------------- 1 | import type { PrimitiveSlideProps } from '@tok/generation/components/PrimitiveSlide'; 2 | import type { 3 | _GenerationPrimitivePaywallConfig, 4 | _GenerationPrimitivePaywallProduct, 5 | } from '@tok/generation/defineConfig'; 6 | 7 | export type PrimitivePaywallProps = Pick & 8 | _GenerationPrimitivePaywallConfig & { 9 | selectedProduct: _GenerationPrimitivePaywallProduct | null; 10 | }; 11 | 12 | export const PrimitivePaywallDefaultProps = { 13 | links: () => [], 14 | mainButtonText: 'Continue', 15 | } as const; 16 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitivePaywall/README.md: -------------------------------------------------------------------------------- 1 | # PaywallPopup 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component extends the [Slide.preset](../../presets/slide/README.md) component. 7 | 2. It overrides the default behavior of the MainButton inside the [Slide.preset](../../presets/slide/README.md) component. 8 | 3. It manages the MainButton with its own logic, including: 9 | - Translating the mainButtonText. 10 | - Replacing {price} inside the mainButtonText. 11 | - Displaying a popup with the payment method. 12 | - Tracking the selected product. 13 | - If a product isn't selected, the MainButton won't be displayed 14 | 4. It renders [Link](../../../ui/components/Link/README.md). 15 | 5. It sends data to the bot when the payment method is selected. 16 | 17 | ## Props 18 | 19 | All available props see in [PrimitivePaywall.props.ts](./PrimitivePaywall.props.ts) 20 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitivePaywall/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PrimitivePaywall.props'; 2 | export { default as PrimitivePaywall } from './PrimitivePaywall.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitiveSlide/PrimitiveSlide.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationSlideConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type PrimitiveSlideProps = Pick< 4 | _GenerationSlideConfig, 5 | 'media' | 'textAlign' | 'shape' | 'background' | 'button' | 'extends' 6 | > & { 7 | active?: boolean; 8 | }; 9 | 10 | export type PrimitiveSlideEmits = { 11 | (e: 'onClick'): void; 12 | }; 13 | 14 | export const PrimitiveSlideDefaultProps = { 15 | button: 'Next', 16 | textAlign: 'left', 17 | shape: 'square', 18 | } as const; 19 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitiveSlide/README.md: -------------------------------------------------------------------------------- 1 | # PrimitiveSlide 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component can render [Media.preset](../Media/README.md). 7 | 2. It manages the `textAlign` property inside the content section. 8 | 3. Can change the positioning of media and content depending on the `shape` prop 9 | 4. It handles [MainButton](../../../telegram-ui/components/MainButton/README.md) behavior, including text translation. 10 | 5. It triggers focus on a fake `div` element to initiate blur on inputs. 11 | 12 | ## Props 13 | 14 | All available props see in [PrimitiveSlide.props.ts](./PrimitiveSlide.props.ts) 15 | -------------------------------------------------------------------------------- /packages/generation/components/PrimitiveSlide/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PrimitiveSlide.props'; 2 | export { default as PrimitiveSlide } from './PrimitiveSlide.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/components/README.md: -------------------------------------------------------------------------------- 1 | # Components 2 | 3 | 1. [DrawPreset](./DrawPreset/README.md) 4 | 2. [ListItem](./ListItem/README.md) 5 | 3. [Media](./Media/README.md) 6 | 4. [PaywallPopup](./PaywallPopup/README.md) 7 | 5. [PrimitivePaywall](./PrimitiveSlide/README.md) 8 | 6. [PrimitiveSlide](./PrimitiveSlide/README.md) 9 | -------------------------------------------------------------------------------- /packages/generation/index.ts: -------------------------------------------------------------------------------- 1 | export { bootstrap } from './bootstrap'; 2 | export { defineConfig } from './defineConfig'; 3 | export { default as Root } from './Root.vue'; 4 | -------------------------------------------------------------------------------- /packages/generation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/generation", 3 | "version": "0.0.0", 4 | "main": "./index.ts", 5 | "types": "./index.ts", 6 | "dependencies": { 7 | "@tok/i18n": "*", 8 | "@tok/telegram-ui": "*", 9 | "@tok/ui": "*", 10 | "vue": "^3.3.4", 11 | "vue-router": "^4.2.5" 12 | }, 13 | "devDependencies": { 14 | "@tok/eslint-config": "*", 15 | "@tok/tsconfig": "*", 16 | "@types/node": "^20.8.0", 17 | "@types/pako": "^1.0.1", 18 | "@vitejs/plugin-vue": "^4.2.3", 19 | "pako": "1.0.11", 20 | "vite": "^4.4.9", 21 | "vite-svg-loader": "^4.0.0" 22 | } 23 | } -------------------------------------------------------------------------------- /packages/generation/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins 2 | 3 | 1. [definePresets](./definePresets/DefinePresets.plugin.ts) 4 | 5 | The main plugin for defining presets within an application generated using the `bootstrap` function 6 | 7 | 2. [formState](./formState/FormState.plugin.ts) 8 | 9 | Plugin for defining form state within an application generated using the `bootstrap` function 10 | 11 | 3. [theme](./theme/Theme.plugin.ts) 12 | 13 | Plugin for defining theme value within an application generated using the `bootstrap` function 14 | -------------------------------------------------------------------------------- /packages/generation/plugins/definePresets/DefinePresets.plugin.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DEFINED_PRESETS_TOKEN, 3 | predefinedPresets, 4 | } from '@tok/generation/tokens'; 5 | import { Plugin } from 'vue'; 6 | 7 | export const DefinePresetsPlugin: Plugin<{}> = { 8 | install(app, options) { 9 | app.provide(DEFINED_PRESETS_TOKEN, { 10 | ...predefinedPresets, 11 | ...options, 12 | }); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/generation/plugins/definePresets/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DefinePresets.plugin'; 2 | -------------------------------------------------------------------------------- /packages/generation/plugins/formState/FormState.plugin.ts: -------------------------------------------------------------------------------- 1 | import { FORM_STATE_TOKEN } from '@tok/generation/tokens'; 2 | import { App, Plugin, ref } from 'vue'; 3 | 4 | export const FormStatePlugin: Plugin = { 5 | install(app: App) { 6 | const state = ref>({}); 7 | 8 | const update = (value: Record) => { 9 | state.value = { 10 | ...state.value, 11 | ...value, 12 | }; 13 | }; 14 | 15 | app.provide(FORM_STATE_TOKEN, { state, update }); 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/generation/plugins/formState/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FormState.plugin'; 2 | -------------------------------------------------------------------------------- /packages/generation/plugins/theme/Theme.plugin.ts: -------------------------------------------------------------------------------- 1 | import { THEME_TOKEN, ThemeConfigParam } from '@tok/generation/tokens'; 2 | import { App, Plugin } from 'vue'; 3 | 4 | export const ThemePlugin: Plugin = { 5 | install(app: App, themeValue: ThemeConfigParam) { 6 | app.provide(THEME_TOKEN, themeValue); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/generation/plugins/theme/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Theme.plugin'; 2 | -------------------------------------------------------------------------------- /packages/generation/presets/Route.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | -------------------------------------------------------------------------------- /packages/generation/presets/base/README.md: -------------------------------------------------------------------------------- 1 | # Base.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is based on the [Carousel](../../../ui/components/Carousel/README.md) component. 7 | 2. It tracks the active index of the carousel and sets it into the query. 8 | 3. It safely restores the active index from the query. 9 | 4. It defines a safe accessor for the [CAROUSEL_ACCESSOR_TOKEN](../../use/README.md). 10 | 5. It renders presets using the [DrawPreset](../../components/DrawPreset/README.md) component. 11 | 12 | ## Props 13 | 14 | All available props see in [base.preset.props.ts](./base.preset.props.ts) 15 | -------------------------------------------------------------------------------- /packages/generation/presets/base/base.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationCarouselConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type BasePresetProps = _GenerationCarouselConfig; 4 | 5 | export const BasePresetDefaultProps = { 6 | slides: () => [], 7 | } as const; 8 | -------------------------------------------------------------------------------- /packages/generation/presets/base/index.ts: -------------------------------------------------------------------------------- 1 | export * from './base.preset.props'; 2 | export { default as BasePreset } from './base.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/form/README.md: -------------------------------------------------------------------------------- 1 | # Form.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is built upon the [Slide.preset](../slide/README.md) component. 7 | 2. It can render controls based on its configuration: 8 | - InputText (type="text") 9 | - InputText (type="number") 10 | - CheckboxBlock (type="checkbox") 11 | 3. It supports various types of inputs that can be configured within [defineConfig](../../defineConfig.ts), such as type="date." 12 | 4. It handles all controls and sets their values to the formState via [FORM_STATE_TOKEN](../../tokens/README.md). 13 | 5. It supports restoring values from the formState even when a control has been destroyed. 14 | 15 | ## Props 16 | 17 | All available props see in [form.preset.props.ts](./form.preset.props.ts) 18 | -------------------------------------------------------------------------------- /packages/generation/presets/form/form.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationFormConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type FormPresetProps = Omit<_GenerationFormConfig, 'extends'>; 4 | 5 | const defaultForm = [ 6 | { 7 | id: 'id1', 8 | placeholder: 'placeholder for type: text', 9 | type: 'text' as const, 10 | }, 11 | ]; 12 | 13 | export const FormPresetDefaultProps = { 14 | form: () => defaultForm, 15 | } as const; 16 | -------------------------------------------------------------------------------- /packages/generation/presets/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './form.preset.props'; 2 | export { default as FormPreset } from './form.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall/README.md: -------------------------------------------------------------------------------- 1 | # Paywall.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is built upon the [PrimitivePaywall.preset](../../components/PrimitivePaywall/README.md) component. 7 | 2. It can display products in a column, where only one can be selected. 8 | 3. It translates the title, description, and discount of the products. 9 | 10 | ## Props 11 | 12 | All available props see in [paywall.preset.props.ts](./paywall.preset.props.ts) 13 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall/index.ts: -------------------------------------------------------------------------------- 1 | export * from './paywall.preset.props'; 2 | export { default as PaywallPreset } from './paywall.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall/paywall.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationPaywallConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type PaywallPresetProps = Omit<_GenerationPaywallConfig, 'extends'>; 4 | 5 | export const PaywallPresetDefaultProps = { 6 | products: () => [], 7 | } as const; 8 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_row/README.md: -------------------------------------------------------------------------------- 1 | # PaywallRow.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is built upon the [PrimitivePaywall.preset](../../components/PrimitivePaywall/README.md) component. 7 | 2. It can display products in a **row**, where only one can be selected. 8 | 3. It translates the "title", "description", and "bestText" of the products. 9 | 4. It can detect the length of products to ensure user-friendly product selection behavior. 10 | 11 | ## Props 12 | 13 | All available props see in [paywall_row.preset.props.ts](./paywall_row.preset.props.ts) 14 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_row/index.ts: -------------------------------------------------------------------------------- 1 | export * from './paywall_row.preset.props'; 2 | export { default as PaywallRowPreset } from './paywall_row.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_row/paywall_row.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationPaywallRowConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type PaywallRowPresetProps = Omit< 4 | _GenerationPaywallRowConfig, 5 | 'extends' 6 | >; 7 | 8 | export const PaywallRowPresetDefaultProps = { 9 | products: () => [], 10 | } as const; 11 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_single/README.md: -------------------------------------------------------------------------------- 1 | # PaywallSingle.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is built upon the [PrimitivePaywall.preset](../../components/PrimitivePaywall/README.md) component. 7 | 2. It can display only one product, which is always selected. 8 | 3. It translates the title and description of the product. 9 | 10 | ## Props 11 | 12 | All available props see in [paywall_single.preset.props.ts](./paywall_single.preset.props.ts) 13 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_single/index.ts: -------------------------------------------------------------------------------- 1 | export * from './paywall_single.preset.props'; 2 | export { default as PaywallSinglePreset } from './paywall_single.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/paywall_single/paywall_single.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { _GenerationPaywallSingleConfig } from '@tok/generation/defineConfig'; 2 | 3 | export type PaywallSinglePresetProps = Omit< 4 | _GenerationPaywallSingleConfig, 5 | 'extends' 6 | >; 7 | 8 | const defaultProduct = { 9 | id: 'id1', 10 | title: 'Product Title', 11 | price: 99.99, 12 | description: 'Product description', 13 | }; 14 | 15 | export const PaywallSinglePresetDefaultProps = { 16 | product: () => defaultProduct, 17 | } as const; 18 | -------------------------------------------------------------------------------- /packages/generation/presets/slide/README.md: -------------------------------------------------------------------------------- 1 | # Slide.preset 2 | 3 | > [!NOTE] 4 | > This component is only intended for use with [bootstrap.ts](../../bootstrap.ts). 5 | 6 | 1. This component is based on the [PrimitiveSlide.preset](../../components/PrimitiveSlide/README.md) component. 7 | 2. It can display pagination if it's inside a carousel. 8 | 3. It translates the title and description of the slide. 9 | 4. It can render lists: 10 | - If the `list` prop is of type string[], it will add default media to every list item. 11 | 5. It handles MainButton.onClick to navigate to the next slide. 12 | 13 | ## Props 14 | 15 | All available props see in [slide.preset.props.ts](./slide.preset.props.ts) 16 | -------------------------------------------------------------------------------- /packages/generation/presets/slide/index.ts: -------------------------------------------------------------------------------- 1 | export * from './slide.preset.props'; 2 | export { default as SlidePreset } from './slide.preset.vue'; 3 | -------------------------------------------------------------------------------- /packages/generation/presets/slide/slide.preset.props.ts: -------------------------------------------------------------------------------- 1 | import type { PrimitiveSlideProps } from '@tok/generation/components/PrimitiveSlide'; 2 | import type { _GenerationSlideConfig } from '@tok/generation/defineConfig'; 3 | 4 | export type SlidePresetProps = PrimitiveSlideProps & 5 | Pick<_GenerationSlideConfig, 'title' | 'description' | 'pagination' | 'list'>; 6 | 7 | export const defaultSlideListMedia = { 8 | type: 'icon' as const, 9 | src: 'checkmark-fill', 10 | } as const; 11 | 12 | export const SlidePresetDefaultProps = { 13 | title: 'Title', 14 | description: '', 15 | list: () => [], 16 | } as const; 17 | -------------------------------------------------------------------------------- /packages/generation/tokens/README.md: -------------------------------------------------------------------------------- 1 | # Tokens 2 | 3 | 1. [definedPresets.token](./definedPresets.token.ts) 4 | 5 | Token that you can use to access all defined presets. Within definedPresets.token, you can find all the predefined presets that are used across all example projects 6 | 7 | 2. [formState.token](./formState.token.ts) 8 | 9 | Token that you can use to access the state of the form. This state will be populated with values inside the [form.preset](../presets/README.md). 10 | 11 | 3. [Theme.token](./theme.token.ts) 12 | 13 | Token that provides access to the theme variable defined within the `defineConfig` function 14 | 15 | 4. [wasInteraction.token](./wasInteraction.token.ts) 16 | 17 | Token that provides access to a boolean variable representing the first interaction on the page 18 | -------------------------------------------------------------------------------- /packages/generation/tokens/definedPresets.token.ts: -------------------------------------------------------------------------------- 1 | import { DefinedPresetsKeys } from '@tok/generation/defineConfig'; 2 | import { BasePreset } from '@tok/generation/presets/base'; 3 | import { SlidePreset } from '@tok/generation/presets/slide'; 4 | import { defineAsyncComponent, InjectionKey } from 'vue'; 5 | 6 | export type DefinePresets = Record< 7 | DefinedPresetsKeys, 8 | ReturnType 9 | >; 10 | 11 | export const predefinedPresets: DefinePresets = { 12 | base: BasePreset, 13 | slide: SlidePreset, 14 | paywall: defineAsyncComponent(() => 15 | import('@tok/generation/presets/paywall').then((m) => m.PaywallPreset) 16 | ), 17 | form: defineAsyncComponent(() => 18 | import('@tok/generation/presets/form').then((m) => m.FormPreset) 19 | ), 20 | paywall_single: defineAsyncComponent(() => 21 | import('@tok/generation/presets/paywall_single').then( 22 | (m) => m.PaywallSinglePreset 23 | ) 24 | ), 25 | paywall_row: defineAsyncComponent(() => 26 | import('@tok/generation/presets/paywall_row').then( 27 | (m) => m.PaywallRowPreset 28 | ) 29 | ), 30 | }; 31 | 32 | export const DEFINED_PRESETS_TOKEN = Symbol() as InjectionKey< 33 | Record 34 | >; 35 | -------------------------------------------------------------------------------- /packages/generation/tokens/formState.token.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue'; 2 | 3 | type State = { 4 | state: Ref>; 5 | update(value: Record): void; 6 | }; 7 | 8 | export const FORM_STATE_TOKEN = Symbol() as InjectionKey; 9 | -------------------------------------------------------------------------------- /packages/generation/tokens/index.ts: -------------------------------------------------------------------------------- 1 | export * from './definedPresets.token'; 2 | export * from './formState.token'; 3 | export * from './theme.token'; 4 | export * from './wasInteraction.token'; 5 | -------------------------------------------------------------------------------- /packages/generation/tokens/theme.token.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey } from 'vue'; 2 | 3 | export type ThemeConfigParam = 'light' | 'dark' | 'auto'; 4 | 5 | export const THEME_TOKEN = Symbol() as InjectionKey; 6 | -------------------------------------------------------------------------------- /packages/generation/tokens/wasInteraction.token.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue'; 2 | 3 | export const WAS_INTERACTION_TOKEN = Symbol() as InjectionKey>; 4 | -------------------------------------------------------------------------------- /packages/generation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | }, 8 | "types": ["pako", "@types/node", "vite/client"] 9 | }, 10 | "include": ["."], 11 | "exclude": ["dist", "build", "node_modules"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/generation/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | declare module '*.tgs' { 8 | export default TelegramStickerJson; 9 | } 10 | -------------------------------------------------------------------------------- /packages/generation/use/README.md: -------------------------------------------------------------------------------- 1 | # Use 2 | 3 | 1. [useCarouse](./carousel/index.ts) 4 | 5 | Provides you with access to [Carousel](../../ui/components/Carousel/README.md) inside [Base.preset.ts](../presets/README.md) for managing or reading `activeIndex`, `length` (for pagination), and safly setting `activeIndex` via `MainButton` or `BackButton`. 6 | 7 | ## Usage 8 | 9 | > [!IMPORTANT] 10 | > Ensure that you call this function within one of the 'children' of the Base.preset component or the component that defines the accessor for the `CAROUSEL_ACCESSOR_TOKEN`. Otherwise, the function will return `null` 11 | 12 | ```vue 13 | 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/generation/use/carousel/index.ts: -------------------------------------------------------------------------------- 1 | import { inject, InjectionKey, Ref } from 'vue'; 2 | 3 | type Accessor = { 4 | next: () => void; 5 | back: () => void; 6 | set: (index: number) => void; 7 | index: Ref; 8 | length: Ref; 9 | }; 10 | 11 | export const CAROUSEL_ACCESSOR_TOKEN = Symbol() as InjectionKey; 12 | 13 | export function useCarousel(): Accessor | null { 14 | const accessor = inject(CAROUSEL_ACCESSOR_TOKEN, null); 15 | 16 | if (accessor === null) { 17 | console.warn( 18 | 'You are using carousel methods outside of the carousel component' 19 | ); 20 | } 21 | 22 | return accessor; 23 | } 24 | -------------------------------------------------------------------------------- /packages/i18n/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/i18n/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugins'; 2 | export * from './use'; 3 | -------------------------------------------------------------------------------- /packages/i18n/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/i18n", 3 | "version": "0.0.0", 4 | "main": "./index.ts", 5 | "types": "./index.ts", 6 | "dependencies": { 7 | "vue": "^3.3.4" 8 | }, 9 | "devDependencies": { 10 | "@tok/eslint-config": "*", 11 | "@tok/tsconfig": "*" 12 | } 13 | } -------------------------------------------------------------------------------- /packages/i18n/plugins/index.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Plugin, Ref, ref } from 'vue'; 2 | 3 | type Loader> = Promise<{ default: T }>; 4 | 5 | type Options = { 6 | default: string; 7 | asyncLocales: Record; 8 | messages?: Record; 9 | }; 10 | 11 | export const TOK_I18N_TOKEN = Symbol() as InjectionKey<{ 12 | fallbackLocale: string; 13 | locale: Ref; 14 | loaders: Record; 15 | messages: Ref>; 16 | }>; 17 | 18 | export const TokI18nPlugin: Plugin = { 19 | install(app, options) { 20 | const locale = ref(options.default); 21 | const _messages = ref(options.messages || {}); 22 | 23 | app.provide(TOK_I18N_TOKEN, { 24 | fallbackLocale: options.default, 25 | locale, 26 | loaders: options.asyncLocales, 27 | messages: _messages, 28 | }); 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /packages/i18n/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | }, 8 | "types": ["pako", "@types/node", "vite/client"] 9 | }, 10 | "include": ["."], 11 | "exclude": ["dist", "build", "node_modules"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/i18n/use/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useI18n'; 2 | -------------------------------------------------------------------------------- /packages/telegram-ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/telegram-ui/README.md: -------------------------------------------------------------------------------- 1 | # @tok/telegram-ui 2 | 3 | This package offers a convenient wrapper around the [@twa-dev/sdk](https://github.com/twa-dev/SDK), providing Vue-like components and use-case solutions for Popups, MainButton, BackButton, and Theme integration. 4 | 5 | ## Components 6 | 7 | 1. [BackButton](./components/BackButton/README.md) 8 | 2. [MainButton](./components/MainButton/README.md) 9 | 3. [Sticker](./components/Sticker/README.md) 10 | 4. [TelegramPopup](./components/TelegramPopup/README.md) 11 | 12 | # Use 13 | 14 | ## [useTelegramSdk](./use/sdk/index.ts) 15 | 16 | Returns whole instance of [@twa-dev/sdk](https://github.com/twa-dev/SDK) 17 | 18 | ### Usage 19 | 20 | ```vue 21 | 29 | ``` 30 | 31 | ## [useTheme](./use/theme/index.ts) 32 | 33 | useTheme will track colorScheme from Telegram sdk in reactive way 34 | 35 | ### Usage 36 | 37 | ```vue 38 | 52 | ``` 53 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/BackButton/BackButton.props.ts: -------------------------------------------------------------------------------- 1 | import type { FlatButtonProps } from '@tok/ui/components/FlatButton'; 2 | 3 | export type BackButtonProps = { 4 | type?: 'telegram' | 'web'; 5 | 6 | show?: boolean; 7 | 8 | appearance?: FlatButtonProps['appearance']; 9 | }; 10 | 11 | export type BackButtonEmits = { 12 | (e: 'onClick'): void; 13 | }; 14 | 15 | export const BackButtonDefaultProps = { 16 | type: 'telegram', 17 | appearance: 'ghost', 18 | } as const; 19 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/BackButton/README.md: -------------------------------------------------------------------------------- 1 | # BackButton 2 | 3 | Wrapper around Telegram.BackButton with fallback to [FlatButton](../../../ui/components/FlatButton/README.md) 4 | 5 | We can determine whether the `TelegramSdk.BackButton` is displayed using 6 | the `TelegramSdk.BackButton.isVisible` property after calling the `TelegramSdk.BackButton.show()` method. 7 | If the `BackButton` is not available, we will display the `FlatButton` as a fallback. 8 | This can be useful during local development in a browser. 9 | 10 | You can easily switch between the telegram and web view modes if you prefer not to use `Telegram.BackButton`. 11 | 12 | By default, the type is set to 'telegram' 13 | 14 | ## Props 15 | 16 | All available props see in [BackButton.props.ts](./BackButton.props.ts) 17 | 18 | ## Usage 19 | 20 | ```vue 21 | 24 | 25 | 35 | ``` 36 | 37 | switch to FlatButton: 38 | 39 | ```vue 40 | 43 | 44 | 54 | ``` 55 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/BackButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BackButton.props'; 2 | export { default as BackButton } from './BackButton.vue'; 3 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/MainButton/MainButton.props.ts: -------------------------------------------------------------------------------- 1 | import type { HapticFeedback } from '@twa-dev/types'; 2 | 3 | type HapticStyle = Parameters[0]; 4 | 5 | export type MainButtonProps = { 6 | text: string; 7 | 8 | disabled?: boolean; 9 | 10 | progress?: boolean; 11 | 12 | color?: string; 13 | 14 | textColor?: string; 15 | 16 | keepAlive?: boolean; 17 | 18 | haptic?: HapticStyle; 19 | }; 20 | 21 | export type MainButtonEmits = { 22 | (e: 'onClick'): void; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/MainButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MainButton.props'; 2 | export { default as MainButton } from './MainButton.vue'; 3 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/Sticker/Sticker.props.ts: -------------------------------------------------------------------------------- 1 | export type StickerProps = { 2 | json: TelegramStickerJson; 3 | 4 | autoplay?: boolean; 5 | 6 | loop?: boolean; 7 | 8 | speed?: number; 9 | 10 | playOnClick?: boolean; 11 | }; 12 | 13 | export const StickerDefaultProps = { 14 | autoplay: true, 15 | loop: true, 16 | speed: 1, 17 | playOnClick: true, 18 | } as const; 19 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/Sticker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Sticker.props'; 2 | export { default as Sticker } from './Sticker.vue'; 3 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/TelegramPopup/TelegramPopup.props.ts: -------------------------------------------------------------------------------- 1 | import { PopupButton } from '@twa-dev/types'; 2 | 3 | export type TelegramPopupProps = { 4 | type?: 'web' | 'telegram'; 5 | modelValue: boolean; 6 | title: string; 7 | message?: string; 8 | buttons: T[]; 9 | }; 10 | 11 | export type TelegramPopupEmits = { 12 | (e: 'update:modelValue', value: boolean): void; 13 | (e: 'onSelect', value: string | undefined): void; 14 | }; 15 | 16 | export type TelegramPopupSlots = { 17 | 'button-icon'?: (props: { item: T }) => void; 18 | }; 19 | 20 | const buttons: PopupButton[] = []; 21 | 22 | export const TelegramPopupDefaultProps = { 23 | title: '', 24 | message: '', 25 | type: 'telegram', 26 | buttons: () => buttons, 27 | } as const; 28 | -------------------------------------------------------------------------------- /packages/telegram-ui/components/TelegramPopup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TelegramPopup.props'; 2 | export { default as TelegramPopup } from './TelegramPopup.vue'; 3 | -------------------------------------------------------------------------------- /packages/telegram-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/telegram-ui", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "@tok/ui": "*", 6 | "@twa-dev/sdk": "^6.9.0", 7 | "lottie-web": "^5.12.2", 8 | "vue": "^3.3.4", 9 | "vue-router": "^4.2.5" 10 | }, 11 | "devDependencies": { 12 | "@tok/eslint-config": "*", 13 | "@tok/tsconfig": "*" 14 | } 15 | } -------------------------------------------------------------------------------- /packages/telegram-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/telegram-ui/types/tgs.d.ts: -------------------------------------------------------------------------------- 1 | declare type TelegramStickerJson = { 2 | tgs: number; 3 | v: string; 4 | fr: number; 5 | }; 6 | 7 | // TODO: Find a way to set this type once 8 | // instead of copying and pasting it from project to project. 9 | declare module '*.tgs' { 10 | export default TelegramStickerJson; 11 | } 12 | -------------------------------------------------------------------------------- /packages/telegram-ui/use/sdk/index.ts: -------------------------------------------------------------------------------- 1 | import Telegram from '@twa-dev/sdk'; 2 | 3 | export function useTelegramSdk() { 4 | return Telegram; 5 | } 6 | -------------------------------------------------------------------------------- /packages/telegram-ui/use/theme/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useTheme'; 2 | -------------------------------------------------------------------------------- /packages/telegram-ui/use/theme/useTheme.ts: -------------------------------------------------------------------------------- 1 | import { useTelegramSdk } from '@tok/telegram-ui/use/sdk'; 2 | import { onBeforeUnmount, onMounted, ref } from 'vue'; 3 | 4 | export function useTheme(value: 'light' | 'dark' | 'auto' = 'auto') { 5 | const sdk = useTelegramSdk(); 6 | 7 | const init = value === 'auto' ? sdk.colorScheme : value; 8 | 9 | const theme = ref(init); 10 | 11 | const onThemeChange = () => { 12 | theme.value = sdk.colorScheme; 13 | }; 14 | 15 | onMounted(() => { 16 | if (value === 'auto') { 17 | sdk.onEvent('themeChanged', onThemeChange); 18 | } 19 | }); 20 | 21 | onBeforeUnmount(() => { 22 | sdk.offEvent('themeChanged', onThemeChange); 23 | }); 24 | 25 | return theme; 26 | } 27 | -------------------------------------------------------------------------------- /packages/tsconfig/README.md: -------------------------------------------------------------------------------- 1 | # @tok/tsconfig 2 | 3 | Basic tsconfig.json for your applications 4 | 5 | ## Usage 6 | 7 | 1. Run the following command: 8 | 9 | ```bash 10 | npm i @tok/tsconfig --save-dev --workspace= 11 | ``` 12 | 13 | 2. Create a `tsconfig.json` file within your app. 14 | 15 | 3. Add the following default configuration to the `tsconfig.json` file: 16 | 17 | ```json 18 | { 19 | "extends": "@tok/tsconfig/tsconfig.base.json", 20 | "include": ["."], 21 | "exclude": ["dist", "build", "node_modules"] 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "composite": false, 5 | "declaration": true, 6 | "declarationMap": true, 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "inlineSources": false, 10 | "isolatedModules": true, 11 | "moduleResolution": "node", 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "preserveWatchOutput": true, 15 | "skipLibCheck": true, 16 | "resolveJsonModule": true, 17 | "strict": true, 18 | "target": "esnext", 19 | "module": "esnext", 20 | "jsx": "preserve", 21 | "importHelpers": true, 22 | "allowSyntheticDefaultImports": true, 23 | "sourceMap": false, 24 | "removeComments": true, 25 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"], 26 | "types": ["vite/client"] 27 | }, 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /packages/ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@tok/eslint-config'], 4 | parserOptions: { tsconfigRootDir: __dirname }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/ui/components/Alert/Alert.props.ts: -------------------------------------------------------------------------------- 1 | import { Component, VNode } from 'vue'; 2 | 3 | export type AlertProps = { 4 | type?: 'success' | 'error' | 'telegram' | string; 5 | 6 | // The "content" property can be a string or another component, and it will receive the "context" prop. 7 | content?: string | Component; 8 | 9 | // The "closable" property determines whether the alert can be closed or not. 10 | closable?: boolean; 11 | 12 | // You can pass data to the "content" as a component through the "data" property. 13 | data?: T; 14 | }; 15 | 16 | // helper type to get correct context inside your component in alert 17 | /* 18 | Usage: 19 | CustomAlert.vue: 20 | 21 | 26 | 27 | type Data = { 28 | sayHello?: boolean; 29 | }; 30 | 31 | defineProps>(); 32 | */ 33 | export type AlertContextProps = { 34 | context: { 35 | close: () => void; 36 | data: T; 37 | }; 38 | }; 39 | 40 | export type AlertSlots = { 41 | default?: (props: {}) => ReadonlyArray; 42 | }; 43 | 44 | export type AlertEmits = { 45 | (e: 'close'): void; 46 | }; 47 | 48 | export const AlertDefaultProps = { 49 | type: 'success', 50 | } as const; 51 | -------------------------------------------------------------------------------- /packages/ui/components/Alert/README.md: -------------------------------------------------------------------------------- 1 | # Alert Component 2 | 3 | The component is used in the [useAlerts()](../../use/alerts/README.md) function 4 | 5 | > [!IMPORTANT] 6 | > To make useAlerts() work, it is essential to wrap your entire application in the [Root](../Root/README.md) component 7 | 8 | ## Props 9 | 10 | All available props see in [Alert.props.ts](./Alert.props.ts) 11 | 12 | ## Usage 13 | 14 | ```vue 15 | 19 | 20 | 23 | ``` 24 | 25 | ## Customization 26 | 27 | ```vue 28 | 31 | 32 | 35 | ``` 36 | 37 | ```scss 38 | /* global.styles.scss */ 39 | .tok-alert { 40 | &[data-type='custom'] { 41 | background: red; 42 | color: white; 43 | 44 | .tok-alert { 45 | // color for icon 46 | &-icon { 47 | color: white; 48 | } 49 | 50 | // color for close icon 51 | &-close { 52 | color: black; 53 | } 54 | } 55 | } 56 | } 57 | ``` 58 | 59 | or inside other component with style in scoped mode 60 | 61 | ```vue 62 | 67 | 68 | 71 | 72 | 81 | ``` 82 | -------------------------------------------------------------------------------- /packages/ui/components/Alert/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Alert.props'; 2 | export { default as Alert } from './Alert.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Carousel/Carousel.props.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue'; 2 | 3 | export type CarouselProps = { 4 | // Current index 5 | modelValue: number; 6 | 7 | // Number of slides shown at the same time 8 | itemsCount: number; 9 | 10 | // Elements inside carousel 11 | items: ReadonlyArray; 12 | 13 | /* 14 | Whether or not slider can be dragged by clicking and holding 15 | 16 | This parameter only works on desktop devices and is ignored on mobile devices. 17 | The determination of whether the device is mobile is made through the `isMobile` function 18 | */ 19 | draggable?: boolean; 20 | 21 | /* 22 | Number of pixels that must be traversed before the carousel recognizes a dragging action 23 | It's helpful when there's a scrollable element inside the carousel 24 | */ 25 | threshold?: number; 26 | 27 | // Custom padding between elements 28 | paddingPx?: number; 29 | }; 30 | 31 | export type CarouselEmits = { 32 | // update current index 33 | (e: 'update:modelValue', value: number): void; 34 | }; 35 | 36 | export type CarouselSlots = { 37 | default: (props: { item: T; index: number }) => ReadonlyArray; 38 | }; 39 | 40 | export type CarouselExpose = { 41 | next: () => void; 42 | back: () => void; 43 | }; 44 | 45 | export const CarouselDefaultProps = { 46 | draggable: false, 47 | threshold: 0, 48 | paddingPx: 8, 49 | } as const; 50 | -------------------------------------------------------------------------------- /packages/ui/components/Carousel/README.md: -------------------------------------------------------------------------------- 1 | # Carousel 2 | 3 | Allows you to rotate through arbitrary items. 4 | 5 | Multiple items can be shown simultaneously 6 | 7 | ## Props 8 | 9 | All available props see in [Carousel.props.ts](./Carousel.props.ts) 10 | 11 | ## Usage 12 | 13 | ```vue 14 | 28 | 29 | 60 | ``` 61 | -------------------------------------------------------------------------------- /packages/ui/components/Carousel/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Carousel.props'; 2 | export { default as Carousel } from './Carousel.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/CheckboxBlock/CheckboxBlock.props.ts: -------------------------------------------------------------------------------- 1 | export type CheckboxBlockProps = { 2 | modelValue: boolean | null; 3 | 4 | placeholder?: string; 5 | 6 | size?: 's' | 'm' | 'l' | string; 7 | 8 | shape?: 'rounded' | string; 9 | 10 | disabled?: boolean; 11 | 12 | invalid?: boolean; 13 | }; 14 | 15 | export type CheckboxBlockEmits = { 16 | (e: 'update:modelValue', v: boolean): void; 17 | }; 18 | 19 | export const CheckboxBlockDefaultProps = { 20 | placeholder: '', 21 | size: 'm', 22 | } as const; 23 | -------------------------------------------------------------------------------- /packages/ui/components/CheckboxBlock/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CheckboxBlock.props'; 2 | export { default as CheckboxBlock } from './CheckboxBlock.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/FlatButton/FlatButton.props.ts: -------------------------------------------------------------------------------- 1 | import type { SvgIconProps } from '@tok/ui/components/SvgIcon'; 2 | import type { RouteLocationRaw } from 'vue-router'; 3 | 4 | export type FlatButtonProps = { 5 | size?: 'xs' | 's' | 'm' | 'l' | string; 6 | icon?: string; 7 | rotate?: boolean; 8 | iconRight?: string; 9 | rightRotate?: boolean; 10 | shape?: 'square' | 'rounded' | null; 11 | appearance?: 'primary' | 'secondary' | 'ghost' | string; 12 | loading?: boolean; 13 | disabled?: boolean; 14 | iconButton?: boolean; 15 | href?: string; 16 | to?: RouteLocationRaw; 17 | 18 | iconSize?: SvgIconProps['size']; 19 | }; 20 | 21 | export const FlatButtonDefaultProps = { 22 | size: 'm', 23 | appearance: 'primary', 24 | shape: null, 25 | } as const; 26 | -------------------------------------------------------------------------------- /packages/ui/components/FlatButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FlatButton.props'; 2 | export { default as FlatButton } from './FlatButton.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/InputText/InputText.props.ts: -------------------------------------------------------------------------------- 1 | export type InputTextProps = { 2 | modelValue: T; 3 | size?: 's' | 'm' | 'l'; 4 | placeholder?: string; 5 | type?: string; 6 | autocomplete?: string; 7 | name?: string; 8 | disabled?: boolean; 9 | invalid?: boolean; 10 | inputmode?: 11 | | 'text' 12 | | 'search' 13 | | 'none' 14 | | 'tel' 15 | | 'url' 16 | | 'email' 17 | | 'numeric' 18 | | 'decimal' 19 | | undefined; 20 | hasCleaner?: boolean; 21 | }; 22 | 23 | export type InputTextEmits = { 24 | (e: 'update:modelValue', value: string | null): void; 25 | }; 26 | 27 | export const InputTextDefaultProps = { 28 | type: 'text', 29 | size: 'm', 30 | inputmode: 'text', 31 | hasCleaner: true, 32 | placeholder: '', 33 | } as const; 34 | -------------------------------------------------------------------------------- /packages/ui/components/InputText/index.ts: -------------------------------------------------------------------------------- 1 | export * from './InputText.props'; 2 | export { default as InputText } from './InputText.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Link/Link.props.ts: -------------------------------------------------------------------------------- 1 | export type LinkProps = { 2 | text: string; 3 | 4 | href: string; 5 | 6 | target?: string; 7 | }; 8 | 9 | export const LinkDefaultProps = { 10 | text: '', 11 | target: '_blank', 12 | } as const; 13 | -------------------------------------------------------------------------------- /packages/ui/components/Link/Link.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 25 | 26 | 31 | -------------------------------------------------------------------------------- /packages/ui/components/Link/README.md: -------------------------------------------------------------------------------- 1 | # Link 2 | 3 | ## Props 4 | 5 | All available props see in [Link.props.ts](./Link.props.ts) 6 | 7 | ## Figma 8 | 9 | [Component in figma project](https://www.figma.com/file/ssQqPZ2vqZhD4QF2xyCTd2/Telegram-Onboarding--ToolKit?type=design&node-id=154-5782&mode=design&t=6yuiDJRdwfFJ7dVT-0) 10 | 11 | ## i18n 12 | 13 | The component natively supports [i18n](../../../i18n/README.md) for text and href values. 14 | 15 | You can provide a text and href as a locale token, and it will be dynamically translated 16 | 17 | ## Usage 18 | 19 | ```vue 20 | 23 | 24 | 27 | ``` 28 | -------------------------------------------------------------------------------- /packages/ui/components/Link/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Link.props'; 2 | export { default as Link } from './Link.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Money/Money.props.ts: -------------------------------------------------------------------------------- 1 | export type MoneyProps = { value: number | string }; 2 | -------------------------------------------------------------------------------- /packages/ui/components/Money/Money.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/Money/README.md: -------------------------------------------------------------------------------- 1 | # Money 2 | 3 | Money transforms and shows money sum. There are some ways to show currency symbol and various decimal settings 4 | 5 | ## Props 6 | 7 | All available props see in [Money.props.ts](./Money.props.ts) 8 | 9 | ## i18n 10 | 11 | The component natively supports [i18n](../../../i18n/README.md) for currency config and value prop. 12 | 13 | You can provide a currency config and value with a locale tokens, and it will be dynamically translated 14 | 15 | ## Usage 16 | 17 | ```vue 18 | 21 | 22 | 36 | ``` 37 | 38 | ### i18n 39 | 40 | ```vue 41 | 44 | 45 | 63 | ``` 64 | -------------------------------------------------------------------------------- /packages/ui/components/Money/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Money } from './Money.vue'; 2 | -------------------------------------------------------------------------------- /packages/ui/components/Pagination/Pagination.props.ts: -------------------------------------------------------------------------------- 1 | export type PaginationProps = { 2 | // Active page index 3 | modelValue: number; 4 | 5 | // Total pages count 6 | length: number; 7 | }; 8 | 9 | export type PaginationEmits = { 10 | (e: 'update:modelValue', value: number): void; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ui/components/Pagination/README.md: -------------------------------------------------------------------------------- 1 | # Pagination 2 | 3 | Pagination component enables the user to select a specific page from a range of pages 4 | 5 | ## Props 6 | 7 | All available props see in [Pagination.props.ts](./Pagination.props.ts) 8 | 9 | ## Figma 10 | 11 | [Component in figma project](https://www.figma.com/file/ssQqPZ2vqZhD4QF2xyCTd2/Telegram-Onboarding--ToolKit?type=design&node-id=154-5776&mode=design&t=6yuiDJRdwfFJ7dVT-0) 12 | 13 | ## Usage 14 | 15 | ```vue 16 | 19 | 20 | 26 | ``` 27 | -------------------------------------------------------------------------------- /packages/ui/components/Pagination/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Pagination.props'; 2 | export { default as Pagination } from './Pagination.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Popup/Popup.props.ts: -------------------------------------------------------------------------------- 1 | export type PopupProps = { 2 | modelValue: boolean; 3 | 4 | title: string; 5 | 6 | message?: string; 7 | }; 8 | 9 | export type PopupEmits = { 10 | (event: 'update:modelValue', value: boolean): void; 11 | }; 12 | 13 | export const PopupDefaultProps = { 14 | modelValue: false, 15 | title: '', 16 | message: '', 17 | } as const; 18 | -------------------------------------------------------------------------------- /packages/ui/components/Popup/README.md: -------------------------------------------------------------------------------- 1 | # Popup 2 | 3 | Optional built-in implementation of modals 4 | 5 | > [!IMPORTANT] 6 | > To make popups work, it is essential to wrap your entire application in the [Root](../Root/README.md) component 7 | 8 | ## Props 9 | 10 | All available props see in [Popup.props.ts](./Popup.props.ts) 11 | 12 | ## i18n 13 | 14 | The component natively supports [i18n](../../../i18n/README.md) for **title** and **message** prop. 15 | 16 | You can provide a title and message with a locale tokens, and it will be dynamically translated 17 | 18 | ## Usage 19 | 20 | ```vue 21 | 26 | 27 | 38 | ``` 39 | -------------------------------------------------------------------------------- /packages/ui/components/Popup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Popup.props'; 2 | export { default as Popup } from './Popup.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Portal/Portal.props.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue'; 2 | 3 | export type PortalProps = { 4 | appendTo?: '#tok-popups-host' | '#tok-alerts-host' | string; 5 | }; 6 | 7 | export type PortalSlots = { 8 | default: (props: {}) => ReadonlyArray; 9 | }; 10 | 11 | export const PortalDefaultProps = { 12 | appendTo: 'body', 13 | } as const; 14 | -------------------------------------------------------------------------------- /packages/ui/components/Portal/Portal.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /packages/ui/components/Portal/README.md: -------------------------------------------------------------------------------- 1 | # Portal 2 | 3 | Primitive wrapper around Vue Teleport component 4 | 5 | ## Props 6 | 7 | All available props see in [Portal.props.ts](./Portal.props.ts) 8 | -------------------------------------------------------------------------------- /packages/ui/components/Portal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Portal.props'; 2 | export { default as Portal } from './Portal.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveCheckbox/PrimitiveCheckbox.props.ts: -------------------------------------------------------------------------------- 1 | export type PrimitiveCheckboxProps = { value: boolean | null }; 2 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveCheckbox/PrimitiveCheckbox.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 51 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveCheckbox/README.md: -------------------------------------------------------------------------------- 1 | # PrimitiveCheckbox 2 | 3 | Static checkbox for usage outside forms as visual indicator without focusing and clicking 4 | 5 | ## Props 6 | 7 | All available props see in [PrimitiveCheckbox.props.ts](./PrimitiveCheckbox.props.ts) 8 | 9 | ## Figma 10 | 11 | [Component in figma project](https://www.figma.com/file/ssQqPZ2vqZhD4QF2xyCTd2/Telegram-Onboarding--ToolKit?type=design&node-id=139-1043&mode=design&t=6yuiDJRdwfFJ7dVT-0) 12 | 13 | ## Usage 14 | 15 | ```vue 16 | 21 | 22 | 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveCheckbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PrimitiveCheckbox.props'; 2 | export { default as PrimitiveCheckbox } from './PrimitiveCheckbox.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveRadio/PrimitiveRadio.props.ts: -------------------------------------------------------------------------------- 1 | export type PrimitiveRadioProps = { 2 | value: boolean; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveRadio/PrimitiveRadio.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 53 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveRadio/README.md: -------------------------------------------------------------------------------- 1 | # PrimitiveRadio 2 | 3 | Static radio for usage outside forms as visual indicator without focusing and clicking 4 | 5 | ## Props 6 | 7 | All available props see in [PrimitiveRadio.props.ts](./PrimitiveRadio.props.ts) 8 | 9 | ## Figma 10 | 11 | [Component in figma project](https://www.figma.com/file/ssQqPZ2vqZhD4QF2xyCTd2/Telegram-Onboarding--ToolKit?type=design&node-id=139-1044&mode=design&t=4lD7Uxk1RttOTrGK-0) 12 | 13 | ## Usage 14 | 15 | ```vue 16 | 21 | 22 | 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/ui/components/PrimitiveRadio/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PrimitiveRadio.props'; 2 | export { default as PrimitiveRadio } from './PrimitiveRadio.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui components 2 | 3 | ## Components 4 | 5 | 1. [Alert](./Alert/README.md) 6 | 2. [Carousel](./Carousel/README.md) 7 | 3. [CheckboxBlock](./CheckboxBlock/README.md) 8 | 4. [FlatButton](./FlatButton/README.md) 9 | 5. [InputText](./InputText/README.md) 10 | 6. [Link](./Link/README.md) 11 | 7. [Money](./Money/README.md) 12 | 8. [Pagination](./Pagination/README.md) 13 | 9. [Popup](./Popup/README.md) 14 | 10. [Portal](./Portal/README.md) 15 | 11. [PrimitiveCheckbox](./PrimitiveCheckbox/README.md) 16 | 12. [PrimitiveRadio](./PrimitiveRadio/README.md) 17 | 13. [Root](./Root/README.md) 18 | 14. [SvgIcon](./SvgIcon/README.md) 19 | 15. [Toggle](./Toggle/README.md) 20 | -------------------------------------------------------------------------------- /packages/ui/components/Root/PopupsHost.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 43 | 44 | 90 | -------------------------------------------------------------------------------- /packages/ui/components/Root/README.md: -------------------------------------------------------------------------------- 1 | # Root 2 | 3 | This component uses the full power of Vue.Teleport, creating layers within the application for consistent rendering of [Alerts](../../use/alerts/README.md) and [Popups](../Popup/README.md) 4 | 5 | ## Props 6 | 7 | All available props see in [Root.props.ts](./Root.props.ts) 8 | 9 | ## Usage 10 | 11 | Wrap all content of your app with root component 12 | 13 | ```vue 14 | 15 | 21 | 22 | 25 | ``` 26 | 27 | If you need, you can add something between portal layers: 28 | 29 | ```vue 30 | 31 | 49 | 50 | 53 | ``` 54 | -------------------------------------------------------------------------------- /packages/ui/components/Root/Root.props.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue'; 2 | 3 | export type RootSlots = { 4 | default: (props: {}) => ReadonlyArray; 5 | 6 | overContent?: (props: {}) => ReadonlyArray; 7 | 8 | overPopups?: (props: {}) => ReadonlyArray; 9 | 10 | overAlerts?: (props: {}) => ReadonlyArray; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ui/components/Root/Root.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /packages/ui/components/Root/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Root } from './Root.vue'; 2 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/SvgIcon.props.ts: -------------------------------------------------------------------------------- 1 | export type SvgIconProps = { 2 | name: string; 3 | 4 | size?: number | [number, number]; 5 | 6 | rotate?: boolean; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/checkmark-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/spinner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/icons/warning-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/components/SvgIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SvgIcon.props'; 2 | export { default as SvgIcon } from './SvgIcon.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/components/Toggle/Toggle.props.ts: -------------------------------------------------------------------------------- 1 | export type ToggleProps = { 2 | modelValue: boolean; 3 | 4 | id?: string; 5 | 6 | size?: 's' | 'm' | string; 7 | 8 | disabled?: boolean; 9 | }; 10 | 11 | export type ToggleEmits = { 12 | (e: 'update:modelValue', value: boolean): void; 13 | }; 14 | 15 | export const ToggleDefaultProps = { 16 | size: 'm', 17 | } as const; 18 | -------------------------------------------------------------------------------- /packages/ui/components/Toggle/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Toggle.props'; 2 | export { default as Toggle } from './Toggle.vue'; 3 | -------------------------------------------------------------------------------- /packages/ui/consts/chars.ts: -------------------------------------------------------------------------------- 1 | export const CHAR_NO_BREAK_SPACE = '\u00A0'; 2 | export const CHAR_COMMA = '\u002C'; 3 | -------------------------------------------------------------------------------- /packages/ui/consts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chars'; 2 | -------------------------------------------------------------------------------- /packages/ui/directives/dragdrop/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dragDrop.directive'; 2 | -------------------------------------------------------------------------------- /packages/ui/directives/intersection/index.ts: -------------------------------------------------------------------------------- 1 | export * from './intersection.directive'; 2 | -------------------------------------------------------------------------------- /packages/ui/directives/intersection/intersection.directive.ts: -------------------------------------------------------------------------------- 1 | import { DirectiveBinding, ObjectDirective } from 'vue'; 2 | 3 | type Binding = { 4 | onEvent: IntersectionObserverCallback; 5 | options?: IntersectionObserverInit; 6 | }; 7 | 8 | const OPTIONS: IntersectionObserverInit = { 9 | threshold: 1.0, 10 | } as const; 11 | 12 | const dict = new Map(); 13 | 14 | function mounted(element: HTMLElement, { value }: DirectiveBinding) { 15 | if (!(window && 'IntersectionObserver' in window)) { 16 | return; 17 | } 18 | 19 | const { options = OPTIONS } = value; 20 | 21 | const observer = new IntersectionObserver(value.onEvent, options); 22 | 23 | observer.observe(element); 24 | 25 | dict.set(element, observer); 26 | } 27 | 28 | function beforeUnmount(element: HTMLElement) { 29 | const observer = dict.get(element); 30 | 31 | observer?.disconnect(); 32 | 33 | dict.delete(element); 34 | } 35 | 36 | export const IntersectionDirective: ObjectDirective = { 37 | mounted, 38 | beforeUnmount, 39 | }; 40 | -------------------------------------------------------------------------------- /packages/ui/directives/ripple/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ripple'; 2 | -------------------------------------------------------------------------------- /packages/ui/directives/swipe/index.ts: -------------------------------------------------------------------------------- 1 | export * from './swipe.directive'; 2 | -------------------------------------------------------------------------------- /packages/ui/dom/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui dom helpers 2 | 3 | ## [1. Focus](./focus/index.ts) 4 | 5 | Utility functions that can help you in triggering focus and blur events on elements 6 | 7 | ## [2. Platform](./platform/index.ts) 8 | 9 | Utility functions that can help you in detecting mobile devices based on the criteria outlined in [this](https://stackoverflow.com/a/11381730/2706426) and [this](http://detectmobilebrowsers.com/) 10 | -------------------------------------------------------------------------------- /packages/ui/dom/focus/blurNativeFocused.ts: -------------------------------------------------------------------------------- 1 | import { getNativeFocused } from './getNativeFocused'; 2 | import { setNativeFocused } from './setNativeFocused'; 3 | 4 | export function blurNativeFocused() { 5 | const activeElement = getNativeFocused(); 6 | 7 | if (activeElement instanceof HTMLElement) { 8 | setNativeFocused(activeElement, false); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/ui/dom/focus/getNativeFocused.ts: -------------------------------------------------------------------------------- 1 | export function getNativeFocused( 2 | documentRef: Document = document 3 | ): Element | null { 4 | if (!documentRef.activeElement || !documentRef.activeElement.shadowRoot) { 5 | return documentRef.activeElement; 6 | } 7 | 8 | let element = documentRef.activeElement.shadowRoot.activeElement; 9 | 10 | while (element && element.shadowRoot) { 11 | element = element.shadowRoot.activeElement; 12 | } 13 | 14 | return element; 15 | } 16 | -------------------------------------------------------------------------------- /packages/ui/dom/focus/index.ts: -------------------------------------------------------------------------------- 1 | export * from './blurNativeFocused'; 2 | export * from './getNativeFocused'; 3 | export * from './setNativeFocused'; 4 | -------------------------------------------------------------------------------- /packages/ui/dom/focus/setNativeFocused.ts: -------------------------------------------------------------------------------- 1 | export function setNativeFocused( 2 | element: HTMLElement, 3 | focused = true, 4 | preventScroll = false 5 | ) { 6 | if (focused) { 7 | element.focus({ preventScroll }); 8 | } else { 9 | element.blur(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/ui/dom/index.ts: -------------------------------------------------------------------------------- 1 | export * from './focus'; 2 | export * from './platform'; 3 | -------------------------------------------------------------------------------- /packages/ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tok/ui", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "vue": "^3.3.4", 6 | "vue-router": "^4.2.5" 7 | }, 8 | "devDependencies": { 9 | "@tok/eslint-config": "*", 10 | "@tok/tsconfig": "*", 11 | "sass": "^1.62.1" 12 | } 13 | } -------------------------------------------------------------------------------- /packages/ui/plugins/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui plugins 2 | 3 | # 1. [Alerts](./alerts/Alerts.plugin.ts) 4 | 5 | Required plugin to enable [useAlerts](../use/alerts/README.md) functionality 6 | 7 | ## Usage 8 | 9 | ```ts 10 | // main.ts 11 | import { createApp } from 'vue'; 12 | import App from './App.vue'; 13 | import { AlertsPlugin } from '@tok/ui/plugins/alerts'; 14 | 15 | createApp(App).use(AlertsPlugin).mount('#app'); 16 | ``` 17 | 18 | # 2. [Currency](./currency/currency.plugin.ts) 19 | 20 | Allows you to globally configure options for [Money component](../components/Money/README.md) 21 | 22 | ## Usage 23 | 24 | ```ts 25 | // main.ts 26 | import { createApp } from 'vue'; 27 | import App from './App.vue'; 28 | import { CurrencyPlugin } from '@tok/ui/plugins/currency'; 29 | 30 | const currencyOptions = { 31 | // currency symbol alignment 32 | // default: 'left' 33 | align?: 'left' | 'right'; 34 | 35 | // currency symbol 36 | // default: 'USD' 37 | currency?: CurrencyVariants; 38 | 39 | // separator for decimal 1.00 or 1,00 as you wish 40 | // default '.' 41 | decimalSeparator?: string; 42 | 43 | // separator for thousand 1_000_000 or 1x000x000 44 | // default ' ' 45 | thousandSeparator?: string; 46 | }; 47 | 48 | createApp(App).use(CurrencyPlugin, currencyOptions).mount('#app'); 49 | ``` 50 | -------------------------------------------------------------------------------- /packages/ui/plugins/alerts/Alerts.plugin.ts: -------------------------------------------------------------------------------- 1 | import { ALERTS_HOST_TOKEN, createAlertsConnector } from '@tok/ui/tokens'; 2 | import { App, Plugin } from 'vue'; 3 | 4 | const install = (app: App) => { 5 | const connector = createAlertsConnector(); 6 | 7 | app.provide(ALERTS_HOST_TOKEN, connector); 8 | }; 9 | 10 | export const AlertsPlugin: Plugin = { 11 | install, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/ui/plugins/alerts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Alerts.plugin'; 2 | -------------------------------------------------------------------------------- /packages/ui/plugins/currency/currency.plugin.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CURRENCY_OPTIONS_TOKEN, 3 | CurrencyOptions, 4 | defaultCurrencyOptions, 5 | } from '@tok/ui/tokens'; 6 | import { Plugin } from 'vue'; 7 | 8 | export const CurrencyPlugin: Plugin = { 9 | install(app, options: CurrencyOptions) { 10 | app.provide(CURRENCY_OPTIONS_TOKEN, { 11 | ...defaultCurrencyOptions, 12 | ...options, 13 | }); 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/ui/plugins/currency/index.ts: -------------------------------------------------------------------------------- 1 | export * from './currency.plugin'; 2 | -------------------------------------------------------------------------------- /packages/ui/styles/local.scss: -------------------------------------------------------------------------------- 1 | @mixin clearbutton() { 2 | appearance: none; 3 | padding: 0; 4 | border: 0; 5 | background: none; 6 | font-size: inherit; 7 | line-height: inherit; 8 | 9 | &:focus, 10 | &:active { 11 | outline: none; 12 | } 13 | } 14 | 15 | @mixin transition($prop, $duration: 0.2s, $timing: ease-in-out) { 16 | transition: $prop $duration $timing; 17 | } 18 | 19 | @mixin size($width, $height) { 20 | min-width: $width; 21 | min-height: $height; 22 | 23 | width: $width; 24 | height: $height; 25 | 26 | max-width: $width; 27 | max-height: $height; 28 | } 29 | 30 | @mixin hidescroll() { 31 | scrollbar-width: none; 32 | -ms-overflow-style: none; 33 | 34 | &::-webkit-scrollbar, 35 | &::-webkit-scrollbar-thumb { 36 | display: none; 37 | 38 | background: transparent; 39 | width: 0; 40 | height: 0; 41 | 42 | -webkit-appearance: none; 43 | } 44 | } 45 | 46 | @mixin clearinput() { 47 | padding: 0; 48 | border: 0; 49 | border-radius: inherit; 50 | background: none; 51 | font-size: inherit; 52 | line-height: inherit; 53 | font-weight: inherit; 54 | color: inherit; 55 | caret-color: currentColor; 56 | outline: none; 57 | appearance: none; 58 | word-break: keep-all; 59 | text-align: left; 60 | -webkit-text-fill-color: currentColor; // for Safari 61 | 62 | &:-webkit-autofill, 63 | &:-webkit-autofill:hover, 64 | &:-webkit-autofill:focus { 65 | border-radius: inherit; 66 | -webkit-text-fill-color: inherit !important; 67 | color: inherit !important; 68 | background-color: transparent !important; 69 | -webkit-box-shadow: 0 0 0 1000px var(--tok-text-color) 5c0 inset !important; // to overlay native background 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/ui/tokens/CurrencyOptions.token.ts: -------------------------------------------------------------------------------- 1 | import { CHAR_NO_BREAK_SPACE } from '@tok/ui/consts'; 2 | import type { CurrencyVariants } from '@tok/ui/use/money/currency'; 3 | import type { InjectionKey } from 'vue'; 4 | 5 | export type CurrencyOptions = { 6 | align?: 'left' | 'right' | string; 7 | currency?: CurrencyVariants; 8 | decimalSeparator?: string; 9 | thousandSeparator?: string; 10 | }; 11 | 12 | export const defaultCurrencyOptions = { 13 | align: 'left', 14 | currency: 'USD', 15 | decimalSeparator: '.', 16 | thousandSeparator: CHAR_NO_BREAK_SPACE, 17 | } as const; 18 | 19 | export const CURRENCY_OPTIONS_TOKEN = Symbol() as InjectionKey< 20 | Required 21 | >; 22 | -------------------------------------------------------------------------------- /packages/ui/tokens/CustomIcons.token.ts: -------------------------------------------------------------------------------- 1 | import { defineAsyncComponent, InjectionKey } from 'vue'; 2 | 3 | export const CUSTOM_ICONS_TOKEN = Symbol() as InjectionKey< 4 | Record> 5 | >; 6 | -------------------------------------------------------------------------------- /packages/ui/tokens/PopupsHost.token.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue'; 2 | 3 | type PopupsHostInstance = { 4 | setOpened: (id: string, value: boolean) => void; 5 | remove: (id: string) => void; 6 | }; 7 | 8 | export const POPUPS_HOST_TOKEN = Symbol() as InjectionKey< 9 | Ref 10 | >; 11 | -------------------------------------------------------------------------------- /packages/ui/tokens/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui tokens 2 | 3 | ## [AlertsHost](./AlertsHost.token.ts) 4 | 5 | Connector between [AlertsPlugin](../plugins/alerts/Alerts.plugin.ts) and [useAlerts](../use/alerts/README.md) 6 | 7 | ## [CurrencyOptions](./CurrencyOptions.token.ts) 8 | 9 | Token for defining currency configuration for use inside [Money](../components/Money/README.md) and [useMoney](../use/README.md) 10 | 11 | ## [CustomIcons](./CustomIcons.token.ts) 12 | 13 | Token for defining custom icons for use inside [SvgIcon](../components/SvgIcon/README.md) 14 | 15 | ## [PopupsHost](./PopupsHost.token.ts) 16 | 17 | Connector between [Popup](../components/Popup/README.md) and [PopupsHost](../components/Root/PopupsHost.vue) indside [Root component](../components/Root/README.md) 18 | -------------------------------------------------------------------------------- /packages/ui/tokens/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AlertsHost.token'; 2 | export * from './CurrencyOptions.token'; 3 | export * from './CustomIcons.token'; 4 | export * from './PopupsHost.token'; 5 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tok/tsconfig/tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "include": ["."], 10 | "exclude": ["dist", "build", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/ui/types/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui types 2 | 3 | ## [MaybeRef](./maybeRef.type.ts) 4 | 5 | Helper type for accessing refs or primitives within useCases 6 | -------------------------------------------------------------------------------- /packages/ui/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './maybeRef.type'; 2 | -------------------------------------------------------------------------------- /packages/ui/types/maybeRef.type.ts: -------------------------------------------------------------------------------- 1 | import { computed, ComputedRef, Ref, ref } from 'vue'; 2 | 3 | export type MaybeRef = Ref | T; 4 | export type MaybeComputedRef = ComputedRef | (() => T) | MaybeRef; 5 | 6 | export function resolveRef(r: MaybeComputedRef): ComputedRef; 7 | export function resolveRef(r: MaybeRef): Ref; 8 | export function resolveRef(r: MaybeComputedRef) { 9 | return typeof r === 'function' ? computed(r as any) : ref(r); 10 | } 11 | -------------------------------------------------------------------------------- /packages/ui/use/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui use 2 | 3 | - [useAlerts](./alerts/README.md) 4 | - [useFocused](./focused/README.md) 5 | - [useMoney](./money/README.md) 6 | -------------------------------------------------------------------------------- /packages/ui/use/alerts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useAlerts'; 2 | -------------------------------------------------------------------------------- /packages/ui/use/alerts/useAlerts.ts: -------------------------------------------------------------------------------- 1 | import { AlertHostParams, ALERTS_HOST_TOKEN } from '@tok/ui/tokens'; 2 | import { getElementId } from '@tok/ui/utility/getElementId'; 3 | import { tryOnBeforeUnmount } from '@tok/ui/utility/tryOnBeforeUnmount'; 4 | import { Component, inject } from 'vue'; 5 | 6 | type Config = { 7 | autoCloseOnUnmount: boolean; 8 | }; 9 | 10 | export function useAlerts(config?: Config) { 11 | const instance = inject(ALERTS_HOST_TOKEN, null); 12 | 13 | if (instance === null) { 14 | console.warn('[useAlerts] You should add AlertsPlugin into your main.ts'); 15 | } 16 | 17 | const showedIds: string[] = []; 18 | 19 | const show = ( 20 | content: string | Component, 21 | params?: AlertHostParams 22 | ) => { 23 | const id = getElementId(); 24 | 25 | instance?.show(id, content, params); 26 | 27 | if (config?.autoCloseOnUnmount) { 28 | showedIds.push(id); 29 | } 30 | 31 | return id; 32 | }; 33 | 34 | const close = (id?: string) => { 35 | if (!id) { 36 | closeLast(); 37 | 38 | return; 39 | } 40 | 41 | instance?.close(id); 42 | }; 43 | 44 | const closeLast = () => { 45 | instance?.closeLast(); 46 | }; 47 | 48 | tryOnBeforeUnmount(() => { 49 | showedIds.forEach(close); 50 | }); 51 | 52 | return { 53 | show, 54 | close, 55 | closeLast, 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /packages/ui/use/focused/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui useFocused 2 | 3 | useCase to detect focus on element 4 | 5 | > Used in: 6 | > [InputText](../../components/InputText/README.md) 7 | 8 | ## Usage 9 | 10 | ```vue 11 | 20 | 21 | 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/ui/use/focused/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useFocused'; 2 | -------------------------------------------------------------------------------- /packages/ui/use/focused/useFocused.ts: -------------------------------------------------------------------------------- 1 | import { MaybeComputedRef, resolveRef } from '@tok/ui/types'; 2 | import { readonly, ref, watch } from 'vue'; 3 | 4 | export function useFocused(native: MaybeComputedRef) { 5 | const nativeRef = resolveRef(native); 6 | const focused = ref(false); 7 | 8 | const onFocus = () => (focused.value = true); 9 | const onBlur = () => { 10 | focused.value = false; 11 | }; 12 | 13 | watch( 14 | nativeRef, 15 | (native, _, onCleanup) => { 16 | native?.addEventListener('focusin', onFocus); 17 | native?.addEventListener('focusout', onBlur); 18 | 19 | onCleanup(() => { 20 | native?.removeEventListener('focusin', onFocus); 21 | native?.removeEventListener('focusout', onBlur); 22 | }); 23 | }, 24 | { immediate: true } 25 | ); 26 | 27 | return readonly(focused); 28 | } 29 | -------------------------------------------------------------------------------- /packages/ui/use/money/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui useMoney 2 | 3 | Helper function for resolving currency configuration provided by [CurrencyOptions.token](../../tokens/README.md) and formatting money based on that configuration. 4 | 5 | ## i18n 6 | 7 | `useMoney` natively supports [i18n](../../../i18n/README.md) all options and value inside it. 8 | 9 | You can provide a locale token inside options with [CurrencyOptions.token](../../tokens/README.md) and value as string or number, and it will be dynamically translated 10 | 11 | ## Usage 12 | 13 | ```vue 14 | 19 | 20 | 33 | ``` 34 | -------------------------------------------------------------------------------- /packages/ui/use/money/currency/currency.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from './currency.enum'; 2 | 3 | type CurrencyAsString = keyof Record; 4 | 5 | export type CurrencyVariants = CurrencyAsString | Currency | string; 6 | -------------------------------------------------------------------------------- /packages/ui/use/money/currency/index.ts: -------------------------------------------------------------------------------- 1 | export * from './currency'; 2 | export * from './currency.enum'; 3 | export * from './getCurrencySymbol'; 4 | -------------------------------------------------------------------------------- /packages/ui/use/money/formatMoney.ts: -------------------------------------------------------------------------------- 1 | import { CHAR_NO_BREAK_SPACE } from '@tok/ui/consts'; 2 | import type { CurrencyOptions } from '@tok/ui/tokens'; 3 | import { formatNumber } from '@tok/ui/utility/formatNumber'; 4 | 5 | import { getCurrencySymbol } from './currency'; 6 | 7 | export const defaultFormatMoney = { 8 | align: 'left' as const, 9 | precision: 2, 10 | currency: 'USD', 11 | decimalSeparator: '.', 12 | thousandSeparator: CHAR_NO_BREAK_SPACE, 13 | }; 14 | 15 | export function formatMoney( 16 | _value: number, 17 | options: Required 18 | ) { 19 | const formatted = formatNumber( 20 | _value, 21 | options.decimalSeparator, 22 | options.thousandSeparator 23 | ); 24 | const currencySymbol = getCurrencySymbol(options.currency); 25 | const [prefix, postfix] = 26 | options.align === 'left' ? [currencySymbol, ''] : ['', currencySymbol]; 27 | 28 | return `${prefix}${formatted}${postfix}`; 29 | } 30 | -------------------------------------------------------------------------------- /packages/ui/use/money/index.ts: -------------------------------------------------------------------------------- 1 | export * from './formatMoney'; 2 | export * from './useMoney'; 3 | -------------------------------------------------------------------------------- /packages/ui/utility/README.md: -------------------------------------------------------------------------------- 1 | # @tok/ui utility 2 | 3 | ## [1. getElementId](./getElementId.ts) 4 | 5 | Returns a unique element ID for your entire application 6 | 7 | ## [2. noop](./noop.ts) 8 | 9 | Do nothing 10 | 11 | ## [3. tryOnBeforeUnmount](./tryOnBeforeUnmount.ts) 12 | 13 | Checks if we are within the Vue scope. If so, it will trigger onBeforeUnmount; if not, it does nothing 14 | 15 | ## [4. clamp](./clamp.ts) 16 | 17 | Helper function to clamp numbers between min and max value 18 | 19 | ## [5. formatNumber](./formatNumber.ts) 20 | 21 | formats a numeric value with specified decimalSeparator and thousandSeparator, improving readability 22 | 23 | > Used in: 24 | > 25 | > 1. [Money](../components/Money/README.md) 26 | -------------------------------------------------------------------------------- /packages/ui/utility/clamp.ts: -------------------------------------------------------------------------------- 1 | export function clamp(value: T, min: T, max: T): T { 2 | return Math.min(max, Math.max(min, value)) as T; 3 | } 4 | -------------------------------------------------------------------------------- /packages/ui/utility/formatNumber.ts: -------------------------------------------------------------------------------- 1 | import { CHAR_COMMA, CHAR_NO_BREAK_SPACE } from '@tok/ui/consts'; 2 | 3 | export function formatNumber( 4 | value: number, 5 | decimalSeparator = CHAR_COMMA, 6 | thousandSeparator: string = CHAR_NO_BREAK_SPACE 7 | ): string { 8 | const integerPartString = `${Math.floor(Math.abs(value))}`; 9 | const fractionPartString = `${value}`.split('.')[1] || ''; 10 | const sign = value < 0 ? '-' : ''; 11 | const remainder = integerPartString.length % 3; 12 | 13 | let result = sign + integerPartString.charAt(0); 14 | 15 | for (let i = 1; i < integerPartString.length; i++) { 16 | if (i % 3 === remainder && integerPartString.length > 3) { 17 | result += thousandSeparator; 18 | } 19 | 20 | result += integerPartString.charAt(i); 21 | } 22 | 23 | return fractionPartString 24 | ? result + decimalSeparator + fractionPartString 25 | : result; 26 | } 27 | -------------------------------------------------------------------------------- /packages/ui/utility/getElementId.ts: -------------------------------------------------------------------------------- 1 | let autoId = 0; 2 | 3 | export function getElementId() { 4 | return `tok-interactive_${autoId++}_${Date.now()}`; 5 | } 6 | -------------------------------------------------------------------------------- /packages/ui/utility/noop.ts: -------------------------------------------------------------------------------- 1 | export function noop() { 2 | // noop 3 | } 4 | -------------------------------------------------------------------------------- /packages/ui/utility/tryOnBeforeUnmount.ts: -------------------------------------------------------------------------------- 1 | import { getCurrentScope, onBeforeUnmount } from 'vue'; 2 | 3 | type Fn = () => void; 4 | 5 | export function tryOnBeforeUnmount(fn: Fn) { 6 | if (getCurrentScope()) { 7 | onBeforeUnmount(fn); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": [ 4 | "**/.env.*local" 5 | ], 6 | "pipeline": { 7 | "build": { 8 | "cache": false, 9 | "outputs": [ 10 | "dist/**", 11 | ".next/**", 12 | "!.next/cache/**" 13 | ], 14 | "dependsOn": [ 15 | "^build" 16 | ] 17 | }, 18 | "dev": { 19 | "cache": false, 20 | "persistent": true 21 | }, 22 | "compress": { 23 | "cache": false 24 | } 25 | } 26 | } --------------------------------------------------------------------------------