diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..13089de --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +Dockerfile +.dockerignore +**/node_modules +npm-debug.log +README.md +**/.next +.git +.github +.turbo +**/.env +landing-page +docs +packages/scripts +wordpress diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1ed453a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.{js,json,yml}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.env.dev.example b/.env.dev.example new file mode 100644 index 0000000..cb029f9 --- /dev/null +++ b/.env.dev.example @@ -0,0 +1,19 @@ +# Make sure to change this to your own random string of 32 characters (https://docs.typebot.io/self-hosting/docker#2-add-the-required-configuration) +ENCRYPTION_SECRET=H+KbL/OFrqbEuDy/1zX8bsPG+spXri3S + +DATABASE_URL=postgresql://postgres:typebot@localhost:5432/typebot + +NEXTAUTH_URL=http://localhost:3000 +NEXT_PUBLIC_VIEWER_URL=http://localhost:3001 + +GITHUB_CLIENT_ID=534b549dd17709a743a2 +GITHUB_CLIENT_SECRET=7adb03507504fb1a54422f6c3c697277cfd000a9 + +S3_ACCESS_KEY=minio +S3_SECRET_KEY=minio123 +S3_BUCKET=typebot +S3_PORT=9000 +S3_ENDPOINT=localhost +S3_SSL=false + +# For more configuration options check out: https://docs.typebot.io/self-hosting/configuration \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2fdb4c7 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Make sure to change this to your own random string of 32 characters (https://docs.typebot.io/self-hosting/docker#2-add-the-required-configuration) +ENCRYPTION_SECRET=do+UspMmB/rewbX2K/rskFmtgGSSZ8Ta + +DATABASE_URL=postgresql://postgres:typebot@typebot-db:5432/typebot + +NEXTAUTH_URL= +NEXT_PUBLIC_VIEWER_URL= + +ADMIN_EMAIL= +# For more configuration options check out: https://docs.typebot.io/self-hosting/configuration \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..cdc401f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: baptisteArno diff --git a/.github/images/logo-dark.png b/.github/images/logo-dark.png new file mode 100644 index 0000000..d890748 Binary files /dev/null and b/.github/images/logo-dark.png differ diff --git a/.github/images/logo-light.png b/.github/images/logo-light.png new file mode 100644 index 0000000..bdf35eb Binary files /dev/null and b/.github/images/logo-light.png differ diff --git a/.github/images/star-project.gif b/.github/images/star-project.gif new file mode 100644 index 0000000..e14d4da Binary files /dev/null and b/.github/images/star-project.gif differ diff --git a/.github/videos/demo.mp4 b/.github/videos/demo.mp4 new file mode 100644 index 0000000..5b41d16 Binary files /dev/null and b/.github/videos/demo.mp4 differ diff --git a/.github/workflows/auto-add-to-project.yml b/.github/workflows/auto-add-to-project.yml new file mode 100644 index 0000000..0625cea --- /dev/null +++ b/.github/workflows/auto-add-to-project.yml @@ -0,0 +1,16 @@ +name: Automatically add issues to projects when labeled + +on: + issues: + types: + - labeled + +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v0.3.0 + with: + project-url: https://github.com/users/baptisteArno/projects/4 + github-token: ${{ secrets.PERSONAL_TOKEN }} diff --git a/.github/workflows/auto-create-release.yml b/.github/workflows/auto-create-release.yml new file mode 100644 index 0000000..70e9c91 --- /dev/null +++ b/.github/workflows/auto-create-release.yml @@ -0,0 +1,24 @@ +on: + push: + tags: + - 'v*' + +name: Create Release + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Extract body from changelog + run: | + NEW_VERSION=$(echo '${{ github.ref }}' | sed 's/refs\/tags\/v//') + echo $NEW_VERSION + sed -n -e "/## ${NEW_VERSION}/,/ extractedBody.md + - name: Create Release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + bodyFile: 'extractedBody.md' diff --git a/.github/workflows/auto-create-tags.yml b/.github/workflows/auto-create-tags.yml new file mode 100644 index 0000000..c9c7288 --- /dev/null +++ b/.github/workflows/auto-create-tags.yml @@ -0,0 +1,41 @@ +name: Create Tag + +on: + push: + branches: + - main + +jobs: + create-tag: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: '${{ secrets.PERSONAL_TOKEN }}' + steps: + - uses: actions/checkout@v2 + - name: 'Create main tag' + id: 'main' + uses: butlerlogic/action-autotag@1.1.2 + with: + tag_prefix: 'v' + + - name: 'Create latest tag' + if: ${{ contains(steps.main.outputs.tagname, 'v') }} + uses: EndBug/latest-tag@latest + + - name: 'Create js tag' + uses: butlerlogic/action-autotag@1.1.2 + with: + root: '/packages/embeds/js' + tag_prefix: 'js-v' + + - name: 'Create react tag' + uses: butlerlogic/action-autotag@1.1.2 + with: + root: '/packages/embeds/react' + tag_prefix: 'react-v' + + - name: 'Create nextjs tag' + uses: butlerlogic/action-autotag@1.1.2 + with: + root: '/packages/embeds/nextjs' + tag_prefix: 'nextjs-v' diff --git a/.github/workflows/check-and-report-chats-usage.yml b/.github/workflows/check-and-report-chats-usage.yml new file mode 100644 index 0000000..86bf7c1 --- /dev/null +++ b/.github/workflows/check-and-report-chats-usage.yml @@ -0,0 +1,34 @@ +name: Check and report chats usage + +on: + schedule: + - cron: '0 * * * *' + +jobs: + send: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./packages/scripts + env: + DATABASE_URL: '${{ secrets.DATABASE_URL }}' + ENCRYPTION_SECRET: '${{ secrets.ENCRYPTION_SECRET }}' + NEXTAUTH_URL: 'http://localhost:3000' + NEXT_PUBLIC_VIEWER_URL: 'http://localhost:3001' + TELEMETRY_WEBHOOK_URL: '${{ secrets.TELEMETRY_WEBHOOK_URL }}' + TELEMETRY_WEBHOOK_BEARER_TOKEN: '${{ secrets.TELEMETRY_WEBHOOK_BEARER_TOKEN }}' + SMTP_USERNAME: '${{ secrets.SMTP_USERNAME }}' + SMTP_PASSWORD: '${{ secrets.SMTP_PASSWORD }}' + SMTP_HOST: '${{ secrets.SMTP_HOST }}' + SMTP_PORT: '${{ secrets.SMTP_PORT }}' + NEXT_PUBLIC_SMTP_FROM: '${{ secrets.NEXT_PUBLIC_SMTP_FROM }}' + STRIPE_SECRET_KEY: '${{ secrets.STRIPE_SECRET_KEY }}' + STRIPE_STARTER_PRICE_ID: '${{ secrets.STRIPE_STARTER_PRICE_ID }}' + STRIPE_STARTER_CHATS_PRICE_ID: '${{ secrets.STRIPE_STARTER_CHATS_PRICE_ID }}' + STRIPE_PRO_PRICE_ID: '${{ secrets.STRIPE_PRO_PRICE_ID }}' + STRIPE_PRO_CHATS_PRICE_ID: '${{ secrets.STRIPE_PRO_CHATS_PRICE_ID }}' + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo run checkAndReportChatsUsage diff --git a/.github/workflows/clean-database.yml b/.github/workflows/clean-database.yml new file mode 100644 index 0000000..efff51d --- /dev/null +++ b/.github/workflows/clean-database.yml @@ -0,0 +1,22 @@ +name: Daily database cleanup + +on: + schedule: + - cron: '0 6 * * *' + +jobs: + clean: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./packages/scripts + env: + DATABASE_URL: '${{ secrets.DATABASE_URL }}' + ENCRYPTION_SECRET: '${{ secrets.ENCRYPTION_SECRET }}' + NEXTAUTH_URL: 'http://localhost:3000' + NEXT_PUBLIC_VIEWER_URL: 'http://localhost:3001' + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo run db:cleanDatabase diff --git a/.github/workflows/publish-lib-to-npm.yml b/.github/workflows/publish-lib-to-npm.yml new file mode 100644 index 0000000..e2936ea --- /dev/null +++ b/.github/workflows/publish-lib-to-npm.yml @@ -0,0 +1,23 @@ +name: Publish typebot-js to NPM + +on: + push: + tags: + - 'js-lib-v*' + +jobs: + publish: + runs-on: ubuntu-latest + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo build --filter=typebot-js... + - name: Set NPM_TOKEN in config + run: pnpm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN} + working-directory: ./packages/typebot-js + - name: Publish + run: pnpm publish --no-git-checks --access public + working-directory: ./packages/typebot-js diff --git a/.github/workflows/publish-typebot-js.yml b/.github/workflows/publish-typebot-js.yml new file mode 100644 index 0000000..b3f7904 --- /dev/null +++ b/.github/workflows/publish-typebot-js.yml @@ -0,0 +1,18 @@ +name: Publish @typebot.io/js package to NPM + +on: + push: + tags: + - 'js-v*' + +jobs: + publish: + runs-on: ubuntu-latest + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo build --filter=@typebot.io/js... + - run: cd packages/embeds/js && pnpm publish --no-git-checks --access public diff --git a/.github/workflows/publish-typebot-nextjs.yml b/.github/workflows/publish-typebot-nextjs.yml new file mode 100644 index 0000000..84cb378 --- /dev/null +++ b/.github/workflows/publish-typebot-nextjs.yml @@ -0,0 +1,18 @@ +name: Publish @typebot.io/nextjs package to NPM + +on: + push: + tags: + - 'nextjs-v*' + +jobs: + publish: + runs-on: ubuntu-latest + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo build --filter=@typebot.io/nextjs... + - run: cd packages/embeds/nextjs && pnpm publish --no-git-checks --access public diff --git a/.github/workflows/publish-typebot-react.yml b/.github/workflows/publish-typebot-react.yml new file mode 100644 index 0000000..8f6858d --- /dev/null +++ b/.github/workflows/publish-typebot-react.yml @@ -0,0 +1,18 @@ +name: Publish @typebot.io/react package to NPM + +on: + push: + tags: + - 'react-v*' + +jobs: + publish: + runs-on: ubuntu-latest + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + steps: + - uses: actions/checkout@v2 + - uses: pnpm/action-setup@v2.2.2 + - run: pnpm i --frozen-lockfile + - run: pnpm turbo build --filter=@typebot.io/react... + - run: cd packages/embeds/react && pnpm publish --no-git-checks --access public diff --git a/.github/workflows/publish_docker_images.yml b/.github/workflows/publish_docker_images.yml new file mode 100644 index 0000000..f99b184 --- /dev/null +++ b/.github/workflows/publish_docker_images.yml @@ -0,0 +1,153 @@ +name: Build Docker images + +on: + push: + tags: ['v*'] + +jobs: + build-amd: + env: + DATABASE_URL: 'postgresql://' + strategy: + matrix: + app: ['builder', 'viewer'] + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Extract existing image metadata + id: image-meta + uses: docker/metadata-action@v4 + with: + images: baptistearno/typebot-${{ matrix.app }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build image + id: docker_build + uses: docker/build-push-action@v4 + with: + context: . + labels: ${{ steps.image-meta.outputs.labels }} + platforms: linux/amd64 + cache-from: type=gha,scope=${{ matrix.app }}-amd + cache-to: type=gha,scope=${{ matrix.app }}-amd,mode=max + build-args: | + SCOPE=${{ matrix.app }} + outputs: type=image,name=baptistearno/typebot-${{ matrix.app }},push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests/${{ matrix.app }} + digest="${{ steps.docker_build.outputs.digest }}" + touch "/tmp/digests/${{ matrix.app }}/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v3 + with: + name: digests-${{ matrix.app }} + path: /tmp/digests/${{matrix.app}}/* + if-no-files-found: error + retention-days: 1 + + build-arm: + env: + DATABASE_URL: 'postgresql://' + strategy: + matrix: + app: ['builder', 'viewer'] + runs-on: buildjet-2vcpu-ubuntu-2204-arm + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Extract existing image metadata + id: image-meta + uses: docker/metadata-action@v4 + with: + images: baptistearno/typebot-${{ matrix.app }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build image + id: docker_build + uses: docker/build-push-action@v4 + with: + context: . + labels: ${{ steps.image-meta.outputs.labels }} + platforms: linux/arm64 + cache-from: type=gha,scope=${{ matrix.app }}-arm + cache-to: type=gha,scope=${{ matrix.app }}-arm,mode=max + build-args: | + SCOPE=${{ matrix.app }} + outputs: type=image,name=baptistearno/typebot-${{ matrix.app }},push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests/${{ matrix.app }} + digest="${{ steps.docker_build.outputs.digest }}" + touch "/tmp/digests/${{ matrix.app }}/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v3 + with: + name: digests-${{ matrix.app }} + path: /tmp/digests/${{matrix.app}}/* + if-no-files-found: error + retention-days: 1 + + merge-and-push: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - build-amd + - build-arm + strategy: + matrix: + app: ['builder', 'viewer'] + steps: + - name: Download AMD digests + uses: actions/download-artifact@v3 + with: + name: digests-${{ matrix.app }} + path: /tmp/digests/${{ matrix.app }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: baptistearno/typebot-${{ matrix.app }} + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Create manifest list and push + working-directory: /tmp/digests/${{ matrix.app }} + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf 'baptistearno/typebot-${{ matrix.app }}@sha256:%s ' *) + - name: Inspect image + run: | + docker buildx imagetools inspect baptistearno/typebot-${{ matrix.app }}:${{ steps.meta.outputs.version }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa52735 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +node_modules +.next +.env.local +workspace.code-workspace +.DS_Store +.turbo +.idea +authenticatedState.json +playwright-report +dist +test-results +**/src/test/results +**/src/test/reporters +test/report +**/api/scripts +.sentryclirc +.docusaurus +.cache-loader +build +firebaseServiceAccount.json + +.env.production +.env.staging + +# Wordpress +.svn +tags + +dump.sql +dump.tar + +__env.js +__ENV.js + +typebotsToFix.json +**/scripts/logs + +snapshots + +.env +.typebot-build diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..58993aa --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +pnpm lint diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..39c9b23 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +public-hoist-pattern[]=*prisma* \ No newline at end of file diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs new file mode 100644 index 0000000..9394b84 --- /dev/null +++ b/.pnpmfile.cjs @@ -0,0 +1,18 @@ +module.exports = { + hooks: { + readPackage(pkg) { + // Solving weird issue: https://github.com/facebook/docusaurus/issues/6724#issuecomment-1188794031 + if (pkg.name != 'docs') { + const deps = [ + '@algolia/client-search', + '@docusaurus/core', + '@docusaurus/preset-classic', + '@docusaurus/theme-common', + '@docusaurus/theme-live-codeblock', + ] + deps.forEach((p) => delete pkg.dependencies[p]) + } + return pkg + }, + }, +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..fa51da2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true +} diff --git a/.tolgeerc b/.tolgeerc new file mode 100644 index 0000000..a809777 --- /dev/null +++ b/.tolgeerc @@ -0,0 +1,5 @@ +{ + "apiUrl": "https://tolgee.server.baptistearno.com", + "projectId": "1", + "delimiter": null +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..db00880 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "bradlc.vscode-tailwindcss", + "unifiedjs.vscode-mdx", + "lokalise.i18n-ally", + "ms-playwright.playwright", + "Prisma.prisma" + ] +} diff --git a/.vscode/i18n-ally-custom-framework.yml b/.vscode/i18n-ally-custom-framework.yml new file mode 100644 index 0000000..3cb5dac --- /dev/null +++ b/.vscode/i18n-ally-custom-framework.yml @@ -0,0 +1,27 @@ +# An array of strings which contain Language Ids defined by VS Code +# You can check avaliable language ids here: https://code.visualstudio.com/docs/languages/overview#_language-id +languageIds: + - javascript + - typescript + - javascriptreact + - typescriptreact + +# An array of RegExes to find the key usage. **The key should be captured in the first match group**. +# You should unescape RegEx strings in order to fit in the YAML file +# To help with this, you can use https://www.freeformatter.com/json-escape.html +usageMatchRegex: + # The following example shows how to detect `t("your.i18n.keys")` + # the `{key}` will be placed by a proper keypath matching regex, + # you can ignore it and use your own matching rules as well + - "[^\\w\\d]t\\([\\s\\n]*'({key})'" + - 'keyName="({key})"' + +# An array of strings containing refactor templates. +# The "$1" will be replaced by the keypath specified. +# Optional: uncomment the following two lines to use + +refactorTemplates: + - t("$1") + +# If set to true, only enables this custom framework (will disable all built-in frameworks) +monopoly: true diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e22d56d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "i18n-ally.localesPaths": ["apps/builder/public/locales"], + "i18n-ally.keystyle": "flat", + "i18n-ally.displayLanguage": "en", + "i18n-ally.enabledFrameworks": ["custom"], + "i18n-ally.sortKeys": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2, + "typescript.updateImportsOnFileMove.enabled": "always", + "playwright.env": { + "DATABASE_URL": "postgresql://postgres:typebot@localhost:5432/typebot", + "NEXT_PUBLIC_VIEWER_URL": "http://localhost:3001", + "NEXTAUTH_URL": "http://localhost:3000" + }, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0b23c13 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2892 @@ +# Changelog + + +## 2.20.0 (2023-12-04) + +### Added + +- ✨ Allow user to share a flow publicly and make it duplicatable [[bb41226](https://github.com/baptisteArno/typebot.io/commit/bb41226a046fe9dccd0ee04d2761c5b96d6001f4)] +- ✨ (openai) Add create speech OpenAI action [[1a44bf4](https://github.com/baptisteArno/typebot.io/commit/1a44bf4935a131010e912e9c7d0ba9127b55be83)] + +### Changed + +- ⚡ (wordpress) Add lib_version prop in shortcode [[eeac493](https://github.com/baptisteArno/typebot.io/commit/eeac4933870216017806586b9032e8af86ce75dc)] +- 🚸 (fileUpload) Properly encode commas from uploaded file urls [[8d413f0](https://github.com/baptisteArno/typebot.io/commit/8d413f0865c8688ec6999937557db1ce9dfc4f26)] +- 🔧 Increase builder request max size to 4MB [[4666fd8](https://github.com/baptisteArno/typebot.io/commit/4666fd8fa09052e315d54b9333557daf66e7a5c2)] +- 🚸 (redirect) Make sure the redirection is always done on top frame [[6ce43ed](https://github.com/baptisteArno/typebot.io/commit/6ce43ed26fafe85200414b83a2f192ed3977ebc6)] +- ⚡ (billing) Improve past_due workspace checking webhook [[0856c59](https://github.com/baptisteArno/typebot.io/commit/0856c59b500b62cdaa26b25f7d9a5be4a2ac8a9c)] + +### Removed + +- 🔥 Remove VIEWER_URL_INTERNAL variable [[73d2e16](https://github.com/baptisteArno/typebot.io/commit/73d2e165bfa38c014d1b8ae3c5c4701b0d3e7149)] + +### Fixed + +- 🐛 (share) Fix duplicate folderId issue [[8ce4e48](https://github.com/baptisteArno/typebot.io/commit/8ce4e4808d36133a49a7af8ad61665e9dbbfbc72)] +- 🐛 Fix default webhook body with multi inputs groups [[880ded9](https://github.com/baptisteArno/typebot.io/commit/880ded97d113dd70cea8a97020a30daef573567a)] +- 🚑 (pictureChoice) Fix pic choice multi select parsing [[b7ee800](https://github.com/baptisteArno/typebot.io/commit/b7ee8006494d4a681b813a4bf9ce4e9762b21fcd)] +- 💚 Update broken action-autotag package [[7f914e9](https://github.com/baptisteArno/typebot.io/commit/7f914e9b8c9afd280bd6d5f091b090fc610bce81)] +- 🐛 Fix processTelemetry endpoint not reachable [[30b09e5](https://github.com/baptisteArno/typebot.io/commit/30b09e56a405d1178018ab52bd69f5d2b7415bd2)] +- 🚑 (billing) Fix stripe webhook "invoice.paid" typo [[5b0073b](https://github.com/baptisteArno/typebot.io/commit/5b0073bb61301ea1370b3bf662652648b30a4225)] +- 🐛 (pictureChoice) Fix choice parsing too unrestrictive [[542e632](https://github.com/baptisteArno/typebot.io/commit/542e632472324a4c88cabee2be4f49921e5b28bb)] +- 🚑 (editor) Fix typebot update permission [[8a07392](https://github.com/baptisteArno/typebot.io/commit/8a073928211cda434246f17ba4b18fdbeec0b4ef)] +- 🐛 (chatwoot) Fix email prefill when Chatwoot contact already exist [[94886ca](https://github.com/baptisteArno/typebot.io/commit/94886ca58e684c6229f2438e66a90ff91dd79b1f)] +- ✏️ Fix typebot v7 breaking changes doc typo [[1e64a73](https://github.com/baptisteArno/typebot.io/commit/1e64a73e54c6c841ff292eecf6f2011a2be86eda)] + +### Miscellaneous + +- 📝 Add flow share docs [[e228f68](https://github.com/baptisteArno/typebot.io/commit/e228f682f5b92b3e168a5b8fc11d7fdd1edb2af2)] +- 🛂 Allow app admin to read a typebot [[cf8df68](https://github.com/baptisteArno/typebot.io/commit/cf8df681868974db099ee9c5d0b0105c68d46e07)] +- 📝 Improve WP prefilled var explanation [[2c203f3](https://github.com/baptisteArno/typebot.io/commit/2c203f3b6d2a59ec7c71a9858678c2daab73e8bd)] +- 📝 Add new start and continue endpoints in the API runtime instructions [[993bc79](https://github.com/baptisteArno/typebot.io/commit/993bc7900ede9fa44189f88724e35852bf5fe032)] +- 🛂 (billing) Add isPastDue field in workspace ([#1046](https://github.com/baptisteArno/typebot.io/issues/1046)) [[ca79934](https://github.com/baptisteArno/typebot.io/commit/ca79934ef5c86feaa60cde4d4bc42171149a1f15)] +- 🌐 Add es and ro support [[f6ac389](https://github.com/baptisteArno/typebot.io/commit/f6ac3891f8d11089d81a3cb7be6c715460570f28)] + + + +## 2.19.1 (2023-11-17) + +### Added + +- 🔊 Add response debug log for failing requests without errors [[5298538](https://github.com/baptisteArno/typebot.io/commit/5298538ecb8e2fd06d38775ac0b4a7d4333055c5)] + +### Changed + +- ♿ Show scrollbar on searchable items [[7cf64a1](https://github.com/baptisteArno/typebot.io/commit/7cf64a1abbd639ca9f45528f7b3917b93ab7e1aa)] +- 🚸 Auto scroll once picture choice images are fully loaded [[1f19eb8](https://github.com/baptisteArno/typebot.io/commit/1f19eb8763b2553feb849075eda8a3c8adec6fa9)] +- ⬆️ (date) Upgrade date parser package [[00265af](https://github.com/baptisteArno/typebot.io/commit/00265af0cc77a6ccdff62676cd03ebcaa20c50c6)] +- ⏪ (wordpress) Revert to specific non breaking version for self-hosters [[6c0f28b](https://github.com/baptisteArno/typebot.io/commit/6c0f28b3e4f70a9920100c5546d47573b02f0b2a)] +- ⚡ Add maxWidth and maxHeight bubble them props [[74dd169](https://github.com/baptisteArno/typebot.io/commit/74dd169b50013ed5603e605ee01aac4dcdf5bf93)] +- ⏪ Revert new authentication method for preview bot [[06065c3](https://github.com/baptisteArno/typebot.io/commit/06065c3e850312f32a8b0611aa8a8824b660dba8)] +- ⚡ Add more video supports ([#1023](https://github.com/baptisteArno/typebot.io/issues/1023)) [[dd4de58](https://github.com/baptisteArno/typebot.io/commit/dd4de582a93132d71b8e50fc5352c997633e2671)] +- 💄 Fix multi choice checkbox UI on small screens [[60829b4](https://github.com/baptisteArno/typebot.io/commit/60829b4d0ab318651bf5ac0ee30799a21a07cbdd)] +- 🚸 (typebotLink) Make "current" option work like typebot links instead of jump [[64418df](https://github.com/baptisteArno/typebot.io/commit/64418df3a1bd9ff1d3832eec1ed038eef4515432)] +- ♻️ Introduce typebot v6 with events ([#1013](https://github.com/baptisteArno/typebot.io/issues/1013)) [[35300ea](https://github.com/baptisteArno/typebot.io/commit/35300eaf340c9bcae41f7b004c682bb8939684ff)] +- ⚡ (chatwoot) Unmount Typebot embed bubble when opening chatwoot [[eed562b](https://github.com/baptisteArno/typebot.io/commit/eed562b47a04676f3067096f61ab11e6c19726bf)] +- ⬆️ Upgrade Sentry to mitigate security issue [[b2b82c4](https://github.com/baptisteArno/typebot.io/commit/b2b82c48e1c46377d19550559afac1d068ba23cb)] + +### Fixed + +- 🐛 (editor) Fix AB test items not connectable [[3a47a0f](https://github.com/baptisteArno/typebot.io/commit/3a47a0fcbda4d850509ab304f15d51f3cc17e5f2)] +- 🐛 (typebotLink) Fix variables merging with new values [[e22bd7d](https://github.com/baptisteArno/typebot.io/commit/e22bd7dc9b1dc816f53d203d518d4643a958fbb7)] +- 🐛 (wordpress) Fix version mismatch for self-hosters for Standard embed as well [[eca6d20](https://github.com/baptisteArno/typebot.io/commit/eca6d207bf54499808b098a883cf399485ff3f25)] +- 🐛 Fix typebot parsing for legacy columnsWidth setting [[8d56349](https://github.com/baptisteArno/typebot.io/commit/8d563499f05a939a4deed1fea26f8397f53260f2)] +- 🐛 (fileUpload) Fix results file display if name contains comma [[bd198a4](https://github.com/baptisteArno/typebot.io/commit/bd198a4e0f0437eb5284f094e45e9af83acd3da3)] +- 🐛 (js) Fix default theme values css variables [[fd00b6f](https://github.com/baptisteArno/typebot.io/commit/fd00b6fdd56a2cbc8e7494aec680bc0bb51a4061)] +- 🐛 (billing) Set invoicing behavior to "always invoice" to fix double payment issue [[a1d7415](https://github.com/baptisteArno/typebot.io/commit/a1d7415227647b3fcf72652fb44dda65ce219510)] +- 🐛 (textBubble) Fix variable parsing when starting or finishing by spaces [[23625ad](https://github.com/baptisteArno/typebot.io/commit/23625ad214925db8a16128181dc25e6c2513038f)] +- 🐛 (webhook) Fix legacy webhook {{state}} body parsing [[63233eb](https://github.com/baptisteArno/typebot.io/commit/63233eb7eea6956ea2ce546b09246bb6df62c4f5)] +- 🐛 Fix theme background and font default selection [[e9a10c0](https://github.com/baptisteArno/typebot.io/commit/e9a10c078fbb3a9dd18f5f79ba83edcc72ae04f7)] +- 🐛 Sort variables to parse to fix text bubble parsing issue [[a38467e](https://github.com/baptisteArno/typebot.io/commit/a38467e5b2eb0fd2eed17a2062dd5fe93c0d0e75)] +- 🐛 (editor) Fix edge delete with undefined groupIndex [[647afdb](https://github.com/baptisteArno/typebot.io/commit/647afdb8faae73edfaffd55b0c29937ba2c87ea6)] +- 🚑 (webhook) Fix webhook execution with default method [[14a3716](https://github.com/baptisteArno/typebot.io/commit/14a37160fd7f6048f143a8a5568782a9034db1b1)] +- 🐛 (typebotLink) Fix link to first group with start event [[9bb5591](https://github.com/baptisteArno/typebot.io/commit/9bb559174ad8aabf0f3a43961f821bd78c0d436b)] +- 🚑 (zapier) Fix execute webhook endpoint too strict on block type check [[9eef166](https://github.com/baptisteArno/typebot.io/commit/9eef1665f536eae568970eb07764cd8b4e5f7f99)] +- 🚑 (editor) Fix move block with outgoing edge [[58b9e0b](https://github.com/baptisteArno/typebot.io/commit/58b9e0b3063a88a8873ac2df49b111c10efe8191)] +- 🐛 Fix default initial items in TableList [[b73ca7a](https://github.com/baptisteArno/typebot.io/commit/b73ca7a98a51d5a216730423640dc4f711d04ffc)] +- 🐛 Fix typebot publishing endpoint events parsing [[4b67f9e](https://github.com/baptisteArno/typebot.io/commit/4b67f9e2e2938dadc2c09f413f8aa51d10dd41de)] +- 🐛 (import) Fix import typebot files that does not have name field [[aceba0a](https://github.com/baptisteArno/typebot.io/commit/aceba0abd086426556f55a49f530b285c035e179)] +- 🚑 Fix parsing issue with new events field on ongoing session states [[db17a0f](https://github.com/baptisteArno/typebot.io/commit/db17a0f508a3557072b34fefaa5c6826c722eed3)] +- 🚑 Fix weird env parsing on Firefox making it crash [[eaa9b81](https://github.com/baptisteArno/typebot.io/commit/eaa9b815c40bf710d35268ed2d8d56e768299c27)] + +### Miscellaneous + +- 📝 Update Discord invite link [[27e9c1a](https://github.com/baptisteArno/typebot.io/commit/27e9c1adb96cfde57f84e877a945fc6ae514d09b)] +- 📝 Change community URLs, introduce Discord server [[8f224e3](https://github.com/baptisteArno/typebot.io/commit/8f224e32930c931d08b4543d9254714f303b953e)] +- 📝 Add OpenAI Dialogue option in breaking change doc [[c59df18](https://github.com/baptisteArno/typebot.io/commit/c59df18f2127f8c827dbda0ef9d49a6eae70974e)] +- 🧑‍💻 (chat) Introduce startChat and continueChat endpoints [[084588a](https://github.com/baptisteArno/typebot.io/commit/084588a086c22029e53ffdef7ae1fe81d7e413b7)] +- 🛂 Reduce sendMessage serverless function max memory [[bac2393](https://github.com/baptisteArno/typebot.io/commit/bac2393b5d7d14eb871945e84f260dcca72d3f65)] +- 📝 Add breaking changes and OpenAI block improvements docs [[df57841](https://github.com/baptisteArno/typebot.io/commit/df578417aa6a261e878f62d0c4865ef7d58f77c0)] +- fix: whole page overflowing on the x axis and displaying a horizontal scrollbar ([#1011](https://github.com/baptisteArno/typebot.io/issues/1011)) [[68e4fc7](https://github.com/baptisteArno/typebot.io/commit/68e4fc71fbee9f45e2869912798304493c75b1b0)] +- 🛂 Update Cache-Control header in generatePresignedPostPolicy [[027c6ff](https://github.com/baptisteArno/typebot.io/commit/027c6ffcef30ff9f091bf9100e584efcc490976b)] +- 📦 Add strict package versioning to avoid incompatibility in workspace [[0c22d85](https://github.com/baptisteArno/typebot.io/commit/0c22d858b749c0f39eb595ad6e8f74a497abc198)] +- 📝 Add UTM params forwarding video tutorial [[57e4540](https://github.com/baptisteArno/typebot.io/commit/57e454008e85c197ad25c78f069d4a4b97d43c6a)] + + + +## 2.19.0 (2023-11-02) + +### Changed + +- ⚡ Add cache-control header on newly uploaded files [[d1502f8](https://github.com/baptisteArno/typebot.io/commit/d1502f8300e85529f9a16e8376f83eb7ef8da556)] + +### Fixed + +- 🚑 Move cache control header into the post policy [[a855d85](https://github.com/baptisteArno/typebot.io/commit/a855d85d048bf7519699628d0bdf834752a54dbc)] +- ✏️ (billing) Fix plan name typo [[bdf9fae](https://github.com/baptisteArno/typebot.io/commit/bdf9faea78b61817ffbb185b4dcaa11d3b537e62)] +- 🐛 Fix formatted message in input block when input is retried [[a564181](https://github.com/baptisteArno/typebot.io/commit/a5641811a320d99867fef246786fae9980bce1d7)] +- ✏️ Fix CORSRules content typo for S3 config [[585e1d4](https://github.com/baptisteArno/typebot.io/commit/585e1d40749528bc69ffea385d2b6b21bac50ae4)] +- 🐛 (number) Fix number input validation with variables [[7586eca](https://github.com/baptisteArno/typebot.io/commit/7586ecaf139efcd3ab86a277cadd61c1a9d9c72f)] +- 🐛 Fix group duplicate new title bug [[2d1ce73](https://github.com/baptisteArno/typebot.io/commit/2d1ce73931221195c6838a384f64821fc837ccb3)] +- 💚 Fix checkAndReportChatsUsage script sending multiple emails at once [[3f7f094](https://github.com/baptisteArno/typebot.io/commit/3f7f0944e15e09c80e2b0aac9bb5100ab55a3526)] +- ✏️ Fix manual deployment doc start script typo [[a347a27](https://github.com/baptisteArno/typebot.io/commit/a347a2741d1c6671610f1f6431e8be1ab7fb3376)] +- 🐛 Fix graph flickering on high res displays ([#959](https://github.com/baptisteArno/typebot.io/issues/959)) [[f1e3836](https://github.com/baptisteArno/typebot.io/commit/f1e38361842432d0224da13379ea5b985cde555a)] + +### Miscellaneous + +- 📝 Add text link section in text bubble doc [[b80bea1](https://github.com/baptisteArno/typebot.io/commit/b80bea11b485707e3a0bbe51549e585f957ac8bf)] +- 📝 Add webhook configuration tuto video [[3e02436](https://github.com/baptisteArno/typebot.io/commit/3e02436d30946ac8732ffbb25acf7a109f9ccff6)] +- 🧑‍💻 Migrate to Tolgee ([#976](https://github.com/baptisteArno/typebot.io/issues/976)) [[bed8b42](https://github.com/baptisteArno/typebot.io/commit/bed8b42a2eb10bd81909ac38a6b3b51a423789c2)] +- 🧑‍💻 Fix type resolution for @typebot.io/react and nextjs [[31b3fc3](https://github.com/baptisteArno/typebot.io/commit/31b3fc311ede7885ff89ee41467308e718c92d4d)] + + + +## 2.18.4 (2023-10-25) + +### Fixed + +- 🚑 Fix can invite new members in workspace bool [[53558dc](https://github.com/baptisteArno/typebot.io/commit/53558dc3036d9839c07f99ab511c707f8a6fb24a)] +- 🐛 (numberInput) Fix input clearing out on dot or comma press [[4b248d5](https://github.com/baptisteArno/typebot.io/commit/4b248d554f54aafef105c1dcb842e3c5e1b28d5f)] +- ✏️ Fix popup blocked toast typo [[1ff5881](https://github.com/baptisteArno/typebot.io/commit/1ff58818a9b7f90eac70680b3af07990c42363e5)] + +### Miscellaneous + +- 🧑‍💻 (whatsapp) Improve whatsapp start log [[c2a08c4](https://github.com/baptisteArno/typebot.io/commit/c2a08c482efc30322b308880bb377e276f9cedfb)] + + + + +## 2.18.3 (2023-10-23) + +## Breaking change + +Billing has been upgraded to be usage-based. Stripe ENV variables have been simplified. Check the configuration for more information + +### Added + +- 👷‍♂️ Add convenient script for migrating Stripe prices [[11186d8](https://github.com/baptisteArno/typebot.io/commit/11186d8d297570270c4c0be17e2315041f8f3836)] +- 👷‍♂️ Improve getUsage accuracy in check cron job [[1cc4ccf](https://github.com/baptisteArno/typebot.io/commit/1cc4ccfcfa2b9876b02ca554f0d8aa1f61296596)] + +### Changed + +- 🚸 (buttons) Trim items content when parsing reply for better consistency [[621fcd5](https://github.com/baptisteArno/typebot.io/commit/621fcd59f10e56e21aa01b84f03da395f711e535)] +- ♻️ Update import contact to brevo script [[be9daee](https://github.com/baptisteArno/typebot.io/commit/be9daee63ea38533667680fe52d70abefc345f2c)] +- ⚡ (billing) Automatic usage-based billing ([#924](https://github.com/baptisteArno/typebot.io/issues/924)) [[797751b](https://github.com/baptisteArno/typebot.io/commit/797751b4185c871b79afef9827f4f9b9aae83366)] + +### Fixed + +- 🐛 Fixed pinch zooming mouse issue (with ctrl key) ([#940](https://github.com/baptisteArno/typebot.io/issues/940)) [[2c15662](https://github.com/baptisteArno/typebot.io/commit/2c15662ef2a21fdc40a4eaff4acb79394f1db166)] +- 🐛 Freeze body overflow when opening a Popup embed ([#937](https://github.com/baptisteArno/typebot.io/issues/937)) [[df3a17e](https://github.com/baptisteArno/typebot.io/commit/df3a17efa08696595bf0e16e4aa2b2187115638c)] +- 💚 Fix send email in CI "React is not defined" [[3e06d89](https://github.com/baptisteArno/typebot.io/commit/3e06d89873cd8177a54ffe2bcf75d7d3705ab854)] +- 🐛 (results) Lower the max limit in getResults endpoint to avoid payload size error [[885dcec](https://github.com/baptisteArno/typebot.io/commit/885dcecd8db922ff98c0676c44d9a25e7f7cd8d5)] +- 🚑 (billing) Fix chats pricing tiers incremental flat amou… [[6b0c263](https://github.com/baptisteArno/typebot.io/commit/6b0c263f885c091e81731230e012d33e223f0cfa)] +- 🐛 (webhook) Fix webhook response data key number parsing [[1d0aab7](https://github.com/baptisteArno/typebot.io/commit/1d0aab71f91e82bba77f73669828aae403f66d00)] + +### Miscellaneous + +- 🩹 Surround logs saving in a try catch block [[b301174](https://github.com/baptisteArno/typebot.io/commit/b3011741066e283013ffba3cb6eded6a46943d5e)] +- Fix audio content overflow in windows. ([#944](https://github.com/baptisteArno/typebot.io/issues/944)) [[eba52a5](https://github.com/baptisteArno/typebot.io/commit/eba52a5397cd2712fff71b20212283d60466943e)] +- 📝 Add bounties info in README [[a8c2deb](https://github.com/baptisteArno/typebot.io/commit/a8c2deb258589d458ed9d16cffb3e413612ba89d)] + + + +## 2.18.2 (2023-10-13) + +### Changed + +- ⚡ (video) Allow changing video height when resolved to an iframe [[ee685f1](https://github.com/baptisteArno/typebot.io/commit/ee685f14f3325a557dd3ef5277219fa3d6f5b4d5)] + +### Fixed + +- 🐛 (videoBubble) Fix youtube parsing for IDs containing a "-" [[ee7dfbf](https://github.com/baptisteArno/typebot.io/commit/ee7dfbf848be1b39a8e6bf5201e201015dea3c20)] +- 🐛 (textBubble) Fix overflow with long links [[9bbb30f](https://github.com/baptisteArno/typebot.io/commit/9bbb30f30d784d9d73bd04c578eef37651033cf0)] +- 🐛 Fix link parsing when using variables [[ad79178](https://github.com/baptisteArno/typebot.io/commit/ad791789ba30f57b8f26c24c8adfda76da57206c)] +- 🐛 (openai) Fix 2 openai streaming back to back [[42fd603](https://github.com/baptisteArno/typebot.io/commit/42fd6037f76c96ed0dfc0d5e66f818432e84b4f2)] +- 🚑 Fix empty bubble issue when plate element does not have a type attribute [[a48026c](https://github.com/baptisteArno/typebot.io/commit/a48026c707eb11e6e8e289075cdc0f88f6dd2f6f)] + +### Miscellaneous + +- 🐳 Force Next.js apps local hostname [[3ca5384](https://github.com/baptisteArno/typebot.io/commit/3ca5384e7f1e4818051978f77029c6ca29818bc6)] +- 📝 (openai) Add "Multiple OpenAI blocks" video section [[e071c81](https://github.com/baptisteArno/typebot.io/commit/e071c810aeb790d111636d513788324d0aec065b)] + + + +## 2.18.1 (2023-10-10) + +### Added + +- ✨ Automatically parse markdown from variables in text bubbles [[cfc5f64](https://github.com/baptisteArno/typebot.io/commit/cfc5f641a62847ef3b38194d87f89a39daeffabd)] + +### Changed + +- 🚸 (openai) Improve streaming bubble sequence and visual [[49826d1](https://github.com/baptisteArno/typebot.io/commit/49826d1303428854a61b8d3322b3f5fc7f0c2ae0)] +- ⬆️ Upgrade sentry and improve its reliability [[3e7b9b3](https://github.com/baptisteArno/typebot.io/commit/3e7b9b3afd3b42c96b61e0a223df45d97df434b4)] +- 🚸 (condition) Don't show value in node content if operator is "set" or "empty" [[224a08b](https://github.com/baptisteArno/typebot.io/commit/224a08b93279cb6baa94d67e577484d792f596f5)] +- ♻️ Remove sentry client monitoring in viewer [[073654e](https://github.com/baptisteArno/typebot.io/commit/073654e1e0064e740260bd7dea6cee558529827f)] +- 💄 Better parsing of lists and code in streaming bubbles [[877a58d](https://github.com/baptisteArno/typebot.io/commit/877a58dac2428e32d545dfc3307b17bc253af237)] +- 🚸 (openai) Improve streamed message lists CSS [[b232a94](https://github.com/baptisteArno/typebot.io/commit/b232a9495ef4168db7cc49734b9d676e5784c788)] +- ⬆️ (openai) Replace openai-edge with openai and upgrade next [[225dfed](https://github.com/baptisteArno/typebot.io/commit/225dfed313eb545c323485c9846b1e7d8f685c1b)] +- ♻️ (api) Auto start bot if starting with input [[9e6a1f7](https://github.com/baptisteArno/typebot.io/commit/9e6a1f7dc0c1a66b3811625b82a0b1b73aeb62ee)] +- 🚸 (videoBubble) Reparse variable video URL to correctly detect provider [[a7b784b](https://github.com/baptisteArno/typebot.io/commit/a7b784b446e085cdfe2c240bec33940a27f8a260)] +- 🚸 (sendEmail) Rename username SMTP creds label to avoid confusion [[42ae75c](https://github.com/baptisteArno/typebot.io/commit/42ae75cb11249926983e24792291fd4704b75ab9)] + +### Removed + +- 🔥 Remove streamer Pages API endpoint [[bf1f657](https://github.com/baptisteArno/typebot.io/commit/bf1f6576421e768f5c4506c5f0610ec2b3e05ae4)] + +### Fixed + +- 💚 Fix docker build when Sentry not enabled [[54788a8](https://github.com/baptisteArno/typebot.io/commit/54788a828ec92d8a24c580a3d29b6a450e0f65bc)] +- 🚑 Fix custom CSS sanitization [[8eb9f25](https://github.com/baptisteArno/typebot.io/commit/8eb9f2568bd6146ff45093c8c7bf2983a69e7cd6)] +- 🐛 (editor) Fix default branding settings on cre… [[258de60](https://github.com/baptisteArno/typebot.io/commit/258de60bd274c05c6783fb06b2458718a86baa04)] +- 🐛 Add no cache instructions to streamer [[4746e38](https://github.com/baptisteArno/typebot.io/commit/4746e38cb27185d3fe063eb7184c1d10f687c9a1)] +- 🐛 Enable stream again by migrating endpoint to route handler [[0ba13b4](https://github.com/baptisteArno/typebot.io/commit/0ba13b4df0febf96d900e5dc794bf42bb8092d66)] +- 🐛 New sendMessage version for the new parser [[3838ac9](https://github.com/baptisteArno/typebot.io/commit/3838ac9c3fbfa1ed85ed2390b2b3cb4a28698796)] +- 🚑 Fix text styling parsing on variables [[6f3e9e9](https://github.com/baptisteArno/typebot.io/commit/6f3e9e92512dc70849737bef2d07a78e997bf0f7)] +- 🚑 (results) Fix broken infinite scroll [[2bc9dfb](https://github.com/baptisteArno/typebot.io/commit/2bc9dfb503b52799fee84845d9ecd5d6a368dbb4)] +- 🐛 (whatsapp) Fix force create session when flow is completed at first round [[bf051be](https://github.com/baptisteArno/typebot.io/commit/bf051bebde1dfa14b759df604ded6d057b38f30c)] +- 🚑 (whatsapp) Fix start whatsapp session when user has multiple whatsapp enabled [[60c06aa](https://github.com/baptisteArno/typebot.io/commit/60c06aa9a95d4185c41f4159d08385ee9ce96ee9)] + +### Miscellaneous + +- 📝 (s3) Add s3 configuration detailed instructions [[021cae3](https://github.com/baptisteArno/typebot.io/commit/021cae3c294e61dacb27ee87e038ca1fd9bdd1af)] +- 🛂 Sanitize custom CSS and head code to avoid modification of lite badge [[8e54824](https://github.com/baptisteArno/typebot.io/commit/8e548248b169b31f5760d6afff809dcbda211220)] +- 📝 (embed) Add note about non-embeddable websites [[15823df](https://github.com/baptisteArno/typebot.io/commit/15823df6bd24a3c71974d1609a5c33421d5c5dfb)] +- 📝 (whatsapp) Remove private beta mention [[d567bed](https://github.com/baptisteArno/typebot.io/commit/d567bede6ed3d5d8d00361aef6b33e7750b01ddf)] +- 🐳 Remove wait-for-it script to avoid edge cases issues [[ee800d5](https://github.com/baptisteArno/typebot.io/commit/ee800d5ba278dc897659378c7cef39ec33b4ae7b)] +- 🧑‍💻 Improve invalid environment variable insight on build fail [[8b8a23a](https://github.com/baptisteArno/typebot.io/commit/8b8a23accb4fb1d05c8dbad10faaaf0dbdeca9f8)] +- 🛂 (whatsapp) Set default whatsapp expiry to 4 hours [[a53d128](https://github.com/baptisteArno/typebot.io/commit/a53d128fb0e7aed454bfc378d2746fdc16228d3a)] +- 🛂 (whatsapp) Disable whatsapp by default on duplication [[3292ccc](https://github.com/baptisteArno/typebot.io/commit/3292cccf5110ba37ad62e468870f19dba2925529)] +- 📝 (docker) Update postgres image name [[317a15b](https://github.com/baptisteArno/typebot.io/commit/317a15b708de6c4af0f439877f2b67534b2c50c4)] +- 📝 (vercel) Add a note on function maxDuration for Hobby plans [[4d475ff](https://github.com/baptisteArno/typebot.io/commit/4d475ff009a62202e18f4db2de21d9b5ef54d6ac)] +- 📝 (whatsapp) Re-organize whatsapp overview doc [[a102d45](https://github.com/baptisteArno/typebot.io/commit/a102d45da1f195b658519fc5bb89d219caf5fd94)] +- 🐳 Bump Postgres version in official docker compose file [[876625d](https://github.com/baptisteArno/typebot.io/commit/876625deb83c3061896dcac03cdbb82854c8db5c)] + + + +## 2.18.0 (2023-09-29) + +## What's new? + +- WhatsApp integration has been greatly improved. Also the documentation to set it up as a self-hosters has more details. + +- New [Zemantic AI](https://zemantic.ai/) bock. It's the first ever block contributed by the community 🥳 + +## Details + +### Added + +- ✨ (whatsapp) Add custom session expiration ([#842](https://github.com/baptisteArno/typebot.io/issues/842)) [[4f953ac](https://github.com/baptisteArno/typebot.io/commit/4f953ac272b1e2a826776f9d4cefcce63757abf1)] +- 👷‍♂️ Only build docker images on tag push [[4cfb45e](https://github.com/baptisteArno/typebot.io/commit/4cfb45e2a3432f91418be402b063c6ce9e5fd907)] +- 👷‍♂️ (vercel) Increase max execution duration for webhooks [[8f4e5b5](https://github.com/baptisteArno/typebot.io/commit/8f4e5b5d634fcb6d706117425f458f647c7751e4)] +- ✨ Add Zemantic AI Integration block ([#752](https://github.com/baptisteArno/typebot.io/issues/752)) [[75e4b16](https://github.com/baptisteArno/typebot.io/commit/75e4b16af0288ad4f6d7618f3439736d10fd5d87)] + +### Changed + +- 🚸 (whatsapp) Improve how the whatsapp preview behaves ([#873](https://github.com/baptisteArno/typebot.io/issues/873)) [[f016072](https://github.com/baptisteArno/typebot.io/commit/f016072e3eef021eb21d32922ce3931bc7306616)] +- 🚸 (pictureChoice) Allow dynamic picture choice with… ([#865](https://github.com/baptisteArno/typebot.io/issues/865)) [[76f4954](https://github.com/baptisteArno/typebot.io/commit/76f4954540b523733f92db5db55f4de842515971)] +- 🚸 (pictureChoice) Improve single picture choice with same titles [[d46e801](https://github.com/baptisteArno/typebot.io/commit/d46e8013d4d3e28eea099f8de8da9055d7d27723)] +- 🚸 (whatsapp) Improve upgrade plan for whatsapp notice [[ccc34b3](https://github.com/baptisteArno/typebot.io/commit/ccc34b30287cc26939d7435aae0e8773f5afa462)] +- 🚸 Better random IDs generation in setVariable [[a176e23](https://github.com/baptisteArno/typebot.io/commit/a176e23cc8c3d82c66df71b741527dd0210c5177)] +- ⚡ (setVariable) Add "Environment name" value in Set variable block ([#850](https://github.com/baptisteArno/typebot.io/issues/850)) [[1ca742f](https://github.com/baptisteArno/typebot.io/commit/1ca742fc0b83e7dc429872816967d767101eedb2)] +- ⚡ Auto continue bot on whatsApp if starting block is input ([#849](https://github.com/baptisteArno/typebot.io/issues/849)) [[b81fcf0](https://github.com/baptisteArno/typebot.io/commit/b81fcf0167e332d6559e44ce409c44ce87316f55)] +- ⚡ (wordpress) Add query params exclusion support [[2307231](https://github.com/baptisteArno/typebot.io/commit/2307231d283ee6af5948ed4941ea06d7627cbdca)] +- ♿ (embed) Add aria-label to bubble button [[90cf2e9](https://github.com/baptisteArno/typebot.io/commit/90cf2e9f81ad938c068dd04ed4346910fe238a60)] +- ⚡ (whatsapp) Improve whatsApp management and media collection [[9e0109f](https://github.com/baptisteArno/typebot.io/commit/9e0109f561591db485626841856f83d13cde4246)] +- ♻️ Remove storage limit related code [[d7dc5fb](https://github.com/baptisteArno/typebot.io/commit/d7dc5fb5fb7bd07b477470c4941f9fc57d7f08b0)] +- ♻️ Export bot-engine code into its own package [[7d57e8d](https://github.com/baptisteArno/typebot.io/commit/7d57e8dd065c01b90c4eb03ccfdbc3b73da85c23)] +- ⚡ (whatsapp) Improve WhatsApp preview management [[f626c98](https://github.com/baptisteArno/typebot.io/commit/f626c9867cb324b8546e8fca40fe8065ff36b5c4)] +- 🚸 (results) Use header id as table accessor to allow duplicate names [[61c46bc](https://github.com/baptisteArno/typebot.io/commit/61c46bcb465ff1a0fd769b02e20c981037a4dfaa)] +- ⚡ (customDomain) Add configuration modal for domain verification [[322c48c](https://github.com/baptisteArno/typebot.io/commit/322c48cddcbf348ab44850499e849d124b9adfed)] +- 🚸 (typebotLink) Make sure variables from child bots are merged if necessary [[21ad061](https://github.com/baptisteArno/typebot.io/commit/21ad061f7bcc001be884c3db033c97f7baab718d)] +- 🚸 (billing) Improve feedback when subscription is "past_due" [[0ccc2ef](https://github.com/baptisteArno/typebot.io/commit/0ccc2efa454e3a0f2c9b7a633b241175d4ee8dac)] +- ⚡ (analytics) Keep track of already explored blocks for drop off rate [[87fac3e](https://github.com/baptisteArno/typebot.io/commit/87fac3e9ffe68965a569d01888d277950c7732d7)] +- 🔧 Add recommended vscode extensions and more settings [[eea5d82](https://github.com/baptisteArno/typebot.io/commit/eea5d82f4047534162d9c939b24399b49dc66b3f)] +- ⚡ (s3) Improve storage management and type safety [[fbb198a](https://github.com/baptisteArno/typebot.io/commit/fbb198af9de1e8e44184373a36973a90c8f77b5f)] +- ⚡ (date) Add min and max options to date input block [[a2e24d0](https://github.com/baptisteArno/typebot.io/commit/a2e24d08a0feba9c5c73339a0d0e0733b3b1c30c)] +- ♻️ (lp) Add back static images into landing page [[cdd3e19](https://github.com/baptisteArno/typebot.io/commit/cdd3e197557b913ea04617d9a2f9fcae9759f92e)] + +### Fixed + +- 🐛 (builder) Fix system color mode not syncing properly [[b31bcdf](https://github.com/baptisteArno/typebot.io/commit/b31bcdfb87d19facfc46f8800f9b562e5b615c1b)] +- 🚑 (js) Fix dependency issue preventing user to install @typebot.io/js [[59cd79a](https://github.com/baptisteArno/typebot.io/commit/59cd79a4b85195e5d3573891f8a942c639cf2fe6)] +- 🐛 (typebotLink) Fix nested typebot link pop [[cd97da2](https://github.com/baptisteArno/typebot.io/commit/cd97da2d34fcf576100d03fa30608ce26f1784c4)] +- 🐛 (whatsapp) Fix auto start input where it didn't display next bu… ([#869](https://github.com/baptisteArno/typebot.io/issues/869)) [[f9a14c0](https://github.com/baptisteArno/typebot.io/commit/f9a14c0685826a00a1873d17baafbe950fab55e0)] +- 🐛 (whatsapp) Fix preview failing to start and wait timeo… [[e10a506](https://github.com/baptisteArno/typebot.io/commit/e10a506c9608dafd9462ea6d20d698551eb751c1)] +- 🐛 (preview) Fix always displayed start props toast [[99b0025](https://github.com/baptisteArno/typebot.io/commit/99b0025a664f951629899160f8ecea42046221b4)] +- 🐛 (pixel) Fix multiple Meta pixels tracking [[56e175b](https://github.com/baptisteArno/typebot.io/commit/56e175bda6df960f6a5f32d7fd5b5f4bdddd8d56)] +- 🚑 (fileUpload) Fix file upload in linked typebots [[7b3cbdb](https://github.com/baptisteArno/typebot.io/commit/7b3cbdb8e8a2dbdfa030ca782a186d9a449ff6d9)] +- 🐛 (bot) Fix reactivity issue when filtering single choices [[459fc4d](https://github.com/baptisteArno/typebot.io/commit/459fc4debc621cdd9f134f81443b4b9c58c93664)] +- 🚑 (billing) Fix disabled upgrade buttons [[ed60caa](https://github.com/baptisteArno/typebot.io/commit/ed60caa8060d6df4492958854f1bcd114b101b17)] +- 💚 Rename back viewer [[4673989](https://github.com/baptisteArno/typebot.io/commit/4673989104f00aeef8a68916b5b4ec55c063437e)] +- 🚑 (upload) Fix upload in embed [[85272af](https://github.com/baptisteArno/typebot.io/commit/85272af8f3c3ef9a9b8fed6161a85d1632404e9b)] +- 🚑 Fix file upload expiration issue [[9d80a3f](https://github.com/baptisteArno/typebot.io/commit/9d80a3f68b972cc649400cd7de26191c4e72e7e8)] +- 🐛 (results) Fix result modal content display [[2ce63f5](https://github.com/baptisteArno/typebot.io/commit/2ce63f5d06515f7808db0bd9abfb0bf9aeb48cbd)] +- 🐛 (payment) Fix postalCode camel case issue [[69ef41b](https://github.com/baptisteArno/typebot.io/commit/69ef41b5347c08049a88a321eaf86657f62f9490)] +- 🐛 Fix bubble icon file upload [[6548752](https://github.com/baptisteArno/typebot.io/commit/6548752b1bd29fbe3acab7efcaf4733fd80708e8)] +- 🐛 (openai) Fix models dropdown list on new block [[096262c](https://github.com/baptisteArno/typebot.io/commit/096262cff9aa6d79e75dba3b07ce91fd2c8e6794)] +- 💚 Remove defineLocale weird TS bug [[59cc450](https://github.com/baptisteArno/typebot.io/commit/59cc450fd36a646230b31c431ab6b33586aa158b)] +- 🚑 (typebotLink) Correctly pass back existing values from parent bot [[bea3332](https://github.com/baptisteArno/typebot.io/commit/bea3332c3248a9b3896c74c7fe6dbf21f4229d4e)] + +### Miscellaneous + +- 📝 Update About page content [[129f558](https://github.com/baptisteArno/typebot.io/commit/129f5582db4e2970a7cb177ef2abb79f47159a99)] +- 🛂 (whatsapp) Remove feature flag [[0e4e10c](https://github.com/baptisteArno/typebot.io/commit/0e4e10c77b0d960ce268ebe2d25600812560e733)] +- 📝 (typebotLink) Add instructions about shared variables and merge answers [[1a4b8bb](https://github.com/baptisteArno/typebot.io/commit/1a4b8bb8fcc3fdf9d8dfae7bc31036eea9df99c0)] +- 📝 (whatsapp) Add a "Create WhatsApp app" guide [[ec52fdc](https://github.com/baptisteArno/typebot.io/commit/ec52fdc0ade4fd3acb651e8eae754269ac8cb6f7)] +- 🛂 Improve editor authorization feedback ([#856](https://github.com/baptisteArno/typebot.io/issues/856)) [[801fea8](https://github.com/baptisteArno/typebot.io/commit/801fea860a9940a6a87b6c4c147c6da6c3234df3)] +- 📝 Add custom domain troobleshoot section [[bad415a](https://github.com/baptisteArno/typebot.io/commit/bad415ae1ff2c9d7bfe4584e042699466a91d9a0)] +- 📝 Change googleSheets date system var name [[797685a](https://github.com/baptisteArno/typebot.io/commit/797685aa9d3de68afedc7515aaaeb6ef972d6b7c)] +- 🛂 (fileUpload) Improve file upload size limit enforcement [[bb13c2b](https://github.com/baptisteArno/typebot.io/commit/bb13c2bd61870a8da18bcf1a00dc85d79ec1f9c9)] +- 📝 Update support contact email [[6375a24](https://github.com/baptisteArno/typebot.io/commit/6375a2425fe5c8a2296effd7136d1fe7d7667295)] +- 📝 (vercel) Add disable github workflows section [[43be38c](https://github.com/baptisteArno/typebot.io/commit/43be38cf50732ae5336f3dc651f95ab782f57c19)] + + + +## 2.17.2 (2023-09-07) + +### Added + +- 👷‍♂️ Remove docker main tag building [[a0df851](https://github.com/baptisteArno/typebot.io/commit/a0df85108f9216bdb5005b15334d074c30a65f1d)] + +### Fixed + +- 💚 Fix docker deployment tagging [[f14808d](https://github.com/baptisteArno/typebot.io/commit/f14808dfcb761d2a0b471f94f6dba9aaf27cd577)] +- 💚 Fix docker multi arch overwrite issue ([#779](https://github.com/baptisteArno/typebot.io/issues/779)) [[b90b6d0](https://github.com/baptisteArno/typebot.io/commit/b90b6d0b255c2ecdab8782151d714d46ae1d961b)] + + + +## 2.17.1 (2023-09-06) + +### Changed + +- ⚡ (dateInput) Add format option and improve parsing [[9e8fa12](https://github.com/baptisteArno/typebot.io/commit/9e8fa124b5851a78ac1f544e940e84a8175e1875)] +- ⚡ (wait) Add pause option on Wait block [[111fb32](https://github.com/baptisteArno/typebot.io/commit/111fb323b11a2b94abedfd63e6faf29794226710)] +- 🚸 Make sure to add start client side action first in the list [[1ebacaa](https://github.com/baptisteArno/typebot.io/commit/1ebacaaa5db4d8f03fe28442b9c0e7a075f919ac)] +- ⚡ (openai) Add custom provider and custom models [[27a5f4e](https://github.com/baptisteArno/typebot.io/commit/27a5f4eb74f6366181c6792e3efbf615b0af79bf)] + +### Fixed + +- 🚑 Fix pt-BR i18n loading [[be0c619](https://github.com/baptisteArno/typebot.io/commit/be0c619316261b5290463333b9fb29e8063a69b5)] +- 🐛 Fix select text in buttons node drag [[5092e14](https://github.com/baptisteArno/typebot.io/commit/5092e142ec3f74e9594be967cfa96ebd5162b805)] +- 🚑 (openai) Fix create credentials modal not displaying [[e8eaac4](https://github.com/baptisteArno/typebot.io/commit/e8eaac45fab2d4974038a97fa46d35c362ecfd9f)] +- 🚑 (fileUpload) Fix web bot file upload input skip option [[968c5e3](https://github.com/baptisteArno/typebot.io/commit/968c5e3c95c952bbb869d137ce22ca9d94e9cfbb)] + +### Miscellaneous + +- 🧑‍💻 (editor) Add group info in focus toolbar [[ac899b3](https://github.com/baptisteArno/typebot.io/commit/ac899b3181ddb0bfb755143a821d354ff32049ef)] +- 📝 Add user preferences doc [[605132e](https://github.com/baptisteArno/typebot.io/commit/605132ec3c817a20a99feb82751347ef50ffa4ef)] +- 🌐 Add pt_BR and more translations ([#767](https://github.com/baptisteArno/typebot.io/issues/767)) [[aaa208c](https://github.com/baptisteArno/typebot.io/commit/aaa208cef451eb58ef26003e3ed2dda8f6972107)] +- 🌐 Add i18n-ally config and upgrade next-international [[e4ece31](https://github.com/baptisteArno/typebot.io/commit/e4ece315edaff157fdd3d841f8e88ce589507015)] +- Docker improvements ([#760](https://github.com/baptisteArno/typebot.io/issues/760)) [[66dc570](https://github.com/baptisteArno/typebot.io/commit/66dc5705270e81938bddfc2b8df1a340a065376e)] +- 📝 Add cancel subscription doc [[a79e605](https://github.com/baptisteArno/typebot.io/commit/a79e605285e306e81dfdba03d51d7c986def5862)] +- 🛂 (whatsapp) Disallow test numbers as they are not unique [[60abddd](https://github.com/baptisteArno/typebot.io/commit/60abddd86e7c32a502d5cc506a5d0fb5e7910c8f)] + + + +## 2.17.0 (2023-09-01) + +### Breaking changes + +Environment management has been improved and merged between builder and viewer. + +If your viewer app do not have the required `NEXTAUTH_URL` env variable, you need to add it. + +## What's new? + +WhatsApp integration is now available 🥳. If you are self-hosting Typebot, refer to the configuration doc (https://docs.typebot.io/self-hosting/configuration#whatsapp-preview) + +Typebot validation has been improved. We make sure that your typebot is valid before storing it in the database, it allows us to avoid unexpected errors. + +New API endpoints: + +- Create typebot +- Update typebot +- Publish typebot + and others... + +## Details + +### Added + +- 🔊 Add logs to debug invalid env [[96ddfad](https://github.com/baptisteArno/typebot.io/commit/96ddfadaa7c2a64a62d59d6522104bbfff3b22ad)] +- ✨ Add WhatsApp integration beta test ([#722](https://github.com/baptisteArno/typebot.io/issues/722)) [[b852b4a](https://github.com/baptisteArno/typebot.io/commit/b852b4af0b3ad581deb00b5d032a3db8a90b6435)] +- 📈 Remove user email from Sentry tracking [[a4f7f8f](https://github.com/baptisteArno/typebot.io/commit/a4f7f8fae72b810e08ebdc55bc79a02cbb1b7f4f)] +- ✨ (api) Add CRUD typebot endpoints [[454d320](https://github.com/baptisteArno/typebot.io/commit/454d320c6b75c1e10dc5f2b43f01ebf87cf6ae13)] +- 🔊 Add debug log for item matching issue [[a72cb5e](https://github.com/baptisteArno/typebot.io/commit/a72cb5e20d1a92bba3509a2a2d0005798846a680)] + +### Changed + +- 🚸 (sendEmail) Improve variable parsing in sendEmail body [[37ccb5d](https://github.com/baptisteArno/typebot.io/commit/37ccb5da5eab5aaba85c1f40c62e957137597b91)] +- 🚸 (bot) Don't auto scroll if a text bubble was streamed [[5fb17db](https://github.com/baptisteArno/typebot.io/commit/5fb17dbf9e9c31f503e068847e14a2e2fc71381e)] +- 🚸 Skip validation if \_\_ENV.js file does not exist [[dfcfdf2](https://github.com/baptisteArno/typebot.io/commit/dfcfdf213857995811f5e71088c1c70d07de6cfc)] +- ♻️ Move s3-related files to specific lib folder [[23b629f](https://github.com/baptisteArno/typebot.io/commit/23b629f82cfecf5656bb91c0524d9e04679454fa)] +- 🚸 (whatsapp) Allow test phone numbers [[5d402d9](https://github.com/baptisteArno/typebot.io/commit/5d402d9a38650224ea5d614233a90e70f2107781)] +- 🚸 (editor) Avoid highlighting variables in text bubble if not created [[a0a7196](https://github.com/baptisteArno/typebot.io/commit/a0a719626c38dac2609716d3c9b4f46b905ddbc7)] +- 🚸 (openai) Implement retries if openai rate limit reached [[d700af1](https://github.com/baptisteArno/typebot.io/commit/d700af17e9b65cadef3dcda74d0ed4f9e1f587b6)] +- ⚡ (typebotLink) Better typebot link with merge option [[ee3b94c](https://github.com/baptisteArno/typebot.io/commit/ee3b94c35d670d4c514082d70542a2e0d50ae1c4)] +- 🚸 Improve parsing preprocessing on typebots [[0acede9](https://github.com/baptisteArno/typebot.io/commit/0acede92effdf9c2a069181e612dbdf06c1e788b)] +- 🚸 (billing) Make sure customer is not created before launching checkout page [[53dd7ba](https://github.com/baptisteArno/typebot.io/commit/53dd7ba499400aca415e1c4e5707788eb3505ad5)] +- ⚡ (customDomains) Fix custom domain update feedback [[c08e0cd](https://github.com/baptisteArno/typebot.io/commit/c08e0cdb0ac03d747f70f6983303a88ab9bbfdea)] +- 🚸 Loosen file import parsing strictness [[19fc576](https://github.com/baptisteArno/typebot.io/commit/19fc576957af972668a46a6664f560c3d6a66918)] +- ⬆️ Upgrade next packages" [[22cedb3](https://github.com/baptisteArno/typebot.io/commit/22cedb379d91d33ef12f7a2f849d6feaabb85076)] +- ⬆️ Upgrade next packages [[401efa9](https://github.com/baptisteArno/typebot.io/commit/401efa9d0c206796867508e3bfae8f607ded6be7)] +- ♿ (embed) Customizable preview message close button [[6786db8](https://github.com/baptisteArno/typebot.io/commit/6786db80ee00bd38c76031e45ae57bcb00d667d6)] +- 🚸 (webhook) Parse user email instead of test email for sample [[0078d6d](https://github.com/baptisteArno/typebot.io/commit/0078d6da718586ce407c5786cd9dfdf86174610e)] +- 🚸 (openai) Add payment method alert in credentials modal [[7c81d0c](https://github.com/baptisteArno/typebot.io/commit/7c81d0cbab543fbe70c464416c024ab933a0d5e5)] +- ♿ Remember last typebot viewed for support bubble [[330d399](https://github.com/baptisteArno/typebot.io/commit/330d399c42276f3b6dd015facab4f83788e35d60)] +- 🔧 Add prettier dependency at root folder [[693631e](https://github.com/baptisteArno/typebot.io/commit/693631e076b8316e54c071e19ac7e599145426ce)] +- 🚸 (webhook) Improve deep keys parser [[9171727](https://github.com/baptisteArno/typebot.io/commit/9171727569d02d64d3adfae25a0a7e4890fe9aaf)] +- 🚸 (bot) Update reply if we get new format from backend [[af1bee8](https://github.com/baptisteArno/typebot.io/commit/af1bee8756015557f1aec44d11a9f9b1fc8fed6e)] +- 💄 (textInput) Show send icon if send label is empty [[ec0a5be](https://github.com/baptisteArno/typebot.io/commit/ec0a5be793f9b88ed617c87f517a2844432e2480)] +- 🚸 (setVariable) Rename Today setVar type to Now [[4d3f67c](https://github.com/baptisteArno/typebot.io/commit/4d3f67c75212fc90b3fc8031c84e5b39d759f83c)] +- ⚡ (audio) Add autoplay switch in settings [[037d4ce](https://github.com/baptisteArno/typebot.io/commit/037d4ce345ce545e29a81b9bb97205145fdacc34)] +- ♻️ (webhook) Integrate webhook in typebot schema [[fc25734](https://github.com/baptisteArno/typebot.io/commit/fc25734689b65c17f84eb03496a729dba0945ea9)] +- ⚡ Add API endpoint to update the typebot in ongoing chat session [[53e4bc2](https://github.com/baptisteArno/typebot.io/commit/53e4bc2b759ada4f43175493f5333dbff917dea9)] +- 🚸 (openai) Display OpenAI initial response error [[c534613](https://github.com/baptisteArno/typebot.io/commit/c5346130875365a3be287c1447ed2db8d3147809)] + +### Removed + +- 🔥 Remove cloudron-specific files [[3d7f778](https://github.com/baptisteArno/typebot.io/commit/3d7f778deefab2c6edf3fa4d102d13326c31c134)] +- ➖ Use minio for presigned urls and remove aws sdk [[9a79bc3](https://github.com/baptisteArno/typebot.io/commit/9a79bc38ee5af4131f862ffd0d9861e7ae70b1e5)] + +### Fixed + +- 🐛 Fix forced color mode localStorage sync issue [[6a0f6e4](https://github.com/baptisteArno/typebot.io/commit/6a0f6e4ef241541b215eb1966e6d5cc9e862250e)] +- 🐛 Fix persistence when user selects system color mode [[ce9ad8b](https://github.com/baptisteArno/typebot.io/commit/ce9ad8b9702bc68edb3699bde89e8cc520bcad27)] +- 🐛 Fix remembered user reset hasStarted on page refresh [[9d29a88](https://github.com/baptisteArno/typebot.io/commit/9d29a88ed3c6260d2cbbdf20398bcae2c8cae49a)] +- 🐛 (fileUpload) Make file type optionnal [[124cb8f](https://github.com/baptisteArno/typebot.io/commit/124cb8f359363259befd3ee0b5aade19194fbcde)] +- 💚 Make sure \_\_ENV.js file is properly cached [[a1179e3](https://github.com/baptisteArno/typebot.io/commit/a1179e39343ce150a84cf0bc48446f3c321b9d9e)] +- 🐛 (embed) Make sure env.ts is not bundled in js embed lib [[da4005e](https://github.com/baptisteArno/typebot.io/commit/da4005e160bbab1622d8b667f5a851b8009cb4db)] +- 🐛 (embed) Fix env reading in embed [[5b20f41](https://github.com/baptisteArno/typebot.io/commit/5b20f414c836715e3f3791607f1e93ce258994b0)] +- 🐛 Fix delete session with client side actions [[013c7a6](https://github.com/baptisteArno/typebot.io/commit/013c7a62652a30ac8fac42b508f139049da06256)] +- 🐛 Improve parse runtime env reading function [[036b407](https://github.com/baptisteArno/typebot.io/commit/036b407a11c5151e55bf7639a0779bb66f5399b7)] +- 🚑 Set proper env defaults [[efd4600](https://github.com/baptisteArno/typebot.io/commit/efd4600b7eea86f33c39365c5269ccc727d9b8c3)] +- 💚 Add required env to github workflows [[1c680c3](https://github.com/baptisteArno/typebot.io/commit/1c680c3ef55b96c8f69104d80e7da5d3b3556223)] +- 🚑 (lp) Fix environment injection in landing page [[6dc9b28](https://github.com/baptisteArno/typebot.io/commit/6dc9b28f7ddd06621d6b13f591e0920f908b1c48)] +- 🐛 (webhook) Fix saving invalid webhook when duplicated [[a23a8c4](https://github.com/baptisteArno/typebot.io/commit/a23a8c4456d5bc63b45a8bbd5497e2d6ef0fce11)] +- 🚑 (typebotLink) Fix incoming linked typebot variables filling [[055cf03](https://github.com/baptisteArno/typebot.io/commit/055cf03703994f3d38397e82323b736e1a7821ba)] +- 🚑 Properly preprocess typebot version [[793218a](https://github.com/baptisteArno/typebot.io/commit/793218a6735c72ec2d3115b7077134f572a40e4e)] +- 🐛 (sendMessage) Correctly preprocess and parse fetched bot [[06ecdf0](https://github.com/baptisteArno/typebot.io/commit/06ecdf040e66c68e93aaaafcace032949e8c9137)] +- 🐛 Fix legacy publicId format validation [[fe54888](https://github.com/baptisteArno/typebot.io/commit/fe54888350d6e48bee26327e671662d00895c7a9)] +- 🐛 (customDomains) Transform name to lower case before validating [[83352d7](https://github.com/baptisteArno/typebot.io/commit/83352d77f5cd08c2740661dc8096d7d289f8f130)] +- 🐛 (billing) Fix cancel webhook when publishedTypebot does not exist [[6240fd9](https://github.com/baptisteArno/typebot.io/commit/6240fd982b0d923d27537ddc0e0eed3af1e9303b)] +- 🐛 Fix getUsage query abort [[dc4c19a](https://github.com/baptisteArno/typebot.io/commit/dc4c19a7550f05588c8eb0adcc53019b4d620cd2)] +- 🐛 (webhook) Fix variable list parsing in custom body [[ed77f5d](https://github.com/baptisteArno/typebot.io/commit/ed77f5d1244cc35d71ac5897c6617f93b94f5a58)] +- 🐛 Stop refresh typebot when typebotId is undefined [[e2075d6](https://github.com/baptisteArno/typebot.io/commit/e2075d6135623feb5f03344d190dedeffa397b65)] +- 🐛 Parse valid publicId even though the prefix is empty [[a4ba9a8](https://github.com/baptisteArno/typebot.io/commit/a4ba9a8a7787eeaa29705b9a4688b3dcfe18d879)] +- 🚑 Fix issue when duplicating bot losing groups [[9cfca38](https://github.com/baptisteArno/typebot.io/commit/9cfca3857e0ea34e3d9453600ad5e6ea82b01916)] +- 🐛 Remove publicId and customDomain duplication on imported bots [[304dfe2](https://github.com/baptisteArno/typebot.io/commit/304dfe2dab6d10e28d9d3f0083117b16bfbec030)] +- 🚑 Fix customDomain regex validation [[fca5865](https://github.com/baptisteArno/typebot.io/commit/fca5865999d0e6569d65443582247ada76f5f0b5)] +- 🐛 Deprecate blockId field in items [[019f72a](https://github.com/baptisteArno/typebot.io/commit/019f72ac7e3aaeead1278b4661460e8011f34da6)] +- 🐛 (editor) Fix edges connection issue when item.blockId does not match [[1cc282a](https://github.com/baptisteArno/typebot.io/commit/1cc282a5fc23f7534ee3358c9d97717a76901d24)] +- 🚑 Incorrect blockId in item when duplicating issue [[1274d25](https://github.com/baptisteArno/typebot.io/commit/1274d2581d427856509d40ad57e55f13eaf21fb5)] +- 🐛 (auth) Fix redirect URL after sign in [[d31500e](https://github.com/baptisteArno/typebot.io/commit/d31500e2e3b629371196f74867fcc752c92566b9)] +- 🐛 Normalize user inputs before comparing [[2b4ada0](https://github.com/baptisteArno/typebot.io/commit/2b4ada007d676dcf717d5b077f59738988e247c4)] +- 🚑 Add missing await on executeGroup [[2c4762b](https://github.com/baptisteArno/typebot.io/commit/2c4762b57f32e0f2748fd5ba72ed9ad0d4782605)] +- 💚 Add conditional rewrites for NEXTAUTH_URL targets [[bd9c8ea](https://github.com/baptisteArno/typebot.io/commit/bd9c8eac4c64d5d0bfbd392957a6b5fc6a6734d1)] + +### Security + +- 🔒 Improve workspace API role filtering [[906845b](https://github.com/baptisteArno/typebot.io/commit/906845bd767f730400c97f060c8b051ca2497582)] +- 🔒 Expose minimum data to NEXT_DATA json [[de616ea](https://github.com/baptisteArno/typebot.io/commit/de616ea649f1e12599ef2c216d4e46588e6846ad)] + +### Miscellaneous + +- 🐳 Fix docker image runtime error [[1aa0171](https://github.com/baptisteArno/typebot.io/commit/1aa017153a4108837a7ba35afe44764eb4f440c6)] +- 🛂 Send alert emails only to workspace admins [[6207edf](https://github.com/baptisteArno/typebot.io/commit/6207edfeefabd01c0ebdea62223218a159bb70e6)] +- 📝 Add troobleshoot section in Audio bubble doc [[baa13c3](https://github.com/baptisteArno/typebot.io/commit/baa13c3fa2862d9f53f0c8e9eb78afe5e22cddea)] +- 📝 Fix iframe's style instruction invalid quotes [[90c8c80](https://github.com/baptisteArno/typebot.io/commit/90c8c809deb028b2582f085647602a25a74a0b09)] +- 📝 Temporarily fix docker files starter urls [[da272f2](https://github.com/baptisteArno/typebot.io/commit/da272f2f9c0041fa2f5b8ce4c1c0da8258e666c7)] +- 🧑‍💻 Improve env variables type safety and management ([#718](https://github.com/baptisteArno/typebot.io/issues/718)) [[786e5cb](https://github.com/baptisteArno/typebot.io/commit/786e5cb58267bf1f19b57ae35cf415a21e4cfa54)] +- 📝 Fix invalid custom CSS line in HTML instructions [[b74117d](https://github.com/baptisteArno/typebot.io/commit/b74117d417a315997bcca1480bd31457f17be642)] +- 📝 Add Sheets advanced example video [[27b15a0](https://github.com/baptisteArno/typebot.io/commit/27b15a0f10ec85e2e146837c00d0c7472fd52428)] +- 🛂 Check if isQuarantined can be toggled on sub update [[e62e71c](https://github.com/baptisteArno/typebot.io/commit/e62e71c13319467d0e0e05d037edcec0c3a0b95e)] +- 📝 Add redirect URL with UTM instructions [[8810aa8](https://github.com/baptisteArno/typebot.io/commit/8810aa8ddb1e4062dfe09a3c15ee53fa693cbf0a)] +- Fix: typo in docker-compose.build.yml ([#692](https://github.com/baptisteArno/typebot.io/issues/692)) [[f508c97](https://github.com/baptisteArno/typebot.io/commit/f508c97ee17c21ebf9833f020cf01ea3a84a2116)] +- Use bulleseye docker image for better compatibility ([#618](https://github.com/baptisteArno/typebot.io/issues/618)) [[e9fac29](https://github.com/baptisteArno/typebot.io/commit/e9fac29886493f1e79d94afc1c20b3da3187a69d)] +- 📝 Dynamic oss-friends landing page [[1ae3029](https://github.com/baptisteArno/typebot.io/commit/1ae302984314c434a2072ea0c65261dd04eb197a)] +- 📝 (sendMessage) Improve sendMessage API ref [[f7de116](https://github.com/baptisteArno/typebot.io/commit/f7de11611ff1b86433243bc89d75a4779c25e7ce)] + + + +## 2.16.0 (2023-08-01) + +### Added + +- ✨ Stream bubble content if placed right after Op… [[3952ae2](https://github.com/baptisteArno/typebot.io/commit/3952ae2755ac2806055072d5cfa4cd32a01693f6)] + +### Changed + +- 💄 Improve multiple choice color when image background [[ee067ce](https://github.com/baptisteArno/typebot.io/commit/ee067ceee1011d946061e9d44abcf789f1000388)] +- ⚡ (condition) Add regex comparison item [[aa9f5bc](https://github.com/baptisteArno/typebot.io/commit/aa9f5bc7322e85e625852d71a5623c16cf485420)] +- 💄 (embed) Improve avatar alignment and audio auto load [[14c3d95](https://github.com/baptisteArno/typebot.io/commit/14c3d95b8aae8897932fc1e7969c2eefe175e33c)] +- ⚡ (video) Detect youtu.be URLs for video bubbles [[e34b939](https://github.com/baptisteArno/typebot.io/commit/e34b939786dd01aa912835b4c23c747051ba28db)] +- ⚡ (paymentInput) Handle Stripe redirection [[c99298e](https://github.com/baptisteArno/typebot.io/commit/c99298e49b8dc722f7259703f22cef8dc99a919f)] +- 🔧 Add import contact to brevo script [[c124671](https://github.com/baptisteArno/typebot.io/commit/c124671682930fca9bbaace5a007ea0aaba32f15)] +- 💄 Fix round icons color in dark mode [[4607f0e](https://github.com/baptisteArno/typebot.io/commit/4607f0ea39fd3c35ab839c902a15f6c90ed6cc8f)] +- 🚸 New dedicated onboarding page [[43555c1](https://github.com/baptisteArno/typebot.io/commit/43555c171ea48181e67defa0fa9cc5b3e22d0fea)] +- 🚸 Update onboarding bot [[283c55c](https://github.com/baptisteArno/typebot.io/commit/283c55c1a406320d2cbefb50c70ab92440f3d401)] +- ⚡ (embed) Add customizable bubble close icon [[c8bc659](https://github.com/baptisteArno/typebot.io/commit/c8bc659941ff9583299397baee33dadb5f6a2618)] +- ⚡ Replace Google fonts with Bunny fonts [[cccf905](https://github.com/baptisteArno/typebot.io/commit/cccf905d38204c466e3ae6476152a2f266ca4e06)] +- ⚡ (video) Add youtube shorts auto parsing [[1ebd528](https://github.com/baptisteArno/typebot.io/commit/1ebd528753909282adf4c15476a7ed3f4c822b76)] +- ⚡ Regroup database queries of /sendMessage in one place [[aa4c16d](https://github.com/baptisteArno/typebot.io/commit/aa4c16dad78e7e4dcd9b78f9b4916fd416da3c5f)] +- ⬆️ Upgrade giphy package [[1095cf7](https://github.com/baptisteArno/typebot.io/commit/1095cf7f0908da2660341471ab6cd9442bb8dfd3)] + +### Fixed + +- 🐛 (embed) Fix custom close icon placement in bubble button [[81c2e50](https://github.com/baptisteArno/typebot.io/commit/81c2e5022bec0e0a5cee75ac58a7dbe2b1e14939)] +- 🐛 Fix TextBubble 'Edit Link' background color in dark mode ([#653](https://github.com/baptisteArno/typebot.io/issues/653)) [[f8af76d](https://github.com/baptisteArno/typebot.io/commit/f8af76d34799f4e26de53efee4781f703d782c34)] +- 🐛 (analytics) Fix analytics drop-off rate not computing correctly [[3df81a3](https://github.com/baptisteArno/typebot.io/commit/3df81a3cb9b9f158d940b01d02bf6f2cbedf6f0c)] +- 🐛 (embed) Remove at functions for better compability [[320cffc](https://github.com/baptisteArno/typebot.io/commit/320cffc42001399e2a646243ba9d6ab632a6f9e8)] +- 🐛 (analytics) Fix previous total computation max call stack exceeded [[7a7d471](https://github.com/baptisteArno/typebot.io/commit/7a7d4718051209ba70b6f2e2d23f4945426988fd)] +- 🐛 Fix table list when empty always show "add" button [[b171b39](https://github.com/baptisteArno/typebot.io/commit/b171b3960640382706ccb75f71015aac60ed3da1)] +- 🐛 (sendMessage) Return updated session in all cases [[7942ae4](https://github.com/baptisteArno/typebot.io/commit/7942ae4751703ef0599366f257a690bae9d15818)] +- 🐛 Fix bunny fonts URL path [[defe001](https://github.com/baptisteArno/typebot.io/commit/defe00155d2977cc26ac3291f6375978723865da)] +- 🐛 Add setInputValue to Typebot embed object [[6c54065](https://github.com/baptisteArno/typebot.io/commit/6c540657a610ec27bf4be6ded09db0b610c48724)] +- 🐛 Fix first-time pnpm dev [[b99b58b](https://github.com/baptisteArno/typebot.io/commit/b99b58bdfe032755da249e076eff1eb29256bb72)] +- 🐛 Fix viewer's `.env.local.example` inline comment [[13ac469](https://github.com/baptisteArno/typebot.io/commit/13ac46975d12d8c3aac3a053ea7f612988c9b90f)] + +### Security + +- 🔒 (auth) Block disposable emails during sign up [[abc3abd](https://github.com/baptisteArno/typebot.io/commit/abc3abd86b4f970e102c1b0c5d5d5d610975f45a)] + +### Miscellaneous + +- 📝 (openai) Add troobleshoot guide for empty message issue [[482462f](https://github.com/baptisteArno/typebot.io/commit/482462f2b10f69903754d53dccf41588cca3f701)] +- 📝 Add a guide on how to create a new block in CONTRIBUTING [[e499478](https://github.com/baptisteArno/typebot.io/commit/e499478deed7b1ac2c6c215c8e472133e28b37ab)] +- 📦 Release WP plugin 3.2.0 [[5dc01db](https://github.com/baptisteArno/typebot.io/commit/5dc01db08201a5637d06212c1271b96fa8c23890)] +- 📝 Remove old stripe env var [[b17177f](https://github.com/baptisteArno/typebot.io/commit/b17177f35f97ab679723a3dbade745f474367e53)] +- 📝 Add "conditionally display button" video in docs [[0c923b7](https://github.com/baptisteArno/typebot.io/commit/0c923b70a60851fb3e840820b9dc5d4714adfcb3)] +- 📝 Update README ([#632](https://github.com/baptisteArno/typebot.io/issues/632)) [[9433d3e](https://github.com/baptisteArno/typebot.io/commit/9433d3ea8f9231613d1a5a3efa3576d4e7c16b23)] +- 🧑‍💻 (docs) Add "Edit this page" links in docs [[04faa3e](https://github.com/baptisteArno/typebot.io/commit/04faa3e847f856e1e4099ccfc850be831be4513a)] +- 🧑‍💻 (results) Add get result by id API endpoint [[3283d7e](https://github.com/baptisteArno/typebot.io/commit/3283d7e26146253ae129395afdeaa4fc2bf1d84e)] +- Support specifying custom OAuth scope ([#619](https://github.com/baptisteArno/typebot.io/issues/619)) [[48f074c](https://github.com/baptisteArno/typebot.io/commit/48f074cdf7edf0558c0d937e855f92aba1fabbed)] +- 📝 Add clarification for forks commercialization [[22c1e2e](https://github.com/baptisteArno/typebot.io/commit/22c1e2e6cf8592e22a682dd53fb5c06e48637991)] +- 🧑‍💻 Exit prisma command if database url starts with "postgres://" [[0ea30bc](https://github.com/baptisteArno/typebot.io/commit/0ea30bc49b2979a21ceea2edfd77d8d4ea1811f5)] + + + +## 2.15.2 (2023-07-17) + +### Added + +- ✨ (embed) Add new command setInputValue [[be7be7b](https://github.com/baptisteArno/typebot.io/commit/be7be7bf7a47baeeee0b597e34790ddf289035cc)] +- ✨ Add Next.js embed library [[e293cb0](https://github.com/baptisteArno/typebot.io/commit/e293cb011174aa170ee136c8a1b476bfc98e797c)] +- 👷‍♂️ Improve monthly clean database script [[455c3bd](https://github.com/baptisteArno/typebot.io/commit/455c3bdfd700553831d39fe578c5ad913f0397cc)] + +### Changed + +- 🗃️ Remove extendedWhereUnique feat [[2c2952e](https://github.com/baptisteArno/typebot.io/commit/2c2952e3649713007b9d4edf3846f10a88c87f4b)] +- ⚡ Replace updates with updateManys when possible [[3426d66](https://github.com/baptisteArno/typebot.io/commit/3426d6689d03ea68116f893c9343c0a1a43e1595)] +- ♿ Remove invalid js in meta head code [[521cb50](https://github.com/baptisteArno/typebot.io/commit/521cb50782b7b1141dcf4ae133c686c8d3533c27)] +- ⏪ Downgrade next package version [[d3fb31b](https://github.com/baptisteArno/typebot.io/commit/d3fb31b43a2317a3f3d4aaf9a6748f446c0023ec)] +- ⬆️ Upgrade dependencies [[81bc074](https://github.com/baptisteArno/typebot.io/commit/81bc0746cf81840e9a92ac00b748ac44c9889128)] +- 🚸 (billing) Set existing stripe customer for custom plan checkout [[de08179](https://github.com/baptisteArno/typebot.io/commit/de08179f8bbf291d79a7df3c701d3913f6cb73ca)] +- ⚡ (audio) Implement more robust auto play [[0a85f33](https://github.com/baptisteArno/typebot.io/commit/0a85f33694300fe62a48bd5925ab6f66060796e4)] +- ⏪ Revert onCanPlay callback [[d6c6434](https://github.com/baptisteArno/typebot.io/commit/d6c64340501d07f9388a5afd7226548f159e9413)] +- ⬆️ Upgrade OpenAI stream deps [[5644a0c](https://github.com/baptisteArno/typebot.io/commit/5644a0c8e0e6557aaf2d0a8bcbbff59813f193cd)] +- ⚡ (settings) Parse custom head code to remove invalid text nodes [[174d50a](https://github.com/baptisteArno/typebot.io/commit/174d50ad1b630dcad43d91b42bfef4cf6986468f)] +- 🔧 Rewrite viewer to landing-page [[0465275](https://github.com/baptisteArno/typebot.io/commit/0465275f822d863a29b0d3d7c58b2a787686bdd9)] +- 🚸 (theme) Move isBrandingEnable param in the Theme tab [[a31345a](https://github.com/baptisteArno/typebot.io/commit/a31345ae26650c2c599796f41f3a9fb4292bd8b6)] + +### Fixed + +- 🐛 (pixel) Fix event tracking [[7d62c7a](https://github.com/baptisteArno/typebot.io/commit/7d62c7ac850a2547f813d23e37475b72ce57535d)] +- 🐛 (bot) Improve canPlay issue fixin [[0b4b15c](https://github.com/baptisteArno/typebot.io/commit/0b4b15ce0a3e59209389af847a999c363d66b234)] +- 🐛 (bot) Fix setTimeout onCanPlay concurrency issues [[082084a](https://github.com/baptisteArno/typebot.io/commit/082084a90cdebfb911367a769650acedf69a58c5)] +- 🐛 (bot) Fix double callback on video and audio bubble [[abb363b](https://github.com/baptisteArno/typebot.io/commit/abb363b59da266c36126ef29c7fe0f4b16132b92)] +- 🐛 (openai) Fix incompatible OpenAI types [[6565fcc](https://github.com/baptisteArno/typebot.io/commit/6565fcc29c7a88f0dd6e6c30a7ece7cfe16024c8)] +- 🐛 (bot) Fix audio and video autoplay when loading take some time [[ba3a2b7](https://github.com/baptisteArno/typebot.io/commit/ba3a2b711e45050b679c2fed1c2c520cbd59aec1)] +- 🚑 Fix invalid rewrites for custom domains [[37bb172](https://github.com/baptisteArno/typebot.io/commit/37bb172f251019f0ea1ddd7c2c9d5e7383f7b7ef)] +- 🚑 (lp) Hard-code rewrite to typebot.io [[b2a9734](https://github.com/baptisteArno/typebot.io/commit/b2a973472f09133b8381ea39437dae27ae770181)] +- 🐛 (workspace) Fix members list limit bug [[fc0e378](https://github.com/baptisteArno/typebot.io/commit/fc0e3782b1915b6b247f7ef4901098d0a6a9ac0e)] +- 🚑 (bot) Fix try catch injection when opening s… [[b71e957](https://github.com/baptisteArno/typebot.io/commit/b71e957e7cb7c64dde5f8614a44bf252b3f8ebc8)] +- 🚑 (bot) Share inject custom head code again [[3421e48](https://github.com/baptisteArno/typebot.io/commit/3421e4822f18a6c6071a0ecdd06447d9794e6803)] +- 🐛 (ga) Fix gtag not initializing properly [[8ce5447](https://github.com/baptisteArno/typebot.io/commit/8ce54470126c61b74f331865a8a34ae26dad64c3)] +- 🐛 (bot) Fix audio and video autoplay error catching [[5587bfb](https://github.com/baptisteArno/typebot.io/commit/5587bfb0e92ed3e43f329a7b21bb34001c98c406)] + +### Miscellaneous + +- 📝 Remove pixel troubleshoot section [[12ce4eb](https://github.com/baptisteArno/typebot.io/commit/12ce4eb01b8027885ebd58be37870d78d66f9fa9)] +- 📝 (settings) Update General section [[93337bd](https://github.com/baptisteArno/typebot.io/commit/93337bd1d9ebc2610da910c37974e37cf442f7df)] +- 📝 Add script block precision [[88e2f50](https://github.com/baptisteArno/typebot.io/commit/88e2f50d35e065188f35b4e49dac2c27f02325f6)] +- 📝 Add troubleshoot self-host page [[844832f](https://github.com/baptisteArno/typebot.io/commit/844832f310f2ff482fd26b0eb77431fc6cd5fb73)] +- Fix typo in inject-runtime-env.sh ([#599](https://github.com/baptisteArno/typebot.io/issues/599)) [[c365c54](https://github.com/baptisteArno/typebot.io/commit/c365c547aaae3c87f533185b02742d5b46ab6c1d)] +- 📝 (theme) Add change bot avatar guide in docs [[28fd81c](https://github.com/baptisteArno/typebot.io/commit/28fd81cb6597c6f61a4c9eaa21f5c377bcd929c0)] +- 🧑‍💻 (bot) Wrap custom head code scripts with try catch [[1beb4bb](https://github.com/baptisteArno/typebot.io/commit/1beb4bb1b918976992bfbacf39412d16146a93b3)] + + + +## 2.15.1 (2023-07-07) + +### Changed + +- 🚸 (video) Improve video autoplay behavior [[5ae6c64](https://github.com/baptisteArno/typebot.io/commit/5ae6c64d065d295780f2b008a88c0e0ea59a70e5)] +- 🚸 Remove new typebot default user avatar [[31b7022](https://github.com/baptisteArno/typebot.io/commit/31b70223c84786ba18a39502c9f750b72f1d014a)] + +### Fixed + +- 🐛 (share) Enable back empty public ID for self-hosted version [[56078b4](https://github.com/baptisteArno/typebot.io/commit/56078b4e0215b2d6313a9d2b3b89ae4936cac7f7)] + + + +## 2.15.0 (2023-07-06) + +### Added + +- ✨ Add Meta Pixel block [[033f8f9](https://github.com/baptisteArno/typebot.io/commit/033f8f99ddb72c91b46cd37cfb012ea45e23bf1e)] +- 📈 (billing) Track when workspace subscription is cancelled [[6f7ef82](https://github.com/baptisteArno/typebot.io/commit/6f7ef820e21e77a2be0c7c8911cc8cdbce9a848e)] +- 👷‍♂️ Surround email alerts sending with try catch [[6430d57](https://github.com/baptisteArno/typebot.io/commit/6430d576add7e3add3bb3ce40eba7e0e78bb2205)] + +### Changed + +- ⚡ (analytics) Improve analytics graph accuracy [[b0f25f3](https://github.com/baptisteArno/typebot.io/commit/b0f25f301b89e6dadb730c1537df2b559b9d549f)] +- 💄 Correctly highlight current line in code editor [[55ff944](https://github.com/baptisteArno/typebot.io/commit/55ff944ebb107577f9bd9728e387e0b75c5bb79a)] +- ⚡ (pixel) Add skip initialization option [[50fcbfd](https://github.com/baptisteArno/typebot.io/commit/50fcbfd95e7e480e2579b1ac4e914cb85770ae27)] +- 🚸 (editor) Improve editor performance by rounding paths [[0582ca7](https://github.com/baptisteArno/typebot.io/commit/0582ca74acded209b84e8929c5b874c00042f694)] +- ⚡ (openai) Use Vercel's AI SDK for streaming [[3be39cb](https://github.com/baptisteArno/typebot.io/commit/3be39cbc789e85aab6b22460eac58da9c074d84f)] +- 🗃️ Convert mysql icon varchar to text [[3b52363](https://github.com/baptisteArno/typebot.io/commit/3b52363e118e1009c3c5ab244f837639c1796305)] +- ⚡ Add recent section in icon and emoji picker [[eaadc59](https://github.com/baptisteArno/typebot.io/commit/eaadc59b1fc39ab79e024b7d85b4ef7269ccc852)] +- 🚸 Move item settings button to the left [[d8e5605](https://github.com/baptisteArno/typebot.io/commit/d8e56050f3415fee1586f00975b451ec82f3af3e)] +- ⚡ (openai) Retry OpenAI call if status code is 503 [[dcdf870](https://github.com/baptisteArno/typebot.io/commit/dcdf8703086cb127b1e135480e088e1f9fd68b8b)] +- 🚸 (openai) Parse stream on client to correctly handle errors [[524f156](https://github.com/baptisteArno/typebot.io/commit/524f1565d8600b7efcc0674c56ee5b2f908c07dd)] +- ⚡ (openai) Add new models and remove tiktoken [[83f2a29](https://github.com/baptisteArno/typebot.io/commit/83f2a29faae2f4ad78eca56256977fbbd20a1740)] +- 🚸 (webhook) Show save in variables accordion only when needed [[e54aab4](https://github.com/baptisteArno/typebot.io/commit/e54aab452acd6b7d492f78d624014dfeb42bdfb0)] +- ⚡ (wp) Add UTM auto forward [[a64e621](https://github.com/baptisteArno/typebot.io/commit/a64e6214329ec298742ef453b7aaaa60cf3fbf42)] +- ⚡ (numberInput) Variabalize min, max, step [[4223485](https://github.com/baptisteArno/typebot.io/commit/42234850ed637f67b8b8b7e31dfd093b4824ac47)] +- ⚡ (setVariable) Add "Moment of the day" variable value [[d8c1a36](https://github.com/baptisteArno/typebot.io/commit/d8c1a36bc0c06426be4da5039d24d97bcf2ef719)] +- 🚸 (sheets) Show info log instead of error when no rows are found [[fbe63aa](https://github.com/baptisteArno/typebot.io/commit/fbe63aa3f357adb65b811f134ff702b9a899803d)] + +### Fixed + +- 🐛 (js) Fix container color when empty [[aeb62f9](https://github.com/baptisteArno/typebot.io/commit/aeb62f968accce7769f34c5a25c142fdfe20961e)] +- 🚑 Fix answer upsert on duplicate itemId [[92740ad](https://github.com/baptisteArno/typebot.io/commit/92740ad2ff46c75152d0dd1c4d586e4f01ad323c)] +- 🚑 Fix answer upsert missing groupId [[24126ac](https://github.com/baptisteArno/typebot.io/commit/24126ac9b89d74705b571e3e54afaf8c22d630cb)] +- 🐛 (sheets) Fix sheet block when filter is undefined [[9658277](https://github.com/baptisteArno/typebot.io/commit/9658277d97b358567547adbe677ca8b08458af4c)] +- 🐛 (condition) Improve comparison on dates [[92f7f3c](https://github.com/baptisteArno/typebot.io/commit/92f7f3cbe2febd0ae348008017d3dbd6aafa6b93)] +- 🐛 (results) Fix export duplicate columns when no order set [[3575fef](https://github.com/baptisteArno/typebot.io/commit/3575fef34f0ee0646af1bbf900b98dc45b0c8177)] +- 💚 Fix prisma schema path evaluation on windows [[dcda2d0](https://github.com/baptisteArno/typebot.io/commit/dcda2d06ac54acfdf1fd6284569f096671a64f6d)] +- 💚 (db) Fix verification bulk delete [[63e826f](https://github.com/baptisteArno/typebot.io/commit/63e826f9913ff0dac6c37dd9c4dcb85e2541a480)] +- 🚑 (condition) Remove null check on comparison value [[c94cd1e](https://github.com/baptisteArno/typebot.io/commit/c94cd1e37cd9acef1e1858075a36b6512c3e2e5f)] +- 🐛 (openai) Fix streaming when starting with OpenAI block [[bfca8d9](https://github.com/baptisteArno/typebot.io/commit/bfca8d9368ef5d2eb664909fcef500f7f6268936)] +- 🐛 (condition) Fix condition parsing with value "null" [[8e7479a](https://github.com/baptisteArno/typebot.io/commit/8e7479a1bde96fa6f46d40b7e96eea23dbc9fbfd)] +- 🐛 (conditions) Fix negative comparisons [[cec072b](https://github.com/baptisteArno/typebot.io/commit/cec072b2a223ec400ab1a6fe022e4bfa06c2c25f)] + +### Security + +- 🔒 Add rate limiter on email signin endpoint [[7c2e574](https://github.com/baptisteArno/typebot.io/commit/7c2e5740dcff4b555c8d6b53fb422af12c222f3d)] +- 🔒 Revert ddos lockdown [[f1b643c](https://github.com/baptisteArno/typebot.io/commit/f1b643c5be8bcfd1de68a13b770b9569d39dd53c)] +- 🔒 Remove lp image DDOS prevention [[3e2c462](https://github.com/baptisteArno/typebot.io/commit/3e2c462617754e7d920a904865d018e7e236531c)] +- 🔒 Disable email auth [[00945bf](https://github.com/baptisteArno/typebot.io/commit/00945bfa0cf4d73293f1438c43203327e104fad2)] + +### Miscellaneous + +- 🛂 Add isSuspended prop on workspace [[5a05310](https://github.com/baptisteArno/typebot.io/commit/5a05310a9c9f1f3ef90a54936cbc2238b05eb8c9)] +- 🧑‍💻 (api) Add icon field in create workspace endpoint [[69254c3](https://github.com/baptisteArno/typebot.io/commit/69254c362416cc014f44133b8597027a1e410ff4)] +- 🛂 (billing) Enable Published bot branding when plan cancelled [[6864667](https://github.com/baptisteArno/typebot.io/commit/6864667297b056b96f76e206aff05231163cbe75)] +- 🛂 Add checkSubscriptions script [[2abce89](https://github.com/baptisteArno/typebot.io/commit/2abce89a4644ba3502cf5a323b3c0b642e603563)] +- 🛂 (billing) Display branding when subscription… [[de0b105](https://github.com/baptisteArno/typebot.io/commit/de0b105276f90881c6d0d8740e1d0a2b09432a56)] +- 🛂 (billing) Always invoice when subscription is updated [[97fcee2](https://github.com/baptisteArno/typebot.io/commit/97fcee276449a2ad18c1ba9709d1a6ebb9194681)] +- ⚗️ Add inspect user script [[931540b](https://github.com/baptisteArno/typebot.io/commit/931540b91bf0b1bcb1658de93faecd34811a3e95)] +- 📝 Add status page link in footers [[3662393](https://github.com/baptisteArno/typebot.io/commit/36623930bce59d59975cba3dd2a6f164710e5866)] +- 📝 (embed) Improve Wix embed instructions [[da289a0](https://github.com/baptisteArno/typebot.io/commit/da289a0da797fb797a8c864cdbb424360c65777e)] +- 📝 Change CNAME value to vercel domain [[471dedc](https://github.com/baptisteArno/typebot.io/commit/471dedccc8964bffa43c5baaeb955d6d34688430)] +- 📝 (makecom) Add return data instructions [[0e31a6c](https://github.com/baptisteArno/typebot.io/commit/0e31a6ce0028b86ad070fbd36b506c47af2484e5)] + + + +## 2.14.1 (2023-06-14) + +### Added + +- 👷‍♂️ Add email alert hourly sender [[a4cb6fa](https://github.com/baptisteArno/typebot.io/commit/a4cb6face8c8311957e233c73cab11f57ca52a9c)] +- ✨ Add Näak product recommendation template [[40ef934](https://github.com/baptisteArno/typebot.io/commit/40ef934740ab3cfad56b5137c7b0ed4ba9ce2584)] +- ✨ Add conditional choice items [[ef0a2d9](https://github.com/baptisteArno/typebot.io/commit/ef0a2d9dc61042281ee486ef5e9bb8d711f92e30)] + +### Changed + +- ♿ (payment) Improve payment input amount label format [[290b491](https://github.com/baptisteArno/typebot.io/commit/290b491e533fcab2448eb0e19af4c283d72a2509)] +- 🚸 Add item duplication [[acaa1c6](https://github.com/baptisteArno/typebot.io/commit/acaa1c622387ec60a8afa8e18964a5fb291032c9)] +- 🚸 (openai) Add missing credentials error to chat completion streamer [[8822e4e](https://github.com/baptisteArno/typebot.io/commit/8822e4e7e4d4239122bffbe60017d1a248c413cd)] + +### Fixed + +- 🐛 Fix GA not working when Send_to is empty string [[0a87386](https://github.com/baptisteArno/typebot.io/commit/0a873863054d63405cadcd51bfcd0858415031f6)] +- 💚 Fix cleanDatabase when deleting more than 100,000 sessions [[4977481](https://github.com/baptisteArno/typebot.io/commit/49774815820c6dffb8d4dc1c0493743521c055e4)] +- 🐛 (openai) Fix default response mapping item [[e9c2dee](https://github.com/baptisteArno/typebot.io/commit/e9c2deee5ff935ee941925aafcf3e70bce850ce6)] +- ✏️ Fix FlutterFlow modal title typo [[a16367b](https://github.com/baptisteArno/typebot.io/commit/a16367b194e0fa778c62ed2dec035d69b113aadd)] +- ✏️ Fix react README examples ([#542](https://github.com/baptisteArno/typebot.io/issues/542)) [[61fd44f](https://github.com/baptisteArno/typebot.io/commit/61fd44f768d80f7298db689e4dde4c94327fdf6f)] + +### Miscellaneous + +- 📦 Add Cloudron package ([#550](https://github.com/baptisteArno/typebot.io/issues/550)) [[1e9c4bc](https://github.com/baptisteArno/typebot.io/commit/1e9c4bcb9aab058630d04482ba6b929d50e85df7)] +- 📝 Add 2 new oss friends in landing page [[25524ac](https://github.com/baptisteArno/typebot.io/commit/25524ac62217c90631e7aaf603ba9a63de05cfe5)] +- 📝 Add Google Ads conversion instructions [[4614caf](https://github.com/baptisteArno/typebot.io/commit/4614caf49873be955b63f1888be16ddbfa8a8540)] + + + +## 2.14.0 (2023-06-02) + +### Changed + +- ♿ Improve credentials dropdown accessibility if long name [[bc90c9c](https://github.com/baptisteArno/typebot.io/commit/bc90c9c81ee6f317ba32e402d1d59cf2d17f372b)] +- 💄 Improve picture choice description UI [[b6e5002](https://github.com/baptisteArno/typebot.io/commit/b6e5002a5692368a15c526b1bd67572574a9ee0e)] +- ⚡ (js) Add placement option for bubble embed [[57f3e5c](https://github.com/baptisteArno/typebot.io/commit/57f3e5c004e55bdfcc87e7275f00375619685970)] + +### Fixed + +- 🚑 Fix bubble window size on mobile devices [[8a0488e](https://github.com/baptisteArno/typebot.io/commit/8a0488ee89d6532874e0d597418db0d5a51a542d)] + +### Miscellaneous + +- Update de.ts ([#535](https://github.com/baptisteArno/typebot.io/issues/535)) [[537b9fe](https://github.com/baptisteArno/typebot.io/commit/537b9fe6ce1a42b618c94eead70ff63a20a29835)] +- 🌐 Translate workspace ([#528](https://github.com/baptisteArno/typebot.io/issues/528)) [[b2ea8fc](https://github.com/baptisteArno/typebot.io/commit/b2ea8fc0595f28cf12a0b8e6dfde102314de1041)] +- Update builder configuration docs ([#531](https://github.com/baptisteArno/typebot.io/issues/531)) [[6651c85](https://github.com/baptisteArno/typebot.io/commit/6651c85f021e977c17bbb2df161197ecdc08e6a5)] +- 🔍 (lp) Add FB app ID in landing page [[9ca0c70](https://github.com/baptisteArno/typebot.io/commit/9ca0c7014e69d1fdd13d02ebfd64f08e0b9d0f99)] + + + +## 2.13.5 (2023-05-26) + +### Changed + +- ♿ (js) Improve auto scroll when no host bubble [[0ca48e4](https://github.com/baptisteArno/typebot.io/commit/0ca48e4c0842ce6d0a2681dfa5325c2e5fec5493)] +- 💄 (js) Fix select background color on Windows [[68f0202](https://github.com/baptisteArno/typebot.io/commit/68f02026017e9ffb3f2a0138c8edfaf115ae9447)] +- ⚡ (webhook) Add client execution option [[75f9da0](https://github.com/baptisteArno/typebot.io/commit/75f9da0a4fe7937e07823ac46a8b449c89bf6eac)] +- ⬆️ Upgrade dependencies [[55bbf0e](https://github.com/baptisteArno/typebot.io/commit/55bbf0e5938ae8ffe2a0e4c7bd7944b6e12d465f)] +- ⚡ (openai) Stream chat completion to avoid serverless timeout ([#526](https://github.com/baptisteArno/typebot.io/issues/526)) [[56364fd](https://github.com/baptisteArno/typebot.io/commit/56364fd86335607cbe6c17bdba7f7caf5397cc1e)] +- 💄 (js) Improve popup ui consistency [[c950406](https://github.com/baptisteArno/typebot.io/commit/c950406997c28dc9aefecbad2aeb58d9b66ccffe)] + +### Fixed + +- 🐛 Fix outside click on picture choice [[4230f47](https://github.com/baptisteArno/typebot.io/commit/4230f47be911c7be21d7055b01f7548b6bf2436e)] +- 🐛 (webhook) Add loading bubble when executing webhook on client [[4dec06f](https://github.com/baptisteArno/typebot.io/commit/4dec06fc7502037282e654eb58c4bb93fc0e75c6)] +- 🐛 (sheets) Fix empty and unique filter [[154271c](https://github.com/baptisteArno/typebot.io/commit/154271c7f22a9d2f7553532a7d16530c2dfe9aae)] +- 🐛 (payment) Round the amount to avoid weird Js long decimals [[16f3ad3](https://github.com/baptisteArno/typebot.io/commit/16f3ad3a19d36b57f9adef22726aedb60745b80a)] +- 🐛 (editor) Remove edge if duplicating last block of group [[6bb6a2b](https://github.com/baptisteArno/typebot.io/commit/6bb6a2b0e36a00d3b296acab4fa2e3f90e4641d4)] +- 🐛 Fix readme typo ([#518](https://github.com/baptisteArno/typebot.io/issues/518)) [[423aca6](https://github.com/baptisteArno/typebot.io/commit/423aca6133ce24f0f0033789eeb0f7f40aba8108)] +- 🐛 Fix embed bubble icon color [[49a8427](https://github.com/baptisteArno/typebot.io/commit/49a8427776ba43417699029e87ee41d85193a05d)] +- 💚 Improve auto create tag workflow [[683ba90](https://github.com/baptisteArno/typebot.io/commit/683ba90403676e8baf1eb27c3488163cbb9e5da1)] + +### Miscellaneous + +- 📝 (lp) Add oss friends page [[084a17f](https://github.com/baptisteArno/typebot.io/commit/084a17ffc8ef587f3f70a46c43a7d35331868d4d)] +- 📝 (embed) Add FlutterFlow embed instructions [[fdfed16](https://github.com/baptisteArno/typebot.io/commit/fdfed160a657475f50af2a7635923b9d747a12c8)] + + + +## 2.13.4 (2023-05-17) + +### Changed + +- ⚡ Remember result in either local or session storage ([#514](https://github.com/baptisteArno/typebot.io/issues/514)) [[27b009d](https://github.com/baptisteArno/typebot.io/commit/27b009dd7693c59f75c9df8ff0d3b27dcae47680)] + +### Fixed + +- 🐛 Disable invite button when email is empty [[8b84a7d](https://github.com/baptisteArno/typebot.io/commit/8b84a7d8b983d4dc36ad4ab89d92b052fcfeb9b9)] +- 🐛 Fix public id validation [[853451b](https://github.com/baptisteArno/typebot.io/commit/853451b4fabf2f2c5e7d001f8d806ea51dd3c80e)] + +### Miscellaneous + +- 🐳 Fix encryption length check script [[0fc6bfa](https://github.com/baptisteArno/typebot.io/commit/0fc6bfa7cefc866d39f464a9efb080c4eff5669b)] +- 📝 (webflow) Add bind commands to button instructions [[c451ba7](https://github.com/baptisteArno/typebot.io/commit/c451ba77846218764d8916d7d22c421fdf97d1cb)] + + + +## 2.13.3 (2023-05-16) + +### Added + +- 🔊 Add DEBUG mode with valuable logs in viewer [[72058fd](https://github.com/baptisteArno/typebot.io/commit/72058fd624c2068d366d560b0ee81697b03daed8)] + +### Changed + +- ⚡ (embed) Add size and icon picker in bubble settings ([#508](https://github.com/baptisteArno/typebot.io/issues/508)) [[0f91b34](https://github.com/baptisteArno/typebot.io/commit/0f91b34497659da34edafa23b80e81782925eda7)] +- 🚸 Improve support accessibility [[123926f](https://github.com/baptisteArno/typebot.io/commit/123926f2735787c15ca22abc55ea1cb73a4631b8)] + +### Fixed + +- 🐛 Restore support bubble in cloud prod [[f8ea2e1](https://github.com/baptisteArno/typebot.io/commit/f8ea2e133786100893fe53504e6549fa5d56d178)] + +### Miscellaneous + +- 📝 Add a self-hosting comparison table in README [[2b54518](https://github.com/baptisteArno/typebot.io/commit/2b54518d04ab26d4489de2b7e42d82796d2aede6)] + + + +## 2.13.2 (2023-05-12) + +### Added + +- ✨ Add icon picker ([#496](https://github.com/baptisteArno/typebot.io/issues/496)) [[9abc50d](https://github.com/baptisteArno/typebot.io/commit/9abc50dce518ff7e0cc2d09196a4171104fa9902)] + +### Changed + +- 🚸 Improve chat auto scroll [[a3fb098](https://github.com/baptisteArno/typebot.io/commit/a3fb098dfa010a29af8fd0e5a7145430d10ccc92)] +- ⚡ (sheets) Add option to select single row when matching multiple [[55dbb1a](https://github.com/baptisteArno/typebot.io/commit/55dbb1abc714462e3479ad42e8eb82d315e32f0e)] +- ⚡ Add predefined set variable values ([#497](https://github.com/baptisteArno/typebot.io/issues/497)) [[bde9416](https://github.com/baptisteArno/typebot.io/commit/bde941613cedaddd3c4fabe466e84ffe09ec670b)] + +### Fixed + +- 🐛 Fix webhook deep keys parsing invalid index [[df8a406](https://github.com/baptisteArno/typebot.io/commit/df8a4065139fb34222efabc8ae4139fa1fe201dd)] + +### Miscellaneous + +- 🧑‍💻 Check required env var before starting the server [[45224f9](https://github.com/baptisteArno/typebot.io/commit/45224f9fb36f97a169ac729def4dd50c6506a2ae)] + + + +## 2.13.1 (2023-05-09) + +### Added + +- ✨ Add dog insurance offer template [[8347e5b](https://github.com/baptisteArno/typebot.io/commit/8347e5b2a89b70957a6a04f7cceac83a4c1a57c6)] +- ✨ Add picture choice block [[035dded](https://github.com/baptisteArno/typebot.io/commit/035dded654fb425c2f1e857b2f328baadc44d799)] + +### Changed + +- 🚸 Add floating menu for block settings [[825ed2f](https://github.com/baptisteArno/typebot.io/commit/825ed2f1ecab3a5cad7659172df38791a6cf2a24)] +- 🚸 Show toast for non-uploaded file in preview mode [[be009a2](https://github.com/baptisteArno/typebot.io/commit/be009a216d8c63864c9b71ebc62647c17494f0e5)] +- ⚡ (payment) Add address in payment input [[c469912](https://github.com/baptisteArno/typebot.io/commit/c46991297961f080f77dbce400849af2e80627a9)] +- 🚸 (billing) Use Stripe checkout page for new subscription with existing customer [[b9f94cd](https://github.com/baptisteArno/typebot.io/commit/b9f94cdf19df3ba69166760d028500650e79a355)] +- ⚡ (sheets) Add rows filtering to update multiple rows at the same time [[55db360](https://github.com/baptisteArno/typebot.io/commit/55db360200612171ac0159296145b21efe5bc59c)] +- 🚸 (editor) Do not show focus toolbar for the Start group [[5f0a99e](https://github.com/baptisteArno/typebot.io/commit/5f0a99ee66fc719f1d3ca9371dba4af3018f66ac)] + +### Fixed + +- 🐛 (webhook) Fix picture choice sample value not sent [[33adc29](https://github.com/baptisteArno/typebot.io/commit/33adc29a57609f6a9a44113886113d94eb642393)] +- 🐛 (ga) Fix value field parsing [[e15e27f](https://github.com/baptisteArno/typebot.io/commit/e15e27f0b47deca2d5d99021642ce770a4df0268)] +- 🐛 (ga) Fix invalid variable parsing [[d99af7e](https://github.com/baptisteArno/typebot.io/commit/d99af7e6c5d6d833c98e99c9ff255cb75a16ee9f)] +- 🐛 (billing) Only fetch active subscriptions [[98a21f3](https://github.com/baptisteArno/typebot.io/commit/98a21f3a9e7cd348b1ea196260633228378ce1be)] +- 🐛 (sheets) Fix update filter invalid indexes [[8b3a690](https://github.com/baptisteArno/typebot.io/commit/8b3a6908098b0bfc49f6aea4506c22ac54d933bb)] +- 🐛 (wp) Fix custom api host variable name on shortcode [[c0fae18](https://github.com/baptisteArno/typebot.io/commit/c0fae185013f0f62effe1eab9455cb7e5bc392c0)] +- 🐛 (googleAnalytics) Fix output validation when using variable as event value [[65c6f66](https://github.com/baptisteArno/typebot.io/commit/65c6f66a5cdd72ad1384a89df5810e800b2cbd06)] +- 💚 Revert rollup upgrade to make it work with turbo dev [[f2d3174](https://github.com/baptisteArno/typebot.io/commit/f2d31745caddf2ab57dd4db2ec2c0264cfafe833)] + +### Miscellaneous + +- Add German Translation ([#485](https://github.com/baptisteArno/typebot.io/issues/485)) [[dd079c3](https://github.com/baptisteArno/typebot.io/commit/dd079c352503bf01fb61061466964a6129ad4bc9)] +- 📝 Custom bubble button position instructions [[ecc3b5f](https://github.com/baptisteArno/typebot.io/commit/ecc3b5fd874aed22a84ba958f722e9424b170430)] +- 📝 Doc about the more options menu from the results tab [[c31642d](https://github.com/baptisteArno/typebot.io/commit/c31642db04f7b197f09646ab9b4e96333326a998)] + + + +## 2.13.0 (2023-05-02) + +### Added + +- 🔊 (sheets) Improve update row error log when not found [[fd0fd51](https://github.com/baptisteArno/typebot.io/commit/fd0fd51c1dd13764f5cdccfd10ea18edc0d4e1bc)] + +### Changed + +- ⬆️ Upgrade dependencies [[37e0153](https://github.com/baptisteArno/typebot.io/commit/37e0153842525b8ef81d9120cdae7d8d45021c33)] +- 💄 Improve toast UI when containing only description [[d50e280](https://github.com/baptisteArno/typebot.io/commit/d50e280ab37a6cb8ec420653ac9ab4bd6f6a2d1f)] +- ⚡ (openai) Truncate messages sequence automatically if reaching token limit [[e58016e](https://github.com/baptisteArno/typebot.io/commit/e58016e43a4dd58c809bcce604ab5af0ab91a41c)] +- 💄 Fix toast UI in dark mode [[ddb5287](https://github.com/baptisteArno/typebot.io/commit/ddb528774bb280f2c3979f8a711074c173918cef)] +- 💄 (js) Fix gap on loading chunk [[ce2565c](https://github.com/baptisteArno/typebot.io/commit/ce2565c4293be28f4fc570cb8174632fe3f82973)] +- ⚡ (scripts) Improve result digest db queries [[5845e1c](https://github.com/baptisteArno/typebot.io/commit/5845e1cb8c448a2a7d8c5832694e18a7a51822c8)] +- 💄 Better toast UI when it doesn't contain details [[e827da7](https://github.com/baptisteArno/typebot.io/commit/e827da7b6bd6da2b22d3b6a92ce8446519f6fdb6)] +- ⚡ (ga) Add send_to option [[9e8acd9](https://github.com/baptisteArno/typebot.io/commit/9e8acd97aa4ffe2790d555dbed50323229605160)] +- ⚡ Better error toast when previewing bot [[d448e64](https://github.com/baptisteArno/typebot.io/commit/d448e64dc9e4693966c335fa453029490e2b650b)] + +### Fixed + +- 🐛 Fix variable dropdown size in text bubble editor when z… [[2b0e2b0](https://github.com/baptisteArno/typebot.io/commit/2b0e2b09f517358653d7a47b93e4fc7f66950e0b)] +- 🐛 (googleAnalytics) Fix sendTo initial value in settings [[e2836f3](https://github.com/baptisteArno/typebot.io/commit/e2836f305c1d0ca0743b120c9b0a54d657e6b949)] +- 🐛 Properly display success message toast for web preview [[9473563](https://github.com/baptisteArno/typebot.io/commit/94735638a608b57501672ed0d113e548cf84dcfe)] + +### Miscellaneous + +- 🩹 (wp) Fix typebotWpUser not defined issue [[c1f3534](https://github.com/baptisteArno/typebot.io/commit/c1f3534374d5f5ad8d492763b538179faec27ac9)] +- 🛂 (billing) Update claimable custom plan options [[458d715](https://github.com/baptisteArno/typebot.io/commit/458d71564866ee9c6a350d69e488f8cc3a3faf12)] + + + +## 2.12.3 (2023-04-27) + +### Added + +- ✨ (buttons) Add searchable choices [[5b4a6c5](https://github.com/baptisteArno/typebot.io/commit/5b4a6c523d0608098ce0204f0416dbfbf060bb18)] +- ✨ Add lead gen with AI template [[3b69b18](https://github.com/baptisteArno/typebot.io/commit/3b69b18601bc3b77b8b1f8780e4e147a01967cd0)] +- 📈 Track workspace limit reached event [[c203a4e](https://github.com/baptisteArno/typebot.io/commit/c203a4e792dfa2e38c7b098d7afc1fca4a853a33)] +- ✨ Add AB test block [[7e937e1](https://github.com/baptisteArno/typebot.io/commit/7e937e1c7cae380c3083c95b207ea9126739b1dc)] + +### Changed + +- 💄 (buttons) Improve multiple choice form UI [[124f350](https://github.com/baptisteArno/typebot.io/commit/124f350aa27fdf33063d98266169b75e8065c4c4)] +- ♿ (sheets) Add duplicate header notice [[a03d124](https://github.com/baptisteArno/typebot.io/commit/a03d1240468dad82bd4f253995ceecf9823b025b)] +- ⚡ (chatwoot) Add result URL custom attribute [[c09a840](https://github.com/baptisteArno/typebot.io/commit/c09a84034e462138d2bd2c95be102ffabc809438)] +- 🚸 (date) Improve date format storage [[3529da2](https://github.com/baptisteArno/typebot.io/commit/3529da210c2415e20cd35c1861fa6d1aad684d02)] +- 🚸 (templates) Add category and description in templates modal [[4d1fe4c](https://github.com/baptisteArno/typebot.io/commit/4d1fe4c1dee7fb79b9e47ed756100e1b1e42c81b)] +- 🚸 (sendEmail) Allow html parsing for body with a single variable [[de432ec](https://github.com/baptisteArno/typebot.io/commit/de432ecaf7f78b7ad44b814cdcf50addb25c0b42)] +- 🚸 (billing) Make yearly plan clearer for subscription updates [[9345b33](https://github.com/baptisteArno/typebot.io/commit/9345b33e740c7190b66404226bf82e5a84d745db)] + +### Fixed + +- 🚑 (buttons) Fix content mapping on searchable multiple items [[7896e3d](https://github.com/baptisteArno/typebot.io/commit/7896e3d732b6543fa4511f5c791429dce39705d3)] +- 🐛 (viewer) Remove default white background when it is set to none [[bda34e3](https://github.com/baptisteArno/typebot.io/commit/bda34e38276351911fc22f5ecb340f9c5a47230f)] +- 🐛 (condition) Greater and Less should compare list length when possible [[c77b8e7](https://github.com/baptisteArno/typebot.io/commit/c77b8e7548c515857b86968a0a7c13cc3bd7180d)] +- 🐛 Refresh variable list on focus [[b614544](https://github.com/baptisteArno/typebot.io/commit/b61454490964a90d6c092e133aac88d9acf29405)] + +### Miscellaneous + +- 📝 Fix GTM instructions [[f51d619](https://github.com/baptisteArno/typebot.io/commit/f51d619c79f82a114ffa5d592ccc9443171584c2)] +- 📝 Add Jump and AB test block docs [[7385e3b](https://github.com/baptisteArno/typebot.io/commit/7385e3bbbf88a3d193ff586927f0a777e6374422)] +- 🛂 Reset isQuarantined on the first of month [[3fbd044](https://github.com/baptisteArno/typebot.io/commit/3fbd044d9284fe2d7dc01f2808a9ee2801dfd9c1)] +- 🛂 Reset isQuarantined when upgrading workspace [[c6983c9](https://github.com/baptisteArno/typebot.io/commit/c6983c952c451eeb026302068afd8a0862673a9d)] +- 🛂 Add isQuarantined field in workspace [[69e1c4f](https://github.com/baptisteArno/typebot.io/commit/69e1c4f20d5c878fb1a58dc4f6c048f8bc6084d0)] +- 🩹 (telemetry) Better limit reached workspace filter [[fc56143](https://github.com/baptisteArno/typebot.io/commit/fc561430a04a6d2acf9fd9e0979b6a7f89d3468a)] +- 📝 Add upgrade plan doc [[a4ca413](https://github.com/baptisteArno/typebot.io/commit/a4ca413c602198a1547f6c227a9329cbb0e20683)] +- 🩹 Correctly convert totalStorageUsed for limit telemetry [[30f93e8](https://github.com/baptisteArno/typebot.io/commit/30f93e8a6f14b73d9a0ab433a0a2df1d471a27f4)] +- 🩹 (share) Fix undefined apiHost under API instructions [[7c2ce2f](https://github.com/baptisteArno/typebot.io/commit/7c2ce2fc41f52ef96f3b1473671600f1d81fa7b6)] + + + +## 2.12.2 (2023-04-17) + +### Changed + +- 🚸 (share) Use custom domain host when possible in embed instruction [[cd0916d](https://github.com/baptisteArno/typebot.io/commit/cd0916df675511466aa9b48302ea9ffd7a1756f0)] + +### Fixed + +- 🐛 (sendEmail) Escape html from variables in custom body [[f7d94de](https://github.com/baptisteArno/typebot.io/commit/f7d94de66ed383bed12db3771c6ff916008e657a)] +- 🐛 Auto scroll X behavior outside of editor [[928afd5](https://github.com/baptisteArno/typebot.io/commit/928afd5a6cc49900279e45f4cf42a168213abf6d)] +- 🐛 (results) Keep focus on current expanded result when new ones arrive [[f8a76f9](https://github.com/baptisteArno/typebot.io/commit/f8a76f98b94ac4ae780b11ffae54104bbf4da69b)] +- 🐛 Await support in set variable and script code [[918dffb](https://github.com/baptisteArno/typebot.io/commit/918dffb4bc7a18da41862b90288bda8fe59246ae)] + + + +## 2.12.1 (2023-04-14) + +### Added + +- ✨ Add lead magnet template [[ee14228](https://github.com/baptisteArno/typebot.io/commit/ee14228ee32894460f11350a4d096d7cf5b082ab)] + +### Changed + +- ⚡ (setVariable) Add client-side set variable execution [[03cc067](https://github.com/baptisteArno/typebot.io/commit/03cc067418bff04054c6aabe4f2615a119a02e9e)] +- 💄 Adapt openAI logo to dark mode [[868b5b8](https://github.com/baptisteArno/typebot.io/commit/868b5b83706d174a2fa9b51375726aaa1f003857)] +- ♻️ Simplify text bubble content shape [[e0a9824](https://github.com/baptisteArno/typebot.io/commit/e0a9824913237cb5340d262770e9e8290fbc4002)] +- 💄 Improve Unsplash picker dark mode UI [[0033108](https://github.com/baptisteArno/typebot.io/commit/00331089a3b3c0644539153745af10d7d193c382)] +- 🚸 (sheets) Better Get data settings UI [[6921cc2](https://github.com/baptisteArno/typebot.io/commit/6921cc23a5423f9485b62c54963324fa4dd54998)] +- ⚡ (imageBubble) Add redirect on image click option [[e06f818](https://github.com/baptisteArno/typebot.io/commit/e06f8186f61bcc4abc5cec8984de00c623088d8b)] + +### Fixed + +- 🐛 Remove lead magnet duplicated block [[0900fb0](https://github.com/baptisteArno/typebot.io/commit/0900fb04079388bc47b18975b6653f1f3a4a9209)] +- 🐛 (auth) Fix signup page text [[39d0dba](https://github.com/baptisteArno/typebot.io/commit/39d0dba18c251134259b2f99f8d0263dc1a51349)] +- 🐛 (webhook) Correctly parse array of strings in data dropdown [[a7dbe93](https://github.com/baptisteArno/typebot.io/commit/a7dbe93eddb41f2be2defc51104eb1c7291d736f)] +- 🐛 (setVariable) Properly parse phone number variables [[44975f9](https://github.com/baptisteArno/typebot.io/commit/44975f9742a63eb82543c0287cf68b91f70295c3)] + +### Miscellaneous + +- 📝 Improve writing on self-hosting introduction [[397a33a](https://github.com/baptisteArno/typebot.io/commit/397a33afc662a873759769907a7bae05b4a53117)] +- Improve translation PT ([#456](https://github.com/baptisteArno/typebot.io/issues/456)) [[27f1015](https://github.com/baptisteArno/typebot.io/commit/27f10159ef0fbd30b70fea48deef318d7c93b82f)] +- 🛂 Add new yearly plans and graduated pricing [[2cbf834](https://github.com/baptisteArno/typebot.io/commit/2cbf8348c34c81b89efb963fa754986729232748)] +- 🛂 Prevent blocking everything once limit is reached [[846dac0](https://github.com/baptisteArno/typebot.io/commit/846dac0bf40bdc27a4df12fe16779525aeece12a)] +- More translation in FR & PT ([#436](https://github.com/baptisteArno/typebot.io/issues/436)) [[75d2a95](https://github.com/baptisteArno/typebot.io/commit/75d2a95d0897ff7d1942f2fc66e8426beaad6e64)] + + + +## 2.12.0 (2023-04-05) + +### Added + +- 🔊 (openai) Add error log details in web console [[a5d3f83](https://github.com/baptisteArno/typebot.io/commit/a5d3f83c7fa0924b9a9f48e841e848681f54bbd5)] +- ✨ Add ChatGPT personas template [[f895c6d](https://github.com/baptisteArno/typebot.io/commit/f895c6d72d276c726e8254e1e8b69792a0cbce71)] +- ✨ Add Unsplash picker [[3ef4efa](https://github.com/baptisteArno/typebot.io/commit/3ef4efab4e0d85839f07de94456e8a2762ffa416)] + +### Changed + +- 🚸 (js) Display last input if send message errored [[9f8398b](https://github.com/baptisteArno/typebot.io/commit/9f8398b9aecbfe2b42e658e2afa4ada084fd9b8c)] +- 🚸 (webhook) Always show save response accordion [[b96a3a6](https://github.com/baptisteArno/typebot.io/commit/b96a3a6a8e38a919a7365faaa3430afd22a5ae97)] +- ⬆️ Upgrade dependencies [[21b1d74](https://github.com/baptisteArno/typebot.io/commit/21b1d74b7e99b15a0d4cb8aff0edc75602161c9b)] +- 🚸 (results) Improve list variables display in results table [[411cf31](https://github.com/baptisteArno/typebot.io/commit/411cf31b397fba2b810b33e0b57bfa4a4eb9b159)] +- ♿ (js) Add "large" bubble button size and part attr [[3cfdb81](https://github.com/baptisteArno/typebot.io/commit/3cfdb8179e3503b67665a3338356bd6bbf6edb92)] +- ♿ (billing) Add HU VAT option [[70416c0](https://github.com/baptisteArno/typebot.io/commit/70416c0d144eabaeef03ab98c7f554fa7479b07b)] +- ⚡ (condition) Add more comparison operators [[80b7dbd](https://github.com/baptisteArno/typebot.io/commit/80b7dbd19e94435733ae0e5057de9045ec9412af)] +- ⚡ (payment) Add description option on Stripe input [[bb45b33](https://github.com/baptisteArno/typebot.io/commit/bb45b33928d48a3d376fdbc19122646447b54a93)] +- ♿ (openai) Show textarea instead of text input for message content [[50db998](https://github.com/baptisteArno/typebot.io/commit/50db9985c44bf25fc1cd555eee6e606f23c942c3)] + +### Fixed + +- 🐛 Fix error display on preview start [[3196fe3](https://github.com/baptisteArno/typebot.io/commit/3196fe375985e90d6246010eca00b5e08694eed4)] +- 🚑 (auth) Fix bad requests with getSession on server side [[49071b7](https://github.com/baptisteArno/typebot.io/commit/49071b73b6424490af8aeb38e207b8b80ae2446c)] +- 🐛 (editor) Make sure you can't remove the Start group [[d32afd8](https://github.com/baptisteArno/typebot.io/commit/d32afd8ba69b1b68860b9ceeceda52147f70cf76)] +- 🐛 (embedBubble) Fix sanitize url adding https to variable [[b9ae314](https://github.com/baptisteArno/typebot.io/commit/b9ae314ef9bee4f027eb61be644210c4b0a15e2e)] +- 🐛 (typebotLink) Fix Out of sort memory with mySQL DB [[79c1b16](https://github.com/baptisteArno/typebot.io/commit/79c1b16ec4d2a915a3f9aad23ea32a80b55fb45e)] +- 🐛 (typebotLink) Fix linked typebot fetching error [[684e633](https://github.com/baptisteArno/typebot.io/commit/684e6338e2374cd30603a24ca20fb993e757fd73)] + +### Miscellaneous + +- 📝 (openai) Add a troobleshooting section [[f18889a](https://github.com/baptisteArno/typebot.io/commit/f18889a0468661a0f6b1cfc685283a4f83317e42)] +- 📝 Add set variable upper and lower case examples [[14abe76](https://github.com/baptisteArno/typebot.io/commit/14abe76691036dc3618571b6357d80c71e27e5cc)] +- 🩹 (billing) Also reset custom limits when plan is cancelled [[2dae416](https://github.com/baptisteArno/typebot.io/commit/2dae4160bd334ae7b9462aba094cba1621b3bc58)] +- 📝 (sheets) Add instructions on how to format spreadsheet [[61981f9](https://github.com/baptisteArno/typebot.io/commit/61981f9e9255633c92559eba279c26d3fe8769a4)] + + + +## 2.11.9 (2023-03-29) + +### Added + +- ✨ (theme) Add theme templates [[38ed575](https://github.com/baptisteArno/typebot.io/commit/38ed5758fe9e50804f75e15bc389a0cb89b248f1)] + +### Changed + +- 💄 Fix misc UI issues [[f13d7a1](https://github.com/baptisteArno/typebot.io/commit/f13d7a1a5ae1e5df1e11fc6d37b94948e5c655cf)] + +### Fixed + +- 🐛 (auth) Fix invalid redirects to internal url [[4986ec7](https://github.com/baptisteArno/typebot.io/commit/4986ec79f5f9714fc89f753779f17396a719334a)] + +### Miscellaneous + +- 🩹 (theme) Remove default opened accordion in Theme [[14d7ebd](https://github.com/baptisteArno/typebot.io/commit/14d7ebd58c3772da4706e02a73f5235b66fb6cd4)] +- 📝 (api) Better theme template api section title [[94aadc8](https://github.com/baptisteArno/typebot.io/commit/94aadc83619499334f0e7124b23e93ff08be1e03)] + + + +## 2.11.8 (2023-03-28) + +### Fixed + +- 🐛 (auth) Fix magic link callback url pointing to internal url [[2946f3e](https://github.com/baptisteArno/typebot.io/commit/2946f3ee3b0dd763c93234f3adb671c8de2bdd6a)] +- 🐛 (wp) Fix wordpress user parsing [[cbeb275](https://github.com/baptisteArno/typebot.io/commit/cbeb2751640b195466f2073b311b32bd45b5d48e)] + + + +## 2.11.7 (2023-03-28) + +### Changed + +- 🚸 (editor) Improve block dragging behavior [[92b92ed](https://github.com/baptisteArno/typebot.io/commit/92b92ed26806ac35f75e060fa6d53ef1e1ca597b)] + +### Fixed + +- 🐛 (auth) Fix email magic link pointing to internal auth URL [[5e91f4d](https://github.com/baptisteArno/typebot.io/commit/5e91f4d0efc3f681f34201b5da30ce645f1db1dd)] +- 🐛 Fix parseVariables when preceding with a dollar sign [[5fb5176](https://github.com/baptisteArno/typebot.io/commit/5fb51766415bc69792a711848105b8f2c40df912)] +- 🐛 (variables) Correctly parse variables in template literals [[fa31984](https://github.com/baptisteArno/typebot.io/commit/fa31984456898c4d3dd66c472a2b9423095f9f6f)] + +### Miscellaneous + +- 📝 Add better examples about variables evaluation on Set variable block [[787ac50](https://github.com/baptisteArno/typebot.io/commit/787ac50f90f9fcf9de3cade64e7ee01b60e68609)] +- 📝 Add required asterix in apps config [[e1de63a](https://github.com/baptisteArno/typebot.io/commit/e1de63a405b8824561aa3d06bc242e71cc121345)] +- 📝 Add explanations about how variables are evaluated in code [[69ee590](https://github.com/baptisteArno/typebot.io/commit/69ee5900b4ec5cd52045ce753ce88033cd17752d)] +- 🩹 (js) Move data-blockid to the right element [[5090bad](https://github.com/baptisteArno/typebot.io/commit/5090badfa985c681c172484a7fd4514c097e077f)] + + + +## 2.11.6 (2023-03-22) + +### Added + +- 🔊 Add more error logs for sendEmail block [[3d8cb40](https://github.com/baptisteArno/typebot.io/commit/3d8cb40f06f3219ed0d7e86b4f7601e6c1bab240)] + +### Changed + +- ⚡ (theme) Add corner roundness customization [[65d33e0](https://github.com/baptisteArno/typebot.io/commit/65d33e04bc6b993d2c9e3d42ee7509cd90a88aed)] +- ⚡ (theme) Support for image background [[3992227](https://github.com/baptisteArno/typebot.io/commit/3992227afc050e5adb23d7644b0b1df338728e2a)] +- ♿ Attempt to disable translation to avoid app crashes [[1cf2195](https://github.com/baptisteArno/typebot.io/commit/1cf2195b4a1812e28e9dfb4a82a09d00863b1f5a)] +- 🚸 (sendEmail) Improve file attachments label [[925cf68](https://github.com/baptisteArno/typebot.io/commit/925cf681194846d6ab551ffd8719bbafe3c228e8)] +- 🚸 (variables) Allow null values in variable list [[0c39ae4](https://github.com/baptisteArno/typebot.io/commit/0c39ae41b6e8b191be496f8d9ff74c6f15090c9c)] +- ⚡ (openai) Add gpt-4 models and temperature setting [[4109a84](https://github.com/baptisteArno/typebot.io/commit/4109a8489ccc21c22506ea89cd48ac38052e6f33)] +- ♿ (phone) Remove spaces from format [[3d6d643](https://github.com/baptisteArno/typebot.io/commit/3d6d643a7e828fbe0b101c46aedcfe61a25d6634)] +- 💄 (lp) Fix overflow issue on mobile [[b3e5887](https://github.com/baptisteArno/typebot.io/commit/b3e5887420bacc475f29f2b33727ac1a35b332c6)] + +### Fixed + +- 🐛 Fix focus after selecting mark in text editor [[02d25d0](https://github.com/baptisteArno/typebot.io/commit/02d25d0fc78a1d5266d64eadcc8aee2062e4627a)] +- 🐛 Transform upload file redirect to a rewrite [[c52a284](https://github.com/baptisteArno/typebot.io/commit/c52a284013b81a7cc0b1c7a9cd8bc7df0f3aa57a)] +- 💚 Fix Sentry sourcemap upload [[90cb075](https://github.com/baptisteArno/typebot.io/commit/90cb0750b848937d2d591c19ebf0f3e32f3c1085)] +- 🐛 (js) Fix upload file in linked typebot [[b4536ab](https://github.com/baptisteArno/typebot.io/commit/b4536abc2f72c2d770d6d8c67566bd4188a6c665)] +- ✏️ Fix old packages/db paths in documentation [[16c261a](https://github.com/baptisteArno/typebot.io/commit/16c261a8a539a7b3fc2962d68655e3da5b4aea26)] +- 🐛 (sheets) Fix can't start bot when filter is undefined [[be7c0fc](https://github.com/baptisteArno/typebot.io/commit/be7c0fc0d07ad4d5c007a609142923cc9e87302f)] +- 💚 Fix isFirstOfKind filter [[f9964e3](https://github.com/baptisteArno/typebot.io/commit/f9964e3f60f3343cb7d40ed715e03a732b794077)] + +### Miscellaneous + +- 📝 Improve license scenarios with collapsibles [[9147c8c](https://github.com/baptisteArno/typebot.io/commit/9147c8cd14a766a2e0609439cfe5c0ec57f8e545)] +- 🛂 Improve lite-badge style forcing [[a41c65f](https://github.com/baptisteArno/typebot.io/commit/a41c65f528b5d2a795efac8ea37d5541b66bc8b3)] +- 📝 (openai) Add youtube video about the basic chatgpt template [[7340ec1](https://github.com/baptisteArno/typebot.io/commit/7340ec139c5627c4257bda9a398764a440fcb0ef)] +- 📝 Improve License explanations [[1e67fd7](https://github.com/baptisteArno/typebot.io/commit/1e67fd7c3f78754637b4d6138e5c49c433e98339)] +- 🧑‍💻 (js) Add data-blockid on input elements [[efdcec1](https://github.com/baptisteArno/typebot.io/commit/efdcec1c0c8e969d9478f3ac1cb867f371afb5b8)] + + + +## 2.11.5 (2023-03-15) + +### Added + +- 📈 Add convenient isFirstOfKind field in total results digest [[25c3679](https://github.com/baptisteArno/typebot.io/commit/25c367901f99413ce886db1bf2b83dc1087f5b27)] +- 📈 Add telemetry webhook [[9ca17e4](https://github.com/baptisteArno/typebot.io/commit/9ca17e4e0b9bfa18c0cba6efdb01d78d0cd88084)] + +### Changed + +- ♻️ Fix folder case issue [[3a6c096](https://github.com/baptisteArno/typebot.io/commit/3a6c09646194f3899bbaa7ed9c38a4501eec269f)] +- ♻️ (viewer) Remove barrel exports and flatten folder arch [[f3af07b](https://github.com/baptisteArno/typebot.io/commit/f3af07b7ffb660bd9040e1f08839ab3809a5683d)] +- ♻️ (builder) Remove barrel export and flatten folder arch [[44d7a0b](https://github.com/baptisteArno/typebot.io/commit/44d7a0bcb87494cb51a422350ea75a4df0c9a966)] +- ♻️ Re-organize workspace folders [[cbc8194](https://github.com/baptisteArno/typebot.io/commit/cbc8194f19396ed8f8b3ea05d75223beeab42c3c)] +- ♻️ Replace schemas with merge and discriminated unions [[d154c4e](https://github.com/baptisteArno/typebot.io/commit/d154c4e2f2ed0548130344ede257e19fb43f6be7)] +- ⬆️ Upgrade dependencies [[ff09814](https://github.com/baptisteArno/typebot.io/commit/ff09814eadca527c0118a537279d961adf55ac0f)] + +### Fixed + +- 🐛 (openai) Fix assistant sequence was not correctly saved [[5aec8b6](https://github.com/baptisteArno/typebot.io/commit/5aec8b6c6682aa2da4034230a894f02add2faef2)] +- 💚 Fix docs build failing [[76a8064](https://github.com/baptisteArno/typebot.io/commit/76a8064e7cf76650f85889bc5866e9b14b39f992)] +- 🐛 (lp) Fix real time airtable bot [[67cb4b4](https://github.com/baptisteArno/typebot.io/commit/67cb4b4878ed80e60a88d6a260a1b4b79016de55)] +- 🐛 (js) Fix preview message without avatar [[e713211](https://github.com/baptisteArno/typebot.io/commit/e7132116f43896ad1e73eae5af123d53e6320cde)] + + + +## 2.11.4 (2023-03-13) + +### Added + +- ✨ Add basic ChatGPT template [[86ecd4a](https://github.com/baptisteArno/typebot.io/commit/86ecd4aa8703665b073cb8d5338899cc4de05d73)] +- ✨ Add movie recommendation template [[53cdb35](https://github.com/baptisteArno/typebot.io/commit/53cdb3598410ac6fa4680d4dfdad71342890ebb9)] +- ✨ Add OpenAI block [[ff04edf](https://github.com/baptisteArno/typebot.io/commit/ff04edf1395770145a89ce2f8303a00cac357c6e)] + +### Changed + +- ⚡ (openai) Add Messages sequence type [[c4db2f4](https://github.com/baptisteArno/typebot.io/commit/c4db2f42a62e43dc7d30af5e0d3dc263e47c3e0a)] +- 🚸 Improve magic link sign in experience [[48db171](https://github.com/baptisteArno/typebot.io/commit/48db171c1b5fb5bdc1837bd2fae06d6ab80f4ca4)] +- ♿ (editor) Allow empty group titles [[f9aef90](https://github.com/baptisteArno/typebot.io/commit/f9aef907e3e09958eb1f595dcfee71c384101c9b)] +- 💄 (js) Make sure lite badge can't be hidden [[1863281](https://github.com/baptisteArno/typebot.io/commit/186328132f8c200d7548df6e8e97aeea72a25649)] +- 🚸 (chatwoot) Add close widget task [[9785a0d](https://github.com/baptisteArno/typebot.io/commit/9785a0df5c11dc88ba9534e45419ba41d71a5085)] +- 💄 Add backgroundColor theme field for Popup [[15c1432](https://github.com/baptisteArno/typebot.io/commit/15c1432c32725da0250ca5d30b2447e8514ef9a4)] +- ⚡ (wp) Add custom api host for WP plugin [[ddd20f6](https://github.com/baptisteArno/typebot.io/commit/ddd20f62353f86f669643b551bbf615ae912919d)] +- 🚸 (phone) Improve phone input behavior and validation [[6b08df7](https://github.com/baptisteArno/typebot.io/commit/6b08df71bab3bc2bd23c253bea1a26154713292f)] + +### Fixed + +- 🐛 Fix form urlencoded content-type webhooks [[bcad99f](https://github.com/baptisteArno/typebot.io/commit/bcad99f555fbbb5850954aa95d78ea0bb17b219d)] +- 🐛 (js) Fix popup closing on bot click [[4ae9ea3](https://github.com/baptisteArno/typebot.io/commit/4ae9ea32e4b6ae0967e2b1f996a64aef3455478b)] +- 🐛 (js) Enable prefill for date input [[a66a1e8](https://github.com/baptisteArno/typebot.io/commit/a66a1e822655934881fde62f8b93ec87dc6d45c7)] +- 💚 More efficient db clean script with chunked operations [[5d8c990](https://github.com/baptisteArno/typebot.io/commit/5d8c990c0545e2d9f92f8b2116988f633ae79e35)] +- 🐛 (js) Fix dynamic avatar on mount [[883d519](https://github.com/baptisteArno/typebot.io/commit/883d519875b3d16e668f7766fcf46a18b493616a)] +- 🐛 Incorrect Jump block duplication on typebot import [[26c80f0](https://github.com/baptisteArno/typebot.io/commit/26c80f064f60c497433d98f9da5df0748d8d636e)] +- 🐛 (editor) Fix code editor variable insertion position [[5bbb539](https://github.com/baptisteArno/typebot.io/commit/5bbb5394ba83aa68424a78058305f6c944d6081b)] +- 🐛 (date) Fix date picker UI when editor is in dark mode [[e680d13](https://github.com/baptisteArno/typebot.io/commit/e680d133a5533851c84b492595e692111eec6bd5)] +- 🐛 Fix theme avatar form variable click unfocus bug [[5435452](https://github.com/baptisteArno/typebot.io/commit/5435452ab01a7cb244328102d8a436c05e3941aa)] + +### Miscellaneous + +- 🌐 Introduce i18n [[138f3f8](https://github.com/baptisteArno/typebot.io/commit/138f3f8b076137604ccec76da16b37ccf3e886d3)] +- 📝 Improve description for DISABLE_SIGNUP param [[8df8307](https://github.com/baptisteArno/typebot.io/commit/8df830721c1f47bd6e0084ec4fbd2301714c9d0e)] +- 🩹 Fix crash on bot load when it has no groups [[bf1fbf2](https://github.com/baptisteArno/typebot.io/commit/bf1fbf2c5362fa3f69a0e9fb2f895ac45b5d1f80)] + + + +## 2.11.3 (2023-03-08) + +### Added + +- ✨ Add NPS Survey template [[852cc73](https://github.com/baptisteArno/typebot.io/commit/852cc735119f5885aafd68bd6c7848837090f6ac)] +- ✨ Add new Jump block [[022c5a5](https://github.com/baptisteArno/typebot.io/commit/022c5a573818275b4934fe19e902242ba8fddb45)] + +### Changed + +- 💄 (js) Fix spacings related to avatars [[b2fa202](https://github.com/baptisteArno/typebot.io/commit/b2fa2024a7b735fa58559b342569602cdcd44297)] +- 🗃️ Remove updatedAt field from Result [[2788d58](https://github.com/baptisteArno/typebot.io/commit/2788d58e50f50e2937b59dfbeddedcbf19602bf3)] +- 🚸 (condition) Improve comparison with lists [[0c19ea2](https://github.com/baptisteArno/typebot.io/commit/0c19ea20f8dec85fa6a7a7c5afd6b2dbfaafa7e2)] +- 💄 (editor) Fix some overflow issues with long variable names [[f527df8](https://github.com/baptisteArno/typebot.io/commit/f527df82dd14ce3448a2af01714b48ece72b6232)] +- 🚸 (billing) Add precheckout form [[26e5d9c](https://github.com/baptisteArno/typebot.io/commit/26e5d9c282df0f338401430f590b2571e97b2f55)] +- ⚡ (webhook) Enable advanced config for Zapier and Make.com [[c1a636b](https://github.com/baptisteArno/typebot.io/commit/c1a636b965ae457e1a2fb89d41fb1459a32f2da5)] +- ⏪ (editor) Revert block overflow hidden [[79e5aed](https://github.com/baptisteArno/typebot.io/commit/79e5aedf00eace124de12a18cca0c9caba347abb)] +- 🚸 (js) Improve phone number parsing [[f1a9a1c](https://github.com/baptisteArno/typebot.io/commit/f1a9a1ce8bd87d092b35e25f6cdb9ec47116e227)] +- 🚸 Add a better select input [[cc7d728](https://github.com/baptisteArno/typebot.io/commit/cc7d7285e57e066fc90b564839627191a269796d)] + +### Removed + +- 🔥 Remove disable response saving option [[b77e2c8](https://github.com/baptisteArno/typebot.io/commit/b77e2c8d2cf1e131136f98d33b434d90a787d38a)] +- 🔥 Remove useless stripe env check for usage [[eb3ae8f](https://github.com/baptisteArno/typebot.io/commit/eb3ae8fc35091691222e67d7a2bf652041f1f536)] + +### Fixed + +- 🐛 (webhook) Fix getResultSample when linked typebot not found [[167d366](https://github.com/baptisteArno/typebot.io/commit/167d366d55f8b05fd720d1450b4cda1e047d5a9f)] +- 🐛 (billing) Collect tax ID manually before checkout [[767a820](https://github.com/baptisteArno/typebot.io/commit/767a8208a8ac174b881271a1e0f8a834a50e9b8c)] +- 🐛 (js) Make sure lite badge is displayed [[5bda556](https://github.com/baptisteArno/typebot.io/commit/5bda556200ea9730cfa611f85811701ad60e1b7e)] +- 🐛 Reset custom domain on typebot archive [[6375a75](https://github.com/baptisteArno/typebot.io/commit/6375a7506555e9a1dc41c3fd8a68287b4a74e322)] +- 🐛 (results) Make sure all columns are parsed in the export [[5c31048](https://github.com/baptisteArno/typebot.io/commit/5c3104848ef46684a55dd6f52a3a34a780c207c4)] +- 🐛 (sheets) Correctly parse variables when getting data [[7d56d5b](https://github.com/baptisteArno/typebot.io/commit/7d56d5b39e2f83a73b1c23fd99393eaa4e283e3a)] +- 🐛 (sheets) Save variable first item if length of 1 [[04028e7](https://github.com/baptisteArno/typebot.io/commit/04028e74d9d6aba90062c7d29c3e06e9b5a61f8a)] + +### Miscellaneous + +- 📝 (api) Add protection to sendMessage api ref to test with auth token [[83ae81c](https://github.com/baptisteArno/typebot.io/commit/83ae81ccc6659f7436bb821bc4faf4c3c01e20e3)] +- 📝 (wp) Update wordpress metadata [[67a3f42](https://github.com/baptisteArno/typebot.io/commit/67a3f42edd8172e9db499cb43f5653e879b4c37f)] +- 📝 (lp) Update testimonials content [[6cd1db7](https://github.com/baptisteArno/typebot.io/commit/6cd1db7ba7653206ec4e098f91e79f9f42d96b47)] + + + +## 2.11.2 (2023-03-02) + +### Changed + +- ♿ (js) Use px instead of rem to look good on any website [[cce63df](https://github.com/baptisteArno/typebot.io/commit/cce63dfea307338ff7f954024bd705f76aeb022a)] +- 🚸 (webhook) Also add atomic deep keys selection [[73f4846](https://github.com/baptisteArno/typebot.io/commit/73f4846e1ba8a0ebf726099527f3de6c73e4bbf0)] + +### Fixed + +- 🚑 (webhook) Remove get deep keys test sample [[9d96805](https://github.com/baptisteArno/typebot.io/commit/9d96805d84810390586e01b9806ee157d522afb4)] +- 🐛 (viewer) Fix client side action when in separate group [[a1cf1e8](https://github.com/baptisteArno/typebot.io/commit/a1cf1e89e79855d3788693a801ebc7db23290240)] +- 🐛 (settings) Fix custom head code not updating [[4968ed4](https://github.com/baptisteArno/typebot.io/commit/4968ed4202fe99031be559bc44f2b3ed6222925f)] +- 🐛 (condition) Fix contains not working with lists [[506fe00](https://github.com/baptisteArno/typebot.io/commit/506fe003d1c25b3f9b4b0ec4443db4aff7efb668)] + +### Miscellaneous + +- 📝 Add change password faq [[b2ad91c](https://github.com/baptisteArno/typebot.io/commit/b2ad91c11fff7cc9595eb5e109ebbf1e3e7b87a4)] + + + +## 2.11.1 (2023-03-02) + +### Changed + +- 🚸 (js) Parse script to content to remove useless script tags if any [[cc07389](https://github.com/baptisteArno/typebot.io/commit/cc07389c37e1008dc5041bb22162bfc69fd5eac4)] + +### Fixed + +- 🐛 (js) Improve session remember behavior [[ba253cf](https://github.com/baptisteArno/typebot.io/commit/ba253cf3e9574ba53ec6d142e87a8ef44da69f10)] +- 🐛 (editor) Graph connectors still displayed when switching to dynamic buttons [[c172a44](https://github.com/baptisteArno/typebot.io/commit/c172a44566ae6f27710c38286b0b60ea4a7f7e0a)] +- 🐛 (share) Fix publicId null when publishing [[eebcbb1](https://github.com/baptisteArno/typebot.io/commit/eebcbb10b820a0a5ac8705a28a965d8fcb2243e8)] + + + +## 2.11.0 (2023-03-01) + +### Added + +- 👷‍♂️ Trigger docker deployment on new main tag [[1d1a254](https://github.com/baptisteArno/typebot.io/commit/1d1a25473b47292fcf2653ea95f54f6bfd83fd5b)] + +### Changed + +- ⚡ (editor) Improve edges responsiveness [[f8f98ad](https://github.com/baptisteArno/typebot.io/commit/f8f98adc1cc4359353339e279b6dedf2d7f6808d)] +- ♻️ Better phone input props pass [[73ef12d](https://github.com/baptisteArno/typebot.io/commit/73ef12db7209a53b76dcaa91f5da22eaefb1242e)] +- ♻️ Improve new version popup polling [[2fc78a5](https://github.com/baptisteArno/typebot.io/commit/2fc78a5b7d8c1cbe249dca911e97dae9d1c70a39)] +- ♿ (viewer) Show error message for incompatible browsers [[edf0ecd](https://github.com/baptisteArno/typebot.io/commit/edf0ecd7125ed028e1b28342d6e693c0012a2fe8)] + +### Removed + +- 🔥 (viewer) Remove buttons input validation [[186b376](https://github.com/baptisteArno/typebot.io/commit/186b3760389c74b0451fc2430eba23ec9941553a)] + +### Fixed + +- 🐛 (webhook) Fix deep key parser dropdown [[8672dfe](https://github.com/baptisteArno/typebot.io/commit/8672dfe9d7ffc44b01058d6ef10c58922d182743)] +- 🐛 (js) Improve bubbles callback reliability [[f6e128b](https://github.com/baptisteArno/typebot.io/commit/f6e128be37fe6b5039da1ae72a48ba34d9ac518e)] +- 🚑 (editor) Fix block drag when dropping at same spot [[5024c1b](https://github.com/baptisteArno/typebot.io/commit/5024c1b22b3a31d3cc93a314200be3623e10facc)] +- 🐛 (script) Execute client side actions before first bubbles [[d5b8a43](https://github.com/baptisteArno/typebot.io/commit/d5b8a43d3f78ec25616e018c413f7f5f0cf1862f)] +- 🐛 (editor) Flush code editor value when closing [[d57fb47](https://github.com/baptisteArno/typebot.io/commit/d57fb4738d08910fae3605c4fea8dd28eda9913e)] +- 🐛 Attempt to fix load crash on UC Browser [[5dd8755](https://github.com/baptisteArno/typebot.io/commit/5dd87554c32e340a66777adaa3ba29c4e083ec6e)] +- 🐛 (wordpress) Fix admin critical bug and better lib import [[c889f30](https://github.com/baptisteArno/typebot.io/commit/c889f302f6a19ebcf4322011e1c8e668b7be114e)] +- 🐛 (webhook) Test response was not updating [[67e1fd2](https://github.com/baptisteArno/typebot.io/commit/67e1fd2e14334c65763983c7e9c72b0922934de1)] + +### Miscellaneous + +- 📝 Add dynamic buttons section [[caf4086](https://github.com/baptisteArno/typebot.io/commit/caf4086dd827404f53bb229f344794e9bfeb47c3)] +- 📝 Add API share instructions [[eaf8024](https://github.com/baptisteArno/typebot.io/commit/eaf8024c84ba9a4d9f58a162bebe171e6a8e3fc7)] +- 🩹 (viewer) Add path where old engine is forced [[680e967](https://github.com/baptisteArno/typebot.io/commit/680e967a8cba838acaa3ea312874475ef3b448b9)] +- 📝 (embed) Add new script embed instructions [[2b2b1c3](https://github.com/baptisteArno/typebot.io/commit/2b2b1c3d6d197df5b87a795d06e6f509ea162ab6)] +- 🩹 (billing) Leave the email checkout field empty [[8034cee](https://github.com/baptisteArno/typebot.io/commit/8034ceeede003a571c78a8dc8c4335cf19afa7e1)] +- 📝 (wordpress) Add litespeed localization issue instruction [[712daf7](https://github.com/baptisteArno/typebot.io/commit/712daf7ab3ab6ab6291975064f7d8b2881586813)] +- 🛂 (billing) Enable tax id and billing address collection [[2e8f2d8](https://github.com/baptisteArno/typebot.io/commit/2e8f2d81c6f34b1ec32bebb28edbc993a755d734)] +- 🩹 (sendEmail) Save error first in logs [[761e1c7](https://github.com/baptisteArno/typebot.io/commit/761e1c71844f4cc4a70147984d6155105b24c68b)] + + + +## 2.10.5 (2023-02-23) + +### Added + +- ✨ (buttons) Allow dynamic buttons from variable [[2ff6991](https://github.com/baptisteArno/typebot.io/commit/2ff6991ca730b895ce86e07cd84f9b2e42ca0425)] +- ✨ Add new user onboarding template [[00b6acc](https://github.com/baptisteArno/typebot.io/commit/00b6acca8e4fd14a6528413a0aaed58e2f805bde)] +- ✨ (preview) Add preview runtime dropdown [[3967e5f](https://github.com/baptisteArno/typebot.io/commit/3967e5f1d0bddb122a4eec4e5815ab599228baf2)] +- ✨ Introduce bot v2 in builder ([#328](https://github.com/baptisteArno/typebot.io/issues/328)) [[debdac1](https://github.com/baptisteArno/typebot.io/commit/debdac12ff238c2a083c020a9dc00173ba7fbad3)] + +### Changed + +- 🚸 (editor) Show toolbar on group click [[0619c60](https://github.com/baptisteArno/typebot.io/commit/0619c609704ee937e16dcbce4697910dea6f9aa7)] +- ⬆️ Upgrade dependencies [[d2880cd](https://github.com/baptisteArno/typebot.io/commit/d2880cdf2dc44cd370d975c5dffb63121759d776)] +- ⚡ Fix / improve results archive crash when too many [[cc9817b](https://github.com/baptisteArno/typebot.io/commit/cc9817b2e36474adbcb5201ce4e7f99d0dd2599d)] +- ♻️ Fix eslint warnings [[be4c8e0](https://github.com/baptisteArno/typebot.io/commit/be4c8e0760046f4a50d3806760694a689f454812)] +- 💄 Improve new version popup animation [[31711dc](https://github.com/baptisteArno/typebot.io/commit/31711dc24d79b3cc2e967234360e247258ffe3a4)] +- 🚸 (editor) Make expanded settings window bigger [[a265143](https://github.com/baptisteArno/typebot.io/commit/a265143dc03dc65175f26659212b2fe2e36d4d89)] +- 🚸 (bot) Show a popup when the redirect is blocked by browser [[b2d1235](https://github.com/baptisteArno/typebot.io/commit/b2d1235f1b48bda4642ed500e4bbff1be120e9cb)] + +### Fixed + +- 🐛 (buttons) Fix dynamic buttons edge not showing [[e1b7320](https://github.com/baptisteArno/typebot.io/commit/e1b7320f6f2c2e6ec72265cdf0b3c3df2e6eee79)] +- 💚 Fix Vercel build due to unnecessary dev packages upload [[8462810](https://github.com/baptisteArno/typebot.io/commit/84628109d07103770f4631f6d689838ab42753f5)] +- 🐛 (editor) Fix text bubble refocus carret position [[bc47cc4](https://github.com/baptisteArno/typebot.io/commit/bc47cc46c0b2b8382046399ab13bddf139736337)] +- 🐛 (editor) Fix saving typebot after undoing changes [[671c2cb](https://github.com/baptisteArno/typebot.io/commit/671c2cb1011e47341cdb466ae67b20f32e36b759)] +- 🐛 (settings) Fix typing emulation not working [[889e6a4](https://github.com/baptisteArno/typebot.io/commit/889e6a4f7e61614442bdd36ff568fbfc8a891138)] +- 🐛 (setVariable) Avoid evaluate code if single variable [[6339f44](https://github.com/baptisteArno/typebot.io/commit/6339f442bf1ef693d87059e4181f09a02716038e)] +- 💚 Don't trigger docker deployment on new lib tags [[96f5e4d](https://github.com/baptisteArno/typebot.io/commit/96f5e4db9e20ff67e1ad16d222b9b70f9f2ade84)] +- 🐛 Fix bot not proceeding when embedded [[bdf088b](https://github.com/baptisteArno/typebot.io/commit/bdf088bd9530e11e32cdd8153ea8098e11a1da8c)] +- 🐛 (phone) Fix phone number parsing and default country [[4efe2c4](https://github.com/baptisteArno/typebot.io/commit/4efe2c48bb92d64b3fb7d7fd1ac9cf1368d76b76)] +- 🐛 Correctly update prefilled variables [[d8194ff](https://github.com/baptisteArno/typebot.io/commit/d8194ff9987dc07a3c4643a19defc36fab98a2d2)] +- 🐛 Fix bubble proper cleanup function [[541dcd2](https://github.com/baptisteArno/typebot.io/commit/541dcd2bb78f018ce24032813f3f5faf8b8cb85e)] +- 🐛 Make sure variables are properly overwritten [[148315f](https://github.com/baptisteArno/typebot.io/commit/148315f6eeb552a68fd6daa2b967597e966c4327)] +- 🐛 Fix variable buttons with new engine [[83ae57c](https://github.com/baptisteArno/typebot.io/commit/83ae57cf0c950159ccb5adeeb707bdb095afda61)] +- 🐛 Use position fixed for bubble [[527dc8a](https://github.com/baptisteArno/typebot.io/commit/527dc8a5b11b198a5cbc605a60487c6b5e469025)] +- 🐛 Improve bot libs mount in prod env [[907cad8](https://github.com/baptisteArno/typebot.io/commit/907cad805031e75161dd2dc83b1f962769208a84)] +- 🐛 Fix bot libs mount behavior and prop types [[46bf25a](https://github.com/baptisteArno/typebot.io/commit/46bf25a5806dc763823bd3f896445977ce64b948)] +- 🐛 (typebot) Attempt to fix updatedAt comparison with different timezones [[6c2df1a](https://github.com/baptisteArno/typebot.io/commit/6c2df1a474dbd0ec80ea9a6b8bd1ece792c3f4d1)] + +### Miscellaneous + +- 📝 Add appropriate docs for new @typebot.io libs [[a4e3f4b](https://github.com/baptisteArno/typebot.io/commit/a4e3f4bf9c072ba0af1be1d32b1f818c21f7c2c4)] +- 🧑‍💻 Better Typebot import in vanilla JS sites [[ab43d80](https://github.com/baptisteArno/typebot.io/commit/ab43d809c36a2879d440eba5b3e318beb5f6b864)] + + + +## 2.10.4 (2023-02-19) + +### Changed + +- ⚡ (embedBubble) Enable variable embed height [[621cd58](https://github.com/baptisteArno/typebot.io/commit/621cd58244d5a21271a2dff6223b64f2c3a8ceb5)] +- ♻️ (auth) Make sure new users have an email [[0831dcf](https://github.com/baptisteArno/typebot.io/commit/0831dcf72a3f0761e583555185dc41c114ae6f43)] +- 💄 Improve new version popup ui [[0e1fa4e](https://github.com/baptisteArno/typebot.io/commit/0e1fa4e339aad615a2925f3b2ac6a56c8d0315c5)] +- ♻️ (billing) Refactor billing server code to trpc [[b73282d](https://github.com/baptisteArno/typebot.io/commit/b73282d8108dbeca7d09e46920d627d07ed52c1a)] +- 🚸 (typebotLink) Exclude current bot name from select list [[9624387](https://github.com/baptisteArno/typebot.io/commit/962438768ec5c2e97f47781b5d3dbad04cdfb9a2)] +- 🚸 (editor) Improve typebot updatedAt detection [[4a0dd0b](https://github.com/baptisteArno/typebot.io/commit/4a0dd0b3dda546b3a472f6f2b8c336daf02cceac)] +- ♿ (editor) Improve variables popover click detection [[618eb8a](https://github.com/baptisteArno/typebot.io/commit/618eb8a8827e1789d9041b34e6d0a474c74436ea)] +- ♿ Add an update notification popup [[8ac3784](https://github.com/baptisteArno/typebot.io/commit/8ac3784c0fa477b9b6ecd5b6102865268e4c4d1f)] +- 💄 Add proper italic fonts in bot [[435edd0](https://github.com/baptisteArno/typebot.io/commit/435edd03c09073442fdd19fb32157bd21e2c16ff)] +- ♻️ (results) Remove unecessary totalSelected compute [[44d7740](https://github.com/baptisteArno/typebot.io/commit/44d77409523a62850d712f4550caa5b6fdd9a8e5)] +- ♻️ (editor) Improve webhook creation [[ac464ea](https://github.com/baptisteArno/typebot.io/commit/ac464eabdf65c62049b41736d6e597f2521970b0)] +- 💄 (collaborator) Fix collab list UI [[6e066c4](https://github.com/baptisteArno/typebot.io/commit/6e066c44e109ccb830d0f4672790a5e66f190699)] + +### Fixed + +- 💚 Build docker images for postgresql only [[8a0155d](https://github.com/baptisteArno/typebot.io/commit/8a0155dab8651c0deca4a65b265879e36b731674)] +- 🐛 (typebot) Make sure old typebot properties are removed when pulled [[d22cc45](https://github.com/baptisteArno/typebot.io/commit/d22cc45a97bc6466c2fb32408e1ca49a88b13d5e)] +- 🐛 (webhook) Fix record to update not found [[c32aadc](https://github.com/baptisteArno/typebot.io/commit/c32aadc95b8a812100e10a7994284b0746e6074f)] +- 🐛 (billing) Fix crash when having a draft invoice [[d805ea9](https://github.com/baptisteArno/typebot.io/commit/d805ea9c10c393c5e7285602286ec28916c9373b)] +- 🐛 (bot) Still parse variables value if code fails [[44cb14d](https://github.com/baptisteArno/typebot.io/commit/44cb14d0cb95e046117ac9fe8b2b7d319600da9a)] +- 🐛 (editor) Fix update typebot when having more than 100.000 results [[3a9e359](https://github.com/baptisteArno/typebot.io/commit/3a9e35916abfc957637389df9313f8573fc60fbb)] +- 🐛 Fix input file empty error [[d0a8faa](https://github.com/baptisteArno/typebot.io/commit/d0a8faa3e7fded1b917d204174eb74c9c1e5a7b9)] +- 🐛 (typebotLink) Fix typebotIds infinite query param [[2f7e71f](https://github.com/baptisteArno/typebot.io/commit/2f7e71f66e7eb88b2ddc681fd0cb9f81cb38bc21)] + +### Miscellaneous + +- 📝 Add a "Publish" doc [[fde14a8](https://github.com/baptisteArno/typebot.io/commit/fde14a800dba9f11cfd6589e44916758c98d3687)] + + + +## 2.10.3 (2023-02-14) + +### Changed + +- 🚸 (bot) Keep bubble content in local state for each bubble [[97e2578](https://github.com/baptisteArno/typebot.io/commit/97e2578bcce56eac8ab79d6e4d4eca4b9fb2bcf2)] +- 🚸 (results) Improve results action buttons [[08e33fb](https://github.com/baptisteArno/typebot.io/commit/08e33fbe702cac9cb057fb346f25b5469beec24b)] +- 🗃️ Improve result logs query [[1a3596b](https://github.com/baptisteArno/typebot.io/commit/1a3596b15c66baeace496c65881d19383c449c24)] +- 🗃️ (webhook) Improve webhook creation query [[e39cd94](https://github.com/baptisteArno/typebot.io/commit/e39cd94eef32338cebc349094957ba4aea3820b2)] +- 🗃️ (results) Improve result delete queries [[1d4d39c](https://github.com/baptisteArno/typebot.io/commit/1d4d39c649be6591290c379522fc602b765fbb86)] +- 🗃️ Improve get typebot query performance [[c0757f8](https://github.com/baptisteArno/typebot.io/commit/c0757f81872dfcf97d071f7f82f6c2f01accc098)] +- 🗃️ Improve usage queries [[e9a1d16](https://github.com/baptisteArno/typebot.io/commit/e9a1d1683eb7a3a64106fb3745899f0423e12857)] +- 🚸 (results) Remove useless scrollbars and make header sticky [[b98aef5](https://github.com/baptisteArno/typebot.io/commit/b98aef53fddd86d9fab98629333b6e29d4fa1924)] +- 🚸 (results) Show deleted block answers if any [[3ab6790](https://github.com/baptisteArno/typebot.io/commit/3ab67902c0b305d33902bbd79c92284701b5f527)] +- 💄 Correct default favicon for viewer [[5e358ca](https://github.com/baptisteArno/typebot.io/commit/5e358caee21e2b6b45d52382c2d4fb4a0d38840d)] +- 🏗️ Add compatibility with different prisma clients [[caf5432](https://github.com/baptisteArno/typebot.io/commit/caf54321ece0934c2979007aa7182a63a992b601)] + +### Removed + +- 🔇 Remove unused logs [[23ec5aa](https://github.com/baptisteArno/typebot.io/commit/23ec5aa4d5d9c813f5265a199903a3393fa158dc)] + +### Fixed + +- 🐛 (bot) Still parse variable ID in code if has no value [[17020c8](https://github.com/baptisteArno/typebot.io/commit/17020c8fef6e2371926308228cf97fa30a3e078d)] +- 🐛 (results) Fix export with deleted blocks [[c35ba58](https://github.com/baptisteArno/typebot.io/commit/c35ba58fae94a5cd677ab6cf2e0654697e2c2c4c)] +- 🐛 Fix 404 error page [[eef015e](https://github.com/baptisteArno/typebot.io/commit/eef015e39587ea3c3a830c2c6d9109203a56788e)] +- 🐛 (editor) Fix text bubble regex not compatible with Safari [[2c80e3a](https://github.com/baptisteArno/typebot.io/commit/2c80e3a1c06ca2b3a4e79aa2f2df54405db9a71e)] +- 🐛 Fix X-Frame-Option header [[7baa610](https://github.com/baptisteArno/typebot.io/commit/7baa610b2d47afee60dbe9d8225e0ebb66d72e84)] +- 🐛 (editor) Fix typebot update permissions [[bac97a8](https://github.com/baptisteArno/typebot.io/commit/bac97a8ee4dfb944863ee07959255dff4757ab6a)] +- 🐛 (webhook) Parse test variables in webhook body sample [[8a02c70](https://github.com/baptisteArno/typebot.io/commit/8a02c701da2970346de179881b18402df0cffd5e)] +- 🐛 (results) Fix results still appearing when deleted [[3728bca](https://github.com/baptisteArno/typebot.io/commit/3728bca17386d3f1faeac3c564f041ab3f21c325)] +- 🐛 (workspace) Fix members invitation when having unlimited plan [[0dba994](https://github.com/baptisteArno/typebot.io/commit/0dba994210407e46a1157b14b626b18f57375241)] +- 💚 Fix clean database script [[770b29e](https://github.com/baptisteArno/typebot.io/commit/770b29e7673a07e3812529b7f4028c81c59ea847)] +- 💚 Fix utils export issue [[c175ade](https://github.com/baptisteArno/typebot.io/commit/c175ade4d0521c196d6cca23f827f28f606279ba)] +- 🐛 (editor) Allow variables in bubble text links [[2dbf0fb](https://github.com/baptisteArno/typebot.io/commit/2dbf0fb848ea5d8ea427c0a68ad57ba1e4b099a6)] +- 🐛 Fix custom CSS initialization [[c386bb5](https://github.com/baptisteArno/typebot.io/commit/c386bb5a08b67fff509b7036e0ba6e59b97ba230)] +- 💚 Fix docker build prisma generate script [[c9fda15](https://github.com/baptisteArno/typebot.io/commit/c9fda1518f5cf1ecceadacb40c738383a4c1d657)] + +### Miscellaneous + +- 📝 Add a planetscale guide [[46e9271](https://github.com/baptisteArno/typebot.io/commit/46e9271aaa051a4b3e0fd3c52867b1b7d978b0b8)] +- 📦 Update cuid to cuid2 [[51f7670](https://github.com/baptisteArno/typebot.io/commit/51f76700b2aa72a3e8e0250d431627064310f0aa)] +- 📝 Remove advanced section in Condition docs [[c879c6f](https://github.com/baptisteArno/typebot.io/commit/c879c6f83a719aae50912b15f935003d9b3a4269)] +- 📝 Fix landing page typo ([#301](https://github.com/baptisteArno/typebot.io/issues/301)) [[c50c2b8](https://github.com/baptisteArno/typebot.io/commit/c50c2b84b6eef085dec77c27a745ea458e70861e)] + + + +## 2.10.2 (2023-02-07) + +### Added + +- 👷‍♂️ Improve sentry release detection [[f07bf25](https://github.com/baptisteArno/typebot.io/commit/f07bf2532e69e49ba61e314b1efe475886cc0343)] + +### Fixed + +- 🐛 (chatwoot) Fix setUser with variables [[f936d4f](https://github.com/baptisteArno/typebot.io/commit/f936d4fae319ff7ed35438b07f74f4aad902421d)] + + + +## 2.10.1 (2023-02-06) + +### Changed + +- ⚡ Improve old engine bubbles display robustness [[ae88d2c](https://github.com/baptisteArno/typebot.io/commit/ae88d2cae1d8fbc5089891ffa3cdef56eb8effff)] +- 🗃️ Add updatedAt fields where missing [[0b34321](https://github.com/baptisteArno/typebot.io/commit/0b34321bf7ea36dc8cd15a63107e541b70841813)] +- 🗃️ Fix schema migration diff [[bf60728](https://github.com/baptisteArno/typebot.io/commit/bf607289f43a33d43d7d26ae3962ad8459f098af)] + +### Removed + +- 🔥 Remove useless console logs [[77df555](https://github.com/baptisteArno/typebot.io/commit/77df5556f475757d3ceecbdefe0bce0b755ed1ec)] + +### Fixed + +- 🐛 Fix searchable dropdown z-index issues [[2b36ced](https://github.com/baptisteArno/typebot.io/commit/2b36cedb7bce77e932285a83923c3459d3e9539d)] +- 🐛 Fix phone input placeholder color [[4e0df33](https://github.com/baptisteArno/typebot.io/commit/4e0df33551946219a60598e23631a69177393d8c)] +- 🐛 Fix overflow issue for Theme and Settings pages [[17d94a9](https://github.com/baptisteArno/typebot.io/commit/17d94a9f9ff80338604346fe33fb1d5219b19cc6)] + +### Miscellaneous + +- 🩹 Clean up typebot before updating [[f42d144](https://github.com/baptisteArno/typebot.io/commit/f42d1445c6f0518e7466401df3988e458a055d1c)] + + + +## 2.10.0 (2023-02-02) + +### Added + +- 👷‍♂️ Add expired records database cleanup scripts [[1b060da](https://github.com/baptisteArno/typebot.io/commit/1b060dac2de4f9631713b8c742ecb06606aa8b98)] + +### Changed + +- 🗃️ Set new fields column to not null [[a5dc982](https://github.com/baptisteArno/typebot.io/commit/a5dc9821d6cf8dbf839ebcebe0b0f67a1a4c11d0)] +- 🗃️ Remove list types from db schema [[6e0f0e4](https://github.com/baptisteArno/typebot.io/commit/6e0f0e487bac1d5cb04bbd702e76f8fa5401d8ff)] + +### Removed + +- 🔥 Remove inline edit in old engine [[58c6efc](https://github.com/baptisteArno/typebot.io/commit/58c6efc5c86d31ed96a9b9bc30a9c0fc6423d892)] + +### Fixed + +- 🐛 Remove deny X-Frame on typebot.io [[2c57eba](https://github.com/baptisteArno/typebot.io/commit/2c57eba994fe318867d8a6b27fc94626653752de)] +- 🐛 Fix workspace member lock banner always on [[1806840](https://github.com/baptisteArno/typebot.io/commit/1806840119476743be7e2c1c4c424c36f5480c13)] +- 🚑 Revert prisma fix [[1dfe4ca](https://github.com/baptisteArno/typebot.io/commit/1dfe4cadf7ab8e01c9f330765459efa66ad12103)] +- 🐛 Fix crash when outgoing edge blockId does not exist [[58ca1c3](https://github.com/baptisteArno/typebot.io/commit/58ca1c3ad69cb4ffc2a8695c074cadf9d80383a0)] + +### Miscellaneous + +- 📝 Add google sheets callback URL instruction [[4a9f2b1](https://github.com/baptisteArno/typebot.io/commit/4a9f2b1b02ca4be041a265d977142fc86e57a25d)] +- 🩹 Better fix for ENOENT schema.prisma [[3851b2d](https://github.com/baptisteArno/typebot.io/commit/3851b2d70b58af87beb6e652e0ea32b6a892c3c5)] +- 🩹 Still accept old bot property when importing [[42d4bc3](https://github.com/baptisteArno/typebot.io/commit/42d4bc3882fa767b6c4df2f0d7d327e277997256)] + + + +## 2.9.4 (2023-01-28) + +### Added + +- ✨ Add Wait block [[fa9e4b7](https://github.com/baptisteArno/typebot.io/commit/fa9e4b7b673571949d7d5c721dae9040a1857902)] + +### Changed + +- ⚡ (editor) Improve textbox incoming variable detection [[8d592a3](https://github.com/baptisteArno/typebot.io/commit/8d592a3cc3e5ef3edd736a53e55f945c097c9d20)] +- ⬆️ Upgrade dependencies [[201939f](https://github.com/baptisteArno/typebot.io/commit/201939f8a3d586a42a7d4a44accb4ced6c44e985)] +- ♻️ (auth) Group join workspaces queries in a transaction [[bfd85b4](https://github.com/baptisteArno/typebot.io/commit/bfd85b4fd3002451f7e3b247282fba2114106e81)] +- ⚡ (engine) Implement skip on engine v2 [[d54822a](https://github.com/baptisteArno/typebot.io/commit/d54822af2b5081616fee790998772c547d45011c)] +- 🚸 (dashboard) Add unpublish menu item in dashboard [[f93bc2f](https://github.com/baptisteArno/typebot.io/commit/f93bc2fcb2cd8df1152f6dce3c9780fda05302ac)] +- ♻️ Rename Code block to Script block [[a842f57](https://github.com/baptisteArno/typebot.io/commit/a842f572974123884b67ac4c01d4c6d09abe08a8)] +- 💄 Improve edges alignment when connected to blocks [[068f9bb](https://github.com/baptisteArno/typebot.io/commit/068f9bbd17bd7796308983a9abcd4de0ead3b7a5)] +- ♻️ Add a new unlimited plan [[409e764](https://github.com/baptisteArno/typebot.io/commit/409e7643ad59732d78704cb39d7d921e09904671)] +- 🚸 (engine) Improve engine v2 client loading and timings [[4f78dda](https://github.com/baptisteArno/typebot.io/commit/4f78dda640ee43811fdcdc2f99e2849af8ae2d13)] +- 🚸 Add better page titles and dashboard icons [[ee864d9](https://github.com/baptisteArno/typebot.io/commit/ee864d972923a6f8f0b2e3d891385b8c119e0145)] +- ⚡ Improve new bot engine client side actions [[9aab6dd](https://github.com/baptisteArno/typebot.io/commit/9aab6ddb2cbc50544dc5b57782f322e6c3252348)] +- ♻️ (lp) Remove old bot-engine from landing page [[79622c6](https://github.com/baptisteArno/typebot.io/commit/79622c6884a4647215b24812ed65f7229e06f325)] +- ⚡ (engine) Improve engine overall robustness [[30baa61](https://github.com/baptisteArno/typebot.io/commit/30baa611e5308f45470552160e92d724c47b5310)] +- ♻️ Migrate default background to white [[ff62b92](https://github.com/baptisteArno/typebot.io/commit/ff62b922a04a21119f21fcb81f675dfb4a45536f)] +- 🚸 (share) Hide custom domain dropdown when env isn't configured [[393f5f2](https://github.com/baptisteArno/typebot.io/commit/393f5f27ed3042f84fa26faea21e886219e5e901)] +- ⬆️ Upgrade dependencies [[04d206e](https://github.com/baptisteArno/typebot.io/commit/04d206eab10f6a889b16cd3edd04c95f6d804358)] + +### Fixed + +- 🐛 (share) Fix custom domain delete [[cb83935](https://github.com/baptisteArno/typebot.io/commit/cb83935da937dc0e872f33c4b0947bde7694b2a4)] +- 🐛 Fix misc bugs [[a738897](https://github.com/baptisteArno/typebot.io/commit/a738897dbb544102a9ce4ca546c309ece5eecc77)] +- 🐛 (editor) Fix outside click not working in some cases [[0fc82cf](https://github.com/baptisteArno/typebot.io/commit/0fc82cf73be5249e829959d87e3ac43afdd66460)] +- 🐛 (viewer) Should not import google font url if empty [[14e6ee3](https://github.com/baptisteArno/typebot.io/commit/14e6ee373fa141af6d3b2aa39a93b5a7b1f862ec)] +- 🐛 (lp) Fix real time airtable bot [[eb01fd2](https://github.com/baptisteArno/typebot.io/commit/eb01fd254e997e8dd3a8abc40bf05d2b7f6edbdd)] +- 🐛 (engine) Fix button validation when item content includes a comma [[07f2626](https://github.com/baptisteArno/typebot.io/commit/07f26262ef5aecbc8b53b3566a75afe53955ac03)] +- 🐛 (share) Fix custom domain button not showing [[2d51a8a](https://github.com/baptisteArno/typebot.io/commit/2d51a8a359ef74f4e2615633224a3c9ebd3839d8)] + +### Miscellaneous + +- 📝 Add affiliate program faq section [[8e0043d](https://github.com/baptisteArno/typebot.io/commit/8e0043d51d7fbf57fe5a662d519536ccf111aabc)] +- 📝 Write a guide about UTM params forwarding [[01c9691](https://github.com/baptisteArno/typebot.io/commit/01c969117517a90c52e8a8770aee6041fb5a721e)] +- 📝 Improve the description of NEXTAUTH_URL_INTERNAL [[3d2d401](https://github.com/baptisteArno/typebot.io/commit/3d2d4017b203169b755894e35ff93c9d4e710a1c)] + + + +## 2.9.3 (2023-01-20) + +### Added + +- 👷‍♂️ Add js and react lib auto publish actions [[ef9170d](https://github.com/baptisteArno/typebot.io/commit/ef9170dcb664705270c6859de16d92ea7c8071b7)] + +### Changed + +- 🚸 (auth) Disable email sign in button when email was sent [[eff83d6](https://github.com/baptisteArno/typebot.io/commit/eff83d63279176f6abba3a362898fa7282018c52)] +- 🚸 (publish) Improve invalid public ID feedback [[0febaf9](https://github.com/baptisteArno/typebot.io/commit/0febaf9760521bffe50f5b32105e7847435fe9ff)] +- 🚸 (fileUpload) Add clear and skip button labels customization [[f697a5e](https://github.com/baptisteArno/typebot.io/commit/f697a5e99c37d331e391597fdb58a99dd51c728f)] +- 🚸 (account) Improve account form and fix cyclic dependencies [[49058da](https://github.com/baptisteArno/typebot.io/commit/49058da206b5ae10ca91ccf991cacf4282ca6b52)] +- ⚡ (editor) Add Ctrl + z shortcut to undo changes in editor ([#255](https://github.com/baptisteArno/typebot.io/issues/255)) [[c711f36](https://github.com/baptisteArno/typebot.io/commit/c711f3660f906f5694dfd67e26a860202729b03a)] +- 🚸 (dashboard) Soften imported bot model check [[67ee197](https://github.com/baptisteArno/typebot.io/commit/67ee197d9b9e4bc74766908bafcd53c92f55a348)] +- ⚡ (chat) Improve chat API compatibility with preview mode [[7311988](https://github.com/baptisteArno/typebot.io/commit/7311988901db728a4cd162fc2cfca03971e28135)] + +### Fixed + +- 🐛 (collaboration) Fix a database rule preventing collaborators to edit a bot [[fe2952d](https://github.com/baptisteArno/typebot.io/commit/fe2952d407874e2104a7e17661b69c89f40ccc45)] +- 🐛 (analytics) Add better completion rate parsing ([#258](https://github.com/baptisteArno/typebot.io/issues/258)) [[cf5520b](https://github.com/baptisteArno/typebot.io/commit/cf5520b0d85f49f45e15583f06cdbfff1478afab)] +- 🐛 (editor) Show variable highlight only when strictly equal [[dbe5c3c](https://github.com/baptisteArno/typebot.io/commit/dbe5c3cdb1f51826cfe7dae14456e720e0d7efee)] + +### Security + +- 🔒 Add X-Frame-Options header in builder and lp [[aa32fe7](https://github.com/baptisteArno/typebot.io/commit/aa32fe782f5be63ab0cbc02616bd6e88775ff8f3)] + +### Miscellaneous + +- 📝 Add extract first name example [[4435fb0](https://github.com/baptisteArno/typebot.io/commit/4435fb0d7ef9ac12f73da3ad5d9464f0b7370021)] +- 📝 Self-hosting manual docs ([#260](https://github.com/baptisteArno/typebot.io/issues/260)) [[930fef2](https://github.com/baptisteArno/typebot.io/commit/930fef2c34f9ea986a15f1a526d464aa547dc18a)] + + + +## 2.9.2 (2023-01-14) + +### Added + +- 👷‍♂️ Adapt manual deployment scripts ([#238](https://github.com/baptisteArno/typebot.io/issues/238)) [[9b5426c](https://github.com/baptisteArno/typebot.io/commit/9b5426ce1808e6a58b0abc81e17b204a00559ff5)] +- 👷‍♂️ Add daily database cleanup action [[4c2eaf9](https://github.com/baptisteArno/typebot.io/commit/4c2eaf9b7939f8e800828f608941e96b74070b00)] +- ✨ Add Bubble and Popup in embed lib v2 [[21f1c7a](https://github.com/baptisteArno/typebot.io/commit/21f1c7a17e8b6576cabc992165df21fb3f57ede6)] + +### Changed + +- ⬆️ Upgrade dependencies [[6459fb8](https://github.com/baptisteArno/typebot.io/commit/6459fb8ec84dd37fba66c998c2d454c8c297a1fa)] +- 🚸 (dashboard) Improve invalid typebot import feedback [[491e60a](https://github.com/baptisteArno/typebot.io/commit/491e60a815dddb4400259b8183e7a8a980cde6ec)] +- 🔧 Add app origin to chat API cors [[f8351e2](https://github.com/baptisteArno/typebot.io/commit/f8351e2c85487931a512c3962af810fd9a25e811)] +- ⚡ Make the default workspace plan configurable [[b142dc1](https://github.com/baptisteArno/typebot.io/commit/b142dc18eb6f75ace3beeba00f1f2f40d7a0ba04)] +- ♻️ Add id token config param to custom OAuth [[4bf93b4](https://github.com/baptisteArno/typebot.io/commit/4bf93b48724203f5f173b1a5bf4e0e231ffeba8a)] +- ⬆️ Upgrade dependencies [[f79f693](https://github.com/baptisteArno/typebot.io/commit/f79f6932c220e1f53c6bf08589e639bc96e694ae)] + +### Fixed + +- 🐛 Fix date input label computation [[13d6679](https://github.com/baptisteArno/typebot.io/commit/13d66793082313d8a39b18b124fcbeaaa68367e2)] +- 🐛 (editor) Don't show variable collection if not recognized [[ecc7e18](https://github.com/baptisteArno/typebot.io/commit/ecc7e18226163bb50eb62aeb9e749e203b6298ee)] +- 💚 Fix clean database script [[5462a1b](https://github.com/baptisteArno/typebot.io/commit/5462a1be6a9d451ce86e2f71761ca8bfea448209)] +- 🐛 (dashboard) Fix typebot name overflow [[5507b8e](https://github.com/baptisteArno/typebot.io/commit/5507b8ef67f14ea21ed69a7ccdfcd5ef4825b66f)] +- 🐛 (editor) Improve variables dropdown auto focus [[b65ffe8](https://github.com/baptisteArno/typebot.io/commit/b65ffe8c53b654885a21214f824e9e7c0d819a86)] + +### Miscellaneous + +- 📝 Update FAQ [[f1fa535](https://github.com/baptisteArno/typebot.io/commit/f1fa5358e98e9f31ad772b65883f33bf25354502)] +- 🧑‍💻 (auth) Improve Custom OAuth set up [[3bc0240](https://github.com/baptisteArno/typebot.io/commit/3bc02406f382852d2a5f6f58fbef1d60e35432cc)] + + + +## 2.9.1 (2023-01-06) + +### Added + +- 🔊 Improve invalid typebot update detection [[ca2c15d](https://github.com/baptisteArno/typebot.io/commit/ca2c15dbab9c673ef07c26c8b37954cbc11eb38a)] + +### Changed + +- 💄 Fix code editor transparent selection [[3f7e1ce](https://github.com/baptisteArno/typebot.io/commit/3f7e1ce1252134e664a11828b37c26707f68172f)] +- 🔧 Explicitly add Sentry release sha [[963f887](https://github.com/baptisteArno/typebot.io/commit/963f887b34559ff07c4b098cffb3223c3e4acbfb)] +- ♻️ (js) Implement Payment input in bot v2 [[61eff4c](https://github.com/baptisteArno/typebot.io/commit/61eff4c36db054a131e04885aceb4d732bbd7708)] +- 🚸 (js) Improve setHiddenVariables command [[b105bf8](https://github.com/baptisteArno/typebot.io/commit/b105bf8b8ebde5998fd2bf0bb6c0f66dd7000c1f)] + +### Fixed + +- 🐛 (editor) Fix popover zIndex [[2d20f1c](https://github.com/baptisteArno/typebot.io/commit/2d20f1c41cda55aeebcb1580d542cbab3f95ceea)] +- 🐛 (share) Fix clipboard for updated typebot ID [[fadf34a](https://github.com/baptisteArno/typebot.io/commit/fadf34ad61505b282412300457f1a113430c3d13)] +- 🐛 (auth) Add custom oauth client id and secret params [[6cc3cbf](https://github.com/baptisteArno/typebot.io/commit/6cc3cbf182950fcfbaea00d4bb1345378244316c)] +- 🐛 Fix new typebot creation host bubble parsing [[119f6dc](https://github.com/baptisteArno/typebot.io/commit/119f6dc348be056eb842b1b969f43151168de611)] +- 🐛 (sendEmail) Check if attachment is URL [[7174ef0](https://github.com/baptisteArno/typebot.io/commit/7174ef0f81ceab4eb6a7d955d7d7c5d9e3ce2baa)] +- 🐛 (editor) Fix variables dropdown behind modal [[b455078](https://github.com/baptisteArno/typebot.io/commit/b455078631d9348a4b88f065b710afc7a1b385b4)] +- 🐛 (chat) Make sure a bot session can be restarted [[de167a8](https://github.com/baptisteArno/typebot.io/commit/de167a8daff49bff581ee76fb738cac73647164d)] +- 🐛 (editor) Fix variable dropdown overflow [[c1a32ce](https://github.com/baptisteArno/typebot.io/commit/c1a32ce26bb0088e8af02eea544158e1bdb446da)] +- 🐛 (sheets) Make sure sheet IDs are string [[e1af6af](https://github.com/baptisteArno/typebot.io/commit/e1af6af9c8024493e07c081fe9b177aea2a75158)] +- 🐛 (sheets) Convert to base options before changing action [[f4615d8](https://github.com/baptisteArno/typebot.io/commit/f4615d83cde86395d238269930ba8962ec46c08e)] + +### Miscellaneous + +- 📝 Add custom body with variable example [[40d230a](https://github.com/baptisteArno/typebot.io/commit/40d230a73a489dda5f2a344669fe97c465af7b5d)] + + + +## 2.9.0 (2023-01-02) + +### Added + +- ✨ (auth) Add custom OAuth provider support [[b9d3893](https://github.com/baptisteArno/typebot.io/commit/b9d38935a69e555921c9a1388bdbf2336d82ca44)] +- ✨ (typebot-js) Add setHiddenVariables command [[99850dd](https://github.com/baptisteArno/typebot.io/commit/99850ddbeb2dbb57396ecd01ae95a715a4ce4c45)] + +### Changed + +- ⬆️ Upgrade dependencies [[ec7481d](https://github.com/baptisteArno/typebot.io/commit/ec7481d002e60d6fd657a083b950bc0cc1da7cc5)] +- 🚸 Only show onboarding modal on cloud manage version [[080353b](https://github.com/baptisteArno/typebot.io/commit/080353bffb42b30799d7e641e828649ddd6e7d61)] + +### Fixed + +- 🐛 (bot) Update result variables when overwritten by input [[f49a301](https://github.com/baptisteArno/typebot.io/commit/f49a3013d418d06ebda7d6901cc91a06e16efc55)] + +### Miscellaneous + +- 🧑‍💻 Parse line breaks for plainText attributes [[bea1a6a](https://github.com/baptisteArno/typebot.io/commit/bea1a6a3f802d69d57321dc7d42345384f5f7b3e)] +- 📝 Add Make.com instructions [[b9ed50b](https://github.com/baptisteArno/typebot.io/commit/b9ed50b016f340ec50beb573c7f7ce8561937b9d)] +- 📝 Improve License section in README [[60ed0b2](https://github.com/baptisteArno/typebot.io/commit/60ed0b2d4a92a5fc1d61ef221b58f8eb70f66820)] + + + +## 2.8.12 (2022-12-28) + +### Changed + +- 🔧 (scripts) Add typebot fix script [[ad72557](https://github.com/baptisteArno/typebot.io/commit/ad725573108daa82d4558926d2623f2ab901b598)] + +### Fixed + +- 🚑 (condition) Fix crash when adding condition block [[853ea79](https://github.com/baptisteArno/typebot.io/commit/853ea79f6bba897a1e9c216265525977440969b9)] + + + +## 2.8.11 (2022-12-25) + +### Summary + +The new dark mode is here! 🌑 + +You can now add a GTM container ID directly in the Settings tab to enable GTM in your typebot. + +Rating input now has a "One click submission", that disable the "Send" button. + +### Added + +- ✨ (rating) Add one click submit option [[449080b](https://github.com/baptisteArno/typebot.io/commit/449080b0add0ef570ffd27de94f39b939f6a5e83)] +- ✨ Add Google Tag Manager ([#185](https://github.com/baptisteArno/typebot.io/issues/185)) [[a898a7a](https://github.com/baptisteArno/typebot.io/commit/a898a7aa4128ba1baff1d645bbcef3ec867a3a38)] +- ✨ Add dark mode ([#191](https://github.com/baptisteArno/typebot.io/issues/191)) [[3394fa5](https://github.com/baptisteArno/typebot.io/commit/3394fa5e0a7ee9448fc31e3c1dd1700f64306ab7)] + +### Changed + +- ⬆️ Upgrade dependencies [[b0075fd](https://github.com/baptisteArno/typebot.io/commit/b0075fd374e3a8480535289c093afbd6f89c6089)] +- 💄 (dashboard) Fix folder color for dark mode [[752e78c](https://github.com/baptisteArno/typebot.io/commit/752e78cea207df91aa45a006f64d9129c56b2575)] +- 🚸 (buttons) Show collected variable in buttons block preview [[f224ab9](https://github.com/baptisteArno/typebot.io/commit/f224ab9b16a7ee91f7281314498f2be5815df6b2)] +- 💄 Fix router progress bar color for dark mode [[e55823e](https://github.com/baptisteArno/typebot.io/commit/e55823e0112291a32886908fd4c63365275106e6)] +- ⚡ Improve app appearance radio group image loading [[25acd04](https://github.com/baptisteArno/typebot.io/commit/25acd04abc332635dfb9dcf996ff732a21df70b9)] + +### Fixed + +- 🐛 (chat) Make sure objects are deeply parsed with variables value [[431ad7c](https://github.com/baptisteArno/typebot.io/commit/431ad7c78c0e08a55e06688d20470ccfa757aa7f)] +- 🐛 (settings) Fix custom head code with noscript injection [[2cdc2b4](https://github.com/baptisteArno/typebot.io/commit/2cdc2b43f50cc0bc2a3255ae2b34dbd9890fcacc)] +- 🐛 (webhook) Prioritize variables parsing over answers [[64cd31c](https://github.com/baptisteArno/typebot.io/commit/64cd31cf13aec5b0df9bfe57d45dcc25952336e0)] +- 🐛 (editor) Fix condition item drag and drop [[4109e63](https://github.com/baptisteArno/typebot.io/commit/4109e63b7b39ee63c92fe4a7310dca9fa2354fd9)] +- 🐛 (webhook) Fix parent linked typebot data parsing in webhook [[c3985b0](https://github.com/baptisteArno/typebot.io/commit/c3985b0d50069f3983f71ee0132c86062fab0dd2)] +- 🐛 (webhook) Fix form encoded request parsing [[9149af7](https://github.com/baptisteArno/typebot.io/commit/9149af7e6bcb4aebc77efb3c9e7e2317ff15ffac)] +- 💚 Fix sentry not sending events [[054cbb3](https://github.com/baptisteArno/typebot.io/commit/054cbb35854b675702610306b16266c9e2f9a78e)] + +### Miscellaneous + +- 📝 Explain how code works in Set variable block [[2934af8](https://github.com/baptisteArno/typebot.io/commit/2934af883585562512dd98a781a0cfb6adfc25e3)] +- 📝 Add "How to" section in Buttons block doc [[11ff7ea](https://github.com/baptisteArno/typebot.io/commit/11ff7eab56c3b54f0271a33ba313e2b90d879fa7)] +- ⚗️ Implement bot v2 MVP ([#194](https://github.com/baptisteArno/typebot.io/issues/194)) [[1a3869a](https://github.com/baptisteArno/typebot.io/commit/1a3869ae6d9fa92fc71ef9d981bfffb8e4ee4ecc)] +- 🩹 Fix dark mode bg remaining issues [[d1b5b6e](https://github.com/baptisteArno/typebot.io/commit/d1b5b6ebe66efce61e207e80f60d198cb47fbfd9)] +- 📝 (lp) Add new testimonial [[2bec6bd](https://github.com/baptisteArno/typebot.io/commit/2bec6bda83a977468bffd0aace1e22aa75b1c2ee)] + + + +## 2.8.10 (2022-12-18) + +### Fixed + +- 🚑 (results) Fix results page crash [[6e5786c](https://github.com/baptisteArno/typebot.io/commit/6e5786cfc3ef9bd5e5a5e272c1ca636b6ba6b4f8)] + + + +## 2.8.9 (2022-12-18) + +### Summary + +Tons of database-related improvements and user experience improvements. + +New Google Sheets Get data filtering. You can now select rows based on multiple column values and it will select a random row that matches your filter. + +### Added + +- ✨ (googleSheets) Advanced get filtering [[dcec1f0](https://github.com/baptisteArno/typebot.io/commit/dcec1f0a5c1fb81a3971952cd6af1117925c7b2d)] + +### Changed + +- ⬆️ Upgrade dependencies [[f46ce47](https://github.com/baptisteArno/typebot.io/commit/f46ce4781f154cabed74d5fe2335849ff180651c)] +- 🔧 Add cross env compatibility to scripts ([#184](https://github.com/baptisteArno/typebot.io/issues/184)) [[2cc61b1](https://github.com/baptisteArno/typebot.io/commit/2cc61b1bf1f36e533d87b10151db8f4045434618)] +- 🚸 (editor) Automatically move graph on first group on mount [[6c55510](https://github.com/baptisteArno/typebot.io/commit/6c55510d80bce5a9383b84d35c018c2c10bb9352)] +- 🚸 (workspace) Keep workspaceId in memory even when logging out [[578e41c](https://github.com/baptisteArno/typebot.io/commit/578e41c09f53620052eb38a859667735a2c26709)] +- ⚡ (dashboard) Improve folders and typebots get queries [[3ab047a](https://github.com/baptisteArno/typebot.io/commit/3ab047a48753783d173fa384543ffbbbbc84aa2a)] +- 🗃️ Write faster prisma queries [[7eac2c7](https://github.com/baptisteArno/typebot.io/commit/7eac2c71100dbe9e74afdb204eb62bcd229457d2)] +- 🗃️ Revert usage query back optimization [[fe8a531](https://github.com/baptisteArno/typebot.io/commit/fe8a531715487e4b2ec9f55e68c393377a1bd98c)] +- 🗃️ Optimize usage queries [[d6f90af](https://github.com/baptisteArno/typebot.io/commit/d6f90af126929dfc36af4284384dc75d99df0d11)] + +### Fixed + +- 💚 Fix sentry not receiving events [[68de7b7](https://github.com/baptisteArno/typebot.io/commit/68de7b720fa327ffdac39e45814fe41f6939f013)] +- 🐛 (typebotLink) Populate variable value when linked typebot is injected [[92dc797](https://github.com/baptisteArno/typebot.io/commit/92dc797b6c61818b584034348dcc0575ba0f19fc)] +- 🐛 (workspace) Read custom limits even without CUSTOM plan [[fd6b94b](https://github.com/baptisteArno/typebot.io/commit/fd6b94bb1b61f2ce416e2f004afb52dde36dbdb4)] +- 🐛 (typebotLink) Make sure to update all linked bot variable values [[656d1e3](https://github.com/baptisteArno/typebot.io/commit/656d1e3cade64c7aaca448c9801dff6c400fd174)] +- 🐛 (typebotLink) Fix fetching when typebot ID is current bot ID [[54dee6e](https://github.com/baptisteArno/typebot.io/commit/54dee6e3628b06a9525d57ef08f98602662a4de9)] +- 🚑 Disable usage check on viewer [[855a285](https://github.com/baptisteArno/typebot.io/commit/855a2856c81614966c8227f52d95475cc5f334b0)] + +### Miscellaneous + +- 📝 Add embed PDF from Google Drive instructions [[8b631d7](https://github.com/baptisteArno/typebot.io/commit/8b631d77eb492e597f957024b9857c4999d028fe)] +- 📝 Improve prefilled variables clarity [[141ffd3](https://github.com/baptisteArno/typebot.io/commit/141ffd35f7e5a4687f7fb4450e50e286a3a2d746)] + + + +## 2.8.8 (2022-12-05) + +### Added + +- ✨ Enable Make.com and implement help doc buttons [[d75eceb](https://github.com/baptisteArno/typebot.io/commit/d75eceb23f1fe737a8f2104b2bc6d318d3c6a471)] +- ✨ Add webhook blocks API public endpoints [[c799717](https://github.com/baptisteArno/typebot.io/commit/c7997179053f91d383c3c31d884f30f2196d1c69)] + +### Changed + +- ⬆️ Upgrade dependencies [[2932043](https://github.com/baptisteArno/typebot.io/commit/293204305636d7871214945314d9a2249f39f452)] +- 🗃️ Update non-string variable values in Database [[461d2e2](https://github.com/baptisteArno/typebot.io/commit/461d2e2746de2888e76d1137b8d25136c7150cae)] +- 🔧 Enable usage limits on viewer [[cfcecaa](https://github.com/baptisteArno/typebot.io/commit/cfcecaaa1713780d1d95712315d80dbfcf13efb5)] +- 💄 (lp) Add 2 other testimonials [[03b09ad](https://github.com/baptisteArno/typebot.io/commit/03b09ad6eb6a2465189f0e603e15925740a7239b)] +- 💄 (lp) Update wall of love [[bdf7c0d](https://github.com/baptisteArno/typebot.io/commit/bdf7c0d5c02710be230f3c14b85dddbffb0e4671)] + +### Fixed + +- 🐛 (textBubble) Fix link parsing in text editor [[b4dc640](https://github.com/baptisteArno/typebot.io/commit/b4dc64028cb2affc3a8a487cf6c04285e64329b1)] +- 🐛 Fix api doc CORS [[94a57ae](https://github.com/baptisteArno/typebot.io/commit/94a57aea216c51e46e0566851a45d185b516d0f7)] +- 🚑 Attempt to fix prisma not defined trpc [[3c8820b](https://github.com/baptisteArno/typebot.io/commit/3c8820b2129ba1f5ec5ba89334c4b66a0568fd38)] +- 🐛 (billing) Fix currency possible mismatch on sub update [[f9ffdbc](https://github.com/baptisteArno/typebot.io/commit/f9ffdbc4c52b4d6e0027eee83209cf2c5794157a)] +- 🐛 (results) Fix export accessor parsing [[43a85b5](https://github.com/baptisteArno/typebot.io/commit/43a85b5529081c4dc90aa8d71721b21c266de7de)] +- 🐛 (viewer) Save new variables even if empty list [[49ba434](https://github.com/baptisteArno/typebot.io/commit/49ba43435012b73f1e5ed5318739e63b772cbc69)] + +### Miscellaneous + +- 📝 Update minio setup instructions [[4b2f42b](https://github.com/baptisteArno/typebot.io/commit/4b2f42b40d638d22603103560010c86306bb8bc7)] +- 📝 Improve Chatwoot block instructions [[ca8240b](https://github.com/baptisteArno/typebot.io/commit/ca8240ba291004f1cfe59f43a00ab64bb01287f6)] +- 📝 Improve Google config instructions [[41149b0](https://github.com/baptisteArno/typebot.io/commit/41149b07c6dba08a224042d0fe05d3e9bacd2f0a)] +- ⚗️ Implement chat API [[bf0d0c2](https://github.com/baptisteArno/typebot.io/commit/bf0d0c2475b0a394ca08fa9c629ac5ecf3ad74de)] +- 📝 Improve send email doc [[3e80af6](https://github.com/baptisteArno/typebot.io/commit/3e80af638b16d19e8522fc0887b26d1692c742bd)] + + + +## 2.8.7 (2022-11-27) + +### Added + +- 📈 (lp) Add Vercel analytics [[b29f732](https://github.com/baptisteArno/typebot.io/commit/b29f7325ad8bb6a47306f87d5513222d386242f0)] +- ✨ Add audio bubble block [[7db0e01](https://github.com/baptisteArno/typebot.io/commit/7db0e01acae0731d3537e702438289c56634a60c)] +- ✨ (settings) Add a "disable responses saving" option [[473d315](https://github.com/baptisteArno/typebot.io/commit/473d315e0fc3fb7b7a24408480d67e1400a269f1)] + +### Changed + +- 🗃️ Add answer - groupId index [[9d69470](https://github.com/baptisteArno/typebot.io/commit/9d6947063069c80ef755724b8a89460acc4bf91a)] +- 🔧 Update db turbo scripts [[bdf4e83](https://github.com/baptisteArno/typebot.io/commit/bdf4e8361720175d1c8f1cd2fc10eadf6908f025)] +- ♻️ Add shared eslint config [[451ffbc](https://github.com/baptisteArno/typebot.io/commit/451ffbcacfe4a0417a5642a40eed533565513cd9)] +- ♻️ (results) Introduce tRPC and use it for the results [[d58f9bd](https://github.com/baptisteArno/typebot.io/commit/d58f9bd3a19f4c963c46ec0673ee45854a9a9118)] +- 🔧 Add Tanzania phone option [[c9cc82c](https://github.com/baptisteArno/typebot.io/commit/c9cc82cc0821390b85a0bcc23dc6fd0a3a6fbee7)] +- ♻️ (editor) Migrate from react-draggable to @use-gesture [[7632c54](https://github.com/baptisteArno/typebot.io/commit/7632c5426c026eb1fa15f5dab20e68b4f0735fa5)] +- 🚸 (typebotLink) Add icon in typebots dropdown [[0c3dcc5](https://github.com/baptisteArno/typebot.io/commit/0c3dcc522e95a313701431617c8eab8a4c381f8f)] +- 🚸 (bot) Avoid waiting for blocks with no returned data [[2bd7cee](https://github.com/baptisteArno/typebot.io/commit/2bd7cee58e90824d5058119288cf1e466c95f800)] +- 🚸 (condition) Enable multiple condition items in one block [[6725c17](https://github.com/baptisteArno/typebot.io/commit/6725c17a02f0df499b1dee3b1c3e909def649426)] + +### Fixed + +- ✏️ Remove "Notion" keywords where it's supposed to be "Typebot" [[ce20f96](https://github.com/baptisteArno/typebot.io/commit/ce20f960f2093660104d0cc93d0405fc83bf1250)] +- 🐛 (graph) Make the text bubble selectable without moving group [[0593d2e](https://github.com/baptisteArno/typebot.io/commit/0593d2ead8df6ba5749887f26cccf4ce942411c7)] +- 🐛 (results) Fix results display when variable has undefined value [[d80cc1b](https://github.com/baptisteArno/typebot.io/commit/d80cc1b248275f28928c87d076dba3fcfdc11e89)] +- 🐛 (dashboard) Fix a bug preventing user to see settings content [[ec0e4be](https://github.com/baptisteArno/typebot.io/commit/ec0e4bee77422750dd5b2bbbcae4876e4664e77d)] +- 💚 (docs) Fix api schema generation in CI [[635e688](https://github.com/baptisteArno/typebot.io/commit/635e6887f37616ae22d681095b1f41a3d095afe1)] +- 🚑 (results) Fix results display when variable has null value [[e6dceca](https://github.com/baptisteArno/typebot.io/commit/e6dceca9f3124774f03a69cd90477f07a8796144)] +- 🐛 (workspace) Filter out guests from members list count [[04af489](https://github.com/baptisteArno/typebot.io/commit/04af489119c9577e900efb28853d53ea65bec76e)] +- 🐛 (bot) Fix input prefill when linked to another typebot [[5619eef](https://github.com/baptisteArno/typebot.io/commit/5619eef459f4c67b3667b4f9ec6bc2e277febbf7)] +- 🐛 (results) Fix export results when more than 200 [[8c15fd1](https://github.com/baptisteArno/typebot.io/commit/8c15fd17a1405f9ef8b16d171536b0a9cb15053c)] +- 🐛 Fix new image upload refresh when URL is the same [[fbd3304](https://github.com/baptisteArno/typebot.io/commit/fbd33046a1c16aabe7538315837825ebd892140e)] +- 🐛 (editor) Fix empty typebot name not editable [[2489318](https://github.com/baptisteArno/typebot.io/commit/2489318fa59e70335964f7d96dba029797fb4a4b)] +- 🐛 (audioBubble) Remove .ogg upload option because of Safari incompatibility [[e09adf5](https://github.com/baptisteArno/typebot.io/commit/e09adf5c643cd23de84ab0e676b27d5f8b6650f9)] +- 🐛 (editor) Make sure typebot name can be editable if empty [[c7fde1d](https://github.com/baptisteArno/typebot.io/commit/c7fde1d0bc5ff124265f74e3ceb5845561e49726)] +- 🚑 (lp) Temporarily disable plausible [[d2f617f](https://github.com/baptisteArno/typebot.io/commit/d2f617ff1e831fa4b03c7a15ef45a9b7a44134fc)] +- 🐛 (editor) Fix undo / redo not working properly on button nodes [[c4a4aa3](https://github.com/baptisteArno/typebot.io/commit/c4a4aa3e8313e6d7fa6b961679c7b27bbdeb9dc5)] +- 🚑 (bot) Fix custom email from field without name [[4e6b8ed](https://github.com/baptisteArno/typebot.io/commit/4e6b8ed521b1274a3d9f4a2556a3a9f8fd4211e1)] + +### Miscellaneous + +- ⚰️ (results) Remove results server parser [[9548733](https://github.com/baptisteArno/typebot.io/commit/9548733543a79575148aa62669a76b1b80cfacca)] +- 🛂 Add backup and restore database scripts [[3645607](https://github.com/baptisteArno/typebot.io/commit/3645607ed423236433a1690c31d770e9214c60b4)] +- 📝 Introduce auto generate API doc [[11695ef](https://github.com/baptisteArno/typebot.io/commit/11695efb57011d5899202f474e688a77dd5a9f32)] +- ⚰️ (docs) Remove old link [[feaf49f](https://github.com/baptisteArno/typebot.io/commit/feaf49f137d9c7cf666e78aca8eff8f58621a35b)] +- 📦 (wordpress) Update package version [[78fd974](https://github.com/baptisteArno/typebot.io/commit/78fd974ebe9e681555dfc85faa64c5d04c47a5b2)] +- 📝 Add Chatwoot integration doc [[96eb77d](https://github.com/baptisteArno/typebot.io/commit/96eb77d94bfb960b73a3e44119eb8deb8a48181a)] +- 🛂 Add setCustomPlan script [[6fdbf98](https://github.com/baptisteArno/typebot.io/commit/6fdbf98eedb0c15138383ae258ba57c7dd4b08a5)] +- 🧑‍💻 (typebot-js) Implement easier commands: open / close / toggle [[087d24e](https://github.com/baptisteArno/typebot.io/commit/087d24e58735091a2fa758821da7423b54dc99cd)] +- 🔊 Send trpc internal errors to Sentry [[0090065](https://github.com/baptisteArno/typebot.io/commit/00900657b2cb83029117772fc6ffe2936488c821)] + + + +## 2.8.5 (2022-11-15) + +### Added + +- ✨ Add Chatwoot livechat integration [[ea84039](https://github.com/baptisteArno/typebot.io/commit/ea840390248cfa966e550c25d9af806bd4397295)] +- ✨ (logic) Add execute in parent window context for code block [[b31b603](https://github.com/baptisteArno/typebot.io/commit/b31b603cc786d5b7b5205db838332f671ea6c324)] + +### Changed + +- ⬆️ Upgrade dependencies [[bae710f](https://github.com/baptisteArno/typebot.io/commit/bae710fb1c09071258804a0cbc1f47a6211123fa)] +- ♻️ (bot) Change to features-centric folder structure [[9720944](https://github.com/baptisteArno/typebot.io/commit/972094425ae72f8b962617ec54bccb89a396efb8)] +- ♻️ (models) Change to features-centric folder structure [[a5c8a8a](https://github.com/baptisteArno/typebot.io/commit/a5c8a8a95cf108c8ad4d068f4a51675b888f7c89)] +- ♻️ (viewer) Change to features-centric folder structure [[a9d0479](https://github.com/baptisteArno/typebot.io/commit/a9d04798bcd0d5d9c2d15ed573e9e1b60ed066c8)] +- ♻️ (builder) Change to features-centric folder structure [[643571f](https://github.com/baptisteArno/typebot.io/commit/643571fe7d2a39f398269636bb57c7e8ae3f7a4e)] +- 🚸 (sendEmail) Make custom sender name optional [[3686465](https://github.com/baptisteArno/typebot.io/commit/3686465a85d21bf6342ab8395a5037063e379cac)] +- 🚸 (chatwoot) Make sure to close the chat bubble before opening Chatwoot [[d01549f](https://github.com/baptisteArno/typebot.io/commit/d01549fee6f0a9898a909496acaede91e5d0e17c)] +- ♻️ Improve file upload management [[d102fe1](https://github.com/baptisteArno/typebot.io/commit/d102fe118c3fd0dad96e692932d9792bdb4d514f)] +- 🚸 (signin) Better disabled signups behavior [[570a780](https://github.com/baptisteArno/typebot.io/commit/570a780db1dd204c7d473f8f6c87f6ea8d789dcd)] + +### Fixed + +- 🚑 (typebot-js) Fix 404 unpkg entrypoint [[92147c3](https://github.com/baptisteArno/typebot.io/commit/92147c315f8d0ba92b42fab8579c0425160afc80)] +- 🐛 (typebot-js) Fix default export from js lib [[8ab67b7](https://github.com/baptisteArno/typebot.io/commit/8ab67b7580d47731995ba7e5ddba6d2ad7cc25b6)] +- 🐛 (editor) Fix undo / redo not moving or renaming groups [[de0158b](https://github.com/baptisteArno/typebot.io/commit/de0158be24b6e6c160b9101ee69841128ca82608)] +- 🐛 (editor) Fix bug preventing user to manually zoom in / out [[1f44e8f](https://github.com/baptisteArno/typebot.io/commit/1f44e8f31fe54dc1f68dcbbc90fbc06501d6a683)] +- 🐛 (results) Fix bug preventing user from seeing linked typebots results [[6dd7bd9](https://github.com/baptisteArno/typebot.io/commit/6dd7bd95620df1d34929c70085db668bb250a243)] +- 🐛 (share) Restrict public ID to non-existant only [[63845ef](https://github.com/baptisteArno/typebot.io/commit/63845effaf6134898cb7f2bf353355c24f46a6cc)] +- 🐛 (workspace) Correctly display Guest tag in members list [[4d38726](https://github.com/baptisteArno/typebot.io/commit/4d38726eae17e90f542e7a7db29124ca1956df1c)] +- 🐛 (settings) Allow meta tags in head element [[ad9be92](https://github.com/baptisteArno/typebot.io/commit/ad9be922555ce6eb0a32470811e27b6db25d55b6)] +- ✏️ (lp) Fix incorrect additional limits price [[c62e20f](https://github.com/baptisteArno/typebot.io/commit/c62e20f81add8e7ae9f12e58b8c15e18480799da)] +- 💚 Fix build docker image workflow [[8a8f3ec](https://github.com/baptisteArno/typebot.io/commit/8a8f3ec69a69dc7e3d6aaf6fe5b87b3c64febd0b)] + +### Miscellaneous + +- 🧑‍💻 (typebot-js) Add closeChatBubble event data [[54a1dc0](https://github.com/baptisteArno/typebot.io/commit/54a1dc04313d7fbc46795cf65e123a588245cd66)] + + + +## 2.8.3 (2022-11-02) + +### Added + +- ✨ (billing) Implement custom plan [[385853c](https://github.com/baptisteArno/typebot.io/commit/385853ca3c80d04635be91b84db8be54c85bf437)] +- 👷‍♂️ Auto move project card to review column [[3f7dc79](https://github.com/baptisteArno/typebot.io/commit/3f7dc79918cf8455d33d0b64a90dfa9bc3e83a74)] +- 👷‍♂️ Add script to deploy only dev or main branches on Vercel [[8582c6e](https://github.com/baptisteArno/typebot.io/commit/8582c6e841797dfe98685907663b145bc1cb675d)] +- 👷‍♂️ Add auto link labeled issues to project [[e2e1c09](https://github.com/baptisteArno/typebot.io/commit/e2e1c098a215a80cd026235a2cca50efc642303e)] +- ✅ (webhook) Improve bot test [[264711b](https://github.com/baptisteArno/typebot.io/commit/264711b02957e043a0f1add65842ec903c80acd7)] +- ✨ (lp) Add custom chats and storage in pricing cards [[57c814c](https://github.com/baptisteArno/typebot.io/commit/57c814ceca777379b7a4b2a3657fac944435e9e2)] +- 👷‍♂️ Add auto tag and release actions [[f9a8e78](https://github.com/baptisteArno/typebot.io/commit/f9a8e789047c55fffa475eb3b87e51a3324e65a9)] +- ✨ (template) Add FAQ bot template [[b87ba40](https://github.com/baptisteArno/typebot.io/commit/b87ba4023dea7b47c835fe11a9d36a653d5469b0)] + +### Changed + +- 🚸 (googleSheets) Set value to null if not found from sheet [[4828547](https://github.com/baptisteArno/typebot.io/commit/48285479cc23377ba54bd61ad9a77f0e077c8592)] +- 🚸 (textBubble) Allow mailto and tel links [[baa63a7](https://github.com/baptisteArno/typebot.io/commit/baa63a781066879c0e01cfe85fcf584beb40c018)] +- 🗃️ Add typebotId index on Result table [[f8e770c](https://github.com/baptisteArno/typebot.io/commit/f8e770c8757b93e751ddb117f7d303600ec0b517)] +- 🚸 (share) Sanitize URL ID [[020a37c](https://github.com/baptisteArno/typebot.io/commit/020a37c1f32a1d0b44246c9364df471fe8ed51ce)] +- ⚡ (bot) Improve variables parsing and predictability [[3dc3ab2](https://github.com/baptisteArno/typebot.io/commit/3dc3ab201db001eff8319cb8978c1073b79f1198)] +- 🚸 (bot) disable auto focus on mobile [[40d2db5](https://github.com/baptisteArno/typebot.io/commit/40d2db59dc5168c0dd55eb9f790f308cdf63e333)] +- 🏗️ Use tsup for bot and typebot-js packages [[e8baaca](https://github.com/baptisteArno/typebot.io/commit/e8baaca2a2a44a80a40518e08f0af36c6528ce2a)] + +### Fixed + +- 🐛 (billing) Upgrade again after cancelling [[d132cb1](https://github.com/baptisteArno/typebot.io/commit/d132cb118afee2bcaaf43f31e0fe0b155aff8e80)] +- 🐛 (settings) Fix remember session switch [[36a2fe3](https://github.com/baptisteArno/typebot.io/commit/36a2fe3a70a7373fd08d72ba362bc5249b1078a8)] +- 🚑 (bot) Fix set variable number computation [[7b0bd08](https://github.com/baptisteArno/typebot.io/commit/7b0bd08dc81ac61d6788630a0b18097d0183147e)] +- 🐛 (analytics) Fix multi usage query timeout [[9cb7f8c](https://github.com/baptisteArno/typebot.io/commit/9cb7f8cd96338a8736686cfd1e73a72dcb401164)] +- 💚 Fix auto release actions [[f437ad6](https://github.com/baptisteArno/typebot.io/commit/f437ad6473562025ec2134805709390e000a0f5a)] +- 🐛 (editor) inconsistency in route change auto save [[b46d352](https://github.com/baptisteArno/typebot.io/commit/b46d35214d68fc60719128d5ea50b26d0a1b1e4d)] +- 🐛 (stripe) add back subscription delete webhook handler [[d1cc918](https://github.com/baptisteArno/typebot.io/commit/d1cc9180c893db8d230af9acf52f8a3beaed6e54)] + +### Miscellaneous + +- 📝 Add instruction for AWS S3 endpoint [[d6dffa9](https://github.com/baptisteArno/typebot.io/commit/d6dffa924eb0368c26fb3139856338197aa75281)] +- 📦 Update packages [[ff52a67](https://github.com/baptisteArno/typebot.io/commit/ff52a676f6c31be9a3b80a7b4d7710def5204958)] + + + +## 2.8.1 (2022-10-09) + +### Added + +- ✨ (editor) Add unpublish and close typebot options [[bfed599](https://github.com/baptisteArno/typebot.io/commit/bfed59969599abc5a844540bd981f7dca7435f0e)] + +### Changed + +- 🚸 (bot) Display inputs to the right s… [[aea9021](https://github.com/baptisteArno/typebot.io/commit/aea9021eb881f3f20e31a9680d0dd7cba9b0ee4e)] +- 🚸 (sendEmail) Better result logging [[7ca97d4](https://github.com/baptisteArno/typebot.io/commit/7ca97d4606c26d5b9aae94ad292bfe053002696c)] + +### Fixed + +- 🐛 (bubbles) Fix giphy search input buggy [[88c4076](https://github.com/baptisteArno/typebot.io/commit/88c40766645d93729495618144083b2fe7b6ed36)] + +### Miscellaneous + +- 📦 Upgrade deps [[5289a96](https://github.com/baptisteArno/typebot.io/commit/5289a96940e2bcc74532a08a91b081131bc17616)] +- 📝 Update changelog [[471ffe8](https://github.com/baptisteArno/typebot.io/commit/471ffe8e217f9b0c48c040d7115b46a5269088c1)] + + + +## 2.8.0 (2022-10-02) + +### Added + +- 🔊 (sendEmail) Add log when smtp config is failing [[75ca255](https://github.com/baptisteArno/typebot.io/commit/75ca255af22bed3646ca3de11f03ce49e7866ab3)] +- ✨ (lp) Add new pricing page [[c94a658](https://github.com/baptisteArno/typebot.io/commit/c94a6581be077d5c8403004f688d3213a80d80a5)] +- 👷‍♂️ Transpile components for better DX [[c1dd4d4](https://github.com/baptisteArno/typebot.io/commit/c1dd4d403e17d0ccdcc44d6c0ff0dc8bad7c15be)] +- ✨ Add usage-based new pricing plans [[898367a](https://github.com/baptisteArno/typebot.io/commit/898367a33be70d86b765421462d1c288d0c8cc05)] + +### Changed + +- 🚸 (inputs) Improve date input response bubble formatting [[fac70b9](https://github.com/baptisteArno/typebot.io/commit/fac70b96395f0554168d650c3971ed388f1b8f0e)] +- ♻️ (usage) Remove limit until temporarily [[3bec24a](https://github.com/baptisteArno/typebot.io/commit/3bec24a8cc3c0aa8d68f5ba44d96aea725bd4e77)] + +### Fixed + +- 🐛 (usage) Archive typebot to be able to compute usage [[15dbc95](https://github.com/baptisteArno/typebot.io/commit/15dbc9577d0de7f117aaa151a2b544b8fe66e4b0)] +- 🐛 (workspace) Allow lifetime users to invite members to workspace [[e1f2d49](https://github.com/baptisteArno/typebot.io/commit/e1f2d49342c0141fb258e42b75b257d110277e87)] +- 🐛 Lifetime users should have access to Pro features [[9ed4916](https://github.com/baptisteArno/typebot.io/commit/9ed4916c59370b17c622cd5818831f2e451d1a8f)] +- 💚 (ci) Fix turbo repo prisma cache [[8c56c6c](https://github.com/baptisteArno/typebot.io/commit/8c56c6c32de0c3faa0b01427f5dce996b78e589c)] +- ✏️ (pricing) Fix typos [[9061c03](https://github.com/baptisteArno/typebot.io/commit/9061c03d6d1515b7c5ac12fe70717b1ce809dd05)] +- 🐛 Remove delete result cascade [[3c803b1](https://github.com/baptisteArno/typebot.io/commit/3c803b134504f8a4f379e97792b60fb8a13f2b62)] +- 🐛 (limits) Fix storage limit trigger and e2e tests [[30dff2d](https://github.com/baptisteArno/typebot.io/commit/30dff2d5d7ceee03e1af7cb65b48b8a151bfb217)] +- 🐛 (usage) Fix storage limit check [[1e26703](https://github.com/baptisteArno/typebot.io/commit/1e26703ad416460a49814c163fc2e7a288d9088c)] +- 🐛 (limits) Fix usage limits email emojis [[1063429](https://github.com/baptisteArno/typebot.io/commit/106342927578f4e844d5fc468d0093448d31c893)] +- 🐛 (stripe) Fix plan update and management [[6384a3a](https://github.com/baptisteArno/typebot.io/commit/6384a3adae6b9078fa782dcba7a787c955bdddd0)] +- 🐛 (stripe) Update additional items when they didn't exist [[f83e0ef](https://github.com/baptisteArno/typebot.io/commit/f83e0efea2dc5920715b0436add2766aeafc7be7)] +- 💚 Better build scripts [[d8b1d8a](https://github.com/baptisteArno/typebot.io/commit/d8b1d8ad596079ca4f35a052304cf9effa6e11be)] +- 🐛 (editor) Shouldn't be able to set a group name to empty string [[6a1eaea](https://github.com/baptisteArno/typebot.io/commit/6a1eaea700cf9c21c2568843c04b0f02b428ec11)] + +### Miscellaneous + +- 📦 Upgrade deps to latest version [[a947c1c](https://github.com/baptisteArno/typebot.io/commit/a947c1ce34cd8d7adbe8d63b317f10122a20c295)] +- 🧑‍💻 (emails) Add decent emails management [[1654de3](https://github.com/baptisteArno/typebot.io/commit/1654de3c1f4449161511a3890a5f540bb6034653)] + + + +## 2.7.1 (2022-09-12) + +### Fixed + +- 🐛 (webhook) Don't send body when GET method is used [[4a04d1c](https://github.com/baptisteArno/typebot.io/commit/4a04d1ccbac67526a376ed798704e153cd63a37e)] +- 🐛 (textinput) Don't submit on enter when long input [[4bf47ec](https://github.com/baptisteArno/typebot.io/commit/4bf47ecf90ee103dccfd6f024943cbe7b39a25f9)] +- 🐛 (viewer) load a bot without a start edge [[b64f787](https://github.com/baptisteArno/typebot.io/commit/b64f787cf5d39bd475a7b7b62dcaff5e3405326c)] + +### Miscellaneous + +- 📦 Update packages [[a262fc1](https://github.com/baptisteArno/typebot.io/commit/a262fc190e1829cb0f2b5adc90a59386c157caac)] +- 🛂 (builder) Make sure old typebots can't overwrite newer [[1a7c25e](https://github.com/baptisteArno/typebot.io/commit/1a7c25ef0b4dd6961101661eb5c47bb3b5bdc9cf)] + + + +## 2.7.0 (2022-09-01) + +### Fixed + +- 🐛 (lp) Update plausible tracking url [[42bf93e](https://github.com/baptisteArno/typebot.io/commit/42bf93e72941a6a05554a2425da4d514dc99acbe)] +- 🐛 (lp) Update plausible tracking url [[a8d1e27](https://github.com/baptisteArno/typebot.io/commit/a8d1e27e15fb0aa884fa43346e75b36f5f4fa475)] + +### Miscellaneous + +- 📝 More explicite set variable compute examples [[a161180](https://github.com/baptisteArno/typebot.io/commit/a16118027d2adb0aedd76902cf8d2d83692bb949)] +- 🧑‍💻 (smtp) Use secure prop instead of ignoreTLS [[cf07cfe](https://github.com/baptisteArno/typebot.io/commit/cf07cfe3abadac0bcdbb136896e6f2cfe71fd142)] + + + +## 2.6.2 (2022-08-29) + +### Miscellaneous + +- 📦 Add cz-emoji [[d94879e](https://github.com/baptisteArno/typebot.io/commit/d94879ec3b2d1bc3ac8461f4626e0073c0f62cd6)] +- chore: upgrade packages [[57866c4](https://github.com/baptisteArno/typebot.io/commit/57866c4aa3d210d24cedaecfa81b45c1a2550f7a)] +- fix(webhooks): improve body parsing [[43891b0](https://github.com/baptisteArno/typebot.io/commit/43891b06aaa85ba297cd0d65526f0307cb8e5858)] +- fix(results): crash when variable is object [[02bb7f5](https://github.com/baptisteArno/typebot.io/commit/02bb7f5ea774eb3f71ebb75aad811730be9031cf)] +- build: upgrade packages [[5928142](https://github.com/baptisteArno/typebot.io/commit/59281426b0d5be31a6b85ec5c71bd47d5f06c614)] +- fix(typebotLink): current typebot dropdown [[93161b7](https://github.com/baptisteArno/typebot.io/commit/93161b74b2b53ea997d6328a3e618fc1023c8d11)] +- fix(paymentInput): don't proceed when modal closed [[bd41d7f](https://github.com/baptisteArno/typebot.io/commit/bd41d7fc9be01fb307cf42fcdf6e0835a03729e1)] +- build(results): add log to investigate crash [[1318d27](https://github.com/baptisteArno/typebot.io/commit/1318d27c74dccd4647d7f9e669d196cbd8069100)] + + + +## 2.6.1 (2022-08-18) + +### Miscellaneous + +- build: bump version [[ec7de58](https://github.com/baptisteArno/typebot.io/commit/ec7de582bddd20091d7c696c7ac11453c2ee05dc)] +- fix(engine): reset button type to submit [[741f31a](https://github.com/baptisteArno/typebot.io/commit/741f31a05ec4fd617d4886f9ff9ac05638b57833)] +- fix(bot): pay button not submitting [[f9c16ce](https://github.com/baptisteArno/typebot.io/commit/f9c16ce4c4382a24af04f4f6517c8c11a6af551f)] +- fix(bot): google pay autocomplete [[dc5a38c](https://github.com/baptisteArno/typebot.io/commit/dc5a38cacfc2b77366bb6e9acea14849eb09c5c2)] +- docs: add a custom domain [[6928848](https://github.com/baptisteArno/typebot.io/commit/69288484ed204a320c2767403ff09df5af660536)] +- feat(inputs): improve input focus behavior [[fd01793](https://github.com/baptisteArno/typebot.io/commit/fd0179359495a5999b6c4e2cc893f958b55235e7)] +- ci: avoid triggering npm publish on any tag [[008724a](https://github.com/baptisteArno/typebot.io/commit/008724a3b1235b91a843a3d545912800e41b2053)] + + + +## 2.6.0 (2022-08-13) + +### Miscellaneous + +- build: bump version [[e16ca64](https://github.com/baptisteArno/typebot.io/commit/e16ca6411891fc0ae1e5d22a6445a3da395ae93d)] +- fix(giphy): search [[5333ba9](https://github.com/baptisteArno/typebot.io/commit/5333ba9088fd27e23e19802c35ae1af5aa617810)] +- docs: add members and guests [[6716cf2](https://github.com/baptisteArno/typebot.io/commit/6716cf2484fdc771636c5b183278bef7dcaab68e)] +- fix(results): crash when accessor contains a dot [[361092f](https://github.com/baptisteArno/typebot.io/commit/361092ffa59b330574358439e844b09b70d6cbf0)] +- fix(collaboration): env var typo [[823793a](https://github.com/baptisteArno/typebot.io/commit/823793aab49ab3feb5562d8fd87a8a4e4f36caea)] +- docs: improve set current date wording [[f9ab0e8](https://github.com/baptisteArno/typebot.io/commit/f9ab0e8a762a2778aa569cc41c602276b59525d9)] +- build: add pnpm [[ee338f6](https://github.com/baptisteArno/typebot.io/commit/ee338f62dc0923bf20b62b0a7696cf99d296611d)] +- docs: update vercel cli command (closes [#116](https://github.com/baptisteArno/typebot.io/issues/116)) [[8c3b505](https://github.com/baptisteArno/typebot.io/commit/8c3b5058f1e2c30a8017e01b883e3e3b2a4b5feb)] +- docs: link to current typebot [[0e3ce7e](https://github.com/baptisteArno/typebot.io/commit/0e3ce7e7a704f346f377518874b3700a12a1d094)] +- docs: add builder url in viewer config [[5ff9afc](https://github.com/baptisteArno/typebot.io/commit/5ff9afc2b049dd6828dd8fa3e8468449ad761e93)] +- docs: add extract cookie example [[47d24c4](https://github.com/baptisteArno/typebot.io/commit/47d24c444782aace04e4134158a64f09baa99a20)] +- docs: add lp and docs start instructions [[22eb48b](https://github.com/baptisteArno/typebot.io/commit/22eb48be0b9222152c8836cdd937bf1f135ba54a)] +- feat(results): remove incomplete results limitation [[7d0a526](https://github.com/baptisteArno/typebot.io/commit/7d0a5267362a18a46be0d7de631cc07d8feda561)] +- fix(docs): openssl command [[bd0d995](https://github.com/baptisteArno/typebot.io/commit/bd0d995c2ce5b125dfb797234f79a8d6fe9b754a)] +- fix(bot): mobile keyboard covering input [[f1a01bf](https://github.com/baptisteArno/typebot.io/commit/f1a01bf6632197fa4c992fea64b0429856040c67)] +- fix(db): switch blockId and groupId on old answers [[b62b955](https://github.com/baptisteArno/typebot.io/commit/b62b955c07ac536898a4cb610f5caedff98824e0)] +- fix: viewer general config table [[c2ff1ff](https://github.com/baptisteArno/typebot.io/commit/c2ff1ff68f4cf7d6c26f9a477c544c3d43659450)] +- fix(templates): duplicate resultsPreference conflict [[481f617](https://github.com/baptisteArno/typebot.io/commit/481f61714ed22e8198319bb53b0536b4571ab104)] +- chore: update msw [[6822b77](https://github.com/baptisteArno/typebot.io/commit/6822b778975631bb79b09b12f94b4ba870e045f7)] +- fix: remove json escape for single variable body [[d6aa6e7](https://github.com/baptisteArno/typebot.io/commit/d6aa6e7c752e26933e46edefd71d5f16aa5750c1)] + + + +## 2.5.1 (2022-06-29) + +### Changed + +- 🚸 Add version number in settings modal [[8c86cb8](https://github.com/baptisteArno/typebot.io/commit/8c86cb8684841f25330aa2b77671e57648d46ca2)] +- ♿ Another attempt to disable autofill on text input [[3600783](https://github.com/baptisteArno/typebot.io/commit/3600783439bd432117364a647bd900ffe21bec21)] + +### Fixed + +- 🐛 From name behavior [[f4c81f2](https://github.com/baptisteArno/typebot.io/commit/f4c81f2f0785f91113bb0f737fb5aaf192be16f9)] +- 💚 Remove unused package [[edec5ba](https://github.com/baptisteArno/typebot.io/commit/edec5ba904020742fb61c07c484d9d3c8eafc6a3)] + +### Miscellaneous + +- 📝 Add General settings [[7caac2b](https://github.com/baptisteArno/typebot.io/commit/7caac2bc25b8ede84f9ff6abbc8c07dab1e7a2c4)] +- 📝 Improve docker guides and examples [[d1e94ee](https://github.com/baptisteArno/typebot.io/commit/d1e94ee562f3c724f312659835a2d978972dcf0c)] + + + +## 2.5.0 (2022-06-27) + +### Changed + +- ♿ Add reply-to name on from field [[75604bd](https://github.com/baptisteArno/typebot.io/commit/75604bd3b1b00f4e37c9d891d0b3f8f4c72112cf)] +- ⚡ Optimize graph navigation [[fc4db57](https://github.com/baptisteArno/typebot.io/commit/fc4db575aca858482a4aa100ca81dbf3a83a5bea)] +- ♿ Make multiple avatar possible [[d7b9bda](https://github.com/baptisteArno/typebot.io/commit/d7b9bda5d5efcdba6093194b8f04c2794ef6db27)] +- ⚡ Accept uploaded gif for image bubble [[9222fcb](https://github.com/baptisteArno/typebot.io/commit/9222fcb050ed30312b7a7a622ff5ed02d352983c)] +- ⚡ Add required option on file upload input [[55108c8](https://github.com/baptisteArno/typebot.io/commit/55108c80e88ca3395e41f6e8887988bc7c06ae37)] +- ⚡ Better incoming variable parsing [[554365d](https://github.com/baptisteArno/typebot.io/commit/554365d64596892b37bb679e239d9ec0f16384ac)] +- ⚡ Add attachment in emails [[7c3345a](https://github.com/baptisteArno/typebot.io/commit/7c3345ab13e8529c79e9995cff7d821815096b13)] +- 💄 Overflow issue [[259473a](https://github.com/baptisteArno/typebot.io/commit/259473a781175255af61b3ac6dc3adf78fb4f440)] +- ⚡ Optimize delete all results query [[64a1655](https://github.com/baptisteArno/typebot.io/commit/64a1655f52c75d5b3fa8d15b2b942e4da71e3016)] +- 💄 Attempt to fix overflow issue [[fdf11af](https://github.com/baptisteArno/typebot.io/commit/fdf11af594f9a451d1767529867c562344b07a00)] + +### Fixed + +- 🐛 Avoid autocomplete on text input [[7b71ac9](https://github.com/baptisteArno/typebot.io/commit/7b71ac94980873e7d24a93348fc170f0a6924bb6)] +- 🐛 Remove storage on result delete [[56dca86](https://github.com/baptisteArno/typebot.io/commit/56dca868c9078a4f28df29d160bf3caea1adab3e)] +- 🐛 Missing content [[bd2b906](https://github.com/baptisteArno/typebot.io/commit/bd2b906bd346e4b57aa67d15a2e783db7dddb430)] +- 🐛 File upload in linked typebot [[b9032b4](https://github.com/baptisteArno/typebot.io/commit/b9032b422c6929630293821562b8ab9e0b5d5d32)] +- 🐛 Enable variable parsing on replyTo field [[a4aa293](https://github.com/baptisteArno/typebot.io/commit/a4aa2938b733150a6ae37a5028d8664cbb9fcac1)] +- 💚 Avoid caching prisma gen [[2441abe](https://github.com/baptisteArno/typebot.io/commit/2441abe0158313f2901a7f2df36652fdebcf813c)] +- ✏️ Fix embed instruction URL [[767f463](https://github.com/baptisteArno/typebot.io/commit/767f4632558937d400a2ea70aeb12b9b9c97cdc6)] +- 🐛 Landing page public env [[7df00ef](https://github.com/baptisteArno/typebot.io/commit/7df00efe463786c31595128feba528d52e15d0db)] + +### Miscellaneous + +- 📝 Add TLS explanations for smtp config [[8c93674](https://github.com/baptisteArno/typebot.io/commit/8c936741f3d0b9d4b1f174838a095bc34158cc18)] +- build: Archive results to still be able to check usage [[3a4f263](https://github.com/baptisteArno/typebot.io/commit/3a4f263c71cf391b96527ed9938fe73f9fc737e2)] + + + +## 2.4.0 (2022-06-22) + +### Added + +- ✨ Add a Help button [[5ef89f7](https://github.com/baptisteArno/typebot.io/commit/5ef89f7501950e8210459c0e643932e8830ded90)] +- ✨ Support variables in buttons [[46900ac](https://github.com/baptisteArno/typebot.io/commit/46900ac6df264fa88467a0a38d4e4fb4000c48bf)] + +### Changed + +- ⚡ Add custom file upload size limit [[ea76564](https://github.com/baptisteArno/typebot.io/commit/ea765640cf50b619fe3f49f61ce23a4627450bd9)] +- ⚡ Remove iframe preview in editor [[a9e8b3e](https://github.com/baptisteArno/typebot.io/commit/a9e8b3e2aa70e551f0266b36e5013783cfa9c48b)] +- 💄 Responsive rating input [[49bf178](https://github.com/baptisteArno/typebot.io/commit/49bf178090543365a026ed301b11336e3933afef)] +- ⚡ Upgrade bubble text editor [[7a32690](https://github.com/baptisteArno/typebot.io/commit/7a326905a4b9932c27889efda0fe5b2c7bdcc5d7)] +- ♿ Remove branding automatically [[3e7b34c](https://github.com/baptisteArno/typebot.io/commit/3e7b34c7214d96002463a37c865139cd3d30b336)] +- 💄 Typebot link dropdown [[f676166](https://github.com/baptisteArno/typebot.io/commit/f676166a17a069ea6699d772917c5263324ef6f0)] +- 💄 History dropdown button size [[5672797](https://github.com/baptisteArno/typebot.io/commit/5672797a01c01ade977b5136c689faec353ddbf6)] +- 🚸 Grant team plan for admin on new workspace [[d991dd5](https://github.com/baptisteArno/typebot.io/commit/d991dd5467f64862736c6096597f48bc45e4451b)] +- ♿ Hide create buttons for guests [[4e62175](https://github.com/baptisteArno/typebot.io/commit/4e6217597ca196fe0e802f9fc80782b66e2ac973)] +- 💄 1-line truncated texts [[e4ad23c](https://github.com/baptisteArno/typebot.io/commit/e4ad23c2b9449a3345eeb767b1ba1e713a516c7c)] +- 💄 Remove file input dark mode css [[e86d436](https://github.com/baptisteArno/typebot.io/commit/e86d436e8d84d263462b6ee175d087dd04546efb)] +- 🚸 Make guest bubble selectable [[9b8b27b](https://github.com/baptisteArno/typebot.io/commit/9b8b27bab0b457204a9384825ddcf57ab31c2890)] + +### Fixed + +- 🐛 Runtime public environment [[f801a29](https://github.com/baptisteArno/typebot.io/commit/f801a295393ce845e563f297e0a007d4fcb07b67)] +- 🐛 Runtime public environment" [[3e47b37](https://github.com/baptisteArno/typebot.io/commit/3e47b37c2e59fa39c5917caf0085c3146518b90d)] +- 🐛 Runtime public environment [[e03fe9f](https://github.com/baptisteArno/typebot.io/commit/e03fe9f7d9e4a36e5b0d6e74670eb9c6c4b6657f)] +- 🐛 Translate crash with Slate [[6938533](https://github.com/baptisteArno/typebot.io/commit/6938533126993794c090ea5421e885013e6d39f3)] +- 🐛 Properly escape backslash and quotes [[20dbfe6](https://github.com/baptisteArno/typebot.io/commit/20dbfe64c9f9eb9e15ce934339e7753d486899c2)] +- 🐛 Make sure delete all works [[18c5ea5](https://github.com/baptisteArno/typebot.io/commit/18c5ea52073df9625379c922a3a7f042e08010a9)] +- 🐛 Avoid chat to start multiple times [[48a4976](https://github.com/baptisteArno/typebot.io/commit/48a49761672b65a0b7d14aeee5b1208077a37061)] +- 🐛 Display file URL in CSV export [[6f4267e](https://github.com/baptisteArno/typebot.io/commit/6f4267e7e27f079c55a4e67a825ce964896be5a6)] +- 🚑 Stripe form isn't showing [[0dd607b](https://github.com/baptisteArno/typebot.io/commit/0dd607bcdfd5763a9fb8b0acccc8e40fdbf95630)] +- 🚑 Empty body emails [[0ffdd88](https://github.com/baptisteArno/typebot.io/commit/0ffdd88dbaff5a4eb77866d5d1f727763310808c)] +- ✏️ About page typo [[2a6e065](https://github.com/baptisteArno/typebot.io/commit/2a6e0652f24c32e1f1024496db978996ac01c2d5)] + +### Security + +- 🔒 Improve delete security checks [[9352587](https://github.com/baptisteArno/typebot.io/commit/93525872980f7d1a05a714f8ed855ff2dbed681e)] + +### Miscellaneous + +- ci: 👷 Simplify build on Vercel [[3392e04](https://github.com/baptisteArno/typebot.io/commit/3392e04d38c2c86af52622bb24a4930d6d3e6c18)] +- Merge branch 'main' of https://github.com/baptisteArno/typebot.io [[1931a5c](https://github.com/baptisteArno/typebot.io/commit/1931a5c9c015dcd25115ee25eaed744ede672a6c)] +- 🛂 Hide folders for guests [[85601fc](https://github.com/baptisteArno/typebot.io/commit/85601fc1def252eda0543cbe71490a8d713f795e)] +- 📝 Add doc for every block [[283509e](https://github.com/baptisteArno/typebot.io/commit/283509ed59140efe50d13d6cd1ef996aaa81cd00)] +- 🔨 Run Playwright tests on pull request [[8358de1](https://github.com/baptisteArno/typebot.io/commit/8358de1dabbf9a14ad14cf3bf2696d4f183416c8)] + + + +## 2.3.0 (2022-06-13) + +### Added + +- ✨ Add file upload input [[75365a0](https://github.com/baptisteArno/typebot.io/commit/75365a0d822fd6e18f0ec6d12287bb03598ea0b0)] +- ✨ Custom email body and HTML content [[97980f4](https://github.com/baptisteArno/typebot.io/commit/97980f42ca255e2e7d690a2c1a39c9732bda1fc1)] +- ✨ Add Rating input [[b1aecf8](https://github.com/baptisteArno/typebot.io/commit/b1aecf843b28e0c06cf7c43f59cc5ebd661da416)] + +### Changed + +- 🔧 Add ignoreTLS option for SMTP creds [[3105ade](https://github.com/baptisteArno/typebot.io/commit/3105adedb39c05f207f7193bcfdccc841506c870)] +- ⚡ Improve first paint delay [[aeaaa5c](https://github.com/baptisteArno/typebot.io/commit/aeaaa5c39814fccfdcdcd35e4c601ef2643826f1)] +- ♻️ Rename step to block [[2df8338](https://github.com/baptisteArno/typebot.io/commit/2df833850504fa2bb8653494a0e3abb120abde1f)] +- 🚸 Attempt to remove Chrome auto complete [[8751766](https://github.com/baptisteArno/typebot.io/commit/8751766d0e2a1e8ee399c4d64e2e333700e73f30)] + +### Fixed + +- 🚑 Add a variable update queue to avoid initial crash [[87a9e7e](https://github.com/baptisteArno/typebot.io/commit/87a9e7e337569da3c16efc17c7ac62ddc1e03270)] +- 💚 Attempt to fix cached prisma models [[4fd5d45](https://github.com/baptisteArno/typebot.io/commit/4fd5d452a378b0ff7c937ae9670356352728f4fc)] +- ✏️ Remove quotes from email config [[0a45a31](https://github.com/baptisteArno/typebot.io/commit/0a45a31007013cf914ae3dd6feddab151aaac4ed)] + +### Security + +- 🔒 Add verification on backend for file input deployment [[14afd22](https://github.com/baptisteArno/typebot.io/commit/14afd2249e9615a0e4a616df81d95032416bd8fa)] + +### Miscellaneous + +- ci: 👷 Auto create tags [[5c54bb7](https://github.com/baptisteArno/typebot.io/commit/5c54bb7755f4ecad319910d7cd1aa87ef5d89b79)] +- 📝 Indicate where var dropdown is available [[177789c](https://github.com/baptisteArno/typebot.io/commit/177789c1a693c1c4ac8ae0c5f6467c25c38a52c2)] +- 🧑‍💻 Keep host avatar when group starts with input [[910b871](https://github.com/baptisteArno/typebot.io/commit/910b87155659c6592f20643ac7609cba0fb2c6f5)] +- 🛂 Restrict file upload input [[353923e](https://github.com/baptisteArno/typebot.io/commit/353923e029426ae748476b2a6462aa043fda2fb1)] +- 📝 Improve hidden variables doc [[d4c52d4](https://github.com/baptisteArno/typebot.io/commit/d4c52d47b31ce3c70067e6fc3938f728757b2b9f)] +- 📝 Update email doc [[6657a85](https://github.com/baptisteArno/typebot.io/commit/6657a85573b00b44b61acbd85b41296da680a8ee)] +- 📝 Update video in README for mobile [[1b569da](https://github.com/baptisteArno/typebot.io/commit/1b569dae99a2d4f138530b058b58006fea81922b)] + + + +## 2.2.9 (2022-07-07) + +### Added + +- ✨ Brand new Results table [[d84f990](https://github.com/baptisteArno/typebot.io/commit/d84f99074ddc02794e7c90fa121a573adc619763)] +- 📈 Inject user id for Sentry [[cf6e8a2](https://github.com/baptisteArno/typebot.io/commit/cf6e8a21be3ac714f136cecfbb6744618dc0a457)] + +### Changed + +- 💄 Change to refreshed logo [[b0d1b11](https://github.com/baptisteArno/typebot.io/commit/b0d1b113259c4e820f0b5e45d3b2d45df5776513)] +- ♿ Indicate why GSheets couldn't find any sheet [[6b32c17](https://github.com/baptisteArno/typebot.io/commit/6b32c171febfe03ab6437563497c667991df39bf)] +- ⚡ Increase upload expiry time [[066147f](https://github.com/baptisteArno/typebot.io/commit/066147f81d87ffe005b4df62bf1aa44877243489)] +- 🚸 Arrow & Enter commands for dropdowns [[bc803fc](https://github.com/baptisteArno/typebot.io/commit/bc803fc5520d0217c00008e2f659fc91f2d6419c)] + +### Fixed + +- 💚 Upgrade to Node 16 for npm publish workflow [[50ab2a9](https://github.com/baptisteArno/typebot.io/commit/50ab2a9b9caea54151293d8503ff268203a4723b)] +- 🐛 Open iframe on proactive message click [[2e4d9d5](https://github.com/baptisteArno/typebot.io/commit/2e4d9d5a1daaafe5792398aa0fee1784aa937060)] +- 🐛 webhookSteps returns blocks instead of step [[d35bfeb](https://github.com/baptisteArno/typebot.io/commit/d35bfeb3239c92805a679fa7de525b39620ea362)] +- 🐛 Files upload progress bar not sequential [[b0010aa](https://github.com/baptisteArno/typebot.io/commit/b0010aae3293f5901f6f01fd4a0d103f603d8024)] +- 🐛 Ignore cell content for column size [[994ae61](https://github.com/baptisteArno/typebot.io/commit/994ae61719dc1bdd14f7ab7083af6e8e3ce5d83b)] +- 🐛 Accept file upload without fileType [[38a3ee7](https://github.com/baptisteArno/typebot.io/commit/38a3ee7010d65619f8d86d44813d3837c2b8557a)] +- 🚑 Forgot the migration script [[407cace](https://github.com/baptisteArno/typebot.io/commit/407cace752402eaed3227b20ef9dfb4628ec167d)] +- 🐛 Reply to name parsing [[a9a0aec](https://github.com/baptisteArno/typebot.io/commit/a9a0aec375df8ef024af45250397e2ddd1b7bb4e)] +- 🐛 Back action trigger on finger swipe [[db9a314](https://github.com/baptisteArno/typebot.io/commit/db9a314b9f5eee989771570593d586f8d85ddbc3)] +- 🐛 Attempt to fix collaboration invitation email [[6e5f507](https://github.com/baptisteArno/typebot.io/commit/6e5f5071716312b63517b029de4b353b7074ad75)] +- 💚 Remove latest tag action [[6c1d9d4](https://github.com/baptisteArno/typebot.io/commit/6c1d9d419b852bdab9f7ad0eed10f44068152110)] + +### Security + +- 🔒 Check token id before updating creds [[9cddc75](https://github.com/baptisteArno/typebot.io/commit/9cddc755a3087631605c91a8efce35b4ad74e916)] + +### Miscellaneous + +- improve Dockerfile size and safety [[9839f5c](https://github.com/baptisteArno/typebot.io/commit/9839f5c1325deeb06162ee7a553b6cf34e769bcd)] +- 📝 Add workspace doc [[0dd99e0](https://github.com/baptisteArno/typebot.io/commit/0dd99e0802a822ba74c8672c1047a5d5edc40e19)] +- 📝 Add Troubleshoot sections [[f1f5299](https://github.com/baptisteArno/typebot.io/commit/f1f529949d400751c092f00e032891dd13cbbccb)] +- 📝 Add Metadata section in Settings [[5fa8dbf](https://github.com/baptisteArno/typebot.io/commit/5fa8dbfb7e13eb35c1219ecb0c877a54032f6019)] +- 📝 Add context menu doc [[2e2b1c1](https://github.com/baptisteArno/typebot.io/commit/2e2b1c1b6b9a3a81daff77493e8ec08782f0c087)] +- 📝 Precise what browsers blocks the popups [[273d476](https://github.com/baptisteArno/typebot.io/commit/273d4767f110a39f8b72ccf1c3b4965d39a3f2d6)] +- 📝 Add dynamic avatar guide [[cc71157](https://github.com/baptisteArno/typebot.io/commit/cc71157e0fcb3832dd3226e4ada42e89a632bde7)] + + + +## 2.2.1 (2022-06-07) + +### Changed + +- 🎨 Build types from validation schemas [[e79ff09](https://github.com/baptisteArno/typebot.io/commit/e79ff09b0f0bdfc50a85784c51ee699743647351)] +- 🗃️ Remove duplicate fields in PublicTypebot [[ad32ae0](https://github.com/baptisteArno/typebot.io/commit/ad32ae02ef4493af34c4e777a7305ffba24cbb7d)] + +### Fixed + +- 🐛 Add public env var in runtime config [[a42e1ca](https://github.com/baptisteArno/typebot.io/commit/a42e1cad22621a9f4a8e0beff693bc58bb7531e3)] +- ✏️ Docker upgrade guide typo [[c67fa7d](https://github.com/baptisteArno/typebot.io/commit/c67fa7d9c1dcdf6c03cdde9a28dd3a12e046bdec)] +- 🐛 Google sheets callback crash when no code [[8ec117a](https://github.com/baptisteArno/typebot.io/commit/8ec117aee4cd50145c1133f8375320bad31f0c4d)] +- ✏️ Email integration youtube ID [[b403d9b](https://github.com/baptisteArno/typebot.io/commit/b403d9b346ba37f0d7f790506cc6cf4defd9aaa6)] +- ✏️ Docker upgrade instructions [[8eefd96](https://github.com/baptisteArno/typebot.io/commit/8eefd96d2fc5ba10912008a033413ee5cb25b882)] + +### Miscellaneous + +- 📝 Update wordpress personalization [[3010976](https://github.com/baptisteArno/typebot.io/commit/301097623ba841312ef66c23d514105f276a2a29)] +- remove unnecessary comment [[853b749](https://github.com/baptisteArno/typebot.io/commit/853b749e2c577aa1c0f25f9833930d1463752752)] +- update docs [[237c388](https://github.com/baptisteArno/typebot.io/commit/237c388e31bdb774d9997c3029bf8a1f5e64d4cd)] +- add azure-ad login option [[ee370b5](https://github.com/baptisteArno/typebot.io/commit/ee370b5f26b2a7e1f58031b29d563fd9f80e11c4)] + + + +## 2.2.0 (2022-06-03) + +### Added + +- ✨ Revokable API tokens [[a0929c4](https://github.com/baptisteArno/typebot.io/commit/a0929c492b260e5e03c4ee0e41dacc120ca066fa)] +- ✨ Start preview from any block [[89d91f9](https://github.com/baptisteArno/typebot.io/commit/89d91f9114c0ce16cedd34ef8a2348c2c734571b)] +- ✨ Add Digital Product Payment template [[89d17a9](https://github.com/baptisteArno/typebot.io/commit/89d17a9ed3f02b6cf33e8382cb9a7135e7549d33)] + +### Changed + +- ♻️ Toast component [[12f2e40](https://github.com/baptisteArno/typebot.io/commit/12f2e401523c4bac8cace617c767540d43a5701b)] +- 🚸 Greater than / Less than [[43fb8a7](https://github.com/baptisteArno/typebot.io/commit/43fb8a7be078426a81903a1bd5849691f4743919)] +- 🚸 Improve plan upgrade flow [[87fe479](https://github.com/baptisteArno/typebot.io/commit/87fe47923eda1bea44001d1b2efe7f69521d4723)] +- 💄 Scroll when payment form appears [[caa6015](https://github.com/baptisteArno/typebot.io/commit/caa6015359614266b5d777218946488565d49882)] +- ⚡ Redirect on current window when embedded [[4f208a2](https://github.com/baptisteArno/typebot.io/commit/4f208a2d0546f0e21101288cfc7651542f54cbf9)] +- ⚡ Better payment accessibility [[c1461f0](https://github.com/baptisteArno/typebot.io/commit/c1461f075882b0fcdca4c6f33b6d295d83ccab5d)] +- ⚡ Accept variables as webhook data path [[26cf38f](https://github.com/baptisteArno/typebot.io/commit/26cf38fb2181de71fdc07663f70128088ae8bee0)] + +### Fixed + +- 🐛 Payment for zero-decimal currencies [[274f30c](https://github.com/baptisteArno/typebot.io/commit/274f30c6c23575ad435ebdb70d3d863861c0a5e9)] +- ✏️ Upgrade modal [[b176c4d](https://github.com/baptisteArno/typebot.io/commit/b176c4dd03498dc4ab3978c167755669a4c1d3a8)] +- 🐛 Redirect new tab backward [[9f58260](https://github.com/baptisteArno/typebot.io/commit/9f582606a792f34d8e75dc547d632c01ca459e05)] +- 🐛 Subscription cancel webhook [[3592321](https://github.com/baptisteArno/typebot.io/commit/35923215b9ace10dfc196689a08a214f8214eef8)] +- ✏️ Remove credentialsId in product payment [[05de48b](https://github.com/baptisteArno/typebot.io/commit/05de48b6a7bcfb5c1d9414ea534c0295aa56662f)] +- 🐛 Empty receipt email [[7aa6dab](https://github.com/baptisteArno/typebot.io/commit/7aa6dab78a80baf7ceb131d74c2d05c74c807ed3)] +- ✏️ Collab invite link [[c6bd3ea](https://github.com/baptisteArno/typebot.io/commit/c6bd3ea634e9bbed086bf89177a86c7521cd6d06)] +- 🐛 Payment receipt email parsing [[797ff18](https://github.com/baptisteArno/typebot.io/commit/797ff1892d43c383a07970436d92eea51b1868f5)] +- 🐛 Variable value reset [[a9f730b](https://github.com/baptisteArno/typebot.io/commit/a9f730b7019330f11dd5b64cc465c9f803508d05)] + +### Miscellaneous + +- 📝 Import / Export flow [[e5d7f1d](https://github.com/baptisteArno/typebot.io/commit/e5d7f1d1ce52e2a242ff894b22af50ff486a6cec)] +- 🧑‍💻 Input default autocompletes [[f42dd48](https://github.com/baptisteArno/typebot.io/commit/f42dd485334966e3aa41d76d1c422fdb2de983cb)] +- 📝 Add instructions for custom docker images [[97eb036](https://github.com/baptisteArno/typebot.io/commit/97eb0361c8d17a9433b7b6a910be5929d7076c73)] +- ci: 👷 Remove docsearch scrapper [[b65d153](https://github.com/baptisteArno/typebot.io/commit/b65d153bf0cf5edef071a1a840699127e5f62242)] +- 📝 Explain how to pass parent URL [[61e4ca1](https://github.com/baptisteArno/typebot.io/commit/61e4ca13132ca72294620c7df18a2644367a8908)] +- build(docker): 👷 Build images on push [[5e19f79](https://github.com/baptisteArno/typebot.io/commit/5e19f796cc3199488b3839f2386f471b486b220a)] + + + +## 2.1.2 (2022-05-30) + +### Fixed + +- 🐛 Number var [[d6b5568](https://github.com/baptisteArno/typebot.io/commit/d6b5568e033473beffec86df05e15c5bca26bda6)] +- 🐛 Multi-line var parsing for webhook [[d02f267](https://github.com/baptisteArno/typebot.io/commit/d02f2675883a7b636fa1a66922b64f85f781e5f5)] +- 🐛 Don't parse "004" as number 4 [[e72934d](https://github.com/baptisteArno/typebot.io/commit/e72934d29af114dfc66d55776833d359a5ebe7af)] +- 🐛 Custom currency payment input [[2cb8330](https://github.com/baptisteArno/typebot.io/commit/2cb83307903e92d67bdf72d1df46dac3d2bcbf2f)] + +### Miscellaneous + +- 🛂 Disable new user signups [[ff5c368](https://github.com/baptisteArno/typebot.io/commit/ff5c3683fcac487301b31ab6b855694c6f9d59d5)] +- Update compose file [[2bdc1ce](https://github.com/baptisteArno/typebot.io/commit/2bdc1ce05635078b58cd8772c016e5e1a1dd3126)] +- 🧱 Improve runtime environment [[a04a11a](https://github.com/baptisteArno/typebot.io/commit/a04a11ae0272170e1f83f4c367b529afaff52efc)] +- 📦 Compatible with iPhone 6 [[92cd56e](https://github.com/baptisteArno/typebot.io/commit/92cd56e5d0e16de5a6b2a234c8a1293cdd68dadf)] +- 📝 Fix FROM email quotes [[30d36b9](https://github.com/baptisteArno/typebot.io/commit/30d36b9a09647e3a259442f7c3342b690f3a0913)] + + + +## 2.1.1 (2022-05-25) + +### Added + +- ✨ Payment input [[3a6ca3d](https://github.com/baptisteArno/typebot.io/commit/3a6ca3dbde916647f5ac7eaba28f5a3b8072f030)] +- 🔊 Better log when can't find a typebot [[0f06aae](https://github.com/baptisteArno/typebot.io/commit/0f06aae80cd12ad350c80d959992ba010fadd958)] + +### Changed + +- 💄 New URL image preview [[faffcc6](https://github.com/baptisteArno/typebot.io/commit/faffcc69a7ceda588ca2e095ca15bf15fd59c9a7)] +- 💄 Proactive message margin [[350719c](https://github.com/baptisteArno/typebot.io/commit/350719c7935604aef4ee5b353422203043921d8b)] +- 💄 Proactive message close icon [[ac278b9](https://github.com/baptisteArno/typebot.io/commit/ac278b9916c7af9daf3bef0daa4d4a97d04b7f50)] +- 💄 Hide avatar if not last block [[0de0d12](https://github.com/baptisteArno/typebot.io/commit/0de0d128b39716d9ababb468bbefc448fa04575c)] +- 💄 Add button ping if unique first [[d9e273b](https://github.com/baptisteArno/typebot.io/commit/d9e273b008376985992d4d32993c6aa13335738b)] +- ⚡ Delete workspace button [[b7b0344](https://github.com/baptisteArno/typebot.io/commit/b7b034432a03e579d42a47f8497a2891ce708e5b)] +- 💄 Variable button tiny dropdown [[0f38141](https://github.com/baptisteArno/typebot.io/commit/0f38141eb156196635aabad287cad30f99e9fdca)] +- 🎨 Code format [[98c1dea](https://github.com/baptisteArno/typebot.io/commit/98c1dea92aba60e449a5a205af2ed91b9f899811)] + +### Removed + +- 🔥 Remove ownerIds [[bda4116](https://github.com/baptisteArno/typebot.io/commit/bda4116fbc26840badf0b723727d58e12da06b54)] + +### Fixed + +- 💚 Missing dependency [[4a5a92b](https://github.com/baptisteArno/typebot.io/commit/4a5a92b973ba2a5b74292ce7d67d01a27fb98051)] +- 🐛 Quit flow if redirecting [[91ea637](https://github.com/baptisteArno/typebot.io/commit/91ea637a0827c77b971e5a26e406f80b22af3728)] +- 🐛 Build syntax error [[71c9c74](https://github.com/baptisteArno/typebot.io/commit/71c9c743d4b501925a916e2abb0dca867285c849)] +- 🐛 Forwarded host check attempt [[c168b67](https://github.com/baptisteArno/typebot.io/commit/c168b678dd397a6c96afaca533a708145b099c67)] +- 🐛 Forwarded host checking" [[a2dd26b](https://github.com/baptisteArno/typebot.io/commit/a2dd26b60f7e28c141f9df7066c9045bbcdc7571)] +- 🐛 Forwarded host checking [[37dea9c](https://github.com/baptisteArno/typebot.io/commit/37dea9c4030f06f8e73ba6ebc773a17ca9a6f911)] +- 🐛 Score addition [[1bb8952](https://github.com/baptisteArno/typebot.io/commit/1bb89527d544c648d846eacf5602ba40b94a4574)] +- 🐛 Ignoring port number when checking matching URL [[62162c6](https://github.com/baptisteArno/typebot.io/commit/62162c6c2a1a17e08a660dad4faed55e7815a95f)] +- 🐛 Standard embed when window is loaded [[ad69cc5](https://github.com/baptisteArno/typebot.io/commit/ad69cc5264b36b9d1a625e0c6a0901bf97aacf6e)] +- 🐛 Code block should never crash bot [[0beb2e6](https://github.com/baptisteArno/typebot.io/commit/0beb2e6619961737786374671b16881079741179)] +- 🐛 Standard embed [[c9b3b04](https://github.com/baptisteArno/typebot.io/commit/c9b3b047dcfb312a8d744bc475a7e57a3b972a41)] + +### Security + +- 🔒 add gitlab pagination [[b39e892](https://github.com/baptisteArno/typebot.io/commit/b39e89202055a0cc7b9bbe36ac724267684a31f2)] + +### Miscellaneous + +- build: 👷 New compose file and entrypoints [[5d786f5](https://github.com/baptisteArno/typebot.io/commit/5d786f59cc6802945908040be86662690903807e)] +- ci: 👷 Build and publish docker images on new version [[e7ae611](https://github.com/baptisteArno/typebot.io/commit/e7ae6118114a9d3145a536422ff55cb763d12b4a)] +- 📝 Improve popup delay builder [[62b77e4](https://github.com/baptisteArno/typebot.io/commit/62b77e49059ba3155e7eb81df5df60a9c5803204)] +- 📝 Callbacks URL typo [[447e87d](https://github.com/baptisteArno/typebot.io/commit/447e87de66774c123b7abde168789da343498c7e)] +- 📝 Edit single button color [[c57ed07](https://github.com/baptisteArno/typebot.io/commit/c57ed0777c33225c0ecc5e20cbf81b59077fcd49)] +- 📝 Improve hero wording and add Plausible [[f07db7f](https://github.com/baptisteArno/typebot.io/commit/f07db7f68adddf0eccaf2c4d7a41d6b265f57501)] +- Fixed CNAME domain [[47a7aa1](https://github.com/baptisteArno/typebot.io/commit/47a7aa165d8dbb9cc0d499a7b048f365e6a55605)] +- ⚗️ Await for result update [[391aead](https://github.com/baptisteArno/typebot.io/commit/391aeaddf12590db0ce7a40dce5a31d31285b971)] +- 📝 initContainer typo [[24b077c](https://github.com/baptisteArno/typebot.io/commit/24b077c0e2d06700a94443acc2adc8954beb03ab)] +- fix(auth): add gitlab to hasNoAuthProvider check [[a178124](https://github.com/baptisteArno/typebot.io/commit/a178124ee988be9982f26ef25fbbc40d88dc877d)] +- 📝 Rename URL examples in config [[730de56](https://github.com/baptisteArno/typebot.io/commit/730de56374313deffb291393f9d0b9791c10eef9)] +- 📝 Add Code block [[fbcd46d](https://github.com/baptisteArno/typebot.io/commit/fbcd46dd9ca0a4ed7598988b82d9b3cd872c4dc3)] +- Update README.md [[137c493](https://github.com/baptisteArno/typebot.io/commit/137c4937d0401d0059aa8e0cedf02ef95e43a2c6)] +- 📝 Add new preview [[bfd20cb](https://github.com/baptisteArno/typebot.io/commit/bfd20cbf63c7d625576750add1ebe14aa8eaa038)] +- 📝 Add demo in README [[71d96c9](https://github.com/baptisteArno/typebot.io/commit/71d96c98eac9f10722de84e14c51bb3596213271)] +- 🔨 Add migration recover script [[d0119ee](https://github.com/baptisteArno/typebot.io/commit/d0119ee24b27f8f6626a219fdd16d594103f82f2)] +- 📝 Improve Set variable [[55224c9](https://github.com/baptisteArno/typebot.io/commit/55224c9095de2041f71cdfcf33238f523f87f04e)] + + + +## 2.1.0 (2022-05-17) + +### Added + +- ✨ Team workspaces [[f0fdf08](https://github.com/baptisteArno/typebot.io/commit/f0fdf08b00f740c4804b49f45dcd8338e29e10fa)] + +### Changed + +- ⚡ Can disable query params auto hide [[4272186](https://github.com/baptisteArno/typebot.io/commit/42721865c5dade0dc40272f997e8f86c37701678)] +- 💄 Attempt to fix font loading [[46037c0](https://github.com/baptisteArno/typebot.io/commit/46037c039e92b31f233bcde38aa8aac91ba0325a)] + +### Fixed + +- 💚 Deployment [[210bad3](https://github.com/baptisteArno/typebot.io/commit/210bad32f905e0556cc56757d3327ed6c91b8851)] +- 🐛 Pass tests [[731e646](https://github.com/baptisteArno/typebot.io/commit/731e64637723b6758ebe82510bafcc6af48d7d80)] +- 🐛 Refresh prevent [[4d9796c](https://github.com/baptisteArno/typebot.io/commit/4d9796c55911c1c3bb6187b8c8e5f4c86279ba7c)] +- 🐛 Disable font optimization temporarly [[508c166](https://github.com/baptisteArno/typebot.io/commit/508c1660b45bdf149e2a6db5591074a928a57a90)] + +### Miscellaneous + +- 👷 Remove maintenance page [[cd24482](https://github.com/baptisteArno/typebot.io/commit/cd24482038788da75178f9a2e7f21b9e3bb820b6)] +- Merge pull request [#36](https://github.com/baptisteArno/typebot.io/issues/36) from baptisteArno/feat/workspaces [[0e3ee9b](https://github.com/baptisteArno/typebot.io/commit/0e3ee9bee30200c999da8ead691c2a6be8276254)] + + + +## 2.0.0 (2022-05-13) + +### Added + +- ✅ Fix e2e tests [[e268638](https://github.com/baptisteArno/typebot.io/commit/e268638786310cd0ade6967825ea3dd212a5f78f)] +- 🔊 Log incoming data to investigate inconsistency [[9213dd3](https://github.com/baptisteArno/typebot.io/commit/9213dd33feb1656ed4716f1138df1b27e48ad9dc)] +- ✨ Custom head code [[2dc0e45](https://github.com/baptisteArno/typebot.io/commit/2dc0e45a65f00221dd5c43ee992ff1293cc24789)] +- ✨ Add Pabbly block [[348055d](https://github.com/baptisteArno/typebot.io/commit/348055d68ad3f74998598e3bf3b24bcd4ab2bff0)] +- ✨ Add Make.com block [[38c53fb](https://github.com/baptisteArno/typebot.io/commit/38c53fbbbce328d56763ee1fa8f092ec64e7b593)] +- ✨ Zoom in/out [[c5d3b92](https://github.com/baptisteArno/typebot.io/commit/c5d3b9214da850919eabea5124bde7a254991ddf)] +- ✨ Improve color picker [[15868f9](https://github.com/baptisteArno/typebot.io/commit/15868f99fcbac25939792bc989f596f74a77fa06)] +- ✨ New create typebot menu [[660b220](https://github.com/baptisteArno/typebot.io/commit/660b220f8d91d83e050045f4f09d59a965652fd0)] +- ✨ Custom icon on typebot [[525887a](https://github.com/baptisteArno/typebot.io/commit/525887a32ca781f36b91a08fa271b83713e74938)] +- ✨ Improve variables in executed codes [[db10f1e](https://github.com/baptisteArno/typebot.io/commit/db10f1ee89f17f85ff0deba3c365e8673f501a24)] +- ✨ Add first name for support bubble [[47403e3](https://github.com/baptisteArno/typebot.io/commit/47403e32b3fcc765393660fae82469f9a87a0adf)] +- ✨ Add customer support [[2ded3cd](https://github.com/baptisteArno/typebot.io/commit/2ded3cd9c7498c677647073605109e46c6291fdf)] +- ✨ Add Embed bubble [[953b95d](https://github.com/baptisteArno/typebot.io/commit/953b95d25409484f2b975fa166c015ffdd44d395)] +- ✨ Duplicate blocks & steps [[c01ffa3](https://github.com/baptisteArno/typebot.io/commit/c01ffa3f0b2b093d6f27d80f95a45492fd6bb554)] +- ✨ Add new onboarding flow [[f4e6f63](https://github.com/baptisteArno/typebot.io/commit/f4e6f63b266bcfea7cc3abaced1ca304b0a48644)] +- ✨ Duplicate webhooks on typebot duplication [[b2bf6f0](https://github.com/baptisteArno/typebot.io/commit/b2bf6f09f616d1d16487f21183f5444b48f227a6)] +- ✨ Add auto open delay for bubble embed [[d6b9413](https://github.com/baptisteArno/typebot.io/commit/d6b94130cb72fb633c513e9bf7d73ce30d0ba29d)] +- ✨ Link typebot step [[7e61ab1](https://github.com/baptisteArno/typebot.io/commit/7e61ab19eb151e24b110e5a9e768324b0aa8fce4)] +- ✨ Add create result on page refresh option [[260819f](https://github.com/baptisteArno/typebot.io/commit/260819f124f314bf6df3553a5d2bfb73bb74a397)] +- ✨ Code step [[e3e07dd](https://github.com/baptisteArno/typebot.io/commit/e3e07ddd4dbae6e7b893a0d6be9f12b80d1a6c9c)] +- ✨ Edge menu on click [[3c67837](https://github.com/baptisteArno/typebot.io/commit/3c6783727e5d28322d282f5358030bf161103550)] +- ✨ Can edit answers by clicking on it [[f124914](https://github.com/baptisteArno/typebot.io/commit/f12491419d1b984e0f125d33970aa9267e07dddf)] +- ✨ Add logs in results [[ebf92b5](https://github.com/baptisteArno/typebot.io/commit/ebf92b5536c498e7bf95371eb044796b3786e811)] +- ✨ Restore published version button [[e17a1a0](https://github.com/baptisteArno/typebot.io/commit/e17a1a0869e7f87c55a32d4df316499567003914)] +- ✨ Add collaboration [[b9dafa6](https://github.com/baptisteArno/typebot.io/commit/b9dafa611e073e142fac7409c8098c20e3cef55b)] +- ✨ Add default country code phone [[6d455a3](https://github.com/baptisteArno/typebot.io/commit/6d455a3861d5160219c6a7a08a47828e7ddebf50)] +- ✨ Add Zapier step [[642a427](https://github.com/baptisteArno/typebot.io/commit/642a42779b81608c13b7032954a3779462558142)] +- ✨ Add {{state}} to body to get form state [[d0994e6](https://github.com/baptisteArno/typebot.io/commit/d0994e6577a442d651ea784c45e598f5c224af3d)] +- ✨ Add get sample result endpoint [[fd822a3](https://github.com/baptisteArno/typebot.io/commit/fd822a35a773cf71b25c0f7dce707b5335f8effa)] +- ✨ Add list results endpoint [[9dfcb30](https://github.com/baptisteArno/typebot.io/commit/9dfcb3036509ba7bb45a3cd6adb56817c5c59cbe)] +- ✨ Add email to `me` endpoint [[5edd63c](https://github.com/baptisteArno/typebot.io/commit/5edd63c5f6a33e8a3b1e13828a27697f403d3637)] +- ✨ Add routes for subscribing webhook [[68ae69f](https://github.com/baptisteArno/typebot.io/commit/68ae69f36641eccf75b4a4e983131fe289ade9f4)] +- ✨ Add cc & bcc + Deletable credentials [[b89e9b1](https://github.com/baptisteArno/typebot.io/commit/b89e9b1b8242aafc775dca367f9c25f194b9587e)] +- ✨ Add custom domains [[f3ecb94](https://github.com/baptisteArno/typebot.io/commit/f3ecb948a1cc863b93b499bed8f87a5d1d483962)] +- ✨ Add variables in URL support [[6e0ab67](https://github.com/baptisteArno/typebot.io/commit/6e0ab675020f216aed55b8dd677898de2fd4b1e0)] +- ✨ Custom avatars [[d2ac13b](https://github.com/baptisteArno/typebot.io/commit/d2ac13ba5f9089eabaa84a060b50a6a519e4b38f)] +- ✨ Allow webhook with basic auth [[93e8f90](https://github.com/baptisteArno/typebot.io/commit/93e8f90ac33699c477c05cdf236ec6ec30823595)] +- 📈 Add Plausible Analytics [[bdfd7ac](https://github.com/baptisteArno/typebot.io/commit/bdfd7ac1bc22aecad5d1a7cc5da2cc9d6a0e6baf)] +- ✨ Add support bubble [[f897102](https://github.com/baptisteArno/typebot.io/commit/f8971022197d3654dc54b19fedb1d1d46ba2fb01)] +- ✨ Add coupon code input [[b345131](https://github.com/baptisteArno/typebot.io/commit/b345131b0b352e6f8abb96f52a796da3a55f4c83)] +- ✨ Add link support in text bubbles [[0338aca](https://github.com/baptisteArno/typebot.io/commit/0338acae82120666d6448fcbeb956a89df0031f6)] +- ✨ Add retry bubbles [[8c8d77e](https://github.com/baptisteArno/typebot.io/commit/8c8d77e052013819c30d38d35ca1b4935a16132f)] +- ✨ Add send email integration [[d6238b3](https://github.com/baptisteArno/typebot.io/commit/d6238b3474e9dda8c5d8db514c72dbfbefa2354d)] +- ✨ Add lead generation template [[1f320c5](https://github.com/baptisteArno/typebot.io/commit/1f320c5d99c52995f3edac8af75ee7da462c767c)] +- ✨ Add unlock/lock sidebar [[1c5bd06](https://github.com/baptisteArno/typebot.io/commit/1c5bd06657bdd1453155965cf715af46c6e5e86c)] +- ✨ Add custom css settings [[21448bc](https://github.com/baptisteArno/typebot.io/commit/21448bcc8a56578e2ca5b12d6bb7672771709586)] +- ✨ Add chat theme settings [[b0abe5b](https://github.com/baptisteArno/typebot.io/commit/b0abe5b8fa5f88b912dd3d1821ce986c88f1d278)] +- ✅ Add general theme settings tests [[619d10a](https://github.com/baptisteArno/typebot.io/commit/619d10ae4e161c27a970d2cb453af9af13984f32)] +- ✨ Add auto save [[079cf5e](https://github.com/baptisteArno/typebot.io/commit/079cf5ec57fe09c4ae2e80061b6287162dad2991)] +- ✨ Add webhooks [[a58600a](https://github.com/baptisteArno/typebot.io/commit/a58600a38a9be025d956dd3dbda9d0020a70b630)] +- ✨ Add video bubble [[df2474e](https://github.com/baptisteArno/typebot.io/commit/df2474ef43c1ea4159dfe2ee2083748cfc5e91b3)] +- ✨ Add image bubble [[2d17897](https://github.com/baptisteArno/typebot.io/commit/2d178978ef79c78a6c10a07d72886ffdefb2536a)] +- ✨ Add Redirect step [[c43fd1d](https://github.com/baptisteArno/typebot.io/commit/c43fd1d386a8321b8461a0c468ee3dd081e48a97)] +- ✨ Add Google Analytics integration [[3506d86](https://github.com/baptisteArno/typebot.io/commit/3506d86d50a8994aa8b67a6808d9ce89f594c196)] +- ✨ Add Google Sheets integration [[f49b514](https://github.com/baptisteArno/typebot.io/commit/f49b5143cf6f6e06626929d46e2b05dde3317a77)] +- ✨ Add Condition step [[2814a35](https://github.com/baptisteArno/typebot.io/commit/2814a352b2f8db4b915a202d795c2750d231e650)] +- ✨ Add Set variable step [[4ccb7bc](https://github.com/baptisteArno/typebot.io/commit/4ccb7bca49aa10b6ebca09eba0274346814dfa04)] +- ✅ Add Button targets e2e tests [[13f72f5](https://github.com/baptisteArno/typebot.io/commit/13f72f5ff7dab08671542c5a644c0d77dc908c9d)] +- ✨ Add Export flow menu button [[659f50e](https://github.com/baptisteArno/typebot.io/commit/659f50eb06a01f0277836ac51b5b0ad1c42e20ef)] +- ✨ Add buttons input [[c02c61c](https://github.com/baptisteArno/typebot.io/commit/c02c61cd8ba2b62a31f3330ddfd6b4813be81b4d)] +- ✨ Add Phone number input [[b20bcb1](https://github.com/baptisteArno/typebot.io/commit/b20bcb14083619868c3ba971c41d60a92ca553ef)] +- ✨ Add Date input [[8cba7ff](https://github.com/baptisteArno/typebot.io/commit/8cba7ff37bc18fb41ef71c021fd741df39faf586)] +- ✨ Add URL input [[ce1b23a](https://github.com/baptisteArno/typebot.io/commit/ce1b23a0e7874548f75ee729fb12aed99cf132a3)] +- ✨ Add email input [[47162cb](https://github.com/baptisteArno/typebot.io/commit/47162cb28afb58e83458cd344ba18c27f6ad9787)] +- ✨ Add number input [[d54ebc0](https://github.com/baptisteArno/typebot.io/commit/d54ebc0cbe62fc253b513cbbccb7d03ca173516e)] +- ✅ Add e2e tests [[2a04030](https://github.com/baptisteArno/typebot.io/commit/2a040308db7b4ea357da04e74834105e6346dabc)] +- ✨ Add text options [[f712c7a](https://github.com/baptisteArno/typebot.io/commit/f712c7ad98d04536965f95bc3d254bb9bc1cffb3)] + +### Changed + +- ⚡ Image picker and dynamic preview [[a89f4ec](https://github.com/baptisteArno/typebot.io/commit/a89f4ec5b60c674f49e94c7168e1f814d8914187)] +- ♿ Trap block title focus [[46f5d5d](https://github.com/baptisteArno/typebot.io/commit/46f5d5df9138974cf0727ec9c6706f574899caf6)] +- ⚡ Rename variable button [[2b56f83](https://github.com/baptisteArno/typebot.io/commit/2b56f83d4366861c81e8d47e86481fd7b437c96a)] +- 💄 Support bubble icon [[1becdad](https://github.com/baptisteArno/typebot.io/commit/1becdad79e6198d00e9810c23a47b62975481677)] +- 🎨 Formatting [[fe26e89](https://github.com/baptisteArno/typebot.io/commit/fe26e8990286e6cea1ad5d4bb2af4a323e3523a0)] +- 💄 Better chat widget icon [[a2cfecc](https://github.com/baptisteArno/typebot.io/commit/a2cfecc16c7f13b47820034a7c2ddd65a6b5463e)] +- 💄 Better long text input [[e339cc1](https://github.com/baptisteArno/typebot.io/commit/e339cc16725984ec0597a4e0cd33318e4556fbd2)] +- ⚡ Pass host URL params [[7b4dc47](https://github.com/baptisteArno/typebot.io/commit/7b4dc47f118b9f59fb25b43869464ed77e5b27a2)] +- 🚨 Not a number warning [[1d82940](https://github.com/baptisteArno/typebot.io/commit/1d82940ed7a6ca2d0875bdcab271b2d034f48a47)] +- ⚡ Better URL validation [[20c402a](https://github.com/baptisteArno/typebot.io/commit/20c402ad1b4043753cfe6c22c57ce10c14fe85a6)] +- ⚡ Show linked typebots results in webhook sample [[12f43cd](https://github.com/baptisteArno/typebot.io/commit/12f43cdb8877c719e81a6b932a0dba71ffae17ba)] +- ⏪ Remove credentials name check [[937621e](https://github.com/baptisteArno/typebot.io/commit/937621ee07df3adf56eff93b8d2ba2cbbf6f4580)] +- 💄 Clear param on page load [[93811a3](https://github.com/baptisteArno/typebot.io/commit/93811a3c48ca43da8d3befbf9e4222d105a06f61)] +- ⚡ Attempt to make redirections more reliable [[a089a45](https://github.com/baptisteArno/typebot.io/commit/a089a451b627bcd33c31294591421c4b101eb66f)] +- ⚡ Improve logs details [[54a757b](https://github.com/baptisteArno/typebot.io/commit/54a757b21b78a224e2503ba70f262c79a7709fa6)] +- ⚡ Make linked bot edge id work [[e50ce64](https://github.com/baptisteArno/typebot.io/commit/e50ce645eb226406b30532b229fcfae56a8bdc96)] +- 💄 Scrollbar on embed [[1a59ce2](https://github.com/baptisteArno/typebot.io/commit/1a59ce20d2ee85ba01fd7ecf8984d671a41ba77c)] +- 🚸 Auto move board when dragging an edge [[b6ba40e](https://github.com/baptisteArno/typebot.io/commit/b6ba40e0095bbdda1b4e689f9921ef31a515931d)] +- ♿ Show Google Sheets detail [[4a2c662](https://github.com/baptisteArno/typebot.io/commit/4a2c6627c35ad372d5573a6733f3829cebe2aa65)] +- 💄 Add margins on bubbles [[611dbad](https://github.com/baptisteArno/typebot.io/commit/611dbad7cdaef8b331ce2e3f6e9f09545f2c7cbc)] +- 💄 Preview drawer zIndex [[f7e779b](https://github.com/baptisteArno/typebot.io/commit/f7e779b0663884bee766ed1c81d0b3f0b2a5c094)] +- 💄 Remove my avatar from quiz [[46a1145](https://github.com/baptisteArno/typebot.io/commit/46a114578ce13c8391ea2bd43c1099da970ade63)] +- 🎨 Improve typebot import [[b38b114](https://github.com/baptisteArno/typebot.io/commit/b38b114f12966d14fd2cf6af6e98f1f70e380f70)] +- 🚸 Pointer events none on video embed [[378fe0f](https://github.com/baptisteArno/typebot.io/commit/378fe0fe82628db3130c2736d7951acf5440da3e)] +- 💄 Center folder title [[1653b53](https://github.com/baptisteArno/typebot.io/commit/1653b539034510fd2f33a51d4af4c1ce2a5837a4)] +- 🚸 Scrollwheel zoom too much [[59ce711](https://github.com/baptisteArno/typebot.io/commit/59ce711303587b3c5b373b2db4945f1ca7b95c3b)] +- 💄 Improve onboarding [[b6d4001](https://github.com/baptisteArno/typebot.io/commit/b6d40016cdad6ff4b65e963d9eee71aa22bc1df5)] +- ♿ Improve graph navigation setting [[4502e68](https://github.com/baptisteArno/typebot.io/commit/4502e68065c5daf19285c3909f0c62935f1bad81)] +- ♿ Lowercase resiliency on "contains" operator [[519723b](https://github.com/baptisteArno/typebot.io/commit/519723b2d895bea93abcc5ec005f6ce81d617c7d)] +- ♿ Add more getting started videos [[eb4feb6](https://github.com/baptisteArno/typebot.io/commit/eb4feb61bdbebf4632cba403b8a539147f41132e)] +- ♿ Getting started editor modal [[786908e](https://github.com/baptisteArno/typebot.io/commit/786908e9cfbf1b1f3673ff14de58312e0ff29dcd)] +- ♻️ Simplify header [[1fdf7e7](https://github.com/baptisteArno/typebot.io/commit/1fdf7e734b41df8befca1589750277c7eb119962)] +- ♿ Create new item when hitting enter [[6867143](https://github.com/baptisteArno/typebot.io/commit/68671433bc0cafc5894429fa4cd65dc019579ed0)] +- ♿ Improve previewing blocks [[327da31](https://github.com/baptisteArno/typebot.io/commit/327da3104dfb5bb957ad6ff731c934e3529fd3e4)] +- 💄 Change default block title [[82f7bf0](https://github.com/baptisteArno/typebot.io/commit/82f7bf0ed67fe0ebd0ee68d142231640f9b3f70b)] +- 💄 UI bump [[7f5d2f4](https://github.com/baptisteArno/typebot.io/commit/7f5d2f4173a61d52a64f5adfc81a812d0170b6db)] +- ⚡ Enforce lite badge even when removed [[3552279](https://github.com/baptisteArno/typebot.io/commit/355227939606169f1415bad157d095991cedc438)] +- 💄 Better code editor dynamic height [[d43623b](https://github.com/baptisteArno/typebot.io/commit/d43623bf592812b732fe7a7a8c74a9fb69ab2290)] +- ♿ Add data-block-name prop [[023a6f2](https://github.com/baptisteArno/typebot.io/commit/023a6f274a8b8e07e33fe3cec864e923b48e11ec)] +- ♿ Improve block focus [[261cd9a](https://github.com/baptisteArno/typebot.io/commit/261cd9a5c7d239e3317d2ffbde29ff218b2ff25c)] +- ♿ Improve format feedback [[90e837e](https://github.com/baptisteArno/typebot.io/commit/90e837e7c2eccac387dcd29b50bbfdfcfc070aa4)] +- ⚡ Await for async code block [[d756dff](https://github.com/baptisteArno/typebot.io/commit/d756dff99ef1c6d3a9ded1934d9d11e3023ec83b)] +- ♿ Add 'Current' to Link typebot [[fb60dcf](https://github.com/baptisteArno/typebot.io/commit/fb60dcf5ff4486953b0d652c6463179ac3cc5ff6)] +- 🚸 More predictable edge management [[c507ef5](https://github.com/baptisteArno/typebot.io/commit/c507ef55ae4b1cc30efb4ebb9e6fae3b3aba8bf8)] +- ♿ Force viewer sub domain [[f9aba27](https://github.com/baptisteArno/typebot.io/commit/f9aba27aae1e6968cadde40d774433e13fbbdc49)] +- ⏪ Make sure old viewer URL still works [[b16c47a](https://github.com/baptisteArno/typebot.io/commit/b16c47adb9ce024f75ca316e1937d596f657555c)] +- ♿ Improve inputs responsivity [[03aadab](https://github.com/baptisteArno/typebot.io/commit/03aadab4094c0460c85c3c2c29f192e7faf5b04e)] +- 🚸 Add Reply-To field for email sending [[ddb6798](https://github.com/baptisteArno/typebot.io/commit/ddb6798eba8b29e421674ca0b1e1c5cb7b51bf8e)] +- 🗃️ Add custom domain primary key [[a533552](https://github.com/baptisteArno/typebot.io/commit/a533552b40f2475a673c5603809cefa447beb77b)] +- ♻️ Migrate from short-uuid to cuid lib [[1423c14](https://github.com/baptisteArno/typebot.io/commit/1423c145472f86af6fb78a5e9496da46119fb416)] +- 💄 Remove v2 annoucements [[64bafd1](https://github.com/baptisteArno/typebot.io/commit/64bafd15a1af6a925efd142dc9b31872e7ad3599)] +- 💄 New README illustration [[d8fe530](https://github.com/baptisteArno/typebot.io/commit/d8fe53012dc0a4b1e35aaa33f4e5f46a79daf004)] +- 💄 Small visual fixes [[52b7733](https://github.com/baptisteArno/typebot.io/commit/52b773379e880083be3b32438d290d6ce330b82c)] +- 💄 Add interactive indications [[d0ece4c](https://github.com/baptisteArno/typebot.io/commit/d0ece4cc8fc1320ca91e8540c86e227157af1221)] +- 💄 Change buttons primary color [[76a8bcf](https://github.com/baptisteArno/typebot.io/commit/76a8bcfbaec4d19cc3335d4862dd9586b1daccff)] +- 💄 Add animation on scroll [[37b7ca3](https://github.com/baptisteArno/typebot.io/commit/37b7ca32e99953e6aa61c8277ba7932e878d8d84)] +- 💄 Refont LP for v2 [[21e926a](https://github.com/baptisteArno/typebot.io/commit/21e926a477b55bea0d7cda17fcddfadba7d12afc)] +- 💄 Better README illustration [[aeb0643](https://github.com/baptisteArno/typebot.io/commit/aeb06433af677fefc583cd873ef4c12102414e61)] +- 🎨 Deploy v2.1.0 [[8f07df8](https://github.com/baptisteArno/typebot.io/commit/8f07df8a05366f5e95ffb73fa687528cdc7945d3)] +- 🎨 Update instructions for 2.2.0 [[69701d1](https://github.com/baptisteArno/typebot.io/commit/69701d12b90eecbc4bc66b065ab81f8e01aaded6)] +- 🎨 Ask for URL instead of publishId [[5a2df9f](https://github.com/baptisteArno/typebot.io/commit/5a2df9fe727273462a7c428988cfe5a22b0c3832)] +- 🏗️ Add docker image and deployment features [[e886d1b](https://github.com/baptisteArno/typebot.io/commit/e886d1b0794f310741b69d982b1cb0a6742f7fc4)] +- ♻️ Migrate to dequal [[5c524a0](https://github.com/baptisteArno/typebot.io/commit/5c524a0432513c4e30eb2760cd25b7dc82661d30)] +- 🏗️ Import typebot-js source [[d134a26](https://github.com/baptisteArno/typebot.io/commit/d134a265cd8a7b667c78dc3f66d3e5d9a5054d7e)] +- 🚸 Improve equality check [[5228cff](https://github.com/baptisteArno/typebot.io/commit/5228cff4686f9c52e20004dbdee556f38bb181d9)] +- 🚸 Improve input variable behaviour (for loops) [[9123977](https://github.com/baptisteArno/typebot.io/commit/91239779f79431ac76dc886ae08a838ab502e2ec)] +- 🚸 Improve and unify inputs [[2c1f694](https://github.com/baptisteArno/typebot.io/commit/2c1f69439bbfa23ea3c93efaa71d6d7732d06f86)] +- ♿ Improve feedback redirect [[1bcc8ae](https://github.com/baptisteArno/typebot.io/commit/1bcc8aee10556fae44b39587f4ab9171d4b1a8c4)] +- ♿ Add sleekplan paths [[7b66494](https://github.com/baptisteArno/typebot.io/commit/7b6649408c37455551c63562cff016647fca3a5b)] +- ♿ Add SSO signin for Sleekplan [[57663fd](https://github.com/baptisteArno/typebot.io/commit/57663fd05c5ffe84afc117f41d1429902ee77674)] +- 🚸 Return empty string if evaluated JS is not defined [[0710403](https://github.com/baptisteArno/typebot.io/commit/07104038c4332162920cc39b0e1a6eb25db8c12b)] +- 🚸 Easy webhook config [[fd9c19a](https://github.com/baptisteArno/typebot.io/commit/fd9c19a4c29061ee9b0bb1464b54d51c3da7d5e6)] +- ♿ Improve feedback on GSheets errors [[d13ca0f](https://github.com/baptisteArno/typebot.io/commit/d13ca0fa9ac8bc2d7605f1adcf68fd15c7b7c964)] +- 💄 Don't show avatar when only input [[9b8f153](https://github.com/baptisteArno/typebot.io/commit/9b8f153579cac287a0132144dcbe88fd233151fb)] +- ♿ Disable edge delete [[31f86d8](https://github.com/baptisteArno/typebot.io/commit/31f86d8ef454f1044d5512d88988399020afd32b)] +- ⚡ Better save management [[507fe4f](https://github.com/baptisteArno/typebot.io/commit/507fe4fa06476ce06d7f8500fa7280e4f6c74eb1)] +- 🚸 Always evaluate Set variable [[a5a1fef](https://github.com/baptisteArno/typebot.io/commit/a5a1fef597576339643736742109e28726ff052a)] +- 🏗️ Add minio in local config [[7045c02](https://github.com/baptisteArno/typebot.io/commit/7045c02a15168ddf3a4a89f8fe3cac6765accae3)] +- ⚡ Smooth panning even with complexe flow [[e9a9dc0](https://github.com/baptisteArno/typebot.io/commit/e9a9dc00e2ac1ea0a3a8b8071b5c9b5b3b526a27)] +- ♿ Add modal that asks for checking Google checkboxes [[5a06bb0](https://github.com/baptisteArno/typebot.io/commit/5a06bb0500434a8d59612ef6451b5581b95a0034)] +- ♿ Display "Log not found" [[8029775](https://github.com/baptisteArno/typebot.io/commit/8029775660c3db2dd48fa410f6b87e2bf3adb8c5)] +- ♿ Better Gsheets dropdowns [[205c347](https://github.com/baptisteArno/typebot.io/commit/205c3477205ef6731d98121b6db34fa55eca76a8)] +- ♿ Better item sample parsing [[dc51010](https://github.com/baptisteArno/typebot.io/commit/dc510100e509db21e2f000ddc220d6d076f2b735)] +- ♿ Hide steps sidebar scrollbar [[0df719d](https://github.com/baptisteArno/typebot.io/commit/0df719d5315fedecd5e783aeb5765aa53c5dc9aa)] +- ♿ Typebot header back to folder if exists [[cb51e6b](https://github.com/baptisteArno/typebot.io/commit/cb51e6bd200a8c6d0553592e7c4ed87530c1d7a7)] +- ♿ Smarter website input [[c5b378d](https://github.com/baptisteArno/typebot.io/commit/c5b378dfad0288705a24f080ed87e63d3b75f6ab)] +- 💄 Add user avatar in support bubble [[b0d7be4](https://github.com/baptisteArno/typebot.io/commit/b0d7be4471686448a4eeb555c166b32817d40a95)] +- ♿ Overflow clip [[74b3464](https://github.com/baptisteArno/typebot.io/commit/74b34644745114d5ef26d24726e9d09d929563b4)] +- ♿ Better autoSave handler [[8171edb](https://github.com/baptisteArno/typebot.io/commit/8171edb290f17dae42925b07390d277208504a58)] +- 💄 Item node overflow when long word [[2a6a474](https://github.com/baptisteArno/typebot.io/commit/2a6a47409213615a6c7ed493c0d3ef22f19a652c)] +- 🏗️ Add script package [[eb23ad6](https://github.com/baptisteArno/typebot.io/commit/eb23ad61a7bf87e49ea4609fe06c8edf985ee9d6)] +- 🏗️ Add wordpress plugin [[27bff8c](https://github.com/baptisteArno/typebot.io/commit/27bff8c4b775ba770ec453024ca1c71a8ba0f4de)] +- 🚚 Add /typebot-lib/v2 endpoint [[64990fc](https://github.com/baptisteArno/typebot.io/commit/64990fc6074f055b0d1f26fb3918c562502d9907)] +- ♻️ Remove any trace of Cypress [[658202e](https://github.com/baptisteArno/typebot.io/commit/658202eaee425e44a1233ef52ec848ac1a84aa1d)] +- 🗃️ Add createdAt and updatedAt [[a499d85](https://github.com/baptisteArno/typebot.io/commit/a499d85c9804c575863bcd757d0c6ae9dccbb68b)] +- 🗃️ Add api token [[5a80774](https://github.com/baptisteArno/typebot.io/commit/5a80774ff5467812b995be2b28c38cf3f06d24be)] +- 💄 Change social logins buttons [[c5972ec](https://github.com/baptisteArno/typebot.io/commit/c5972ec91b30aec55027eb8dbd4b358ff88397d9)] +- 🔧 Ignore Resize exceeded error in Sentry [[3313bda](https://github.com/baptisteArno/typebot.io/commit/3313bdaa8a0a4931ed87002f651d0a6daa5899b7)] +- 💄 Make steps side bar scrollable [[f7d6f0b](https://github.com/baptisteArno/typebot.io/commit/f7d6f0b766e9b503e718062323b043a35ffa33cf)] +- 💄 Social login colored logos [[00c3588](https://github.com/baptisteArno/typebot.io/commit/00c35886a4473fea7868fd92c720f2f08e2d91ae)] +- ♿ Improve code editor readiness [[daaa8a0](https://github.com/baptisteArno/typebot.io/commit/daaa8a0a2d344d5850c38f936f4450e308ca62e1)] +- 🏗️ Add sentry to viewer [[b339add](https://github.com/baptisteArno/typebot.io/commit/b339add83866f13074c4dd1f2b0d1c4144c7ce9b)] +- ♿ Save both bots when updating name or publicId [[2eee226](https://github.com/baptisteArno/typebot.io/commit/2eee226a88ffa8e7fc5adf7af8cfb53bda651015)] +- ⚡ Improve graph transition perf [[714f7c8](https://github.com/baptisteArno/typebot.io/commit/714f7c8ce505f4bae901e55e5ae81dadfecbd373)] +- ⚡ Add docs and connect Stripe [[56bd5fa](https://github.com/baptisteArno/typebot.io/commit/56bd5fafc38f1a50053d43e9b7bc5ffd5a26a6bb)] +- 🏗️ Remove frame security headers on LP [[aeb3e4c](https://github.com/baptisteArno/typebot.io/commit/aeb3e4caa7f74675472901da3ce4c30e78f471a8)] +- 🏗️ include sentry.properties [[e2606eb](https://github.com/baptisteArno/typebot.io/commit/e2606ebf1193c5de23439ecb3cbd49604be38bca)] +- 🏗️ Add Sentry to builder [[8501d39](https://github.com/baptisteArno/typebot.io/commit/8501d39234bf312a3dc0fe99cbaa68f795d9c549)] +- ♻️ Better S3 env var format [[9c20ef0](https://github.com/baptisteArno/typebot.io/commit/9c20ef00b931e194526a8194474c8de24f96aa1d)] +- ⚡ Add msw and mock authentication [[b1f54b7](https://github.com/baptisteArno/typebot.io/commit/b1f54b77c687f03d95830e044d559cfab396154c)] +- ♻️ Revert tables to arrays [[524ef08](https://github.com/baptisteArno/typebot.io/commit/524ef0812c60a23e3e63a9f2db587a06cb392714)] +- ♻️ Undo / Redo buttons + structure refacto [[8a350ee](https://github.com/baptisteArno/typebot.io/commit/8a350eee6c93abec6bce40351a0b4ef0b854defe)] +- ⚡ Migrate to Playwright [[73f277f](https://github.com/baptisteArno/typebot.io/commit/73f277fce7078f70e89702f2aa30daa8b3a7a218)] +- ♻️ Add defaults everywhere (+ settings page)): [[c5aaa32](https://github.com/baptisteArno/typebot.io/commit/c5aaa323d1d5a4d684d51f071284663a864de713)] +- ♻️ Add Edges table in Typebot [[8bbd897](https://github.com/baptisteArno/typebot.io/commit/8bbd8977b2697e616ca38e4880397af85e7440a0)] +- 💄 Face lift [[44b4785](https://github.com/baptisteArno/typebot.io/commit/44b478550f73171caa899d27c732e6ca22afb0f3)] +- ⏪ Remove migration files and push until db is stable [[77b553a](https://github.com/baptisteArno/typebot.io/commit/77b553acf5b1ba1d121620a9f8ad140cc611f9d5)] +- ♻️ Normalize data [[9fa4c7d](https://github.com/baptisteArno/typebot.io/commit/9fa4c7dffa4b7ef6fa67a5205400fd6781664e21)] +- 🔧 Optimize bot-engine [[90d7a73](https://github.com/baptisteArno/typebot.io/commit/90d7a7343ef556ac585049d9082f5247a8156cbb)] + +### Removed + +- 🔥 Remove save button [[1b900b3](https://github.com/baptisteArno/typebot.io/commit/1b900b3f5d8f4f31bec99ea69080645955f09a75)] + +### Fixed + +- 🐛 Webhook duplication [[7507a1a](https://github.com/baptisteArno/typebot.io/commit/7507a1ab1e1ff9d0c7d9633e49068e7809e65e2e)] +- 🐛 Airtable real-time [[936dde2](https://github.com/baptisteArno/typebot.io/commit/936dde2195708eb19bcf4d6e02f3eb6299c16c11)] +- 🐛 Throttle incoming typebot to avoid overwrite bug [[6af47f0](https://github.com/baptisteArno/typebot.io/commit/6af47f0277b52f22bfa1ccbf24314b1ff3c6fbbc)] +- 🐛 Algolia contextual search [[22e4873](https://github.com/baptisteArno/typebot.io/commit/22e4873c115ea61cd1bd3b642cbaadfd7d3008e0)] +- 🐛 Misc [[092f16d](https://github.com/baptisteArno/typebot.io/commit/092f16d3c1df469f31fb451055734dbb64dd2269)] +- 🐛 Remove missing creds GFont error [[c4cf793](https://github.com/baptisteArno/typebot.io/commit/c4cf793b5da487eef7348103f8a0c6de1355ed7e)] +- 🐛 Bubble not displaying with proactive message [[ad3a140](https://github.com/baptisteArno/typebot.io/commit/ad3a140982ee890e206b6f7bc6b44fe0b42cc03f)] +- 🐛 Make custom domain fetching more predictable [[8fdfda6](https://github.com/baptisteArno/typebot.io/commit/8fdfda64829d301c6cf8e8ba8c001f38071cc37a)] +- 🐛 Delete domain when Vercel doesn't have it [[28710dd](https://github.com/baptisteArno/typebot.io/commit/28710dddc72f09731d8eddfa1c38aff62d5ee123)] +- 🐛 Embed bubble variable [[4d98de2](https://github.com/baptisteArno/typebot.io/commit/4d98de2c7014e3c9d8e22b1050ccd0cd36753ebe)] +- 🐛 add missing account attributes [[b28fb06](https://github.com/baptisteArno/typebot.io/commit/b28fb063293ed4e698daf8a15b72b094cb9519f8)] +- 🐛 Avoid variables duplication [[b175974](https://github.com/baptisteArno/typebot.io/commit/b1759749e47536e926fa74e6d2eee5b7ee829989)] +- 🐛 Nested typebots webhhok exec [[9fbe1cc](https://github.com/baptisteArno/typebot.io/commit/9fbe1cc34c94fae08b813ba6b46e5af70a3aa5a7)] +- 🐛 webhookId in non webhook step [[240cbee](https://github.com/baptisteArno/typebot.io/commit/240cbeed626c2cac9e6df6f7cd59caa6e580e0d1)] +- 🐛 Exporting many results [[281fddc](https://github.com/baptisteArno/typebot.io/commit/281fddc8efa39f3ca8a29583689ef264c7cc41dc)] +- 🐛 Export all for free users [[df3e926](https://github.com/baptisteArno/typebot.io/commit/df3e92685e698ba7816ff2b4726e3506379b2421)] +- 💚 Database default URL [[a49d1ca](https://github.com/baptisteArno/typebot.io/commit/a49d1cac0368fbe774042aeaad6c87f445de3c89)] +- 🐛 Fix multiple cc bcc email [[7b8169c](https://github.com/baptisteArno/typebot.io/commit/7b8169c9ae9defda56396087522ec934d6412f57)] +- 🐛 Typebot import with items [[cd879ee](https://github.com/baptisteArno/typebot.io/commit/cd879eee5fafdfb2f3790b1cb75dae5abca8fef3)] +- 🐛 Linked typebot webhook [[8981a57](https://github.com/baptisteArno/typebot.io/commit/8981a572ed3b713e407a0c2a3314b10d4dd91d1d)] +- 🐛 Result creation fail [[82446c4](https://github.com/baptisteArno/typebot.io/commit/82446c41af903e450469084267647b5837a26cee)] +- 🐛 Graph navigation [[0c23f2d](https://github.com/baptisteArno/typebot.io/commit/0c23f2dbcdc774d2745554b994b0e009ac67dc9b)] +- 🐛 Graceful fail if typebot not found [[fffcb06](https://github.com/baptisteArno/typebot.io/commit/fffcb060ac6f4d3166965d51c982bd466071e884)] +- 🐛 Template modal scroll [[e941ce1](https://github.com/baptisteArno/typebot.io/commit/e941ce1e13bdcb5c980a35a9340600fb8524070b)] +- 🐛 Fix item list delete [[c5ffd8c](https://github.com/baptisteArno/typebot.io/commit/c5ffd8cb7444768da4eea727ab87c62eafb67d1e)] +- 🐛 Safari context menu trap [[144ffae](https://github.com/baptisteArno/typebot.io/commit/144ffaeb031603dc8bd6ddfb70146e870fedf686)] +- 🐛 Delete collaborator [[c5919a7](https://github.com/baptisteArno/typebot.io/commit/c5919a766f9f991c4c9349051fc39155af23eff6)] +- 🐛 undefined when copying custom domain [[6e90ad1](https://github.com/baptisteArno/typebot.io/commit/6e90ad1b70bfaa80f8d7861d68dcbbc5bb88bdb0)] +- 🐛 jump to login for no reason [[25961d3](https://github.com/baptisteArno/typebot.io/commit/25961d32fcc629bd1e9920d5d926b0d8d0a73645)] +- 🐛 Fix variables parsing [[e9c3ec1](https://github.com/baptisteArno/typebot.io/commit/e9c3ec1e4658c1f9f9dbe1433dd433c8b4360ed4)] +- 🐛 Docker build 'qs' missing [[366f93f](https://github.com/baptisteArno/typebot.io/commit/366f93fd50c0c345170d925f000a9b1f22a05fff)] +- 🚑 Preview panel not showing [[8f36516](https://github.com/baptisteArno/typebot.io/commit/8f36516e4b9acc749051243948f7fd56529a3c5d)] +- 🐛 UpgradeModal ending with a dot [[1fb4328](https://github.com/baptisteArno/typebot.io/commit/1fb4328938de58abfbab5fa39484135b586ad5c3)] +- 🐛 Wrap webhook evalution in try catch [[eb5a5d9](https://github.com/baptisteArno/typebot.io/commit/eb5a5d9a15731f911516df52f49788578f236e5a)] +- 🐛 Command typo [[ceedb05](https://github.com/baptisteArno/typebot.io/commit/ceedb05b64b21b5f6358c705a835974036b5c500)] +- 🐛 Overflow issue on Safari [[56f1d5f](https://github.com/baptisteArno/typebot.io/commit/56f1d5fbbf636a0ae4c8a75a3d47b18fee9df7ab)] +- 💚 Improve linked typebot test robustness [[f6b5189](https://github.com/baptisteArno/typebot.io/commit/f6b518989c8eabd444c295942161074c5ac690fb)] +- 🐛 Current id bug when linking to current bot [[da95cbd](https://github.com/baptisteArno/typebot.io/commit/da95cbd355a5fb0d0cd08fb67ade6d5377f025e5)] +- 🐛 FIx rewrite pages [[0822703](https://github.com/baptisteArno/typebot.io/commit/082270370b5b3d546c76677f4e004567a4871619)] +- 🐛 Auto open chat bubble [[a4d4576](https://github.com/baptisteArno/typebot.io/commit/a4d4576e48b2cc7ba3539be421220b19f79854d2)] +- 🚑 Webhook return func [[3585e63](https://github.com/baptisteArno/typebot.io/commit/3585e63c48b67f7447720281dd94819a6cacae99)] +- 🚑 Webhook in viewer [[22a36e6](https://github.com/baptisteArno/typebot.io/commit/22a36e6de7aab896fec1aadd3b75e50b0d4ac311)] +- 🐛 Webhook call on linked typebot [[86117d6](https://github.com/baptisteArno/typebot.io/commit/86117d6d3c9852551c529826c46999a5a24f8c80)] +- 🐛 misc [[c7d5373](https://github.com/baptisteArno/typebot.io/commit/c7d53731273b259656cdcd675171217f8cf8f989)] +- 🐛 useLogs returns nothing [[2461dd8](https://github.com/baptisteArno/typebot.io/commit/2461dd89be4b517d4584042e7a03c7ee1644efc4)] +- 🐛 Attempt to fix prerender error [[21311a6](https://github.com/baptisteArno/typebot.io/commit/21311a6eca511bd8d435ff8d600bc974a6afbc4d)] +- 🐛 Attempt to fix auto zoom on Android [[8d6330f](https://github.com/baptisteArno/typebot.io/commit/8d6330f6fd0a6fedc2d0263801f22c20007f0461)] +- 🐛 Phone input overflow on mobile [[236c63d](https://github.com/baptisteArno/typebot.io/commit/236c63d7db31fa9792b09025ef94c9b6522c1f5a)] +- 🐛 Fix the whole docker deployment pipeline [[1f992c6](https://github.com/baptisteArno/typebot.io/commit/1f992c6779258f51023d9aac6d4a744d06aa58e8)] +- 🐛 Fix edge on item offset top on drop [[c64afb7](https://github.com/baptisteArno/typebot.io/commit/c64afb7073267b1c2853aada92d7c9b4cd43586a)] +- 🚑 DB migration [[43fa411](https://github.com/baptisteArno/typebot.io/commit/43fa411320ab711b9f4057eb9eef93387585e8f5)] +- 🐛 Save variables from webhooks in results [[60dcd5c](https://github.com/baptisteArno/typebot.io/commit/60dcd5c246337203c523f23d0b41a284b9ec6eeb)] +- 🐛 Undo with item change [[cd6c5c0](https://github.com/baptisteArno/typebot.io/commit/cd6c5c04c5436f893d9291e10190bdc249ca7da8)] +- 🐛 Step undefined items duplicate [[f869ca3](https://github.com/baptisteArno/typebot.io/commit/f869ca377a2e002eaa4bbdf2c8e1bcae9c6c9501)] +- 🐛 When URL is empty [[84dda32](https://github.com/baptisteArno/typebot.io/commit/84dda32b13be7404d637266dc74d4059c8f38d59)] +- 🐛 Make sure to build typebot-js on prepare [[194a5fb](https://github.com/baptisteArno/typebot.io/commit/194a5fbae161665f5632a94307aa8d0b3b2138b9)] +- 🐛 docker build [[f22fbc9](https://github.com/baptisteArno/typebot.io/commit/f22fbc9ade26560e4da8070525b4962be9d7c328)] +- 🐛 Duplicate steps with items [[d06cbea](https://github.com/baptisteArno/typebot.io/commit/d06cbeac7325a591b55f160f2fc54413b2c4957c)] +- 🐛 Debounce value on popover close [[f3c5f6b](https://github.com/baptisteArno/typebot.io/commit/f3c5f6bea2154bf820b70693edc91989c9f0beef)] +- 🐛 Better result initialization [[de78482](https://github.com/baptisteArno/typebot.io/commit/de784820ebcbaa87066efb1424137b3ad3515741)] +- 🐛 Encode hidden variables properly [[2ae326c](https://github.com/baptisteArno/typebot.io/commit/2ae326c102a14c2eeeee6f6e8aac1186a72d3c1c)] +- 🐛 Support bubble closes on save [[9fe85cd](https://github.com/baptisteArno/typebot.io/commit/9fe85cd9133f99becef4e32b8354375c66364d0a)] +- 🐛 Minor changes and improved accessibility [[b784e89](https://github.com/baptisteArno/typebot.io/commit/b784e8918e3191a034835af69acf71975aadd3af)] +- 🐛 PDF embed viewer [[bcff2e0](https://github.com/baptisteArno/typebot.io/commit/bcff2e0c1466350b170b25f987b00f08f81e1aba)] +- 🚑 Step id duplication [[b8019f3](https://github.com/baptisteArno/typebot.io/commit/b8019f3732779cc57e8c89a74a04221c775cc3b3)] +- 🚑 Viewer host [[e502413](https://github.com/baptisteArno/typebot.io/commit/e502413ecf79ae8ed31000431f67f8be923fb18d)] +- 🐛 Sample result w/ loops [[11101a4](https://github.com/baptisteArno/typebot.io/commit/11101a4600c885c93e057a78c5b584c25e0faa7d)] +- 🐛 Sample result w/ multi input blocks [[7399140](https://github.com/baptisteArno/typebot.io/commit/7399140e498c1d23cec6ad43738c39f5f0734b0a)] +- 🐛 Shortcode default URL [[5d3010d](https://github.com/baptisteArno/typebot.io/commit/5d3010d280d4e254d3af4cd324b2edfbec8e40e0)] +- 🐛 subscribeWebhook upsert [[cfbea6b](https://github.com/baptisteArno/typebot.io/commit/cfbea6bbbaf3e338d40ea1e3b30f0d616fa69ff6)] +- 🐛 Result parsing csv [[c437211](https://github.com/baptisteArno/typebot.io/commit/c4372113272243eef2c6a8eba3515b7dc9344db9)] +- 🐛 Parse variables for code step [[fb3d2bc](https://github.com/baptisteArno/typebot.io/commit/fb3d2bc9e6cf989f6b68325869a78441a34f00c5)] +- 🐛 Fix inconsistent webhook saving [[eef60fd](https://github.com/baptisteArno/typebot.io/commit/eef60fdf691f5b07b882286012acdf31706367f2)] +- 🚑 Custom domain lookup [[666f0c3](https://github.com/baptisteArno/typebot.io/commit/666f0c36bf02c6d7d442cb6a2b5414651399a453)] +- 🐛 Fix date picker UI on iOS [[8954730](https://github.com/baptisteArno/typebot.io/commit/89547305089d2936414f55791f30e9684db3f780)] +- 💚 Fix docker-compose builder entrypoint [[e4a3722](https://github.com/baptisteArno/typebot.io/commit/e4a3722c14ceb32b4eea459346da1c70e35cc522)] +- 🐛 Fix block title select on Chrome and Safari [[80679df](https://github.com/baptisteArno/typebot.io/commit/80679dfbd09ec9b28f76dc1d4b5fc3d095d86499)] +- 🐛 Duplicate webhook id [[1dbbc9a](https://github.com/baptisteArno/typebot.io/commit/1dbbc9a2517095ef0aacf7da30efbb5d93653be4)] +- 🐛 FIx Webhook settings debounce [[31298e3](https://github.com/baptisteArno/typebot.io/commit/31298e39c18342be87778d655ef8f78dcd78ac7e)] +- 🐛 Link to public bot CORS [[9427b2a](https://github.com/baptisteArno/typebot.io/commit/9427b2a823805ebbc30a481d84b0804aa9433fce)] +- 🐛 Attempt to fix auth issue behind proxy [[30fe7b3](https://github.com/baptisteArno/typebot.io/commit/30fe7b3db0baa9bc23c338265ca60b3095d791f0)] +- 🐛 Variables button in text editor [[36838f0](https://github.com/baptisteArno/typebot.io/commit/36838f05d3312b85271e32e74d933dcec1466139)] +- 🐛 Display results for blocks w/ multiple inputs [[4767cdc](https://github.com/baptisteArno/typebot.io/commit/4767cdc5421acd7c6c555c8f5c4134fa383b4b01)] +- 💚 Potentially fix turborepo cache [[7f82604](https://github.com/baptisteArno/typebot.io/commit/7f826047403818ceee76229c8b727feaa568a06c)] +- 🐛 Shared typebot case sensitivity [[b2784f1](https://github.com/baptisteArno/typebot.io/commit/b2784f19fd9fe60bcc24dc09fd42a0148fc5112f)] +- 🐛 Force display block on lite badge [[4c65b4c](https://github.com/baptisteArno/typebot.io/commit/4c65b4ce30f45f943fbc79a1549c93e0ef79739b)] +- 🐛 Avatar display on mobile [[ed9d791](https://github.com/baptisteArno/typebot.io/commit/ed9d791aacb35b2eb4adac08145a5c5830a9f394)] +- 🐛 Attempt to fix Google Sheets refresh [[c7d31be](https://github.com/baptisteArno/typebot.io/commit/c7d31bebf83b932d0f3326ee5614df8c90a6a6b3)] +- 🐛 Attempt to fix loading issue in iframe safari [[93639c1](https://github.com/baptisteArno/typebot.io/commit/93639c1fc6c932d8e1fe8b58b72809664605b532)] +- 🐛 Chat chunk management [[4714e80](https://github.com/baptisteArno/typebot.io/commit/4714e8046a16ce85ea398c55643e29ada06360e9)] +- 🐛 Fix subscribe webhook method [[831150e](https://github.com/baptisteArno/typebot.io/commit/831150e0404bca591a16f28680ea5d004dad5d30)] +- 🐛 Get data when extracting 1 column [[1bf3baf](https://github.com/baptisteArno/typebot.io/commit/1bf3bafb60dd84ab5c786d138e3f1ca4b842e8ad)] +- 🚑 Fix multiple avatars [[6ea23ef](https://github.com/baptisteArno/typebot.io/commit/6ea23ef63eb6c8d6870bea018e069581f821569d)] +- 🐛 outgoingEdgeId remaining when moving step [[6b34f76](https://github.com/baptisteArno/typebot.io/commit/6b34f7660471e29e25805ebe7c30b2aa27e425ba)] +- 🐛 Standalone '?' when no query params [[d6c3e8d](https://github.com/baptisteArno/typebot.io/commit/d6c3e8d41afb10a6c994cb9f6c6d9e32e9f26842)] +- 🐛 Drag single step from block [[ae347ee](https://github.com/baptisteArno/typebot.io/commit/ae347eeb53702074819ce13ba84e47ad6cd77a4a)] +- 🐛 Export header valid name [[71b2b84](https://github.com/baptisteArno/typebot.io/commit/71b2b84cdf609da9ac391526c7fb43965a2ac111)] +- 🐛 subscribe unsub zapier [[4630512](https://github.com/baptisteArno/typebot.io/commit/4630512b8ba8f4dfed23754d6f17ae398c9d8bdf)] +- 🐛 Fix duplication when customDomain is set [[33497b8](https://github.com/baptisteArno/typebot.io/commit/33497b876620ad51b9b844065f943b25f13c7ea7)] +- 🐛 Fix basic auth header without ':' [[8552cc2](https://github.com/baptisteArno/typebot.io/commit/8552cc237bc65b158f4533b51817b05cced42af1)] +- 🐛 Tiny bugs (Sentry) [[9e08ff5](https://github.com/baptisteArno/typebot.io/commit/9e08ff574b76399df4c058f56e2412a08d8f739c)] +- 🐛 Properly handle variable avatars [[d21b172](https://github.com/baptisteArno/typebot.io/commit/d21b1722b51f551b15d75404e2df9119f5658dc3)] +- 🐛 Start block was deletable [[8533bb9](https://github.com/baptisteArno/typebot.io/commit/8533bb92a856917c98c3db15e028f955111b7c14)] +- 🚑 Don't allow user without id [[7e7596d](https://github.com/baptisteArno/typebot.io/commit/7e7596d75e548ec21d2e98b2d2417c4046a1ed4a)] +- 🐛 Equal condition number vs string [[dd671a5](https://github.com/baptisteArno/typebot.io/commit/dd671a5d2c570558d5ad2d2a40561d774a384152)] +- 🚑 Duplicate typebot [[aca7d68](https://github.com/baptisteArno/typebot.io/commit/aca7d68360c8129e3f9212d899f147c649dc4b3d)] +- 🐛 Typing emulation on arabic chars [[b6618ba](https://github.com/baptisteArno/typebot.io/commit/b6618ba16557af2bf666e35f4579660c2f9fcad9)] +- 🐛 Smash tiny bugs [[1dc2264](https://github.com/baptisteArno/typebot.io/commit/1dc2264bdfefd1331076fa9681b4042280e4981b)] +- 🚑 Webhook and instant updates [[d49461c](https://github.com/baptisteArno/typebot.io/commit/d49461cde68cc5dfd52d2fe900c4f60e1de61fe3)] +- 🐛 Parse condition value variable [[65c206e](https://github.com/baptisteArno/typebot.io/commit/65c206e00ab87935fdd8ce278c7f674cf7a6bd74)] +- 🐛 Custom metadata in viewer [[6ec8d06](https://github.com/baptisteArno/typebot.io/commit/6ec8d06b97d3dc37015ec05aabe2ab0723578ad0)] +- 🐛 Edge not properly connecting to step target [[7a4b96f](https://github.com/baptisteArno/typebot.io/commit/7a4b96ff7e04471e560f95f42aab37b74d0afd90)] +- 🐛 Settings modal moving block [[3456e5a](https://github.com/baptisteArno/typebot.io/commit/3456e5af82ad16bb9fd2fab05494745c9d2f2af7)] +- 🐛 Typebot support bubble hidden vars [[341cd15](https://github.com/baptisteArno/typebot.io/commit/341cd15e0bd9e963c9e79f683700b52d7456706b)] +- 🐛 Custom path on domain [[291b4b3](https://github.com/baptisteArno/typebot.io/commit/291b4b31597293891d84fa6aa2b5f5bad8e2ffd4)] +- 💚 Use MIGRATION_DATABASE_URL [[a58c400](https://github.com/baptisteArno/typebot.io/commit/a58c400a7df36f20b1e596d0c58f726852c7f492)] +- 🐛 Collect prefilled variables in db [[aaf78e8](https://github.com/baptisteArno/typebot.io/commit/aaf78e8a54e8e606e909d0181cac241638259816)] +- 🐛 Frame load on Safari [[4b26ab3](https://github.com/baptisteArno/typebot.io/commit/4b26ab331d83ef59682b7144fdfc93aaddcd0283)] +- 🐛 No request if not published [[0bb50f9](https://github.com/baptisteArno/typebot.io/commit/0bb50f9e78a4c70c46ffc7688094e13c9d368403)] +- 🐛 Publish button sync [[adf99ac](https://github.com/baptisteArno/typebot.io/commit/adf99ac30c7a095cf85e6cf5e10f3756306a789d)] +- 🐛 Delete edge when adding last step [[67ccf07](https://github.com/baptisteArno/typebot.io/commit/67ccf07a610461f2c512af80d737990bbd9c3080)] +- 🐛 quick fixes [[b95d907](https://github.com/baptisteArno/typebot.io/commit/b95d907e8f5a1a12178f436788db932b0e848072)] +- 🐛 Duplicate typebot [[ea80fd6](https://github.com/baptisteArno/typebot.io/commit/ea80fd6d3ec3e31c99b3cfb2f1d94f45c1c4b749)] +- 💚 Incomplete results [[e6f6e25](https://github.com/baptisteArno/typebot.io/commit/e6f6e2523c13d5bce7d30900e22bab21778677d8)] +- 🐛 Import from file button [[5a060c7](https://github.com/baptisteArno/typebot.io/commit/5a060c7f7e65c456d5bb7394d352ef929c0fd33c)] +- 🐛 Fix email step in viewer [[d19b26e](https://github.com/baptisteArno/typebot.io/commit/d19b26e7dee0dfd6b6110ef4e8f517ef47c2be6b)] +- 🐛 Analytics board [[7c164e2](https://github.com/baptisteArno/typebot.io/commit/7c164e25d733266b154a32d8c60cf289a410fccb)] +- 🐛 Loading rows [[93fed89](https://github.com/baptisteArno/typebot.io/commit/93fed893c05f023a6e04b816f5bff9c7e065864f)] +- 💚 Attempt to fix LP rewrites [[19f4fdb](https://github.com/baptisteArno/typebot.io/commit/19f4fdb83a4db45d4e940db247793587bf37eb63)] +- 🐛 Fix scrolling behavior and avatar position [[f4336b8](https://github.com/baptisteArno/typebot.io/commit/f4336b83cc5de98f81ec8e4a02c7f68a10d013f6)] +- 🐛 Fix save button [[66f3e7e](https://github.com/baptisteArno/typebot.io/commit/66f3e7ee7cf1a4ba0d4ca1c55f4692d650fb8d44)] +- 💚 Fix tests [[ab34f95](https://github.com/baptisteArno/typebot.io/commit/ab34f95cce53499d41ecddf8fb289ac85691ec7a)] +- 💚 Fix e2e window reload bug [[8391bcc](https://github.com/baptisteArno/typebot.io/commit/8391bcce5e071605f217f424aa65985242794571)] +- 🐛 Step node drag [[6fe27bd](https://github.com/baptisteArno/typebot.io/commit/6fe27bd8eac9d7d43ec1139e3d3893264e2bb41a)] +- 🐛 Production bug [[eea522f](https://github.com/baptisteArno/typebot.io/commit/eea522f5bd972a09aa5e251d267e901af756e517)] + +### Security + +- 🔒 Enforce Sheets security [[78c4596](https://github.com/baptisteArno/typebot.io/commit/78c4596e9348f872576234a692fcf6b1fd8044e1)] +- 🔒 add checking for required group [[3db753e](https://github.com/baptisteArno/typebot.io/commit/3db753e886955f7f534d0d0af7f18beb96c845c9)] +- 🔒 add gitlab provider [[a4a62f2](https://github.com/baptisteArno/typebot.io/commit/a4a62f23b6595166fb660134a258f6569d7f512e)] +- 🔒 Still investigating sheets creds issue [[606932a](https://github.com/baptisteArno/typebot.io/commit/606932a77e030296d200472fcbb3a48a0ed7b5ff)] +- 🔒 Investigate on why spreadsheets sometimes fail [[bdd7a17](https://github.com/baptisteArno/typebot.io/commit/bdd7a1712eb7995a241ac6771ec03814659f927a)] +- 🔒 Enforce credentials security [[ed68096](https://github.com/baptisteArno/typebot.io/commit/ed680969f9e3acc3404d52952b983cd601a9ec09)] +- 🔒 Better guard spreadsheets GET [[97ba29f](https://github.com/baptisteArno/typebot.io/commit/97ba29f80193dff79abe821c9cfc92f7822aabe5)] +- 🔒 Change Google fonts key [[89ac0f8](https://github.com/baptisteArno/typebot.io/commit/89ac0f89cd440fa526cd6db3e746bd3317e378dd)] +- 🔒 Add extra user check in api [[ec18912](https://github.com/baptisteArno/typebot.io/commit/ec18912879f48a240288cb0260d4bf46ba6bb6c2)] + +### Miscellaneous + +- 📦 Update packages [[6c29865](https://github.com/baptisteArno/typebot.io/commit/6c2986590b79d9a16d4e747f2b89e975eeef5147)] +- 📝 Fix links and update doc [[ddaaa68](https://github.com/baptisteArno/typebot.io/commit/ddaaa68e282f1f702c8ddd10fda4a3b9412279b4)] +- 📝 Webhook block [[2271da8](https://github.com/baptisteArno/typebot.io/commit/2271da8870448a2e2128ed696abaf792ab7c1939)] +- 📝 Theme [[a848fa0](https://github.com/baptisteArno/typebot.io/commit/a848fa0a15da679b1384a1177174435d2004f0ff)] +- 📝 Email block [[f5404f9](https://github.com/baptisteArno/typebot.io/commit/f5404f96d5af656078ec3772fef0ea2873994247)] +- Merge pull request [#35](https://github.com/baptisteArno/typebot.io/issues/35) from baptisteArno/fix/google-font-error [[176cb4e](https://github.com/baptisteArno/typebot.io/commit/176cb4ed552c7a08c38174376cb784a521f20e19)] +- 📝 Typing emulation [[bf766e5](https://github.com/baptisteArno/typebot.io/commit/bf766e5cd90ea46e6875bbd3b5a239f2d3a13c20)] +- Merge pull request [#32](https://github.com/baptisteArno/typebot.io/issues/32) from laurin-wolf/10-add-gitlab-idp [[a863a4c](https://github.com/baptisteArno/typebot.io/commit/a863a4cb21a4c987d360cf610d3325b49c71d119)] +- 📦 Update typebot lib declarations [[1139569](https://github.com/baptisteArno/typebot.io/commit/113956929303325d1c810f56996c4d831c8e9464)] +- 🛂 Temporarily disable Make.com [[cff5ec6](https://github.com/baptisteArno/typebot.io/commit/cff5ec67deae7125b9e70ba6d780c0a319781a14)] +- 📝 add gitlab idp env variables [[b2b0685](https://github.com/baptisteArno/typebot.io/commit/b2b0685298d5417475b21885d5b198a3a9a306bb)] +- Merge branch 'main' of https://github.com/baptisteArno/typebot.io [[f788541](https://github.com/baptisteArno/typebot.io/commit/f7885415d84c97dbec70f42c13fbcae6f12ad333)] +- 🚧 Help to debug evaluated expressions [[e1d7533](https://github.com/baptisteArno/typebot.io/commit/e1d7533384f792e4f7158619ee820ae5a0b1a38a)] +- fix(auth):🐛explicitly set linkAccount user values , [#10](https://github.com/baptisteArno/typebot.io/issues/10) [[97b14f1](https://github.com/baptisteArno/typebot.io/commit/97b14f19f089c2e68f4d88ffbf8b58f1a1633dd2)] +- 📝 Add callback URL instructions [[e569e59](https://github.com/baptisteArno/typebot.io/commit/e569e59699dd8b4e102f2d193f54771b112116e2)] +- 📝 Simplified API endpoints [[29254f6](https://github.com/baptisteArno/typebot.io/commit/29254f675c6d0c1364ee3d22762e32140dd3fff3)] +- 📝 Improve configuration doc [[18319c8](https://github.com/baptisteArno/typebot.io/commit/18319c88c8b46db30e93c0d40da00c71e0401675)] +- Merge pull request [#24](https://github.com/baptisteArno/typebot.io/issues/24) from baptisteArno/feat/disable-smtp-auth [[1820686](https://github.com/baptisteArno/typebot.io/commit/18206866b8fb59f75822f78ec6d922b2b4b49ca6)] +- feat(auth): 👷 Disable smtp auth [[c657850](https://github.com/baptisteArno/typebot.io/commit/c6578505a511e46e6d7cb977d313efc6a3c9ce0f)] +- 📝 Add about page [[6a8d6d4](https://github.com/baptisteArno/typebot.io/commit/6a8d6d4d9a7e88a0352b3707fa1422e35c06a6db)] +- 📝 Better explain base url config [[a5491dc](https://github.com/baptisteArno/typebot.io/commit/a5491dc7a87f51f2cff6b35c5d217c63a06fd87d)] +- 📝 Add Lead Scoring template [[a08618d](https://github.com/baptisteArno/typebot.io/commit/a08618d24ebace50c4cd7a450c9dfb7e0796da86)] +- 📝 Condition block [[b1d30fc](https://github.com/baptisteArno/typebot.io/commit/b1d30fcb3bd965ab0ca293669fef058f9048708e)] +- Merge pull request [#21](https://github.com/baptisteArno/typebot.io/issues/21) from baptisteArno/feat/zoom [[47947a6](https://github.com/baptisteArno/typebot.io/commit/47947a6a142951b9148a1812eaec6434ba39cfbe)] +- build: 👷 Add Sentry context [[fb3bba8](https://github.com/baptisteArno/typebot.io/commit/fb3bba897f844e9f51dc1158909ac541f91c18c9)] +- 📝 Add Quizz [[5aac822](https://github.com/baptisteArno/typebot.io/commit/5aac8229d2b888348dd7b88948076cd3ce944da2)] +- 💫 Add name in user creation webhook [[4c9f97b](https://github.com/baptisteArno/typebot.io/commit/4c9f97b25470253da7735060096435b4125fd51a)] +- Merge pull request [#20](https://github.com/baptisteArno/typebot.io/issues/20) from baptisteArno/fix/delete-collaborator [[6314ce2](https://github.com/baptisteArno/typebot.io/commit/6314ce2f6259dca659cbc08b9a916d5941c0283a)] +- Merge branch 'main' of https://github.com/baptisteArno/typebot.io [[6ba6466](https://github.com/baptisteArno/typebot.io/commit/6ba646618d217c7476a89758fba99f13936925df)] +- Merge pull request [#18](https://github.com/baptisteArno/typebot.io/issues/18) from baptisteArno/fix/docker-prod [[5ce0212](https://github.com/baptisteArno/typebot.io/commit/5ce021247638185e7b857f57d2d80586d85701f7)] +- Merge pull request [#16](https://github.com/baptisteArno/typebot.io/issues/16) from baptisteArno/fix/uprade-modal-directory-typo [[a6a2fcc](https://github.com/baptisteArno/typebot.io/commit/a6a2fccdb8dd4a752f4372503ba660e73786bbf7)] +- Merge pull request [#14](https://github.com/baptisteArno/typebot.io/issues/14) from baptisteArno/fix/linked-typebot [[5903120](https://github.com/baptisteArno/typebot.io/commit/59031206aec39ab07542e9d41f1fd3f4b333ec26)] +- 📦 Update packages [[0500981](https://github.com/baptisteArno/typebot.io/commit/05009814d4afcaebc57d0e1fea22c926efb808a2)] +- 📝 Add privacy policies explanation [[e653ced](https://github.com/baptisteArno/typebot.io/commit/e653cedee92442feb7f6bfa3f4c8fb5223e00871)] +- 📝 Add "Set variable" doc [[af9e08f](https://github.com/baptisteArno/typebot.io/commit/af9e08fea0a76149d01b4124f6b4705d65740433)] +- 🛂 Make sure booleans are parsed in table [[f7d12dc](https://github.com/baptisteArno/typebot.io/commit/f7d12dc9954ff9c984fbd11f28eb91bc1e9a8125)] +- 🛂 Improve collab permissions [[bb194b1](https://github.com/baptisteArno/typebot.io/commit/bb194b1dbbcf6b8bfc4af64e124d98e3531e8566)] +- 📝 Add `hiddenVariables` JS instructions [[38c39d4](https://github.com/baptisteArno/typebot.io/commit/38c39d4a3130de6b775ae0b48156337c0c0a30a9)] +- build(self-host): 👷 Add chown Dockerfile [[f9a30bc](https://github.com/baptisteArno/typebot.io/commit/f9a30bc4ca9228b10bc08773e724e8d092213443)] +- 📝 Add License paragraph in README [[3a7078d](https://github.com/baptisteArno/typebot.io/commit/3a7078d0d05338020f34e1a2fb5d4a16d6927ef9)] +- 🚩 Add webhook url call on user creation [[39b0143](https://github.com/baptisteArno/typebot.io/commit/39b01431e026a33d08ad2b0885942351ecb99b73)] +- 🛂 Make sure branding is forced on file import [[0704213](https://github.com/baptisteArno/typebot.io/commit/07042137fb79ada80b57b1873cdfefd14373ab8d)] +- 📝 Add "Stay up-to-date" section in README [[bd702f2](https://github.com/baptisteArno/typebot.io/commit/bd702f2ebab8f4168e32de4e3ddc4b038d20a9b9)] +- 📝 Add 3rd testimonial [[d4022c6](https://github.com/baptisteArno/typebot.io/commit/d4022c6e3fb5aca1da3e1f8d8bf59a37bfe459eb)] +- 📝 Update typebot URL in embed instructions [[71816f7](https://github.com/baptisteArno/typebot.io/commit/71816f76ad54c1f264072abe4492264b722d9f07)] +- 📝 Fix A record CM name [[53fb34d](https://github.com/baptisteArno/typebot.io/commit/53fb34d2adda98cf99ec4c3097af05fd04d5f658)] +- 📝 Add "Human takeover" faq [[3d4f90d](https://github.com/baptisteArno/typebot.io/commit/3d4f90de16b763e723c5ae8ab720c6a32b4153ef)] +- 📝 Change SEO related info [[8ba231f](https://github.com/baptisteArno/typebot.io/commit/8ba231f39305c4647bc8f236859151cbba7740b7)] +- 🩹 Fix build [[ec8a27e](https://github.com/baptisteArno/typebot.io/commit/ec8a27e972f5d72841d38967e84ddaf0b3584663)] +- 📝 Update env var and write Configuration doc [[69248f9](https://github.com/baptisteArno/typebot.io/commit/69248f94d49e8361d22dd6473a247f94a74d033b)] +- 📝 Update README and contribution instructions [[b37db3c](https://github.com/baptisteArno/typebot.io/commit/b37db3cee3f62eba6a2bd5085e08e87da82ad4b4)] +- 📝 Add Google Sheets video [[6cf89d8](https://github.com/baptisteArno/typebot.io/commit/6cf89d8d9c468faa562935d51f6c2350757357e3)] +- 📝 Add RTL guide [[533fdb1](https://github.com/baptisteArno/typebot.io/commit/533fdb1b3a293f75380bfcc583d8b031ce4b5420)] +- 📝 Update feedback board links [[e73fce3](https://github.com/baptisteArno/typebot.io/commit/e73fce3907acb8e4b96b8544d1c9d90219b3e703)] +- build: 👷 Add Plan in support bubble [[380eae5](https://github.com/baptisteArno/typebot.io/commit/380eae545b16ef209a34d21a8d762be6da6daed4)] +- 📝 Init cool README (WIP) [[63a90f2](https://github.com/baptisteArno/typebot.io/commit/63a90f2deb3ff35a0fcd3d18c9282b5f56e49921)] +- chore: 👷 Add user info on Google sheets endpoints for Sentry [[0e14a23](https://github.com/baptisteArno/typebot.io/commit/0e14a238be9f071955b951ab4858eb7f457b5657)] +- 📝 Remove the 3 months notice on FAQ [[4bb5a57](https://github.com/baptisteArno/typebot.io/commit/4bb5a57f695168c5ff41fb24b72c747beda90bd1)] +- fix(hotfix): [[cc1dd51](https://github.com/baptisteArno/typebot.io/commit/cc1dd5152ea3fe59e9aa32da70326260587b6017)] +- 📝 Add API overview [[3ecde23](https://github.com/baptisteArno/typebot.io/commit/3ecde23e51a4c6274eabdee44143584830983e3e)] +- 📄 Change patch webhook to post [[1c758d3](https://github.com/baptisteArno/typebot.io/commit/1c758d39e5c3653a2d97c2b4f492d3db38bba7ac)] +- 🩹 Switch from stepId to id (for Zapier) [[e3704f6](https://github.com/baptisteArno/typebot.io/commit/e3704f6dd9586ac163f572d840ce24742a654ce4)] +- 📝 Add MailerLite guide [[37ef56b](https://github.com/baptisteArno/typebot.io/commit/37ef56bfc4ee345c7ecf40575538c8ff20a0afa2)] +- 📝 Default retry message bubble [[feb966d](https://github.com/baptisteArno/typebot.io/commit/feb966d51314c2cbbd775e7bc73930043698fe32)] +- 🛂 Add god rule to view typebots [[5d9356b](https://github.com/baptisteArno/typebot.io/commit/5d9356bd9cfb2f55de126c21e4a33976d232539a)] +- 🛂 Protect from others to consult typebots and folders [[f6d5eb5](https://github.com/baptisteArno/typebot.io/commit/f6d5eb577755e9f28c27265c3fe263ea8749e009)] +- 🛂 Add context variables to support typebot [[7402ad5](https://github.com/baptisteArno/typebot.io/commit/7402ad5f6d6bdafaca6b867f4f1810695bf2c03e)] +- 📝 Variables doc [[9b9e0f6](https://github.com/baptisteArno/typebot.io/commit/9b9e0f6312eacdfe8eca6eb61386fdc167222587)] +- ci: 👷 Add connection pooling DB [[1c178e0](https://github.com/baptisteArno/typebot.io/commit/1c178e01a67a5e68a2b8ce6bd3d4939217b601f9)] +- fix: Fix db critical [[558a603](https://github.com/baptisteArno/typebot.io/commit/558a60329d9e398fd4b455e049a0e2470e1705c6)] +- build: 👷 Fix error page [[7ebfd43](https://github.com/baptisteArno/typebot.io/commit/7ebfd43db82fd1c3fa935e7434692c9075fcecb3)] +- fix(editor): source endpoint even on buttons step [[0336bc2](https://github.com/baptisteArno/typebot.io/commit/0336bc2a421ccfd4560f86ea4fecac69297a6652)] +- 🩹 Avatar scroll on media bubbles [[1d3917f](https://github.com/baptisteArno/typebot.io/commit/1d3917f4403ca968e79bcb3ce68a9573ae7166cf)] +- 🩹 Vs pages typebot [[b1916e4](https://github.com/baptisteArno/typebot.io/commit/b1916e4f9c19c5b3f9ad4d76e78fa8555dbd1029)] +- 📝 Add 2.0 annoucement modal [[ab9c55e](https://github.com/baptisteArno/typebot.io/commit/ab9c55e2971893623d51c596c36d0c348b71c056)] +- 📝 Add FAQ [[c502bbb](https://github.com/baptisteArno/typebot.io/commit/c502bbb93bb86936c909f914381f6fc694b6f1a7)] +- build: 👷 Remove Sentry traceSampling [[a8a03fb](https://github.com/baptisteArno/typebot.io/commit/a8a03fbcf2f51e13960fa7ca4cae7b10b2cbe2da)] +- 💅 Show when the bot is published [[8583e2a](https://github.com/baptisteArno/typebot.io/commit/8583e2a1ba76cfdc114241a59d38bf93ea946726)] +- 🩹 Slow down graph panning on Chromium [[130f85e](https://github.com/baptisteArno/typebot.io/commit/130f85e3c9832c1a68d807798f598c43468ae1dd)] +- 📦 Update packages [[e7d1f5d](https://github.com/baptisteArno/typebot.io/commit/e7d1f5d67488e9a9498bcc22badf13152c78d24c)] +- 💅 Add access to v1 banner [[1fbe324](https://github.com/baptisteArno/typebot.io/commit/1fbe324e4396b562a52d01d9cd99111eebccdb80)] +- 🛂 Use env file from builder for db [[80c15f9](https://github.com/baptisteArno/typebot.io/commit/80c15f9491b176921cd62a8500488be9087eb03a)] +- 💫 Can pan graph with mouse + click [[1033e42](https://github.com/baptisteArno/typebot.io/commit/1033e42b60867ebbc245b42abf66ea9b5dc385aa)] +- 👔 Send email disabled in preview [[f8a6415](https://github.com/baptisteArno/typebot.io/commit/f8a64151ef2341ffc67f74bbb1ab6bc0c2aaea9b)] +- 🛂 Limit typebot branding [[f57827c](https://github.com/baptisteArno/typebot.io/commit/f57827c5303287fefa46a313cd7617c27b37b79b)] +- 🛂 Limit analytics [[f46ba38](https://github.com/baptisteArno/typebot.io/commit/f46ba381adffb02408b742f00c0c2ecd96a9f267)] +- 🛂 Limit incomplete submissions [[ec470b5](https://github.com/baptisteArno/typebot.io/commit/ec470b578c1d2aa769838b566d60a3c652164fac)] +- 🛂 Limit create folder to Pro user [[3a7b9a0](https://github.com/baptisteArno/typebot.io/commit/3a7b9a0c6321d330f3162d361bebaf8a2cd0e912)] +- 🗑️ Tidy up env files [[901e2f3](https://github.com/baptisteArno/typebot.io/commit/901e2f39b089d7a62e39f025c6c55cd8aafc89ff)] +- 🛂 Fix viewer host env name [[92515ef](https://github.com/baptisteArno/typebot.io/commit/92515efcc3358a1b6100268884a0052b2970460e)] +- 🛂 Dynamically parse the viewer api host [[cfbf3d4](https://github.com/baptisteArno/typebot.io/commit/cfbf3d4c0dfdc72567fdc56e0c6a988446abb1a9)] +- 📝 Add code blocks in embed instructions [[276f1c1](https://github.com/baptisteArno/typebot.io/commit/276f1c1e90f7c36d7329d3410e634d0aed73daf1)] +- 🗑️ Clean up gitignores [[c66827b](https://github.com/baptisteArno/typebot.io/commit/c66827b606f2708a4dbcffb05b8043356ce0843a)] +- 📦 Import existing Landing page [[36be357](https://github.com/baptisteArno/typebot.io/commit/36be3577e19aa7f9ef42fe08575da27afb2c103b)] +- 📝 Add embed instructions [[65b30bf](https://github.com/baptisteArno/typebot.io/commit/65b30bfc489fdfebc8e8a047383840cf9ff6ea7f)] +- 🩹 typebot buttons menu [[fc1d654](https://github.com/baptisteArno/typebot.io/commit/fc1d6547720fb6d3cd5fa22f90d7254819d6f94e)] +- chore(e2e): 👷 Fix e2e pipeline [[02bd2b9](https://github.com/baptisteArno/typebot.io/commit/02bd2b94ba2c4f61f88c1501e3c57e35a8525517)] +- ci(deployment): 👷 Add e2e tests on Vercel deployment [[65209c2](https://github.com/baptisteArno/typebot.io/commit/65209c26387420bbfde0f7d2d12f9fbb805a534d)] +- ⚗️ Add export results [[6c1e0fd](https://github.com/baptisteArno/typebot.io/commit/6c1e0fd345ba0d81f418236a85b20518ffa764bd)] +- ⚗️ Add infinite scroll in results table [[72454c0](https://github.com/baptisteArno/typebot.io/commit/72454c0f68b870c0a59992d34e8f86af677584c6)] +- ⚗️ Add delete results logic [[8ddf608](https://github.com/baptisteArno/typebot.io/commit/8ddf608c9ecd71376cf4125e74899e4b4e60a9cc)] +- 🧪 Add delete tests on dashboard [[6db34a8](https://github.com/baptisteArno/typebot.io/commit/6db34a8d4f3b8b7ef736b3ea355223c1305952d2)] +- 🖐️ Analytics drop off rates [[6322402](https://github.com/baptisteArno/typebot.io/commit/6322402c96265b78890c8143e72c5beebfc6c528)] +- 🪥 Consult submissions [[1093453](https://github.com/baptisteArno/typebot.io/commit/1093453c07f7ff99b9a9cfb1be4947ba098f2499)] +- 🧰 Aggregate utils & set up results collection in viewer [[f088f69](https://github.com/baptisteArno/typebot.io/commit/f088f694b97cf591a37053a4aa8adf7d77999b37)] +- 🧯 Fix template page [[447172d](https://github.com/baptisteArno/typebot.io/commit/447172d0cb436fe5fa69c1d835855989000a4352)] +- Add e2e tests for account [[8c826fc](https://github.com/baptisteArno/typebot.io/commit/8c826fcf709ad4d8f199ad1e48d7e1883c9246ea)] +- Add user account page [[e10fe1a](https://github.com/baptisteArno/typebot.io/commit/e10fe1a1868054e8b7683c7701274d8d4ad1469f)] +- 🦴 Add results backbone [[698867d](https://github.com/baptisteArno/typebot.io/commit/698867da5d39d256b11526cbd1616d06bd37d988)] +- 🦴 Add viewer backbone [[d369b4d](https://github.com/baptisteArno/typebot.io/commit/d369b4d941a73db4edbad85e57eec223ee3a8c50)] +- 🦴 Add share page backbone [[9a78a34](https://github.com/baptisteArno/typebot.io/commit/9a78a341d278beaec13c1b8cb84d6bd9d7ee1e9f)] +- 🦴 Add settings page backbone [[79aede1](https://github.com/baptisteArno/typebot.io/commit/79aede1f3f520849c7fc68bf99aa9ae9ab5bbbce)] +- 💼 Add license to package.jsons [[4d8056d](https://github.com/baptisteArno/typebot.io/commit/4d8056dfe8dcfb01beac113c87c2ea5cd9c1f792)] +- 🦴 Add theme page backbone [[30ddb14](https://github.com/baptisteArno/typebot.io/commit/30ddb143b474fc03e1fd0a07266a5e31d883deb5)] +- 🤽 Update turborepo [[6ee0647](https://github.com/baptisteArno/typebot.io/commit/6ee0647384d465cd1a3d0712c199285741f25bf2)] +- 🚀 Init preview and typebot cotext in editor [[b7cdc0d](https://github.com/baptisteArno/typebot.io/commit/b7cdc0d14a83891786507f6cdf76339b320461c3)] +- 🛠️ Adapt Cypress to Turbo Repo [[a54e42f](https://github.com/baptisteArno/typebot.io/commit/a54e42f255ac791251baf582e4925c7c58246603)] +- 🚀 Init Turbo Repo [[772b16c](https://github.com/baptisteArno/typebot.io/commit/772b16c6ce887d70f4615d8155160d3a8fc32113)] +- Add Graph draft [[da9459e](https://github.com/baptisteArno/typebot.io/commit/da9459edf3b244145c742b5168c54b290f7066d9)] +- Update README.md [[0f85d2c](https://github.com/baptisteArno/typebot.io/commit/0f85d2cd94e39d1fd138c227dce493126f600bf8)] +- Create LICENSE [[e3ab332](https://github.com/baptisteArno/typebot.io/commit/e3ab3320349e7a65692a2f6d38627a910f1252de)] +- Create FUNDING.yml [[dd3d11b](https://github.com/baptisteArno/typebot.io/commit/dd3d11bcb34ccf50814c2fe78038ba247fe240d5)] +- 🚀 Init bot-engine [[9dbad1d](https://github.com/baptisteArno/typebot.io/commit/9dbad1dbab22cf9a20d959ffbced6fff5ba1e74f)] +- 💅 Renamed prisma package to db [[641ba3d](https://github.com/baptisteArno/typebot.io/commit/641ba3db8af43d1dd9940b1d9ab2426a13c6d950)] +- 📤 Remove workspace file from git [[17665de](https://github.com/baptisteArno/typebot.io/commit/17665def128efaa2914286f993e0aa6497a0cfb7)] +- 🧯 Fix auth with db sessions [[575361e](https://github.com/baptisteArno/typebot.io/commit/575361ec19036b4b8e7d7e16d1c0fb1a69d61ca5)] +- 🖨️ Add prisma deploy script [[e2659b4](https://github.com/baptisteArno/typebot.io/commit/e2659b49e8a49e3ae72f9d0047bb10689c4adf86)] +- Add Dashboard [[54a641b](https://github.com/baptisteArno/typebot.io/commit/54a641b819c2c83a474bc6e1b708e2218d0162ea)] +- Add authentication [[5e14a94](https://github.com/baptisteArno/typebot.io/commit/5e14a94dea907712b6bb43ec963e04355f4a3cb5)] +- Set node-linker to node_modules [[68dd491](https://github.com/baptisteArno/typebot.io/commit/68dd491eca6f812c60383c49ae2ad376513d4264)] +- Init project [[6fe9807](https://github.com/baptisteArno/typebot.io/commit/6fe9807fbe460efe673ad19b0518faca546dcbff)] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..02abc17 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# Contributing to Typebot + +You are considering contributing to Typebot. I thank you for this 🙏. + +Any contributions you make are **greatly appreciated**. It can be anything from typo fixes to new features. + +Let's [discuss](https://github.com/baptisteArno/typebot.io/discussions/new) about what you want to implement before creating a PR if you are unsure about the requirements or the vision of Typebot. + +Typebot is a Monorepo powered by [Turborepo](https://turborepo.org/). It is composed of 2 main applications: + +- the builder ([`./apps/builder`](apps/builder)), where you build your typebots +- the viewer ([`./apps/viewer`](./apps/viewer)), where your user answer the typebot + +These apps are built with awesome web technologies including [Typescript](https://www.typescriptlang.org/), [Next.js](https://nextjs.org/), [Prisma](https://www.prisma.io/), [Chakra UI](https://chakra-ui.com/), [Tailwind CSS](https://tailwindcss.com/). + +## Get started + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your + own GitHub account and then + [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device. + +2. Create a new branch: + + ```sh + git checkout -b MY_BRANCH_NAME + ``` + +## Running the project locally + +1. Install dependencies + + ```sh + cd typebot.io + pnpm i + ``` + +2. Set up environment variables + + Copy [`.env.dev.example`](./.env.dev.example) to `.env` + + Check out the [Configuration guide](https://docs.typebot.io/self-hosting/configuration) if you want to enable more options + +3. Make sure you have [Docker](https://docs.docker.com/compose/install/) running + +4. Make sure you have Node.js installed. I suggest you use [`nvm`](https://github.com/nvm-sh/nvm) allowing you to manage different versions. Once you installed nvm, you can install and use the latest version of Node.js: `nvm install && nvm use` + +5. Start the builder and viewer + + ```sh + pnpm dev + ``` + + Builder is available at [`http://localhost:3000`](http://localhost:3000) + + Viewer is available at [`http://localhost:3001`](http://localhost:3001) + + Database inspector is available at [`http://localhost:5555`](http://localhost:5555) + + By default, you can easily authenticate in the builder using the "Github Sign In" button. For other options, check out the [Configuration guide](https://docs.typebot.io/self-hosting/configuration) + +6. (Optionnal) Start the landing page + + Copy [`apps/landing-page/.env.local.example`](apps/landing-page/.env.local.example) to `apps/landing-page/.env.local` + + ```sh + cd apps/landing-page + pnpm dev + ``` + +7. (Optionnal) Start the docs + + ```sh + cd apps/docs + pnpm start + ``` + +I know the project can be a bit hard to understand at first. I'm working on improving the documentation and the codebase to make it easier to contribute. If you have any questions, feel free to [open a discussion](https://github.com/baptisteArno/typebot.io/discussions/new) + +## How to create a new integration block + +The first step to create a new Typebot block is to define its schema. For this you need to + +1. Add your integration in the enum `IntegrationBlockType` in [`packages/schemas/features/blocks/integrations/enums.ts`](packages/schemas/features/blocks/integrations/enums.ts) +2. Create a new file in [`packages/schemas/features/blocks/integrations`](packages/schemas/features/blocks/integrations). + + Your schema should look like: + + ```ts + import { z } from 'zod' + import { blockBaseSchema } from '../baseSchemas' + + export const myIntegrationBlockSchema = blockBaseSchema.merge( + z.object({ + type: z.enum([IntegrationBlockType.MY_INTEGRATION]), + options: z.object({ + //... + }), + }) + ) + + export type MyIntegrationBlock = z.infer + ``` + +3. Add `myIntegrationBlockSchema` to `blockSchema` in `packages/schemas/features/blocks/schemas.ts` + +As soon as you have defined your schema, you can start implementing your block in the builder and the viewer. +Since the code is strictly typed, you should see exactly where you need to add your integration-specific code. + +To sum it up you need to create a folder in [`apps/builder/src/features/blocks/integrations`](apps/builder/src/features/blocks/integrations) and in [`apps/viewer/src/features/blocks/integrations`](apps/viewer/src/features/blocks/integrations) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..da8b115 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,59 @@ +FROM node:18-bullseye-slim AS base +WORKDIR /app +ARG SCOPE +ENV SCOPE=${SCOPE} +RUN apt-get -qy update \ + && apt-get -qy --no-install-recommends install \ + openssl \ + && apt-get autoremove -yq \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +RUN npm --global install pnpm + +FROM base AS pruner +RUN npm --global install turbo +WORKDIR /app +COPY . . +RUN turbo prune --scope=${SCOPE} --docker + +FROM base AS builder +RUN apt-get -qy update && apt-get -qy --no-install-recommends install openssl git +WORKDIR /app +COPY .gitignore .gitignore +COPY .npmrc .pnpmfile.cjs ./ +COPY --from=pruner /app/out/json/ . +COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +RUN pnpm install +COPY --from=pruner /app/out/full/ . +COPY turbo.json turbo.json + +RUN SKIP_ENV_CHECK=true pnpm turbo run build --filter=${SCOPE}... + +FROM base AS runner +WORKDIR /app + +COPY --from=builder --chown=node:node /app/apps/${SCOPE}/.next/standalone ./ +COPY --from=builder --chown=node:node /app/apps/${SCOPE}/.next/static ./apps/${SCOPE}/.next/static +COPY --from=builder --chown=nextjs:nodejs /app/apps/${SCOPE}/public ./apps/${SCOPE}/public + +## Copy next-runtime-env and its dependencies for runtime public variable injection +COPY --from=builder /app/node_modules/.pnpm/chalk@4.1.2/node_modules/chalk ./node_modules/chalk +COPY --from=builder /app/node_modules/.pnpm/chalk@4.1.2/node_modules/ansi-styles ./node_modules/ansi-styles +COPY --from=builder /app/node_modules/.pnpm/chalk@4.1.2/node_modules/supports-color ./node_modules/supports-color +COPY --from=builder /app/node_modules/.pnpm/has-flag@4.0.0/node_modules/has-flag ./node_modules/has-flag +COPY --from=builder /app/node_modules/.pnpm/next-runtime-env@1.6.2/node_modules/next-runtime-env/build ./node_modules/next-runtime-env/build + +## Copy prisma package and its dependencies and generate schema +COPY ./packages/prisma/postgresql ./packages/prisma/postgresql +COPY --from=builder /app/node_modules/.pnpm/@prisma+client@5.0.0_prisma@5.0.0/node_modules/@prisma/client ./node_modules/@prisma/client +COPY --from=builder /app/node_modules/.pnpm/@prisma+engines@5.0.0/node_modules/@prisma/engines ./node_modules/@prisma/engines +COPY --from=builder /app/node_modules/.pnpm/prisma@5.0.0/node_modules/prisma ./node_modules/prisma +COPY --from=builder /app/node_modules/.bin/prisma ./node_modules/.bin/prisma +RUN ./node_modules/.bin/prisma generate --schema=packages/prisma/postgresql/schema.prisma; + +COPY scripts/${SCOPE}-entrypoint.sh ./ +RUN chmod +x ./${SCOPE}-entrypoint.sh +ENTRYPOINT ./${SCOPE}-entrypoint.sh + +EXPOSE 3000 +ENV PORT 3000 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cb3a038 --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +
+

+ + Typebot illustration + + + Typebot illustration + +

+
+ +

+Typebot is an open-source chatbot builder. It allows you to create advanced chatbots visually, embed them anywhere on your web/mobile apps, and collect results in real-time +

+ +

+Github Stars + +Commits per month + + + +License +Uptime +Report a bug +Ask a question +Ask a question +Ask a question + +

+ +

+ Try Typebot + • + Docs + +--- + +## Builder demo + +https://user-images.githubusercontent.com/16015833/168876388-0310678d-080b-4eca-8633-e5cc4d7bd5d1.mp4 + +## Features + +Typebot makes it easy to create advanced chatbots. It provides the building block that are adaptable to any business use case. I improve Typebot regularly with bug fixes, new features, and performance improvements regularly. + +**Chat builder** with 34+ building blocks such as: + +- 💬 Bubbles: Text, Image / GIF, video, audio, embed. +- 🔤 Inputs: Text, email, phone number, buttons, picture choice, date picker, payment (Stripe), file picker... inputs +- 🧠 Logic: Conditional branching, URL redirections, scripting (Javascript), A/B testing +- 🔌 Integrations: Webhook / HTTP requests, OpenAI, Google Sheets, Google Analytics, Meta Pixel, Zapier, Make.com, Chatwoot, More to come... + +**Theme** your chatbot to match your brand identity: + +- 🎨 Customize the fonts, background, colors, roundness, shadows, and more +- 💪 Advanced theming with custom CSS. +- 💾 Reusable theme templates + +**Share** your typebot anywhere: + +- 🔗 Custom domain +- 👨‍💻 Embed as a container, popup, or chat bubble easily with the native JS library. +- ⚡ Blazing fast embed lib. No iframe, no external dependencies, no performance impact. +- 💻 Executable with HTTP requests + +Collect your **Results** and get insights: + +- 📊 In-depth analytics with drop-off rates, completion rates, and more +- 📥 Export results to CSV + +Built for **developers**: + +- 🔓 No vendor-locking. Features built with flexibility in mind. +- 💻 Easy-to-use [APIs](https://docs.typebot.io/api). + +## Getting started with Typebot + +The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). You'll have high availability, backups, security, and maintenance all managed for you by me, [Baptiste, Typebot's founder](https://twitter.com/baptisteArno). + +The cloud version can save a substantial amount of developer time and resources. For most sites this ends up being the best value option and the revenue goes to funding the maintenance and further development of Typebot. +So you’ll be supporting open source software and getting a great service! 💙 + +## Support & Community + +You'll find a lot of resources to help you get started with Typebot in the [documentation](https://docs.typebot.io/). + +- Have a question? Join the [Discord server](https://typebot.io/discord) and get instant help. +- Found a bug? [Create an issue](https://github.com/baptisteArno/typebot.io/issues/new) + +## Self-hosting + +Interested in self-hosting Typebot on your server? Take a look at the [self-hosting installation instructions](https://docs.typebot.io/self-hosting). + +## How to Contribute + +You are awesome, lets build great software together. Head over to the [Contribute guidelines](https://github.com/baptisteArno/typebot.io/blob/main/CONTRIBUTING.md) to get started. 💪 + +### Claim these open bounties 👇 + + + + + Bounties of typebot + + + +## Run the project locally + +Follow the [Get started](https://github.com/baptisteArno/typebot.io/blob/main/CONTRIBUTING.md#get-started) section of the Contributing guide. + +### Top contributors + + + + + +Made with [contrib.rocks](https://contrib.rocks). + +## License + +Typebot is open-source under the GNU Affero General Public License Version 3 (AGPLv3). You will find more information about the license and how to comply with it [here](https://docs.typebot.io/self-hosting#license-requirements). diff --git a/apps/builder/.eslintrc.js b/apps/builder/.eslintrc.js new file mode 100644 index 0000000..b56159e --- /dev/null +++ b/apps/builder/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['custom'], +} diff --git a/apps/builder/next-env.d.ts b/apps/builder/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/apps/builder/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/apps/builder/next.config.mjs b/apps/builder/next.config.mjs new file mode 100644 index 0000000..e341496 --- /dev/null +++ b/apps/builder/next.config.mjs @@ -0,0 +1,118 @@ +import { withSentryConfig } from '@sentry/nextjs' +import { join, dirname } from 'path' +import '@typebot.io/env/dist/env.mjs' +import { configureRuntimeEnv } from 'next-runtime-env/build/configure.js' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) + +const __dirname = dirname(__filename) + +const injectViewerUrlIfVercelPreview = (val) => { + if ( + (val && typeof val === 'string' && val.length > 0) || + process.env.VERCEL_ENV !== 'preview' || + !process.env.VERCEL_BUILDER_PROJECT_NAME || + !process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) + return + process.env.NEXT_PUBLIC_VIEWER_URL = + `https://${process.env.VERCEL_BRANCH_URL}`.replace( + process.env.VERCEL_BUILDER_PROJECT_NAME, + process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) +} + +injectViewerUrlIfVercelPreview(process.env.NEXT_PUBLIC_VIEWER_URL) + +configureRuntimeEnv() + +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + output: 'standalone', + transpilePackages: [ + '@typebot.io/lib', + '@typebot.io/schemas', + '@typebot.io/emails', + '@typebot.io/env', + ], + i18n: { + defaultLocale: 'en', + locales: ['en', 'fr', 'pt', 'pt-BR', 'de', 'ro', 'es'], + }, + experimental: { + outputFileTracingRoot: join(__dirname, '../../'), + }, + webpack: (config, { nextRuntime }) => { + if (nextRuntime === 'nodejs') return config + + if (nextRuntime === 'edge') { + config.resolve.alias['minio'] = false + config.resolve.alias['got'] = false + return config + } + // These packages are imports from the integrations definition files that can be ignored for the client. + config.resolve.alias['minio'] = false + config.resolve.alias['got'] = false + config.resolve.alias['openai'] = false + return config + }, + headers: async () => { + return [ + { + source: '/(.*)?', + headers: [ + { + key: 'X-Frame-Options', + value: 'SAMEORIGIN', + }, + ], + }, + ] + }, + async rewrites() { + return process.env.NEXT_PUBLIC_POSTHOG_KEY + ? [ + { + source: '/ingest/:path*', + destination: + (process.env.NEXT_PUBLIC_POSTHOG_HOST ?? + 'https://app.posthog.com') + '/:path*', + }, + ] + : [] + }, +} + +export default process.env.NEXT_PUBLIC_SENTRY_DSN + ? withSentryConfig( + nextConfig, + { + // For all available options, see: + // https://github.com/getsentry/sentry-webpack-plugin#options + + // Suppresses source map uploading logs during build + silent: true, + release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder', + org: process.env.SENTRY_ORG, + project: process.env.SENTRY_PROJECT, + }, + { + // For all available options, see: + // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ + + // Upload a larger set of source maps for prettier stack traces (increases build time) + widenClientFileUpload: true, + + // Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load) + tunnelRoute: '/monitoring', + + // Hides source maps from generated client bundles + hideSourceMaps: true, + + // Automatically tree-shake Sentry logger statements to reduce bundle size + disableLogger: true, + } + ) + : nextConfig diff --git a/apps/builder/package.json b/apps/builder/package.json new file mode 100644 index 0000000..59ee08b --- /dev/null +++ b/apps/builder/package.json @@ -0,0 +1,127 @@ +{ + "name": "builder", + "version": "0.1.0", + "license": "AGPL-3.0-or-later", + "scripts": { + "dev": "dotenv -e ./.env -e ../../.env -- next dev -p 3000", + "build": "dotenv -e ./.env -e ../../.env -- next build", + "start": "dotenv -e ./.env -e ../../.env -- next start", + "lint": "dotenv -e ./.env -e ../../.env -- next lint", + "test": "dotenv -e ./.env -e ../../.env -- pnpm playwright test", + "test:show-report": "pnpm playwright show-report src/test/reporters" + }, + "dependencies": { + "@chakra-ui/anatomy": "2.1.1", + "@chakra-ui/react": "2.7.1", + "@chakra-ui/theme-tools": "2.0.18", + "@dnd-kit/core": "6.0.8", + "@dnd-kit/sortable": "7.0.2", + "@dnd-kit/utilities": "3.2.1", + "@emotion/react": "11.11.1", + "@emotion/styled": "11.11.0", + "@faire/mjml-react": "3.3.0", + "@giphy/js-fetch-api": "5.0.0", + "@giphy/js-types": "4.4.0", + "@giphy/js-util": "5.0.0", + "@giphy/react-components": "7.1.0", + "@googleapis/drive": "8.0.0", + "@paralleldrive/cuid2": "2.2.1", + "@sentry/nextjs": "7.77.0", + "@tanstack/react-query": "4.29.19", + "@tanstack/react-table": "8.9.3", + "@tolgee/format-icu": "5.13.3", + "@tolgee/react": "5.13.3", + "@trpc/client": "10.40.0", + "@trpc/next": "10.40.0", + "@trpc/react-query": "10.40.0", + "@trpc/server": "10.40.0", + "@typebot.io/bot-engine": "workspace:*", + "@typebot.io/emails": "workspace:*", + "@typebot.io/env": "workspace:*", + "@typebot.io/js": "workspace:*", + "@typebot.io/nextjs": "workspace:*", + "@udecode/plate-basic-marks": "21.1.5", + "@udecode/plate-common": "21.1.5", + "@udecode/plate-core": "21.1.5", + "@udecode/plate-link": "21.2.0", + "@udecode/plate-ui-link": "21.2.0", + "@udecode/plate-ui-toolbar": "21.1.5", + "@uiw/codemirror-extensions-langs": "4.21.7", + "@uiw/codemirror-theme-github": "4.21.7", + "@uiw/codemirror-theme-tokyo-night": "4.21.7", + "@uiw/react-codemirror": "4.21.7", + "@upstash/ratelimit": "0.4.3", + "@upstash/redis": "1.22.0", + "@use-gesture/react": "10.2.27", + "browser-image-compression": "2.0.2", + "canvas-confetti": "1.6.0", + "codemirror": "6.0.1", + "deep-object-diff": "1.1.9", + "dequal": "2.0.3", + "emojilib": "3.0.10", + "focus-visible": "5.2.0", + "framer-motion": "10.3.0", + "google-auth-library": "8.9.0", + "google-spreadsheet": "4.0.2", + "got": "12.6.0", + "immer": "10.0.2", + "jsonwebtoken": "9.0.1", + "libphonenumber-js": "1.10.37", + "micro": "10.0.1", + "micro-cors": "0.1.1", + "next": "14.0.3", + "next-auth": "4.22.1", + "nextjs-cors": "2.1.2", + "nodemailer": "6.9.3", + "nprogress": "0.2.0", + "openai": "4.19.0", + "papaparse": "5.4.1", + "posthog-js": "1.77.1", + "posthog-node": "3.1.1", + "prettier": "2.8.8", + "qs": "6.11.2", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-markdown": "^9.0.1", + "slate": "0.94.1", + "slate-history": "0.93.0", + "slate-react": "0.94.2", + "stripe": "12.13.0", + "svg-round-corners": "0.4.1", + "swr": "2.2.0", + "tinycolor2": "1.6.0", + "trpc-openapi": "1.2.0", + "unsplash-js": "7.0.18", + "use-debounce": "9.0.4" + }, + "devDependencies": { + "@chakra-ui/styled-system": "2.9.1", + "@playwright/test": "1.36.0", + "@typebot.io/forge": "workspace:*", + "@typebot.io/forge-repository": "workspace:*", + "@typebot.io/forge-schemas": "workspace:*", + "@typebot.io/lib": "workspace:*", + "@typebot.io/prisma": "workspace:*", + "@typebot.io/schemas": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@typebot.io/radar": "workspace:*", + "@types/canvas-confetti": "1.6.0", + "@types/jsonwebtoken": "9.0.2", + "@types/micro-cors": "0.1.3", + "@types/node": "20.4.2", + "@types/nodemailer": "6.4.8", + "@types/nprogress": "0.2.0", + "@types/papaparse": "5.3.7", + "@types/prettier": "2.7.3", + "@types/qs": "6.9.7", + "@types/react": "18.2.15", + "@types/tinycolor2": "1.4.3", + "dotenv-cli": "7.2.1", + "eslint": "8.44.0", + "eslint-config-custom": "workspace:*", + "next-runtime-env": "1.6.2", + "superjson": "1.12.4", + "typescript": "5.3.2", + "zod": "3.22.4" + } +} diff --git a/apps/builder/playwright.config.ts b/apps/builder/playwright.config.ts new file mode 100644 index 0000000..9e00557 --- /dev/null +++ b/apps/builder/playwright.config.ts @@ -0,0 +1,20 @@ +import { PlaywrightTestConfig } from '@playwright/test' +import path from 'path' +import { playwrightBaseConfig } from '@typebot.io/lib/playwright/baseConfig' + +const config: PlaywrightTestConfig = { + ...playwrightBaseConfig, + webServer: process.env.CI + ? { + ...(playwrightBaseConfig.webServer as { command: string }), + port: 3000, + } + : undefined, + use: { + ...playwrightBaseConfig.use, + baseURL: process.env.NEXTAUTH_URL, + storageState: path.join(__dirname, 'src/test/storageState.json'), + }, +} + +export default config diff --git a/apps/builder/public/favicon.png b/apps/builder/public/favicon.png new file mode 100644 index 0000000..214afed Binary files /dev/null and b/apps/builder/public/favicon.png differ diff --git a/apps/builder/public/icons/0.svg b/apps/builder/public/icons/0.svg new file mode 100644 index 0000000..18c1560 --- /dev/null +++ b/apps/builder/public/icons/0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/1.svg b/apps/builder/public/icons/1.svg new file mode 100644 index 0000000..2269b8f --- /dev/null +++ b/apps/builder/public/icons/1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/2.svg b/apps/builder/public/icons/2.svg new file mode 100644 index 0000000..e2b9463 --- /dev/null +++ b/apps/builder/public/icons/2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/3.svg b/apps/builder/public/icons/3.svg new file mode 100644 index 0000000..07e2d2b --- /dev/null +++ b/apps/builder/public/icons/3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/4.svg b/apps/builder/public/icons/4.svg new file mode 100644 index 0000000..6767164 --- /dev/null +++ b/apps/builder/public/icons/4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/5.svg b/apps/builder/public/icons/5.svg new file mode 100644 index 0000000..a9d018d --- /dev/null +++ b/apps/builder/public/icons/5.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/6.svg b/apps/builder/public/icons/6.svg new file mode 100644 index 0000000..5c6443e --- /dev/null +++ b/apps/builder/public/icons/6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/7.svg b/apps/builder/public/icons/7.svg new file mode 100644 index 0000000..1f25b65 --- /dev/null +++ b/apps/builder/public/icons/7.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/8.svg b/apps/builder/public/icons/8.svg new file mode 100644 index 0000000..cb7a9e0 --- /dev/null +++ b/apps/builder/public/icons/8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/9.svg b/apps/builder/public/icons/9.svg new file mode 100644 index 0000000..b6594f0 --- /dev/null +++ b/apps/builder/public/icons/9.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/a.svg b/apps/builder/public/icons/a.svg new file mode 100644 index 0000000..d3a0fcd --- /dev/null +++ b/apps/builder/public/icons/a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/address-book.svg b/apps/builder/public/icons/address-book.svg new file mode 100644 index 0000000..7f921cb --- /dev/null +++ b/apps/builder/public/icons/address-book.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/address-card.svg b/apps/builder/public/icons/address-card.svg new file mode 100644 index 0000000..be48b25 --- /dev/null +++ b/apps/builder/public/icons/address-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/align-center.svg b/apps/builder/public/icons/align-center.svg new file mode 100644 index 0000000..c83a4b7 --- /dev/null +++ b/apps/builder/public/icons/align-center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/align-justify.svg b/apps/builder/public/icons/align-justify.svg new file mode 100644 index 0000000..03679ba --- /dev/null +++ b/apps/builder/public/icons/align-justify.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/align-left.svg b/apps/builder/public/icons/align-left.svg new file mode 100644 index 0000000..bfc309e --- /dev/null +++ b/apps/builder/public/icons/align-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/align-right.svg b/apps/builder/public/icons/align-right.svg new file mode 100644 index 0000000..8ad6d2b --- /dev/null +++ b/apps/builder/public/icons/align-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/anchor-circle-check.svg b/apps/builder/public/icons/anchor-circle-check.svg new file mode 100644 index 0000000..6950f61 --- /dev/null +++ b/apps/builder/public/icons/anchor-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/anchor-circle-exclamation.svg b/apps/builder/public/icons/anchor-circle-exclamation.svg new file mode 100644 index 0000000..32df08d --- /dev/null +++ b/apps/builder/public/icons/anchor-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/anchor-circle-xmark.svg b/apps/builder/public/icons/anchor-circle-xmark.svg new file mode 100644 index 0000000..bd9cbd5 --- /dev/null +++ b/apps/builder/public/icons/anchor-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/anchor-lock.svg b/apps/builder/public/icons/anchor-lock.svg new file mode 100644 index 0000000..3b183c6 --- /dev/null +++ b/apps/builder/public/icons/anchor-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/anchor.svg b/apps/builder/public/icons/anchor.svg new file mode 100644 index 0000000..3b16802 --- /dev/null +++ b/apps/builder/public/icons/anchor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angle-down.svg b/apps/builder/public/icons/angle-down.svg new file mode 100644 index 0000000..d660c91 --- /dev/null +++ b/apps/builder/public/icons/angle-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angle-left.svg b/apps/builder/public/icons/angle-left.svg new file mode 100644 index 0000000..0391d14 --- /dev/null +++ b/apps/builder/public/icons/angle-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angle-right.svg b/apps/builder/public/icons/angle-right.svg new file mode 100644 index 0000000..3b024d9 --- /dev/null +++ b/apps/builder/public/icons/angle-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angle-up.svg b/apps/builder/public/icons/angle-up.svg new file mode 100644 index 0000000..f972f28 --- /dev/null +++ b/apps/builder/public/icons/angle-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angles-down.svg b/apps/builder/public/icons/angles-down.svg new file mode 100644 index 0000000..47c937e --- /dev/null +++ b/apps/builder/public/icons/angles-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angles-left.svg b/apps/builder/public/icons/angles-left.svg new file mode 100644 index 0000000..df7e622 --- /dev/null +++ b/apps/builder/public/icons/angles-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angles-right.svg b/apps/builder/public/icons/angles-right.svg new file mode 100644 index 0000000..2fbc541 --- /dev/null +++ b/apps/builder/public/icons/angles-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/angles-up.svg b/apps/builder/public/icons/angles-up.svg new file mode 100644 index 0000000..d0d8d5e --- /dev/null +++ b/apps/builder/public/icons/angles-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ankh.svg b/apps/builder/public/icons/ankh.svg new file mode 100644 index 0000000..45e8ecb --- /dev/null +++ b/apps/builder/public/icons/ankh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/apple-whole.svg b/apps/builder/public/icons/apple-whole.svg new file mode 100644 index 0000000..c92aa63 --- /dev/null +++ b/apps/builder/public/icons/apple-whole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/archway.svg b/apps/builder/public/icons/archway.svg new file mode 100644 index 0000000..964257b --- /dev/null +++ b/apps/builder/public/icons/archway.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-1-9.svg b/apps/builder/public/icons/arrow-down-1-9.svg new file mode 100644 index 0000000..5c0ab23 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-1-9.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-9-1.svg b/apps/builder/public/icons/arrow-down-9-1.svg new file mode 100644 index 0000000..bd8a0d6 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-9-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-a-z.svg b/apps/builder/public/icons/arrow-down-a-z.svg new file mode 100644 index 0000000..9c4fd06 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-a-z.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-long.svg b/apps/builder/public/icons/arrow-down-long.svg new file mode 100644 index 0000000..878c07d --- /dev/null +++ b/apps/builder/public/icons/arrow-down-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-short-wide.svg b/apps/builder/public/icons/arrow-down-short-wide.svg new file mode 100644 index 0000000..608e0cf --- /dev/null +++ b/apps/builder/public/icons/arrow-down-short-wide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-up-across-line.svg b/apps/builder/public/icons/arrow-down-up-across-line.svg new file mode 100644 index 0000000..0559396 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-up-across-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-up-lock.svg b/apps/builder/public/icons/arrow-down-up-lock.svg new file mode 100644 index 0000000..6913992 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-up-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-wide-short.svg b/apps/builder/public/icons/arrow-down-wide-short.svg new file mode 100644 index 0000000..f1bba6b --- /dev/null +++ b/apps/builder/public/icons/arrow-down-wide-short.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down-z-a.svg b/apps/builder/public/icons/arrow-down-z-a.svg new file mode 100644 index 0000000..15b7f51 --- /dev/null +++ b/apps/builder/public/icons/arrow-down-z-a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-down.svg b/apps/builder/public/icons/arrow-down.svg new file mode 100644 index 0000000..c3d1ee8 --- /dev/null +++ b/apps/builder/public/icons/arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-left-long.svg b/apps/builder/public/icons/arrow-left-long.svg new file mode 100644 index 0000000..bdddf9b --- /dev/null +++ b/apps/builder/public/icons/arrow-left-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-left.svg b/apps/builder/public/icons/arrow-left.svg new file mode 100644 index 0000000..c289342 --- /dev/null +++ b/apps/builder/public/icons/arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-pointer.svg b/apps/builder/public/icons/arrow-pointer.svg new file mode 100644 index 0000000..3fa4e36 --- /dev/null +++ b/apps/builder/public/icons/arrow-pointer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right-arrow-left.svg b/apps/builder/public/icons/arrow-right-arrow-left.svg new file mode 100644 index 0000000..e7319ce --- /dev/null +++ b/apps/builder/public/icons/arrow-right-arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right-from-bracket.svg b/apps/builder/public/icons/arrow-right-from-bracket.svg new file mode 100644 index 0000000..1dce7dc --- /dev/null +++ b/apps/builder/public/icons/arrow-right-from-bracket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right-long.svg b/apps/builder/public/icons/arrow-right-long.svg new file mode 100644 index 0000000..4cb4846 --- /dev/null +++ b/apps/builder/public/icons/arrow-right-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right-to-bracket.svg b/apps/builder/public/icons/arrow-right-to-bracket.svg new file mode 100644 index 0000000..4132709 --- /dev/null +++ b/apps/builder/public/icons/arrow-right-to-bracket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right-to-city.svg b/apps/builder/public/icons/arrow-right-to-city.svg new file mode 100644 index 0000000..19dd17b --- /dev/null +++ b/apps/builder/public/icons/arrow-right-to-city.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-right.svg b/apps/builder/public/icons/arrow-right.svg new file mode 100644 index 0000000..a74e604 --- /dev/null +++ b/apps/builder/public/icons/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-rotate-left.svg b/apps/builder/public/icons/arrow-rotate-left.svg new file mode 100644 index 0000000..fd41a64 --- /dev/null +++ b/apps/builder/public/icons/arrow-rotate-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-rotate-right.svg b/apps/builder/public/icons/arrow-rotate-right.svg new file mode 100644 index 0000000..6c8c48f --- /dev/null +++ b/apps/builder/public/icons/arrow-rotate-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-trend-down.svg b/apps/builder/public/icons/arrow-trend-down.svg new file mode 100644 index 0000000..aaafc8d --- /dev/null +++ b/apps/builder/public/icons/arrow-trend-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-trend-up.svg b/apps/builder/public/icons/arrow-trend-up.svg new file mode 100644 index 0000000..fc62982 --- /dev/null +++ b/apps/builder/public/icons/arrow-trend-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-turn-down.svg b/apps/builder/public/icons/arrow-turn-down.svg new file mode 100644 index 0000000..a516889 --- /dev/null +++ b/apps/builder/public/icons/arrow-turn-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-turn-up.svg b/apps/builder/public/icons/arrow-turn-up.svg new file mode 100644 index 0000000..9d44652 --- /dev/null +++ b/apps/builder/public/icons/arrow-turn-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-1-9.svg b/apps/builder/public/icons/arrow-up-1-9.svg new file mode 100644 index 0000000..cc6f1e6 --- /dev/null +++ b/apps/builder/public/icons/arrow-up-1-9.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-9-1.svg b/apps/builder/public/icons/arrow-up-9-1.svg new file mode 100644 index 0000000..5f78369 --- /dev/null +++ b/apps/builder/public/icons/arrow-up-9-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-a-z.svg b/apps/builder/public/icons/arrow-up-a-z.svg new file mode 100644 index 0000000..d6d104c --- /dev/null +++ b/apps/builder/public/icons/arrow-up-a-z.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-from-bracket.svg b/apps/builder/public/icons/arrow-up-from-bracket.svg new file mode 100644 index 0000000..44bbb9f --- /dev/null +++ b/apps/builder/public/icons/arrow-up-from-bracket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-from-ground-water.svg b/apps/builder/public/icons/arrow-up-from-ground-water.svg new file mode 100644 index 0000000..8a0b9db --- /dev/null +++ b/apps/builder/public/icons/arrow-up-from-ground-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-from-water-pump.svg b/apps/builder/public/icons/arrow-up-from-water-pump.svg new file mode 100644 index 0000000..9690f4d --- /dev/null +++ b/apps/builder/public/icons/arrow-up-from-water-pump.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-long.svg b/apps/builder/public/icons/arrow-up-long.svg new file mode 100644 index 0000000..a7fec95 --- /dev/null +++ b/apps/builder/public/icons/arrow-up-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-right-dots.svg b/apps/builder/public/icons/arrow-up-right-dots.svg new file mode 100644 index 0000000..09c2d5d --- /dev/null +++ b/apps/builder/public/icons/arrow-up-right-dots.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-right-from-square.svg b/apps/builder/public/icons/arrow-up-right-from-square.svg new file mode 100644 index 0000000..1a529a8 --- /dev/null +++ b/apps/builder/public/icons/arrow-up-right-from-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-short-wide.svg b/apps/builder/public/icons/arrow-up-short-wide.svg new file mode 100644 index 0000000..6cc8809 --- /dev/null +++ b/apps/builder/public/icons/arrow-up-short-wide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-wide-short.svg b/apps/builder/public/icons/arrow-up-wide-short.svg new file mode 100644 index 0000000..bb75f8b --- /dev/null +++ b/apps/builder/public/icons/arrow-up-wide-short.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up-z-a.svg b/apps/builder/public/icons/arrow-up-z-a.svg new file mode 100644 index 0000000..4db6fde --- /dev/null +++ b/apps/builder/public/icons/arrow-up-z-a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrow-up.svg b/apps/builder/public/icons/arrow-up.svg new file mode 100644 index 0000000..a93e5d4 --- /dev/null +++ b/apps/builder/public/icons/arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-down-to-line.svg b/apps/builder/public/icons/arrows-down-to-line.svg new file mode 100644 index 0000000..4097d6a --- /dev/null +++ b/apps/builder/public/icons/arrows-down-to-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-down-to-people.svg b/apps/builder/public/icons/arrows-down-to-people.svg new file mode 100644 index 0000000..3c5b4c8 --- /dev/null +++ b/apps/builder/public/icons/arrows-down-to-people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-left-right-to-line.svg b/apps/builder/public/icons/arrows-left-right-to-line.svg new file mode 100644 index 0000000..c9a0c9a --- /dev/null +++ b/apps/builder/public/icons/arrows-left-right-to-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-left-right.svg b/apps/builder/public/icons/arrows-left-right.svg new file mode 100644 index 0000000..3b55212 --- /dev/null +++ b/apps/builder/public/icons/arrows-left-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-rotate.svg b/apps/builder/public/icons/arrows-rotate.svg new file mode 100644 index 0000000..4bb19a8 --- /dev/null +++ b/apps/builder/public/icons/arrows-rotate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-spin.svg b/apps/builder/public/icons/arrows-spin.svg new file mode 100644 index 0000000..fa6eb05 --- /dev/null +++ b/apps/builder/public/icons/arrows-spin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-split-up-and-left.svg b/apps/builder/public/icons/arrows-split-up-and-left.svg new file mode 100644 index 0000000..e5cdfd0 --- /dev/null +++ b/apps/builder/public/icons/arrows-split-up-and-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-to-circle.svg b/apps/builder/public/icons/arrows-to-circle.svg new file mode 100644 index 0000000..be13ac6 --- /dev/null +++ b/apps/builder/public/icons/arrows-to-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-to-dot.svg b/apps/builder/public/icons/arrows-to-dot.svg new file mode 100644 index 0000000..c0508af --- /dev/null +++ b/apps/builder/public/icons/arrows-to-dot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-to-eye.svg b/apps/builder/public/icons/arrows-to-eye.svg new file mode 100644 index 0000000..09463f2 --- /dev/null +++ b/apps/builder/public/icons/arrows-to-eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-turn-right.svg b/apps/builder/public/icons/arrows-turn-right.svg new file mode 100644 index 0000000..11b363a --- /dev/null +++ b/apps/builder/public/icons/arrows-turn-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-turn-to-dots.svg b/apps/builder/public/icons/arrows-turn-to-dots.svg new file mode 100644 index 0000000..17cb35a --- /dev/null +++ b/apps/builder/public/icons/arrows-turn-to-dots.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-up-down-left-right.svg b/apps/builder/public/icons/arrows-up-down-left-right.svg new file mode 100644 index 0000000..4fca5d4 --- /dev/null +++ b/apps/builder/public/icons/arrows-up-down-left-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-up-down.svg b/apps/builder/public/icons/arrows-up-down.svg new file mode 100644 index 0000000..551ef68 --- /dev/null +++ b/apps/builder/public/icons/arrows-up-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/arrows-up-to-line.svg b/apps/builder/public/icons/arrows-up-to-line.svg new file mode 100644 index 0000000..f49281e --- /dev/null +++ b/apps/builder/public/icons/arrows-up-to-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/asterisk.svg b/apps/builder/public/icons/asterisk.svg new file mode 100644 index 0000000..d8e1834 --- /dev/null +++ b/apps/builder/public/icons/asterisk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/at.svg b/apps/builder/public/icons/at.svg new file mode 100644 index 0000000..7c7be16 --- /dev/null +++ b/apps/builder/public/icons/at.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/atom.svg b/apps/builder/public/icons/atom.svg new file mode 100644 index 0000000..7293dc2 --- /dev/null +++ b/apps/builder/public/icons/atom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/audio-description.svg b/apps/builder/public/icons/audio-description.svg new file mode 100644 index 0000000..4de3cdb --- /dev/null +++ b/apps/builder/public/icons/audio-description.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/austral-sign.svg b/apps/builder/public/icons/austral-sign.svg new file mode 100644 index 0000000..77d647b --- /dev/null +++ b/apps/builder/public/icons/austral-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/award.svg b/apps/builder/public/icons/award.svg new file mode 100644 index 0000000..82c5ee6 --- /dev/null +++ b/apps/builder/public/icons/award.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/b.svg b/apps/builder/public/icons/b.svg new file mode 100644 index 0000000..44f0481 --- /dev/null +++ b/apps/builder/public/icons/b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/baby-carriage.svg b/apps/builder/public/icons/baby-carriage.svg new file mode 100644 index 0000000..472e2ca --- /dev/null +++ b/apps/builder/public/icons/baby-carriage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/baby.svg b/apps/builder/public/icons/baby.svg new file mode 100644 index 0000000..516a92e --- /dev/null +++ b/apps/builder/public/icons/baby.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/backward-fast.svg b/apps/builder/public/icons/backward-fast.svg new file mode 100644 index 0000000..2a5c1e6 --- /dev/null +++ b/apps/builder/public/icons/backward-fast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/backward-step.svg b/apps/builder/public/icons/backward-step.svg new file mode 100644 index 0000000..b96dbc7 --- /dev/null +++ b/apps/builder/public/icons/backward-step.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/backward.svg b/apps/builder/public/icons/backward.svg new file mode 100644 index 0000000..2237008 --- /dev/null +++ b/apps/builder/public/icons/backward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bacon.svg b/apps/builder/public/icons/bacon.svg new file mode 100644 index 0000000..5819e37 --- /dev/null +++ b/apps/builder/public/icons/bacon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bacteria.svg b/apps/builder/public/icons/bacteria.svg new file mode 100644 index 0000000..2f6b6db --- /dev/null +++ b/apps/builder/public/icons/bacteria.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bacterium.svg b/apps/builder/public/icons/bacterium.svg new file mode 100644 index 0000000..3664428 --- /dev/null +++ b/apps/builder/public/icons/bacterium.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bag-shopping.svg b/apps/builder/public/icons/bag-shopping.svg new file mode 100644 index 0000000..469b1c6 --- /dev/null +++ b/apps/builder/public/icons/bag-shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bahai.svg b/apps/builder/public/icons/bahai.svg new file mode 100644 index 0000000..60f074e --- /dev/null +++ b/apps/builder/public/icons/bahai.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/baht-sign.svg b/apps/builder/public/icons/baht-sign.svg new file mode 100644 index 0000000..acba371 --- /dev/null +++ b/apps/builder/public/icons/baht-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ban-smoking.svg b/apps/builder/public/icons/ban-smoking.svg new file mode 100644 index 0000000..79da86f --- /dev/null +++ b/apps/builder/public/icons/ban-smoking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ban.svg b/apps/builder/public/icons/ban.svg new file mode 100644 index 0000000..0d3c748 --- /dev/null +++ b/apps/builder/public/icons/ban.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bandage.svg b/apps/builder/public/icons/bandage.svg new file mode 100644 index 0000000..9711381 --- /dev/null +++ b/apps/builder/public/icons/bandage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bangladeshi-taka-sign.svg b/apps/builder/public/icons/bangladeshi-taka-sign.svg new file mode 100644 index 0000000..15a5ca6 --- /dev/null +++ b/apps/builder/public/icons/bangladeshi-taka-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/barcode.svg b/apps/builder/public/icons/barcode.svg new file mode 100644 index 0000000..c4c78ec --- /dev/null +++ b/apps/builder/public/icons/barcode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bars-progress.svg b/apps/builder/public/icons/bars-progress.svg new file mode 100644 index 0000000..d0f83c5 --- /dev/null +++ b/apps/builder/public/icons/bars-progress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bars-staggered.svg b/apps/builder/public/icons/bars-staggered.svg new file mode 100644 index 0000000..b6a203a --- /dev/null +++ b/apps/builder/public/icons/bars-staggered.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bars.svg b/apps/builder/public/icons/bars.svg new file mode 100644 index 0000000..8260b5e --- /dev/null +++ b/apps/builder/public/icons/bars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/baseball-bat-ball.svg b/apps/builder/public/icons/baseball-bat-ball.svg new file mode 100644 index 0000000..2afa230 --- /dev/null +++ b/apps/builder/public/icons/baseball-bat-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/baseball.svg b/apps/builder/public/icons/baseball.svg new file mode 100644 index 0000000..e1bfc9d --- /dev/null +++ b/apps/builder/public/icons/baseball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/basket-shopping.svg b/apps/builder/public/icons/basket-shopping.svg new file mode 100644 index 0000000..1b6bac3 --- /dev/null +++ b/apps/builder/public/icons/basket-shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/basketball.svg b/apps/builder/public/icons/basketball.svg new file mode 100644 index 0000000..12a12bd --- /dev/null +++ b/apps/builder/public/icons/basketball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bath.svg b/apps/builder/public/icons/bath.svg new file mode 100644 index 0000000..7fcb850 --- /dev/null +++ b/apps/builder/public/icons/bath.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/battery-empty.svg b/apps/builder/public/icons/battery-empty.svg new file mode 100644 index 0000000..0e2ee0c --- /dev/null +++ b/apps/builder/public/icons/battery-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/battery-full.svg b/apps/builder/public/icons/battery-full.svg new file mode 100644 index 0000000..9bafeeb --- /dev/null +++ b/apps/builder/public/icons/battery-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/battery-half.svg b/apps/builder/public/icons/battery-half.svg new file mode 100644 index 0000000..363b41f --- /dev/null +++ b/apps/builder/public/icons/battery-half.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/battery-quarter.svg b/apps/builder/public/icons/battery-quarter.svg new file mode 100644 index 0000000..525812d --- /dev/null +++ b/apps/builder/public/icons/battery-quarter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/battery-three-quarters.svg b/apps/builder/public/icons/battery-three-quarters.svg new file mode 100644 index 0000000..d09b55a --- /dev/null +++ b/apps/builder/public/icons/battery-three-quarters.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bed-pulse.svg b/apps/builder/public/icons/bed-pulse.svg new file mode 100644 index 0000000..033e0b4 --- /dev/null +++ b/apps/builder/public/icons/bed-pulse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bed.svg b/apps/builder/public/icons/bed.svg new file mode 100644 index 0000000..eb09e1f --- /dev/null +++ b/apps/builder/public/icons/bed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/beer-mug-empty.svg b/apps/builder/public/icons/beer-mug-empty.svg new file mode 100644 index 0000000..504257e --- /dev/null +++ b/apps/builder/public/icons/beer-mug-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bell-concierge.svg b/apps/builder/public/icons/bell-concierge.svg new file mode 100644 index 0000000..cddb249 --- /dev/null +++ b/apps/builder/public/icons/bell-concierge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bell-slash.svg b/apps/builder/public/icons/bell-slash.svg new file mode 100644 index 0000000..dc82948 --- /dev/null +++ b/apps/builder/public/icons/bell-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bell.svg b/apps/builder/public/icons/bell.svg new file mode 100644 index 0000000..dd2bfd0 --- /dev/null +++ b/apps/builder/public/icons/bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bezier-curve.svg b/apps/builder/public/icons/bezier-curve.svg new file mode 100644 index 0000000..50c40c3 --- /dev/null +++ b/apps/builder/public/icons/bezier-curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bicycle.svg b/apps/builder/public/icons/bicycle.svg new file mode 100644 index 0000000..74a61f1 --- /dev/null +++ b/apps/builder/public/icons/bicycle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/binoculars.svg b/apps/builder/public/icons/binoculars.svg new file mode 100644 index 0000000..b03930f --- /dev/null +++ b/apps/builder/public/icons/binoculars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/biohazard.svg b/apps/builder/public/icons/biohazard.svg new file mode 100644 index 0000000..7f1c19f --- /dev/null +++ b/apps/builder/public/icons/biohazard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bitcoin-sign.svg b/apps/builder/public/icons/bitcoin-sign.svg new file mode 100644 index 0000000..3c36a51 --- /dev/null +++ b/apps/builder/public/icons/bitcoin-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/blender-phone.svg b/apps/builder/public/icons/blender-phone.svg new file mode 100644 index 0000000..f877db0 --- /dev/null +++ b/apps/builder/public/icons/blender-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/blender.svg b/apps/builder/public/icons/blender.svg new file mode 100644 index 0000000..865caa5 --- /dev/null +++ b/apps/builder/public/icons/blender.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/blog.svg b/apps/builder/public/icons/blog.svg new file mode 100644 index 0000000..1a31b0f --- /dev/null +++ b/apps/builder/public/icons/blog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bold.svg b/apps/builder/public/icons/bold.svg new file mode 100644 index 0000000..e1e00fd --- /dev/null +++ b/apps/builder/public/icons/bold.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bolt-lightning.svg b/apps/builder/public/icons/bolt-lightning.svg new file mode 100644 index 0000000..72e7d3a --- /dev/null +++ b/apps/builder/public/icons/bolt-lightning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bolt.svg b/apps/builder/public/icons/bolt.svg new file mode 100644 index 0000000..d855bb9 --- /dev/null +++ b/apps/builder/public/icons/bolt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bomb.svg b/apps/builder/public/icons/bomb.svg new file mode 100644 index 0000000..9432816 --- /dev/null +++ b/apps/builder/public/icons/bomb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bone.svg b/apps/builder/public/icons/bone.svg new file mode 100644 index 0000000..d9e2971 --- /dev/null +++ b/apps/builder/public/icons/bone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bong.svg b/apps/builder/public/icons/bong.svg new file mode 100644 index 0000000..10482f7 --- /dev/null +++ b/apps/builder/public/icons/bong.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-atlas.svg b/apps/builder/public/icons/book-atlas.svg new file mode 100644 index 0000000..1588163 --- /dev/null +++ b/apps/builder/public/icons/book-atlas.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-bible.svg b/apps/builder/public/icons/book-bible.svg new file mode 100644 index 0000000..30f0cfb --- /dev/null +++ b/apps/builder/public/icons/book-bible.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-bookmark.svg b/apps/builder/public/icons/book-bookmark.svg new file mode 100644 index 0000000..94aa93f --- /dev/null +++ b/apps/builder/public/icons/book-bookmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-journal-whills.svg b/apps/builder/public/icons/book-journal-whills.svg new file mode 100644 index 0000000..27cee03 --- /dev/null +++ b/apps/builder/public/icons/book-journal-whills.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-medical.svg b/apps/builder/public/icons/book-medical.svg new file mode 100644 index 0000000..74c2991 --- /dev/null +++ b/apps/builder/public/icons/book-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-open-reader.svg b/apps/builder/public/icons/book-open-reader.svg new file mode 100644 index 0000000..949d342 --- /dev/null +++ b/apps/builder/public/icons/book-open-reader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-open.svg b/apps/builder/public/icons/book-open.svg new file mode 100644 index 0000000..af60ed8 --- /dev/null +++ b/apps/builder/public/icons/book-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-quran.svg b/apps/builder/public/icons/book-quran.svg new file mode 100644 index 0000000..ae61f10 --- /dev/null +++ b/apps/builder/public/icons/book-quran.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-skull.svg b/apps/builder/public/icons/book-skull.svg new file mode 100644 index 0000000..d04b169 --- /dev/null +++ b/apps/builder/public/icons/book-skull.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book-tanakh.svg b/apps/builder/public/icons/book-tanakh.svg new file mode 100644 index 0000000..9d46cd4 --- /dev/null +++ b/apps/builder/public/icons/book-tanakh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/book.svg b/apps/builder/public/icons/book.svg new file mode 100644 index 0000000..a1917ef --- /dev/null +++ b/apps/builder/public/icons/book.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bookmark.svg b/apps/builder/public/icons/bookmark.svg new file mode 100644 index 0000000..ebb8e9b --- /dev/null +++ b/apps/builder/public/icons/bookmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/border-all.svg b/apps/builder/public/icons/border-all.svg new file mode 100644 index 0000000..7ae83a8 --- /dev/null +++ b/apps/builder/public/icons/border-all.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/border-none.svg b/apps/builder/public/icons/border-none.svg new file mode 100644 index 0000000..eb0f29d --- /dev/null +++ b/apps/builder/public/icons/border-none.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/border-top-left.svg b/apps/builder/public/icons/border-top-left.svg new file mode 100644 index 0000000..f32d8d7 --- /dev/null +++ b/apps/builder/public/icons/border-top-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bore-hole.svg b/apps/builder/public/icons/bore-hole.svg new file mode 100644 index 0000000..50c7069 --- /dev/null +++ b/apps/builder/public/icons/bore-hole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bottle-droplet.svg b/apps/builder/public/icons/bottle-droplet.svg new file mode 100644 index 0000000..2d7cb4a --- /dev/null +++ b/apps/builder/public/icons/bottle-droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bottle-water.svg b/apps/builder/public/icons/bottle-water.svg new file mode 100644 index 0000000..99dde00 --- /dev/null +++ b/apps/builder/public/icons/bottle-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bowl-food.svg b/apps/builder/public/icons/bowl-food.svg new file mode 100644 index 0000000..29f9143 --- /dev/null +++ b/apps/builder/public/icons/bowl-food.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bowl-rice.svg b/apps/builder/public/icons/bowl-rice.svg new file mode 100644 index 0000000..3740b1e --- /dev/null +++ b/apps/builder/public/icons/bowl-rice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bowling-ball.svg b/apps/builder/public/icons/bowling-ball.svg new file mode 100644 index 0000000..8f2b8bb --- /dev/null +++ b/apps/builder/public/icons/bowling-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/box-archive.svg b/apps/builder/public/icons/box-archive.svg new file mode 100644 index 0000000..5235b12 --- /dev/null +++ b/apps/builder/public/icons/box-archive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/box-open.svg b/apps/builder/public/icons/box-open.svg new file mode 100644 index 0000000..7f2a5c6 --- /dev/null +++ b/apps/builder/public/icons/box-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/box-tissue.svg b/apps/builder/public/icons/box-tissue.svg new file mode 100644 index 0000000..4a106fa --- /dev/null +++ b/apps/builder/public/icons/box-tissue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/box.svg b/apps/builder/public/icons/box.svg new file mode 100644 index 0000000..639ecd8 --- /dev/null +++ b/apps/builder/public/icons/box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/boxes-packing.svg b/apps/builder/public/icons/boxes-packing.svg new file mode 100644 index 0000000..3aa06f3 --- /dev/null +++ b/apps/builder/public/icons/boxes-packing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/boxes-stacked.svg b/apps/builder/public/icons/boxes-stacked.svg new file mode 100644 index 0000000..3b60390 --- /dev/null +++ b/apps/builder/public/icons/boxes-stacked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/braille.svg b/apps/builder/public/icons/braille.svg new file mode 100644 index 0000000..b012e81 --- /dev/null +++ b/apps/builder/public/icons/braille.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/brain.svg b/apps/builder/public/icons/brain.svg new file mode 100644 index 0000000..a19e239 --- /dev/null +++ b/apps/builder/public/icons/brain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/brazilian-real-sign.svg b/apps/builder/public/icons/brazilian-real-sign.svg new file mode 100644 index 0000000..c4fe6b1 --- /dev/null +++ b/apps/builder/public/icons/brazilian-real-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bread-slice.svg b/apps/builder/public/icons/bread-slice.svg new file mode 100644 index 0000000..dea35cf --- /dev/null +++ b/apps/builder/public/icons/bread-slice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge-circle-check.svg b/apps/builder/public/icons/bridge-circle-check.svg new file mode 100644 index 0000000..fb00496 --- /dev/null +++ b/apps/builder/public/icons/bridge-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge-circle-exclamation.svg b/apps/builder/public/icons/bridge-circle-exclamation.svg new file mode 100644 index 0000000..6f2a07f --- /dev/null +++ b/apps/builder/public/icons/bridge-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge-circle-xmark.svg b/apps/builder/public/icons/bridge-circle-xmark.svg new file mode 100644 index 0000000..f7b41f0 --- /dev/null +++ b/apps/builder/public/icons/bridge-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge-lock.svg b/apps/builder/public/icons/bridge-lock.svg new file mode 100644 index 0000000..540079f --- /dev/null +++ b/apps/builder/public/icons/bridge-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge-water.svg b/apps/builder/public/icons/bridge-water.svg new file mode 100644 index 0000000..f732063 --- /dev/null +++ b/apps/builder/public/icons/bridge-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bridge.svg b/apps/builder/public/icons/bridge.svg new file mode 100644 index 0000000..7662df5 --- /dev/null +++ b/apps/builder/public/icons/bridge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/briefcase-medical.svg b/apps/builder/public/icons/briefcase-medical.svg new file mode 100644 index 0000000..5a00302 --- /dev/null +++ b/apps/builder/public/icons/briefcase-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/briefcase.svg b/apps/builder/public/icons/briefcase.svg new file mode 100644 index 0000000..3d64251 --- /dev/null +++ b/apps/builder/public/icons/briefcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/broom-ball.svg b/apps/builder/public/icons/broom-ball.svg new file mode 100644 index 0000000..84ca1fa --- /dev/null +++ b/apps/builder/public/icons/broom-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/broom.svg b/apps/builder/public/icons/broom.svg new file mode 100644 index 0000000..07f74e8 --- /dev/null +++ b/apps/builder/public/icons/broom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/brush.svg b/apps/builder/public/icons/brush.svg new file mode 100644 index 0000000..105e245 --- /dev/null +++ b/apps/builder/public/icons/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bucket.svg b/apps/builder/public/icons/bucket.svg new file mode 100644 index 0000000..97e153c --- /dev/null +++ b/apps/builder/public/icons/bucket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bug-slash.svg b/apps/builder/public/icons/bug-slash.svg new file mode 100644 index 0000000..9b04a87 --- /dev/null +++ b/apps/builder/public/icons/bug-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bug.svg b/apps/builder/public/icons/bug.svg new file mode 100644 index 0000000..b5c1667 --- /dev/null +++ b/apps/builder/public/icons/bug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bugs.svg b/apps/builder/public/icons/bugs.svg new file mode 100644 index 0000000..3a502fe --- /dev/null +++ b/apps/builder/public/icons/bugs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-circle-arrow-right.svg b/apps/builder/public/icons/building-circle-arrow-right.svg new file mode 100644 index 0000000..6e63de7 --- /dev/null +++ b/apps/builder/public/icons/building-circle-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-circle-check.svg b/apps/builder/public/icons/building-circle-check.svg new file mode 100644 index 0000000..bdee3c8 --- /dev/null +++ b/apps/builder/public/icons/building-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-circle-exclamation.svg b/apps/builder/public/icons/building-circle-exclamation.svg new file mode 100644 index 0000000..3e7ac40 --- /dev/null +++ b/apps/builder/public/icons/building-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-circle-xmark.svg b/apps/builder/public/icons/building-circle-xmark.svg new file mode 100644 index 0000000..a52db42 --- /dev/null +++ b/apps/builder/public/icons/building-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-columns.svg b/apps/builder/public/icons/building-columns.svg new file mode 100644 index 0000000..ebc7aac --- /dev/null +++ b/apps/builder/public/icons/building-columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-flag.svg b/apps/builder/public/icons/building-flag.svg new file mode 100644 index 0000000..f111a11 --- /dev/null +++ b/apps/builder/public/icons/building-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-lock.svg b/apps/builder/public/icons/building-lock.svg new file mode 100644 index 0000000..99bd44b --- /dev/null +++ b/apps/builder/public/icons/building-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-ngo.svg b/apps/builder/public/icons/building-ngo.svg new file mode 100644 index 0000000..ab3ed10 --- /dev/null +++ b/apps/builder/public/icons/building-ngo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-shield.svg b/apps/builder/public/icons/building-shield.svg new file mode 100644 index 0000000..2212afb --- /dev/null +++ b/apps/builder/public/icons/building-shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-un.svg b/apps/builder/public/icons/building-un.svg new file mode 100644 index 0000000..b900b6f --- /dev/null +++ b/apps/builder/public/icons/building-un.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-user.svg b/apps/builder/public/icons/building-user.svg new file mode 100644 index 0000000..f30fb62 --- /dev/null +++ b/apps/builder/public/icons/building-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building-wheat.svg b/apps/builder/public/icons/building-wheat.svg new file mode 100644 index 0000000..d6b6397 --- /dev/null +++ b/apps/builder/public/icons/building-wheat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/building.svg b/apps/builder/public/icons/building.svg new file mode 100644 index 0000000..83e7231 --- /dev/null +++ b/apps/builder/public/icons/building.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bullhorn.svg b/apps/builder/public/icons/bullhorn.svg new file mode 100644 index 0000000..ae18dee --- /dev/null +++ b/apps/builder/public/icons/bullhorn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bullseye.svg b/apps/builder/public/icons/bullseye.svg new file mode 100644 index 0000000..466cf4b --- /dev/null +++ b/apps/builder/public/icons/bullseye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/burger.svg b/apps/builder/public/icons/burger.svg new file mode 100644 index 0000000..ef6a2e7 --- /dev/null +++ b/apps/builder/public/icons/burger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/burst.svg b/apps/builder/public/icons/burst.svg new file mode 100644 index 0000000..d3806e3 --- /dev/null +++ b/apps/builder/public/icons/burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bus-simple.svg b/apps/builder/public/icons/bus-simple.svg new file mode 100644 index 0000000..1d4fd5e --- /dev/null +++ b/apps/builder/public/icons/bus-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/bus.svg b/apps/builder/public/icons/bus.svg new file mode 100644 index 0000000..25164ca --- /dev/null +++ b/apps/builder/public/icons/bus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/business-time.svg b/apps/builder/public/icons/business-time.svg new file mode 100644 index 0000000..1e7c361 --- /dev/null +++ b/apps/builder/public/icons/business-time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/c.svg b/apps/builder/public/icons/c.svg new file mode 100644 index 0000000..4759c6e --- /dev/null +++ b/apps/builder/public/icons/c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cable-car.svg b/apps/builder/public/icons/cable-car.svg new file mode 100644 index 0000000..f39b01e --- /dev/null +++ b/apps/builder/public/icons/cable-car.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cake-candles.svg b/apps/builder/public/icons/cake-candles.svg new file mode 100644 index 0000000..806e7cd --- /dev/null +++ b/apps/builder/public/icons/cake-candles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calculator.svg b/apps/builder/public/icons/calculator.svg new file mode 100644 index 0000000..d14fb2f --- /dev/null +++ b/apps/builder/public/icons/calculator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-check.svg b/apps/builder/public/icons/calendar-check.svg new file mode 100644 index 0000000..511525d --- /dev/null +++ b/apps/builder/public/icons/calendar-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-day.svg b/apps/builder/public/icons/calendar-day.svg new file mode 100644 index 0000000..a8d60e2 --- /dev/null +++ b/apps/builder/public/icons/calendar-day.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-days.svg b/apps/builder/public/icons/calendar-days.svg new file mode 100644 index 0000000..99d77cb --- /dev/null +++ b/apps/builder/public/icons/calendar-days.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-minus.svg b/apps/builder/public/icons/calendar-minus.svg new file mode 100644 index 0000000..32002e2 --- /dev/null +++ b/apps/builder/public/icons/calendar-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-plus.svg b/apps/builder/public/icons/calendar-plus.svg new file mode 100644 index 0000000..d9bc44d --- /dev/null +++ b/apps/builder/public/icons/calendar-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-week.svg b/apps/builder/public/icons/calendar-week.svg new file mode 100644 index 0000000..e889186 --- /dev/null +++ b/apps/builder/public/icons/calendar-week.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar-xmark.svg b/apps/builder/public/icons/calendar-xmark.svg new file mode 100644 index 0000000..f5cf63e --- /dev/null +++ b/apps/builder/public/icons/calendar-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/calendar.svg b/apps/builder/public/icons/calendar.svg new file mode 100644 index 0000000..6907e96 --- /dev/null +++ b/apps/builder/public/icons/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/camera-retro.svg b/apps/builder/public/icons/camera-retro.svg new file mode 100644 index 0000000..c55742d --- /dev/null +++ b/apps/builder/public/icons/camera-retro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/camera-rotate.svg b/apps/builder/public/icons/camera-rotate.svg new file mode 100644 index 0000000..208e151 --- /dev/null +++ b/apps/builder/public/icons/camera-rotate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/camera.svg b/apps/builder/public/icons/camera.svg new file mode 100644 index 0000000..8b4b1e1 --- /dev/null +++ b/apps/builder/public/icons/camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/campground.svg b/apps/builder/public/icons/campground.svg new file mode 100644 index 0000000..37289aa --- /dev/null +++ b/apps/builder/public/icons/campground.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/candy-cane.svg b/apps/builder/public/icons/candy-cane.svg new file mode 100644 index 0000000..784dc15 --- /dev/null +++ b/apps/builder/public/icons/candy-cane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cannabis.svg b/apps/builder/public/icons/cannabis.svg new file mode 100644 index 0000000..ae18275 --- /dev/null +++ b/apps/builder/public/icons/cannabis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/capsules.svg b/apps/builder/public/icons/capsules.svg new file mode 100644 index 0000000..8c27060 --- /dev/null +++ b/apps/builder/public/icons/capsules.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-battery.svg b/apps/builder/public/icons/car-battery.svg new file mode 100644 index 0000000..748d5a1 --- /dev/null +++ b/apps/builder/public/icons/car-battery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-burst.svg b/apps/builder/public/icons/car-burst.svg new file mode 100644 index 0000000..8e0223c --- /dev/null +++ b/apps/builder/public/icons/car-burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-on.svg b/apps/builder/public/icons/car-on.svg new file mode 100644 index 0000000..316ca9d --- /dev/null +++ b/apps/builder/public/icons/car-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-rear.svg b/apps/builder/public/icons/car-rear.svg new file mode 100644 index 0000000..73c92c4 --- /dev/null +++ b/apps/builder/public/icons/car-rear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-side.svg b/apps/builder/public/icons/car-side.svg new file mode 100644 index 0000000..a854a62 --- /dev/null +++ b/apps/builder/public/icons/car-side.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car-tunnel.svg b/apps/builder/public/icons/car-tunnel.svg new file mode 100644 index 0000000..a7151fe --- /dev/null +++ b/apps/builder/public/icons/car-tunnel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/car.svg b/apps/builder/public/icons/car.svg new file mode 100644 index 0000000..63314c0 --- /dev/null +++ b/apps/builder/public/icons/car.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/caravan.svg b/apps/builder/public/icons/caravan.svg new file mode 100644 index 0000000..906f922 --- /dev/null +++ b/apps/builder/public/icons/caravan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/caret-down.svg b/apps/builder/public/icons/caret-down.svg new file mode 100644 index 0000000..1833ee3 --- /dev/null +++ b/apps/builder/public/icons/caret-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/caret-left.svg b/apps/builder/public/icons/caret-left.svg new file mode 100644 index 0000000..44cb4e2 --- /dev/null +++ b/apps/builder/public/icons/caret-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/caret-right.svg b/apps/builder/public/icons/caret-right.svg new file mode 100644 index 0000000..6885065 --- /dev/null +++ b/apps/builder/public/icons/caret-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/caret-up.svg b/apps/builder/public/icons/caret-up.svg new file mode 100644 index 0000000..181f746 --- /dev/null +++ b/apps/builder/public/icons/caret-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/carrot.svg b/apps/builder/public/icons/carrot.svg new file mode 100644 index 0000000..3d18fc9 --- /dev/null +++ b/apps/builder/public/icons/carrot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cart-arrow-down.svg b/apps/builder/public/icons/cart-arrow-down.svg new file mode 100644 index 0000000..2983380 --- /dev/null +++ b/apps/builder/public/icons/cart-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cart-flatbed-suitcase.svg b/apps/builder/public/icons/cart-flatbed-suitcase.svg new file mode 100644 index 0000000..1e04b2c --- /dev/null +++ b/apps/builder/public/icons/cart-flatbed-suitcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cart-flatbed.svg b/apps/builder/public/icons/cart-flatbed.svg new file mode 100644 index 0000000..9c4b183 --- /dev/null +++ b/apps/builder/public/icons/cart-flatbed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cart-plus.svg b/apps/builder/public/icons/cart-plus.svg new file mode 100644 index 0000000..4717bea --- /dev/null +++ b/apps/builder/public/icons/cart-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cart-shopping.svg b/apps/builder/public/icons/cart-shopping.svg new file mode 100644 index 0000000..1f35623 --- /dev/null +++ b/apps/builder/public/icons/cart-shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cash-register.svg b/apps/builder/public/icons/cash-register.svg new file mode 100644 index 0000000..feef82e --- /dev/null +++ b/apps/builder/public/icons/cash-register.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cat.svg b/apps/builder/public/icons/cat.svg new file mode 100644 index 0000000..365105c --- /dev/null +++ b/apps/builder/public/icons/cat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cedi-sign.svg b/apps/builder/public/icons/cedi-sign.svg new file mode 100644 index 0000000..b72cad3 --- /dev/null +++ b/apps/builder/public/icons/cedi-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cent-sign.svg b/apps/builder/public/icons/cent-sign.svg new file mode 100644 index 0000000..340b8df --- /dev/null +++ b/apps/builder/public/icons/cent-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/certificate.svg b/apps/builder/public/icons/certificate.svg new file mode 100644 index 0000000..39b6072 --- /dev/null +++ b/apps/builder/public/icons/certificate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chair.svg b/apps/builder/public/icons/chair.svg new file mode 100644 index 0000000..9b357ac --- /dev/null +++ b/apps/builder/public/icons/chair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chalkboard-user.svg b/apps/builder/public/icons/chalkboard-user.svg new file mode 100644 index 0000000..a5c0ae6 --- /dev/null +++ b/apps/builder/public/icons/chalkboard-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chalkboard.svg b/apps/builder/public/icons/chalkboard.svg new file mode 100644 index 0000000..2a2e9c9 --- /dev/null +++ b/apps/builder/public/icons/chalkboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/champagne-glasses.svg b/apps/builder/public/icons/champagne-glasses.svg new file mode 100644 index 0000000..877c6fc --- /dev/null +++ b/apps/builder/public/icons/champagne-glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/charging-station.svg b/apps/builder/public/icons/charging-station.svg new file mode 100644 index 0000000..d98fe17 --- /dev/null +++ b/apps/builder/public/icons/charging-station.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-area.svg b/apps/builder/public/icons/chart-area.svg new file mode 100644 index 0000000..aee66f6 --- /dev/null +++ b/apps/builder/public/icons/chart-area.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-bar.svg b/apps/builder/public/icons/chart-bar.svg new file mode 100644 index 0000000..fc54d82 --- /dev/null +++ b/apps/builder/public/icons/chart-bar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-column.svg b/apps/builder/public/icons/chart-column.svg new file mode 100644 index 0000000..eacbb3e --- /dev/null +++ b/apps/builder/public/icons/chart-column.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-gantt.svg b/apps/builder/public/icons/chart-gantt.svg new file mode 100644 index 0000000..fe80dcc --- /dev/null +++ b/apps/builder/public/icons/chart-gantt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-line.svg b/apps/builder/public/icons/chart-line.svg new file mode 100644 index 0000000..f082952 --- /dev/null +++ b/apps/builder/public/icons/chart-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-pie.svg b/apps/builder/public/icons/chart-pie.svg new file mode 100644 index 0000000..49edb09 --- /dev/null +++ b/apps/builder/public/icons/chart-pie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chart-simple.svg b/apps/builder/public/icons/chart-simple.svg new file mode 100644 index 0000000..51a80fc --- /dev/null +++ b/apps/builder/public/icons/chart-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/check-double.svg b/apps/builder/public/icons/check-double.svg new file mode 100644 index 0000000..41125f2 --- /dev/null +++ b/apps/builder/public/icons/check-double.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/check-to-slot.svg b/apps/builder/public/icons/check-to-slot.svg new file mode 100644 index 0000000..e5cee03 --- /dev/null +++ b/apps/builder/public/icons/check-to-slot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/check.svg b/apps/builder/public/icons/check.svg new file mode 100644 index 0000000..c26e709 --- /dev/null +++ b/apps/builder/public/icons/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cheese.svg b/apps/builder/public/icons/cheese.svg new file mode 100644 index 0000000..13bb1b5 --- /dev/null +++ b/apps/builder/public/icons/cheese.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-bishop.svg b/apps/builder/public/icons/chess-bishop.svg new file mode 100644 index 0000000..c9c4533 --- /dev/null +++ b/apps/builder/public/icons/chess-bishop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-board.svg b/apps/builder/public/icons/chess-board.svg new file mode 100644 index 0000000..216943b --- /dev/null +++ b/apps/builder/public/icons/chess-board.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-king.svg b/apps/builder/public/icons/chess-king.svg new file mode 100644 index 0000000..5d99e75 --- /dev/null +++ b/apps/builder/public/icons/chess-king.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-knight.svg b/apps/builder/public/icons/chess-knight.svg new file mode 100644 index 0000000..d76fcd5 --- /dev/null +++ b/apps/builder/public/icons/chess-knight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-pawn.svg b/apps/builder/public/icons/chess-pawn.svg new file mode 100644 index 0000000..786f39c --- /dev/null +++ b/apps/builder/public/icons/chess-pawn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-queen.svg b/apps/builder/public/icons/chess-queen.svg new file mode 100644 index 0000000..fc4ce8e --- /dev/null +++ b/apps/builder/public/icons/chess-queen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess-rook.svg b/apps/builder/public/icons/chess-rook.svg new file mode 100644 index 0000000..58cf8fc --- /dev/null +++ b/apps/builder/public/icons/chess-rook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chess.svg b/apps/builder/public/icons/chess.svg new file mode 100644 index 0000000..ee904f9 --- /dev/null +++ b/apps/builder/public/icons/chess.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chevron-down.svg b/apps/builder/public/icons/chevron-down.svg new file mode 100644 index 0000000..f72bea9 --- /dev/null +++ b/apps/builder/public/icons/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chevron-left.svg b/apps/builder/public/icons/chevron-left.svg new file mode 100644 index 0000000..ef8e7f9 --- /dev/null +++ b/apps/builder/public/icons/chevron-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chevron-right.svg b/apps/builder/public/icons/chevron-right.svg new file mode 100644 index 0000000..00bd8e4 --- /dev/null +++ b/apps/builder/public/icons/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/chevron-up.svg b/apps/builder/public/icons/chevron-up.svg new file mode 100644 index 0000000..2778fba --- /dev/null +++ b/apps/builder/public/icons/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/child-combatant.svg b/apps/builder/public/icons/child-combatant.svg new file mode 100644 index 0000000..7afb947 --- /dev/null +++ b/apps/builder/public/icons/child-combatant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/child-dress.svg b/apps/builder/public/icons/child-dress.svg new file mode 100644 index 0000000..603fdd5 --- /dev/null +++ b/apps/builder/public/icons/child-dress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/child-reaching.svg b/apps/builder/public/icons/child-reaching.svg new file mode 100644 index 0000000..5583aa1 --- /dev/null +++ b/apps/builder/public/icons/child-reaching.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/child.svg b/apps/builder/public/icons/child.svg new file mode 100644 index 0000000..b2b32f5 --- /dev/null +++ b/apps/builder/public/icons/child.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/children.svg b/apps/builder/public/icons/children.svg new file mode 100644 index 0000000..d08a779 --- /dev/null +++ b/apps/builder/public/icons/children.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/church.svg b/apps/builder/public/icons/church.svg new file mode 100644 index 0000000..f48b231 --- /dev/null +++ b/apps/builder/public/icons/church.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-arrow-down.svg b/apps/builder/public/icons/circle-arrow-down.svg new file mode 100644 index 0000000..8cc6e47 --- /dev/null +++ b/apps/builder/public/icons/circle-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-arrow-left.svg b/apps/builder/public/icons/circle-arrow-left.svg new file mode 100644 index 0000000..8703cb6 --- /dev/null +++ b/apps/builder/public/icons/circle-arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-arrow-right.svg b/apps/builder/public/icons/circle-arrow-right.svg new file mode 100644 index 0000000..6d51ef1 --- /dev/null +++ b/apps/builder/public/icons/circle-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-arrow-up.svg b/apps/builder/public/icons/circle-arrow-up.svg new file mode 100644 index 0000000..a0537df --- /dev/null +++ b/apps/builder/public/icons/circle-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-check.svg b/apps/builder/public/icons/circle-check.svg new file mode 100644 index 0000000..7a8ecba --- /dev/null +++ b/apps/builder/public/icons/circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-chevron-down.svg b/apps/builder/public/icons/circle-chevron-down.svg new file mode 100644 index 0000000..ca86bf3 --- /dev/null +++ b/apps/builder/public/icons/circle-chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-chevron-left.svg b/apps/builder/public/icons/circle-chevron-left.svg new file mode 100644 index 0000000..b866d2a --- /dev/null +++ b/apps/builder/public/icons/circle-chevron-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-chevron-right.svg b/apps/builder/public/icons/circle-chevron-right.svg new file mode 100644 index 0000000..26e4f7d --- /dev/null +++ b/apps/builder/public/icons/circle-chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-chevron-up.svg b/apps/builder/public/icons/circle-chevron-up.svg new file mode 100644 index 0000000..b8babbe --- /dev/null +++ b/apps/builder/public/icons/circle-chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-dollar-to-slot.svg b/apps/builder/public/icons/circle-dollar-to-slot.svg new file mode 100644 index 0000000..d2bd603 --- /dev/null +++ b/apps/builder/public/icons/circle-dollar-to-slot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-dot.svg b/apps/builder/public/icons/circle-dot.svg new file mode 100644 index 0000000..3b1ebb4 --- /dev/null +++ b/apps/builder/public/icons/circle-dot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-down.svg b/apps/builder/public/icons/circle-down.svg new file mode 100644 index 0000000..a0ca434 --- /dev/null +++ b/apps/builder/public/icons/circle-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-exclamation.svg b/apps/builder/public/icons/circle-exclamation.svg new file mode 100644 index 0000000..651650d --- /dev/null +++ b/apps/builder/public/icons/circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-h.svg b/apps/builder/public/icons/circle-h.svg new file mode 100644 index 0000000..12edcb8 --- /dev/null +++ b/apps/builder/public/icons/circle-h.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-half-stroke.svg b/apps/builder/public/icons/circle-half-stroke.svg new file mode 100644 index 0000000..c156205 --- /dev/null +++ b/apps/builder/public/icons/circle-half-stroke.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-info.svg b/apps/builder/public/icons/circle-info.svg new file mode 100644 index 0000000..b798dee --- /dev/null +++ b/apps/builder/public/icons/circle-info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-left.svg b/apps/builder/public/icons/circle-left.svg new file mode 100644 index 0000000..2f48b7a --- /dev/null +++ b/apps/builder/public/icons/circle-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-minus.svg b/apps/builder/public/icons/circle-minus.svg new file mode 100644 index 0000000..0a0877d --- /dev/null +++ b/apps/builder/public/icons/circle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-nodes.svg b/apps/builder/public/icons/circle-nodes.svg new file mode 100644 index 0000000..4f1800b --- /dev/null +++ b/apps/builder/public/icons/circle-nodes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-notch.svg b/apps/builder/public/icons/circle-notch.svg new file mode 100644 index 0000000..a6ab038 --- /dev/null +++ b/apps/builder/public/icons/circle-notch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-pause.svg b/apps/builder/public/icons/circle-pause.svg new file mode 100644 index 0000000..bb46380 --- /dev/null +++ b/apps/builder/public/icons/circle-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-play.svg b/apps/builder/public/icons/circle-play.svg new file mode 100644 index 0000000..e5390a2 --- /dev/null +++ b/apps/builder/public/icons/circle-play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-plus.svg b/apps/builder/public/icons/circle-plus.svg new file mode 100644 index 0000000..aa8dded --- /dev/null +++ b/apps/builder/public/icons/circle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-question.svg b/apps/builder/public/icons/circle-question.svg new file mode 100644 index 0000000..70bb95f --- /dev/null +++ b/apps/builder/public/icons/circle-question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-radiation.svg b/apps/builder/public/icons/circle-radiation.svg new file mode 100644 index 0000000..7676b71 --- /dev/null +++ b/apps/builder/public/icons/circle-radiation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-right.svg b/apps/builder/public/icons/circle-right.svg new file mode 100644 index 0000000..6579076 --- /dev/null +++ b/apps/builder/public/icons/circle-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-stop.svg b/apps/builder/public/icons/circle-stop.svg new file mode 100644 index 0000000..d5eb4d4 --- /dev/null +++ b/apps/builder/public/icons/circle-stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-up.svg b/apps/builder/public/icons/circle-up.svg new file mode 100644 index 0000000..d17d2d9 --- /dev/null +++ b/apps/builder/public/icons/circle-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-user.svg b/apps/builder/public/icons/circle-user.svg new file mode 100644 index 0000000..98d07d7 --- /dev/null +++ b/apps/builder/public/icons/circle-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle-xmark.svg b/apps/builder/public/icons/circle-xmark.svg new file mode 100644 index 0000000..5f5fe5f --- /dev/null +++ b/apps/builder/public/icons/circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/circle.svg b/apps/builder/public/icons/circle.svg new file mode 100644 index 0000000..68dcadf --- /dev/null +++ b/apps/builder/public/icons/circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/city.svg b/apps/builder/public/icons/city.svg new file mode 100644 index 0000000..7af23d6 --- /dev/null +++ b/apps/builder/public/icons/city.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clapperboard.svg b/apps/builder/public/icons/clapperboard.svg new file mode 100644 index 0000000..4a4f54c --- /dev/null +++ b/apps/builder/public/icons/clapperboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clipboard-check.svg b/apps/builder/public/icons/clipboard-check.svg new file mode 100644 index 0000000..75142e9 --- /dev/null +++ b/apps/builder/public/icons/clipboard-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clipboard-list.svg b/apps/builder/public/icons/clipboard-list.svg new file mode 100644 index 0000000..6f458eb --- /dev/null +++ b/apps/builder/public/icons/clipboard-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clipboard-question.svg b/apps/builder/public/icons/clipboard-question.svg new file mode 100644 index 0000000..2856fdf --- /dev/null +++ b/apps/builder/public/icons/clipboard-question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clipboard-user.svg b/apps/builder/public/icons/clipboard-user.svg new file mode 100644 index 0000000..e09a866 --- /dev/null +++ b/apps/builder/public/icons/clipboard-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clipboard.svg b/apps/builder/public/icons/clipboard.svg new file mode 100644 index 0000000..3f32518 --- /dev/null +++ b/apps/builder/public/icons/clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clock-rotate-left.svg b/apps/builder/public/icons/clock-rotate-left.svg new file mode 100644 index 0000000..7422f88 --- /dev/null +++ b/apps/builder/public/icons/clock-rotate-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clock.svg b/apps/builder/public/icons/clock.svg new file mode 100644 index 0000000..042e349 --- /dev/null +++ b/apps/builder/public/icons/clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clone.svg b/apps/builder/public/icons/clone.svg new file mode 100644 index 0000000..1cea5d5 --- /dev/null +++ b/apps/builder/public/icons/clone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/closed-captioning.svg b/apps/builder/public/icons/closed-captioning.svg new file mode 100644 index 0000000..b21cba1 --- /dev/null +++ b/apps/builder/public/icons/closed-captioning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-arrow-down.svg b/apps/builder/public/icons/cloud-arrow-down.svg new file mode 100644 index 0000000..b25eeb1 --- /dev/null +++ b/apps/builder/public/icons/cloud-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-arrow-up.svg b/apps/builder/public/icons/cloud-arrow-up.svg new file mode 100644 index 0000000..40724d5 --- /dev/null +++ b/apps/builder/public/icons/cloud-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-bolt.svg b/apps/builder/public/icons/cloud-bolt.svg new file mode 100644 index 0000000..0b41cac --- /dev/null +++ b/apps/builder/public/icons/cloud-bolt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-meatball.svg b/apps/builder/public/icons/cloud-meatball.svg new file mode 100644 index 0000000..f1cd242 --- /dev/null +++ b/apps/builder/public/icons/cloud-meatball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-moon-rain.svg b/apps/builder/public/icons/cloud-moon-rain.svg new file mode 100644 index 0000000..8059d73 --- /dev/null +++ b/apps/builder/public/icons/cloud-moon-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-moon.svg b/apps/builder/public/icons/cloud-moon.svg new file mode 100644 index 0000000..2c26a33 --- /dev/null +++ b/apps/builder/public/icons/cloud-moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-rain.svg b/apps/builder/public/icons/cloud-rain.svg new file mode 100644 index 0000000..53d196a --- /dev/null +++ b/apps/builder/public/icons/cloud-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-showers-heavy.svg b/apps/builder/public/icons/cloud-showers-heavy.svg new file mode 100644 index 0000000..9ea339e --- /dev/null +++ b/apps/builder/public/icons/cloud-showers-heavy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-showers-water.svg b/apps/builder/public/icons/cloud-showers-water.svg new file mode 100644 index 0000000..d1a664b --- /dev/null +++ b/apps/builder/public/icons/cloud-showers-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-sun-rain.svg b/apps/builder/public/icons/cloud-sun-rain.svg new file mode 100644 index 0000000..0277a40 --- /dev/null +++ b/apps/builder/public/icons/cloud-sun-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud-sun.svg b/apps/builder/public/icons/cloud-sun.svg new file mode 100644 index 0000000..acd3b5d --- /dev/null +++ b/apps/builder/public/icons/cloud-sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cloud.svg b/apps/builder/public/icons/cloud.svg new file mode 100644 index 0000000..a93925e --- /dev/null +++ b/apps/builder/public/icons/cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/clover.svg b/apps/builder/public/icons/clover.svg new file mode 100644 index 0000000..ed4cd52 --- /dev/null +++ b/apps/builder/public/icons/clover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-branch.svg b/apps/builder/public/icons/code-branch.svg new file mode 100644 index 0000000..8d117e8 --- /dev/null +++ b/apps/builder/public/icons/code-branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-commit.svg b/apps/builder/public/icons/code-commit.svg new file mode 100644 index 0000000..63326b9 --- /dev/null +++ b/apps/builder/public/icons/code-commit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-compare.svg b/apps/builder/public/icons/code-compare.svg new file mode 100644 index 0000000..b354ada --- /dev/null +++ b/apps/builder/public/icons/code-compare.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-fork.svg b/apps/builder/public/icons/code-fork.svg new file mode 100644 index 0000000..a3967c1 --- /dev/null +++ b/apps/builder/public/icons/code-fork.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-merge.svg b/apps/builder/public/icons/code-merge.svg new file mode 100644 index 0000000..0df1a84 --- /dev/null +++ b/apps/builder/public/icons/code-merge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code-pull-request.svg b/apps/builder/public/icons/code-pull-request.svg new file mode 100644 index 0000000..0c4c056 --- /dev/null +++ b/apps/builder/public/icons/code-pull-request.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/code.svg b/apps/builder/public/icons/code.svg new file mode 100644 index 0000000..ec86527 --- /dev/null +++ b/apps/builder/public/icons/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/coins.svg b/apps/builder/public/icons/coins.svg new file mode 100644 index 0000000..150ae3b --- /dev/null +++ b/apps/builder/public/icons/coins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/colon-sign.svg b/apps/builder/public/icons/colon-sign.svg new file mode 100644 index 0000000..6a5d851 --- /dev/null +++ b/apps/builder/public/icons/colon-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment-dollar.svg b/apps/builder/public/icons/comment-dollar.svg new file mode 100644 index 0000000..9dc8c77 --- /dev/null +++ b/apps/builder/public/icons/comment-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment-dots.svg b/apps/builder/public/icons/comment-dots.svg new file mode 100644 index 0000000..d273fd5 --- /dev/null +++ b/apps/builder/public/icons/comment-dots.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment-medical.svg b/apps/builder/public/icons/comment-medical.svg new file mode 100644 index 0000000..b6ab775 --- /dev/null +++ b/apps/builder/public/icons/comment-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment-slash.svg b/apps/builder/public/icons/comment-slash.svg new file mode 100644 index 0000000..3a0a1b3 --- /dev/null +++ b/apps/builder/public/icons/comment-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment-sms.svg b/apps/builder/public/icons/comment-sms.svg new file mode 100644 index 0000000..088ef30 --- /dev/null +++ b/apps/builder/public/icons/comment-sms.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comment.svg b/apps/builder/public/icons/comment.svg new file mode 100644 index 0000000..4069c49 --- /dev/null +++ b/apps/builder/public/icons/comment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comments-dollar.svg b/apps/builder/public/icons/comments-dollar.svg new file mode 100644 index 0000000..05b2bc3 --- /dev/null +++ b/apps/builder/public/icons/comments-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/comments.svg b/apps/builder/public/icons/comments.svg new file mode 100644 index 0000000..f4e8e83 --- /dev/null +++ b/apps/builder/public/icons/comments.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/compact-disc.svg b/apps/builder/public/icons/compact-disc.svg new file mode 100644 index 0000000..dd622c4 --- /dev/null +++ b/apps/builder/public/icons/compact-disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/compass-drafting.svg b/apps/builder/public/icons/compass-drafting.svg new file mode 100644 index 0000000..deedf41 --- /dev/null +++ b/apps/builder/public/icons/compass-drafting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/compass.svg b/apps/builder/public/icons/compass.svg new file mode 100644 index 0000000..0f08ff4 --- /dev/null +++ b/apps/builder/public/icons/compass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/compress.svg b/apps/builder/public/icons/compress.svg new file mode 100644 index 0000000..ce80ed9 --- /dev/null +++ b/apps/builder/public/icons/compress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/computer-mouse.svg b/apps/builder/public/icons/computer-mouse.svg new file mode 100644 index 0000000..7d53181 --- /dev/null +++ b/apps/builder/public/icons/computer-mouse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/computer.svg b/apps/builder/public/icons/computer.svg new file mode 100644 index 0000000..50fc610 --- /dev/null +++ b/apps/builder/public/icons/computer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cookie-bite.svg b/apps/builder/public/icons/cookie-bite.svg new file mode 100644 index 0000000..4fb1030 --- /dev/null +++ b/apps/builder/public/icons/cookie-bite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cookie.svg b/apps/builder/public/icons/cookie.svg new file mode 100644 index 0000000..616e2f3 --- /dev/null +++ b/apps/builder/public/icons/cookie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/copy.svg b/apps/builder/public/icons/copy.svg new file mode 100644 index 0000000..17e0482 --- /dev/null +++ b/apps/builder/public/icons/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/copyright.svg b/apps/builder/public/icons/copyright.svg new file mode 100644 index 0000000..d74fa4e --- /dev/null +++ b/apps/builder/public/icons/copyright.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/couch.svg b/apps/builder/public/icons/couch.svg new file mode 100644 index 0000000..b3dd99f --- /dev/null +++ b/apps/builder/public/icons/couch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cow.svg b/apps/builder/public/icons/cow.svg new file mode 100644 index 0000000..717497d --- /dev/null +++ b/apps/builder/public/icons/cow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/credit-card.svg b/apps/builder/public/icons/credit-card.svg new file mode 100644 index 0000000..e06d6e3 --- /dev/null +++ b/apps/builder/public/icons/credit-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crop-simple.svg b/apps/builder/public/icons/crop-simple.svg new file mode 100644 index 0000000..2c64d66 --- /dev/null +++ b/apps/builder/public/icons/crop-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crop.svg b/apps/builder/public/icons/crop.svg new file mode 100644 index 0000000..5bba5f9 --- /dev/null +++ b/apps/builder/public/icons/crop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cross.svg b/apps/builder/public/icons/cross.svg new file mode 100644 index 0000000..ba59e09 --- /dev/null +++ b/apps/builder/public/icons/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crosshairs.svg b/apps/builder/public/icons/crosshairs.svg new file mode 100644 index 0000000..1163f33 --- /dev/null +++ b/apps/builder/public/icons/crosshairs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crow.svg b/apps/builder/public/icons/crow.svg new file mode 100644 index 0000000..d91f5bf --- /dev/null +++ b/apps/builder/public/icons/crow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crown.svg b/apps/builder/public/icons/crown.svg new file mode 100644 index 0000000..671ba07 --- /dev/null +++ b/apps/builder/public/icons/crown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/crutch.svg b/apps/builder/public/icons/crutch.svg new file mode 100644 index 0000000..dc2deda --- /dev/null +++ b/apps/builder/public/icons/crutch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cruzeiro-sign.svg b/apps/builder/public/icons/cruzeiro-sign.svg new file mode 100644 index 0000000..33c84ab --- /dev/null +++ b/apps/builder/public/icons/cruzeiro-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cube.svg b/apps/builder/public/icons/cube.svg new file mode 100644 index 0000000..2d75fd6 --- /dev/null +++ b/apps/builder/public/icons/cube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cubes-stacked.svg b/apps/builder/public/icons/cubes-stacked.svg new file mode 100644 index 0000000..c20cac9 --- /dev/null +++ b/apps/builder/public/icons/cubes-stacked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/cubes.svg b/apps/builder/public/icons/cubes.svg new file mode 100644 index 0000000..2fc9fd9 --- /dev/null +++ b/apps/builder/public/icons/cubes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/d.svg b/apps/builder/public/icons/d.svg new file mode 100644 index 0000000..0032848 --- /dev/null +++ b/apps/builder/public/icons/d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/database.svg b/apps/builder/public/icons/database.svg new file mode 100644 index 0000000..9790d40 --- /dev/null +++ b/apps/builder/public/icons/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/delete-left.svg b/apps/builder/public/icons/delete-left.svg new file mode 100644 index 0000000..a7eb0ca --- /dev/null +++ b/apps/builder/public/icons/delete-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/democrat.svg b/apps/builder/public/icons/democrat.svg new file mode 100644 index 0000000..03daf39 --- /dev/null +++ b/apps/builder/public/icons/democrat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/desktop.svg b/apps/builder/public/icons/desktop.svg new file mode 100644 index 0000000..50aa72e --- /dev/null +++ b/apps/builder/public/icons/desktop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dharmachakra.svg b/apps/builder/public/icons/dharmachakra.svg new file mode 100644 index 0000000..33774bb --- /dev/null +++ b/apps/builder/public/icons/dharmachakra.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diagram-next.svg b/apps/builder/public/icons/diagram-next.svg new file mode 100644 index 0000000..f9570a1 --- /dev/null +++ b/apps/builder/public/icons/diagram-next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diagram-predecessor.svg b/apps/builder/public/icons/diagram-predecessor.svg new file mode 100644 index 0000000..9c35563 --- /dev/null +++ b/apps/builder/public/icons/diagram-predecessor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diagram-project.svg b/apps/builder/public/icons/diagram-project.svg new file mode 100644 index 0000000..0184869 --- /dev/null +++ b/apps/builder/public/icons/diagram-project.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diagram-successor.svg b/apps/builder/public/icons/diagram-successor.svg new file mode 100644 index 0000000..501eb09 --- /dev/null +++ b/apps/builder/public/icons/diagram-successor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diamond-turn-right.svg b/apps/builder/public/icons/diamond-turn-right.svg new file mode 100644 index 0000000..83c1ada --- /dev/null +++ b/apps/builder/public/icons/diamond-turn-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/diamond.svg b/apps/builder/public/icons/diamond.svg new file mode 100644 index 0000000..15cf8b1 --- /dev/null +++ b/apps/builder/public/icons/diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-d20.svg b/apps/builder/public/icons/dice-d20.svg new file mode 100644 index 0000000..64bf310 --- /dev/null +++ b/apps/builder/public/icons/dice-d20.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-d6.svg b/apps/builder/public/icons/dice-d6.svg new file mode 100644 index 0000000..7a7281a --- /dev/null +++ b/apps/builder/public/icons/dice-d6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-five.svg b/apps/builder/public/icons/dice-five.svg new file mode 100644 index 0000000..a88b482 --- /dev/null +++ b/apps/builder/public/icons/dice-five.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-four.svg b/apps/builder/public/icons/dice-four.svg new file mode 100644 index 0000000..88d7db9 --- /dev/null +++ b/apps/builder/public/icons/dice-four.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-one.svg b/apps/builder/public/icons/dice-one.svg new file mode 100644 index 0000000..cbee54f --- /dev/null +++ b/apps/builder/public/icons/dice-one.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-six.svg b/apps/builder/public/icons/dice-six.svg new file mode 100644 index 0000000..5129e98 --- /dev/null +++ b/apps/builder/public/icons/dice-six.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-three.svg b/apps/builder/public/icons/dice-three.svg new file mode 100644 index 0000000..1956eac --- /dev/null +++ b/apps/builder/public/icons/dice-three.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice-two.svg b/apps/builder/public/icons/dice-two.svg new file mode 100644 index 0000000..529fe45 --- /dev/null +++ b/apps/builder/public/icons/dice-two.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dice.svg b/apps/builder/public/icons/dice.svg new file mode 100644 index 0000000..afbf892 --- /dev/null +++ b/apps/builder/public/icons/dice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/disease.svg b/apps/builder/public/icons/disease.svg new file mode 100644 index 0000000..3502f8c --- /dev/null +++ b/apps/builder/public/icons/disease.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/display.svg b/apps/builder/public/icons/display.svg new file mode 100644 index 0000000..4264739 --- /dev/null +++ b/apps/builder/public/icons/display.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/divide.svg b/apps/builder/public/icons/divide.svg new file mode 100644 index 0000000..1b9be3f --- /dev/null +++ b/apps/builder/public/icons/divide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dna.svg b/apps/builder/public/icons/dna.svg new file mode 100644 index 0000000..13ecf53 --- /dev/null +++ b/apps/builder/public/icons/dna.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dog.svg b/apps/builder/public/icons/dog.svg new file mode 100644 index 0000000..7f86f45 --- /dev/null +++ b/apps/builder/public/icons/dog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dollar-sign.svg b/apps/builder/public/icons/dollar-sign.svg new file mode 100644 index 0000000..7ea03f3 --- /dev/null +++ b/apps/builder/public/icons/dollar-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dolly.svg b/apps/builder/public/icons/dolly.svg new file mode 100644 index 0000000..1cc1b85 --- /dev/null +++ b/apps/builder/public/icons/dolly.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dong-sign.svg b/apps/builder/public/icons/dong-sign.svg new file mode 100644 index 0000000..d36c6c0 --- /dev/null +++ b/apps/builder/public/icons/dong-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/door-closed.svg b/apps/builder/public/icons/door-closed.svg new file mode 100644 index 0000000..3d31516 --- /dev/null +++ b/apps/builder/public/icons/door-closed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/door-open.svg b/apps/builder/public/icons/door-open.svg new file mode 100644 index 0000000..9ca6d2a --- /dev/null +++ b/apps/builder/public/icons/door-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dove.svg b/apps/builder/public/icons/dove.svg new file mode 100644 index 0000000..6b613cc --- /dev/null +++ b/apps/builder/public/icons/dove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/down-left-and-up-right-to-center.svg b/apps/builder/public/icons/down-left-and-up-right-to-center.svg new file mode 100644 index 0000000..ad6cc39 --- /dev/null +++ b/apps/builder/public/icons/down-left-and-up-right-to-center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/down-long.svg b/apps/builder/public/icons/down-long.svg new file mode 100644 index 0000000..2d73c78 --- /dev/null +++ b/apps/builder/public/icons/down-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/download.svg b/apps/builder/public/icons/download.svg new file mode 100644 index 0000000..b112962 --- /dev/null +++ b/apps/builder/public/icons/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dragon.svg b/apps/builder/public/icons/dragon.svg new file mode 100644 index 0000000..169036c --- /dev/null +++ b/apps/builder/public/icons/dragon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/draw-polygon.svg b/apps/builder/public/icons/draw-polygon.svg new file mode 100644 index 0000000..8ac81d4 --- /dev/null +++ b/apps/builder/public/icons/draw-polygon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/droplet-slash.svg b/apps/builder/public/icons/droplet-slash.svg new file mode 100644 index 0000000..613e64d --- /dev/null +++ b/apps/builder/public/icons/droplet-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/droplet.svg b/apps/builder/public/icons/droplet.svg new file mode 100644 index 0000000..137eae4 --- /dev/null +++ b/apps/builder/public/icons/droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/drum-steelpan.svg b/apps/builder/public/icons/drum-steelpan.svg new file mode 100644 index 0000000..69f7de8 --- /dev/null +++ b/apps/builder/public/icons/drum-steelpan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/drum.svg b/apps/builder/public/icons/drum.svg new file mode 100644 index 0000000..9e8e7c2 --- /dev/null +++ b/apps/builder/public/icons/drum.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/drumstick-bite.svg b/apps/builder/public/icons/drumstick-bite.svg new file mode 100644 index 0000000..df491b4 --- /dev/null +++ b/apps/builder/public/icons/drumstick-bite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dumbbell.svg b/apps/builder/public/icons/dumbbell.svg new file mode 100644 index 0000000..f8e04b6 --- /dev/null +++ b/apps/builder/public/icons/dumbbell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dumpster-fire.svg b/apps/builder/public/icons/dumpster-fire.svg new file mode 100644 index 0000000..7d88212 --- /dev/null +++ b/apps/builder/public/icons/dumpster-fire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dumpster.svg b/apps/builder/public/icons/dumpster.svg new file mode 100644 index 0000000..4a58487 --- /dev/null +++ b/apps/builder/public/icons/dumpster.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/dungeon.svg b/apps/builder/public/icons/dungeon.svg new file mode 100644 index 0000000..ba73580 --- /dev/null +++ b/apps/builder/public/icons/dungeon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/e.svg b/apps/builder/public/icons/e.svg new file mode 100644 index 0000000..08ede3f --- /dev/null +++ b/apps/builder/public/icons/e.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ear-deaf.svg b/apps/builder/public/icons/ear-deaf.svg new file mode 100644 index 0000000..469e9cf --- /dev/null +++ b/apps/builder/public/icons/ear-deaf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ear-listen.svg b/apps/builder/public/icons/ear-listen.svg new file mode 100644 index 0000000..0e916f2 --- /dev/null +++ b/apps/builder/public/icons/ear-listen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/earth-africa.svg b/apps/builder/public/icons/earth-africa.svg new file mode 100644 index 0000000..91f21f2 --- /dev/null +++ b/apps/builder/public/icons/earth-africa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/earth-americas.svg b/apps/builder/public/icons/earth-americas.svg new file mode 100644 index 0000000..68102b2 --- /dev/null +++ b/apps/builder/public/icons/earth-americas.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/earth-asia.svg b/apps/builder/public/icons/earth-asia.svg new file mode 100644 index 0000000..079f94e --- /dev/null +++ b/apps/builder/public/icons/earth-asia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/earth-europe.svg b/apps/builder/public/icons/earth-europe.svg new file mode 100644 index 0000000..4453a00 --- /dev/null +++ b/apps/builder/public/icons/earth-europe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/earth-oceania.svg b/apps/builder/public/icons/earth-oceania.svg new file mode 100644 index 0000000..9fe0e34 --- /dev/null +++ b/apps/builder/public/icons/earth-oceania.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/egg.svg b/apps/builder/public/icons/egg.svg new file mode 100644 index 0000000..fdce91e --- /dev/null +++ b/apps/builder/public/icons/egg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eject.svg b/apps/builder/public/icons/eject.svg new file mode 100644 index 0000000..5eb8289 --- /dev/null +++ b/apps/builder/public/icons/eject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/elevator.svg b/apps/builder/public/icons/elevator.svg new file mode 100644 index 0000000..852d6af --- /dev/null +++ b/apps/builder/public/icons/elevator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ellipsis-vertical.svg b/apps/builder/public/icons/ellipsis-vertical.svg new file mode 100644 index 0000000..db26a1d --- /dev/null +++ b/apps/builder/public/icons/ellipsis-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ellipsis.svg b/apps/builder/public/icons/ellipsis.svg new file mode 100644 index 0000000..e3b9946 --- /dev/null +++ b/apps/builder/public/icons/ellipsis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/envelope-circle-check.svg b/apps/builder/public/icons/envelope-circle-check.svg new file mode 100644 index 0000000..0bbffe1 --- /dev/null +++ b/apps/builder/public/icons/envelope-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/envelope-open-text.svg b/apps/builder/public/icons/envelope-open-text.svg new file mode 100644 index 0000000..9ecab8c --- /dev/null +++ b/apps/builder/public/icons/envelope-open-text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/envelope-open.svg b/apps/builder/public/icons/envelope-open.svg new file mode 100644 index 0000000..ca020ad --- /dev/null +++ b/apps/builder/public/icons/envelope-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/envelope.svg b/apps/builder/public/icons/envelope.svg new file mode 100644 index 0000000..6feb0d8 --- /dev/null +++ b/apps/builder/public/icons/envelope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/envelopes-bulk.svg b/apps/builder/public/icons/envelopes-bulk.svg new file mode 100644 index 0000000..86b570e --- /dev/null +++ b/apps/builder/public/icons/envelopes-bulk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/equals.svg b/apps/builder/public/icons/equals.svg new file mode 100644 index 0000000..68bd242 --- /dev/null +++ b/apps/builder/public/icons/equals.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eraser.svg b/apps/builder/public/icons/eraser.svg new file mode 100644 index 0000000..286bd27 --- /dev/null +++ b/apps/builder/public/icons/eraser.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ethernet.svg b/apps/builder/public/icons/ethernet.svg new file mode 100644 index 0000000..91b3853 --- /dev/null +++ b/apps/builder/public/icons/ethernet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/euro-sign.svg b/apps/builder/public/icons/euro-sign.svg new file mode 100644 index 0000000..6534c74 --- /dev/null +++ b/apps/builder/public/icons/euro-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/exclamation.svg b/apps/builder/public/icons/exclamation.svg new file mode 100644 index 0000000..814b9c0 --- /dev/null +++ b/apps/builder/public/icons/exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/expand.svg b/apps/builder/public/icons/expand.svg new file mode 100644 index 0000000..a77a3aa --- /dev/null +++ b/apps/builder/public/icons/expand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/explosion.svg b/apps/builder/public/icons/explosion.svg new file mode 100644 index 0000000..aad0214 --- /dev/null +++ b/apps/builder/public/icons/explosion.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eye-dropper.svg b/apps/builder/public/icons/eye-dropper.svg new file mode 100644 index 0000000..297a25a --- /dev/null +++ b/apps/builder/public/icons/eye-dropper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eye-low-vision.svg b/apps/builder/public/icons/eye-low-vision.svg new file mode 100644 index 0000000..73bc0b5 --- /dev/null +++ b/apps/builder/public/icons/eye-low-vision.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eye-slash.svg b/apps/builder/public/icons/eye-slash.svg new file mode 100644 index 0000000..7ba9458 --- /dev/null +++ b/apps/builder/public/icons/eye-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/eye.svg b/apps/builder/public/icons/eye.svg new file mode 100644 index 0000000..eb599e1 --- /dev/null +++ b/apps/builder/public/icons/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/f.svg b/apps/builder/public/icons/f.svg new file mode 100644 index 0000000..e8445c6 --- /dev/null +++ b/apps/builder/public/icons/f.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-angry.svg b/apps/builder/public/icons/face-angry.svg new file mode 100644 index 0000000..057eb7b --- /dev/null +++ b/apps/builder/public/icons/face-angry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-dizzy.svg b/apps/builder/public/icons/face-dizzy.svg new file mode 100644 index 0000000..870518b --- /dev/null +++ b/apps/builder/public/icons/face-dizzy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-flushed.svg b/apps/builder/public/icons/face-flushed.svg new file mode 100644 index 0000000..6ceedb2 --- /dev/null +++ b/apps/builder/public/icons/face-flushed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-frown-open.svg b/apps/builder/public/icons/face-frown-open.svg new file mode 100644 index 0000000..0e78f5e --- /dev/null +++ b/apps/builder/public/icons/face-frown-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-frown.svg b/apps/builder/public/icons/face-frown.svg new file mode 100644 index 0000000..b68a2ad --- /dev/null +++ b/apps/builder/public/icons/face-frown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grimace.svg b/apps/builder/public/icons/face-grimace.svg new file mode 100644 index 0000000..12db217 --- /dev/null +++ b/apps/builder/public/icons/face-grimace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-beam-sweat.svg b/apps/builder/public/icons/face-grin-beam-sweat.svg new file mode 100644 index 0000000..c2f9295 --- /dev/null +++ b/apps/builder/public/icons/face-grin-beam-sweat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-beam.svg b/apps/builder/public/icons/face-grin-beam.svg new file mode 100644 index 0000000..2b5a139 --- /dev/null +++ b/apps/builder/public/icons/face-grin-beam.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-hearts.svg b/apps/builder/public/icons/face-grin-hearts.svg new file mode 100644 index 0000000..b196993 --- /dev/null +++ b/apps/builder/public/icons/face-grin-hearts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-squint-tears.svg b/apps/builder/public/icons/face-grin-squint-tears.svg new file mode 100644 index 0000000..8b2e8b7 --- /dev/null +++ b/apps/builder/public/icons/face-grin-squint-tears.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-squint.svg b/apps/builder/public/icons/face-grin-squint.svg new file mode 100644 index 0000000..05d9319 --- /dev/null +++ b/apps/builder/public/icons/face-grin-squint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-stars.svg b/apps/builder/public/icons/face-grin-stars.svg new file mode 100644 index 0000000..5e29a15 --- /dev/null +++ b/apps/builder/public/icons/face-grin-stars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-tears.svg b/apps/builder/public/icons/face-grin-tears.svg new file mode 100644 index 0000000..e8fda4a --- /dev/null +++ b/apps/builder/public/icons/face-grin-tears.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-tongue-squint.svg b/apps/builder/public/icons/face-grin-tongue-squint.svg new file mode 100644 index 0000000..709f8fa --- /dev/null +++ b/apps/builder/public/icons/face-grin-tongue-squint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-tongue-wink.svg b/apps/builder/public/icons/face-grin-tongue-wink.svg new file mode 100644 index 0000000..be48716 --- /dev/null +++ b/apps/builder/public/icons/face-grin-tongue-wink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-tongue.svg b/apps/builder/public/icons/face-grin-tongue.svg new file mode 100644 index 0000000..32f009c --- /dev/null +++ b/apps/builder/public/icons/face-grin-tongue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-wide.svg b/apps/builder/public/icons/face-grin-wide.svg new file mode 100644 index 0000000..a5c36b6 --- /dev/null +++ b/apps/builder/public/icons/face-grin-wide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin-wink.svg b/apps/builder/public/icons/face-grin-wink.svg new file mode 100644 index 0000000..6e3e67f --- /dev/null +++ b/apps/builder/public/icons/face-grin-wink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-grin.svg b/apps/builder/public/icons/face-grin.svg new file mode 100644 index 0000000..f998002 --- /dev/null +++ b/apps/builder/public/icons/face-grin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-kiss-beam.svg b/apps/builder/public/icons/face-kiss-beam.svg new file mode 100644 index 0000000..d09a2c4 --- /dev/null +++ b/apps/builder/public/icons/face-kiss-beam.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-kiss-wink-heart.svg b/apps/builder/public/icons/face-kiss-wink-heart.svg new file mode 100644 index 0000000..7ddb90e --- /dev/null +++ b/apps/builder/public/icons/face-kiss-wink-heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-kiss.svg b/apps/builder/public/icons/face-kiss.svg new file mode 100644 index 0000000..50cff3a --- /dev/null +++ b/apps/builder/public/icons/face-kiss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-laugh-beam.svg b/apps/builder/public/icons/face-laugh-beam.svg new file mode 100644 index 0000000..aa4441a --- /dev/null +++ b/apps/builder/public/icons/face-laugh-beam.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-laugh-squint.svg b/apps/builder/public/icons/face-laugh-squint.svg new file mode 100644 index 0000000..eb4dfbc --- /dev/null +++ b/apps/builder/public/icons/face-laugh-squint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-laugh-wink.svg b/apps/builder/public/icons/face-laugh-wink.svg new file mode 100644 index 0000000..135cdfb --- /dev/null +++ b/apps/builder/public/icons/face-laugh-wink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-laugh.svg b/apps/builder/public/icons/face-laugh.svg new file mode 100644 index 0000000..f5efa31 --- /dev/null +++ b/apps/builder/public/icons/face-laugh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-meh-blank.svg b/apps/builder/public/icons/face-meh-blank.svg new file mode 100644 index 0000000..e8a6819 --- /dev/null +++ b/apps/builder/public/icons/face-meh-blank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-meh.svg b/apps/builder/public/icons/face-meh.svg new file mode 100644 index 0000000..6c5b701 --- /dev/null +++ b/apps/builder/public/icons/face-meh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-rolling-eyes.svg b/apps/builder/public/icons/face-rolling-eyes.svg new file mode 100644 index 0000000..360a58e --- /dev/null +++ b/apps/builder/public/icons/face-rolling-eyes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-sad-cry.svg b/apps/builder/public/icons/face-sad-cry.svg new file mode 100644 index 0000000..ba6fe39 --- /dev/null +++ b/apps/builder/public/icons/face-sad-cry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-sad-tear.svg b/apps/builder/public/icons/face-sad-tear.svg new file mode 100644 index 0000000..d5f3f2b --- /dev/null +++ b/apps/builder/public/icons/face-sad-tear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-smile-beam.svg b/apps/builder/public/icons/face-smile-beam.svg new file mode 100644 index 0000000..934e4b8 --- /dev/null +++ b/apps/builder/public/icons/face-smile-beam.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-smile-wink.svg b/apps/builder/public/icons/face-smile-wink.svg new file mode 100644 index 0000000..27cda91 --- /dev/null +++ b/apps/builder/public/icons/face-smile-wink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-smile.svg b/apps/builder/public/icons/face-smile.svg new file mode 100644 index 0000000..56c5cb8 --- /dev/null +++ b/apps/builder/public/icons/face-smile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-surprise.svg b/apps/builder/public/icons/face-surprise.svg new file mode 100644 index 0000000..70153d9 --- /dev/null +++ b/apps/builder/public/icons/face-surprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/face-tired.svg b/apps/builder/public/icons/face-tired.svg new file mode 100644 index 0000000..a6c61e8 --- /dev/null +++ b/apps/builder/public/icons/face-tired.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fan.svg b/apps/builder/public/icons/fan.svg new file mode 100644 index 0000000..7029d7f --- /dev/null +++ b/apps/builder/public/icons/fan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/faucet-drip.svg b/apps/builder/public/icons/faucet-drip.svg new file mode 100644 index 0000000..b16de30 --- /dev/null +++ b/apps/builder/public/icons/faucet-drip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/faucet.svg b/apps/builder/public/icons/faucet.svg new file mode 100644 index 0000000..ca5d647 --- /dev/null +++ b/apps/builder/public/icons/faucet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fax.svg b/apps/builder/public/icons/fax.svg new file mode 100644 index 0000000..c0b53a2 --- /dev/null +++ b/apps/builder/public/icons/fax.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/feather-pointed.svg b/apps/builder/public/icons/feather-pointed.svg new file mode 100644 index 0000000..eba7e60 --- /dev/null +++ b/apps/builder/public/icons/feather-pointed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/feather.svg b/apps/builder/public/icons/feather.svg new file mode 100644 index 0000000..f05942e --- /dev/null +++ b/apps/builder/public/icons/feather.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ferry.svg b/apps/builder/public/icons/ferry.svg new file mode 100644 index 0000000..7437457 --- /dev/null +++ b/apps/builder/public/icons/ferry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-arrow-down.svg b/apps/builder/public/icons/file-arrow-down.svg new file mode 100644 index 0000000..010fe94 --- /dev/null +++ b/apps/builder/public/icons/file-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-arrow-up.svg b/apps/builder/public/icons/file-arrow-up.svg new file mode 100644 index 0000000..4c9b952 --- /dev/null +++ b/apps/builder/public/icons/file-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-audio.svg b/apps/builder/public/icons/file-audio.svg new file mode 100644 index 0000000..771207a --- /dev/null +++ b/apps/builder/public/icons/file-audio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-check.svg b/apps/builder/public/icons/file-circle-check.svg new file mode 100644 index 0000000..bc6da65 --- /dev/null +++ b/apps/builder/public/icons/file-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-exclamation.svg b/apps/builder/public/icons/file-circle-exclamation.svg new file mode 100644 index 0000000..10e9a7a --- /dev/null +++ b/apps/builder/public/icons/file-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-minus.svg b/apps/builder/public/icons/file-circle-minus.svg new file mode 100644 index 0000000..6968400 --- /dev/null +++ b/apps/builder/public/icons/file-circle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-plus.svg b/apps/builder/public/icons/file-circle-plus.svg new file mode 100644 index 0000000..773cef6 --- /dev/null +++ b/apps/builder/public/icons/file-circle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-question.svg b/apps/builder/public/icons/file-circle-question.svg new file mode 100644 index 0000000..4cda659 --- /dev/null +++ b/apps/builder/public/icons/file-circle-question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-circle-xmark.svg b/apps/builder/public/icons/file-circle-xmark.svg new file mode 100644 index 0000000..532a151 --- /dev/null +++ b/apps/builder/public/icons/file-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-code.svg b/apps/builder/public/icons/file-code.svg new file mode 100644 index 0000000..20c48d4 --- /dev/null +++ b/apps/builder/public/icons/file-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-contract.svg b/apps/builder/public/icons/file-contract.svg new file mode 100644 index 0000000..4341727 --- /dev/null +++ b/apps/builder/public/icons/file-contract.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-csv.svg b/apps/builder/public/icons/file-csv.svg new file mode 100644 index 0000000..409316c --- /dev/null +++ b/apps/builder/public/icons/file-csv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-excel.svg b/apps/builder/public/icons/file-excel.svg new file mode 100644 index 0000000..5002932 --- /dev/null +++ b/apps/builder/public/icons/file-excel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-export.svg b/apps/builder/public/icons/file-export.svg new file mode 100644 index 0000000..6a42e79 --- /dev/null +++ b/apps/builder/public/icons/file-export.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-image.svg b/apps/builder/public/icons/file-image.svg new file mode 100644 index 0000000..0725741 --- /dev/null +++ b/apps/builder/public/icons/file-image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-import.svg b/apps/builder/public/icons/file-import.svg new file mode 100644 index 0000000..5d033b4 --- /dev/null +++ b/apps/builder/public/icons/file-import.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-invoice-dollar.svg b/apps/builder/public/icons/file-invoice-dollar.svg new file mode 100644 index 0000000..460ef51 --- /dev/null +++ b/apps/builder/public/icons/file-invoice-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-invoice.svg b/apps/builder/public/icons/file-invoice.svg new file mode 100644 index 0000000..590c965 --- /dev/null +++ b/apps/builder/public/icons/file-invoice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-lines.svg b/apps/builder/public/icons/file-lines.svg new file mode 100644 index 0000000..d8058f8 --- /dev/null +++ b/apps/builder/public/icons/file-lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-medical.svg b/apps/builder/public/icons/file-medical.svg new file mode 100644 index 0000000..f2a2be8 --- /dev/null +++ b/apps/builder/public/icons/file-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-pdf.svg b/apps/builder/public/icons/file-pdf.svg new file mode 100644 index 0000000..8bdec66 --- /dev/null +++ b/apps/builder/public/icons/file-pdf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-pen.svg b/apps/builder/public/icons/file-pen.svg new file mode 100644 index 0000000..f08361c --- /dev/null +++ b/apps/builder/public/icons/file-pen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-powerpoint.svg b/apps/builder/public/icons/file-powerpoint.svg new file mode 100644 index 0000000..1eeef65 --- /dev/null +++ b/apps/builder/public/icons/file-powerpoint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-prescription.svg b/apps/builder/public/icons/file-prescription.svg new file mode 100644 index 0000000..9b159c5 --- /dev/null +++ b/apps/builder/public/icons/file-prescription.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-shield.svg b/apps/builder/public/icons/file-shield.svg new file mode 100644 index 0000000..1706194 --- /dev/null +++ b/apps/builder/public/icons/file-shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-signature.svg b/apps/builder/public/icons/file-signature.svg new file mode 100644 index 0000000..97e01bf --- /dev/null +++ b/apps/builder/public/icons/file-signature.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-video.svg b/apps/builder/public/icons/file-video.svg new file mode 100644 index 0000000..6f863a7 --- /dev/null +++ b/apps/builder/public/icons/file-video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-waveform.svg b/apps/builder/public/icons/file-waveform.svg new file mode 100644 index 0000000..c407c7f --- /dev/null +++ b/apps/builder/public/icons/file-waveform.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-word.svg b/apps/builder/public/icons/file-word.svg new file mode 100644 index 0000000..c4ca7b2 --- /dev/null +++ b/apps/builder/public/icons/file-word.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file-zipper.svg b/apps/builder/public/icons/file-zipper.svg new file mode 100644 index 0000000..26b42f3 --- /dev/null +++ b/apps/builder/public/icons/file-zipper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/file.svg b/apps/builder/public/icons/file.svg new file mode 100644 index 0000000..3841a03 --- /dev/null +++ b/apps/builder/public/icons/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fill-drip.svg b/apps/builder/public/icons/fill-drip.svg new file mode 100644 index 0000000..f98b308 --- /dev/null +++ b/apps/builder/public/icons/fill-drip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fill.svg b/apps/builder/public/icons/fill.svg new file mode 100644 index 0000000..d803590 --- /dev/null +++ b/apps/builder/public/icons/fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/film.svg b/apps/builder/public/icons/film.svg new file mode 100644 index 0000000..c291ff6 --- /dev/null +++ b/apps/builder/public/icons/film.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/filter-circle-dollar.svg b/apps/builder/public/icons/filter-circle-dollar.svg new file mode 100644 index 0000000..cdda916 --- /dev/null +++ b/apps/builder/public/icons/filter-circle-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/filter-circle-xmark.svg b/apps/builder/public/icons/filter-circle-xmark.svg new file mode 100644 index 0000000..7088147 --- /dev/null +++ b/apps/builder/public/icons/filter-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/filter.svg b/apps/builder/public/icons/filter.svg new file mode 100644 index 0000000..a0cc80c --- /dev/null +++ b/apps/builder/public/icons/filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fingerprint.svg b/apps/builder/public/icons/fingerprint.svg new file mode 100644 index 0000000..17a5ffc --- /dev/null +++ b/apps/builder/public/icons/fingerprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fire-burner.svg b/apps/builder/public/icons/fire-burner.svg new file mode 100644 index 0000000..9f7c603 --- /dev/null +++ b/apps/builder/public/icons/fire-burner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fire-extinguisher.svg b/apps/builder/public/icons/fire-extinguisher.svg new file mode 100644 index 0000000..74ed8a6 --- /dev/null +++ b/apps/builder/public/icons/fire-extinguisher.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fire-flame-curved.svg b/apps/builder/public/icons/fire-flame-curved.svg new file mode 100644 index 0000000..4ac2bb6 --- /dev/null +++ b/apps/builder/public/icons/fire-flame-curved.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fire-flame-simple.svg b/apps/builder/public/icons/fire-flame-simple.svg new file mode 100644 index 0000000..b23aa0c --- /dev/null +++ b/apps/builder/public/icons/fire-flame-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fire.svg b/apps/builder/public/icons/fire.svg new file mode 100644 index 0000000..dc2d20a --- /dev/null +++ b/apps/builder/public/icons/fire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fish-fins.svg b/apps/builder/public/icons/fish-fins.svg new file mode 100644 index 0000000..a3cd8b6 --- /dev/null +++ b/apps/builder/public/icons/fish-fins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/fish.svg b/apps/builder/public/icons/fish.svg new file mode 100644 index 0000000..0d99b4e --- /dev/null +++ b/apps/builder/public/icons/fish.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/flag-checkered.svg b/apps/builder/public/icons/flag-checkered.svg new file mode 100644 index 0000000..c458d6f --- /dev/null +++ b/apps/builder/public/icons/flag-checkered.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/flag-usa.svg b/apps/builder/public/icons/flag-usa.svg new file mode 100644 index 0000000..0cb57bf --- /dev/null +++ b/apps/builder/public/icons/flag-usa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/flag.svg b/apps/builder/public/icons/flag.svg new file mode 100644 index 0000000..360e186 --- /dev/null +++ b/apps/builder/public/icons/flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/flask-vial.svg b/apps/builder/public/icons/flask-vial.svg new file mode 100644 index 0000000..3fe60d8 --- /dev/null +++ b/apps/builder/public/icons/flask-vial.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/flask.svg b/apps/builder/public/icons/flask.svg new file mode 100644 index 0000000..8974e2f --- /dev/null +++ b/apps/builder/public/icons/flask.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/floppy-disk.svg b/apps/builder/public/icons/floppy-disk.svg new file mode 100644 index 0000000..c756486 --- /dev/null +++ b/apps/builder/public/icons/floppy-disk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/florin-sign.svg b/apps/builder/public/icons/florin-sign.svg new file mode 100644 index 0000000..e62953c --- /dev/null +++ b/apps/builder/public/icons/florin-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder-closed.svg b/apps/builder/public/icons/folder-closed.svg new file mode 100644 index 0000000..564972e --- /dev/null +++ b/apps/builder/public/icons/folder-closed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder-minus.svg b/apps/builder/public/icons/folder-minus.svg new file mode 100644 index 0000000..513101b --- /dev/null +++ b/apps/builder/public/icons/folder-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder-open.svg b/apps/builder/public/icons/folder-open.svg new file mode 100644 index 0000000..8d671eb --- /dev/null +++ b/apps/builder/public/icons/folder-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder-plus.svg b/apps/builder/public/icons/folder-plus.svg new file mode 100644 index 0000000..e871b12 --- /dev/null +++ b/apps/builder/public/icons/folder-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder-tree.svg b/apps/builder/public/icons/folder-tree.svg new file mode 100644 index 0000000..319aa22 --- /dev/null +++ b/apps/builder/public/icons/folder-tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/folder.svg b/apps/builder/public/icons/folder.svg new file mode 100644 index 0000000..41c83a1 --- /dev/null +++ b/apps/builder/public/icons/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/font-awesome.svg b/apps/builder/public/icons/font-awesome.svg new file mode 100644 index 0000000..3db2185 --- /dev/null +++ b/apps/builder/public/icons/font-awesome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/font.svg b/apps/builder/public/icons/font.svg new file mode 100644 index 0000000..6f17824 --- /dev/null +++ b/apps/builder/public/icons/font.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/football.svg b/apps/builder/public/icons/football.svg new file mode 100644 index 0000000..19acce2 --- /dev/null +++ b/apps/builder/public/icons/football.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/forward-fast.svg b/apps/builder/public/icons/forward-fast.svg new file mode 100644 index 0000000..fe8d287 --- /dev/null +++ b/apps/builder/public/icons/forward-fast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/forward-step.svg b/apps/builder/public/icons/forward-step.svg new file mode 100644 index 0000000..7e39d93 --- /dev/null +++ b/apps/builder/public/icons/forward-step.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/forward.svg b/apps/builder/public/icons/forward.svg new file mode 100644 index 0000000..8e2ae5b --- /dev/null +++ b/apps/builder/public/icons/forward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/franc-sign.svg b/apps/builder/public/icons/franc-sign.svg new file mode 100644 index 0000000..1c66f0d --- /dev/null +++ b/apps/builder/public/icons/franc-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/frog.svg b/apps/builder/public/icons/frog.svg new file mode 100644 index 0000000..7fcd4b5 --- /dev/null +++ b/apps/builder/public/icons/frog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/futbol.svg b/apps/builder/public/icons/futbol.svg new file mode 100644 index 0000000..54fc359 --- /dev/null +++ b/apps/builder/public/icons/futbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/g.svg b/apps/builder/public/icons/g.svg new file mode 100644 index 0000000..6af8c0b --- /dev/null +++ b/apps/builder/public/icons/g.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gamepad.svg b/apps/builder/public/icons/gamepad.svg new file mode 100644 index 0000000..30fdd77 --- /dev/null +++ b/apps/builder/public/icons/gamepad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gas-pump.svg b/apps/builder/public/icons/gas-pump.svg new file mode 100644 index 0000000..e3cd628 --- /dev/null +++ b/apps/builder/public/icons/gas-pump.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gauge-high.svg b/apps/builder/public/icons/gauge-high.svg new file mode 100644 index 0000000..a36a0e8 --- /dev/null +++ b/apps/builder/public/icons/gauge-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gauge-simple-high.svg b/apps/builder/public/icons/gauge-simple-high.svg new file mode 100644 index 0000000..a27a18b --- /dev/null +++ b/apps/builder/public/icons/gauge-simple-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gauge-simple.svg b/apps/builder/public/icons/gauge-simple.svg new file mode 100644 index 0000000..2418b26 --- /dev/null +++ b/apps/builder/public/icons/gauge-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gauge.svg b/apps/builder/public/icons/gauge.svg new file mode 100644 index 0000000..7102b90 --- /dev/null +++ b/apps/builder/public/icons/gauge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gavel.svg b/apps/builder/public/icons/gavel.svg new file mode 100644 index 0000000..5b0cc34 --- /dev/null +++ b/apps/builder/public/icons/gavel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gear.svg b/apps/builder/public/icons/gear.svg new file mode 100644 index 0000000..319bcfe --- /dev/null +++ b/apps/builder/public/icons/gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gears.svg b/apps/builder/public/icons/gears.svg new file mode 100644 index 0000000..987f40b --- /dev/null +++ b/apps/builder/public/icons/gears.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gem.svg b/apps/builder/public/icons/gem.svg new file mode 100644 index 0000000..54a80eb --- /dev/null +++ b/apps/builder/public/icons/gem.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/genderless.svg b/apps/builder/public/icons/genderless.svg new file mode 100644 index 0000000..8e86109 --- /dev/null +++ b/apps/builder/public/icons/genderless.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ghost.svg b/apps/builder/public/icons/ghost.svg new file mode 100644 index 0000000..a7e7b26 --- /dev/null +++ b/apps/builder/public/icons/ghost.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gift.svg b/apps/builder/public/icons/gift.svg new file mode 100644 index 0000000..3f6f7a1 --- /dev/null +++ b/apps/builder/public/icons/gift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gifts.svg b/apps/builder/public/icons/gifts.svg new file mode 100644 index 0000000..78095ff --- /dev/null +++ b/apps/builder/public/icons/gifts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/glass-water-droplet.svg b/apps/builder/public/icons/glass-water-droplet.svg new file mode 100644 index 0000000..31c29b4 --- /dev/null +++ b/apps/builder/public/icons/glass-water-droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/glass-water.svg b/apps/builder/public/icons/glass-water.svg new file mode 100644 index 0000000..44d61c4 --- /dev/null +++ b/apps/builder/public/icons/glass-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/glasses.svg b/apps/builder/public/icons/glasses.svg new file mode 100644 index 0000000..3d1999d --- /dev/null +++ b/apps/builder/public/icons/glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/globe.svg b/apps/builder/public/icons/globe.svg new file mode 100644 index 0000000..6083d15 --- /dev/null +++ b/apps/builder/public/icons/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/golf-ball-tee.svg b/apps/builder/public/icons/golf-ball-tee.svg new file mode 100644 index 0000000..6df836b --- /dev/null +++ b/apps/builder/public/icons/golf-ball-tee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gopuram.svg b/apps/builder/public/icons/gopuram.svg new file mode 100644 index 0000000..4e31100 --- /dev/null +++ b/apps/builder/public/icons/gopuram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/graduation-cap.svg b/apps/builder/public/icons/graduation-cap.svg new file mode 100644 index 0000000..7e9347a --- /dev/null +++ b/apps/builder/public/icons/graduation-cap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/greater-than-equal.svg b/apps/builder/public/icons/greater-than-equal.svg new file mode 100644 index 0000000..b12b008 --- /dev/null +++ b/apps/builder/public/icons/greater-than-equal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/greater-than.svg b/apps/builder/public/icons/greater-than.svg new file mode 100644 index 0000000..34beef1 --- /dev/null +++ b/apps/builder/public/icons/greater-than.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/grip-lines-vertical.svg b/apps/builder/public/icons/grip-lines-vertical.svg new file mode 100644 index 0000000..b1de091 --- /dev/null +++ b/apps/builder/public/icons/grip-lines-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/grip-lines.svg b/apps/builder/public/icons/grip-lines.svg new file mode 100644 index 0000000..3e05b2e --- /dev/null +++ b/apps/builder/public/icons/grip-lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/grip-vertical.svg b/apps/builder/public/icons/grip-vertical.svg new file mode 100644 index 0000000..62f18fe --- /dev/null +++ b/apps/builder/public/icons/grip-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/grip.svg b/apps/builder/public/icons/grip.svg new file mode 100644 index 0000000..1862f73 --- /dev/null +++ b/apps/builder/public/icons/grip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/group-arrows-rotate.svg b/apps/builder/public/icons/group-arrows-rotate.svg new file mode 100644 index 0000000..0ee36fa --- /dev/null +++ b/apps/builder/public/icons/group-arrows-rotate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/guarani-sign.svg b/apps/builder/public/icons/guarani-sign.svg new file mode 100644 index 0000000..d18df97 --- /dev/null +++ b/apps/builder/public/icons/guarani-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/guitar.svg b/apps/builder/public/icons/guitar.svg new file mode 100644 index 0000000..c2f7567 --- /dev/null +++ b/apps/builder/public/icons/guitar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/gun.svg b/apps/builder/public/icons/gun.svg new file mode 100644 index 0000000..7a56457 --- /dev/null +++ b/apps/builder/public/icons/gun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/h.svg b/apps/builder/public/icons/h.svg new file mode 100644 index 0000000..9743cdb --- /dev/null +++ b/apps/builder/public/icons/h.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hammer.svg b/apps/builder/public/icons/hammer.svg new file mode 100644 index 0000000..8dc36f4 --- /dev/null +++ b/apps/builder/public/icons/hammer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hamsa.svg b/apps/builder/public/icons/hamsa.svg new file mode 100644 index 0000000..843c1f2 --- /dev/null +++ b/apps/builder/public/icons/hamsa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-back-fist.svg b/apps/builder/public/icons/hand-back-fist.svg new file mode 100644 index 0000000..2943bdc --- /dev/null +++ b/apps/builder/public/icons/hand-back-fist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-dots.svg b/apps/builder/public/icons/hand-dots.svg new file mode 100644 index 0000000..784473a --- /dev/null +++ b/apps/builder/public/icons/hand-dots.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-fist.svg b/apps/builder/public/icons/hand-fist.svg new file mode 100644 index 0000000..5604413 --- /dev/null +++ b/apps/builder/public/icons/hand-fist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding-dollar.svg b/apps/builder/public/icons/hand-holding-dollar.svg new file mode 100644 index 0000000..3f6a354 --- /dev/null +++ b/apps/builder/public/icons/hand-holding-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding-droplet.svg b/apps/builder/public/icons/hand-holding-droplet.svg new file mode 100644 index 0000000..4733845 --- /dev/null +++ b/apps/builder/public/icons/hand-holding-droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding-hand.svg b/apps/builder/public/icons/hand-holding-hand.svg new file mode 100644 index 0000000..b58eed9 --- /dev/null +++ b/apps/builder/public/icons/hand-holding-hand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding-heart.svg b/apps/builder/public/icons/hand-holding-heart.svg new file mode 100644 index 0000000..4366130 --- /dev/null +++ b/apps/builder/public/icons/hand-holding-heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding-medical.svg b/apps/builder/public/icons/hand-holding-medical.svg new file mode 100644 index 0000000..23972c3 --- /dev/null +++ b/apps/builder/public/icons/hand-holding-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-holding.svg b/apps/builder/public/icons/hand-holding.svg new file mode 100644 index 0000000..06ed0e6 --- /dev/null +++ b/apps/builder/public/icons/hand-holding.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-lizard.svg b/apps/builder/public/icons/hand-lizard.svg new file mode 100644 index 0000000..78ffca3 --- /dev/null +++ b/apps/builder/public/icons/hand-lizard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-middle-finger.svg b/apps/builder/public/icons/hand-middle-finger.svg new file mode 100644 index 0000000..743c589 --- /dev/null +++ b/apps/builder/public/icons/hand-middle-finger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-peace.svg b/apps/builder/public/icons/hand-peace.svg new file mode 100644 index 0000000..1ab0503 --- /dev/null +++ b/apps/builder/public/icons/hand-peace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-point-down.svg b/apps/builder/public/icons/hand-point-down.svg new file mode 100644 index 0000000..b8de55a --- /dev/null +++ b/apps/builder/public/icons/hand-point-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-point-left.svg b/apps/builder/public/icons/hand-point-left.svg new file mode 100644 index 0000000..dc60e7d --- /dev/null +++ b/apps/builder/public/icons/hand-point-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-point-right.svg b/apps/builder/public/icons/hand-point-right.svg new file mode 100644 index 0000000..6f77b30 --- /dev/null +++ b/apps/builder/public/icons/hand-point-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-point-up.svg b/apps/builder/public/icons/hand-point-up.svg new file mode 100644 index 0000000..5bc005e --- /dev/null +++ b/apps/builder/public/icons/hand-point-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-pointer.svg b/apps/builder/public/icons/hand-pointer.svg new file mode 100644 index 0000000..d82e692 --- /dev/null +++ b/apps/builder/public/icons/hand-pointer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-scissors.svg b/apps/builder/public/icons/hand-scissors.svg new file mode 100644 index 0000000..cf5711b --- /dev/null +++ b/apps/builder/public/icons/hand-scissors.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-sparkles.svg b/apps/builder/public/icons/hand-sparkles.svg new file mode 100644 index 0000000..708e09e --- /dev/null +++ b/apps/builder/public/icons/hand-sparkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand-spock.svg b/apps/builder/public/icons/hand-spock.svg new file mode 100644 index 0000000..ae31560 --- /dev/null +++ b/apps/builder/public/icons/hand-spock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hand.svg b/apps/builder/public/icons/hand.svg new file mode 100644 index 0000000..bdca894 --- /dev/null +++ b/apps/builder/public/icons/hand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handcuffs.svg b/apps/builder/public/icons/handcuffs.svg new file mode 100644 index 0000000..c77770d --- /dev/null +++ b/apps/builder/public/icons/handcuffs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-asl-interpreting.svg b/apps/builder/public/icons/hands-asl-interpreting.svg new file mode 100644 index 0000000..33565ae --- /dev/null +++ b/apps/builder/public/icons/hands-asl-interpreting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-bound.svg b/apps/builder/public/icons/hands-bound.svg new file mode 100644 index 0000000..89046f0 --- /dev/null +++ b/apps/builder/public/icons/hands-bound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-bubbles.svg b/apps/builder/public/icons/hands-bubbles.svg new file mode 100644 index 0000000..a58af47 --- /dev/null +++ b/apps/builder/public/icons/hands-bubbles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-clapping.svg b/apps/builder/public/icons/hands-clapping.svg new file mode 100644 index 0000000..e8263cf --- /dev/null +++ b/apps/builder/public/icons/hands-clapping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-holding-child.svg b/apps/builder/public/icons/hands-holding-child.svg new file mode 100644 index 0000000..d1867c9 --- /dev/null +++ b/apps/builder/public/icons/hands-holding-child.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-holding-circle.svg b/apps/builder/public/icons/hands-holding-circle.svg new file mode 100644 index 0000000..4b3216f --- /dev/null +++ b/apps/builder/public/icons/hands-holding-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-holding.svg b/apps/builder/public/icons/hands-holding.svg new file mode 100644 index 0000000..ab34156 --- /dev/null +++ b/apps/builder/public/icons/hands-holding.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands-praying.svg b/apps/builder/public/icons/hands-praying.svg new file mode 100644 index 0000000..c12c8e8 --- /dev/null +++ b/apps/builder/public/icons/hands-praying.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hands.svg b/apps/builder/public/icons/hands.svg new file mode 100644 index 0000000..76cfd01 --- /dev/null +++ b/apps/builder/public/icons/hands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handshake-angle.svg b/apps/builder/public/icons/handshake-angle.svg new file mode 100644 index 0000000..b960362 --- /dev/null +++ b/apps/builder/public/icons/handshake-angle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handshake-simple-slash.svg b/apps/builder/public/icons/handshake-simple-slash.svg new file mode 100644 index 0000000..044741b --- /dev/null +++ b/apps/builder/public/icons/handshake-simple-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handshake-simple.svg b/apps/builder/public/icons/handshake-simple.svg new file mode 100644 index 0000000..1fb90d5 --- /dev/null +++ b/apps/builder/public/icons/handshake-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handshake-slash.svg b/apps/builder/public/icons/handshake-slash.svg new file mode 100644 index 0000000..ae34b56 --- /dev/null +++ b/apps/builder/public/icons/handshake-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/handshake.svg b/apps/builder/public/icons/handshake.svg new file mode 100644 index 0000000..b50437f --- /dev/null +++ b/apps/builder/public/icons/handshake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hanukiah.svg b/apps/builder/public/icons/hanukiah.svg new file mode 100644 index 0000000..64dd2b4 --- /dev/null +++ b/apps/builder/public/icons/hanukiah.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hard-drive.svg b/apps/builder/public/icons/hard-drive.svg new file mode 100644 index 0000000..a1ce1fc --- /dev/null +++ b/apps/builder/public/icons/hard-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hashtag.svg b/apps/builder/public/icons/hashtag.svg new file mode 100644 index 0000000..f7f5cfa --- /dev/null +++ b/apps/builder/public/icons/hashtag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hat-cowboy-side.svg b/apps/builder/public/icons/hat-cowboy-side.svg new file mode 100644 index 0000000..8e2ff3e --- /dev/null +++ b/apps/builder/public/icons/hat-cowboy-side.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hat-cowboy.svg b/apps/builder/public/icons/hat-cowboy.svg new file mode 100644 index 0000000..9dfbeb8 --- /dev/null +++ b/apps/builder/public/icons/hat-cowboy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hat-wizard.svg b/apps/builder/public/icons/hat-wizard.svg new file mode 100644 index 0000000..caca6d1 --- /dev/null +++ b/apps/builder/public/icons/hat-wizard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/head-side-cough-slash.svg b/apps/builder/public/icons/head-side-cough-slash.svg new file mode 100644 index 0000000..948bebd --- /dev/null +++ b/apps/builder/public/icons/head-side-cough-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/head-side-cough.svg b/apps/builder/public/icons/head-side-cough.svg new file mode 100644 index 0000000..32ef039 --- /dev/null +++ b/apps/builder/public/icons/head-side-cough.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/head-side-mask.svg b/apps/builder/public/icons/head-side-mask.svg new file mode 100644 index 0000000..24450ff --- /dev/null +++ b/apps/builder/public/icons/head-side-mask.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/head-side-virus.svg b/apps/builder/public/icons/head-side-virus.svg new file mode 100644 index 0000000..bcf7b61 --- /dev/null +++ b/apps/builder/public/icons/head-side-virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heading.svg b/apps/builder/public/icons/heading.svg new file mode 100644 index 0000000..eae4bc7 --- /dev/null +++ b/apps/builder/public/icons/heading.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/headphones-simple.svg b/apps/builder/public/icons/headphones-simple.svg new file mode 100644 index 0000000..5de2aac --- /dev/null +++ b/apps/builder/public/icons/headphones-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/headphones.svg b/apps/builder/public/icons/headphones.svg new file mode 100644 index 0000000..89a7e43 --- /dev/null +++ b/apps/builder/public/icons/headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/headset.svg b/apps/builder/public/icons/headset.svg new file mode 100644 index 0000000..85eea46 --- /dev/null +++ b/apps/builder/public/icons/headset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-bolt.svg b/apps/builder/public/icons/heart-circle-bolt.svg new file mode 100644 index 0000000..8747054 --- /dev/null +++ b/apps/builder/public/icons/heart-circle-bolt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-check.svg b/apps/builder/public/icons/heart-circle-check.svg new file mode 100644 index 0000000..841d4d5 --- /dev/null +++ b/apps/builder/public/icons/heart-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-exclamation.svg b/apps/builder/public/icons/heart-circle-exclamation.svg new file mode 100644 index 0000000..1d45c36 --- /dev/null +++ b/apps/builder/public/icons/heart-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-minus.svg b/apps/builder/public/icons/heart-circle-minus.svg new file mode 100644 index 0000000..256768b --- /dev/null +++ b/apps/builder/public/icons/heart-circle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-plus.svg b/apps/builder/public/icons/heart-circle-plus.svg new file mode 100644 index 0000000..40586ad --- /dev/null +++ b/apps/builder/public/icons/heart-circle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-circle-xmark.svg b/apps/builder/public/icons/heart-circle-xmark.svg new file mode 100644 index 0000000..4bb0bce --- /dev/null +++ b/apps/builder/public/icons/heart-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-crack.svg b/apps/builder/public/icons/heart-crack.svg new file mode 100644 index 0000000..5c2a3a9 --- /dev/null +++ b/apps/builder/public/icons/heart-crack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart-pulse.svg b/apps/builder/public/icons/heart-pulse.svg new file mode 100644 index 0000000..20c626f --- /dev/null +++ b/apps/builder/public/icons/heart-pulse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/heart.svg b/apps/builder/public/icons/heart.svg new file mode 100644 index 0000000..b4f96c5 --- /dev/null +++ b/apps/builder/public/icons/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/helicopter-symbol.svg b/apps/builder/public/icons/helicopter-symbol.svg new file mode 100644 index 0000000..698ce8f --- /dev/null +++ b/apps/builder/public/icons/helicopter-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/helicopter.svg b/apps/builder/public/icons/helicopter.svg new file mode 100644 index 0000000..1993485 --- /dev/null +++ b/apps/builder/public/icons/helicopter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/helmet-safety.svg b/apps/builder/public/icons/helmet-safety.svg new file mode 100644 index 0000000..09ef9f1 --- /dev/null +++ b/apps/builder/public/icons/helmet-safety.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/helmet-un.svg b/apps/builder/public/icons/helmet-un.svg new file mode 100644 index 0000000..54e5057 --- /dev/null +++ b/apps/builder/public/icons/helmet-un.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/highlighter.svg b/apps/builder/public/icons/highlighter.svg new file mode 100644 index 0000000..1a6e410 --- /dev/null +++ b/apps/builder/public/icons/highlighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hill-avalanche.svg b/apps/builder/public/icons/hill-avalanche.svg new file mode 100644 index 0000000..f93422d --- /dev/null +++ b/apps/builder/public/icons/hill-avalanche.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hill-rockslide.svg b/apps/builder/public/icons/hill-rockslide.svg new file mode 100644 index 0000000..655e985 --- /dev/null +++ b/apps/builder/public/icons/hill-rockslide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hippo.svg b/apps/builder/public/icons/hippo.svg new file mode 100644 index 0000000..e65faf5 --- /dev/null +++ b/apps/builder/public/icons/hippo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hockey-puck.svg b/apps/builder/public/icons/hockey-puck.svg new file mode 100644 index 0000000..1a1d8ad --- /dev/null +++ b/apps/builder/public/icons/hockey-puck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/holly-berry.svg b/apps/builder/public/icons/holly-berry.svg new file mode 100644 index 0000000..6ae0f55 --- /dev/null +++ b/apps/builder/public/icons/holly-berry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/horse-head.svg b/apps/builder/public/icons/horse-head.svg new file mode 100644 index 0000000..6b8d52b --- /dev/null +++ b/apps/builder/public/icons/horse-head.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/horse.svg b/apps/builder/public/icons/horse.svg new file mode 100644 index 0000000..cc0dc76 --- /dev/null +++ b/apps/builder/public/icons/horse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hospital-user.svg b/apps/builder/public/icons/hospital-user.svg new file mode 100644 index 0000000..a8e21da --- /dev/null +++ b/apps/builder/public/icons/hospital-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hospital.svg b/apps/builder/public/icons/hospital.svg new file mode 100644 index 0000000..98461e0 --- /dev/null +++ b/apps/builder/public/icons/hospital.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hot-tub-person.svg b/apps/builder/public/icons/hot-tub-person.svg new file mode 100644 index 0000000..18b6264 --- /dev/null +++ b/apps/builder/public/icons/hot-tub-person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hotdog.svg b/apps/builder/public/icons/hotdog.svg new file mode 100644 index 0000000..e90fbe6 --- /dev/null +++ b/apps/builder/public/icons/hotdog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hotel.svg b/apps/builder/public/icons/hotel.svg new file mode 100644 index 0000000..344474c --- /dev/null +++ b/apps/builder/public/icons/hotel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hourglass-end.svg b/apps/builder/public/icons/hourglass-end.svg new file mode 100644 index 0000000..ccdece0 --- /dev/null +++ b/apps/builder/public/icons/hourglass-end.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hourglass-half.svg b/apps/builder/public/icons/hourglass-half.svg new file mode 100644 index 0000000..00b26a1 --- /dev/null +++ b/apps/builder/public/icons/hourglass-half.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hourglass-start.svg b/apps/builder/public/icons/hourglass-start.svg new file mode 100644 index 0000000..52291a8 --- /dev/null +++ b/apps/builder/public/icons/hourglass-start.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hourglass.svg b/apps/builder/public/icons/hourglass.svg new file mode 100644 index 0000000..0851a8c --- /dev/null +++ b/apps/builder/public/icons/hourglass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-chimney-crack.svg b/apps/builder/public/icons/house-chimney-crack.svg new file mode 100644 index 0000000..5436095 --- /dev/null +++ b/apps/builder/public/icons/house-chimney-crack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-chimney-medical.svg b/apps/builder/public/icons/house-chimney-medical.svg new file mode 100644 index 0000000..2a0b079 --- /dev/null +++ b/apps/builder/public/icons/house-chimney-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-chimney-user.svg b/apps/builder/public/icons/house-chimney-user.svg new file mode 100644 index 0000000..3f67844 --- /dev/null +++ b/apps/builder/public/icons/house-chimney-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-chimney-window.svg b/apps/builder/public/icons/house-chimney-window.svg new file mode 100644 index 0000000..bb4d7fc --- /dev/null +++ b/apps/builder/public/icons/house-chimney-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-chimney.svg b/apps/builder/public/icons/house-chimney.svg new file mode 100644 index 0000000..4a56a38 --- /dev/null +++ b/apps/builder/public/icons/house-chimney.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-circle-check.svg b/apps/builder/public/icons/house-circle-check.svg new file mode 100644 index 0000000..f6b6f39 --- /dev/null +++ b/apps/builder/public/icons/house-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-circle-exclamation.svg b/apps/builder/public/icons/house-circle-exclamation.svg new file mode 100644 index 0000000..97a3905 --- /dev/null +++ b/apps/builder/public/icons/house-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-circle-xmark.svg b/apps/builder/public/icons/house-circle-xmark.svg new file mode 100644 index 0000000..8fedb0b --- /dev/null +++ b/apps/builder/public/icons/house-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-crack.svg b/apps/builder/public/icons/house-crack.svg new file mode 100644 index 0000000..dd4da9b --- /dev/null +++ b/apps/builder/public/icons/house-crack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-fire.svg b/apps/builder/public/icons/house-fire.svg new file mode 100644 index 0000000..4f13407 --- /dev/null +++ b/apps/builder/public/icons/house-fire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-flag.svg b/apps/builder/public/icons/house-flag.svg new file mode 100644 index 0000000..f1fd325 --- /dev/null +++ b/apps/builder/public/icons/house-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-flood-water-circle-arrow-right.svg b/apps/builder/public/icons/house-flood-water-circle-arrow-right.svg new file mode 100644 index 0000000..d872eb0 --- /dev/null +++ b/apps/builder/public/icons/house-flood-water-circle-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-flood-water.svg b/apps/builder/public/icons/house-flood-water.svg new file mode 100644 index 0000000..3bdb969 --- /dev/null +++ b/apps/builder/public/icons/house-flood-water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-laptop.svg b/apps/builder/public/icons/house-laptop.svg new file mode 100644 index 0000000..b71484c --- /dev/null +++ b/apps/builder/public/icons/house-laptop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-lock.svg b/apps/builder/public/icons/house-lock.svg new file mode 100644 index 0000000..63ed26d --- /dev/null +++ b/apps/builder/public/icons/house-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-medical-circle-check.svg b/apps/builder/public/icons/house-medical-circle-check.svg new file mode 100644 index 0000000..54b95ae --- /dev/null +++ b/apps/builder/public/icons/house-medical-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-medical-circle-exclamation.svg b/apps/builder/public/icons/house-medical-circle-exclamation.svg new file mode 100644 index 0000000..00b522f --- /dev/null +++ b/apps/builder/public/icons/house-medical-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-medical-circle-xmark.svg b/apps/builder/public/icons/house-medical-circle-xmark.svg new file mode 100644 index 0000000..8314c62 --- /dev/null +++ b/apps/builder/public/icons/house-medical-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-medical-flag.svg b/apps/builder/public/icons/house-medical-flag.svg new file mode 100644 index 0000000..9ccf0a5 --- /dev/null +++ b/apps/builder/public/icons/house-medical-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-medical.svg b/apps/builder/public/icons/house-medical.svg new file mode 100644 index 0000000..d2d15e7 --- /dev/null +++ b/apps/builder/public/icons/house-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-signal.svg b/apps/builder/public/icons/house-signal.svg new file mode 100644 index 0000000..4b1da12 --- /dev/null +++ b/apps/builder/public/icons/house-signal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-tsunami.svg b/apps/builder/public/icons/house-tsunami.svg new file mode 100644 index 0000000..91bf285 --- /dev/null +++ b/apps/builder/public/icons/house-tsunami.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house-user.svg b/apps/builder/public/icons/house-user.svg new file mode 100644 index 0000000..eed98c7 --- /dev/null +++ b/apps/builder/public/icons/house-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/house.svg b/apps/builder/public/icons/house.svg new file mode 100644 index 0000000..4fe5f30 --- /dev/null +++ b/apps/builder/public/icons/house.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hryvnia-sign.svg b/apps/builder/public/icons/hryvnia-sign.svg new file mode 100644 index 0000000..ed28260 --- /dev/null +++ b/apps/builder/public/icons/hryvnia-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/hurricane.svg b/apps/builder/public/icons/hurricane.svg new file mode 100644 index 0000000..66df657 --- /dev/null +++ b/apps/builder/public/icons/hurricane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/i-cursor.svg b/apps/builder/public/icons/i-cursor.svg new file mode 100644 index 0000000..a28cdfb --- /dev/null +++ b/apps/builder/public/icons/i-cursor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/i.svg b/apps/builder/public/icons/i.svg new file mode 100644 index 0000000..05fb112 --- /dev/null +++ b/apps/builder/public/icons/i.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ice-cream.svg b/apps/builder/public/icons/ice-cream.svg new file mode 100644 index 0000000..de0e895 --- /dev/null +++ b/apps/builder/public/icons/ice-cream.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/icicles.svg b/apps/builder/public/icons/icicles.svg new file mode 100644 index 0000000..dafef48 --- /dev/null +++ b/apps/builder/public/icons/icicles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/icons.svg b/apps/builder/public/icons/icons.svg new file mode 100644 index 0000000..5292ef5 --- /dev/null +++ b/apps/builder/public/icons/icons.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/id-badge.svg b/apps/builder/public/icons/id-badge.svg new file mode 100644 index 0000000..9810ef3 --- /dev/null +++ b/apps/builder/public/icons/id-badge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/id-card-clip.svg b/apps/builder/public/icons/id-card-clip.svg new file mode 100644 index 0000000..da21685 --- /dev/null +++ b/apps/builder/public/icons/id-card-clip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/id-card.svg b/apps/builder/public/icons/id-card.svg new file mode 100644 index 0000000..807d67f --- /dev/null +++ b/apps/builder/public/icons/id-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/igloo.svg b/apps/builder/public/icons/igloo.svg new file mode 100644 index 0000000..a75ac30 --- /dev/null +++ b/apps/builder/public/icons/igloo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/image-portrait.svg b/apps/builder/public/icons/image-portrait.svg new file mode 100644 index 0000000..b34b087 --- /dev/null +++ b/apps/builder/public/icons/image-portrait.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/image.svg b/apps/builder/public/icons/image.svg new file mode 100644 index 0000000..c09909c --- /dev/null +++ b/apps/builder/public/icons/image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/images.svg b/apps/builder/public/icons/images.svg new file mode 100644 index 0000000..8e00421 --- /dev/null +++ b/apps/builder/public/icons/images.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/inbox.svg b/apps/builder/public/icons/inbox.svg new file mode 100644 index 0000000..1e0529b --- /dev/null +++ b/apps/builder/public/icons/inbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/indent.svg b/apps/builder/public/icons/indent.svg new file mode 100644 index 0000000..d147782 --- /dev/null +++ b/apps/builder/public/icons/indent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/indian-rupee-sign.svg b/apps/builder/public/icons/indian-rupee-sign.svg new file mode 100644 index 0000000..49f6bb4 --- /dev/null +++ b/apps/builder/public/icons/indian-rupee-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/industry.svg b/apps/builder/public/icons/industry.svg new file mode 100644 index 0000000..4c9a8a2 --- /dev/null +++ b/apps/builder/public/icons/industry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/infinity.svg b/apps/builder/public/icons/infinity.svg new file mode 100644 index 0000000..9459c37 --- /dev/null +++ b/apps/builder/public/icons/infinity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/info.svg b/apps/builder/public/icons/info.svg new file mode 100644 index 0000000..88d2dc6 --- /dev/null +++ b/apps/builder/public/icons/info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/italic.svg b/apps/builder/public/icons/italic.svg new file mode 100644 index 0000000..0653990 --- /dev/null +++ b/apps/builder/public/icons/italic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/j.svg b/apps/builder/public/icons/j.svg new file mode 100644 index 0000000..750eb48 --- /dev/null +++ b/apps/builder/public/icons/j.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jar-wheat.svg b/apps/builder/public/icons/jar-wheat.svg new file mode 100644 index 0000000..64e7824 --- /dev/null +++ b/apps/builder/public/icons/jar-wheat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jar.svg b/apps/builder/public/icons/jar.svg new file mode 100644 index 0000000..265bcf5 --- /dev/null +++ b/apps/builder/public/icons/jar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jedi.svg b/apps/builder/public/icons/jedi.svg new file mode 100644 index 0000000..fe0504f --- /dev/null +++ b/apps/builder/public/icons/jedi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jet-fighter-up.svg b/apps/builder/public/icons/jet-fighter-up.svg new file mode 100644 index 0000000..2830e37 --- /dev/null +++ b/apps/builder/public/icons/jet-fighter-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jet-fighter.svg b/apps/builder/public/icons/jet-fighter.svg new file mode 100644 index 0000000..b6ecdef --- /dev/null +++ b/apps/builder/public/icons/jet-fighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/joint.svg b/apps/builder/public/icons/joint.svg new file mode 100644 index 0000000..50a4994 --- /dev/null +++ b/apps/builder/public/icons/joint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/jug-detergent.svg b/apps/builder/public/icons/jug-detergent.svg new file mode 100644 index 0000000..a4c9ef2 --- /dev/null +++ b/apps/builder/public/icons/jug-detergent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/k.svg b/apps/builder/public/icons/k.svg new file mode 100644 index 0000000..18fb097 --- /dev/null +++ b/apps/builder/public/icons/k.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/kaaba.svg b/apps/builder/public/icons/kaaba.svg new file mode 100644 index 0000000..53a00cb --- /dev/null +++ b/apps/builder/public/icons/kaaba.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/key.svg b/apps/builder/public/icons/key.svg new file mode 100644 index 0000000..2e911a2 --- /dev/null +++ b/apps/builder/public/icons/key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/keyboard.svg b/apps/builder/public/icons/keyboard.svg new file mode 100644 index 0000000..c71c549 --- /dev/null +++ b/apps/builder/public/icons/keyboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/khanda.svg b/apps/builder/public/icons/khanda.svg new file mode 100644 index 0000000..fb25596 --- /dev/null +++ b/apps/builder/public/icons/khanda.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/kip-sign.svg b/apps/builder/public/icons/kip-sign.svg new file mode 100644 index 0000000..1e38416 --- /dev/null +++ b/apps/builder/public/icons/kip-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/kit-medical.svg b/apps/builder/public/icons/kit-medical.svg new file mode 100644 index 0000000..d74fe53 --- /dev/null +++ b/apps/builder/public/icons/kit-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/kitchen-set.svg b/apps/builder/public/icons/kitchen-set.svg new file mode 100644 index 0000000..f800e4a --- /dev/null +++ b/apps/builder/public/icons/kitchen-set.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/kiwi-bird.svg b/apps/builder/public/icons/kiwi-bird.svg new file mode 100644 index 0000000..40c9f89 --- /dev/null +++ b/apps/builder/public/icons/kiwi-bird.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/l.svg b/apps/builder/public/icons/l.svg new file mode 100644 index 0000000..c72b00a --- /dev/null +++ b/apps/builder/public/icons/l.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/land-mine-on.svg b/apps/builder/public/icons/land-mine-on.svg new file mode 100644 index 0000000..21c4b39 --- /dev/null +++ b/apps/builder/public/icons/land-mine-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/landmark-dome.svg b/apps/builder/public/icons/landmark-dome.svg new file mode 100644 index 0000000..e73d54c --- /dev/null +++ b/apps/builder/public/icons/landmark-dome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/landmark-flag.svg b/apps/builder/public/icons/landmark-flag.svg new file mode 100644 index 0000000..c49639c --- /dev/null +++ b/apps/builder/public/icons/landmark-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/landmark.svg b/apps/builder/public/icons/landmark.svg new file mode 100644 index 0000000..408b320 --- /dev/null +++ b/apps/builder/public/icons/landmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/language.svg b/apps/builder/public/icons/language.svg new file mode 100644 index 0000000..dec9553 --- /dev/null +++ b/apps/builder/public/icons/language.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/laptop-code.svg b/apps/builder/public/icons/laptop-code.svg new file mode 100644 index 0000000..2b977e0 --- /dev/null +++ b/apps/builder/public/icons/laptop-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/laptop-file.svg b/apps/builder/public/icons/laptop-file.svg new file mode 100644 index 0000000..758cbac --- /dev/null +++ b/apps/builder/public/icons/laptop-file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/laptop-medical.svg b/apps/builder/public/icons/laptop-medical.svg new file mode 100644 index 0000000..627906a --- /dev/null +++ b/apps/builder/public/icons/laptop-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/laptop.svg b/apps/builder/public/icons/laptop.svg new file mode 100644 index 0000000..edcc9d1 --- /dev/null +++ b/apps/builder/public/icons/laptop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lari-sign.svg b/apps/builder/public/icons/lari-sign.svg new file mode 100644 index 0000000..468d40d --- /dev/null +++ b/apps/builder/public/icons/lari-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/layer-group.svg b/apps/builder/public/icons/layer-group.svg new file mode 100644 index 0000000..a8c8824 --- /dev/null +++ b/apps/builder/public/icons/layer-group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/leaf.svg b/apps/builder/public/icons/leaf.svg new file mode 100644 index 0000000..2951d19 --- /dev/null +++ b/apps/builder/public/icons/leaf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/left-long.svg b/apps/builder/public/icons/left-long.svg new file mode 100644 index 0000000..7eb4936 --- /dev/null +++ b/apps/builder/public/icons/left-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/left-right.svg b/apps/builder/public/icons/left-right.svg new file mode 100644 index 0000000..9d48095 --- /dev/null +++ b/apps/builder/public/icons/left-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lemon.svg b/apps/builder/public/icons/lemon.svg new file mode 100644 index 0000000..a7ef9f7 --- /dev/null +++ b/apps/builder/public/icons/lemon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/less-than-equal.svg b/apps/builder/public/icons/less-than-equal.svg new file mode 100644 index 0000000..11d2a77 --- /dev/null +++ b/apps/builder/public/icons/less-than-equal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/less-than.svg b/apps/builder/public/icons/less-than.svg new file mode 100644 index 0000000..0f32c4c --- /dev/null +++ b/apps/builder/public/icons/less-than.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/life-ring.svg b/apps/builder/public/icons/life-ring.svg new file mode 100644 index 0000000..91afed0 --- /dev/null +++ b/apps/builder/public/icons/life-ring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lightbulb.svg b/apps/builder/public/icons/lightbulb.svg new file mode 100644 index 0000000..f5eca74 --- /dev/null +++ b/apps/builder/public/icons/lightbulb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lines-leaning.svg b/apps/builder/public/icons/lines-leaning.svg new file mode 100644 index 0000000..f12fd55 --- /dev/null +++ b/apps/builder/public/icons/lines-leaning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/link-slash.svg b/apps/builder/public/icons/link-slash.svg new file mode 100644 index 0000000..5701966 --- /dev/null +++ b/apps/builder/public/icons/link-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/link.svg b/apps/builder/public/icons/link.svg new file mode 100644 index 0000000..3f79141 --- /dev/null +++ b/apps/builder/public/icons/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lira-sign.svg b/apps/builder/public/icons/lira-sign.svg new file mode 100644 index 0000000..0eb4f41 --- /dev/null +++ b/apps/builder/public/icons/lira-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/list-check.svg b/apps/builder/public/icons/list-check.svg new file mode 100644 index 0000000..09d74e2 --- /dev/null +++ b/apps/builder/public/icons/list-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/list-ol.svg b/apps/builder/public/icons/list-ol.svg new file mode 100644 index 0000000..a240417 --- /dev/null +++ b/apps/builder/public/icons/list-ol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/list-ul.svg b/apps/builder/public/icons/list-ul.svg new file mode 100644 index 0000000..35b0bf2 --- /dev/null +++ b/apps/builder/public/icons/list-ul.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/list.svg b/apps/builder/public/icons/list.svg new file mode 100644 index 0000000..7190c58 --- /dev/null +++ b/apps/builder/public/icons/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/litecoin-sign.svg b/apps/builder/public/icons/litecoin-sign.svg new file mode 100644 index 0000000..3fdb022 --- /dev/null +++ b/apps/builder/public/icons/litecoin-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/location-arrow.svg b/apps/builder/public/icons/location-arrow.svg new file mode 100644 index 0000000..23d66c6 --- /dev/null +++ b/apps/builder/public/icons/location-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/location-crosshairs.svg b/apps/builder/public/icons/location-crosshairs.svg new file mode 100644 index 0000000..e34e167 --- /dev/null +++ b/apps/builder/public/icons/location-crosshairs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/location-dot.svg b/apps/builder/public/icons/location-dot.svg new file mode 100644 index 0000000..e8868d2 --- /dev/null +++ b/apps/builder/public/icons/location-dot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/location-pin-lock.svg b/apps/builder/public/icons/location-pin-lock.svg new file mode 100644 index 0000000..100791d --- /dev/null +++ b/apps/builder/public/icons/location-pin-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/location-pin.svg b/apps/builder/public/icons/location-pin.svg new file mode 100644 index 0000000..19a96c1 --- /dev/null +++ b/apps/builder/public/icons/location-pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lock-open.svg b/apps/builder/public/icons/lock-open.svg new file mode 100644 index 0000000..5a8d1fd --- /dev/null +++ b/apps/builder/public/icons/lock-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lock.svg b/apps/builder/public/icons/lock.svg new file mode 100644 index 0000000..6f05125 --- /dev/null +++ b/apps/builder/public/icons/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/locust.svg b/apps/builder/public/icons/locust.svg new file mode 100644 index 0000000..171fbe1 --- /dev/null +++ b/apps/builder/public/icons/locust.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lungs-virus.svg b/apps/builder/public/icons/lungs-virus.svg new file mode 100644 index 0000000..a975bc6 --- /dev/null +++ b/apps/builder/public/icons/lungs-virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/lungs.svg b/apps/builder/public/icons/lungs.svg new file mode 100644 index 0000000..4de4da7 --- /dev/null +++ b/apps/builder/public/icons/lungs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/m.svg b/apps/builder/public/icons/m.svg new file mode 100644 index 0000000..214ce6e --- /dev/null +++ b/apps/builder/public/icons/m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnet.svg b/apps/builder/public/icons/magnet.svg new file mode 100644 index 0000000..c58dc3d --- /dev/null +++ b/apps/builder/public/icons/magnet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-arrow-right.svg b/apps/builder/public/icons/magnifying-glass-arrow-right.svg new file mode 100644 index 0000000..d0849e6 --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-chart.svg b/apps/builder/public/icons/magnifying-glass-chart.svg new file mode 100644 index 0000000..8585bc7 --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-dollar.svg b/apps/builder/public/icons/magnifying-glass-dollar.svg new file mode 100644 index 0000000..1d34d5c --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-location.svg b/apps/builder/public/icons/magnifying-glass-location.svg new file mode 100644 index 0000000..f478637 --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-minus.svg b/apps/builder/public/icons/magnifying-glass-minus.svg new file mode 100644 index 0000000..543bdac --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass-plus.svg b/apps/builder/public/icons/magnifying-glass-plus.svg new file mode 100644 index 0000000..f09d33a --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/magnifying-glass.svg b/apps/builder/public/icons/magnifying-glass.svg new file mode 100644 index 0000000..bdbd37b --- /dev/null +++ b/apps/builder/public/icons/magnifying-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/manat-sign.svg b/apps/builder/public/icons/manat-sign.svg new file mode 100644 index 0000000..8968e73 --- /dev/null +++ b/apps/builder/public/icons/manat-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/map-location-dot.svg b/apps/builder/public/icons/map-location-dot.svg new file mode 100644 index 0000000..6b06486 --- /dev/null +++ b/apps/builder/public/icons/map-location-dot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/map-location.svg b/apps/builder/public/icons/map-location.svg new file mode 100644 index 0000000..9c7ce0b --- /dev/null +++ b/apps/builder/public/icons/map-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/map-pin.svg b/apps/builder/public/icons/map-pin.svg new file mode 100644 index 0000000..6e34074 --- /dev/null +++ b/apps/builder/public/icons/map-pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/map.svg b/apps/builder/public/icons/map.svg new file mode 100644 index 0000000..1d1f117 --- /dev/null +++ b/apps/builder/public/icons/map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/marker.svg b/apps/builder/public/icons/marker.svg new file mode 100644 index 0000000..af0bf77 --- /dev/null +++ b/apps/builder/public/icons/marker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-and-venus-burst.svg b/apps/builder/public/icons/mars-and-venus-burst.svg new file mode 100644 index 0000000..9e85da5 --- /dev/null +++ b/apps/builder/public/icons/mars-and-venus-burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-and-venus.svg b/apps/builder/public/icons/mars-and-venus.svg new file mode 100644 index 0000000..0f061d8 --- /dev/null +++ b/apps/builder/public/icons/mars-and-venus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-double.svg b/apps/builder/public/icons/mars-double.svg new file mode 100644 index 0000000..a9d919b --- /dev/null +++ b/apps/builder/public/icons/mars-double.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-stroke-right.svg b/apps/builder/public/icons/mars-stroke-right.svg new file mode 100644 index 0000000..187f90c --- /dev/null +++ b/apps/builder/public/icons/mars-stroke-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-stroke-up.svg b/apps/builder/public/icons/mars-stroke-up.svg new file mode 100644 index 0000000..15ca6c6 --- /dev/null +++ b/apps/builder/public/icons/mars-stroke-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars-stroke.svg b/apps/builder/public/icons/mars-stroke.svg new file mode 100644 index 0000000..a33c76d --- /dev/null +++ b/apps/builder/public/icons/mars-stroke.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mars.svg b/apps/builder/public/icons/mars.svg new file mode 100644 index 0000000..2c4b904 --- /dev/null +++ b/apps/builder/public/icons/mars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/martini-glass-citrus.svg b/apps/builder/public/icons/martini-glass-citrus.svg new file mode 100644 index 0000000..3248834 --- /dev/null +++ b/apps/builder/public/icons/martini-glass-citrus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/martini-glass-empty.svg b/apps/builder/public/icons/martini-glass-empty.svg new file mode 100644 index 0000000..b006b8a --- /dev/null +++ b/apps/builder/public/icons/martini-glass-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/martini-glass.svg b/apps/builder/public/icons/martini-glass.svg new file mode 100644 index 0000000..181d31d --- /dev/null +++ b/apps/builder/public/icons/martini-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mask-face.svg b/apps/builder/public/icons/mask-face.svg new file mode 100644 index 0000000..2f5c8ae --- /dev/null +++ b/apps/builder/public/icons/mask-face.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mask-ventilator.svg b/apps/builder/public/icons/mask-ventilator.svg new file mode 100644 index 0000000..7eb0621 --- /dev/null +++ b/apps/builder/public/icons/mask-ventilator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mask.svg b/apps/builder/public/icons/mask.svg new file mode 100644 index 0000000..d4ef7be --- /dev/null +++ b/apps/builder/public/icons/mask.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/masks-theater.svg b/apps/builder/public/icons/masks-theater.svg new file mode 100644 index 0000000..c9df7e2 --- /dev/null +++ b/apps/builder/public/icons/masks-theater.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mattress-pillow.svg b/apps/builder/public/icons/mattress-pillow.svg new file mode 100644 index 0000000..6995622 --- /dev/null +++ b/apps/builder/public/icons/mattress-pillow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/maximize.svg b/apps/builder/public/icons/maximize.svg new file mode 100644 index 0000000..31334b4 --- /dev/null +++ b/apps/builder/public/icons/maximize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/medal.svg b/apps/builder/public/icons/medal.svg new file mode 100644 index 0000000..ac8da21 --- /dev/null +++ b/apps/builder/public/icons/medal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/memory.svg b/apps/builder/public/icons/memory.svg new file mode 100644 index 0000000..d01e379 --- /dev/null +++ b/apps/builder/public/icons/memory.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/menorah.svg b/apps/builder/public/icons/menorah.svg new file mode 100644 index 0000000..f613a95 --- /dev/null +++ b/apps/builder/public/icons/menorah.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mercury.svg b/apps/builder/public/icons/mercury.svg new file mode 100644 index 0000000..d5fe415 --- /dev/null +++ b/apps/builder/public/icons/mercury.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/message.svg b/apps/builder/public/icons/message.svg new file mode 100644 index 0000000..877a294 --- /dev/null +++ b/apps/builder/public/icons/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/meteor.svg b/apps/builder/public/icons/meteor.svg new file mode 100644 index 0000000..f408bd5 --- /dev/null +++ b/apps/builder/public/icons/meteor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microchip.svg b/apps/builder/public/icons/microchip.svg new file mode 100644 index 0000000..987caf7 --- /dev/null +++ b/apps/builder/public/icons/microchip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microphone-lines-slash.svg b/apps/builder/public/icons/microphone-lines-slash.svg new file mode 100644 index 0000000..58199d2 --- /dev/null +++ b/apps/builder/public/icons/microphone-lines-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microphone-lines.svg b/apps/builder/public/icons/microphone-lines.svg new file mode 100644 index 0000000..fb38f2d --- /dev/null +++ b/apps/builder/public/icons/microphone-lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microphone-slash.svg b/apps/builder/public/icons/microphone-slash.svg new file mode 100644 index 0000000..eae8b04 --- /dev/null +++ b/apps/builder/public/icons/microphone-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microphone.svg b/apps/builder/public/icons/microphone.svg new file mode 100644 index 0000000..5e01a66 --- /dev/null +++ b/apps/builder/public/icons/microphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/microscope.svg b/apps/builder/public/icons/microscope.svg new file mode 100644 index 0000000..0946a77 --- /dev/null +++ b/apps/builder/public/icons/microscope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mill-sign.svg b/apps/builder/public/icons/mill-sign.svg new file mode 100644 index 0000000..fa561b9 --- /dev/null +++ b/apps/builder/public/icons/mill-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/minimize.svg b/apps/builder/public/icons/minimize.svg new file mode 100644 index 0000000..b509a7c --- /dev/null +++ b/apps/builder/public/icons/minimize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/minus.svg b/apps/builder/public/icons/minus.svg new file mode 100644 index 0000000..a71d514 --- /dev/null +++ b/apps/builder/public/icons/minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mitten.svg b/apps/builder/public/icons/mitten.svg new file mode 100644 index 0000000..7d8a99a --- /dev/null +++ b/apps/builder/public/icons/mitten.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mobile-button.svg b/apps/builder/public/icons/mobile-button.svg new file mode 100644 index 0000000..15c9763 --- /dev/null +++ b/apps/builder/public/icons/mobile-button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mobile-retro.svg b/apps/builder/public/icons/mobile-retro.svg new file mode 100644 index 0000000..105c89f --- /dev/null +++ b/apps/builder/public/icons/mobile-retro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mobile-screen-button.svg b/apps/builder/public/icons/mobile-screen-button.svg new file mode 100644 index 0000000..01a0188 --- /dev/null +++ b/apps/builder/public/icons/mobile-screen-button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mobile-screen.svg b/apps/builder/public/icons/mobile-screen.svg new file mode 100644 index 0000000..910753f --- /dev/null +++ b/apps/builder/public/icons/mobile-screen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mobile.svg b/apps/builder/public/icons/mobile.svg new file mode 100644 index 0000000..3cf856b --- /dev/null +++ b/apps/builder/public/icons/mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-1-wave.svg b/apps/builder/public/icons/money-bill-1-wave.svg new file mode 100644 index 0000000..964a977 --- /dev/null +++ b/apps/builder/public/icons/money-bill-1-wave.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-1.svg b/apps/builder/public/icons/money-bill-1.svg new file mode 100644 index 0000000..6cbc09f --- /dev/null +++ b/apps/builder/public/icons/money-bill-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-transfer.svg b/apps/builder/public/icons/money-bill-transfer.svg new file mode 100644 index 0000000..9410a2e --- /dev/null +++ b/apps/builder/public/icons/money-bill-transfer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-trend-up.svg b/apps/builder/public/icons/money-bill-trend-up.svg new file mode 100644 index 0000000..5f38ac0 --- /dev/null +++ b/apps/builder/public/icons/money-bill-trend-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-wave.svg b/apps/builder/public/icons/money-bill-wave.svg new file mode 100644 index 0000000..105e6c4 --- /dev/null +++ b/apps/builder/public/icons/money-bill-wave.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill-wheat.svg b/apps/builder/public/icons/money-bill-wheat.svg new file mode 100644 index 0000000..2163647 --- /dev/null +++ b/apps/builder/public/icons/money-bill-wheat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bill.svg b/apps/builder/public/icons/money-bill.svg new file mode 100644 index 0000000..9af40b7 --- /dev/null +++ b/apps/builder/public/icons/money-bill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-bills.svg b/apps/builder/public/icons/money-bills.svg new file mode 100644 index 0000000..df25850 --- /dev/null +++ b/apps/builder/public/icons/money-bills.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-check-dollar.svg b/apps/builder/public/icons/money-check-dollar.svg new file mode 100644 index 0000000..d152780 --- /dev/null +++ b/apps/builder/public/icons/money-check-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/money-check.svg b/apps/builder/public/icons/money-check.svg new file mode 100644 index 0000000..a807130 --- /dev/null +++ b/apps/builder/public/icons/money-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/monument.svg b/apps/builder/public/icons/monument.svg new file mode 100644 index 0000000..65777c5 --- /dev/null +++ b/apps/builder/public/icons/monument.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/moon.svg b/apps/builder/public/icons/moon.svg new file mode 100644 index 0000000..a000929 --- /dev/null +++ b/apps/builder/public/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mortar-pestle.svg b/apps/builder/public/icons/mortar-pestle.svg new file mode 100644 index 0000000..701095d --- /dev/null +++ b/apps/builder/public/icons/mortar-pestle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mosque.svg b/apps/builder/public/icons/mosque.svg new file mode 100644 index 0000000..c64a246 --- /dev/null +++ b/apps/builder/public/icons/mosque.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mosquito-net.svg b/apps/builder/public/icons/mosquito-net.svg new file mode 100644 index 0000000..09c6b25 --- /dev/null +++ b/apps/builder/public/icons/mosquito-net.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mosquito.svg b/apps/builder/public/icons/mosquito.svg new file mode 100644 index 0000000..0790c3a --- /dev/null +++ b/apps/builder/public/icons/mosquito.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/motorcycle.svg b/apps/builder/public/icons/motorcycle.svg new file mode 100644 index 0000000..4ecaff9 --- /dev/null +++ b/apps/builder/public/icons/motorcycle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mound.svg b/apps/builder/public/icons/mound.svg new file mode 100644 index 0000000..606b636 --- /dev/null +++ b/apps/builder/public/icons/mound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mountain-city.svg b/apps/builder/public/icons/mountain-city.svg new file mode 100644 index 0000000..fe98212 --- /dev/null +++ b/apps/builder/public/icons/mountain-city.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mountain-sun.svg b/apps/builder/public/icons/mountain-sun.svg new file mode 100644 index 0000000..86fdae6 --- /dev/null +++ b/apps/builder/public/icons/mountain-sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mountain.svg b/apps/builder/public/icons/mountain.svg new file mode 100644 index 0000000..204c7ee --- /dev/null +++ b/apps/builder/public/icons/mountain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mug-hot.svg b/apps/builder/public/icons/mug-hot.svg new file mode 100644 index 0000000..37643d5 --- /dev/null +++ b/apps/builder/public/icons/mug-hot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/mug-saucer.svg b/apps/builder/public/icons/mug-saucer.svg new file mode 100644 index 0000000..77809b2 --- /dev/null +++ b/apps/builder/public/icons/mug-saucer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/music.svg b/apps/builder/public/icons/music.svg new file mode 100644 index 0000000..5602e5f --- /dev/null +++ b/apps/builder/public/icons/music.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/n.svg b/apps/builder/public/icons/n.svg new file mode 100644 index 0000000..c8fbeff --- /dev/null +++ b/apps/builder/public/icons/n.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/naira-sign.svg b/apps/builder/public/icons/naira-sign.svg new file mode 100644 index 0000000..0775390 --- /dev/null +++ b/apps/builder/public/icons/naira-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/network-wired.svg b/apps/builder/public/icons/network-wired.svg new file mode 100644 index 0000000..4de1eae --- /dev/null +++ b/apps/builder/public/icons/network-wired.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/neuter.svg b/apps/builder/public/icons/neuter.svg new file mode 100644 index 0000000..42cefc3 --- /dev/null +++ b/apps/builder/public/icons/neuter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/newspaper.svg b/apps/builder/public/icons/newspaper.svg new file mode 100644 index 0000000..af99a6a --- /dev/null +++ b/apps/builder/public/icons/newspaper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/not-equal.svg b/apps/builder/public/icons/not-equal.svg new file mode 100644 index 0000000..aa6dcd3 --- /dev/null +++ b/apps/builder/public/icons/not-equal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/notdef.svg b/apps/builder/public/icons/notdef.svg new file mode 100644 index 0000000..3996b8d --- /dev/null +++ b/apps/builder/public/icons/notdef.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/note-sticky.svg b/apps/builder/public/icons/note-sticky.svg new file mode 100644 index 0000000..3d62b8d --- /dev/null +++ b/apps/builder/public/icons/note-sticky.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/notes-medical.svg b/apps/builder/public/icons/notes-medical.svg new file mode 100644 index 0000000..8a94781 --- /dev/null +++ b/apps/builder/public/icons/notes-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/o.svg b/apps/builder/public/icons/o.svg new file mode 100644 index 0000000..dfee7cd --- /dev/null +++ b/apps/builder/public/icons/o.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/object-group.svg b/apps/builder/public/icons/object-group.svg new file mode 100644 index 0000000..78f227b --- /dev/null +++ b/apps/builder/public/icons/object-group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/object-ungroup.svg b/apps/builder/public/icons/object-ungroup.svg new file mode 100644 index 0000000..cf5e334 --- /dev/null +++ b/apps/builder/public/icons/object-ungroup.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/oil-can.svg b/apps/builder/public/icons/oil-can.svg new file mode 100644 index 0000000..499e0b0 --- /dev/null +++ b/apps/builder/public/icons/oil-can.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/oil-well.svg b/apps/builder/public/icons/oil-well.svg new file mode 100644 index 0000000..a7794a2 --- /dev/null +++ b/apps/builder/public/icons/oil-well.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/om.svg b/apps/builder/public/icons/om.svg new file mode 100644 index 0000000..58d8999 --- /dev/null +++ b/apps/builder/public/icons/om.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/otter.svg b/apps/builder/public/icons/otter.svg new file mode 100644 index 0000000..d830a42 --- /dev/null +++ b/apps/builder/public/icons/otter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/outdent.svg b/apps/builder/public/icons/outdent.svg new file mode 100644 index 0000000..93334b4 --- /dev/null +++ b/apps/builder/public/icons/outdent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/p.svg b/apps/builder/public/icons/p.svg new file mode 100644 index 0000000..a80ea37 --- /dev/null +++ b/apps/builder/public/icons/p.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pager.svg b/apps/builder/public/icons/pager.svg new file mode 100644 index 0000000..1c88d4a --- /dev/null +++ b/apps/builder/public/icons/pager.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paint-roller.svg b/apps/builder/public/icons/paint-roller.svg new file mode 100644 index 0000000..6256fdc --- /dev/null +++ b/apps/builder/public/icons/paint-roller.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paintbrush.svg b/apps/builder/public/icons/paintbrush.svg new file mode 100644 index 0000000..94449f4 --- /dev/null +++ b/apps/builder/public/icons/paintbrush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/palette.svg b/apps/builder/public/icons/palette.svg new file mode 100644 index 0000000..123537f --- /dev/null +++ b/apps/builder/public/icons/palette.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pallet.svg b/apps/builder/public/icons/pallet.svg new file mode 100644 index 0000000..ea7f2de --- /dev/null +++ b/apps/builder/public/icons/pallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/panorama.svg b/apps/builder/public/icons/panorama.svg new file mode 100644 index 0000000..e8ac4aa --- /dev/null +++ b/apps/builder/public/icons/panorama.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paper-plane.svg b/apps/builder/public/icons/paper-plane.svg new file mode 100644 index 0000000..3226184 --- /dev/null +++ b/apps/builder/public/icons/paper-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paperclip.svg b/apps/builder/public/icons/paperclip.svg new file mode 100644 index 0000000..ab1e07a --- /dev/null +++ b/apps/builder/public/icons/paperclip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/parachute-box.svg b/apps/builder/public/icons/parachute-box.svg new file mode 100644 index 0000000..35cbf39 --- /dev/null +++ b/apps/builder/public/icons/parachute-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paragraph.svg b/apps/builder/public/icons/paragraph.svg new file mode 100644 index 0000000..47335d6 --- /dev/null +++ b/apps/builder/public/icons/paragraph.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/passport.svg b/apps/builder/public/icons/passport.svg new file mode 100644 index 0000000..8a36f3e --- /dev/null +++ b/apps/builder/public/icons/passport.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paste.svg b/apps/builder/public/icons/paste.svg new file mode 100644 index 0000000..6547c15 --- /dev/null +++ b/apps/builder/public/icons/paste.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pause.svg b/apps/builder/public/icons/pause.svg new file mode 100644 index 0000000..474ce1c --- /dev/null +++ b/apps/builder/public/icons/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/paw.svg b/apps/builder/public/icons/paw.svg new file mode 100644 index 0000000..1148615 --- /dev/null +++ b/apps/builder/public/icons/paw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/peace.svg b/apps/builder/public/icons/peace.svg new file mode 100644 index 0000000..726b798 --- /dev/null +++ b/apps/builder/public/icons/peace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen-clip.svg b/apps/builder/public/icons/pen-clip.svg new file mode 100644 index 0000000..dd52867 --- /dev/null +++ b/apps/builder/public/icons/pen-clip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen-fancy.svg b/apps/builder/public/icons/pen-fancy.svg new file mode 100644 index 0000000..8468378 --- /dev/null +++ b/apps/builder/public/icons/pen-fancy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen-nib.svg b/apps/builder/public/icons/pen-nib.svg new file mode 100644 index 0000000..8cac478 --- /dev/null +++ b/apps/builder/public/icons/pen-nib.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen-ruler.svg b/apps/builder/public/icons/pen-ruler.svg new file mode 100644 index 0000000..f3d344c --- /dev/null +++ b/apps/builder/public/icons/pen-ruler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen-to-square.svg b/apps/builder/public/icons/pen-to-square.svg new file mode 100644 index 0000000..7bb9685 --- /dev/null +++ b/apps/builder/public/icons/pen-to-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pen.svg b/apps/builder/public/icons/pen.svg new file mode 100644 index 0000000..2574d1d --- /dev/null +++ b/apps/builder/public/icons/pen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pencil.svg b/apps/builder/public/icons/pencil.svg new file mode 100644 index 0000000..07b5fee --- /dev/null +++ b/apps/builder/public/icons/pencil.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-arrows.svg b/apps/builder/public/icons/people-arrows.svg new file mode 100644 index 0000000..8652d30 --- /dev/null +++ b/apps/builder/public/icons/people-arrows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-carry-box.svg b/apps/builder/public/icons/people-carry-box.svg new file mode 100644 index 0000000..32c597c --- /dev/null +++ b/apps/builder/public/icons/people-carry-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-group.svg b/apps/builder/public/icons/people-group.svg new file mode 100644 index 0000000..46cd6ad --- /dev/null +++ b/apps/builder/public/icons/people-group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-line.svg b/apps/builder/public/icons/people-line.svg new file mode 100644 index 0000000..c66ac78 --- /dev/null +++ b/apps/builder/public/icons/people-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-pulling.svg b/apps/builder/public/icons/people-pulling.svg new file mode 100644 index 0000000..0e21950 --- /dev/null +++ b/apps/builder/public/icons/people-pulling.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-robbery.svg b/apps/builder/public/icons/people-robbery.svg new file mode 100644 index 0000000..b836862 --- /dev/null +++ b/apps/builder/public/icons/people-robbery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/people-roof.svg b/apps/builder/public/icons/people-roof.svg new file mode 100644 index 0000000..36761d4 --- /dev/null +++ b/apps/builder/public/icons/people-roof.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pepper-hot.svg b/apps/builder/public/icons/pepper-hot.svg new file mode 100644 index 0000000..ab32ae4 --- /dev/null +++ b/apps/builder/public/icons/pepper-hot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/percent.svg b/apps/builder/public/icons/percent.svg new file mode 100644 index 0000000..4b1f62d --- /dev/null +++ b/apps/builder/public/icons/percent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-arrow-down-to-line.svg b/apps/builder/public/icons/person-arrow-down-to-line.svg new file mode 100644 index 0000000..4ba77cb --- /dev/null +++ b/apps/builder/public/icons/person-arrow-down-to-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-arrow-up-from-line.svg b/apps/builder/public/icons/person-arrow-up-from-line.svg new file mode 100644 index 0000000..df14d8c --- /dev/null +++ b/apps/builder/public/icons/person-arrow-up-from-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-biking.svg b/apps/builder/public/icons/person-biking.svg new file mode 100644 index 0000000..26a1ecc --- /dev/null +++ b/apps/builder/public/icons/person-biking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-booth.svg b/apps/builder/public/icons/person-booth.svg new file mode 100644 index 0000000..d1e8538 --- /dev/null +++ b/apps/builder/public/icons/person-booth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-breastfeeding.svg b/apps/builder/public/icons/person-breastfeeding.svg new file mode 100644 index 0000000..59d624d --- /dev/null +++ b/apps/builder/public/icons/person-breastfeeding.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-burst.svg b/apps/builder/public/icons/person-burst.svg new file mode 100644 index 0000000..e592b17 --- /dev/null +++ b/apps/builder/public/icons/person-burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-cane.svg b/apps/builder/public/icons/person-cane.svg new file mode 100644 index 0000000..7db8032 --- /dev/null +++ b/apps/builder/public/icons/person-cane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-chalkboard.svg b/apps/builder/public/icons/person-chalkboard.svg new file mode 100644 index 0000000..77532c6 --- /dev/null +++ b/apps/builder/public/icons/person-chalkboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-check.svg b/apps/builder/public/icons/person-circle-check.svg new file mode 100644 index 0000000..998c423 --- /dev/null +++ b/apps/builder/public/icons/person-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-exclamation.svg b/apps/builder/public/icons/person-circle-exclamation.svg new file mode 100644 index 0000000..42c76f5 --- /dev/null +++ b/apps/builder/public/icons/person-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-minus.svg b/apps/builder/public/icons/person-circle-minus.svg new file mode 100644 index 0000000..338a186 --- /dev/null +++ b/apps/builder/public/icons/person-circle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-plus.svg b/apps/builder/public/icons/person-circle-plus.svg new file mode 100644 index 0000000..f1c6eec --- /dev/null +++ b/apps/builder/public/icons/person-circle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-question.svg b/apps/builder/public/icons/person-circle-question.svg new file mode 100644 index 0000000..7f058c1 --- /dev/null +++ b/apps/builder/public/icons/person-circle-question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-circle-xmark.svg b/apps/builder/public/icons/person-circle-xmark.svg new file mode 100644 index 0000000..c58a2a5 --- /dev/null +++ b/apps/builder/public/icons/person-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-digging.svg b/apps/builder/public/icons/person-digging.svg new file mode 100644 index 0000000..4626cf3 --- /dev/null +++ b/apps/builder/public/icons/person-digging.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-dots-from-line.svg b/apps/builder/public/icons/person-dots-from-line.svg new file mode 100644 index 0000000..2f42c82 --- /dev/null +++ b/apps/builder/public/icons/person-dots-from-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-dress-burst.svg b/apps/builder/public/icons/person-dress-burst.svg new file mode 100644 index 0000000..e88d013 --- /dev/null +++ b/apps/builder/public/icons/person-dress-burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-dress.svg b/apps/builder/public/icons/person-dress.svg new file mode 100644 index 0000000..ecccbcf --- /dev/null +++ b/apps/builder/public/icons/person-dress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-drowning.svg b/apps/builder/public/icons/person-drowning.svg new file mode 100644 index 0000000..16a3460 --- /dev/null +++ b/apps/builder/public/icons/person-drowning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-falling-burst.svg b/apps/builder/public/icons/person-falling-burst.svg new file mode 100644 index 0000000..9bac481 --- /dev/null +++ b/apps/builder/public/icons/person-falling-burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-falling.svg b/apps/builder/public/icons/person-falling.svg new file mode 100644 index 0000000..d3a8161 --- /dev/null +++ b/apps/builder/public/icons/person-falling.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-half-dress.svg b/apps/builder/public/icons/person-half-dress.svg new file mode 100644 index 0000000..c58cf09 --- /dev/null +++ b/apps/builder/public/icons/person-half-dress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-harassing.svg b/apps/builder/public/icons/person-harassing.svg new file mode 100644 index 0000000..b35f037 --- /dev/null +++ b/apps/builder/public/icons/person-harassing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-hiking.svg b/apps/builder/public/icons/person-hiking.svg new file mode 100644 index 0000000..d5ccdc0 --- /dev/null +++ b/apps/builder/public/icons/person-hiking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-military-pointing.svg b/apps/builder/public/icons/person-military-pointing.svg new file mode 100644 index 0000000..ecc5dc4 --- /dev/null +++ b/apps/builder/public/icons/person-military-pointing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-military-rifle.svg b/apps/builder/public/icons/person-military-rifle.svg new file mode 100644 index 0000000..414b1fb --- /dev/null +++ b/apps/builder/public/icons/person-military-rifle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-military-to-person.svg b/apps/builder/public/icons/person-military-to-person.svg new file mode 100644 index 0000000..ca48da4 --- /dev/null +++ b/apps/builder/public/icons/person-military-to-person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-praying.svg b/apps/builder/public/icons/person-praying.svg new file mode 100644 index 0000000..4d82d23 --- /dev/null +++ b/apps/builder/public/icons/person-praying.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-pregnant.svg b/apps/builder/public/icons/person-pregnant.svg new file mode 100644 index 0000000..3162584 --- /dev/null +++ b/apps/builder/public/icons/person-pregnant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-rays.svg b/apps/builder/public/icons/person-rays.svg new file mode 100644 index 0000000..2c6edd3 --- /dev/null +++ b/apps/builder/public/icons/person-rays.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-rifle.svg b/apps/builder/public/icons/person-rifle.svg new file mode 100644 index 0000000..ef5081a --- /dev/null +++ b/apps/builder/public/icons/person-rifle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-running.svg b/apps/builder/public/icons/person-running.svg new file mode 100644 index 0000000..a38b5ad --- /dev/null +++ b/apps/builder/public/icons/person-running.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-shelter.svg b/apps/builder/public/icons/person-shelter.svg new file mode 100644 index 0000000..285b3e2 --- /dev/null +++ b/apps/builder/public/icons/person-shelter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-skating.svg b/apps/builder/public/icons/person-skating.svg new file mode 100644 index 0000000..4cf31cc --- /dev/null +++ b/apps/builder/public/icons/person-skating.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-skiing-nordic.svg b/apps/builder/public/icons/person-skiing-nordic.svg new file mode 100644 index 0000000..6a7627e --- /dev/null +++ b/apps/builder/public/icons/person-skiing-nordic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-skiing.svg b/apps/builder/public/icons/person-skiing.svg new file mode 100644 index 0000000..c4f6074 --- /dev/null +++ b/apps/builder/public/icons/person-skiing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-snowboarding.svg b/apps/builder/public/icons/person-snowboarding.svg new file mode 100644 index 0000000..15dd685 --- /dev/null +++ b/apps/builder/public/icons/person-snowboarding.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-swimming.svg b/apps/builder/public/icons/person-swimming.svg new file mode 100644 index 0000000..7814ea3 --- /dev/null +++ b/apps/builder/public/icons/person-swimming.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-through-window.svg b/apps/builder/public/icons/person-through-window.svg new file mode 100644 index 0000000..191bc4a --- /dev/null +++ b/apps/builder/public/icons/person-through-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking-arrow-loop-left.svg b/apps/builder/public/icons/person-walking-arrow-loop-left.svg new file mode 100644 index 0000000..a9fb873 --- /dev/null +++ b/apps/builder/public/icons/person-walking-arrow-loop-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking-arrow-right.svg b/apps/builder/public/icons/person-walking-arrow-right.svg new file mode 100644 index 0000000..873aafd --- /dev/null +++ b/apps/builder/public/icons/person-walking-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking-dashed-line-arrow-right.svg b/apps/builder/public/icons/person-walking-dashed-line-arrow-right.svg new file mode 100644 index 0000000..77f60c7 --- /dev/null +++ b/apps/builder/public/icons/person-walking-dashed-line-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking-luggage.svg b/apps/builder/public/icons/person-walking-luggage.svg new file mode 100644 index 0000000..e1392ba --- /dev/null +++ b/apps/builder/public/icons/person-walking-luggage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking-with-cane.svg b/apps/builder/public/icons/person-walking-with-cane.svg new file mode 100644 index 0000000..1181270 --- /dev/null +++ b/apps/builder/public/icons/person-walking-with-cane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person-walking.svg b/apps/builder/public/icons/person-walking.svg new file mode 100644 index 0000000..9acfa77 --- /dev/null +++ b/apps/builder/public/icons/person-walking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/person.svg b/apps/builder/public/icons/person.svg new file mode 100644 index 0000000..5510938 --- /dev/null +++ b/apps/builder/public/icons/person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/peseta-sign.svg b/apps/builder/public/icons/peseta-sign.svg new file mode 100644 index 0000000..3c76cbd --- /dev/null +++ b/apps/builder/public/icons/peseta-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/peso-sign.svg b/apps/builder/public/icons/peso-sign.svg new file mode 100644 index 0000000..109524a --- /dev/null +++ b/apps/builder/public/icons/peso-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/phone-flip.svg b/apps/builder/public/icons/phone-flip.svg new file mode 100644 index 0000000..11074c5 --- /dev/null +++ b/apps/builder/public/icons/phone-flip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/phone-slash.svg b/apps/builder/public/icons/phone-slash.svg new file mode 100644 index 0000000..80ef8c3 --- /dev/null +++ b/apps/builder/public/icons/phone-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/phone-volume.svg b/apps/builder/public/icons/phone-volume.svg new file mode 100644 index 0000000..ddde847 --- /dev/null +++ b/apps/builder/public/icons/phone-volume.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/phone.svg b/apps/builder/public/icons/phone.svg new file mode 100644 index 0000000..0586ac3 --- /dev/null +++ b/apps/builder/public/icons/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/photo-film.svg b/apps/builder/public/icons/photo-film.svg new file mode 100644 index 0000000..1199cdd --- /dev/null +++ b/apps/builder/public/icons/photo-film.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/piggy-bank.svg b/apps/builder/public/icons/piggy-bank.svg new file mode 100644 index 0000000..b35109f --- /dev/null +++ b/apps/builder/public/icons/piggy-bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pills.svg b/apps/builder/public/icons/pills.svg new file mode 100644 index 0000000..87f402c --- /dev/null +++ b/apps/builder/public/icons/pills.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pizza-slice.svg b/apps/builder/public/icons/pizza-slice.svg new file mode 100644 index 0000000..fa9f397 --- /dev/null +++ b/apps/builder/public/icons/pizza-slice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/place-of-worship.svg b/apps/builder/public/icons/place-of-worship.svg new file mode 100644 index 0000000..90376cf --- /dev/null +++ b/apps/builder/public/icons/place-of-worship.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-arrival.svg b/apps/builder/public/icons/plane-arrival.svg new file mode 100644 index 0000000..65fade9 --- /dev/null +++ b/apps/builder/public/icons/plane-arrival.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-circle-check.svg b/apps/builder/public/icons/plane-circle-check.svg new file mode 100644 index 0000000..8551b0a --- /dev/null +++ b/apps/builder/public/icons/plane-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-circle-exclamation.svg b/apps/builder/public/icons/plane-circle-exclamation.svg new file mode 100644 index 0000000..35f56ff --- /dev/null +++ b/apps/builder/public/icons/plane-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-circle-xmark.svg b/apps/builder/public/icons/plane-circle-xmark.svg new file mode 100644 index 0000000..90f341b --- /dev/null +++ b/apps/builder/public/icons/plane-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-departure.svg b/apps/builder/public/icons/plane-departure.svg new file mode 100644 index 0000000..050dcdd --- /dev/null +++ b/apps/builder/public/icons/plane-departure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-lock.svg b/apps/builder/public/icons/plane-lock.svg new file mode 100644 index 0000000..d0f5a53 --- /dev/null +++ b/apps/builder/public/icons/plane-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-slash.svg b/apps/builder/public/icons/plane-slash.svg new file mode 100644 index 0000000..d1eb1dc --- /dev/null +++ b/apps/builder/public/icons/plane-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane-up.svg b/apps/builder/public/icons/plane-up.svg new file mode 100644 index 0000000..7317d8c --- /dev/null +++ b/apps/builder/public/icons/plane-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plane.svg b/apps/builder/public/icons/plane.svg new file mode 100644 index 0000000..ff9702c --- /dev/null +++ b/apps/builder/public/icons/plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plant-wilt.svg b/apps/builder/public/icons/plant-wilt.svg new file mode 100644 index 0000000..f0c77e2 --- /dev/null +++ b/apps/builder/public/icons/plant-wilt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plate-wheat.svg b/apps/builder/public/icons/plate-wheat.svg new file mode 100644 index 0000000..e8aa4d1 --- /dev/null +++ b/apps/builder/public/icons/plate-wheat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/play.svg b/apps/builder/public/icons/play.svg new file mode 100644 index 0000000..0c17afa --- /dev/null +++ b/apps/builder/public/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-bolt.svg b/apps/builder/public/icons/plug-circle-bolt.svg new file mode 100644 index 0000000..921983d --- /dev/null +++ b/apps/builder/public/icons/plug-circle-bolt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-check.svg b/apps/builder/public/icons/plug-circle-check.svg new file mode 100644 index 0000000..46d07fb --- /dev/null +++ b/apps/builder/public/icons/plug-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-exclamation.svg b/apps/builder/public/icons/plug-circle-exclamation.svg new file mode 100644 index 0000000..ff23514 --- /dev/null +++ b/apps/builder/public/icons/plug-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-minus.svg b/apps/builder/public/icons/plug-circle-minus.svg new file mode 100644 index 0000000..8a9c76a --- /dev/null +++ b/apps/builder/public/icons/plug-circle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-plus.svg b/apps/builder/public/icons/plug-circle-plus.svg new file mode 100644 index 0000000..d354bad --- /dev/null +++ b/apps/builder/public/icons/plug-circle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug-circle-xmark.svg b/apps/builder/public/icons/plug-circle-xmark.svg new file mode 100644 index 0000000..a04773c --- /dev/null +++ b/apps/builder/public/icons/plug-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plug.svg b/apps/builder/public/icons/plug.svg new file mode 100644 index 0000000..7c9a801 --- /dev/null +++ b/apps/builder/public/icons/plug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plus-minus.svg b/apps/builder/public/icons/plus-minus.svg new file mode 100644 index 0000000..ec35633 --- /dev/null +++ b/apps/builder/public/icons/plus-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/plus.svg b/apps/builder/public/icons/plus.svg new file mode 100644 index 0000000..8598dad --- /dev/null +++ b/apps/builder/public/icons/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/podcast.svg b/apps/builder/public/icons/podcast.svg new file mode 100644 index 0000000..f47dcfc --- /dev/null +++ b/apps/builder/public/icons/podcast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/poo-storm.svg b/apps/builder/public/icons/poo-storm.svg new file mode 100644 index 0000000..792809c --- /dev/null +++ b/apps/builder/public/icons/poo-storm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/poo.svg b/apps/builder/public/icons/poo.svg new file mode 100644 index 0000000..2548424 --- /dev/null +++ b/apps/builder/public/icons/poo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/poop.svg b/apps/builder/public/icons/poop.svg new file mode 100644 index 0000000..b375512 --- /dev/null +++ b/apps/builder/public/icons/poop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/power-off.svg b/apps/builder/public/icons/power-off.svg new file mode 100644 index 0000000..676efb8 --- /dev/null +++ b/apps/builder/public/icons/power-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/prescription-bottle-medical.svg b/apps/builder/public/icons/prescription-bottle-medical.svg new file mode 100644 index 0000000..47f9f34 --- /dev/null +++ b/apps/builder/public/icons/prescription-bottle-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/prescription-bottle.svg b/apps/builder/public/icons/prescription-bottle.svg new file mode 100644 index 0000000..86925e9 --- /dev/null +++ b/apps/builder/public/icons/prescription-bottle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/prescription.svg b/apps/builder/public/icons/prescription.svg new file mode 100644 index 0000000..fe9be3a --- /dev/null +++ b/apps/builder/public/icons/prescription.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/print.svg b/apps/builder/public/icons/print.svg new file mode 100644 index 0000000..3e5b309 --- /dev/null +++ b/apps/builder/public/icons/print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pump-medical.svg b/apps/builder/public/icons/pump-medical.svg new file mode 100644 index 0000000..7429472 --- /dev/null +++ b/apps/builder/public/icons/pump-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/pump-soap.svg b/apps/builder/public/icons/pump-soap.svg new file mode 100644 index 0000000..ad2db3c --- /dev/null +++ b/apps/builder/public/icons/pump-soap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/puzzle-piece.svg b/apps/builder/public/icons/puzzle-piece.svg new file mode 100644 index 0000000..c92a9d5 --- /dev/null +++ b/apps/builder/public/icons/puzzle-piece.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/q.svg b/apps/builder/public/icons/q.svg new file mode 100644 index 0000000..10cdfbd --- /dev/null +++ b/apps/builder/public/icons/q.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/qrcode.svg b/apps/builder/public/icons/qrcode.svg new file mode 100644 index 0000000..3b20133 --- /dev/null +++ b/apps/builder/public/icons/qrcode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/question.svg b/apps/builder/public/icons/question.svg new file mode 100644 index 0000000..47d1752 --- /dev/null +++ b/apps/builder/public/icons/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/quote-left.svg b/apps/builder/public/icons/quote-left.svg new file mode 100644 index 0000000..eb1adfe --- /dev/null +++ b/apps/builder/public/icons/quote-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/quote-right.svg b/apps/builder/public/icons/quote-right.svg new file mode 100644 index 0000000..75e111d --- /dev/null +++ b/apps/builder/public/icons/quote-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/r.svg b/apps/builder/public/icons/r.svg new file mode 100644 index 0000000..8abf6a0 --- /dev/null +++ b/apps/builder/public/icons/r.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/radiation.svg b/apps/builder/public/icons/radiation.svg new file mode 100644 index 0000000..9bb2d19 --- /dev/null +++ b/apps/builder/public/icons/radiation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/radio.svg b/apps/builder/public/icons/radio.svg new file mode 100644 index 0000000..b093fcf --- /dev/null +++ b/apps/builder/public/icons/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rainbow.svg b/apps/builder/public/icons/rainbow.svg new file mode 100644 index 0000000..12d13d0 --- /dev/null +++ b/apps/builder/public/icons/rainbow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ranking-star.svg b/apps/builder/public/icons/ranking-star.svg new file mode 100644 index 0000000..aa113c5 --- /dev/null +++ b/apps/builder/public/icons/ranking-star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/receipt.svg b/apps/builder/public/icons/receipt.svg new file mode 100644 index 0000000..de0b6cf --- /dev/null +++ b/apps/builder/public/icons/receipt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/record-vinyl.svg b/apps/builder/public/icons/record-vinyl.svg new file mode 100644 index 0000000..6ce7ea2 --- /dev/null +++ b/apps/builder/public/icons/record-vinyl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rectangle-ad.svg b/apps/builder/public/icons/rectangle-ad.svg new file mode 100644 index 0000000..e2bc032 --- /dev/null +++ b/apps/builder/public/icons/rectangle-ad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rectangle-list.svg b/apps/builder/public/icons/rectangle-list.svg new file mode 100644 index 0000000..71d9cf3 --- /dev/null +++ b/apps/builder/public/icons/rectangle-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rectangle-xmark.svg b/apps/builder/public/icons/rectangle-xmark.svg new file mode 100644 index 0000000..5138250 --- /dev/null +++ b/apps/builder/public/icons/rectangle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/recycle.svg b/apps/builder/public/icons/recycle.svg new file mode 100644 index 0000000..0035c8c --- /dev/null +++ b/apps/builder/public/icons/recycle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/registered.svg b/apps/builder/public/icons/registered.svg new file mode 100644 index 0000000..a2b6d28 --- /dev/null +++ b/apps/builder/public/icons/registered.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/repeat.svg b/apps/builder/public/icons/repeat.svg new file mode 100644 index 0000000..1115500 --- /dev/null +++ b/apps/builder/public/icons/repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/reply-all.svg b/apps/builder/public/icons/reply-all.svg new file mode 100644 index 0000000..abf4112 --- /dev/null +++ b/apps/builder/public/icons/reply-all.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/reply.svg b/apps/builder/public/icons/reply.svg new file mode 100644 index 0000000..62abddf --- /dev/null +++ b/apps/builder/public/icons/reply.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/republican.svg b/apps/builder/public/icons/republican.svg new file mode 100644 index 0000000..3f5e72c --- /dev/null +++ b/apps/builder/public/icons/republican.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/restroom.svg b/apps/builder/public/icons/restroom.svg new file mode 100644 index 0000000..6a4676b --- /dev/null +++ b/apps/builder/public/icons/restroom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/retweet.svg b/apps/builder/public/icons/retweet.svg new file mode 100644 index 0000000..96205e6 --- /dev/null +++ b/apps/builder/public/icons/retweet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ribbon.svg b/apps/builder/public/icons/ribbon.svg new file mode 100644 index 0000000..574c7ff --- /dev/null +++ b/apps/builder/public/icons/ribbon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/right-from-bracket.svg b/apps/builder/public/icons/right-from-bracket.svg new file mode 100644 index 0000000..7d07202 --- /dev/null +++ b/apps/builder/public/icons/right-from-bracket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/right-left.svg b/apps/builder/public/icons/right-left.svg new file mode 100644 index 0000000..1798dd8 --- /dev/null +++ b/apps/builder/public/icons/right-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/right-long.svg b/apps/builder/public/icons/right-long.svg new file mode 100644 index 0000000..2845757 --- /dev/null +++ b/apps/builder/public/icons/right-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/right-to-bracket.svg b/apps/builder/public/icons/right-to-bracket.svg new file mode 100644 index 0000000..9bf1af3 --- /dev/null +++ b/apps/builder/public/icons/right-to-bracket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ring.svg b/apps/builder/public/icons/ring.svg new file mode 100644 index 0000000..2d83745 --- /dev/null +++ b/apps/builder/public/icons/ring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-barrier.svg b/apps/builder/public/icons/road-barrier.svg new file mode 100644 index 0000000..b7c0d3c --- /dev/null +++ b/apps/builder/public/icons/road-barrier.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-bridge.svg b/apps/builder/public/icons/road-bridge.svg new file mode 100644 index 0000000..70eb241 --- /dev/null +++ b/apps/builder/public/icons/road-bridge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-circle-check.svg b/apps/builder/public/icons/road-circle-check.svg new file mode 100644 index 0000000..003fe78 --- /dev/null +++ b/apps/builder/public/icons/road-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-circle-exclamation.svg b/apps/builder/public/icons/road-circle-exclamation.svg new file mode 100644 index 0000000..1bfb0fe --- /dev/null +++ b/apps/builder/public/icons/road-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-circle-xmark.svg b/apps/builder/public/icons/road-circle-xmark.svg new file mode 100644 index 0000000..b94b229 --- /dev/null +++ b/apps/builder/public/icons/road-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-lock.svg b/apps/builder/public/icons/road-lock.svg new file mode 100644 index 0000000..538a0c5 --- /dev/null +++ b/apps/builder/public/icons/road-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road-spikes.svg b/apps/builder/public/icons/road-spikes.svg new file mode 100644 index 0000000..ed2bc17 --- /dev/null +++ b/apps/builder/public/icons/road-spikes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/road.svg b/apps/builder/public/icons/road.svg new file mode 100644 index 0000000..64a25fb --- /dev/null +++ b/apps/builder/public/icons/road.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/robot.svg b/apps/builder/public/icons/robot.svg new file mode 100644 index 0000000..0b14ad8 --- /dev/null +++ b/apps/builder/public/icons/robot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rocket.svg b/apps/builder/public/icons/rocket.svg new file mode 100644 index 0000000..978860c --- /dev/null +++ b/apps/builder/public/icons/rocket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rotate-left.svg b/apps/builder/public/icons/rotate-left.svg new file mode 100644 index 0000000..4e8316a --- /dev/null +++ b/apps/builder/public/icons/rotate-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rotate-right.svg b/apps/builder/public/icons/rotate-right.svg new file mode 100644 index 0000000..4d2a730 --- /dev/null +++ b/apps/builder/public/icons/rotate-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rotate.svg b/apps/builder/public/icons/rotate.svg new file mode 100644 index 0000000..7590402 --- /dev/null +++ b/apps/builder/public/icons/rotate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/route.svg b/apps/builder/public/icons/route.svg new file mode 100644 index 0000000..9f7bf12 --- /dev/null +++ b/apps/builder/public/icons/route.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rss.svg b/apps/builder/public/icons/rss.svg new file mode 100644 index 0000000..566ab69 --- /dev/null +++ b/apps/builder/public/icons/rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ruble-sign.svg b/apps/builder/public/icons/ruble-sign.svg new file mode 100644 index 0000000..eb0fe3c --- /dev/null +++ b/apps/builder/public/icons/ruble-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rug.svg b/apps/builder/public/icons/rug.svg new file mode 100644 index 0000000..9bce75f --- /dev/null +++ b/apps/builder/public/icons/rug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ruler-combined.svg b/apps/builder/public/icons/ruler-combined.svg new file mode 100644 index 0000000..05585f0 --- /dev/null +++ b/apps/builder/public/icons/ruler-combined.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ruler-horizontal.svg b/apps/builder/public/icons/ruler-horizontal.svg new file mode 100644 index 0000000..97cad04 --- /dev/null +++ b/apps/builder/public/icons/ruler-horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ruler-vertical.svg b/apps/builder/public/icons/ruler-vertical.svg new file mode 100644 index 0000000..e683a10 --- /dev/null +++ b/apps/builder/public/icons/ruler-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ruler.svg b/apps/builder/public/icons/ruler.svg new file mode 100644 index 0000000..cd602ae --- /dev/null +++ b/apps/builder/public/icons/ruler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rupee-sign.svg b/apps/builder/public/icons/rupee-sign.svg new file mode 100644 index 0000000..28ec744 --- /dev/null +++ b/apps/builder/public/icons/rupee-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/rupiah-sign.svg b/apps/builder/public/icons/rupiah-sign.svg new file mode 100644 index 0000000..908f81f --- /dev/null +++ b/apps/builder/public/icons/rupiah-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/s.svg b/apps/builder/public/icons/s.svg new file mode 100644 index 0000000..5d32e5e --- /dev/null +++ b/apps/builder/public/icons/s.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sack-dollar.svg b/apps/builder/public/icons/sack-dollar.svg new file mode 100644 index 0000000..eb19b4d --- /dev/null +++ b/apps/builder/public/icons/sack-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sack-xmark.svg b/apps/builder/public/icons/sack-xmark.svg new file mode 100644 index 0000000..d3a0ab9 --- /dev/null +++ b/apps/builder/public/icons/sack-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sailboat.svg b/apps/builder/public/icons/sailboat.svg new file mode 100644 index 0000000..500d518 --- /dev/null +++ b/apps/builder/public/icons/sailboat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/satellite-dish.svg b/apps/builder/public/icons/satellite-dish.svg new file mode 100644 index 0000000..d0e4de0 --- /dev/null +++ b/apps/builder/public/icons/satellite-dish.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/satellite.svg b/apps/builder/public/icons/satellite.svg new file mode 100644 index 0000000..88d2c7d --- /dev/null +++ b/apps/builder/public/icons/satellite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scale-balanced.svg b/apps/builder/public/icons/scale-balanced.svg new file mode 100644 index 0000000..88751f8 --- /dev/null +++ b/apps/builder/public/icons/scale-balanced.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scale-unbalanced-flip.svg b/apps/builder/public/icons/scale-unbalanced-flip.svg new file mode 100644 index 0000000..f4b4629 --- /dev/null +++ b/apps/builder/public/icons/scale-unbalanced-flip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scale-unbalanced.svg b/apps/builder/public/icons/scale-unbalanced.svg new file mode 100644 index 0000000..daab19d --- /dev/null +++ b/apps/builder/public/icons/scale-unbalanced.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school-circle-check.svg b/apps/builder/public/icons/school-circle-check.svg new file mode 100644 index 0000000..d94837b --- /dev/null +++ b/apps/builder/public/icons/school-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school-circle-exclamation.svg b/apps/builder/public/icons/school-circle-exclamation.svg new file mode 100644 index 0000000..e223a81 --- /dev/null +++ b/apps/builder/public/icons/school-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school-circle-xmark.svg b/apps/builder/public/icons/school-circle-xmark.svg new file mode 100644 index 0000000..57d8929 --- /dev/null +++ b/apps/builder/public/icons/school-circle-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school-flag.svg b/apps/builder/public/icons/school-flag.svg new file mode 100644 index 0000000..e480e81 --- /dev/null +++ b/apps/builder/public/icons/school-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school-lock.svg b/apps/builder/public/icons/school-lock.svg new file mode 100644 index 0000000..555fe18 --- /dev/null +++ b/apps/builder/public/icons/school-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/school.svg b/apps/builder/public/icons/school.svg new file mode 100644 index 0000000..921329c --- /dev/null +++ b/apps/builder/public/icons/school.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scissors.svg b/apps/builder/public/icons/scissors.svg new file mode 100644 index 0000000..2d32e21 --- /dev/null +++ b/apps/builder/public/icons/scissors.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/screwdriver-wrench.svg b/apps/builder/public/icons/screwdriver-wrench.svg new file mode 100644 index 0000000..25bdc28 --- /dev/null +++ b/apps/builder/public/icons/screwdriver-wrench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/screwdriver.svg b/apps/builder/public/icons/screwdriver.svg new file mode 100644 index 0000000..55661f4 --- /dev/null +++ b/apps/builder/public/icons/screwdriver.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scroll-torah.svg b/apps/builder/public/icons/scroll-torah.svg new file mode 100644 index 0000000..56bf5db --- /dev/null +++ b/apps/builder/public/icons/scroll-torah.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/scroll.svg b/apps/builder/public/icons/scroll.svg new file mode 100644 index 0000000..ef37904 --- /dev/null +++ b/apps/builder/public/icons/scroll.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sd-card.svg b/apps/builder/public/icons/sd-card.svg new file mode 100644 index 0000000..24580b6 --- /dev/null +++ b/apps/builder/public/icons/sd-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/section.svg b/apps/builder/public/icons/section.svg new file mode 100644 index 0000000..adbc85f --- /dev/null +++ b/apps/builder/public/icons/section.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/seedling.svg b/apps/builder/public/icons/seedling.svg new file mode 100644 index 0000000..2ad1d8b --- /dev/null +++ b/apps/builder/public/icons/seedling.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/server.svg b/apps/builder/public/icons/server.svg new file mode 100644 index 0000000..aee1ada --- /dev/null +++ b/apps/builder/public/icons/server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shapes.svg b/apps/builder/public/icons/shapes.svg new file mode 100644 index 0000000..c46b1c2 --- /dev/null +++ b/apps/builder/public/icons/shapes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/share-from-square.svg b/apps/builder/public/icons/share-from-square.svg new file mode 100644 index 0000000..3c82d61 --- /dev/null +++ b/apps/builder/public/icons/share-from-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/share-nodes.svg b/apps/builder/public/icons/share-nodes.svg new file mode 100644 index 0000000..486a505 --- /dev/null +++ b/apps/builder/public/icons/share-nodes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/share.svg b/apps/builder/public/icons/share.svg new file mode 100644 index 0000000..2f1e562 --- /dev/null +++ b/apps/builder/public/icons/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sheet-plastic.svg b/apps/builder/public/icons/sheet-plastic.svg new file mode 100644 index 0000000..1c33329 --- /dev/null +++ b/apps/builder/public/icons/sheet-plastic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shekel-sign.svg b/apps/builder/public/icons/shekel-sign.svg new file mode 100644 index 0000000..c535930 --- /dev/null +++ b/apps/builder/public/icons/shekel-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield-cat.svg b/apps/builder/public/icons/shield-cat.svg new file mode 100644 index 0000000..b5436c5 --- /dev/null +++ b/apps/builder/public/icons/shield-cat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield-dog.svg b/apps/builder/public/icons/shield-dog.svg new file mode 100644 index 0000000..8579c32 --- /dev/null +++ b/apps/builder/public/icons/shield-dog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield-halved.svg b/apps/builder/public/icons/shield-halved.svg new file mode 100644 index 0000000..ae1a9a7 --- /dev/null +++ b/apps/builder/public/icons/shield-halved.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield-heart.svg b/apps/builder/public/icons/shield-heart.svg new file mode 100644 index 0000000..604bd25 --- /dev/null +++ b/apps/builder/public/icons/shield-heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield-virus.svg b/apps/builder/public/icons/shield-virus.svg new file mode 100644 index 0000000..13b7320 --- /dev/null +++ b/apps/builder/public/icons/shield-virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shield.svg b/apps/builder/public/icons/shield.svg new file mode 100644 index 0000000..f570e64 --- /dev/null +++ b/apps/builder/public/icons/shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ship.svg b/apps/builder/public/icons/ship.svg new file mode 100644 index 0000000..0834143 --- /dev/null +++ b/apps/builder/public/icons/ship.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shirt.svg b/apps/builder/public/icons/shirt.svg new file mode 100644 index 0000000..481fd8b --- /dev/null +++ b/apps/builder/public/icons/shirt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shoe-prints.svg b/apps/builder/public/icons/shoe-prints.svg new file mode 100644 index 0000000..ea877a5 --- /dev/null +++ b/apps/builder/public/icons/shoe-prints.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shop-lock.svg b/apps/builder/public/icons/shop-lock.svg new file mode 100644 index 0000000..9496996 --- /dev/null +++ b/apps/builder/public/icons/shop-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shop-slash.svg b/apps/builder/public/icons/shop-slash.svg new file mode 100644 index 0000000..1e3e975 --- /dev/null +++ b/apps/builder/public/icons/shop-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shop.svg b/apps/builder/public/icons/shop.svg new file mode 100644 index 0000000..6d499fa --- /dev/null +++ b/apps/builder/public/icons/shop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shower.svg b/apps/builder/public/icons/shower.svg new file mode 100644 index 0000000..99930e1 --- /dev/null +++ b/apps/builder/public/icons/shower.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shrimp.svg b/apps/builder/public/icons/shrimp.svg new file mode 100644 index 0000000..8651017 --- /dev/null +++ b/apps/builder/public/icons/shrimp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shuffle.svg b/apps/builder/public/icons/shuffle.svg new file mode 100644 index 0000000..e135655 --- /dev/null +++ b/apps/builder/public/icons/shuffle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/shuttle-space.svg b/apps/builder/public/icons/shuttle-space.svg new file mode 100644 index 0000000..4dd4831 --- /dev/null +++ b/apps/builder/public/icons/shuttle-space.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sign-hanging.svg b/apps/builder/public/icons/sign-hanging.svg new file mode 100644 index 0000000..993cf1d --- /dev/null +++ b/apps/builder/public/icons/sign-hanging.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/signal.svg b/apps/builder/public/icons/signal.svg new file mode 100644 index 0000000..b8fc2a7 --- /dev/null +++ b/apps/builder/public/icons/signal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/signature.svg b/apps/builder/public/icons/signature.svg new file mode 100644 index 0000000..ad612df --- /dev/null +++ b/apps/builder/public/icons/signature.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/signs-post.svg b/apps/builder/public/icons/signs-post.svg new file mode 100644 index 0000000..99ba19d --- /dev/null +++ b/apps/builder/public/icons/signs-post.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sim-card.svg b/apps/builder/public/icons/sim-card.svg new file mode 100644 index 0000000..3e9e9c7 --- /dev/null +++ b/apps/builder/public/icons/sim-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sink.svg b/apps/builder/public/icons/sink.svg new file mode 100644 index 0000000..d4854c6 --- /dev/null +++ b/apps/builder/public/icons/sink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sitemap.svg b/apps/builder/public/icons/sitemap.svg new file mode 100644 index 0000000..3c17bb3 --- /dev/null +++ b/apps/builder/public/icons/sitemap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/skull-crossbones.svg b/apps/builder/public/icons/skull-crossbones.svg new file mode 100644 index 0000000..044b042 --- /dev/null +++ b/apps/builder/public/icons/skull-crossbones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/skull.svg b/apps/builder/public/icons/skull.svg new file mode 100644 index 0000000..a42502b --- /dev/null +++ b/apps/builder/public/icons/skull.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/slash.svg b/apps/builder/public/icons/slash.svg new file mode 100644 index 0000000..798fd31 --- /dev/null +++ b/apps/builder/public/icons/slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sleigh.svg b/apps/builder/public/icons/sleigh.svg new file mode 100644 index 0000000..1f32147 --- /dev/null +++ b/apps/builder/public/icons/sleigh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sliders.svg b/apps/builder/public/icons/sliders.svg new file mode 100644 index 0000000..ff0251c --- /dev/null +++ b/apps/builder/public/icons/sliders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/smog.svg b/apps/builder/public/icons/smog.svg new file mode 100644 index 0000000..d4ffe57 --- /dev/null +++ b/apps/builder/public/icons/smog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/smoking.svg b/apps/builder/public/icons/smoking.svg new file mode 100644 index 0000000..26f86dc --- /dev/null +++ b/apps/builder/public/icons/smoking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/snowflake.svg b/apps/builder/public/icons/snowflake.svg new file mode 100644 index 0000000..9a19640 --- /dev/null +++ b/apps/builder/public/icons/snowflake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/snowman.svg b/apps/builder/public/icons/snowman.svg new file mode 100644 index 0000000..ec2aab3 --- /dev/null +++ b/apps/builder/public/icons/snowman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/snowplow.svg b/apps/builder/public/icons/snowplow.svg new file mode 100644 index 0000000..b35316c --- /dev/null +++ b/apps/builder/public/icons/snowplow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/soap.svg b/apps/builder/public/icons/soap.svg new file mode 100644 index 0000000..ed1cde1 --- /dev/null +++ b/apps/builder/public/icons/soap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/socks.svg b/apps/builder/public/icons/socks.svg new file mode 100644 index 0000000..2a4bd08 --- /dev/null +++ b/apps/builder/public/icons/socks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/solar-panel.svg b/apps/builder/public/icons/solar-panel.svg new file mode 100644 index 0000000..2c2c71b --- /dev/null +++ b/apps/builder/public/icons/solar-panel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sort-down.svg b/apps/builder/public/icons/sort-down.svg new file mode 100644 index 0000000..6456958 --- /dev/null +++ b/apps/builder/public/icons/sort-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sort-up.svg b/apps/builder/public/icons/sort-up.svg new file mode 100644 index 0000000..03bd3ac --- /dev/null +++ b/apps/builder/public/icons/sort-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sort.svg b/apps/builder/public/icons/sort.svg new file mode 100644 index 0000000..825ec98 --- /dev/null +++ b/apps/builder/public/icons/sort.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spa.svg b/apps/builder/public/icons/spa.svg new file mode 100644 index 0000000..bb5bebe --- /dev/null +++ b/apps/builder/public/icons/spa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spaghetti-monster-flying.svg b/apps/builder/public/icons/spaghetti-monster-flying.svg new file mode 100644 index 0000000..f8e5431 --- /dev/null +++ b/apps/builder/public/icons/spaghetti-monster-flying.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spell-check.svg b/apps/builder/public/icons/spell-check.svg new file mode 100644 index 0000000..f89b831 --- /dev/null +++ b/apps/builder/public/icons/spell-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spider.svg b/apps/builder/public/icons/spider.svg new file mode 100644 index 0000000..329bb50 --- /dev/null +++ b/apps/builder/public/icons/spider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spinner.svg b/apps/builder/public/icons/spinner.svg new file mode 100644 index 0000000..da959de --- /dev/null +++ b/apps/builder/public/icons/spinner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/splotch.svg b/apps/builder/public/icons/splotch.svg new file mode 100644 index 0000000..a07e172 --- /dev/null +++ b/apps/builder/public/icons/splotch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spoon.svg b/apps/builder/public/icons/spoon.svg new file mode 100644 index 0000000..e8d4bde --- /dev/null +++ b/apps/builder/public/icons/spoon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spray-can-sparkles.svg b/apps/builder/public/icons/spray-can-sparkles.svg new file mode 100644 index 0000000..18bd3d9 --- /dev/null +++ b/apps/builder/public/icons/spray-can-sparkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/spray-can.svg b/apps/builder/public/icons/spray-can.svg new file mode 100644 index 0000000..8732b7d --- /dev/null +++ b/apps/builder/public/icons/spray-can.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-arrow-up-right.svg b/apps/builder/public/icons/square-arrow-up-right.svg new file mode 100644 index 0000000..283ad67 --- /dev/null +++ b/apps/builder/public/icons/square-arrow-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-caret-down.svg b/apps/builder/public/icons/square-caret-down.svg new file mode 100644 index 0000000..0631218 --- /dev/null +++ b/apps/builder/public/icons/square-caret-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-caret-left.svg b/apps/builder/public/icons/square-caret-left.svg new file mode 100644 index 0000000..1d5c249 --- /dev/null +++ b/apps/builder/public/icons/square-caret-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-caret-right.svg b/apps/builder/public/icons/square-caret-right.svg new file mode 100644 index 0000000..8b0c834 --- /dev/null +++ b/apps/builder/public/icons/square-caret-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-caret-up.svg b/apps/builder/public/icons/square-caret-up.svg new file mode 100644 index 0000000..85b46c8 --- /dev/null +++ b/apps/builder/public/icons/square-caret-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-check.svg b/apps/builder/public/icons/square-check.svg new file mode 100644 index 0000000..f0222ff --- /dev/null +++ b/apps/builder/public/icons/square-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-envelope.svg b/apps/builder/public/icons/square-envelope.svg new file mode 100644 index 0000000..eb0cd73 --- /dev/null +++ b/apps/builder/public/icons/square-envelope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-full.svg b/apps/builder/public/icons/square-full.svg new file mode 100644 index 0000000..1658886 --- /dev/null +++ b/apps/builder/public/icons/square-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-h.svg b/apps/builder/public/icons/square-h.svg new file mode 100644 index 0000000..4361f0b --- /dev/null +++ b/apps/builder/public/icons/square-h.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-minus.svg b/apps/builder/public/icons/square-minus.svg new file mode 100644 index 0000000..5a90e5e --- /dev/null +++ b/apps/builder/public/icons/square-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-nfi.svg b/apps/builder/public/icons/square-nfi.svg new file mode 100644 index 0000000..c60570b --- /dev/null +++ b/apps/builder/public/icons/square-nfi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-parking.svg b/apps/builder/public/icons/square-parking.svg new file mode 100644 index 0000000..88c925d --- /dev/null +++ b/apps/builder/public/icons/square-parking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-pen.svg b/apps/builder/public/icons/square-pen.svg new file mode 100644 index 0000000..b02ace1 --- /dev/null +++ b/apps/builder/public/icons/square-pen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-person-confined.svg b/apps/builder/public/icons/square-person-confined.svg new file mode 100644 index 0000000..52d9b25 --- /dev/null +++ b/apps/builder/public/icons/square-person-confined.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-phone-flip.svg b/apps/builder/public/icons/square-phone-flip.svg new file mode 100644 index 0000000..61b944a --- /dev/null +++ b/apps/builder/public/icons/square-phone-flip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-phone.svg b/apps/builder/public/icons/square-phone.svg new file mode 100644 index 0000000..c3bcfaa --- /dev/null +++ b/apps/builder/public/icons/square-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-plus.svg b/apps/builder/public/icons/square-plus.svg new file mode 100644 index 0000000..ccc6918 --- /dev/null +++ b/apps/builder/public/icons/square-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-poll-horizontal.svg b/apps/builder/public/icons/square-poll-horizontal.svg new file mode 100644 index 0000000..207b3f4 --- /dev/null +++ b/apps/builder/public/icons/square-poll-horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-poll-vertical.svg b/apps/builder/public/icons/square-poll-vertical.svg new file mode 100644 index 0000000..1b64e94 --- /dev/null +++ b/apps/builder/public/icons/square-poll-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-root-variable.svg b/apps/builder/public/icons/square-root-variable.svg new file mode 100644 index 0000000..4dae41f --- /dev/null +++ b/apps/builder/public/icons/square-root-variable.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-rss.svg b/apps/builder/public/icons/square-rss.svg new file mode 100644 index 0000000..a87f88d --- /dev/null +++ b/apps/builder/public/icons/square-rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-share-nodes.svg b/apps/builder/public/icons/square-share-nodes.svg new file mode 100644 index 0000000..2ee2438 --- /dev/null +++ b/apps/builder/public/icons/square-share-nodes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-up-right.svg b/apps/builder/public/icons/square-up-right.svg new file mode 100644 index 0000000..22febd8 --- /dev/null +++ b/apps/builder/public/icons/square-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-virus.svg b/apps/builder/public/icons/square-virus.svg new file mode 100644 index 0000000..2e49218 --- /dev/null +++ b/apps/builder/public/icons/square-virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square-xmark.svg b/apps/builder/public/icons/square-xmark.svg new file mode 100644 index 0000000..32bd236 --- /dev/null +++ b/apps/builder/public/icons/square-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/square.svg b/apps/builder/public/icons/square.svg new file mode 100644 index 0000000..54b6e4c --- /dev/null +++ b/apps/builder/public/icons/square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/staff-snake.svg b/apps/builder/public/icons/staff-snake.svg new file mode 100644 index 0000000..c11464a --- /dev/null +++ b/apps/builder/public/icons/staff-snake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stairs.svg b/apps/builder/public/icons/stairs.svg new file mode 100644 index 0000000..da410a5 --- /dev/null +++ b/apps/builder/public/icons/stairs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stamp.svg b/apps/builder/public/icons/stamp.svg new file mode 100644 index 0000000..58476e3 --- /dev/null +++ b/apps/builder/public/icons/stamp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stapler.svg b/apps/builder/public/icons/stapler.svg new file mode 100644 index 0000000..472db4b --- /dev/null +++ b/apps/builder/public/icons/stapler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star-and-crescent.svg b/apps/builder/public/icons/star-and-crescent.svg new file mode 100644 index 0000000..7848a40 --- /dev/null +++ b/apps/builder/public/icons/star-and-crescent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star-half-stroke.svg b/apps/builder/public/icons/star-half-stroke.svg new file mode 100644 index 0000000..f1ac660 --- /dev/null +++ b/apps/builder/public/icons/star-half-stroke.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star-half.svg b/apps/builder/public/icons/star-half.svg new file mode 100644 index 0000000..d77e29e --- /dev/null +++ b/apps/builder/public/icons/star-half.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star-of-david.svg b/apps/builder/public/icons/star-of-david.svg new file mode 100644 index 0000000..c1499d3 --- /dev/null +++ b/apps/builder/public/icons/star-of-david.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star-of-life.svg b/apps/builder/public/icons/star-of-life.svg new file mode 100644 index 0000000..e47bfe7 --- /dev/null +++ b/apps/builder/public/icons/star-of-life.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/star.svg b/apps/builder/public/icons/star.svg new file mode 100644 index 0000000..31b21c2 --- /dev/null +++ b/apps/builder/public/icons/star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sterling-sign.svg b/apps/builder/public/icons/sterling-sign.svg new file mode 100644 index 0000000..b328300 --- /dev/null +++ b/apps/builder/public/icons/sterling-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stethoscope.svg b/apps/builder/public/icons/stethoscope.svg new file mode 100644 index 0000000..9c3c9ec --- /dev/null +++ b/apps/builder/public/icons/stethoscope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stop.svg b/apps/builder/public/icons/stop.svg new file mode 100644 index 0000000..e2adac7 --- /dev/null +++ b/apps/builder/public/icons/stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stopwatch-20.svg b/apps/builder/public/icons/stopwatch-20.svg new file mode 100644 index 0000000..cd6197d --- /dev/null +++ b/apps/builder/public/icons/stopwatch-20.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stopwatch.svg b/apps/builder/public/icons/stopwatch.svg new file mode 100644 index 0000000..b4a58a1 --- /dev/null +++ b/apps/builder/public/icons/stopwatch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/store-slash.svg b/apps/builder/public/icons/store-slash.svg new file mode 100644 index 0000000..d65de19 --- /dev/null +++ b/apps/builder/public/icons/store-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/store.svg b/apps/builder/public/icons/store.svg new file mode 100644 index 0000000..f070795 --- /dev/null +++ b/apps/builder/public/icons/store.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/street-view.svg b/apps/builder/public/icons/street-view.svg new file mode 100644 index 0000000..ed132c9 --- /dev/null +++ b/apps/builder/public/icons/street-view.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/strikethrough.svg b/apps/builder/public/icons/strikethrough.svg new file mode 100644 index 0000000..fc0475f --- /dev/null +++ b/apps/builder/public/icons/strikethrough.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/stroopwafel.svg b/apps/builder/public/icons/stroopwafel.svg new file mode 100644 index 0000000..9a2760a --- /dev/null +++ b/apps/builder/public/icons/stroopwafel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/subscript.svg b/apps/builder/public/icons/subscript.svg new file mode 100644 index 0000000..e37964b --- /dev/null +++ b/apps/builder/public/icons/subscript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/suitcase-medical.svg b/apps/builder/public/icons/suitcase-medical.svg new file mode 100644 index 0000000..a5b6fa1 --- /dev/null +++ b/apps/builder/public/icons/suitcase-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/suitcase-rolling.svg b/apps/builder/public/icons/suitcase-rolling.svg new file mode 100644 index 0000000..69cf4f2 --- /dev/null +++ b/apps/builder/public/icons/suitcase-rolling.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/suitcase.svg b/apps/builder/public/icons/suitcase.svg new file mode 100644 index 0000000..9f80437 --- /dev/null +++ b/apps/builder/public/icons/suitcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sun-plant-wilt.svg b/apps/builder/public/icons/sun-plant-wilt.svg new file mode 100644 index 0000000..662fa56 --- /dev/null +++ b/apps/builder/public/icons/sun-plant-wilt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/sun.svg b/apps/builder/public/icons/sun.svg new file mode 100644 index 0000000..e81d882 --- /dev/null +++ b/apps/builder/public/icons/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/superscript.svg b/apps/builder/public/icons/superscript.svg new file mode 100644 index 0000000..3d32fbd --- /dev/null +++ b/apps/builder/public/icons/superscript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/swatchbook.svg b/apps/builder/public/icons/swatchbook.svg new file mode 100644 index 0000000..80c5a03 --- /dev/null +++ b/apps/builder/public/icons/swatchbook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/synagogue.svg b/apps/builder/public/icons/synagogue.svg new file mode 100644 index 0000000..68ca27a --- /dev/null +++ b/apps/builder/public/icons/synagogue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/syringe.svg b/apps/builder/public/icons/syringe.svg new file mode 100644 index 0000000..993190c --- /dev/null +++ b/apps/builder/public/icons/syringe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/t.svg b/apps/builder/public/icons/t.svg new file mode 100644 index 0000000..e1d6c85 --- /dev/null +++ b/apps/builder/public/icons/t.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table-cells-large.svg b/apps/builder/public/icons/table-cells-large.svg new file mode 100644 index 0000000..54abe65 --- /dev/null +++ b/apps/builder/public/icons/table-cells-large.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table-cells.svg b/apps/builder/public/icons/table-cells.svg new file mode 100644 index 0000000..bb113b4 --- /dev/null +++ b/apps/builder/public/icons/table-cells.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table-columns.svg b/apps/builder/public/icons/table-columns.svg new file mode 100644 index 0000000..2a594aa --- /dev/null +++ b/apps/builder/public/icons/table-columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table-list.svg b/apps/builder/public/icons/table-list.svg new file mode 100644 index 0000000..80d8e36 --- /dev/null +++ b/apps/builder/public/icons/table-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table-tennis-paddle-ball.svg b/apps/builder/public/icons/table-tennis-paddle-ball.svg new file mode 100644 index 0000000..8d3fe2e --- /dev/null +++ b/apps/builder/public/icons/table-tennis-paddle-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/table.svg b/apps/builder/public/icons/table.svg new file mode 100644 index 0000000..d324d5c --- /dev/null +++ b/apps/builder/public/icons/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tablet-button.svg b/apps/builder/public/icons/tablet-button.svg new file mode 100644 index 0000000..a66c845 --- /dev/null +++ b/apps/builder/public/icons/tablet-button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tablet-screen-button.svg b/apps/builder/public/icons/tablet-screen-button.svg new file mode 100644 index 0000000..b4701fa --- /dev/null +++ b/apps/builder/public/icons/tablet-screen-button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tablet.svg b/apps/builder/public/icons/tablet.svg new file mode 100644 index 0000000..c9d4090 --- /dev/null +++ b/apps/builder/public/icons/tablet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tablets.svg b/apps/builder/public/icons/tablets.svg new file mode 100644 index 0000000..14a8e3c --- /dev/null +++ b/apps/builder/public/icons/tablets.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tachograph-digital.svg b/apps/builder/public/icons/tachograph-digital.svg new file mode 100644 index 0000000..40decc3 --- /dev/null +++ b/apps/builder/public/icons/tachograph-digital.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tag.svg b/apps/builder/public/icons/tag.svg new file mode 100644 index 0000000..7f5b5e2 --- /dev/null +++ b/apps/builder/public/icons/tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tags.svg b/apps/builder/public/icons/tags.svg new file mode 100644 index 0000000..58c7fce --- /dev/null +++ b/apps/builder/public/icons/tags.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tape.svg b/apps/builder/public/icons/tape.svg new file mode 100644 index 0000000..aa74a88 --- /dev/null +++ b/apps/builder/public/icons/tape.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tarp-droplet.svg b/apps/builder/public/icons/tarp-droplet.svg new file mode 100644 index 0000000..4604d4f --- /dev/null +++ b/apps/builder/public/icons/tarp-droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tarp.svg b/apps/builder/public/icons/tarp.svg new file mode 100644 index 0000000..1272e3f --- /dev/null +++ b/apps/builder/public/icons/tarp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/taxi.svg b/apps/builder/public/icons/taxi.svg new file mode 100644 index 0000000..041c858 --- /dev/null +++ b/apps/builder/public/icons/taxi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/teeth-open.svg b/apps/builder/public/icons/teeth-open.svg new file mode 100644 index 0000000..2c30152 --- /dev/null +++ b/apps/builder/public/icons/teeth-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/teeth.svg b/apps/builder/public/icons/teeth.svg new file mode 100644 index 0000000..16272ac --- /dev/null +++ b/apps/builder/public/icons/teeth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-arrow-down.svg b/apps/builder/public/icons/temperature-arrow-down.svg new file mode 100644 index 0000000..f8a7bfc --- /dev/null +++ b/apps/builder/public/icons/temperature-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-arrow-up.svg b/apps/builder/public/icons/temperature-arrow-up.svg new file mode 100644 index 0000000..ea635d4 --- /dev/null +++ b/apps/builder/public/icons/temperature-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-empty.svg b/apps/builder/public/icons/temperature-empty.svg new file mode 100644 index 0000000..cb5638c --- /dev/null +++ b/apps/builder/public/icons/temperature-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-full.svg b/apps/builder/public/icons/temperature-full.svg new file mode 100644 index 0000000..b3c4a3b --- /dev/null +++ b/apps/builder/public/icons/temperature-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-half.svg b/apps/builder/public/icons/temperature-half.svg new file mode 100644 index 0000000..d1f1da1 --- /dev/null +++ b/apps/builder/public/icons/temperature-half.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-high.svg b/apps/builder/public/icons/temperature-high.svg new file mode 100644 index 0000000..272b36a --- /dev/null +++ b/apps/builder/public/icons/temperature-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-low.svg b/apps/builder/public/icons/temperature-low.svg new file mode 100644 index 0000000..bf148f8 --- /dev/null +++ b/apps/builder/public/icons/temperature-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-quarter.svg b/apps/builder/public/icons/temperature-quarter.svg new file mode 100644 index 0000000..1023b0f --- /dev/null +++ b/apps/builder/public/icons/temperature-quarter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/temperature-three-quarters.svg b/apps/builder/public/icons/temperature-three-quarters.svg new file mode 100644 index 0000000..19e6212 --- /dev/null +++ b/apps/builder/public/icons/temperature-three-quarters.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tenge-sign.svg b/apps/builder/public/icons/tenge-sign.svg new file mode 100644 index 0000000..5a2a971 --- /dev/null +++ b/apps/builder/public/icons/tenge-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tent-arrow-down-to-line.svg b/apps/builder/public/icons/tent-arrow-down-to-line.svg new file mode 100644 index 0000000..f31ebd1 --- /dev/null +++ b/apps/builder/public/icons/tent-arrow-down-to-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tent-arrow-left-right.svg b/apps/builder/public/icons/tent-arrow-left-right.svg new file mode 100644 index 0000000..2d6b39e --- /dev/null +++ b/apps/builder/public/icons/tent-arrow-left-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tent-arrow-turn-left.svg b/apps/builder/public/icons/tent-arrow-turn-left.svg new file mode 100644 index 0000000..ad84d98 --- /dev/null +++ b/apps/builder/public/icons/tent-arrow-turn-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tent-arrows-down.svg b/apps/builder/public/icons/tent-arrows-down.svg new file mode 100644 index 0000000..c672e16 --- /dev/null +++ b/apps/builder/public/icons/tent-arrows-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tent.svg b/apps/builder/public/icons/tent.svg new file mode 100644 index 0000000..c645978 --- /dev/null +++ b/apps/builder/public/icons/tent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tents.svg b/apps/builder/public/icons/tents.svg new file mode 100644 index 0000000..d4b2d01 --- /dev/null +++ b/apps/builder/public/icons/tents.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/terminal.svg b/apps/builder/public/icons/terminal.svg new file mode 100644 index 0000000..97127db --- /dev/null +++ b/apps/builder/public/icons/terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/text-height.svg b/apps/builder/public/icons/text-height.svg new file mode 100644 index 0000000..62d9449 --- /dev/null +++ b/apps/builder/public/icons/text-height.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/text-slash.svg b/apps/builder/public/icons/text-slash.svg new file mode 100644 index 0000000..01ceac0 --- /dev/null +++ b/apps/builder/public/icons/text-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/text-width.svg b/apps/builder/public/icons/text-width.svg new file mode 100644 index 0000000..d38198e --- /dev/null +++ b/apps/builder/public/icons/text-width.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/thermometer.svg b/apps/builder/public/icons/thermometer.svg new file mode 100644 index 0000000..969e2da --- /dev/null +++ b/apps/builder/public/icons/thermometer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/thumbs-down.svg b/apps/builder/public/icons/thumbs-down.svg new file mode 100644 index 0000000..f4a02af --- /dev/null +++ b/apps/builder/public/icons/thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/thumbs-up.svg b/apps/builder/public/icons/thumbs-up.svg new file mode 100644 index 0000000..c6cc67a --- /dev/null +++ b/apps/builder/public/icons/thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/thumbtack.svg b/apps/builder/public/icons/thumbtack.svg new file mode 100644 index 0000000..2c7b061 --- /dev/null +++ b/apps/builder/public/icons/thumbtack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ticket-simple.svg b/apps/builder/public/icons/ticket-simple.svg new file mode 100644 index 0000000..81316ae --- /dev/null +++ b/apps/builder/public/icons/ticket-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/ticket.svg b/apps/builder/public/icons/ticket.svg new file mode 100644 index 0000000..3ccf22e --- /dev/null +++ b/apps/builder/public/icons/ticket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/timeline.svg b/apps/builder/public/icons/timeline.svg new file mode 100644 index 0000000..88b3208 --- /dev/null +++ b/apps/builder/public/icons/timeline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toggle-off.svg b/apps/builder/public/icons/toggle-off.svg new file mode 100644 index 0000000..a0384db --- /dev/null +++ b/apps/builder/public/icons/toggle-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toggle-on.svg b/apps/builder/public/icons/toggle-on.svg new file mode 100644 index 0000000..b4a9c0d --- /dev/null +++ b/apps/builder/public/icons/toggle-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toilet-paper-slash.svg b/apps/builder/public/icons/toilet-paper-slash.svg new file mode 100644 index 0000000..78758aa --- /dev/null +++ b/apps/builder/public/icons/toilet-paper-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toilet-paper.svg b/apps/builder/public/icons/toilet-paper.svg new file mode 100644 index 0000000..f9fc0a2 --- /dev/null +++ b/apps/builder/public/icons/toilet-paper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toilet-portable.svg b/apps/builder/public/icons/toilet-portable.svg new file mode 100644 index 0000000..0730d5e --- /dev/null +++ b/apps/builder/public/icons/toilet-portable.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toilet.svg b/apps/builder/public/icons/toilet.svg new file mode 100644 index 0000000..27f3114 --- /dev/null +++ b/apps/builder/public/icons/toilet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toilets-portable.svg b/apps/builder/public/icons/toilets-portable.svg new file mode 100644 index 0000000..5f1a46c --- /dev/null +++ b/apps/builder/public/icons/toilets-portable.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/toolbox.svg b/apps/builder/public/icons/toolbox.svg new file mode 100644 index 0000000..7f03f66 --- /dev/null +++ b/apps/builder/public/icons/toolbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tooth.svg b/apps/builder/public/icons/tooth.svg new file mode 100644 index 0000000..835d6f2 --- /dev/null +++ b/apps/builder/public/icons/tooth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/torii-gate.svg b/apps/builder/public/icons/torii-gate.svg new file mode 100644 index 0000000..f69d717 --- /dev/null +++ b/apps/builder/public/icons/torii-gate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tornado.svg b/apps/builder/public/icons/tornado.svg new file mode 100644 index 0000000..0c9e8db --- /dev/null +++ b/apps/builder/public/icons/tornado.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tower-broadcast.svg b/apps/builder/public/icons/tower-broadcast.svg new file mode 100644 index 0000000..079dc24 --- /dev/null +++ b/apps/builder/public/icons/tower-broadcast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tower-cell.svg b/apps/builder/public/icons/tower-cell.svg new file mode 100644 index 0000000..ed45c1d --- /dev/null +++ b/apps/builder/public/icons/tower-cell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tower-observation.svg b/apps/builder/public/icons/tower-observation.svg new file mode 100644 index 0000000..9b852d7 --- /dev/null +++ b/apps/builder/public/icons/tower-observation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tractor.svg b/apps/builder/public/icons/tractor.svg new file mode 100644 index 0000000..56926e0 --- /dev/null +++ b/apps/builder/public/icons/tractor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trademark.svg b/apps/builder/public/icons/trademark.svg new file mode 100644 index 0000000..70eeaf4 --- /dev/null +++ b/apps/builder/public/icons/trademark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/traffic-light.svg b/apps/builder/public/icons/traffic-light.svg new file mode 100644 index 0000000..f7af47c --- /dev/null +++ b/apps/builder/public/icons/traffic-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trailer.svg b/apps/builder/public/icons/trailer.svg new file mode 100644 index 0000000..793fae7 --- /dev/null +++ b/apps/builder/public/icons/trailer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/train-subway.svg b/apps/builder/public/icons/train-subway.svg new file mode 100644 index 0000000..fb1e82e --- /dev/null +++ b/apps/builder/public/icons/train-subway.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/train-tram.svg b/apps/builder/public/icons/train-tram.svg new file mode 100644 index 0000000..1994c67 --- /dev/null +++ b/apps/builder/public/icons/train-tram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/train.svg b/apps/builder/public/icons/train.svg new file mode 100644 index 0000000..cf01fd4 --- /dev/null +++ b/apps/builder/public/icons/train.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/transgender.svg b/apps/builder/public/icons/transgender.svg new file mode 100644 index 0000000..611f672 --- /dev/null +++ b/apps/builder/public/icons/transgender.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trash-arrow-up.svg b/apps/builder/public/icons/trash-arrow-up.svg new file mode 100644 index 0000000..b470c6b --- /dev/null +++ b/apps/builder/public/icons/trash-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trash-can-arrow-up.svg b/apps/builder/public/icons/trash-can-arrow-up.svg new file mode 100644 index 0000000..b9e0ec9 --- /dev/null +++ b/apps/builder/public/icons/trash-can-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trash-can.svg b/apps/builder/public/icons/trash-can.svg new file mode 100644 index 0000000..f3fb0d9 --- /dev/null +++ b/apps/builder/public/icons/trash-can.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trash.svg b/apps/builder/public/icons/trash.svg new file mode 100644 index 0000000..8e33c91 --- /dev/null +++ b/apps/builder/public/icons/trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tree-city.svg b/apps/builder/public/icons/tree-city.svg new file mode 100644 index 0000000..15221ad --- /dev/null +++ b/apps/builder/public/icons/tree-city.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tree.svg b/apps/builder/public/icons/tree.svg new file mode 100644 index 0000000..af16408 --- /dev/null +++ b/apps/builder/public/icons/tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/triangle-exclamation.svg b/apps/builder/public/icons/triangle-exclamation.svg new file mode 100644 index 0000000..bd04934 --- /dev/null +++ b/apps/builder/public/icons/triangle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trophy.svg b/apps/builder/public/icons/trophy.svg new file mode 100644 index 0000000..b44b30c --- /dev/null +++ b/apps/builder/public/icons/trophy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trowel-bricks.svg b/apps/builder/public/icons/trowel-bricks.svg new file mode 100644 index 0000000..012b568 --- /dev/null +++ b/apps/builder/public/icons/trowel-bricks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/trowel.svg b/apps/builder/public/icons/trowel.svg new file mode 100644 index 0000000..11c15af --- /dev/null +++ b/apps/builder/public/icons/trowel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-arrow-right.svg b/apps/builder/public/icons/truck-arrow-right.svg new file mode 100644 index 0000000..4490e68 --- /dev/null +++ b/apps/builder/public/icons/truck-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-droplet.svg b/apps/builder/public/icons/truck-droplet.svg new file mode 100644 index 0000000..2e3264d --- /dev/null +++ b/apps/builder/public/icons/truck-droplet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-fast.svg b/apps/builder/public/icons/truck-fast.svg new file mode 100644 index 0000000..606bbdf --- /dev/null +++ b/apps/builder/public/icons/truck-fast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-field-un.svg b/apps/builder/public/icons/truck-field-un.svg new file mode 100644 index 0000000..c458ae4 --- /dev/null +++ b/apps/builder/public/icons/truck-field-un.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-field.svg b/apps/builder/public/icons/truck-field.svg new file mode 100644 index 0000000..3018845 --- /dev/null +++ b/apps/builder/public/icons/truck-field.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-front.svg b/apps/builder/public/icons/truck-front.svg new file mode 100644 index 0000000..33a4f70 --- /dev/null +++ b/apps/builder/public/icons/truck-front.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-medical.svg b/apps/builder/public/icons/truck-medical.svg new file mode 100644 index 0000000..87908a0 --- /dev/null +++ b/apps/builder/public/icons/truck-medical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-monster.svg b/apps/builder/public/icons/truck-monster.svg new file mode 100644 index 0000000..d3d8309 --- /dev/null +++ b/apps/builder/public/icons/truck-monster.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-moving.svg b/apps/builder/public/icons/truck-moving.svg new file mode 100644 index 0000000..713f030 --- /dev/null +++ b/apps/builder/public/icons/truck-moving.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-pickup.svg b/apps/builder/public/icons/truck-pickup.svg new file mode 100644 index 0000000..a93a55d --- /dev/null +++ b/apps/builder/public/icons/truck-pickup.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-plane.svg b/apps/builder/public/icons/truck-plane.svg new file mode 100644 index 0000000..b96eea3 --- /dev/null +++ b/apps/builder/public/icons/truck-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck-ramp-box.svg b/apps/builder/public/icons/truck-ramp-box.svg new file mode 100644 index 0000000..89b4249 --- /dev/null +++ b/apps/builder/public/icons/truck-ramp-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/truck.svg b/apps/builder/public/icons/truck.svg new file mode 100644 index 0000000..ff2645b --- /dev/null +++ b/apps/builder/public/icons/truck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tty.svg b/apps/builder/public/icons/tty.svg new file mode 100644 index 0000000..e8944de --- /dev/null +++ b/apps/builder/public/icons/tty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/turkish-lira-sign.svg b/apps/builder/public/icons/turkish-lira-sign.svg new file mode 100644 index 0000000..b746618 --- /dev/null +++ b/apps/builder/public/icons/turkish-lira-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/turn-down.svg b/apps/builder/public/icons/turn-down.svg new file mode 100644 index 0000000..4e8f219 --- /dev/null +++ b/apps/builder/public/icons/turn-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/turn-up.svg b/apps/builder/public/icons/turn-up.svg new file mode 100644 index 0000000..82ff26e --- /dev/null +++ b/apps/builder/public/icons/turn-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/tv.svg b/apps/builder/public/icons/tv.svg new file mode 100644 index 0000000..b209346 --- /dev/null +++ b/apps/builder/public/icons/tv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/u.svg b/apps/builder/public/icons/u.svg new file mode 100644 index 0000000..b11a476 --- /dev/null +++ b/apps/builder/public/icons/u.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/umbrella-beach.svg b/apps/builder/public/icons/umbrella-beach.svg new file mode 100644 index 0000000..e973b1d --- /dev/null +++ b/apps/builder/public/icons/umbrella-beach.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/umbrella.svg b/apps/builder/public/icons/umbrella.svg new file mode 100644 index 0000000..9c1a4e9 --- /dev/null +++ b/apps/builder/public/icons/umbrella.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/underline.svg b/apps/builder/public/icons/underline.svg new file mode 100644 index 0000000..8a24216 --- /dev/null +++ b/apps/builder/public/icons/underline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/universal-access.svg b/apps/builder/public/icons/universal-access.svg new file mode 100644 index 0000000..cc83f9c --- /dev/null +++ b/apps/builder/public/icons/universal-access.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/unlock-keyhole.svg b/apps/builder/public/icons/unlock-keyhole.svg new file mode 100644 index 0000000..7f12050 --- /dev/null +++ b/apps/builder/public/icons/unlock-keyhole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/unlock.svg b/apps/builder/public/icons/unlock.svg new file mode 100644 index 0000000..43df3f9 --- /dev/null +++ b/apps/builder/public/icons/unlock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/up-down-left-right.svg b/apps/builder/public/icons/up-down-left-right.svg new file mode 100644 index 0000000..054ae43 --- /dev/null +++ b/apps/builder/public/icons/up-down-left-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/up-down.svg b/apps/builder/public/icons/up-down.svg new file mode 100644 index 0000000..baf690c --- /dev/null +++ b/apps/builder/public/icons/up-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/up-long.svg b/apps/builder/public/icons/up-long.svg new file mode 100644 index 0000000..07c84aa --- /dev/null +++ b/apps/builder/public/icons/up-long.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/up-right-and-down-left-from-center.svg b/apps/builder/public/icons/up-right-and-down-left-from-center.svg new file mode 100644 index 0000000..ff2d0b2 --- /dev/null +++ b/apps/builder/public/icons/up-right-and-down-left-from-center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/up-right-from-square.svg b/apps/builder/public/icons/up-right-from-square.svg new file mode 100644 index 0000000..40e8777 --- /dev/null +++ b/apps/builder/public/icons/up-right-from-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/upload.svg b/apps/builder/public/icons/upload.svg new file mode 100644 index 0000000..f2d07ee --- /dev/null +++ b/apps/builder/public/icons/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-astronaut.svg b/apps/builder/public/icons/user-astronaut.svg new file mode 100644 index 0000000..7ea5013 --- /dev/null +++ b/apps/builder/public/icons/user-astronaut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-check.svg b/apps/builder/public/icons/user-check.svg new file mode 100644 index 0000000..c7d00f9 --- /dev/null +++ b/apps/builder/public/icons/user-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-clock.svg b/apps/builder/public/icons/user-clock.svg new file mode 100644 index 0000000..2fbf4d3 --- /dev/null +++ b/apps/builder/public/icons/user-clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-doctor.svg b/apps/builder/public/icons/user-doctor.svg new file mode 100644 index 0000000..2a7bea5 --- /dev/null +++ b/apps/builder/public/icons/user-doctor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-gear.svg b/apps/builder/public/icons/user-gear.svg new file mode 100644 index 0000000..ca1afa4 --- /dev/null +++ b/apps/builder/public/icons/user-gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-graduate.svg b/apps/builder/public/icons/user-graduate.svg new file mode 100644 index 0000000..ed7c175 --- /dev/null +++ b/apps/builder/public/icons/user-graduate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-group.svg b/apps/builder/public/icons/user-group.svg new file mode 100644 index 0000000..01f7de9 --- /dev/null +++ b/apps/builder/public/icons/user-group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-injured.svg b/apps/builder/public/icons/user-injured.svg new file mode 100644 index 0000000..f3508a7 --- /dev/null +++ b/apps/builder/public/icons/user-injured.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-large-slash.svg b/apps/builder/public/icons/user-large-slash.svg new file mode 100644 index 0000000..77eb343 --- /dev/null +++ b/apps/builder/public/icons/user-large-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-large.svg b/apps/builder/public/icons/user-large.svg new file mode 100644 index 0000000..e67c811 --- /dev/null +++ b/apps/builder/public/icons/user-large.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-lock.svg b/apps/builder/public/icons/user-lock.svg new file mode 100644 index 0000000..ac32f46 --- /dev/null +++ b/apps/builder/public/icons/user-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-minus.svg b/apps/builder/public/icons/user-minus.svg new file mode 100644 index 0000000..4eef61f --- /dev/null +++ b/apps/builder/public/icons/user-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-ninja.svg b/apps/builder/public/icons/user-ninja.svg new file mode 100644 index 0000000..c87b471 --- /dev/null +++ b/apps/builder/public/icons/user-ninja.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-nurse.svg b/apps/builder/public/icons/user-nurse.svg new file mode 100644 index 0000000..05a2aa2 --- /dev/null +++ b/apps/builder/public/icons/user-nurse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-pen.svg b/apps/builder/public/icons/user-pen.svg new file mode 100644 index 0000000..6823a18 --- /dev/null +++ b/apps/builder/public/icons/user-pen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-plus.svg b/apps/builder/public/icons/user-plus.svg new file mode 100644 index 0000000..1cb4622 --- /dev/null +++ b/apps/builder/public/icons/user-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-secret.svg b/apps/builder/public/icons/user-secret.svg new file mode 100644 index 0000000..1af1914 --- /dev/null +++ b/apps/builder/public/icons/user-secret.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-shield.svg b/apps/builder/public/icons/user-shield.svg new file mode 100644 index 0000000..3006285 --- /dev/null +++ b/apps/builder/public/icons/user-shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-slash.svg b/apps/builder/public/icons/user-slash.svg new file mode 100644 index 0000000..3ec888f --- /dev/null +++ b/apps/builder/public/icons/user-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-tag.svg b/apps/builder/public/icons/user-tag.svg new file mode 100644 index 0000000..8ec1780 --- /dev/null +++ b/apps/builder/public/icons/user-tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-tie.svg b/apps/builder/public/icons/user-tie.svg new file mode 100644 index 0000000..20f5074 --- /dev/null +++ b/apps/builder/public/icons/user-tie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user-xmark.svg b/apps/builder/public/icons/user-xmark.svg new file mode 100644 index 0000000..696139f --- /dev/null +++ b/apps/builder/public/icons/user-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/user.svg b/apps/builder/public/icons/user.svg new file mode 100644 index 0000000..c04f5bc --- /dev/null +++ b/apps/builder/public/icons/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-between-lines.svg b/apps/builder/public/icons/users-between-lines.svg new file mode 100644 index 0000000..22ab72f --- /dev/null +++ b/apps/builder/public/icons/users-between-lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-gear.svg b/apps/builder/public/icons/users-gear.svg new file mode 100644 index 0000000..5b0f4ca --- /dev/null +++ b/apps/builder/public/icons/users-gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-line.svg b/apps/builder/public/icons/users-line.svg new file mode 100644 index 0000000..4a55284 --- /dev/null +++ b/apps/builder/public/icons/users-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-rays.svg b/apps/builder/public/icons/users-rays.svg new file mode 100644 index 0000000..968bfeb --- /dev/null +++ b/apps/builder/public/icons/users-rays.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-rectangle.svg b/apps/builder/public/icons/users-rectangle.svg new file mode 100644 index 0000000..38d226c --- /dev/null +++ b/apps/builder/public/icons/users-rectangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-slash.svg b/apps/builder/public/icons/users-slash.svg new file mode 100644 index 0000000..faab44b --- /dev/null +++ b/apps/builder/public/icons/users-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users-viewfinder.svg b/apps/builder/public/icons/users-viewfinder.svg new file mode 100644 index 0000000..c559fcb --- /dev/null +++ b/apps/builder/public/icons/users-viewfinder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/users.svg b/apps/builder/public/icons/users.svg new file mode 100644 index 0000000..2d36d29 --- /dev/null +++ b/apps/builder/public/icons/users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/utensils.svg b/apps/builder/public/icons/utensils.svg new file mode 100644 index 0000000..6d7a27a --- /dev/null +++ b/apps/builder/public/icons/utensils.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/v.svg b/apps/builder/public/icons/v.svg new file mode 100644 index 0000000..5c1e749 --- /dev/null +++ b/apps/builder/public/icons/v.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/van-shuttle.svg b/apps/builder/public/icons/van-shuttle.svg new file mode 100644 index 0000000..64feb32 --- /dev/null +++ b/apps/builder/public/icons/van-shuttle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vault.svg b/apps/builder/public/icons/vault.svg new file mode 100644 index 0000000..065a06c --- /dev/null +++ b/apps/builder/public/icons/vault.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vector-square.svg b/apps/builder/public/icons/vector-square.svg new file mode 100644 index 0000000..749cc66 --- /dev/null +++ b/apps/builder/public/icons/vector-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/venus-double.svg b/apps/builder/public/icons/venus-double.svg new file mode 100644 index 0000000..c82fda3 --- /dev/null +++ b/apps/builder/public/icons/venus-double.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/venus-mars.svg b/apps/builder/public/icons/venus-mars.svg new file mode 100644 index 0000000..3607f29 --- /dev/null +++ b/apps/builder/public/icons/venus-mars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/venus.svg b/apps/builder/public/icons/venus.svg new file mode 100644 index 0000000..cd63df0 --- /dev/null +++ b/apps/builder/public/icons/venus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vest-patches.svg b/apps/builder/public/icons/vest-patches.svg new file mode 100644 index 0000000..e91d684 --- /dev/null +++ b/apps/builder/public/icons/vest-patches.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vest.svg b/apps/builder/public/icons/vest.svg new file mode 100644 index 0000000..f11d701 --- /dev/null +++ b/apps/builder/public/icons/vest.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vial-circle-check.svg b/apps/builder/public/icons/vial-circle-check.svg new file mode 100644 index 0000000..65ba5ed --- /dev/null +++ b/apps/builder/public/icons/vial-circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vial-virus.svg b/apps/builder/public/icons/vial-virus.svg new file mode 100644 index 0000000..13e16cd --- /dev/null +++ b/apps/builder/public/icons/vial-virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vial.svg b/apps/builder/public/icons/vial.svg new file mode 100644 index 0000000..9a0e1dd --- /dev/null +++ b/apps/builder/public/icons/vial.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vials.svg b/apps/builder/public/icons/vials.svg new file mode 100644 index 0000000..aa6e4e7 --- /dev/null +++ b/apps/builder/public/icons/vials.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/video-slash.svg b/apps/builder/public/icons/video-slash.svg new file mode 100644 index 0000000..7a18c08 --- /dev/null +++ b/apps/builder/public/icons/video-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/video.svg b/apps/builder/public/icons/video.svg new file mode 100644 index 0000000..9b581cd --- /dev/null +++ b/apps/builder/public/icons/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vihara.svg b/apps/builder/public/icons/vihara.svg new file mode 100644 index 0000000..8e932d8 --- /dev/null +++ b/apps/builder/public/icons/vihara.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/virus-covid-slash.svg b/apps/builder/public/icons/virus-covid-slash.svg new file mode 100644 index 0000000..6d0419b --- /dev/null +++ b/apps/builder/public/icons/virus-covid-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/virus-covid.svg b/apps/builder/public/icons/virus-covid.svg new file mode 100644 index 0000000..6784cb9 --- /dev/null +++ b/apps/builder/public/icons/virus-covid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/virus-slash.svg b/apps/builder/public/icons/virus-slash.svg new file mode 100644 index 0000000..da000fb --- /dev/null +++ b/apps/builder/public/icons/virus-slash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/virus.svg b/apps/builder/public/icons/virus.svg new file mode 100644 index 0000000..8585ede --- /dev/null +++ b/apps/builder/public/icons/virus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/viruses.svg b/apps/builder/public/icons/viruses.svg new file mode 100644 index 0000000..5effbea --- /dev/null +++ b/apps/builder/public/icons/viruses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/voicemail.svg b/apps/builder/public/icons/voicemail.svg new file mode 100644 index 0000000..407b017 --- /dev/null +++ b/apps/builder/public/icons/voicemail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volcano.svg b/apps/builder/public/icons/volcano.svg new file mode 100644 index 0000000..e42e586 --- /dev/null +++ b/apps/builder/public/icons/volcano.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volleyball.svg b/apps/builder/public/icons/volleyball.svg new file mode 100644 index 0000000..7ef78bf --- /dev/null +++ b/apps/builder/public/icons/volleyball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volume-high.svg b/apps/builder/public/icons/volume-high.svg new file mode 100644 index 0000000..85303a5 --- /dev/null +++ b/apps/builder/public/icons/volume-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volume-low.svg b/apps/builder/public/icons/volume-low.svg new file mode 100644 index 0000000..c2e286a --- /dev/null +++ b/apps/builder/public/icons/volume-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volume-off.svg b/apps/builder/public/icons/volume-off.svg new file mode 100644 index 0000000..411d13f --- /dev/null +++ b/apps/builder/public/icons/volume-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/volume-xmark.svg b/apps/builder/public/icons/volume-xmark.svg new file mode 100644 index 0000000..31af0de --- /dev/null +++ b/apps/builder/public/icons/volume-xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/vr-cardboard.svg b/apps/builder/public/icons/vr-cardboard.svg new file mode 100644 index 0000000..73e8fba --- /dev/null +++ b/apps/builder/public/icons/vr-cardboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/w.svg b/apps/builder/public/icons/w.svg new file mode 100644 index 0000000..27f36ce --- /dev/null +++ b/apps/builder/public/icons/w.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/walkie-talkie.svg b/apps/builder/public/icons/walkie-talkie.svg new file mode 100644 index 0000000..9025248 --- /dev/null +++ b/apps/builder/public/icons/walkie-talkie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wallet.svg b/apps/builder/public/icons/wallet.svg new file mode 100644 index 0000000..0021053 --- /dev/null +++ b/apps/builder/public/icons/wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wand-magic-sparkles.svg b/apps/builder/public/icons/wand-magic-sparkles.svg new file mode 100644 index 0000000..985df05 --- /dev/null +++ b/apps/builder/public/icons/wand-magic-sparkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wand-magic.svg b/apps/builder/public/icons/wand-magic.svg new file mode 100644 index 0000000..947adfd --- /dev/null +++ b/apps/builder/public/icons/wand-magic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wand-sparkles.svg b/apps/builder/public/icons/wand-sparkles.svg new file mode 100644 index 0000000..b9731b3 --- /dev/null +++ b/apps/builder/public/icons/wand-sparkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/warehouse.svg b/apps/builder/public/icons/warehouse.svg new file mode 100644 index 0000000..a204ecd --- /dev/null +++ b/apps/builder/public/icons/warehouse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/water-ladder.svg b/apps/builder/public/icons/water-ladder.svg new file mode 100644 index 0000000..116f288 --- /dev/null +++ b/apps/builder/public/icons/water-ladder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/water.svg b/apps/builder/public/icons/water.svg new file mode 100644 index 0000000..a608f78 --- /dev/null +++ b/apps/builder/public/icons/water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wave-square.svg b/apps/builder/public/icons/wave-square.svg new file mode 100644 index 0000000..187e240 --- /dev/null +++ b/apps/builder/public/icons/wave-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/weight-hanging.svg b/apps/builder/public/icons/weight-hanging.svg new file mode 100644 index 0000000..65f909c --- /dev/null +++ b/apps/builder/public/icons/weight-hanging.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/weight-scale.svg b/apps/builder/public/icons/weight-scale.svg new file mode 100644 index 0000000..f5b099a --- /dev/null +++ b/apps/builder/public/icons/weight-scale.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wheat-awn-circle-exclamation.svg b/apps/builder/public/icons/wheat-awn-circle-exclamation.svg new file mode 100644 index 0000000..5da2f55 --- /dev/null +++ b/apps/builder/public/icons/wheat-awn-circle-exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wheat-awn.svg b/apps/builder/public/icons/wheat-awn.svg new file mode 100644 index 0000000..8a34b08 --- /dev/null +++ b/apps/builder/public/icons/wheat-awn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wheelchair-move.svg b/apps/builder/public/icons/wheelchair-move.svg new file mode 100644 index 0000000..bbf8854 --- /dev/null +++ b/apps/builder/public/icons/wheelchair-move.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wheelchair.svg b/apps/builder/public/icons/wheelchair.svg new file mode 100644 index 0000000..482cd56 --- /dev/null +++ b/apps/builder/public/icons/wheelchair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/whiskey-glass.svg b/apps/builder/public/icons/whiskey-glass.svg new file mode 100644 index 0000000..13257bd --- /dev/null +++ b/apps/builder/public/icons/whiskey-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wifi.svg b/apps/builder/public/icons/wifi.svg new file mode 100644 index 0000000..556cc82 --- /dev/null +++ b/apps/builder/public/icons/wifi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wind.svg b/apps/builder/public/icons/wind.svg new file mode 100644 index 0000000..a4db64f --- /dev/null +++ b/apps/builder/public/icons/wind.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/window-maximize.svg b/apps/builder/public/icons/window-maximize.svg new file mode 100644 index 0000000..f51a38e --- /dev/null +++ b/apps/builder/public/icons/window-maximize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/window-minimize.svg b/apps/builder/public/icons/window-minimize.svg new file mode 100644 index 0000000..40ef123 --- /dev/null +++ b/apps/builder/public/icons/window-minimize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/window-restore.svg b/apps/builder/public/icons/window-restore.svg new file mode 100644 index 0000000..fad5f83 --- /dev/null +++ b/apps/builder/public/icons/window-restore.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wine-bottle.svg b/apps/builder/public/icons/wine-bottle.svg new file mode 100644 index 0000000..f40b6fe --- /dev/null +++ b/apps/builder/public/icons/wine-bottle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wine-glass-empty.svg b/apps/builder/public/icons/wine-glass-empty.svg new file mode 100644 index 0000000..f94814b --- /dev/null +++ b/apps/builder/public/icons/wine-glass-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wine-glass.svg b/apps/builder/public/icons/wine-glass.svg new file mode 100644 index 0000000..ca1ad3b --- /dev/null +++ b/apps/builder/public/icons/wine-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/won-sign.svg b/apps/builder/public/icons/won-sign.svg new file mode 100644 index 0000000..481ac67 --- /dev/null +++ b/apps/builder/public/icons/won-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/worm.svg b/apps/builder/public/icons/worm.svg new file mode 100644 index 0000000..b569ba6 --- /dev/null +++ b/apps/builder/public/icons/worm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/wrench.svg b/apps/builder/public/icons/wrench.svg new file mode 100644 index 0000000..e3d1e50 --- /dev/null +++ b/apps/builder/public/icons/wrench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/x-ray.svg b/apps/builder/public/icons/x-ray.svg new file mode 100644 index 0000000..220fb34 --- /dev/null +++ b/apps/builder/public/icons/x-ray.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/x.svg b/apps/builder/public/icons/x.svg new file mode 100644 index 0000000..a85315e --- /dev/null +++ b/apps/builder/public/icons/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/xmark.svg b/apps/builder/public/icons/xmark.svg new file mode 100644 index 0000000..5ad62fc --- /dev/null +++ b/apps/builder/public/icons/xmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/xmarks-lines.svg b/apps/builder/public/icons/xmarks-lines.svg new file mode 100644 index 0000000..5316c3f --- /dev/null +++ b/apps/builder/public/icons/xmarks-lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/y.svg b/apps/builder/public/icons/y.svg new file mode 100644 index 0000000..22f9239 --- /dev/null +++ b/apps/builder/public/icons/y.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/yen-sign.svg b/apps/builder/public/icons/yen-sign.svg new file mode 100644 index 0000000..c78f072 --- /dev/null +++ b/apps/builder/public/icons/yen-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/yin-yang.svg b/apps/builder/public/icons/yin-yang.svg new file mode 100644 index 0000000..6f1590f --- /dev/null +++ b/apps/builder/public/icons/yin-yang.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/icons/z.svg b/apps/builder/public/icons/z.svg new file mode 100644 index 0000000..d5ea310 --- /dev/null +++ b/apps/builder/public/icons/z.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/builder/public/images/actionRequiredBanner.png b/apps/builder/public/images/actionRequiredBanner.png new file mode 100644 index 0000000..f0c8c37 Binary files /dev/null and b/apps/builder/public/images/actionRequiredBanner.png differ diff --git a/apps/builder/public/images/backgrounds/brightRain.jpeg b/apps/builder/public/images/backgrounds/brightRain.jpeg new file mode 100644 index 0000000..942e950 Binary files /dev/null and b/apps/builder/public/images/backgrounds/brightRain.jpeg differ diff --git a/apps/builder/public/images/backgrounds/rayOfLights.jpeg b/apps/builder/public/images/backgrounds/rayOfLights.jpeg new file mode 100644 index 0000000..828ad25 Binary files /dev/null and b/apps/builder/public/images/backgrounds/rayOfLights.jpeg differ diff --git a/apps/builder/public/images/dark-mode.png b/apps/builder/public/images/dark-mode.png new file mode 100644 index 0000000..cbc025c Binary files /dev/null and b/apps/builder/public/images/dark-mode.png differ diff --git a/apps/builder/public/images/dynamic-image.png b/apps/builder/public/images/dynamic-image.png new file mode 100644 index 0000000..a4ed173 Binary files /dev/null and b/apps/builder/public/images/dynamic-image.png differ diff --git a/apps/builder/public/images/google-spreadsheets-scopes.png b/apps/builder/public/images/google-spreadsheets-scopes.png new file mode 100644 index 0000000..c1fc7b7 Binary files /dev/null and b/apps/builder/public/images/google-spreadsheets-scopes.png differ diff --git a/apps/builder/public/images/invitationBanner.png b/apps/builder/public/images/invitationBanner.png new file mode 100644 index 0000000..87ba024 Binary files /dev/null and b/apps/builder/public/images/invitationBanner.png differ diff --git a/apps/builder/public/images/light-mode.png b/apps/builder/public/images/light-mode.png new file mode 100644 index 0000000..9b909ed Binary files /dev/null and b/apps/builder/public/images/light-mode.png differ diff --git a/apps/builder/public/images/meta-system-user-assets.png b/apps/builder/public/images/meta-system-user-assets.png new file mode 100644 index 0000000..efbbdfe Binary files /dev/null and b/apps/builder/public/images/meta-system-user-assets.png differ diff --git a/apps/builder/public/images/og.png b/apps/builder/public/images/og.png new file mode 100644 index 0000000..762c3e6 Binary files /dev/null and b/apps/builder/public/images/og.png differ diff --git a/apps/builder/public/images/system-mode.png b/apps/builder/public/images/system-mode.png new file mode 100644 index 0000000..e53c092 Binary files /dev/null and b/apps/builder/public/images/system-mode.png differ diff --git a/apps/builder/public/images/whatsapp-phone-selection.png b/apps/builder/public/images/whatsapp-phone-selection.png new file mode 100644 index 0000000..ef6996b Binary files /dev/null and b/apps/builder/public/images/whatsapp-phone-selection.png differ diff --git a/apps/builder/public/images/whatsapp-quickstart-page.png b/apps/builder/public/images/whatsapp-quickstart-page.png new file mode 100644 index 0000000..01b6e3f Binary files /dev/null and b/apps/builder/public/images/whatsapp-quickstart-page.png differ diff --git a/apps/builder/public/images/yourBotIsFlyingBanner.png b/apps/builder/public/images/yourBotIsFlyingBanner.png new file mode 100644 index 0000000..d6d5c8f Binary files /dev/null and b/apps/builder/public/images/yourBotIsFlyingBanner.png differ diff --git a/apps/builder/public/images/yourMagicLinkBanner.png b/apps/builder/public/images/yourMagicLinkBanner.png new file mode 100644 index 0000000..90cafe2 Binary files /dev/null and b/apps/builder/public/images/yourMagicLinkBanner.png differ diff --git a/apps/builder/public/locales/de.json b/apps/builder/public/locales/de.json new file mode 100644 index 0000000..adb5ec3 --- /dev/null +++ b/apps/builder/public/locales/de.json @@ -0,0 +1,247 @@ +{ + "account.apiTokens.createButton.label": "Erstellen", + "account.apiTokens.createModal.copyInstruction": "Bitte kopiere deinen Token und bewahre ihn an einem sicheren Ort auf.", + "account.apiTokens.createModal.createButton.label": "Token erstellen", + "account.apiTokens.createModal.createHeading": "Token erstellen", + "account.apiTokens.createModal.createdHeading": "Token erstellt", + "account.apiTokens.createModal.doneButton.label": "Fertig", + "account.apiTokens.createModal.nameInput.label": "Gib einen eindeutigen Namen für deinen Token ein, um ihn von anderen Token zu unterscheiden.", + "account.apiTokens.createModal.nameInput.placeholder": "Z.B. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Aus Sicherheitsgründen können wir ihn nicht erneut anzeigen.", + "account.apiTokens.deleteButton.label": "Löschen", + "account.apiTokens.deleteConfirmationMessage": "Der Token tokenName wird dauerhaft widerrufen, bist du sicher, dass du fortfahren möchtest?", + "account.apiTokens.description": "Diese Token ermöglichen es anderen Apps, dein gesamtes Konto und Typebots zu steuern. Sei vorsichtig!", + "account.apiTokens.heading": "API-Token", + "account.apiTokens.table.createdHeader": "Erstellt", + "account.apiTokens.table.nameHeader": "Name", + "account.myAccount.changePhotoButton.label": "Foto ändern", + "account.myAccount.changePhotoButton.specification": ".jpg oder .png, max 1MB", + "account.myAccount.emailInput.disabledTooltip": "Das Aktualisieren der E-Mail-Adresse ist nicht verfügbar. Kontaktiere den Support, wenn du sie ändern möchtest.", + "account.myAccount.emailInput.label": "E-Mail-Adresse:", + "account.myAccount.nameInput.label": "Name:", + "account.preferences.appearance.darkLabel": "Dunkel", + "account.preferences.appearance.heading": "Erscheinungsbild", + "account.preferences.appearance.lightLabel": "Hell", + "account.preferences.appearance.systemLabel": "System", + "account.preferences.graphNavigation.heading": "Editor-Navigation", + "account.preferences.graphNavigation.mouse.description": "Bewege dich, indem du das Board ziehst und zoome rein/raus mit dem Mausrad", + "account.preferences.graphNavigation.mouse.label": "Maus", + "account.preferences.graphNavigation.trackpad.description": "Bewege das Board mit 2 Fingern und zoome rein/raus, indem du kneifst", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Sprache", + "account.preferences.language.tooltip": "Die Übersetzungen sind noch nicht vollständig. Es ist eine laufende Arbeit. \uD83E\uDD13", + "analytics.completionRateLabel": "Abschlussrate", + "analytics.notAvailableLabel": "Nicht verfügbar", + "analytics.startsLabel": "Starts", + "analytics.viewsLabel": "Ansichten", + "auth.emailSubmitButton.label": "Absenden", + "auth.error.default": "Versuche, dich mit einem anderen Konto anzumelden.", + "auth.error.email": "E-Mail nicht gefunden. Versuche, dich mit einem anderen Anbieter anzumelden.", + "auth.error.oauthNotLinked": "Um deine Identität zu bestätigen, melde dich mit demselben Konto an, das du ursprünglich verwendet hast.", + "auth.error.unknown": "Ein Fehler ist aufgetreten. Bitte versuche es erneut.", + "auth.magicLink.description": "Vergiss nicht, deinen Spam-Ordner zu überprüfen.", + "auth.magicLink.title": "Eine E-Mail mit magischem Link wurde gesendet. \uD83E\uDE84", + "auth.noProvider.link": "mindestens einen Authentifizierungsanbieter konfigurieren (E-Mail, Google, GitHub, Facebook oder Azure AD).", + "auth.noProvider.preLink": "Du musst", + "auth.orEmailLabel": "Oder mit deiner E-Mail", + "auth.register.aggreeToTerms": "Durch die Registrierung stimmst du unseren nutzungsbedingungen und datenschutzrichtlinie zu.", + "auth.register.alreadyHaveAccountLabel.link": "Anmelden", + "auth.register.alreadyHaveAccountLabel.preLink": "Bereits ein Konto vorhanden?", + "auth.register.heading": "Konto erstellen", + "auth.signin.heading": "Anmelden", + "auth.signin.noAccountLabel.link": "Kostenlos anmelden", + "auth.signin.noAccountLabel.preLink": "Noch kein Konto?", + "auth.signinErrorToast.description": "Anmeldungen sind deaktiviert.", + "auth.signinErrorToast.title": "Nicht autorisiert", + "auth.signinErrorToast.tooManyRequests": "Zu viele Anfragen. Versuche es später erneut.", + "auth.socialLogin.azureButton.label": "Mit {azureProviderName} fortfahren", + "auth.socialLogin.customButton.label": "Mit {customProviderName} fortfahren", + "auth.socialLogin.facebookButton.label": "Mit Facebook fortfahren", + "auth.socialLogin.githubButton.label": "Mit GitHub fortfahren", + "auth.socialLogin.gitlabButton.label": "Mit {gitlabProviderName} fortfahren", + "auth.socialLogin.googleButton.label": "Mit Google fortfahren", + "back": "Zurück", + "billing.billingPortalButton.label": "Abrechnungsportal", + "billing.contribution.link": "Erfahre mehr.", + "billing.contribution.preLink": "Typebot trägt 1% deines Abonnements dazu bei, CO₂ aus der Atmosphäre zu entfernen.", + "billing.currentSubscription.cancelDate": "Wird storniert am", + "billing.currentSubscription.heading": "Abonnement", + "billing.currentSubscription.pastDueAlert": "Die letzte Zahlung ist fehlgeschlagen. Gehen Sie zum Abrechnungsportal, um fortzufahren und eine Kündigung Ihres Abonnements zu vermeiden.", + "billing.currentSubscription.subheading": "Aktuelles Workspace-Abonnement:", + "billing.customLimit.link": "Lass uns darüber sprechen!", + "billing.customLimit.preLink": "Brauchst du individuelle Limits? Spezielle Funktionen?", + "billing.invoices.empty": "Keine Rechnungen für diesen Workspace gefunden.", + "billing.invoices.heading": "Rechnungen", + "billing.invoices.paidAt": "Bezahlt am", + "billing.invoices.subtotal": "Zwischensumme", + "billing.limitMessage.analytics": "Detaillierte Analysen freischalten", + "billing.limitMessage.brand": "Branding entfernen", + "billing.limitMessage.customDomain": "Eigene Domains hinzufügen", + "billing.limitMessage.fileInput": "Datei-Eingabefelder verwenden", + "billing.limitMessage.folder": "Ordner erstellen", + "billing.preCheckoutModal.companyInput.label": "Firmenname:", + "billing.preCheckoutModal.emailInput.label": "E-Mail:", + "billing.preCheckoutModal.submitButton.label": "Zur Kasse gehen", + "billing.preCheckoutModal.taxId.label": "Steuernummer:", + "billing.preCheckoutModal.taxId.placeholder": "ID-Typ", + "billing.pricingCard.chatsPerMonth": "Chats/Monat", + "billing.pricingCard.chatsTooltip": "Ein Chat wird gezählt, wenn ein Benutzer eine Diskussion startet. Es ist unabhängig von der Anzahl der gesendeten und empfangenen Nachrichten.", + "billing.pricingCard.heading": "Upgrade auf plan", + "billing.pricingCard.perMonth": "/ Monat", + "billing.pricingCard.plus": ", plus:", + "billing.pricingCard.pro.analytics": "Detaillierte Analysen", + "billing.pricingCard.pro.customDomains": "Eigene Domains", + "billing.pricingCard.pro.description": "Für Agenturen & wachsende Start-ups.", + "billing.pricingCard.pro.everythingFromStarter": "Alles in Starter", + "billing.pricingCard.pro.includedSeats": "5 Plätze inklusive", + "billing.pricingCard.pro.mostPopularLabel": "Am beliebtesten", + "billing.pricingCard.pro.whatsAppIntegration": "WhatsApp-Integration", + "billing.pricingCard.starter.brandingRemoved": "Branding entfernt", + "billing.pricingCard.starter.createFolders": "Ordner erstellen", + "billing.pricingCard.starter.description": "Für Einzelpersonen & kleine Unternehmen.", + "billing.pricingCard.starter.fileUploadBlock": "Datei-Upload Eingabefeld", + "billing.pricingCard.starter.includedSeats": "2 Plätze inklusive", + "billing.pricingCard.upgradeButton.current": "Dein aktueller Tarif", + "billing.updateSuccessToast.description": "Workspace {plan} Plan erfolgreich aktualisiert \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Mehr Informationen", + "billing.upgradeLimitLabel": "Um {type} hinzuzufügen, musst du deinen Tarif aktualisieren", + "billing.usage.chats.alert.soonReach": "Deine Typebots sind beliebt! Du wirst bald das Chat-Limit deines Tarifs erreichen. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Vergewissere dich, dass du deinen Tarif aktualisierst, um dieses Limit zu erhöhen und weiterhin mit deinen Benutzern zu chatten.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Nutzung", + "billing.usage.unlimited": "Unbegrenzt", + "blocks.bubbles.embed.blockCard.tooltip": "Ein PDF, ein iframe, eine Website einbetten...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Dateien hochladen", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Tabellen", + "cancel": "Abbrechen", + "clickToEdit": "Zum Bearbeiten klicken...", + "confirmModal.defaultTitle": "Bist du sicher?", + "dashboard.header.settingsButton.label": "Einstellungen & Mitglieder", + "dashboard.redirectionMessage": "Du wirst weitergeleitet...", + "dashboard.title": "Meine Typebots", + "delete": "Löschen", + "downgrade": "Downgrade", + "editor.blockCard.logicBlock.tooltip.code.label": "JavaScript-Code ausführen", + "editor.blockCard.logicBlock.tooltip.jump.label": "Ablauf zu einer anderen Gruppe beschleunigen", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Verlinkung zu einem anderen Typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Autoplay aktivieren", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Datei auswählen", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Link einbetten", + "editor.blocks.bubbles.audio.settings.upload.label": "Hochladen", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Füge den Audio-Dateilink ein...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Funktioniert mit .MP3- und .WAV-Dateien", + "editor.blocks.bubbles.embed.node.show.text": "Einbetten anzeigen", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Füge den Link oder Code ein...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Funktioniert mit PDFs, iframes, Websites...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Beim Klicken Link", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link Alternativtext (Beschreibung)", + "editor.blocks.bubbles.textEditor.plate.label": "Texteditor", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Nach einer Variable suchen", + "editor.blocks.start.text": "Start", + "editor.editableTypebotName.tooltip.rename.label": "Umbenennen", + "editor.gettingStartedModal.editorBasics.heading": "Grundlagen des Editors", + "editor.gettingStartedModal.editorBasics.list.four.label": "Klicke auf die Vorschau-Schaltfläche oben rechts, um deinen Bot anzusehen.", + "editor.gettingStartedModal.editorBasics.list.label": "Wenn du Fragen hast, verwende gerne die Sprechblase unten rechts, um sie mir zu stellen. Ich beantworte normalerweise innerhalb der nächsten 24 Stunden. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "Die Seitenleiste enthält Blöcke, die du auf das Board ziehen und ablegen kannst.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Verbinde die Gruppen miteinander.", + "editor.gettingStartedModal.editorBasics.list.two.label": "Du kannst Blöcke gruppieren, indem du sie unter oder über einander ablegst.", + "editor.gettingStartedModal.seeAction.item.label": "Weitere Videos", + "editor.gettingStartedModal.seeAction.label": "In Aktion sehen", + "editor.gettingStartedModal.seeAction.time": "5 Minuten", + "editor.headers.flowButton.label": "Ablauf", + "editor.headers.helpButton.label": "Hilfe", + "editor.headers.previewButton.label": "Vorschau", + "editor.headers.resultsButton.label": "Ergebnisse", + "editor.headers.savingSpinner.label": "Speichern...", + "editor.headers.settingsButton.label": "Einstellungen", + "editor.headers.shareButton.label": "Teilen", + "editor.headers.themeButton.label": "Design", + "editor.sidebarBlock.abTest.label": "AB-Test", + "editor.sidebarBlock.analytics.label": "Analytics", + "editor.sidebarBlock.audio.label": "Audio", + "editor.sidebarBlock.button.label": "Buttons", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Bedingung", + "editor.sidebarBlock.date.label": "Datum", + "editor.sidebarBlock.email.label": "E-Mail", + "editor.sidebarBlock.embed.label": "Einbetten", + "editor.sidebarBlock.file.label": "Datei", + "editor.sidebarBlock.image.label": "Bild", + "editor.sidebarBlock.jump.label": "Springen", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Nummer", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Zahlung", + "editor.sidebarBlock.phone.label": "Telefon", + "editor.sidebarBlock.picChoice.label": "Bildauswahl", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Bewertung", + "editor.sidebarBlock.redirect.label": "Weiterleitung", + "editor.sidebarBlock.script.label": "Skript", + "editor.sidebarBlock.setVariable.label": "Variable setzen", + "editor.sidebarBlock.sheets.label": "Tabellen", + "editor.sidebarBlock.start.label": "Start", + "editor.sidebarBlock.text.label": "Text", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Video", + "editor.sidebarBlock.wait.label": "Warten", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Website", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Blasen", + "editor.sidebarBlocks.blockType.inputs.heading": "Eingaben", + "editor.sidebarBlocks.blockType.integrations.heading": "Integrationen", + "editor.sidebarBlocks.blockType.logic.heading": "Logik", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Sperren", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Entsperren", + "editor.sidebarBlocks.sidebar.lock.label": "Seitenleiste sperren", + "editor.sidebarBlocks.sidebar.unlock.label": "Seitenleiste entsperren", + "errorMessage": "Ein Fehler ist aufgetreten", + "folders.createFolderButton.label": "Ordner erstellen", + "folders.createTypebotButton.label": "Typebot erstellen", + "folders.folderButton.deleteConfirmationMessage": "Möchtest du den Ordner folderName wirklich löschen? (Alles im Inneren wird in dein Dashboard verschoben)", + "folders.typebotButton.delete": "Löschen", + "folders.typebotButton.deleteConfirmationMessage": "Möchtest du deinen Typebot typebotName wirklich löschen?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Alle zugehörigen Daten werden gelöscht und können nicht wiederhergestellt werden.", + "folders.typebotButton.duplicate": "Duplizieren", + "folders.typebotButton.live": "Live", + "folders.typebotButton.showMoreOptions": "Mehr Optionen anzeigen", + "folders.typebotButton.unpublish": "Veröffentlichung aufheben", + "pending": "Ausstehend", + "remove": "Entfernen", + "skip": "Überspringen", + "templates.buttons.fromScratchButton.label": "Von Grund auf starten", + "templates.buttons.fromTemplateButton.label": "Von einer Vorlage starten", + "templates.buttons.heading": "Erstelle einen neuen Typebot", + "templates.buttons.importFileButton.label": "Datei importieren", + "templates.importFromFileButon.toastError.description": "Konnte die Datei nicht verarbeiten. Bist du sicher, dass es sich um einen Typebot handelt?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Neu", + "templates.modal.menuHeading.other": "Andere", + "templates.modal.menuHeading.product": "Produkt", + "templates.modal.useTemplateButton.label": "Diese Vorlage verwenden", + "upgrade": "Upgrade", + "video.urlInput.helperText": "Funktioniert mit YouTube, Vimeo, Gumlet, TikTok und anderen", + "video.urlInput.placeholder": "Füge den Videolink ein...", + "workspace.dropdown.logoutButton.label": "Abmelden", + "workspace.dropdown.newButton.label": "Neuer Workspace", + "workspace.membersList.inviteButton.label": "Einladen", + "workspace.membersList.inviteInput.placeholder": "name@unternehmen.de", + "workspace.membersList.title": "Mitglieder", + "workspace.membersList.unlockBanner.label": "Aktualisiere deinen Plan, um mit mehr Teammitgliedern zu arbeiten und neue Limits freizuschalten \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Sind Sie sicher, dass Sie den Workspace {workspaceName} löschen möchten? Alle seine Ordner, Typebots und Ergebnisse werden dauerhaft gelöscht.", + "workspace.settings.deleteButton.label": "Workspace löschen", + "workspace.settings.icon.title": "Symbol", + "workspace.settings.modal.menu.billingAndUsage.label": "Abrechnung & Nutzung", + "workspace.settings.modal.menu.members.label": "Mitglieder", + "workspace.settings.modal.menu.myAccount.label": "Mein Konto", + "workspace.settings.modal.menu.preferences.label": "Einstellungen", + "workspace.settings.modal.menu.settings.label": "Einstellungen", + "workspace.settings.modal.menu.version.label": "Version: {version}", + "workspace.settings.modal.menu.workspace.label": "Workspace", + "workspace.settings.name.label": "Name:" +} diff --git a/apps/builder/public/locales/en.json b/apps/builder/public/locales/en.json new file mode 100644 index 0000000..102b44a --- /dev/null +++ b/apps/builder/public/locales/en.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Create", + "account.apiTokens.createModal.copyInstruction": "Please copy your token and store it in a safe place.", + "account.apiTokens.createModal.createButton.label": "Create token", + "account.apiTokens.createModal.createHeading": "Create Token", + "account.apiTokens.createModal.createdHeading": "Token Created", + "account.apiTokens.createModal.doneButton.label": "Done", + "account.apiTokens.createModal.nameInput.label": "Enter a unique name for your token to differentiate it from other tokens.", + "account.apiTokens.createModal.nameInput.placeholder": "I.e. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "For security reasons we cannot show it again.", + "account.apiTokens.deleteButton.label": "Delete", + "account.apiTokens.deleteConfirmationMessage": "The token tokenName will be permanently revoked, are you sure you want to continue?", + "account.apiTokens.description": "These tokens allow other apps to control your whole account and typebots. Be careful!", + "account.apiTokens.heading": "API tokens", + "account.apiTokens.table.createdHeader": "Created", + "account.apiTokens.table.nameHeader": "Name", + "account.myAccount.changePhotoButton.label": "Change photo", + "account.myAccount.changePhotoButton.specification": ".jpg or.png, max 1MB", + "account.myAccount.emailInput.disabledTooltip": "Updating email is not available. Contact the support if you want to change it.", + "account.myAccount.emailInput.label": "Email address:", + "account.myAccount.nameInput.label": "Name:", + "account.preferences.appearance.darkLabel": "Dark", + "account.preferences.appearance.heading": "Appearance", + "account.preferences.appearance.lightLabel": "Light", + "account.preferences.appearance.systemLabel": "System", + "account.preferences.graphNavigation.heading": "Editor Navigation", + "account.preferences.graphNavigation.mouse.description": "Move by dragging the board and zoom in/out using the scroll wheel", + "account.preferences.graphNavigation.mouse.label": "Mouse", + "account.preferences.graphNavigation.trackpad.description": "Move the board using 2 fingers and zoom in/out by pinching", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Language", + "account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. \uD83E\uDD13", + "analytics.completionRateLabel": "Completion rate", + "analytics.notAvailableLabel": "Not available", + "analytics.startsLabel": "Starts", + "analytics.viewsLabel": "Views", + "auth.emailSubmitButton.label": "Submit", + "auth.error.default": "Try signing with a different account.", + "auth.error.email": "Email not found. Try signing with a different provider.", + "auth.error.oauthNotLinked": "To confirm your identity, sign in with the same account you used originally.", + "auth.error.unknown": "An error occurred. Please try again.", + "auth.magicLink.description": "Make sure to check your spam folder.", + "auth.magicLink.title": "A magic link email was sent. \uD83E\uDE84", + "auth.noProvider.link": "configure at least one auth provider (Email, Google, GitHub, Facebook or Azure AD).", + "auth.noProvider.preLink": "You need to", + "auth.orEmailLabel": "Or with your email", + "auth.register.aggreeToTerms": "By signing up, you agree to our terms of service and privacy policy.", + "auth.register.alreadyHaveAccountLabel.link": "Sign in", + "auth.register.alreadyHaveAccountLabel.preLink": "Already have an account?", + "auth.register.heading": "Create an account", + "auth.signin.heading": "Sign In", + "auth.signin.noAccountLabel.link": "Sign up for free", + "auth.signin.noAccountLabel.preLink": "Don't have an account?", + "auth.signinErrorToast.description": "Sign ups are disabled.", + "auth.signinErrorToast.title": "Unauthorized", + "auth.signinErrorToast.tooManyRequests": "Too many requests. Try again later.", + "auth.socialLogin.azureButton.label": "Continue with {azureProviderName}", + "auth.socialLogin.customButton.label": "Continue with {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continue with Facebook", + "auth.socialLogin.githubButton.label": "Continue with GitHub", + "auth.socialLogin.gitlabButton.label": "Continue with {gitlabProviderName}", + "auth.socialLogin.googleButton.label": "Continue with Google", + "back": "Back", + "billing.billingPortalButton.label": "Billing portal", + "billing.contribution.link": "Learn more.", + "billing.contribution.preLink": "Typebot is contributing 1% of your subscription to remove CO₂ from the atmosphere.", + "billing.currentSubscription.cancelDate": "Will be cancelled on", + "billing.currentSubscription.heading": "Subscription", + "billing.currentSubscription.pastDueAlert": "The latest payment failed. Head over to the billing portal to proceed and avoid having your subscription canceled.", + "billing.currentSubscription.subheading": "Current workspace subscription:", + "billing.customLimit.link": "Let's chat!", + "billing.customLimit.preLink": "Need custom limits? Specific features?", + "billing.invoices.empty": "No invoices found for this workspace.", + "billing.invoices.heading": "Invoices", + "billing.invoices.paidAt": "Paid at", + "billing.invoices.subtotal": "Subtotal", + "billing.limitMessage.analytics": "unlock in-depth analytics", + "billing.limitMessage.brand": "remove branding", + "billing.limitMessage.customDomain": "add custom domains", + "billing.limitMessage.fileInput": "use file input blocks", + "billing.limitMessage.folder": "create folders", + "billing.preCheckoutModal.companyInput.label": "Company name:", + "billing.preCheckoutModal.emailInput.label": "Email:", + "billing.preCheckoutModal.submitButton.label": "Go to checkout", + "billing.preCheckoutModal.taxId.label": "Tax ID:", + "billing.preCheckoutModal.taxId.placeholder": "ID type", + "billing.pricingCard.chatsPerMonth": "chats/mo", + "billing.pricingCard.chatsTooltip": "A chat is counted whenever a user starts a discussion. It is independant of the number of messages he sends and receives.", + "billing.pricingCard.heading": "Upgrade to plan", + "billing.pricingCard.perMonth": "/ month", + "billing.pricingCard.plus": ", plus:", + "billing.pricingCard.pro.analytics": "In-depth analytics", + "billing.pricingCard.pro.customDomains": "Custom domains", + "billing.pricingCard.pro.description": "For agencies & growing startups.", + "billing.pricingCard.pro.everythingFromStarter": "Everything in Starter", + "billing.pricingCard.pro.includedSeats": "5 seats included", + "billing.pricingCard.pro.mostPopularLabel": "Most popular", + "billing.pricingCard.pro.whatsAppIntegration": "WhatsApp integration", + "billing.pricingCard.starter.brandingRemoved": "Branding removed", + "billing.pricingCard.starter.createFolders": "Create folders", + "billing.pricingCard.starter.description": "For individuals & small businesses.", + "billing.pricingCard.starter.fileUploadBlock": "File upload input block", + "billing.pricingCard.starter.includedSeats": "2 seats included", + "billing.pricingCard.upgradeButton.current": "Your current plan", + "billing.tiersModal.heading": "Chats pricing table", + "billing.updateSuccessToast.description": "Workspace {plan} plan successfully updated \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "More info", + "billing.upgradeLimitLabel": "You need to upgrade your plan in order to {type}", + "billing.usage.chats.alert.soonReach": "Your typebots are popular! You will soon reach your plan's chats limit. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Make sure to update your plan to increase this limit and continue chatting with your users.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Usage", + "billing.usage.unlimited": "Unlimited", + "blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets", + "cancel": "Cancel", + "clickToEdit": "Click to edit...", + "confirmModal.defaultTitle": "Are you sure?", + "dashboard.header.settingsButton.label": "Settings & Members", + "dashboard.redirectionMessage": "You are being redirected...", + "dashboard.title": "My typebots", + "delete": "Delete", + "downgrade": "Downgrade", + "editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code", + "editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Enable autoplay", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Choose a file", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Embed link", + "editor.blocks.bubbles.audio.settings.upload.label": "Upload", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Paste the audio file link...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Works with .MP3s and .WAVs", + "editor.blocks.bubbles.embed.node.show.text": "Show embed", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Paste the link or code...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Works with PDFs, iframes, websites...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "On click link", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (description)", + "editor.blocks.bubbles.textEditor.plate.label": "Text editor", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Search for a variable", + "editor.blocks.start.text": "Start", + "editor.editableTypebotName.tooltip.rename.label": "Rename", + "editor.gettingStartedModal.editorBasics.heading": "Editor Basics", + "editor.gettingStartedModal.editorBasics.list.four.label": "Preview your bot by clicking the test button on the top right", + "editor.gettingStartedModal.editorBasics.list.label": "Feel free to use the bottom-right bubble to reach out if you have any question. I usually answer within the next 24 hours. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "The left side bar contains blocks that you can drag and drop to the board.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Connect the groups together", + "editor.gettingStartedModal.editorBasics.list.two.label": "You can group blocks together by dropping them below or above each other", + "editor.gettingStartedModal.seeAction.item.label": "Other videos", + "editor.gettingStartedModal.seeAction.label": "See it in action", + "editor.gettingStartedModal.seeAction.time": "5 minutes", + "editor.headers.flowButton.label": "Flow", + "editor.headers.helpButton.label": "Help", + "editor.headers.previewButton.label": "Test", + "editor.headers.resultsButton.label": "Results", + "editor.headers.savingSpinner.label": "Saving...", + "editor.headers.settingsButton.label": "Settings", + "editor.headers.shareButton.label": "Share", + "editor.headers.themeButton.label": "Theme", + "editor.sidebarBlock.abTest.label": "AB Test", + "editor.sidebarBlock.analytics.label": "Analytics", + "editor.sidebarBlock.audio.label": "Audio", + "editor.sidebarBlock.button.label": "Buttons", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condition", + "editor.sidebarBlock.date.label": "Date", + "editor.sidebarBlock.email.label": "Email", + "editor.sidebarBlock.embed.label": "Embed", + "editor.sidebarBlock.file.label": "File", + "editor.sidebarBlock.image.label": "Image", + "editor.sidebarBlock.jump.label": "Jump", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Number", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Payment", + "editor.sidebarBlock.phone.label": "Phone", + "editor.sidebarBlock.picChoice.label": "Pic choice", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Rating", + "editor.sidebarBlock.redirect.label": "Redirect", + "editor.sidebarBlock.script.label": "Script", + "editor.sidebarBlock.setVariable.label": "Set variable", + "editor.sidebarBlock.sheets.label": "Sheets", + "editor.sidebarBlock.start.label": "Start", + "editor.sidebarBlock.text.label": "Text", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Video", + "editor.sidebarBlock.wait.label": "Wait", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Website", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles", + "editor.sidebarBlocks.blockType.inputs.heading": "Inputs", + "editor.sidebarBlocks.blockType.integrations.heading": "Integrations", + "editor.sidebarBlocks.blockType.logic.heading": "Logic", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Lock", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Unlock", + "editor.sidebarBlocks.sidebar.lock.label": "Lock sidebar", + "editor.sidebarBlocks.sidebar.unlock.label": "Unlock sidebar", + "errorMessage": "An error occured", + "folders.createFolderButton.label": "Create a folder", + "folders.createTypebotButton.label": "Create a typebot", + "folders.folderButton.deleteConfirmationMessage": "Are you sure you want to delete folderName folder? (Everything inside will be move to your dashboard)", + "folders.typebotButton.delete": "Delete", + "folders.typebotButton.deleteConfirmationMessage": "Are you sure you want to delete your typebot typebotName?", + "folders.typebotButton.deleteConfirmationMessageWarning": "All its associated data will be deleted and won't be recoverable.", + "folders.typebotButton.duplicate": "Duplicate", + "folders.typebotButton.live": "Live", + "folders.typebotButton.showMoreOptions": "Show more options", + "folders.typebotButton.unpublish": "Unpublish", + "pending": "Pending", + "remove": "Remove", + "skip": "Skip", + "templates.buttons.fromScratchButton.label": "Start from scratch", + "templates.buttons.fromTemplateButton.label": "Start from a template", + "templates.buttons.heading": "Create a new typebot", + "templates.buttons.importFileButton.label": "Import a file", + "templates.importFromFileButon.toastError.description": "Failed to parse the file. Are you sure it's a typebot?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "New", + "templates.modal.menuHeading.other": "Other", + "templates.modal.menuHeading.product": "Product", + "templates.modal.useTemplateButton.label": "Use this template", + "upgrade": "Upgrade", + "video.aspectRatioInput.label": "Aspect ratio", + "video.aspectRatioInput.moreInfoTooltip": "Example: \"16/9\" or \"9/16\"", + "video.maxWidthInput.label": "Max width", + "video.maxWidthInput.moreInfoTooltip": "Example: \"300px\" or \"100%\"", + "video.urlInput.helperText": "Works with Youtube, Vimeo, Gumlet, TikTok and others", + "video.urlInput.placeholder": "Paste the video link...", + "workspace.dropdown.logoutButton.label": "Log out", + "workspace.dropdown.newButton.label": "New workspace", + "workspace.membersList.inviteButton.label": "Invite", + "workspace.membersList.inviteInput.placeholder": "colleague@company.com", + "workspace.membersList.title": "Members", + "workspace.membersList.unlockBanner.label": "Upgrade your plan to work with more team members, and unlock awesome power features \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Are you sure you want to delete {workspaceName} workspace? All its folders, typebots and results will be deleted forever.", + "workspace.settings.deleteButton.label": "Delete workspace", + "workspace.settings.icon.title": "Icon", + "workspace.settings.modal.menu.billingAndUsage.label": "Billing & Usage", + "workspace.settings.modal.menu.members.label": "Members", + "workspace.settings.modal.menu.myAccount.label": "My account", + "workspace.settings.modal.menu.preferences.label": "Preferences", + "workspace.settings.modal.menu.settings.label": "Settings", + "workspace.settings.modal.menu.version.label": "Version: {version}", + "workspace.settings.modal.menu.workspace.label": "Workspace", + "workspace.settings.name.label": "Name:" +} diff --git a/apps/builder/public/locales/es.json b/apps/builder/public/locales/es.json new file mode 100644 index 0000000..d561963 --- /dev/null +++ b/apps/builder/public/locales/es.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Crear", + "account.apiTokens.createModal.copyInstruction": "Por favor, copia tu token y guárdalo en un lugar seguro.", + "account.apiTokens.createModal.createButton.label": "Crear token", + "account.apiTokens.createModal.createHeading": "Crear token", + "account.apiTokens.createModal.createdHeading": "Token Creado", + "account.apiTokens.createModal.doneButton.label": "Hecho", + "account.apiTokens.createModal.nameInput.label": "Ingresa un nombre único para tu token, para diferenciarlo de otros tokens.", + "account.apiTokens.createModal.nameInput.placeholder": "Ej. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Por motivos de seguridad, no podemos mostrarlo nuevamente.", + "account.apiTokens.deleteButton.label": "Eliminar", + "account.apiTokens.deleteConfirmationMessage": "El token tokenName será anulado de forma permanente. ¿Deseas continuar?", + "account.apiTokens.description": "Estos tokens permiten que otras aplicaciones controlen toda tu cuenta y tus typebots. ¡Ten cuidado!", + "account.apiTokens.heading": "Tokens de API", + "account.apiTokens.table.createdHeader": "Creado", + "account.apiTokens.table.nameHeader": "Nombre", + "account.myAccount.changePhotoButton.label": "Cambiar foto", + "account.myAccount.changePhotoButton.specification": ".jpg o .png, máximo 1MB", + "account.myAccount.emailInput.disabledTooltip": "El cambio de email no está disponible. Contacta al soporte si quieres cambiarlo.", + "account.myAccount.emailInput.label": "Correo electrónico:", + "account.myAccount.nameInput.label": "Nombre:", + "account.preferences.appearance.darkLabel": "Oscuro", + "account.preferences.appearance.heading": "Apariencia", + "account.preferences.appearance.lightLabel": "Claro", + "account.preferences.appearance.systemLabel": "Sistema", + "account.preferences.graphNavigation.heading": "Navegación del Editor", + "account.preferences.graphNavigation.mouse.description": "Muévete arrastrando el tablero y acerca/aleja el zoom usando la rueda de desplazamiento.", + "account.preferences.graphNavigation.mouse.label": "Mouse", + "account.preferences.graphNavigation.trackpad.description": "Mueve el tablero con 2 dedos y acerca o aleja el zoom pellizcando", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Idioma", + "account.preferences.language.tooltip": "Las traducciones aún no están completas. Es un trabajo en progreso. \uD83E\uDD13", + "analytics.completionRateLabel": "Tasa de finalización", + "analytics.notAvailableLabel": "No disponible", + "analytics.startsLabel": "Iniciaron", + "analytics.viewsLabel": "Vistas", + "auth.emailSubmitButton.label": "Enviar", + "auth.error.default": "Intenta iniciar sesión con una cuenta diferente.", + "auth.error.email": "No se encontró el correo electrónico. Intenta iniciar sesión con un proveedor diferente.", + "auth.error.oauthNotLinked": "Para confirmar tu identidad, inicia sesión con la misma cuenta que utilizaste originalmente.", + "auth.error.unknown": "Se produjo un error. Inténtalo de nuevo.", + "auth.magicLink.description": "Asegúrate de revisar tu carpeta spam.", + "auth.magicLink.title": "Se envió un correo electrónico con enlace mágico. \uD83E\uDE84", + "auth.noProvider.link": "Configurar al menos un proveedor de autenticación (correo electrónico, Google, GitHub, Facebook o Azure AD).", + "auth.noProvider.preLink": "Necesitas", + "auth.orEmailLabel": "O con tu correo electrónico", + "auth.register.aggreeToTerms": "Al registrarte, aceptas nuestros términos de servicio y política de privacidad.", + "auth.register.alreadyHaveAccountLabel.link": "Iniciar sesión", + "auth.register.alreadyHaveAccountLabel.preLink": "¿Ya tienes una cuenta?", + "auth.register.heading": "Crear una cuenta", + "auth.signin.heading": "Iniciar sesión", + "auth.signin.noAccountLabel.link": "Regístrate gratis", + "auth.signin.noAccountLabel.preLink": "¿No tienes una cuenta?", + "auth.signinErrorToast.description": "Los registros están deshabilitados.", + "auth.signinErrorToast.title": "No autorizado", + "auth.signinErrorToast.tooManyRequests": "Demasiadas solicitudes. Inténtalo de nuevo más tarde.", + "auth.socialLogin.azureButton.label": "Continuar con {azureProviderName}", + "auth.socialLogin.customButton.label": "Continuar con {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continuar con Facebook", + "auth.socialLogin.githubButton.label": "Continuar con GitHub", + "auth.socialLogin.gitlabButton.label": "Continuar con {gitlabProviderName}", + "auth.socialLogin.googleButton.label": "Continuar con Google", + "back": "Volver", + "billing.billingPortalButton.label": "Portal de facturación", + "billing.contribution.link": "Más información.", + "billing.contribution.preLink": "Typebot está contribuyendo con un 1% de tu suscripción para eliminar CO₂ de la atmósfera.", + "billing.currentSubscription.cancelDate": "Será cancelado en", + "billing.currentSubscription.heading": "Suscripción", + "billing.currentSubscription.pastDueAlert": "El último pago falló. Ve al portal de facturación para continuar y evitar que tu suscripción sea cancelada.", + "billing.currentSubscription.subheading": "Suscripción actual del espacio de trabajo:", + "billing.customLimit.link": "¡Hablemos!", + "billing.customLimit.preLink": "¿Necesitas límites personalizados? ¿Funciones específicas?", + "billing.invoices.empty": "No se encontraron facturas para este espacio de trabajo.", + "billing.invoices.heading": "Facturas", + "billing.invoices.paidAt": "Pagado el", + "billing.invoices.subtotal": "Subtotal", + "billing.limitMessage.analytics": "desbloquea análisis detallados", + "billing.limitMessage.brand": "elimina la marca", + "billing.limitMessage.customDomain": "añade dominios personalizados", + "billing.limitMessage.fileInput": "usa bloques de carga de archivos", + "billing.limitMessage.folder": "crea carpetas", + "billing.preCheckoutModal.companyInput.label": "Nombre de la empresa:", + "billing.preCheckoutModal.emailInput.label": "Correo electrónico:", + "billing.preCheckoutModal.submitButton.label": "Ir a la página de pagos", + "billing.preCheckoutModal.taxId.label": "Identificación fiscal:", + "billing.preCheckoutModal.taxId.placeholder": "Tipo de ID", + "billing.pricingCard.chatsPerMonth": "chats/mes", + "billing.pricingCard.chatsTooltip": "Se cuenta un chat cada vez que un usuario inicia una conversación. Es independiente del número de mensajes que envía y recibe.", + "billing.pricingCard.heading": "Actualiza a plan", + "billing.pricingCard.perMonth": "/ mes", + "billing.pricingCard.plus": ", más:", + "billing.pricingCard.pro.analytics": "Análisis detallados", + "billing.pricingCard.pro.customDomains": "Dominios personalizados", + "billing.pricingCard.pro.description": "Para agencias y startups en crecimiento.", + "billing.pricingCard.pro.everythingFromStarter": "Todo en Starter", + "billing.pricingCard.pro.includedSeats": "5 asientos incluidos", + "billing.pricingCard.pro.mostPopularLabel": "Más popular", + "billing.pricingCard.pro.whatsAppIntegration": "Integración de WhatsApp", + "billing.pricingCard.starter.brandingRemoved": "Marca eliminada", + "billing.pricingCard.starter.createFolders": "Crear carpetas", + "billing.pricingCard.starter.description": "Para individuos y pequeñas empresas.", + "billing.pricingCard.starter.fileUploadBlock": "Bloque de carga de archivos", + "billing.pricingCard.starter.includedSeats": "2 asientos incluidos", + "billing.pricingCard.upgradeButton.current": "Tu plan actual", + "billing.tiersModal.heading": "Tabla de precios de Chats", + "billing.updateSuccessToast.description": "Espacio de trabajo {plan} actualizado correctamente \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Más información", + "billing.upgradeLimitLabel": "Necesitas actualizar tu plan para {type}", + "billing.usage.chats.alert.soonReach": "¡Tus typebots son populares! Pronto alcanzarás el límite de chats de tu plan. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Asegúrate de actualizar tu plan para aumentar este límite y seguir chateando con tus usuarios.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Uso", + "billing.usage.unlimited": "Ilimitado", + "blocks.bubbles.embed.blockCard.tooltip": "Insertar un PDF, un iframe, un sitio web...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Cargar archivos", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets", + "cancel": "Cancelar", + "clickToEdit": "Haz clic para editar...", + "confirmModal.defaultTitle": "¿Estás seguro?", + "dashboard.header.settingsButton.label": "Configuración y Miembros", + "dashboard.redirectionMessage": "Estás siendo redirigido...", + "dashboard.title": "Mis typebots", + "delete": "Eliminar", + "downgrade": "Degradar", + "editor.blockCard.logicBlock.tooltip.code.label": "Ejecutar código Javascript", + "editor.blockCard.logicBlock.tooltip.jump.label": "Saltar al flujo de otro grupo", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Enlazar y avanzar a otro typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Habilitar reproducción automática", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Elegir un archivo", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Adicionar link", + "editor.blocks.bubbles.audio.settings.upload.label": "Subir", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Pega el enlace del archivo de audio...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Compatible con .MP3 y .WAV", + "editor.blocks.bubbles.embed.node.show.text": "Mostrar inserción", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Pega el enlace o código...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Funciona con PDF, iframes, sitios web...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Enlace al hacer clic", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo del enlace (descripción)", + "editor.blocks.bubbles.textEditor.plate.label": "Editor de texto", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Buscar una variable", + "editor.blocks.start.text": "Inicio", + "editor.editableTypebotName.tooltip.rename.label": "Renombrar", + "editor.gettingStartedModal.editorBasics.heading": "Conceptos básicos del Editor", + "editor.gettingStartedModal.editorBasics.list.four.label": "Previsualiza tu bot haciendo clic en el botón de previsualización en la esquina superior derecha", + "editor.gettingStartedModal.editorBasics.list.label": "Si tienes alguna pregunta, no dudes en usar la burbuja en la esquina inferior derecha. Suelo responder en las próximas 24 horas. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "La barra lateral izquierda contiene bloques que puedes arrastrar y soltar en el tablero.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Conecta los grupos entre sí", + "editor.gettingStartedModal.editorBasics.list.two.label": "Puedes agrupar bloques ubicándolos debajo o encima de cada uno", + "editor.gettingStartedModal.seeAction.item.label": "Otros videos", + "editor.gettingStartedModal.seeAction.label": "Verlo en acción", + "editor.gettingStartedModal.seeAction.time": "5 minutos", + "editor.headers.flowButton.label": "Flujo", + "editor.headers.helpButton.label": "Ayuda", + "editor.headers.previewButton.label": "Previsualización", + "editor.headers.resultsButton.label": "Resultados", + "editor.headers.savingSpinner.label": "Guardando...", + "editor.headers.settingsButton.label": "Configuración", + "editor.headers.shareButton.label": "Compartir", + "editor.headers.themeButton.label": "Tema", + "editor.sidebarBlock.abTest.label": "Prueba A/B", + "editor.sidebarBlock.analytics.label": "Análisis", + "editor.sidebarBlock.audio.label": "Audio", + "editor.sidebarBlock.button.label": "Botones", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condición", + "editor.sidebarBlock.date.label": "Fecha", + "editor.sidebarBlock.email.label": "Email", + "editor.sidebarBlock.embed.label": "Insertar", + "editor.sidebarBlock.file.label": "Archivo", + "editor.sidebarBlock.image.label": "Imagen", + "editor.sidebarBlock.jump.label": "Saltar", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Número", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Pago", + "editor.sidebarBlock.phone.label": "Teléfono", + "editor.sidebarBlock.picChoice.label": "Elegir imagen", + "editor.sidebarBlock.pixel.label": "Píxel", + "editor.sidebarBlock.rating.label": "Calificación", + "editor.sidebarBlock.redirect.label": "Redireccionar", + "editor.sidebarBlock.script.label": "Script", + "editor.sidebarBlock.setVariable.label": "Establecer variable", + "editor.sidebarBlock.sheets.label": "Sheets", + "editor.sidebarBlock.start.label": "Iniciar", + "editor.sidebarBlock.text.label": "Texto", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Video", + "editor.sidebarBlock.wait.label": "Esperar", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Sitio web", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Burbujas", + "editor.sidebarBlocks.blockType.inputs.heading": "Entradas", + "editor.sidebarBlocks.blockType.integrations.heading": "Integraciones", + "editor.sidebarBlocks.blockType.logic.heading": "Lógica", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Bloquear", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Desbloquear", + "editor.sidebarBlocks.sidebar.lock.label": "Bloquear barra lateral", + "editor.sidebarBlocks.sidebar.unlock.label": "Desbloquear barra lateral", + "errorMessage": "Se produjo un error", + "folders.createFolderButton.label": "Crear una carpeta", + "folders.createTypebotButton.label": "Crear un Typebot", + "folders.folderButton.deleteConfirmationMessage": "¿Estás seguro de que quieres eliminar la carpeta folderName? (Todo lo que hay dentro se moverá a tu tablero)", + "folders.typebotButton.delete": "Eliminar", + "folders.typebotButton.deleteConfirmationMessage": "¿Estás seguro de que quieres eliminar tu Typebot typebotName?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Todos sus datos asociados se eliminarán y no se podrán recuperar.", + "folders.typebotButton.duplicate": "Duplicar", + "folders.typebotButton.live": "En vivo", + "folders.typebotButton.showMoreOptions": "Mostrar más opciones", + "folders.typebotButton.unpublish": "Despublicar", + "pending": "Pendiente", + "remove": "Eliminar", + "skip": "Saltar", + "templates.buttons.fromScratchButton.label": "Empezar desde cero", + "templates.buttons.fromTemplateButton.label": "Empezar desde una plantilla", + "templates.buttons.heading": "Crear un nuevo Typebot", + "templates.buttons.importFileButton.label": "Importar un archivo", + "templates.importFromFileButon.toastError.description": "Error al analizar el archivo. ¿Estás seguro de que es un Typebot?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Nuevo", + "templates.modal.menuHeading.other": "Otro", + "templates.modal.menuHeading.product": "Producto", + "templates.modal.useTemplateButton.label": "Usar esta plantilla", + "upgrade": "Actualizar", + "video.aspectRatioInput.label": "Relación de aspecto", + "video.aspectRatioInput.moreInfoTooltip": "Ejemplo: \"16/9\" o \"9/16\"", + "video.maxWidthInput.label": "Ancho máximo", + "video.maxWidthInput.moreInfoTooltip": "Ejemplo: \"300px\" o \"100%\"", + "video.urlInput.helperText": "Funciona con Youtube, Vimeo, Gumlet, TikTok y otros", + "video.urlInput.placeholder": "Pega el enlace del video...", + "workspace.dropdown.logoutButton.label": "Cerrar sesión", + "workspace.dropdown.newButton.label": "Nuevo espacio de trabajo", + "workspace.membersList.inviteButton.label": "Invitar", + "workspace.membersList.inviteInput.placeholder": "colega@empresa.com", + "workspace.membersList.title": "Miembros", + "workspace.membersList.unlockBanner.label": "Actualiza tu plan para trabajar con más miembros del equipo y desbloquear increíbles funciones avanzadas \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "¿Estás seguro de que quieres eliminar el espacio de trabajo {workspaceName}? Se eliminarán para siempre todas sus carpetas, Typebots y resultados.", + "workspace.settings.deleteButton.label": "Eliminar espacio de trabajo", + "workspace.settings.icon.title": "Icono", + "workspace.settings.modal.menu.billingAndUsage.label": "Facturación y uso", + "workspace.settings.modal.menu.members.label": "Miembros", + "workspace.settings.modal.menu.myAccount.label": "Mi cuenta", + "workspace.settings.modal.menu.preferences.label": "Preferencias", + "workspace.settings.modal.menu.settings.label": "Configuración", + "workspace.settings.modal.menu.version.label": "Versión: {version}", + "workspace.settings.modal.menu.workspace.label": "Espacio de trabajo", + "workspace.settings.name.label": "Nombre:" +} diff --git a/apps/builder/public/locales/fr.json b/apps/builder/public/locales/fr.json new file mode 100644 index 0000000..cc8af15 --- /dev/null +++ b/apps/builder/public/locales/fr.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Créer", + "account.apiTokens.createModal.copyInstruction": "Copie ton token et enregistre le dans un endroit sûr.", + "account.apiTokens.createModal.createButton.label": "Créer un token", + "account.apiTokens.createModal.createHeading": "Créer un token", + "account.apiTokens.createModal.createdHeading": "Token créé", + "account.apiTokens.createModal.doneButton.label": "Terminé", + "account.apiTokens.createModal.nameInput.label": "Tape un nom unique pour votre token afin de le différencier des autres tokens.", + "account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Pour des raisons de sécurité, nous ne pourrons pas le montrer à nouveau.", + "account.apiTokens.deleteButton.label": "Supprimer", + "account.apiTokens.deleteConfirmationMessage": "Le token tokenName sera définitivement révoqué, es-tu sûr de vouloir continuer ?", + "account.apiTokens.description": "Ces tokens permettent à d'autres applications de contrôler ton compte et tes typebots. Prudence !", + "account.apiTokens.heading": "Tokens API", + "account.apiTokens.table.createdHeader": "Créé", + "account.apiTokens.table.nameHeader": "Nom", + "account.myAccount.changePhotoButton.label": "Changer de photo", + "account.myAccount.changePhotoButton.specification": ".jpg ou.png, max 1MB", + "account.myAccount.emailInput.disabledTooltip": "La mise à jour de l'adresse e-mail n'est pas disponible. Contacte le service d'assistance si tu souhaites la modifier.", + "account.myAccount.emailInput.label": "Adresse e-mail:", + "account.myAccount.nameInput.label": "Nom:", + "account.preferences.appearance.darkLabel": "Sombre", + "account.preferences.appearance.heading": "Apparence", + "account.preferences.appearance.lightLabel": "Clair", + "account.preferences.appearance.systemLabel": "Système", + "account.preferences.graphNavigation.heading": "Navigation de l'éditeur", + "account.preferences.graphNavigation.mouse.description": "Déplace le board en cliquant avec la souris et zoom utilisant la molette", + "account.preferences.graphNavigation.mouse.label": "Souris", + "account.preferences.graphNavigation.trackpad.description": "Déplace le board en déplaçant les 2 doigts et zoom pincant", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Langue", + "account.preferences.language.tooltip": "Les traductions ne sont pas encore complètes. C'est un travail en cours. \uD83E\uDD13", + "analytics.completionRateLabel": "Taux de complétion", + "analytics.notAvailableLabel": "Non disponible", + "analytics.startsLabel": "Démarrés", + "analytics.viewsLabel": "Vues", + "auth.emailSubmitButton.label": "Se connecter", + "auth.error.default": "Essaye de te connecter avec un compte différent.", + "auth.error.email": "Email non trouvé. Essaye de te connecter avec un fournisseur différent.", + "auth.error.oauthNotLinked": "Pour confirmer ton identité, connecte-toi avec le même compte que tu as utilisé à lorigine.", + "auth.error.unknown": "Une erreur est survenue. Essaye à nouveau.", + "auth.magicLink.description": "N'oublie pas de vérifier ton dossier spam.", + "auth.magicLink.title": "Un email avec un lien d'authentification a été envoyé. \uD83E\uDE84", + "auth.noProvider.link": "configurer au moins un fournisseur d'authentification (E-mail, Google, GitHub, Facebook ou Azure AD).", + "auth.noProvider.preLink": "Tu as besoin de", + "auth.orEmailLabel": "Ou avec votre email", + "auth.register.aggreeToTerms": "En vous inscrivant, vous acceptez nos conditions de service et politique de protection de la vie privée.", + "auth.register.alreadyHaveAccountLabel.link": "Se connecter", + "auth.register.alreadyHaveAccountLabel.preLink": "Tu as déjà un compte?", + "auth.register.heading": "Créer un compte", + "auth.signin.heading": "Se connecter", + "auth.signin.noAccountLabel.link": "Inscris-toi gratuitement", + "auth.signin.noAccountLabel.preLink": "Tu n'as pas de compte?", + "auth.signinErrorToast.description": "Les inscriptions sont désactivées.", + "auth.signinErrorToast.title": "Non autorisé", + "auth.signinErrorToast.tooManyRequests": "Trop de tentatives de connexion.", + "auth.socialLogin.azureButton.label": "Continuer avec {azureProviderName}", + "auth.socialLogin.customButton.label": "Continuer avec {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continuer avec Facebook", + "auth.socialLogin.githubButton.label": "Continuer avec GitHub", + "auth.socialLogin.gitlabButton.label": "Continuer avec {gitlabProviderName}", + "auth.socialLogin.googleButton.label": "Continuer avec Google", + "back": "Retour", + "billing.billingPortalButton.label": "Portail de facturation", + "billing.contribution.link": "En savoir plus.", + "billing.contribution.preLink": "Typebot contribue à hauteur de 1% de votre abonnement pour éliminer le CO₂ de l'atmosphère.", + "billing.currentSubscription.cancelDate": "Sera annulé le", + "billing.currentSubscription.heading": "Abonnement", + "billing.currentSubscription.pastDueAlert": "Le dernier paiement a échoué. Rendez-vous sur le portail de facturation pour effectuer la procédure et éviter l'annulation de votre abonnement.", + "billing.currentSubscription.subheading": "Abonnement actuel du workspace :", + "billing.customLimit.link": "Discutons-en!", + "billing.customLimit.preLink": "Tu as besoin de limites personnalisées ? De fonctionnalités spécifiques ?", + "billing.invoices.empty": "Aucune facture trouvée pour ce workspace.", + "billing.invoices.heading": "Factures", + "billing.invoices.paidAt": "Payé le", + "billing.invoices.subtotal": "Sous-total", + "billing.limitMessage.analytics": "débloquer des analyses approfondies", + "billing.limitMessage.brand": "supprimer la marque", + "billing.limitMessage.customDomain": "ajouter des domaines personnalisés", + "billing.limitMessage.fileInput": "utiliser des blocs de saisie de fichiers", + "billing.limitMessage.folder": "créer des dossiers", + "billing.preCheckoutModal.companyInput.label": "Nom de l'entreprise :", + "billing.preCheckoutModal.emailInput.label": "E-mail :", + "billing.preCheckoutModal.submitButton.label": "Continuer", + "billing.preCheckoutModal.taxId.label": "Numéro de TVA :", + "billing.preCheckoutModal.taxId.placeholder": "Type", + "billing.pricingCard.chatsPerMonth": "chats/mois", + "billing.pricingCard.chatsTooltip": "Un chat est comptabilisé chaque fois qu'un utilisateur démarre une discussion. Il est indépendant du nombre de messages qu'il envoie et reçoit.", + "billing.pricingCard.heading": "Passer à plan", + "billing.pricingCard.perMonth": "/ mois", + "billing.pricingCard.plus": ", plus :", + "billing.pricingCard.pro.analytics": "Analyses approfondies", + "billing.pricingCard.pro.customDomains": "Domaines personnalisés", + "billing.pricingCard.pro.description": "Pour les agences et les startups en croissance.", + "billing.pricingCard.pro.everythingFromStarter": "Tout ce qu'il y a dans Starter", + "billing.pricingCard.pro.includedSeats": "5 collègues inclus", + "billing.pricingCard.pro.mostPopularLabel": "Le plus populaire", + "billing.pricingCard.pro.whatsAppIntegration": "Intégration WhatsApp", + "billing.pricingCard.starter.brandingRemoved": "Marque enlevée", + "billing.pricingCard.starter.createFolders": "Créer des dossiers", + "billing.pricingCard.starter.description": "Pour les particuliers et les petites entreprises.", + "billing.pricingCard.starter.fileUploadBlock": "Bloc d'upload de fichier", + "billing.pricingCard.starter.includedSeats": "2 collègues inclus", + "billing.pricingCard.upgradeButton.current": "Abonnement actuel", + "billing.tiersModal.heading": "Table des prix des chats", + "billing.updateSuccessToast.description": "Ton abonnement {plan} a été mis à jour avec succès \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Plus d'informations", + "billing.upgradeLimitLabel": "Tu dois mettre à niveau ton abonnement pour {type}", + "billing.usage.chats.alert.soonReach": "Tes typebots sont populaires ! Tu atteindras bientôt la limite de chats de votre abonnement. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Assure-toi de mettre à jour votre abonnement pour augmenter cette limite et continuer à discuter avec vos utilisateurs.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Utilisation", + "billing.usage.unlimited": "Illimité", + "blocks.bubbles.embed.blockCard.tooltip": "Intégrer un pdf, un iframe, un site web...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Télécharger des fichiers", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets", + "cancel": "Annuler", + "clickToEdit": "Clique pour modifier...", + "confirmModal.defaultTitle": "Es-tu sûr ?", + "dashboard.header.settingsButton.label": "Paramètres & Membres", + "dashboard.redirectionMessage": "Redirection en cours...", + "dashboard.title": "Mes typebots", + "delete": "Supprimer", + "downgrade": "Downgrade", + "editor.blockCard.logicBlock.tooltip.code.label": "Exécuter du code Javascript", + "editor.blockCard.logicBlock.tooltip.jump.label": "Passer rapidement au groupe suivant", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Lier et exécuter un autre typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Activer la lecture automatique", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Choisir un fichier", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Lien intégré", + "editor.blocks.bubbles.audio.settings.upload.label": "Uploader", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Collez le lien du fichier audio...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Fonctionne avec les fichiers .MP3 et .WAV", + "editor.blocks.bubbles.embed.node.show.text": "Afficher l'intégration", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Collez le lien ou le code...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Fonctionne avec les PDF, les iframes, les sites web...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Redirection au clic", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texte alternatif du lien (description)", + "editor.blocks.bubbles.textEditor.plate.label": "Éditeur de texte", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Rechercher une variable", + "editor.blocks.start.text": "Démarrer", + "editor.editableTypebotName.tooltip.rename.label": "Renommer", + "editor.gettingStartedModal.editorBasics.heading": "Principes de base de l'éditeur", + "editor.gettingStartedModal.editorBasics.list.four.label": "Prévisualisez votre bot en cliquant sur le bouton \"Tester\" en haut à droite.", + "editor.gettingStartedModal.editorBasics.list.label": "N'hésitez pas à utiliser la bulle en bas à droite pour me poser des questions. Je réponds généralement dans les 24 heures. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "La barre latérale de gauche contient des blocs que vous pouvez glisser-déposer sur le graph.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Connectez les groupes ensemble.", + "editor.gettingStartedModal.editorBasics.list.two.label": "Vous pouvez regrouper les blocs en les déposant les uns au-dessus ou en-dessous des autres.", + "editor.gettingStartedModal.seeAction.item.label": "Autres vidéos", + "editor.gettingStartedModal.seeAction.label": "Voir en action", + "editor.gettingStartedModal.seeAction.time": "5 minutes", + "editor.headers.flowButton.label": "Flow", + "editor.headers.helpButton.label": "Aide", + "editor.headers.previewButton.label": "Tester", + "editor.headers.resultsButton.label": "Résultats", + "editor.headers.savingSpinner.label": "Enregistrement...", + "editor.headers.settingsButton.label": "Paramètres", + "editor.headers.shareButton.label": "Partage", + "editor.headers.themeButton.label": "Thème", + "editor.sidebarBlock.abTest.label": "AB Test", + "editor.sidebarBlock.analytics.label": "Analytics", + "editor.sidebarBlock.audio.label": "Audio", + "editor.sidebarBlock.button.label": "Boutons", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condition", + "editor.sidebarBlock.date.label": "Date", + "editor.sidebarBlock.email.label": "Email", + "editor.sidebarBlock.embed.label": "Iframe", + "editor.sidebarBlock.file.label": "Fichier", + "editor.sidebarBlock.image.label": "Image", + "editor.sidebarBlock.jump.label": "Sauter", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Nombre", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Paiement", + "editor.sidebarBlock.phone.label": "Téléphone", + "editor.sidebarBlock.picChoice.label": "Choix image", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Évaluation", + "editor.sidebarBlock.redirect.label": "Rediriger", + "editor.sidebarBlock.script.label": "Script", + "editor.sidebarBlock.setVariable.label": "Définir variable", + "editor.sidebarBlock.sheets.label": "Sheets", + "editor.sidebarBlock.start.label": "Démarrer", + "editor.sidebarBlock.text.label": "Texte", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Vidéo", + "editor.sidebarBlock.wait.label": "Attendre", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Site web", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Bulles", + "editor.sidebarBlocks.blockType.inputs.heading": "Inputs", + "editor.sidebarBlocks.blockType.integrations.heading": "Intégrations", + "editor.sidebarBlocks.blockType.logic.heading": "Logique", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Fermée", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Ouverte", + "editor.sidebarBlocks.sidebar.lock.label": "Fermer la barre latérale", + "editor.sidebarBlocks.sidebar.unlock.label": "Ouvrir la barre latérale", + "errorMessage": "Une erreur s'est produite", + "folders.createFolderButton.label": "Créer un dossier", + "folders.createTypebotButton.label": "Créer un typebot", + "folders.folderButton.deleteConfirmationMessage": "Es-tu sûr de vouloir supprimer le dossier folderName ? (Tout ce qui est à l'intérieur sera déplacé dans le dossier parent ou sur votre tableau de bord)", + "folders.typebotButton.delete": "Supprimer", + "folders.typebotButton.deleteConfirmationMessage": "Es-tu sûr de vouloir supprimer votre typebot typebotName ?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Toutes les données associées seront supprimées et ne pourront pas être récupérées.", + "folders.typebotButton.duplicate": "Dupliquer", + "folders.typebotButton.live": "Live", + "folders.typebotButton.showMoreOptions": "Afficher plus d'options", + "folders.typebotButton.unpublish": "Dépublier", + "pending": "En attente", + "remove": "Retirer", + "skip": "Passer", + "templates.buttons.fromScratchButton.label": "Commencer à partir de zéro", + "templates.buttons.fromTemplateButton.label": "Commencer à partir d'un modèle", + "templates.buttons.heading": "Créer un nouveau typebot", + "templates.buttons.importFileButton.label": "Importer un fichier", + "templates.importFromFileButon.toastError.description": "Échec de l'analyse du fichier. Es-tu sûr que c'est un typebot ?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Nouveau", + "templates.modal.menuHeading.other": "Autre", + "templates.modal.menuHeading.product": "Produit", + "templates.modal.useTemplateButton.label": "Utiliser ce modèle", + "upgrade": "Upgrade", + "video.aspectRatioInput.label": "Ratio", + "video.aspectRatioInput.moreInfoTooltip": "Exemple: \"16/9\" ou \"9/16\"", + "video.maxWidthInput.label": "Largeur max", + "video.maxWidthInput.moreInfoTooltip": "Exemple: \"300px\" ou \"100%\"", + "video.urlInput.helperText": "Fonctionne avec Youtube, Vimeo, Gumlet, TikTok et autres", + "video.urlInput.placeholder": "Collez le lien de la vidéo...", + "workspace.dropdown.logoutButton.label": "Déconnexion", + "workspace.dropdown.newButton.label": "Nouveau workspace", + "workspace.membersList.inviteButton.label": "Inviter", + "workspace.membersList.inviteInput.placeholder": "collegue@entreprise.fr", + "workspace.membersList.title": "Membres", + "workspace.membersList.unlockBanner.label": "Upgrade ton plan pour travailler les membres de ton équipe et débloquer d'autres fonctionnalités puissantes \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Es-tu sûr(e) de vouloir supprimer le workspace {workspaceName} ? Tous ses dossiers, typebots et résultats seront supprimés pour toujours.", + "workspace.settings.deleteButton.label": "Supprimer le workspace", + "workspace.settings.icon.title": "Icône", + "workspace.settings.modal.menu.billingAndUsage.label": "Facturation et utilisation", + "workspace.settings.modal.menu.members.label": "Membres", + "workspace.settings.modal.menu.myAccount.label": "Mon compte", + "workspace.settings.modal.menu.preferences.label": "Préférences", + "workspace.settings.modal.menu.settings.label": "Paramètres", + "workspace.settings.modal.menu.version.label": "Version : {version}", + "workspace.settings.modal.menu.workspace.label": "Workspace", + "workspace.settings.name.label": "Nom:" +} diff --git a/apps/builder/public/locales/pt-BR.json b/apps/builder/public/locales/pt-BR.json new file mode 100644 index 0000000..d670ec0 --- /dev/null +++ b/apps/builder/public/locales/pt-BR.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Criar", + "account.apiTokens.createModal.copyInstruction": "Por favor, copie seu token e guarde-o em um lugar seguro.", + "account.apiTokens.createModal.createButton.label": "Criar token", + "account.apiTokens.createModal.createHeading": "Criar Token", + "account.apiTokens.createModal.createdHeading": "Token Criado", + "account.apiTokens.createModal.doneButton.label": "Concluído", + "account.apiTokens.createModal.nameInput.label": "Insira um nome único para o seu token para diferenciá-lo de outros tokens.", + "account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Por motivos de segurança, não podemos mostrá-lo novamente.", + "account.apiTokens.deleteButton.label": "Excluir", + "account.apiTokens.deleteConfirmationMessage": "O token tokenName será revogado permanentemente. Tem certeza de que deseja continuar?", + "account.apiTokens.description": "Esses tokens permitem que outros aplicativos controlem toda a sua conta e typebots. Tenha cuidado!", + "account.apiTokens.heading": "Tokens de API", + "account.apiTokens.table.createdHeader": "Criado", + "account.apiTokens.table.nameHeader": "Nome", + "account.myAccount.changePhotoButton.label": "Alterar foto", + "account.myAccount.changePhotoButton.specification": ".jpg ou.png, máximo 1MB", + "account.myAccount.emailInput.disabledTooltip": "A atualização do e-mail não está disponível. Entre em contato com o suporte se quiser alterá-lo.", + "account.myAccount.emailInput.label": "Endereço de e-mail:", + "account.myAccount.nameInput.label": "Nome:", + "account.preferences.appearance.darkLabel": "Escuro", + "account.preferences.appearance.heading": "Aparência", + "account.preferences.appearance.lightLabel": "Claro", + "account.preferences.appearance.systemLabel": "Sistema", + "account.preferences.graphNavigation.heading": "Navegação do Editor", + "account.preferences.graphNavigation.mouse.description": "Mova arrastando o quadro e amplie/reduza usando a roda de rolagem", + "account.preferences.graphNavigation.mouse.label": "Mouse", + "account.preferences.graphNavigation.trackpad.description": "Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Idioma", + "account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em andamento. \uD83E\uDD13", + "analytics.completionRateLabel": "Taxa de conclusão", + "analytics.notAvailableLabel": "Não disponível", + "analytics.startsLabel": "Inícios", + "analytics.viewsLabel": "Visualizações", + "auth.emailSubmitButton.label": "Enviar", + "auth.error.default": "Tente entrar com uma conta diferente.", + "auth.error.email": "E-mail não encontrado. Tente entrar com um provedor diferente.", + "auth.error.oauthNotLinked": "Já existe uma conta vinculada a esse E-mail, entre com a mesma conta que você usou originalmente.", + "auth.error.unknown": "Ocorreu um erro. Tente novamente.", + "auth.magicLink.description": "Certifique-se de verificar sua pasta de spam.", + "auth.magicLink.title": "Um email com o link mágico foi enviado. \uD83E\uDE84", + "auth.noProvider.link": "configurar pelo menos um provedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).", + "auth.noProvider.preLink": "Você precisa", + "auth.orEmailLabel": "Ou com seu email", + "auth.register.aggreeToTerms": "Ao se cadastrar, você concorda com nossos termos de serviço e política de privacidade.", + "auth.register.alreadyHaveAccountLabel.link": "Entrar", + "auth.register.alreadyHaveAccountLabel.preLink": "Já tem uma conta?", + "auth.register.heading": "Criar uma conta", + "auth.signin.heading": "Entrar", + "auth.signin.noAccountLabel.link": "Registre-se gratuitamente", + "auth.signin.noAccountLabel.preLink": "Não tem uma conta?", + "auth.signinErrorToast.description": "As inscrições estão desativadas.", + "auth.signinErrorToast.title": "Não autorizado", + "auth.signinErrorToast.tooManyRequests": "Muitas tentativas. Tente novamente mais tarde.", + "auth.socialLogin.azureButton.label": "Continuar com {azureProviderName}", + "auth.socialLogin.customButton.label": "Continuar com {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continuar com Facebook", + "auth.socialLogin.githubButton.label": "Continuar com GitHub", + "auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}", + "auth.socialLogin.googleButton.label": "Continuar com Google", + "back": "Voltar", + "billing.billingPortalButton.label": "Portal de cobrança", + "billing.contribution.link": "Saiba mais.", + "billing.contribution.preLink": "A Typebot está contribuindo com 1% da sua assinatura para remover o CO₂ da atmosfera.", + "billing.currentSubscription.cancelDate": "Será cancelado em", + "billing.currentSubscription.heading": "Assinatura", + "billing.currentSubscription.pastDueAlert": "O último pagamento falhou. Acesse o portal de faturamento para prosseguir e evitar o cancelamento da sua assinatura.", + "billing.currentSubscription.subheading": "Assinatura atual do espaço de trabalho:", + "billing.customLimit.link": "Vamos conversar!", + "billing.customLimit.preLink": "Precisa de limites personalizados? Recursos específicos?", + "billing.invoices.empty": "Nenhuma fatura encontrada para este espaço de trabalho.", + "billing.invoices.heading": "Faturas", + "billing.invoices.paidAt": "Pago em", + "billing.invoices.subtotal": "Subtotal", + "billing.limitMessage.analytics": "desbloquear análises aprofundadas", + "billing.limitMessage.brand": "remover a marca", + "billing.limitMessage.customDomain": "adicionar domínios personalizados", + "billing.limitMessage.fileInput": "usar blocos de envio de arquivo", + "billing.limitMessage.folder": "criar pastas", + "billing.preCheckoutModal.companyInput.label": "Nome da empresa:", + "billing.preCheckoutModal.emailInput.label": "E-mail:", + "billing.preCheckoutModal.submitButton.label": "Ir para a finalização da compra", + "billing.preCheckoutModal.taxId.label": "Identificação fiscal (CPF):", + "billing.preCheckoutModal.taxId.placeholder": "Tipo de ID", + "billing.pricingCard.chatsPerMonth": "chats/mês", + "billing.pricingCard.chatsTooltip": "Um chat é contado sempre que um usuário inicia uma discussão. Ele é independente do número de mensagens que ele envia e recebe.", + "billing.pricingCard.heading": "Mudar para plan", + "billing.pricingCard.perMonth": "/ mês", + "billing.pricingCard.plus": ", mais:", + "billing.pricingCard.pro.analytics": "Análises aprofundadas", + "billing.pricingCard.pro.customDomains": "Domínios personalizados", + "billing.pricingCard.pro.description": "Para agências e startups em crescimento.", + "billing.pricingCard.pro.everythingFromStarter": "Tudo em Starter", + "billing.pricingCard.pro.includedSeats": "5 assentos incluídos", + "billing.pricingCard.pro.mostPopularLabel": "Mais popular", + "billing.pricingCard.pro.whatsAppIntegration": "Integração do WhatsApp", + "billing.pricingCard.starter.brandingRemoved": "Marca removida", + "billing.pricingCard.starter.createFolders": "Criar pastas", + "billing.pricingCard.starter.description": "Para indivíduos e pequenas empresas.", + "billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de arquivo", + "billing.pricingCard.starter.includedSeats": "2 assentos incluídos", + "billing.pricingCard.upgradeButton.current": "Sua assinatura atual", + "billing.tiersModal.heading": "Tabela de preço de chats", + "billing.updateSuccessToast.description": "Sua assinatura {plan} foi atualizada com sucesso \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Mais informações", + "billing.upgradeLimitLabel": "Você precisa atualizar sua assinatura para {type}", + "billing.usage.chats.alert.soonReach": "Seus typebots são populares! Você logo alcançará o limite de chats de seu plano. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Certifique-se de atualizar seu plano para aumentar esse limite e continuar conversando com seus usuários.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Uso", + "billing.usage.unlimited": "Ilimitado", + "blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Anexar arquivos", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets", + "cancel": "Cancelar", + "clickToEdit": "Clique para editar...", + "confirmModal.defaultTitle": "Tem certeza?", + "dashboard.header.settingsButton.label": "Configurações & Membros", + "dashboard.redirectionMessage": "Você está sendo redirecionado...", + "dashboard.title": "Meus typebots", + "delete": "Apagar", + "downgrade": "Downgrade", + "editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript", + "editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um arquivo", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link", + "editor.blocks.bubbles.audio.settings.upload.label": "Carregar", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do arquivo de áudio...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs", + "editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)", + "editor.blocks.bubbles.textEditor.plate.label": "Editor de texto", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável", + "editor.blocks.start.text": "Início", + "editor.editableTypebotName.tooltip.rename.label": "Renomear", + "editor.gettingStartedModal.editorBasics.heading": "Fundamentos do Editor", + "editor.gettingStartedModal.editorBasics.list.four.label": "Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito", + "editor.gettingStartedModal.editorBasics.list.label": "Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contato se tiver alguma dúvida. Normalmente, respondo nas próximas 24 horas. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "A barra lateral esquerda contém blocos que podem ser arrastados e soltos no quadro.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Conecte os grupos entre eles", + "editor.gettingStartedModal.editorBasics.list.two.label": "Você pode agrupar blocos juntos, colocando-os abaixo ou acima dos outros", + "editor.gettingStartedModal.seeAction.item.label": "Outros vídeos", + "editor.gettingStartedModal.seeAction.label": "Veja como funciona em", + "editor.gettingStartedModal.seeAction.time": "5 minutos", + "editor.headers.flowButton.label": "Fluxo", + "editor.headers.helpButton.label": "Ajuda", + "editor.headers.previewButton.label": "Visualizar", + "editor.headers.resultsButton.label": "Resultados", + "editor.headers.savingSpinner.label": "Salvando...", + "editor.headers.settingsButton.label": "Configurações", + "editor.headers.shareButton.label": "Compartilhar", + "editor.headers.themeButton.label": "Tema", + "editor.sidebarBlock.abTest.label": "Teste AB", + "editor.sidebarBlock.analytics.label": "Analytics", + "editor.sidebarBlock.audio.label": "Áudio", + "editor.sidebarBlock.button.label": "Botão", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condição", + "editor.sidebarBlock.date.label": "Data", + "editor.sidebarBlock.email.label": "Email", + "editor.sidebarBlock.embed.label": "Incorporar", + "editor.sidebarBlock.file.label": "Arquivo", + "editor.sidebarBlock.image.label": "Imagem", + "editor.sidebarBlock.jump.label": "Pular", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Número", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Pagamento", + "editor.sidebarBlock.phone.label": "Telefone", + "editor.sidebarBlock.picChoice.label": "Seleção de Imagem", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Avaliação", + "editor.sidebarBlock.redirect.label": "Redirecionar", + "editor.sidebarBlock.script.label": "Script", + "editor.sidebarBlock.setVariable.label": "Variável", + "editor.sidebarBlock.sheets.label": "Sheets", + "editor.sidebarBlock.start.label": "Início", + "editor.sidebarBlock.text.label": "Texto", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Vídeo", + "editor.sidebarBlock.wait.label": "Espera", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Website", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles", + "editor.sidebarBlocks.blockType.inputs.heading": "Inputs", + "editor.sidebarBlocks.blockType.integrations.heading": "Integrações", + "editor.sidebarBlocks.blockType.logic.heading": "Condicionais", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Bloquear", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Desbloquear", + "editor.sidebarBlocks.sidebar.lock.label": "Bloquear barra lateral", + "editor.sidebarBlocks.sidebar.unlock.label": "Desbloquear barra lateral", + "errorMessage": "Ocorreu um erro", + "folders.createFolderButton.label": "Criar uma pasta", + "folders.createTypebotButton.label": "Criar um typebot", + "folders.folderButton.deleteConfirmationMessage": "Tem certeza de que deseja excluir a pasta folderName? (Tudo o que estiver dentro será movido para o seu painel)", + "folders.typebotButton.delete": "Apagar", + "folders.typebotButton.deleteConfirmationMessage": "Tem certeza de que deseja excluir seu typebot typebotName?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Todos os dados associados serão excluídos e não poderão ser recuperados.", + "folders.typebotButton.duplicate": "Duplicar", + "folders.typebotButton.live": "Live", + "folders.typebotButton.showMoreOptions": "Mostrar mais opções", + "folders.typebotButton.unpublish": "Despublicar", + "pending": "Pendente", + "remove": "Remover", + "skip": "Pular", + "templates.buttons.fromScratchButton.label": "Comece do zero", + "templates.buttons.fromTemplateButton.label": "Comece a partir de um modelo", + "templates.buttons.heading": "Criar um novo typebot", + "templates.buttons.importFileButton.label": "Importar um arquivo", + "templates.importFromFileButon.toastError.description": "Falha ao analisar o arquivo. Tem certeza de que é um typebot?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Novo", + "templates.modal.menuHeading.other": "Outros", + "templates.modal.menuHeading.product": "Produto", + "templates.modal.useTemplateButton.label": "Usar esse modelo", + "upgrade": "Upgrade", + "video.aspectRatioInput.label": "Proporção", + "video.aspectRatioInput.moreInfoTooltip": "Exemplo: \"16/9\" ou \"9/16\"", + "video.maxWidthInput.label": "Largura máxima", + "video.maxWidthInput.moreInfoTooltip": "Exemplo: \"300px\" ou \"100%\"", + "video.urlInput.helperText": "Compatível com Youtube, Vimeo, Gumlet, TikTok e outros", + "video.urlInput.placeholder": "Colar o link do vídeo...", + "workspace.dropdown.logoutButton.label": "Sair", + "workspace.dropdown.newButton.label": "Novo espaço de trabalho", + "workspace.membersList.inviteButton.label": "Convidar", + "workspace.membersList.inviteInput.placeholder": "colega@empresa.com", + "workspace.membersList.title": "Membros", + "workspace.membersList.unlockBanner.label": "Atualize seu plano para trabalhar com mais membros da equipe e desbloqueie recursos incríveis \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Você tem certeza de que deseja excluir o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.", + "workspace.settings.deleteButton.label": "Excluir espaço de trabalho", + "workspace.settings.icon.title": "Ícone", + "workspace.settings.modal.menu.billingAndUsage.label": "Faturamento e uso", + "workspace.settings.modal.menu.members.label": "Membros", + "workspace.settings.modal.menu.myAccount.label": "Minha conta", + "workspace.settings.modal.menu.preferences.label": "Preferências", + "workspace.settings.modal.menu.settings.label": "Configurações", + "workspace.settings.modal.menu.version.label": "Versão: {version}", + "workspace.settings.modal.menu.workspace.label": "Espaço de trabalho", + "workspace.settings.name.label": "Nome:" +} diff --git a/apps/builder/public/locales/pt.json b/apps/builder/public/locales/pt.json new file mode 100644 index 0000000..41986fe --- /dev/null +++ b/apps/builder/public/locales/pt.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Criar", + "account.apiTokens.createModal.copyInstruction": "Por favor, copie o seu token e guarde-o num lugar seguro.", + "account.apiTokens.createModal.createButton.label": "Criar token", + "account.apiTokens.createModal.createHeading": "Criar Token", + "account.apiTokens.createModal.createdHeading": "Token Criado", + "account.apiTokens.createModal.doneButton.label": "Concluído", + "account.apiTokens.createModal.nameInput.label": "Insira um nome único para o seu token para o diferenciar de outros tokens.", + "account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Por razões de segurança, não o podemos mostrar novamente.", + "account.apiTokens.deleteButton.label": "Excluir", + "account.apiTokens.deleteConfirmationMessage": "O token tokenName será revogado permanentemente. Tem a certeza de que deseja continuar?", + "account.apiTokens.description": "Estes tokens permitem que outras aplicações controlem toda a sua conta e typebots. Tenha cuidado!", + "account.apiTokens.heading": "Tokens de API", + "account.apiTokens.table.createdHeader": "Criado", + "account.apiTokens.table.nameHeader": "Nome", + "account.myAccount.changePhotoButton.label": "Alterar foto", + "account.myAccount.changePhotoButton.specification": ".jpg ou.png, máximo 1MB", + "account.myAccount.emailInput.disabledTooltip": "A atualização do e-mail não está disponível. Entre em contacto com o apoio se quiser alterá-lo.", + "account.myAccount.emailInput.label": "Endereço de e-mail:", + "account.myAccount.nameInput.label": "Nome:", + "account.preferences.appearance.darkLabel": "Escuro", + "account.preferences.appearance.heading": "Aparência", + "account.preferences.appearance.lightLabel": "Claro", + "account.preferences.appearance.systemLabel": "Sistema", + "account.preferences.graphNavigation.heading": "Navegação do Editor", + "account.preferences.graphNavigation.mouse.description": "Mova arrastando o quadro e amplie/reduza usando a roda de deslocamento", + "account.preferences.graphNavigation.mouse.label": "Rato", + "account.preferences.graphNavigation.trackpad.description": "Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Idioma", + "account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em curso. \uD83E\uDD13", + "analytics.completionRateLabel": "Taxa de conclusão", + "analytics.notAvailableLabel": "Não disponível", + "analytics.startsLabel": "Inícios", + "analytics.viewsLabel": "Visualizações", + "auth.emailSubmitButton.label": "Enviar", + "auth.error.default": "Tente entrar com uma conta diferente.", + "auth.error.email": "E-mail não encontrado. Tente entrar com um fornecedor diferente.", + "auth.error.oauthNotLinked": "Para confirmar a sua identidade, entre com a mesma conta que usou originalmente.", + "auth.error.unknown": "Ocorreu um erro. Tente novamente.", + "auth.magicLink.description": "Certifique-se de verificar a sua pasta de spam.", + "auth.magicLink.title": "Foi enviado um e-mail com a ligação mágica. \uD83E\uDE84", + "auth.noProvider.link": "configurar pelo menos um fornecedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).", + "auth.noProvider.preLink": "Precisa de", + "auth.orEmailLabel": "Ou com o seu e-mail", + "auth.register.aggreeToTerms": "Ao registar-se, concorda com os nossos termos de serviço e política de privacidade.", + "auth.register.alreadyHaveAccountLabel.link": "Entrar", + "auth.register.alreadyHaveAccountLabel.preLink": "Já tem uma conta?", + "auth.register.heading": "Criar uma conta", + "auth.signin.heading": "Entrar", + "auth.signin.noAccountLabel.link": "Registe-se gratuitamente", + "auth.signin.noAccountLabel.preLink": "Não tem uma conta?", + "auth.signinErrorToast.description": "As inscrições estão desativadas.", + "auth.signinErrorToast.title": "Não autorizado", + "auth.signinErrorToast.tooManyRequests": "Muitas tentativas. Tente novamente mais tarde.", + "auth.socialLogin.azureButton.label": "Continuar com {azureProviderName}", + "auth.socialLogin.customButton.label": "Continuar com {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continuar com Facebook", + "auth.socialLogin.githubButton.label": "Continuar com GitHub", + "auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}", + "auth.socialLogin.googleButton.label": "Continuar com Google", + "back": "Voltar", + "billing.billingPortalButton.label": "Portal de facturação", + "billing.contribution.link": "Saiba mais.", + "billing.contribution.preLink": "A Typebot está a contribuir com 1% da sua subscrição para remover o CO₂ da atmosfera.", + "billing.currentSubscription.cancelDate": "Será cancelado em", + "billing.currentSubscription.heading": "Subscrição", + "billing.currentSubscription.pastDueAlert": "O último pagamento falhou. Acesse o portal de faturamento para continuar e evitar o cancelamento da sua assinatura.", + "billing.currentSubscription.subheading": "Subscrição actual do espaço de trabalho:", + "billing.customLimit.link": "Vamos falar!", + "billing.customLimit.preLink": "Precisa de limites personalizados? Funcionalidades específicas?", + "billing.invoices.empty": "Nenhuma factura encontrada para este espaço de trabalho.", + "billing.invoices.heading": "Facturas", + "billing.invoices.paidAt": "Pago em", + "billing.invoices.subtotal": "Subtotal", + "billing.limitMessage.analytics": "desbloquear análises aprofundadas", + "billing.limitMessage.brand": "remover a marca", + "billing.limitMessage.customDomain": "adicionar domínios personalizados", + "billing.limitMessage.fileInput": "usar blocos de envio de ficheiros", + "billing.limitMessage.folder": "criar pastas", + "billing.preCheckoutModal.companyInput.label": "Nome da empresa:", + "billing.preCheckoutModal.emailInput.label": "E-mail:", + "billing.preCheckoutModal.submitButton.label": "Ir para a finalização da compra", + "billing.preCheckoutModal.taxId.label": "Identificação fiscal (NIF):", + "billing.preCheckoutModal.taxId.placeholder": "Tipo de ID", + "billing.pricingCard.chatsPerMonth": "chats/mês", + "billing.pricingCard.chatsTooltip": "Um chat é contado sempre que um utilizador inicia uma discussão. Ele é independente do número de mensagens que envia e recebe.", + "billing.pricingCard.heading": "Mudar para plan", + "billing.pricingCard.perMonth": "/ mês", + "billing.pricingCard.plus": ", mais:", + "billing.pricingCard.pro.analytics": "Análises aprofundadas", + "billing.pricingCard.pro.customDomains": "Domínios personalizados", + "billing.pricingCard.pro.description": "Para agências e startups em crescimento.", + "billing.pricingCard.pro.everythingFromStarter": "Tudo em Starter", + "billing.pricingCard.pro.includedSeats": "5 lugares incluídos", + "billing.pricingCard.pro.mostPopularLabel": "Mais popular", + "billing.pricingCard.pro.whatsAppIntegration": "Integração do WhatsApp", + "billing.pricingCard.starter.brandingRemoved": "Marca removida", + "billing.pricingCard.starter.createFolders": "Criar pastas", + "billing.pricingCard.starter.description": "Para indivíduos e pequenas empresas.", + "billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de ficheiro", + "billing.pricingCard.starter.includedSeats": "2 lugares incluídos", + "billing.pricingCard.upgradeButton.current": "A sua subscrição atual", + "billing.tiersModal.heading": "Tabela de preços de chat", + "billing.updateSuccessToast.description": "A sua subscrição {plan} foi atualizada com sucesso \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Mais informações", + "billing.upgradeLimitLabel": "Precisa de atualizar a sua subscrição para {type}", + "billing.usage.chats.alert.soonReach": "Os seus typebots são populares! Vai alcançar em breve o limite de chats do seu plano. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Certifique-se de atualizar o seu plano para aumentar esse limite e continuar a conversar com os seus utilizadores.", + "billing.usage.chats.heading": "Chats", + "billing.usage.heading": "Uso", + "billing.usage.unlimited": "Ilimitado", + "blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets", + "cancel": "Cancelar", + "clickToEdit": "Clique para editar...", + "confirmModal.defaultTitle": "Tem a certeza?", + "dashboard.header.settingsButton.label": "Configurações & Membros", + "dashboard.redirectionMessage": "Está a ser redirecionado...", + "dashboard.title": "Os meus typebots", + "delete": "Apagar", + "downgrade": "Downgrade", + "editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript", + "editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um ficheiro", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link", + "editor.blocks.bubbles.audio.settings.upload.label": "Carregar", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do ficheiro de áudio...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs", + "editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)", + "editor.blocks.bubbles.textEditor.plate.label": "Editor de texto", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável", + "editor.blocks.start.text": "Começar", + "editor.editableTypebotName.tooltip.rename.label": "Renomear", + "editor.gettingStartedModal.editorBasics.heading": "Noções básicas de editor", + "editor.gettingStartedModal.editorBasics.list.four.label": "Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito", + "editor.gettingStartedModal.editorBasics.list.label": "Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contacto se tiver alguma questão. Normalmente, respondo nas próximas 24 horas. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "A barra lateral esquerda contém blocos que pode arrastar e largar no quadro.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Ligue os grupos entre si", + "editor.gettingStartedModal.editorBasics.list.two.label": "Pode agrupar blocos juntos, colocando-os uns abaixo ou acima dos outros", + "editor.gettingStartedModal.seeAction.item.label": "Outros vídeos", + "editor.gettingStartedModal.seeAction.label": "Veja o funcionamento em", + "editor.gettingStartedModal.seeAction.time": "5 minutos", + "editor.headers.flowButton.label": "Fluxo", + "editor.headers.helpButton.label": "Ajuda", + "editor.headers.previewButton.label": "Visualizar", + "editor.headers.resultsButton.label": "Resultados", + "editor.headers.savingSpinner.label": "Salvando...", + "editor.headers.settingsButton.label": "Configurações", + "editor.headers.shareButton.label": "Compartilhar", + "editor.headers.themeButton.label": "Tema", + "editor.sidebarBlock.abTest.label": "Teste AB", + "editor.sidebarBlock.analytics.label": "Analytics", + "editor.sidebarBlock.audio.label": "Áudio", + "editor.sidebarBlock.button.label": "Botão", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condição", + "editor.sidebarBlock.date.label": "Data", + "editor.sidebarBlock.email.label": "Email", + "editor.sidebarBlock.embed.label": "Incorporar", + "editor.sidebarBlock.file.label": "Ficheiro", + "editor.sidebarBlock.image.label": "Imagem", + "editor.sidebarBlock.jump.label": "Saltar", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Número", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Pagamento", + "editor.sidebarBlock.phone.label": "Telefone", + "editor.sidebarBlock.picChoice.label": "Seleção de Imagem", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Classificação", + "editor.sidebarBlock.redirect.label": "Redirecionar", + "editor.sidebarBlock.script.label": "Script", + "editor.sidebarBlock.setVariable.label": "Variável", + "editor.sidebarBlock.sheets.label": "Sheets", + "editor.sidebarBlock.start.label": "Início", + "editor.sidebarBlock.text.label": "Texto", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Vídeo", + "editor.sidebarBlock.wait.label": "Espera", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Website", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles", + "editor.sidebarBlocks.blockType.inputs.heading": "Inputs", + "editor.sidebarBlocks.blockType.integrations.heading": "Integrações", + "editor.sidebarBlocks.blockType.logic.heading": "Condicionais", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Bloquear", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Desbloquear", + "editor.sidebarBlocks.sidebar.lock.label": "Bloquear barra lateral", + "editor.sidebarBlocks.sidebar.unlock.label": "Desbloquear barra lateral", + "errorMessage": "Ocorreu um erro", + "folders.createFolderButton.label": "Criar uma pasta", + "folders.createTypebotButton.label": "Criar um typebot", + "folders.folderButton.deleteConfirmationMessage": "Tem a certeza de que deseja excluir a pasta folderName? (Tudo o que estiver dentro será movido para o seu painel)", + "folders.typebotButton.delete": "Apagar", + "folders.typebotButton.deleteConfirmationMessage": "Tem a certeza de que deseja excluir o seu typebot typebotName?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Todos os dados associados serão excluídos e não poderão ser recuperados.", + "folders.typebotButton.duplicate": "Duplicar", + "folders.typebotButton.live": "Ao Vivo", + "folders.typebotButton.showMoreOptions": "Mostrar mais opções", + "folders.typebotButton.unpublish": "Despublicar", + "pending": "Pendente", + "remove": "Remover", + "skip": "Saltar", + "templates.buttons.fromScratchButton.label": "Comece do zero", + "templates.buttons.fromTemplateButton.label": "Comece a partir de um modelo", + "templates.buttons.heading": "Criar um novo typebot", + "templates.buttons.importFileButton.label": "Importar um ficheiro", + "templates.importFromFileButon.toastError.description": "Falha ao analisar o ficheiro. Tem certeza de que é um typebot?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Novo", + "templates.modal.menuHeading.other": "Outros", + "templates.modal.menuHeading.product": "Produto", + "templates.modal.useTemplateButton.label": "Usar este modelo", + "upgrade": "Upgrade", + "video.aspectRatioInput.label": "Proporção", + "video.aspectRatioInput.moreInfoTooltip": "Exemplo: \"16/9\" ou \"9/16\"", + "video.maxWidthInput.label": "Largura máxima", + "video.maxWidthInput.moreInfoTooltip": "Exemplo: \"300px\" ou \"100%\"", + "video.urlInput.helperText": "Compatível com Youtube, Vimeo, Gumlet, TikTok e outros", + "video.urlInput.placeholder": "Colar o link do vídeo...", + "workspace.dropdown.logoutButton.label": "Sair", + "workspace.dropdown.newButton.label": "Novo espaço de trabalho", + "workspace.membersList.inviteButton.label": "Convidar", + "workspace.membersList.inviteInput.placeholder": "colega@empresa.com", + "workspace.membersList.title": "Membros", + "workspace.membersList.unlockBanner.label": "Atualize o seu plano para trabalhar com mais membros da equipa e desbloquear funcionalidades incríveis \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Tem a certeza de que deseja eliminar o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.", + "workspace.settings.deleteButton.label": "Eliminar espaço de trabalho", + "workspace.settings.icon.title": "Ícone", + "workspace.settings.modal.menu.billingAndUsage.label": "Faturação e uso", + "workspace.settings.modal.menu.members.label": "Membros", + "workspace.settings.modal.menu.myAccount.label": "A minha conta", + "workspace.settings.modal.menu.preferences.label": "Preferências", + "workspace.settings.modal.menu.settings.label": "Configurações", + "workspace.settings.modal.menu.version.label": "Versão: {version}", + "workspace.settings.modal.menu.workspace.label": "Espaço de trabalho", + "workspace.settings.name.label": "Nome:" +} diff --git a/apps/builder/public/locales/ro.json b/apps/builder/public/locales/ro.json new file mode 100644 index 0000000..75b4683 --- /dev/null +++ b/apps/builder/public/locales/ro.json @@ -0,0 +1,252 @@ +{ + "account.apiTokens.createButton.label": "Crează", + "account.apiTokens.createModal.copyInstruction": "Vă rugăm să vă copiați jetonul și să-l păstrați într-un loc sigur.", + "account.apiTokens.createModal.createButton.label": "Creați token", + "account.apiTokens.createModal.createHeading": "Creați token", + "account.apiTokens.createModal.createdHeading": "Token creat", + "account.apiTokens.createModal.doneButton.label": "Terminat", + "account.apiTokens.createModal.nameInput.label": "Introduceți un nume unic pentru token-ul dvs. pentru a-l diferenția de alte jetoane.", + "account.apiTokens.createModal.nameInput.placeholder": "d.e. Zapier, Github, Make.com", + "account.apiTokens.createModal.securityWarning": "Din motive de securitate, nu îl putem arăta din nou.", + "account.apiTokens.deleteButton.label": "Șterge", + "account.apiTokens.deleteConfirmationMessage": "Indicatorul tokenName va fi revocat definitiv, sunteți sigur că doriți să continuați?", + "account.apiTokens.description": "Aceste jetoane permit altor aplicații să vă controleze întregul cont și typebots. Atenție!", + "account.apiTokens.heading": "Jetoane API", + "account.apiTokens.table.createdHeader": "Creat", + "account.apiTokens.table.nameHeader": "Nume", + "account.myAccount.changePhotoButton.label": "Schimbare fotografie", + "account.myAccount.changePhotoButton.specification": ".jpg sau.png, maxim 1MB", + "account.myAccount.emailInput.disabledTooltip": "Actualizarea e-mailului nu este disponibilă. Contactați asistența dacă doriți să o schimbați.", + "account.myAccount.emailInput.label": "Adresa de e-mail:", + "account.myAccount.nameInput.label": "Nume:", + "account.preferences.appearance.darkLabel": "Întuneric", + "account.preferences.appearance.heading": "Aspect", + "account.preferences.appearance.lightLabel": "Luminos", + "account.preferences.appearance.systemLabel": "Sistem", + "account.preferences.graphNavigation.heading": "Navigare editor", + "account.preferences.graphNavigation.mouse.description": "Deplasați-vă trăgând panoul și măriți / micșorați folosind rotița de defilare", + "account.preferences.graphNavigation.mouse.label": "Mouse", + "account.preferences.graphNavigation.trackpad.description": "Mutați placa folosind 2 degete și măriți/micșorați prin ciupire", + "account.preferences.graphNavigation.trackpad.label": "Trackpad", + "account.preferences.language.heading": "Limba", + "account.preferences.language.tooltip": "Traducerile nu sunt încă complete. Este o lucrare în curs. \uD83E\uDD13", + "analytics.completionRateLabel": "Rata de finalizare", + "analytics.notAvailableLabel": "Nu este disponibil", + "analytics.startsLabel": "Începe", + "analytics.viewsLabel": "Vizualizări", + "auth.emailSubmitButton.label": "Trimite", + "auth.error.default": "Încercați să semnați cu alt cont.", + "auth.error.email": "E-mail nu a fost găsit. Încercați să semnați cu un alt furnizor.", + "auth.error.oauthNotLinked": "Pentru a vă confirma identitatea, conectați-vă cu același cont pe care l-ați folosit inițial.", + "auth.error.unknown": "A aparut o eroare. Vă rugăm să încercați din nou.", + "auth.magicLink.description": "Asigurați-vă că verificați folderul de spam.", + "auth.magicLink.title": "A fost trimis un e-mail cu link magic. \uD83E\uDE84", + "auth.noProvider.link": "configurați cel puțin un furnizor de autentificare (E-mail, Google, GitHub, Facebook sau Azure AD).", + "auth.noProvider.preLink": "Trebuie să", + "auth.orEmailLabel": "Sau cu e-mailul tău", + "auth.register.aggreeToTerms": "Prin înscriere, sunteți de acord cu termeni și condiții de utilizare și cu politica de confidențialitate.", + "auth.register.alreadyHaveAccountLabel.link": "Conectare", + "auth.register.alreadyHaveAccountLabel.preLink": "Ai deja un cont?", + "auth.register.heading": "Creați un cont", + "auth.signin.heading": "Conectare", + "auth.signin.noAccountLabel.link": "Inregistreaza-te GRATUIT", + "auth.signin.noAccountLabel.preLink": "Nu ai un cont?", + "auth.signinErrorToast.description": "Înscrierile sunt dezactivate.", + "auth.signinErrorToast.title": "Neautorizat", + "auth.signinErrorToast.tooManyRequests": "Prea multe cereri. Încercați mai târziu.", + "auth.socialLogin.azureButton.label": "Continuați cu {customProviderName}", + "auth.socialLogin.customButton.label": "Continuați cu {customProviderName}", + "auth.socialLogin.facebookButton.label": "Continuați cu Facebook", + "auth.socialLogin.githubButton.label": "Continuați cu GitHub", + "auth.socialLogin.gitlabButton.label": "Continuați cu {customProviderName}", + "auth.socialLogin.googleButton.label": "Continuați cu Google", + "back": "Înapoi", + "billing.billingPortalButton.label": "Portalul de facturare", + "billing.contribution.link": "Află mai multe.", + "billing.contribution.preLink": "Typebot contribuie cu 1% din abonamentul dvs. pentru a elimina CO₂ din atmosferă.", + "billing.currentSubscription.cancelDate": "Va fi anulat pe", + "billing.currentSubscription.heading": "Abonament", + "billing.currentSubscription.pastDueAlert": "Ultima plată a eșuat. Accesați portalul de facturare pentru a continua și pentru a evita anularea abonamentului.", + "billing.currentSubscription.subheading": "Abonament curent pentru spațiul de lucru:", + "billing.customLimit.link": "Hai sa vorbim!", + "billing.customLimit.preLink": "Ai nevoie de limite personalizate? Caracteristici specifice?", + "billing.invoices.empty": "Nu s-au găsit facturi pentru acest spațiu de lucru.", + "billing.invoices.heading": "Facturi", + "billing.invoices.paidAt": "Plătit la", + "billing.invoices.subtotal": "Subtotal", + "billing.limitMessage.analytics": "deblocați analize aprofundate", + "billing.limitMessage.brand": "eliminați brandingul", + "billing.limitMessage.customDomain": "adăugați domenii personalizate", + "billing.limitMessage.fileInput": "utilizați blocuri de introducere a fișierelor", + "billing.limitMessage.folder": "creați foldere", + "billing.preCheckoutModal.companyInput.label": "Numele companiei:", + "billing.preCheckoutModal.emailInput.label": "E-mail:", + "billing.preCheckoutModal.submitButton.label": "Mergi la casa", + "billing.preCheckoutModal.taxId.label": "Cod fiscal:", + "billing.preCheckoutModal.taxId.placeholder": "tip ID", + "billing.pricingCard.chatsPerMonth": "chat-uri/lună", + "billing.pricingCard.chatsTooltip": "Un chat este numărat ori de câte ori un utilizator începe o discuție. Este independent de numărul de mesaje pe care le trimite și le primește.", + "billing.pricingCard.heading": "Treceți la plan", + "billing.pricingCard.perMonth": "/luna", + "billing.pricingCard.plus": ", la care se adauga:", + "billing.pricingCard.pro.analytics": "Analize aprofundate", + "billing.pricingCard.pro.customDomains": "Domenii personalizate", + "billing.pricingCard.pro.description": "Pentru agenții și startup-uri în creștere.", + "billing.pricingCard.pro.everythingFromStarter": "Totul în Starter", + "billing.pricingCard.pro.includedSeats": "5 locuri incluse", + "billing.pricingCard.pro.mostPopularLabel": "Cel mai popular", + "billing.pricingCard.pro.whatsAppIntegration": "Integrare WhatsApp", + "billing.pricingCard.starter.brandingRemoved": "Branding eliminat", + "billing.pricingCard.starter.createFolders": "Creați foldere", + "billing.pricingCard.starter.description": "Pentru persoane fizice și întreprinderi mici.", + "billing.pricingCard.starter.fileUploadBlock": "Bloc de intrare pentru încărcarea fișierului", + "billing.pricingCard.starter.includedSeats": "2 locuri incluse", + "billing.pricingCard.upgradeButton.current": "Planul dvs. actual", + "billing.tiersModal.heading": "Tabelul de prețuri pentru chat", + "billing.updateSuccessToast.description": "Planul spațiului de lucru {plan} a fost actualizat cu succes \uD83C\uDF89", + "billing.upgradeAlert.buttonDefaultLabel": "Mai multe informatii", + "billing.upgradeLimitLabel": "Trebuie să vă actualizați planul pentru a {type}", + "billing.usage.chats.alert.soonReach": "Typebot-ii tăi sunt populari! În curând vei atinge limita de chat-uri a planului tău. \uD83D\uDE80", + "billing.usage.chats.alert.updatePlan": "Asigurați-vă că vă actualizați planul pentru a crește această limită și continuați să discutați cu utilizatorii dvs.", + "billing.usage.chats.heading": "Chat-uri", + "billing.usage.heading": "Utilizare", + "billing.usage.unlimited": "Nelimitat", + "blocks.bubbles.embed.blockCard.tooltip": "Încorporați un pdf, un iframe, un site web...", + "blocks.inputs.fileUpload.blockCard.tooltip": "Încărca fișiere", + "blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics", + "blocks.integrations.googleSheets.blockCard.tooltip": "Foi de calcul Google", + "cancel": "Anulare", + "clickToEdit": "Faceți clic pentru a edita...", + "confirmModal.defaultTitle": "Esti sigur?", + "dashboard.header.settingsButton.label": "Setări și membri", + "dashboard.redirectionMessage": "Sunteti redirectionat...", + "dashboard.title": "Typebot-ii mei", + "delete": "Șterge", + "downgrade": "Degradează", + "editor.blockCard.logicBlock.tooltip.code.label": "Executați codul Javascript", + "editor.blockCard.logicBlock.tooltip.jump.label": "Avansați rapid fluxul către alt grup", + "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Conectați-vă și săriți la alt typebot", + "editor.blocks.bubbles.audio.settings.autoplay.label": "Activați redarea automată", + "editor.blocks.bubbles.audio.settings.chooseFile.label": "Alegeți un fișier", + "editor.blocks.bubbles.audio.settings.embedLink.label": "Încorporați linkul", + "editor.blocks.bubbles.audio.settings.upload.label": "Încărcați", + "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Lipiți linkul fișierului audio...", + "editor.blocks.bubbles.audio.settings.worksWith.text": "Funcționează cu .MP3 și .WAV", + "editor.blocks.bubbles.embed.node.show.text": "Afișați încorporarea", + "editor.blocks.bubbles.embed.settings.numberInput.unit": "px", + "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Lipiți linkul sau codul...", + "editor.blocks.bubbles.embed.settings.worksWith.text": "Funcționează cu PDF-uri, iframe, site-uri web...", + "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "La clic pe link", + "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (descriere)", + "editor.blocks.bubbles.textEditor.plate.label": "Editor de text", + "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Căutați o variabilă", + "editor.blocks.start.text": "start", + "editor.editableTypebotName.tooltip.rename.label": "Redenumiți", + "editor.gettingStartedModal.editorBasics.heading": "Elementele de bază ale editorului", + "editor.gettingStartedModal.editorBasics.list.four.label": "Previzualizați botul dvs. făcând clic pe butonul de previzualizare din dreapta sus", + "editor.gettingStartedModal.editorBasics.list.label": "Simțiți-vă liber să utilizați balonul din dreapta jos pentru a contacta dacă aveți întrebări. De obicei răspund în următoarele 24 de ore. \uD83D\uDE03", + "editor.gettingStartedModal.editorBasics.list.one.label": "Bara din stânga conține blocuri pe care le puteți trage și plasa pe panou.", + "editor.gettingStartedModal.editorBasics.list.three.label": "Conectați grupurile împreună", + "editor.gettingStartedModal.editorBasics.list.two.label": "Puteți grupa blocuri, aruncându-le unul sub celălalt sau deasupra celuilalt", + "editor.gettingStartedModal.seeAction.item.label": "Alte videoclipuri", + "editor.gettingStartedModal.seeAction.label": "Vedeți-l în acțiune", + "editor.gettingStartedModal.seeAction.time": "5 minute", + "editor.headers.flowButton.label": "curgere", + "editor.headers.helpButton.label": "Ajutor", + "editor.headers.previewButton.label": "previzualizare", + "editor.headers.resultsButton.label": "Rezultate", + "editor.headers.savingSpinner.label": "Salvare...", + "editor.headers.settingsButton.label": "Setări", + "editor.headers.shareButton.label": "Acțiune", + "editor.headers.themeButton.label": "Temă", + "editor.sidebarBlock.abTest.label": "Testul AB", + "editor.sidebarBlock.analytics.label": "Analitica", + "editor.sidebarBlock.audio.label": "Audio", + "editor.sidebarBlock.button.label": "Butoane", + "editor.sidebarBlock.chatwoot.label": "Chatwoot", + "editor.sidebarBlock.condition.label": "Condiție", + "editor.sidebarBlock.date.label": "Data", + "editor.sidebarBlock.email.label": "E-mail", + "editor.sidebarBlock.embed.label": "Încorporare", + "editor.sidebarBlock.file.label": "Fişier", + "editor.sidebarBlock.image.label": "Imagine", + "editor.sidebarBlock.jump.label": "Sari", + "editor.sidebarBlock.makecom.label": "Make.com", + "editor.sidebarBlock.number.label": "Număr", + "editor.sidebarBlock.openai.label": "OpenAI", + "editor.sidebarBlock.pabbly.label": "Pabbly", + "editor.sidebarBlock.payment.label": "Plată", + "editor.sidebarBlock.phone.label": "Telefon", + "editor.sidebarBlock.picChoice.label": "Alegerea poza", + "editor.sidebarBlock.pixel.label": "Pixel", + "editor.sidebarBlock.rating.label": "Evaluare", + "editor.sidebarBlock.redirect.label": "Redirecţiona", + "editor.sidebarBlock.script.label": "Scenariul", + "editor.sidebarBlock.setVariable.label": "Setați variabila", + "editor.sidebarBlock.sheets.label": "Foi", + "editor.sidebarBlock.start.label": "Start", + "editor.sidebarBlock.text.label": "Text", + "editor.sidebarBlock.typebot.label": "Typebot", + "editor.sidebarBlock.video.label": "Video", + "editor.sidebarBlock.wait.label": "Așteaptă", + "editor.sidebarBlock.webhook.label": "Webhook", + "editor.sidebarBlock.website.label": "Site-ul web", + "editor.sidebarBlock.zapier.label": "Zapier", + "editor.sidebarBlock.zemanticAi.label": "Zemantic AI", + "editor.sidebarBlocks.blockType.bubbles.heading": "Bule", + "editor.sidebarBlocks.blockType.inputs.heading": "Intrări", + "editor.sidebarBlocks.blockType.integrations.heading": "Integrari", + "editor.sidebarBlocks.blockType.logic.heading": "Logică", + "editor.sidebarBlocks.sidebar.icon.lock.label": "Blocați", + "editor.sidebarBlocks.sidebar.icon.unlock.label": "Deblocați", + "editor.sidebarBlocks.sidebar.lock.label": "Blocați bara laterală", + "editor.sidebarBlocks.sidebar.unlock.label": "Deblocați bara laterală", + "errorMessage": "A aparut o eroare", + "folders.createFolderButton.label": "Creați un folder", + "folders.createTypebotButton.label": "Creați un typebot", + "folders.folderButton.deleteConfirmationMessage": "Sigur doriți să ștergeți dosarul folderName? (Totul din interior va fi mutat în tabloul de bord)", + "folders.typebotButton.delete": "Șterge", + "folders.typebotButton.deleteConfirmationMessage": "Sigur doriți să ștergeți typebotName de typebot?", + "folders.typebotButton.deleteConfirmationMessageWarning": "Toate datele asociate acesteia vor fi șterse și nu vor fi recuperate.", + "folders.typebotButton.duplicate": "Duplicat", + "folders.typebotButton.live": "Trăi", + "folders.typebotButton.showMoreOptions": "Afișați mai multe opțiuni", + "folders.typebotButton.unpublish": "Anulați publicarea", + "pending": "In asteptarea", + "remove": "Elimina", + "skip": "Ocolire", + "templates.buttons.fromScratchButton.label": "Începe de la zero", + "templates.buttons.fromTemplateButton.label": "Începeți de la un șablon", + "templates.buttons.heading": "Creați un nou typebot", + "templates.buttons.importFileButton.label": "Importați un fișier", + "templates.importFromFileButon.toastError.description": "Nu s-a putut analiza fișierul. Ești sigur că este un typebot?", + "templates.modal.menuHeading.marketing": "Marketing", + "templates.modal.menuHeading.new.tag": "Nou", + "templates.modal.menuHeading.other": "Alte", + "templates.modal.menuHeading.product": "Produs", + "templates.modal.useTemplateButton.label": "Utilizați acest șablon", + "upgrade": "Actualizare", + "video.aspectRatioInput.label": "Raportul de aspect", + "video.aspectRatioInput.moreInfoTooltip": "Exemplu: „16/9” sau „9/16”", + "video.maxWidthInput.label": "lățimea maximă", + "video.maxWidthInput.moreInfoTooltip": "Exemplu: „300px” sau „100%”", + "video.urlInput.helperText": "Funcționează cu Youtube, Vimeo, Gumlet, TikTok și altele", + "video.urlInput.placeholder": "Lipiți linkul video...", + "workspace.dropdown.logoutButton.label": "Deconectați-vă", + "workspace.dropdown.newButton.label": "Nou spațiu de lucru", + "workspace.membersList.inviteButton.label": "A invita", + "workspace.membersList.inviteInput.placeholder": "colega@company.com", + "workspace.membersList.title": "Membrii", + "workspace.membersList.unlockBanner.label": "Actualizați-vă planul pentru a lucra cu mai mulți membri ai echipei și deblocați funcții extraordinare de putere \uD83D\uDE80", + "workspace.settings.deleteButton.confirmMessage": "Sigur doriți să ștergeți spațiul de lucru {workspaceName}? Toate folderele, tiproboții și rezultatele sale vor fi șterse pentru totdeauna.", + "workspace.settings.deleteButton.label": "Șterge spațiul de lucru", + "workspace.settings.icon.title": "Pictogramă", + "workspace.settings.modal.menu.billingAndUsage.label": "Facturare și utilizare", + "workspace.settings.modal.menu.members.label": "Membrii", + "workspace.settings.modal.menu.myAccount.label": "Contul meu", + "workspace.settings.modal.menu.preferences.label": "Preferințe", + "workspace.settings.modal.menu.settings.label": "Setări", + "workspace.settings.modal.menu.version.label": "Versiune: {version}", + "workspace.settings.modal.menu.workspace.label": "Spațiul de lucru", + "workspace.settings.name.label": "Nume:" +} diff --git a/apps/builder/public/templates/audio-chat-gpt.json b/apps/builder/public/templates/audio-chat-gpt.json new file mode 100644 index 0000000..3cf83c6 --- /dev/null +++ b/apps/builder/public/templates/audio-chat-gpt.json @@ -0,0 +1,200 @@ +{ + "version": "6", + "id": "clpntvmje00031aboan4plzzx", + "name": "Audio ChatGPT", + "events": [ + { + "id": "ewnfbo0exlu7ihfu2lu2lusm", + "outgoingEdgeId": "f2hmh9jelbqb889l6lx5e1u5", + "graphCoordinates": { "x": -228.25, "y": -123.31 }, + "type": "start" + } + ], + "groups": [ + { + "id": "qfrz5nwm63g12dajsjxothb5", + "title": "User input", + "graphCoordinates": { "x": 105.17, "y": -56.29 }, + "blocks": [ + { + "id": "ovgk70u0kfxrbtz9dy4e040o", + "type": "text input", + "options": { "variableId": "vudksu3zyrat6s1bq6qne0rx3" } + }, + { + "id": "m4jadtknjb3za3gvxj1xdn1k", + "outgoingEdgeId": "fpj0xacppqd1s5slyljzhzc9", + "type": "Set variable", + "options": { + "variableId": "vabkycu0qqff5d6ar2ama16pf", + "type": "Append value(s)", + "item": "{{User Message}}" + } + } + ] + }, + { + "id": "a6ymhjwtkqwp8t127plz8qmk", + "title": "ChatGPT reply", + "graphCoordinates": { "x": 445.12, "y": -56.2 }, + "blocks": [ + { + "id": "e57nnbkl97h49jaaslxkg3u0", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "Dialogue", + "dialogueVariableId": "vabkycu0qqff5d6ar2ama16pf" + } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "yblc864bzipaqfja7b2o3oo0", + "type": "Set variable", + "options": { + "variableId": "vabkycu0qqff5d6ar2ama16pf", + "type": "Append value(s)", + "item": "{{Assistant Message}}" + } + }, + { + "id": "av59rg9zeqtl73o8icnrr2xd", + "type": "openai", + "options": { + "input": "{{Assistant Message}}", + "voice": "alloy", + "action": "Create speech", + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "saveUrlInVariableId": "vgr0iwg95npp7pztkmdyn89m1" + } + }, + { + "id": "f6onszqys2tx7pw3tshb2vcy", + "outgoingEdgeId": "dw9jclv60i040saiikj3a386", + "type": "audio", + "content": { "url": "{{Assistant audio message}}" } + } + ] + }, + { + "id": "c5f00f3oclwi1srcz10jjt9u", + "title": "Intro", + "graphCoordinates": { "x": -222.61, "y": -54.39 }, + "blocks": [ + { + "id": "yuiyeh0czhpymzwuzrm3af5r", + "type": "openai", + "options": { + "input": "Hi there! How can I help?", + "voice": "alloy", + "action": "Create speech", + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "saveUrlInVariableId": "vxw4quja426402hvhtm33tsp3" + } + }, + { + "id": "dmab8kc35uh84vvw1a53xbjn", + "outgoingEdgeId": "xnao10ucc1hbynv3pmk1t4by", + "type": "audio", + "content": { "url": "{{Welcome audio}}" } + } + ] + }, + { + "id": "yswu9fml4zflxaqlujb94ir8", + "title": "", + "graphCoordinates": { "x": 19.51, "y": -338.93 }, + "blocks": [ + { + "id": "okm2zz32zn8b60u1vkfrv9ca", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your OpenAI credentials to make this bot work. 🪄" + } + ] + } + ] + } + }, + { + "id": "m5a1d0vhsrpyvvvyj89awxzc", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, delete this group and connect the " + }, + { "bold": true, "text": "Start" }, + { "text": " event with " }, + { "bold": true, "text": "Intro" }, + { "text": " 🚀\n" } + ] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "fpj0xacppqd1s5slyljzhzc9", + "from": { "blockId": "m4jadtknjb3za3gvxj1xdn1k" }, + "to": { "groupId": "a6ymhjwtkqwp8t127plz8qmk" } + }, + { + "id": "xnao10ucc1hbynv3pmk1t4by", + "from": { "blockId": "dmab8kc35uh84vvw1a53xbjn" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "id": "dw9jclv60i040saiikj3a386", + "from": { "blockId": "f6onszqys2tx7pw3tshb2vcy" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "from": { "eventId": "ewnfbo0exlu7ihfu2lu2lusm" }, + "to": { "groupId": "yswu9fml4zflxaqlujb94ir8" }, + "id": "f2hmh9jelbqb889l6lx5e1u5" + } + ], + "variables": [ + { "id": "vni6kwbch8zlq92dclgcivzyr", "name": "Assistant Message" }, + { "id": "vudksu3zyrat6s1bq6qne0rx3", "name": "User Message" }, + { "id": "vabkycu0qqff5d6ar2ama16pf", "name": "Chat history" }, + { "id": "vxw4quja426402hvhtm33tsp3", "name": "Welcome audio" }, + { "id": "vgr0iwg95npp7pztkmdyn89m1", "name": "Assistant audio message" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-12-02T09:05:10.874Z", + "updatedAt": "2023-12-02T09:08:20.451Z", + "icon": "🔈", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/basic-chat-gpt.json b/apps/builder/public/templates/basic-chat-gpt.json new file mode 100644 index 0000000..4d3af96 --- /dev/null +++ b/apps/builder/public/templates/basic-chat-gpt.json @@ -0,0 +1,192 @@ +{ + "version": "6", + "id": "clpntkei400011aboogh27ead", + "name": "Basic ChatGPT", + "events": [ + { + "id": "ewnfbo0exlu7ihfu2lu2lusm", + "outgoingEdgeId": "pn7omb9mx5xxc4mzq028fcmq", + "graphCoordinates": { "x": -228.25, "y": -123.31 }, + "type": "start" + } + ], + "groups": [ + { + "id": "t3tv4dm3khwmiotjle5jb65g", + "title": "", + "graphCoordinates": { "x": 10.94, "y": -121.96 }, + "blocks": [ + { + "id": "s6eky7dd3md9hto9y4wsuj7h", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your OpenAI credentials to make this bot work. 🪄" + } + ] + } + ] + } + }, + { + "id": "nqsu9f13q5j8tt56bcbuto62", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, delete this group and connect the " + }, + { "bold": true, "text": "Start" }, + { "text": " event with " }, + { "bold": true, "text": "Intro" }, + { "text": " 🚀" } + ] + } + ] + } + } + ] + }, + { + "id": "qfrz5nwm63g12dajsjxothb5", + "title": "User input", + "graphCoordinates": { "x": 198.64, "y": 179.04 }, + "blocks": [ + { + "id": "ovgk70u0kfxrbtz9dy4e040o", + "type": "text input", + "options": { "variableId": "vudksu3zyrat6s1bq6qne0rx3" } + }, + { + "id": "m4jadtknjb3za3gvxj1xdn1k", + "outgoingEdgeId": "fpj0xacppqd1s5slyljzhzc9", + "type": "Set variable", + "options": { + "variableId": "vabkycu0qqff5d6ar2ama16pf", + "type": "Append value(s)", + "item": "{{User Message}}" + } + } + ] + }, + { + "id": "a6ymhjwtkqwp8t127plz8qmk", + "title": "ChatGPT reply", + "graphCoordinates": { "x": 624.57, "y": 200.09 }, + "blocks": [ + { + "id": "p4q3wbk4wcw818qocrvu7dxs", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "Dialogue", + "dialogueVariableId": "vabkycu0qqff5d6ar2ama16pf" + } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "yblc864bzipaqfja7b2o3oo0", + "type": "Set variable", + "options": { + "variableId": "vabkycu0qqff5d6ar2ama16pf", + "type": "Append value(s)", + "item": "{{Assistant Message}}" + } + }, + { + "id": "myldn1l1nfdwwm8qvza71rwv", + "outgoingEdgeId": "y8ml9ljnsydol9b42fd9zdve", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{Assistant Message}}" }] } + ] + } + } + ] + }, + { + "id": "c5f00f3oclwi1srcz10jjt9u", + "title": "Intro", + "graphCoordinates": { "x": -183.19, "y": 156.03 }, + "blocks": [ + { + "id": "vzcrfk4vl9gy8igu0ysja5nc", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Hi there 👋" }] } + ] + } + }, + { + "id": "gphm5wy1md9cunwkdtbzg6nq", + "outgoingEdgeId": "h5sk58j0ryrxmfv4gmw7r4dw", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How can I help?" }] } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "h5sk58j0ryrxmfv4gmw7r4dw", + "from": { "blockId": "gphm5wy1md9cunwkdtbzg6nq" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "id": "y8ml9ljnsydol9b42fd9zdve", + "from": { "blockId": "myldn1l1nfdwwm8qvza71rwv" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "id": "fpj0xacppqd1s5slyljzhzc9", + "from": { "blockId": "m4jadtknjb3za3gvxj1xdn1k" }, + "to": { "groupId": "a6ymhjwtkqwp8t127plz8qmk" } + }, + { + "from": { "eventId": "ewnfbo0exlu7ihfu2lu2lusm" }, + "to": { "groupId": "t3tv4dm3khwmiotjle5jb65g" }, + "id": "pn7omb9mx5xxc4mzq028fcmq" + } + ], + "variables": [ + { "id": "vni6kwbch8zlq92dclgcivzyr", "name": "Assistant Message" }, + { "id": "vudksu3zyrat6s1bq6qne0rx3", "name": "User Message" }, + { "id": "vabkycu0qqff5d6ar2ama16pf", "name": "Chat history" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": { "general": {} }, + "createdAt": "2023-12-02T08:56:27.244Z", + "updatedAt": "2023-12-02T09:00:25.221Z", + "icon": "🤖", + "folderId": null, + "publicId": null, + "customDomain": null, + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/chat-gpt-personas.json b/apps/builder/public/templates/chat-gpt-personas.json new file mode 100644 index 0000000..995a76e --- /dev/null +++ b/apps/builder/public/templates/chat-gpt-personas.json @@ -0,0 +1,705 @@ +{ + "version": "6", + "id": "clpnu8xj800071abop3o19y02", + "name": "ChatGPT personas", + "events": [ + { + "id": "w99qhdr20tw02sfrfwkfc1tg", + "outgoingEdgeId": "k5bj58emklqfqv3hemko4u23", + "graphCoordinates": { "x": -95.29, "y": -267.02 }, + "type": "start" + } + ], + "groups": [ + { + "id": "bofjp88arodr4k0btv2esyqy", + "title": "", + "graphCoordinates": { "x": 188.44, "y": -308.74 }, + "blocks": [ + { + "id": "s6eky7dd3md9hto9y4wsuj7h", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your OpenAI credentials to make this bot work. 🪄" + } + ] + } + ] + } + }, + { + "id": "nqsu9f13q5j8tt56bcbuto62", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, delete this group and connect the " + }, + { "bold": true, "text": "Start" }, + { "text": " block with " }, + { "bold": true, "text": "Intro" }, + { "text": " 🚀" } + ] + } + ] + } + } + ] + }, + { + "id": "dmg57mgick51p8l5pnyqtyf9", + "title": "Explainer AI reply", + "graphCoordinates": { "x": 1053.297810684862, "y": 919.9658659364646 }, + "blocks": [ + { + "id": "qqlv6ikxqh2l7wjibjqk3j93", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "user", + "content": "Starting from now, I want you to explain things with simple words, as if I'm 11 years old." + }, + { + "role": "Dialogue", + "dialogueVariableId": "vu9adij5penetej2xz89htfe6" + } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "kftq9x1wnrcefzc268ydmqkn", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{Assistant Message}}" + } + }, + { + "id": "myldn1l1nfdwwm8qvza71rwv", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{Assistant Message}}" }] } + ] + } + }, + { + "id": "jz9mklagfikyukzs7n3kmlcf", + "type": "choice input", + "items": [ + { + "id": "x18iwzwmbzi9jjpnwij1861i", + "outgoingEdgeId": "mxl8lftsj3pbmj4g24ymxajo", + "content": "Continue" + }, + { + "id": "imx7otsonvm0takr02b4ulyo", + "outgoingEdgeId": "ny44r5sp69gne7obgshidhph", + "content": "Menu" + } + ] + } + ] + }, + { + "id": "fj5z2nx488htv0843kq6qeyk", + "title": "Professor AI reply", + "graphCoordinates": { "x": 1052.26, "y": -56.02 }, + "blocks": [ + { + "id": "itiwmw62ml38rmeawxxawkub", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "user", + "content": "I want you to act as an English translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in English. I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level English words and sentences. Keep the meaning same, but make them more literary. I want you to only reply the correction, the improvements and nothing else, do not write explanations." + }, + { + "role": "Dialogue", + "dialogueVariableId": "vu9adij5penetej2xz89htfe6" + } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "dyfigmu4095x8p99qe461zbh", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{Assistant Message}}" + } + }, + { + "id": "sei88rrjcmpgm3vhxjvkofyt", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{Assistant Message}}" }] } + ] + } + }, + { + "id": "h3qetbhcpxhawnqoymo0v3hw", + "type": "choice input", + "items": [ + { + "id": "zaylo8bstqx0wp6bpdbd1rak", + "outgoingEdgeId": "q6o0cbyzxtvgls3jtz7rpdgw", + "content": "Continue" + }, + { + "id": "d5jv3sjpzobsrnhcp055mxkv", + "outgoingEdgeId": "xjv7pkpgpwh169448t8pepg4", + "content": "Back to menu" + } + ] + } + ] + }, + { + "id": "csbysu8dr08zxr4i6hzvzjdf", + "title": "Copywriter AI reply", + "graphCoordinates": { "x": 1055.63, "y": 436.9 }, + "blocks": [ + { + "id": "w2y6tl8mggplu8vsc9hu2080", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "user", + "content": "I want you to act as a copywriter. You will come up with copywriting advices that are engaging, imaginative, and captivating for the audience." + }, + { + "role": "Dialogue", + "dialogueVariableId": "vu9adij5penetej2xz89htfe6" + } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "usolgxcte60rin18ccygzbdu", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{Assistant Message}}" + } + }, + { + "id": "h96lile0evtqa0jx24gmfo25", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{Assistant Message}}" }] } + ] + } + }, + { + "id": "u4jdl0gwv8965o2etxjk12w0", + "type": "choice input", + "items": [ + { + "id": "b6zif4xxe2cuiddc2oqayaxi", + "outgoingEdgeId": "jwydpoxngp2gvwanaruphe6s", + "content": "Continue" + }, + { + "id": "ooib3mqlfkazta6iol1ocloe", + "outgoingEdgeId": "gfrpgowch879p1qaj9jzsh01", + "content": "Back to menu" + } + ] + } + ] + }, + { + "id": "u6nm47oyneidmsebszp60t0m", + "title": "Menu", + "graphCoordinates": { "x": -6.082566623728974, "y": 37.78518756228981 }, + "blocks": [ + { + "id": "rzlhl61q6dmh8n93usvqgyij", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Empty" + } + }, + { + "id": "gphm5wy1md9cunwkdtbzg6nq", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Who would you want to talk to?" }] + } + ] + } + }, + { + "id": "ohh19koa7up0nbke3146hnjp", + "type": "choice input", + "items": [ + { + "id": "rn0lqz1wvsg9lmc0jcl6ps8j", + "outgoingEdgeId": "ry7l8wcaidxw5izm7zoy83kj", + "content": "English professor" + }, + { + "id": "le84cls9vkmrxquvqw8bhp7h", + "outgoingEdgeId": "iy2htkuup0l908fsosg6d2qz", + "content": "Copywriter" + }, + { + "id": "mx4kgfgena53mxf87piwu1j2", + "outgoingEdgeId": "kmex71jzzzekni4louuy3xbf", + "content": "Concept explainer" + } + ], + "options": { "variableId": "vs7wwz29yyd21pfl4syeptdgi" } + } + ] + }, + { + "id": "oemwa82xy3yt74gzilrojogl", + "title": "Jumps", + "graphCoordinates": { "x": 1431.381871940994, "y": 1083.626261828848 }, + "blocks": [ + { + "id": "nnzp5mle206cl3nnqlkqjau1", + "type": "Jump", + "options": { "groupId": "irnu2zu8m2i4fu6485hxtra5" } + }, + { + "id": "nm6vp6ifbjq7mttohwhibjvj", + "type": "Jump", + "options": { "groupId": "u6nm47oyneidmsebszp60t0m" } + } + ] + }, + { + "id": "p1fh0e2y8sq4lhrskc4rb5z2", + "title": "Jumps", + "graphCoordinates": { "x": 1436.545931193238, "y": 679.7247165284323 }, + "blocks": [ + { + "id": "kyuvkruakbxjvxwgtjqti3gc", + "type": "Jump", + "options": { "groupId": "h4mcrr5x6lvy1mz96k0ey3do" } + }, + { + "id": "vywm4h8yz87ew4gjy4l6nmm3", + "type": "Jump", + "options": { "groupId": "u6nm47oyneidmsebszp60t0m" } + } + ] + }, + { + "id": "ow2g8fv93xxrgpcabnx8uod8", + "title": "Jumps", + "graphCoordinates": { "x": 1419.568721793131, "y": 169.5335644029076 }, + "blocks": [ + { + "id": "qxgl1cscs38pfwzaj4pqsd46", + "type": "Jump", + "options": { "groupId": "m84gejzvl08ky6ynruiuszpc" } + }, + { + "id": "m94q879l9yr1vx5xrbxlsj6q", + "type": "Jump", + "options": { "groupId": "u6nm47oyneidmsebszp60t0m" } + } + ] + }, + { + "id": "py719ungczkgz5f40zkw3tr2", + "title": "EN professor intro", + "graphCoordinates": { "x": 339.814926172369, "y": 9.945652574763692 }, + "blocks": [ + { + "id": "qm3v36qb93ijnghdjgy9mcwf", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hi 👋" }] }] + } + }, + { + "id": "ln8d3vdq4shclzrxcy9rmxfg", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "I can help you translate things and perfect your English." + } + ] + } + ] + } + }, + { + "id": "r7yu488ugfif8hxy3e4sospb", + "outgoingEdgeId": "ripf74t9yicdze8xr2yrklyx", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How can I help?" }] } + ] + } + } + ] + }, + { + "id": "uyry49c9bm1pvk6t8i471l2d", + "title": "Copywriter intro", + "graphCoordinates": { "x": 335.3081238025464, "y": 468.3681191076254 }, + "blocks": [ + { + "id": "bbeedootn9m8eass0mqu3w4t", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hi 👋" }] }] + } + }, + { + "id": "chdghb0k27c4okwu9yky4ox4", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "I'm an expert in copywriting." }] + } + ] + } + }, + { + "id": "idp7w8c8zbkvl95oa1vquiml", + "outgoingEdgeId": "v0tfmbt8tpwwrieftvzg8lti", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How can I help?" }] } + ] + } + } + ] + }, + { + "id": "zfa8oj0a0tnlho9a67llulst", + "title": "Explainer intro", + "graphCoordinates": { "x": 326.9849960884654, "y": 928.6632806049557 }, + "blocks": [ + { + "id": "n96j3pf3m87aufcapx2ulr2n", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hi 👋" }] }] + } + }, + { + "id": "wxk5z9yyiojkk9u3b5m6shax", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "I can explain concept with very simple terms." } + ] + } + ] + } + }, + { + "id": "ileqgg2r2kyh2zovpivr775s", + "outgoingEdgeId": "v5bki4h7m1lnryhgzudnvvpx", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "What concept would you like me to explain?" } + ] + } + ] + } + } + ] + }, + { + "id": "m84gejzvl08ky6ynruiuszpc", + "title": "EN professor question", + "graphCoordinates": { "x": 692.86, "y": -14.84 }, + "blocks": [ + { + "id": "ovgk70u0kfxrbtz9dy4e040o", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your answer...", + "button": "Send" + }, + "variableId": "vevnx5f5bojz0sv648x6ppcmv", + "isLong": true + } + }, + { + "id": "nx6v1ogcp9x9o6regjopvff8", + "outgoingEdgeId": "cplyootzgqo5jpmhntgz4shm", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{User Message}}" + } + } + ] + }, + { + "id": "h4mcrr5x6lvy1mz96k0ey3do", + "title": "Copywriter question", + "graphCoordinates": { "x": 692.3449852228088, "y": 462.3858990822391 }, + "blocks": [ + { + "id": "emii43mtihiuy35gpp6b91d8", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your answer...", + "button": "Send" + }, + "variableId": "vevnx5f5bojz0sv648x6ppcmv", + "isLong": true + } + }, + { + "id": "h0cgmv6q61s3yhuq6u2pb5p0", + "outgoingEdgeId": "za1pwdunrlwgfu1kz7dnsb3m", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{User Message}}" + } + } + ] + }, + { + "id": "irnu2zu8m2i4fu6485hxtra5", + "title": "Explainer question", + "graphCoordinates": { "x": 686.3012488543691, "y": 924.2085365228105 }, + "blocks": [ + { + "id": "e6rovxwxlizr54iy8nyi84pi", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your answer...", + "button": "Send" + }, + "variableId": "vevnx5f5bojz0sv648x6ppcmv", + "isLong": false + } + }, + { + "id": "b937909x86r3wzbn4mzxmw25", + "outgoingEdgeId": "fz77htstfb4jig82k66pl0vt", + "type": "Set variable", + "options": { + "variableId": "vu9adij5penetej2xz89htfe6", + "type": "Append value(s)", + "item": "{{User Message}}" + } + } + ] + } + ], + "edges": [ + { + "id": "ny44r5sp69gne7obgshidhph", + "from": { + "blockId": "jz9mklagfikyukzs7n3kmlcf", + "itemId": "imx7otsonvm0takr02b4ulyo" + }, + "to": { + "groupId": "oemwa82xy3yt74gzilrojogl", + "blockId": "nm6vp6ifbjq7mttohwhibjvj" + } + }, + { + "id": "mxl8lftsj3pbmj4g24ymxajo", + "from": { + "blockId": "jz9mklagfikyukzs7n3kmlcf", + "itemId": "x18iwzwmbzi9jjpnwij1861i" + }, + "to": { + "groupId": "oemwa82xy3yt74gzilrojogl", + "blockId": "nnzp5mle206cl3nnqlkqjau1" + } + }, + { + "id": "ry7l8wcaidxw5izm7zoy83kj", + "from": { + "blockId": "ohh19koa7up0nbke3146hnjp", + "itemId": "rn0lqz1wvsg9lmc0jcl6ps8j" + }, + "to": { "groupId": "py719ungczkgz5f40zkw3tr2" } + }, + { + "id": "ripf74t9yicdze8xr2yrklyx", + "from": { "blockId": "r7yu488ugfif8hxy3e4sospb" }, + "to": { "groupId": "m84gejzvl08ky6ynruiuszpc" } + }, + { + "id": "q6o0cbyzxtvgls3jtz7rpdgw", + "from": { + "blockId": "h3qetbhcpxhawnqoymo0v3hw", + "itemId": "zaylo8bstqx0wp6bpdbd1rak" + }, + "to": { + "groupId": "ow2g8fv93xxrgpcabnx8uod8", + "blockId": "qxgl1cscs38pfwzaj4pqsd46" + } + }, + { + "id": "xjv7pkpgpwh169448t8pepg4", + "from": { + "blockId": "h3qetbhcpxhawnqoymo0v3hw", + "itemId": "d5jv3sjpzobsrnhcp055mxkv" + }, + "to": { + "groupId": "ow2g8fv93xxrgpcabnx8uod8", + "blockId": "m94q879l9yr1vx5xrbxlsj6q" + } + }, + { + "id": "v0tfmbt8tpwwrieftvzg8lti", + "from": { "blockId": "idp7w8c8zbkvl95oa1vquiml" }, + "to": { "groupId": "h4mcrr5x6lvy1mz96k0ey3do" } + }, + { + "id": "iy2htkuup0l908fsosg6d2qz", + "from": { + "blockId": "ohh19koa7up0nbke3146hnjp", + "itemId": "le84cls9vkmrxquvqw8bhp7h" + }, + "to": { "groupId": "uyry49c9bm1pvk6t8i471l2d" } + }, + { + "id": "kmex71jzzzekni4louuy3xbf", + "from": { + "blockId": "ohh19koa7up0nbke3146hnjp", + "itemId": "mx4kgfgena53mxf87piwu1j2" + }, + "to": { "groupId": "zfa8oj0a0tnlho9a67llulst" } + }, + { + "id": "v5bki4h7m1lnryhgzudnvvpx", + "from": { "blockId": "ileqgg2r2kyh2zovpivr775s" }, + "to": { "groupId": "irnu2zu8m2i4fu6485hxtra5" } + }, + { + "id": "gfrpgowch879p1qaj9jzsh01", + "from": { + "blockId": "u4jdl0gwv8965o2etxjk12w0", + "itemId": "ooib3mqlfkazta6iol1ocloe" + }, + "to": { + "groupId": "p1fh0e2y8sq4lhrskc4rb5z2", + "blockId": "vywm4h8yz87ew4gjy4l6nmm3" + } + }, + { + "id": "jwydpoxngp2gvwanaruphe6s", + "from": { + "blockId": "u4jdl0gwv8965o2etxjk12w0", + "itemId": "b6zif4xxe2cuiddc2oqayaxi" + }, + "to": { + "groupId": "p1fh0e2y8sq4lhrskc4rb5z2", + "blockId": "kyuvkruakbxjvxwgtjqti3gc" + } + }, + { + "id": "cplyootzgqo5jpmhntgz4shm", + "from": { "blockId": "nx6v1ogcp9x9o6regjopvff8" }, + "to": { "groupId": "fj5z2nx488htv0843kq6qeyk" } + }, + { + "id": "za1pwdunrlwgfu1kz7dnsb3m", + "from": { "blockId": "h0cgmv6q61s3yhuq6u2pb5p0" }, + "to": { "groupId": "csbysu8dr08zxr4i6hzvzjdf" } + }, + { + "id": "fz77htstfb4jig82k66pl0vt", + "from": { "blockId": "b937909x86r3wzbn4mzxmw25" }, + "to": { "groupId": "dmg57mgick51p8l5pnyqtyf9" } + }, + { + "from": { "eventId": "w99qhdr20tw02sfrfwkfc1tg" }, + "to": { "groupId": "bofjp88arodr4k0btv2esyqy" }, + "id": "k5bj58emklqfqv3hemko4u23" + } + ], + "variables": [ + { "id": "vni6kwbch8zlq92dclgcivzyr", "name": "Assistant Message" }, + { "id": "vevnx5f5bojz0sv648x6ppcmv", "name": "User Message" }, + { "id": "vu9adij5penetej2xz89htfe6", "name": "Chat history" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-12-02T09:15:31.652Z", + "updatedAt": "2023-12-02T09:18:34.891Z", + "icon": "🎭", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/customer-support.json b/apps/builder/public/templates/customer-support.json new file mode 100644 index 0000000..e4190ec --- /dev/null +++ b/apps/builder/public/templates/customer-support.json @@ -0,0 +1,345 @@ +{ + "version": "6", + "id": "cloo046v300051aorhtv76f0i", + "name": "Customer Support", + "events": [ + { + "id": "uG1tt8JdDyu2nju3oJ4wc1", + "outgoingEdgeId": "2dzxChB1qm9WGfzNF91tfg", + "graphCoordinates": { "x": -281, "y": -89 }, + "type": "start" + } + ], + "groups": [ + { + "id": "vLUAPaxKwPF49iZhg4XZYa", + "title": "Menu", + "graphCoordinates": { "x": -28.4, "y": -88.19 }, + "blocks": [ + { + "id": "spud6U3K1omh2dZG8yN2CW4", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Hey friend 👋" }] }, + { "type": "p", "children": [{ "text": "How can I help you?" }] } + ] + } + }, + { + "id": "s6kp2Z4igeY3kL7B64qBdUg", + "type": "choice input", + "items": [ + { + "id": "fQ8oLDnKmDBuPDK7riJ2kt", + "outgoingEdgeId": "dhniFxrsH5r54aEE5JXwK2", + "content": "I have a feature request ✨" + }, + { + "id": "h2rFDX2UnKS4Kdu3Eyuqq3", + "outgoingEdgeId": "2C4mhU5o2Hdm7dztR9xNE9", + "content": "There is a bug 🐛" + }, + { + "id": "hcUFBPeQA3gSyXRprRk2v9", + "outgoingEdgeId": "bTo6CZD1YapDDyVdvJgFDV", + "content": "I have a question 💭" + } + ] + } + ] + }, + { + "id": "7MuqF6nen1ZTwGB53Mz8VY", + "title": "Bug", + "graphCoordinates": { "x": 364.46, "y": 92.39 }, + "blocks": [ + { + "id": "sjsECyfSBMkUnoWaEnBTmJX", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Shoot! 🤪" }] }] + } + }, + { + "id": "seomQsnPWgiMzQVeZ3us7x2", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Can you describe the bug with as many details as possible?" + } + ] + } + ] + } + }, + { + "id": "s3LYyyYtjdQ88jkMMV5DSW7", + "outgoingEdgeId": "cl1571jhh00022e6dk77f52wg", + "type": "text input", + "options": { + "labels": { + "placeholder": "Describe the bug..." + }, + "variableId": "v51BcuecnB6kRU1tsttaGyR", + "isLong": true + } + } + ] + }, + { + "id": "kyK8JQ77NodUYaz3JLS88A", + "title": "Feature request", + "graphCoordinates": { "x": 364.36, "y": -517.93 }, + "blocks": [ + { + "id": "s9bgHcWdobb8Z5cTbrnTz6R", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Awesome!" }] }] + } + }, + { + "id": "s2NbNaBGKhMvdEUdVPXKZjy", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Head up to the feedback board." }] + }, + { "type": "p", "children": [{ "text": "" }] }, + { + "type": "p", + "children": [ + { "text": "👉 " }, + { + "url": "https://app.typebot.io/feedback", + "type": "a", + "children": [{ "text": "https://app.typebot.io/feedback" }] + }, + { "text": "" } + ] + }, + { "type": "p", "children": [{ "text": "" }] }, + { + "type": "p", + "children": [ + { + "text": "There, you'll be able to check existing feature requests and submit yours if it's missing 💪" + } + ] + } + ] + } + }, + { + "id": "cl16lb3b300092e6dh4h01vxw", + "type": "choice input", + "items": [{ "id": "cl16lb3b3000a2e6dy8zdhzpz", "content": "Restart" }] + }, + { + "id": "j08qxg0h804rngfroedblt5f", + "type": "Jump", + "options": { "groupId": "vLUAPaxKwPF49iZhg4XZYa" } + } + ] + }, + { + "id": "puWCBhGWSQRbqTkVH89RCf", + "title": "Question", + "graphCoordinates": { "x": 365.4, "y": 491.3 }, + "blocks": [ + { + "id": "sm4iHhLQs9yNdRG3b7xqV8Y", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "First, don't forget to check out the " }, + { + "url": "https://docs.typebot.io/", + "type": "a", + "children": [{ "text": "Documentation 🙏" }] + } + ] + } + ] + } + }, + { + "id": "sreX6rwMevEmbTpnkGCtp3k", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Otherwise, I'm all ears!" }] + } + ] + } + }, + { + "id": "so4GiKFWWjKCjXgmMJYCGbe", + "type": "image", + "content": { + "url": "https://media0.giphy.com/media/rhgwg4qBu97ISgbfni/giphy-downsized.gif?cid=fe3852a3wimy48e55djt23j44uto7gdlu8ksytylafisvr0q&rid=giphy-downsized.gif&ct=g" + } + }, + { + "id": "sjd4qACugMarB7gJC8nMhb3", + "outgoingEdgeId": "cl1571ktd00032e6dyti22850", + "type": "text input", + "options": { + "variableId": "v51BcuecnB6kRU1tsttaGyR", + "isLong": true + } + } + ] + }, + { + "id": "1GvxCAAEysxJMxrVngud3X", + "title": "Bye", + "graphCoordinates": { "x": 1115.81, "y": 728.71 }, + "blocks": [ + { + "id": "s6uLw72EAKbACrpYHr7DSyY", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Thank you so much for your submission 💙" } + ] + } + ] + } + }, + { + "id": "stM7cTBFCLhpQagRHT64K6u", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "I'll get back to you ASAP (usually within 24 hours)" + } + ] + } + ] + } + }, + { + "id": "s4JATFkBxzmcqqEKQB2xFfa", + "type": "choice input", + "items": [{ "id": "jqm8wZa5yYb73493n5s3Uc", "content": "Restart" }] + }, + { + "id": "igdnc34rcmiyamazghr8s708", + "type": "Jump", + "options": { "groupId": "vLUAPaxKwPF49iZhg4XZYa" } + } + ] + }, + { + "id": "wncvzVDFJDvhh1M3CXJ6aL", + "title": "Email", + "graphCoordinates": { "x": 746.29, "y": 577.22 }, + "blocks": [ + { + "id": "soiDpBL5r1dbvHxuT2Sd3mH", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "On which email can I contact you?" }] + } + ] + } + }, + { + "id": "s5Fh7zHUw3j4zDM5xjzwsXB", + "outgoingEdgeId": "cl1571xtc00042e6dcptam5jw", + "type": "email input", + "options": { + "variableId": "t2k6cj3uYfNdJX13APA4b9" + } + } + ] + } + ], + "edges": [ + { + "id": "2dzxChB1qm9WGfzNF91tfg", + "from": { "eventId": "uG1tt8JdDyu2nju3oJ4wc1" }, + "to": { "groupId": "vLUAPaxKwPF49iZhg4XZYa" } + }, + { + "id": "dhniFxrsH5r54aEE5JXwK2", + "from": { + "blockId": "s6kp2Z4igeY3kL7B64qBdUg", + "itemId": "fQ8oLDnKmDBuPDK7riJ2kt" + }, + "to": { "groupId": "kyK8JQ77NodUYaz3JLS88A" } + }, + { + "id": "2C4mhU5o2Hdm7dztR9xNE9", + "from": { + "blockId": "s6kp2Z4igeY3kL7B64qBdUg", + "itemId": "h2rFDX2UnKS4Kdu3Eyuqq3" + }, + "to": { "groupId": "7MuqF6nen1ZTwGB53Mz8VY" } + }, + { + "id": "bTo6CZD1YapDDyVdvJgFDV", + "from": { + "blockId": "s6kp2Z4igeY3kL7B64qBdUg", + "itemId": "hcUFBPeQA3gSyXRprRk2v9" + }, + "to": { "groupId": "puWCBhGWSQRbqTkVH89RCf" } + }, + { + "id": "cl1571jhh00022e6dk77f52wg", + "from": { "blockId": "s3LYyyYtjdQ88jkMMV5DSW7" }, + "to": { "groupId": "wncvzVDFJDvhh1M3CXJ6aL" } + }, + { + "id": "cl1571ktd00032e6dyti22850", + "from": { "blockId": "sjd4qACugMarB7gJC8nMhb3" }, + "to": { "groupId": "wncvzVDFJDvhh1M3CXJ6aL" } + }, + { + "id": "cl1571xtc00042e6dcptam5jw", + "from": { "blockId": "s5Fh7zHUw3j4zDM5xjzwsXB" }, + "to": { "groupId": "1GvxCAAEysxJMxrVngud3X" } + } + ], + "variables": [ + { "id": "t2k6cj3uYfNdJX13APA4b9", "name": "Email" }, + { "id": "v51BcuecnB6kRU1tsttaGyR", "name": "Content" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:20:05.823Z", + "updatedAt": "2023-11-07T07:24:28.824Z", + "icon": "😍", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/digital-product-payment.json b/apps/builder/public/templates/digital-product-payment.json new file mode 100644 index 0000000..340dbcd --- /dev/null +++ b/apps/builder/public/templates/digital-product-payment.json @@ -0,0 +1,418 @@ +{ + "version": "6", + "id": "cloo0oket000d1aortnxzuslp", + "name": "Digital Product Payment", + "events": [ + { + "id": "cl3u43cht00044z1adg20ffni", + "outgoingEdgeId": "cl3u448z200062e6gr653itny", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "cl3u4431400042e6go5nd0euq", + "title": "Name", + "graphCoordinates": { "x": 257.86, "y": 0.85 }, + "blocks": [ + { + "id": "cl3u4431500052e6gruhlxklx", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Hi there 👋" }] } + ] + } + }, + { + "id": "cl3u4592z00082e6go92cuu43", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your name?" }] } + ] + } + }, + { + "id": "cl3u45f0n000a2e6gci2xgmph", + "outgoingEdgeId": "cl3u45j0n000c2e6go4nnaavg", + "type": "text input", + "options": { + "labels": { "placeholder": "Type your name..." }, + "variableId": "vcl3u45hek000b2e6gkl05z1da" + } + } + ] + }, + { + "id": "cl3u45dib00092e6g4q2tdkpu", + "title": "Product demo", + "graphCoordinates": { "x": 613.7, "y": 1.82 }, + "blocks": [ + { + "id": "cl3u45lqz000d2e6gxo4n5ets", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Cool, nice to meet you {{Name}}" }] + } + ] + } + }, + { + "id": "cl3u44adg00072e6gc13e1n12", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "I've been working on a Notion template for the last 3 months to help you Grow your business." + } + ] + } + ] + } + }, + { + "id": "cl3u46b0i000e2e6gkpf4qiry", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "It is based on the Bullseye Growth Framework" } + ] + } + ] + } + }, + { + "id": "cl3u49lmg000f2e6guhhgf825", + "type": "video", + "content": { + "url": "https://typebot.s3.eu-west-3.amazonaws.com/assets/bullseye+template+preview.mp4", + "type": "url" + } + }, + { + "id": "cl3u4hyl9000i2e6gtdz8m04b", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "It's yours for $9" }] } + ] + } + }, + { + "id": "cl3u4hyl9000i2e6gtdz8m04a", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Are you interested in receive a copy of this template?" + } + ] + } + ] + } + }, + { + "id": "cl3u4id67000l2e6gahw4v1ny", + "type": "choice input", + "items": [ + { + "id": "cl3u4id67000m2e6g3x3do8kd", + "outgoingEdgeId": "cl3u4l4do00102e6ghd9s5p3f", + "content": "Hell yes!" + }, + { + "id": "cl3u4iexy000o2e6gbagmrxcc", + "outgoingEdgeId": "cl3u4jxq2000v2e6gkpwko0uo", + "content": "I'm ok, thanks." + } + ] + } + ] + }, + { + "id": "cl3u4iw28000s2e6gdmukl6qb", + "title": "Bye", + "graphCoordinates": { "x": 795.34, "y": 877.43 }, + "blocks": [ + { + "id": "cl3u4iw29000t2e6gakbxvz4u", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Oh ok, feel free to come back when you feel ready {{Name}}!" + } + ] + } + ] + } + }, + { + "id": "cl3u4jcyt000u2e6gzyj2p5ss", + "type": "image", + "content": { + "url": "https://media3.giphy.com/media/48FhEMYGWji8/giphy.gif?cid=fe3852a32dqdmhdazal2zzctxpxukjx171k0e4eflp0w36jf&rid=giphy.gif&ct=g" + } + } + ] + }, + { + "id": "cl3u4kblb000w2e6gfflsq56p", + "title": "Email", + "graphCoordinates": { "x": 992.42, "y": 342.36 }, + "blocks": [ + { + "id": "cl3u4kblb000x2e6g49rot8h0", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "That's awesome!" }] } + ] + } + }, + { + "id": "cl3u4khsx000y2e6gx9iysgt4", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "What's the email address where you want to receive the link?" + } + ] + } + ] + } + }, + { + "id": "cl3u4l2et000z2e6gjlmh45jp", + "outgoingEdgeId": "dstr8midu9f0x6ylyet7dljw", + "type": "email input", + "options": { + "variableId": "vcl3u4n1vk00162e6gs6x59o2k" + } + } + ] + }, + { + "id": "cl3u4leig00112e6gxbk65r7y", + "title": "Payment", + "graphCoordinates": { "x": 1338.38, "y": 343.48 }, + "blocks": [ + { + "id": "cl3u4leig00122e6gqx7skfhb", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Sounds good." }] } + ] + } + }, + { + "id": "cl3u4llj300132e6gciw2ivyv", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You're a step away from implementing proven growth systems to your business 🚀" + } + ] + } + ] + } + }, + { + "id": "cl3u4mjq900152e6grwyg90zt", + "outgoingEdgeId": "cl3u4wynv001b2e6g6pxc7int", + "type": "payment input", + "options": { + "additionalInformation": { + "name": "{{Name}}", + "email": "{{Email}}" + }, + "amount": "9" + } + } + ] + }, + { + "id": "cl3u4vnth00182e6g2hh0gewl", + "title": "Send email", + "graphCoordinates": { "x": 1683.86, "y": 346.93 }, + "blocks": [ + { + "id": "cl3u4wi2d001a2e6gznp1r9d4", + "type": "image", + "content": { + "url": "https://media1.giphy.com/media/s2qXK8wAvkHTO/giphy.gif?cid=fe3852a3edx7hsbquhw3lu17c422yzc6wsiplnpn02rzm2kf&rid=giphy.gif&ct=g" + } + }, + { + "id": "cl3u4xcqc001c2e6g355vnigh", + "type": "Email", + "options": { + "isCustomBody": true, + "recipients": ["{{Email}}"], + "subject": "Here is your Bullseye Framework template 🎉", + "body": "Hey {{Name}},\n\nThank you again for buying the template.\n\nHere is the link where you can duplicate it:\n\nhttps://baptistearno.notion.site/Growth-Framework-Bullseye-c2166e03d99340daa1aa87e4356bdc83\n\nFeel free to tell me what I can improve.\n\nBaptiste." + } + }, + { + "id": "cl3u5189q001d2e6gd1q7qshq", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "It's all good, you should have received the email!" + } + ] + } + ] + } + }, + { + "id": "cl3u51mpe001e2e6ggrjjzxek", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Thanks again for your visit." }] + } + ] + } + }, + { + "id": "cl3u51z0o001f2e6gbl96p7bi", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Bye 👋" }] }] + } + } + ] + }, + { + "id": "i47yu1c1pjhsqoe68kktbxgl", + "title": "", + "graphCoordinates": { "x": 1336.77, "y": 43.66 }, + "blocks": [ + { + "id": "unw1076x8ematnu6jrbop8sv", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your Stripe credentials in the next Payment block." + } + ] + } + ] + } + }, + { + "id": "ck19ttflkp6mbxnxpnyxp7vh", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, you can remove this group and connect the email input to the \"Payment\" group 🪄" + } + ] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "cl3u448z200062e6gr653itny", + "from": { "eventId": "cl3u43cht00044z1adg20ffni" }, + "to": { "groupId": "cl3u4431400042e6go5nd0euq" } + }, + { + "id": "cl3u45j0n000c2e6go4nnaavg", + "from": { "blockId": "cl3u45f0n000a2e6gci2xgmph" }, + "to": { "groupId": "cl3u45dib00092e6g4q2tdkpu" } + }, + { + "id": "cl3u4jxq2000v2e6gkpwko0uo", + "from": { + "blockId": "cl3u4id67000l2e6gahw4v1ny", + "itemId": "cl3u4iexy000o2e6gbagmrxcc" + }, + "to": { "groupId": "cl3u4iw28000s2e6gdmukl6qb" } + }, + { + "id": "cl3u4l4do00102e6ghd9s5p3f", + "from": { + "blockId": "cl3u4id67000l2e6gahw4v1ny", + "itemId": "cl3u4id67000m2e6g3x3do8kd" + }, + "to": { "groupId": "cl3u4kblb000w2e6gfflsq56p" } + }, + { + "id": "cl3u4wynv001b2e6g6pxc7int", + "from": { "blockId": "cl3u4mjq900152e6grwyg90zt" }, + "to": { "groupId": "cl3u4vnth00182e6g2hh0gewl" } + }, + { + "from": { + "blockId": "cl3u4l2et000z2e6gjlmh45jp", + "groupId": "cl3u4kblb000w2e6gfflsq56p" + }, + "to": { "groupId": "i47yu1c1pjhsqoe68kktbxgl" }, + "id": "dstr8midu9f0x6ylyet7dljw" + } + ], + "variables": [ + { "id": "vcl3u45hek000b2e6gkl05z1da", "name": "Name" }, + { "id": "vcl3u4n1vk00162e6gs6x59o2k", "name": "Email" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:35:56.501Z", + "updatedAt": "2023-11-07T07:40:03.471Z", + "icon": "🖼️", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/dog-insurance-offer.json b/apps/builder/public/templates/dog-insurance-offer.json new file mode 100644 index 0000000..f9402ba --- /dev/null +++ b/apps/builder/public/templates/dog-insurance-offer.json @@ -0,0 +1,613 @@ +{ + "version": "6", + "id": "clonzza7600031aorlgsreya0", + "name": "Insurance offer", + "events": [ + { + "id": "f4ef28wxteh0wdjgubtojnkr", + "outgoingEdgeId": "u0009iy3sakdgh3k1x41i5yr", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "av0jzkh3qhgdyjrouvl2zywe", + "title": "Welcome", + "graphCoordinates": { "x": 68.4296875, "y": 176.178531769944 }, + "blocks": [ + { + "id": "y0iukpry1i6h8sv22gz4ffsg", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "0" + } + }, + { + "id": "wza92in5v03w0oiaa1y3k68x", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hey 👋" }] }] + } + }, + { + "id": "rhp6p4obkdehddhm6j7tqxe0", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "I'm John from Dogz" }] } + ] + } + }, + { + "id": "tizd6f2qo70g59lz1rnnvho7", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Let's determine what would be the best insurance offer you can have for your dog 🐶" + } + ] + } + ] + } + }, + { + "id": "dtvbio4qytr3iojc7tq2quvy", + "type": "choice input", + "items": [ + { + "id": "m7l8u4y5vmwozvdtsmhq3q49", + "outgoingEdgeId": "vl23l0ak8w2qxj9wrgxhznz3", + "content": "Let's go!" + } + ] + } + ] + }, + { + "id": "dh3wz001jaclg8ifc1vhovlq", + "title": "Breed", + "graphCoordinates": { "x": 431.756656769944, "y": 177.60546875 }, + "blocks": [ + { + "id": "mvdogpw4qucgot4yzabpxtcl", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What breed is your dog?" }] + } + ] + } + }, + { + "id": "f2902yy6o00fwe5h4xihrntj", + "outgoingEdgeId": "moj9ezfl6bvpr4aj76cztkiu", + "type": "choice input", + "items": [ + { "id": "q7ydcwda7rsfn1w5ep9ur4y3", "content": "Crossbreed" }, + { "id": "q33qu26t8uhtp63rl7th4p0u", "content": "Labrador" }, + { "id": "c9fy5o23cuanywze536ie071", "content": "Golden Retriever" }, + { "id": "xmozt619ao4pn3lcovs6e1wp", "content": "Jack Russel" }, + { "id": "qhc245vs9s3vhq8oz9sur4jy", "content": "Husky" }, + { "id": "bqt7o8aotn5wwye98vw2u8is", "content": "Other" } + ] + } + ] + }, + { + "id": "ynt0ya95bvuqj8mf39e938k4", + "title": "Sex", + "graphCoordinates": { "x": 786.06640625, "y": 173.0310202976334 }, + "blocks": [ + { + "id": "u4voz45sk9gh4khul8c519df", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Is it a male or a female?" }] + } + ] + } + }, + { + "id": "zuza6om08ubafgqhbadwv60i", + "type": "choice input", + "items": [ + { + "id": "mrca2ini7z81ik4k1o9g3a1s", + "outgoingEdgeId": "wciafstvwt3m4lhrejlgl0s0", + "content": "♂️ Male" + }, + { + "id": "ymxxgoxxbfcmnhudwmerfgbx", + "outgoingEdgeId": "f60ldz2g58kfkvsfmnf39fjb", + "content": "♀️ Female" + } + ] + } + ] + }, + { + "id": "c59xwfc18i4xjpaeu9dzrjcu", + "title": "", + "graphCoordinates": { "x": 1142.220231700246, "y": 145.316328962412 }, + "blocks": [ + { + "id": "meoptkjq8tupr3qkyqkpaxqq", + "type": "Set variable", + "options": { + "variableId": "vhl1s7qoksnw7r8b1soocxwsd", + "expressionToEvaluate": "he" + } + }, + { + "id": "kqbiaq87al2uq07vuno69syo", + "outgoingEdgeId": "to4im28nzrg3yk0ama07l2oz", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's his name?" }] } + ] + } + } + ] + }, + { + "id": "qzge99trjqvp7vjmjo6rk56o", + "title": "", + "graphCoordinates": { "x": 1140.34375, "y": 328.5390625 }, + "blocks": [ + { + "id": "jyi9t11totyrw2jeohfhvfw1", + "type": "Set variable", + "options": { + "variableId": "vhl1s7qoksnw7r8b1soocxwsd", + "expressionToEvaluate": "she" + } + }, + { + "id": "f9qyzjo67x7zen5q4xih3xv2", + "outgoingEdgeId": "c6x6fubn2qu5vvgfc6d14krl", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's her name?" }] } + ] + } + } + ] + }, + { + "id": "eq1tnkdfxxf8q08vxckl3md6", + "title": "Name", + "graphCoordinates": { "x": 1501.890625, "y": 169.65234375 }, + "blocks": [ + { + "id": "kxzi32ioxwqpdy9yy0ktoavu", + "outgoingEdgeId": "g4do01p1scej1trqlbidbrw1", + "type": "text input", + "options": { + "variableId": "vgl2m65vej3cjwqvkawnpih2l" + } + } + ] + }, + { + "id": "xgulc4hfxlmjmr288ghillwz", + "title": "Age", + "graphCoordinates": { "x": 1846.419374527324, "y": 168.0560932773236 }, + "blocks": [ + { + "id": "e61e41j7wdisp1yxlr78gjxs", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How cute 😊" }] } + ] + } + }, + { + "id": "ep4iqxpgalslj0blt71rglbv", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How old is {{Name}}?" }] } + ] + } + }, + { + "id": "y2fcko12ha5n9zjxickaakxt", + "type": "picture choice input", + "items": [ + { + "id": "vliolql8p4vo58pvsz7olf5w", + "outgoingEdgeId": "pehpu3fo38ofsgh6b9dli0i4", + "pictureSrc": "https://images.unsplash.com/photo-1592924728350-f7d4fd5d1655?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=Mnw0MjU2MDR8MHwxfHNlYXJjaHwxNXx8cHVwcHl8ZW58MHwwfHx8MTY4MzIyNDMxOA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Less than 1 year" + }, + { + "id": "b3ci3fpppgsu312gsl4hs6au", + "outgoingEdgeId": "ilvu55d6cmembesg0askzgzh", + "pictureSrc": "https://images.unsplash.com/photo-1672363340663-37526fffa24d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=Mnw0MjU2MDR8MHwxfHNlYXJjaHwxMHx8eW91bmclMjBkb2d8ZW58MHwwfHx8MTY4MzIyNDM0OA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "1-5 years" + }, + { + "id": "asi8dmhlwnysvm4tmvoipglz", + "outgoingEdgeId": "kvlz0ly8o4h99997ijiejwe8", + "pictureSrc": "https://images.unsplash.com/photo-1587300003388-59208cc962cb?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=Mnw0MjU2MDR8MHwxfHNlYXJjaHwzfHxkb2d8ZW58MHwwfHx8MTY4MzIyNDEwNg&ixlib=rb-4.0.3&q=80&w=1080", + "title": "5-10 years" + }, + { + "id": "w9eeiclycv7nm0ennaxbxo1d", + "outgoingEdgeId": "y8v7vkh236e4o4f2latpb7mr", + "pictureSrc": "https://images.unsplash.com/photo-1553531009-7e4b807a0673?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=Mnw0MjU2MDR8MHwxfHNlYXJjaHw4fHxvbGQlMjBkb2d8ZW58MHwwfHx8MTY4MzIyNDQxNw&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Above 10 years" + } + ] + } + ] + }, + { + "id": "s4cccw69brg5ipyakvsoaioo", + "title": "Spayed", + "graphCoordinates": { "x": 2535.586058093481, "y": 164.2060504876776 }, + "blocks": [ + { + "id": "zw0mfpqem8eib75qs5brnfnu", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Is {{Pronoun}} spayed or neutered" }] + } + ] + } + }, + { + "id": "w8l8qekmkjwdct0f73f64yke", + "type": "choice input", + "items": [ + { + "id": "njc0kol8iicj5xo06gezhl52", + "outgoingEdgeId": "bindxs5p6lbkszkuw7rhpvh1", + "content": "❌ No" + }, + { + "id": "jp5k0mx1drijt7k1v4a2z6t8", + "outgoingEdgeId": "igwjs895n7q48h47xhpc90wc", + "content": "✅ Yes" + } + ] + } + ] + }, + { + "id": "j19dlmdh2ojntwk1lzqemo7a", + "title": "Email", + "graphCoordinates": { "x": 2989.53096827949, "y": 367.6582890794456 }, + "blocks": [ + { + "id": "os3ecqb05r4todaekg0206t4", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Thank you for all this information." }] + } + ] + } + }, + { + "id": "v5sxfs35u83hqfsh9970flj7", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "We can provide the best insurance for {{Name}} 👍" + } + ] + } + ] + } + }, + { + "id": "sutyhv073mi6p80115jyu8s4", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "On what email should we send the offer?" } + ] + } + ] + } + }, + { + "id": "ouu081yxvf9raf522k08vr6g", + "outgoingEdgeId": "bw2ddpla0a4qggv8b7et3m12", + "type": "email input", + "options": { + "variableId": "vzhkagzjqqa0amfc78jekl2gz" + } + } + ] + }, + { + "id": "rly6ojrxf1oo4augnflhj0kj", + "title": "", + "graphCoordinates": { "x": 2186.904241629908, "y": 387.2160670995469 }, + "blocks": [ + { + "id": "cubvtqhhgvf6k9597von95bt", + "outgoingEdgeId": "wtbthu0nu61a6qijaranccfw", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "{{Estimated price}} + 5" + } + } + ] + }, + { + "id": "ggiqdlnnh0urjn8r5d0wip5u", + "title": "", + "graphCoordinates": { "x": 2892.884331508873, "y": 193.3583588107446 }, + "blocks": [ + { + "id": "ww4zmawu2jbvrykqwqq7fnh5", + "outgoingEdgeId": "kuh8vfaq0nazrtpkif9pzrpu", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "{{Estimated price}} + 20" + } + } + ] + }, + { + "id": "trjrsr2xpg0idmldl9pwcqry", + "title": "", + "graphCoordinates": { "x": 2187.765700621067, "y": 522.8303147750385 }, + "blocks": [ + { + "id": "gdujudl5bf90oayj6z96ghv8", + "outgoingEdgeId": "dvaakgyx7rteqs23qxz8uqx8", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "{{Estimated price}} + 10" + } + } + ] + }, + { + "id": "ykjr48s18zp8a0tiwik18mum", + "title": "", + "graphCoordinates": { "x": 2187.927544552159, "y": 661.0263366270658 }, + "blocks": [ + { + "id": "sevhy7y6pkbss80rph5blunn", + "outgoingEdgeId": "opipj5xi262umvn98kkga4tx", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "{{Estimated price}} + 25" + } + } + ] + }, + { + "id": "c1x4umwx2g4j39peylr9rfor", + "title": "", + "graphCoordinates": { "x": 2189.67995427391, "y": 796.4435670811636 }, + "blocks": [ + { + "id": "bw9d73ypbvc83ltqme9kwwzc", + "outgoingEdgeId": "ozsoiu70hbqp5pqucstlnh3b", + "type": "Set variable", + "options": { + "variableId": "vq61f8ykwadq1pj8389qf9h91", + "expressionToEvaluate": "{{Estimated price}} + 55" + } + } + ] + }, + { + "id": "lmrd5falh8nkdizqy9obpeqi", + "title": "Bye", + "graphCoordinates": { "x": 3340.474508360785, "y": 365.6627012838016 }, + "blocks": [ + { + "id": "ddpum0cjrd2bredvakte914k", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Perfect 👌" }] } + ] + } + }, + { + "id": "qabtk59h81p0fv14au584ay8", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "In the mean time feel free to check out what other services we are offering at Dogz" + } + ] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "u0009iy3sakdgh3k1x41i5yr", + "from": { "eventId": "f4ef28wxteh0wdjgubtojnkr" }, + "to": { "groupId": "av0jzkh3qhgdyjrouvl2zywe" } + }, + { + "id": "vl23l0ak8w2qxj9wrgxhznz3", + "from": { + "blockId": "dtvbio4qytr3iojc7tq2quvy", + "itemId": "m7l8u4y5vmwozvdtsmhq3q49" + }, + "to": { "groupId": "dh3wz001jaclg8ifc1vhovlq" } + }, + { + "id": "moj9ezfl6bvpr4aj76cztkiu", + "from": { "blockId": "f2902yy6o00fwe5h4xihrntj" }, + "to": { "groupId": "ynt0ya95bvuqj8mf39e938k4" } + }, + { + "id": "wciafstvwt3m4lhrejlgl0s0", + "from": { + "blockId": "zuza6om08ubafgqhbadwv60i", + "itemId": "mrca2ini7z81ik4k1o9g3a1s" + }, + "to": { "groupId": "c59xwfc18i4xjpaeu9dzrjcu" } + }, + { + "id": "f60ldz2g58kfkvsfmnf39fjb", + "from": { + "blockId": "zuza6om08ubafgqhbadwv60i", + "itemId": "ymxxgoxxbfcmnhudwmerfgbx" + }, + "to": { "groupId": "qzge99trjqvp7vjmjo6rk56o" } + }, + { + "id": "to4im28nzrg3yk0ama07l2oz", + "from": { "blockId": "kqbiaq87al2uq07vuno69syo" }, + "to": { "groupId": "eq1tnkdfxxf8q08vxckl3md6" } + }, + { + "id": "c6x6fubn2qu5vvgfc6d14krl", + "from": { "blockId": "f9qyzjo67x7zen5q4xih3xv2" }, + "to": { "groupId": "eq1tnkdfxxf8q08vxckl3md6" } + }, + { + "id": "g4do01p1scej1trqlbidbrw1", + "from": { "blockId": "kxzi32ioxwqpdy9yy0ktoavu" }, + "to": { "groupId": "xgulc4hfxlmjmr288ghillwz" } + }, + { + "id": "pehpu3fo38ofsgh6b9dli0i4", + "from": { + "blockId": "y2fcko12ha5n9zjxickaakxt", + "itemId": "vliolql8p4vo58pvsz7olf5w" + }, + "to": { "groupId": "rly6ojrxf1oo4augnflhj0kj" } + }, + { + "id": "ilvu55d6cmembesg0askzgzh", + "from": { + "blockId": "y2fcko12ha5n9zjxickaakxt", + "itemId": "b3ci3fpppgsu312gsl4hs6au" + }, + "to": { "groupId": "trjrsr2xpg0idmldl9pwcqry" } + }, + { + "id": "kvlz0ly8o4h99997ijiejwe8", + "from": { + "blockId": "y2fcko12ha5n9zjxickaakxt", + "itemId": "asi8dmhlwnysvm4tmvoipglz" + }, + "to": { "groupId": "ykjr48s18zp8a0tiwik18mum" } + }, + { + "id": "y8v7vkh236e4o4f2latpb7mr", + "from": { + "blockId": "y2fcko12ha5n9zjxickaakxt", + "itemId": "w9eeiclycv7nm0ennaxbxo1d" + }, + "to": { "groupId": "c1x4umwx2g4j39peylr9rfor" } + }, + { + "id": "wtbthu0nu61a6qijaranccfw", + "from": { "blockId": "cubvtqhhgvf6k9597von95bt" }, + "to": { "groupId": "s4cccw69brg5ipyakvsoaioo" } + }, + { + "id": "dvaakgyx7rteqs23qxz8uqx8", + "from": { "blockId": "gdujudl5bf90oayj6z96ghv8" }, + "to": { "groupId": "s4cccw69brg5ipyakvsoaioo" } + }, + { + "id": "opipj5xi262umvn98kkga4tx", + "from": { "blockId": "sevhy7y6pkbss80rph5blunn" }, + "to": { "groupId": "s4cccw69brg5ipyakvsoaioo" } + }, + { + "id": "ozsoiu70hbqp5pqucstlnh3b", + "from": { "blockId": "bw9d73ypbvc83ltqme9kwwzc" }, + "to": { "groupId": "s4cccw69brg5ipyakvsoaioo" } + }, + { + "id": "bindxs5p6lbkszkuw7rhpvh1", + "from": { + "blockId": "w8l8qekmkjwdct0f73f64yke", + "itemId": "njc0kol8iicj5xo06gezhl52" + }, + "to": { "groupId": "ggiqdlnnh0urjn8r5d0wip5u" } + }, + { + "id": "igwjs895n7q48h47xhpc90wc", + "from": { + "blockId": "w8l8qekmkjwdct0f73f64yke", + "itemId": "jp5k0mx1drijt7k1v4a2z6t8" + }, + "to": { "groupId": "j19dlmdh2ojntwk1lzqemo7a" } + }, + { + "id": "kuh8vfaq0nazrtpkif9pzrpu", + "from": { "blockId": "ww4zmawu2jbvrykqwqq7fnh5" }, + "to": { "groupId": "j19dlmdh2ojntwk1lzqemo7a" } + }, + { + "id": "bw2ddpla0a4qggv8b7et3m12", + "from": { "blockId": "ouu081yxvf9raf522k08vr6g" }, + "to": { "groupId": "lmrd5falh8nkdizqy9obpeqi" } + } + ], + "variables": [ + { "id": "vgl2m65vej3cjwqvkawnpih2l", "name": "Name" }, + { "id": "vhl1s7qoksnw7r8b1soocxwsd", "name": "Pronoun" }, + { "id": "vq61f8ykwadq1pj8389qf9h91", "name": "Estimated price" }, + { "id": "vzhkagzjqqa0amfc78jekl2gz", "name": "Email" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:16:16.866Z", + "updatedAt": "2023-11-07T07:16:16.866Z", + "icon": "🐶", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/faq.json b/apps/builder/public/templates/faq.json new file mode 100644 index 0000000..f9b320b --- /dev/null +++ b/apps/builder/public/templates/faq.json @@ -0,0 +1,455 @@ +{ + "version": "6", + "id": "cloo0iymj000b1aoraoto4iom", + "name": "FAQ", + "events": [ + { + "id": "cl96ns7za000309kyewk56s22", + "outgoingEdgeId": "cl96nv0ij00093b6id4t83dvu", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "cl96ns9qr00043b6ii07bo25o", + "title": "Menu", + "graphCoordinates": { "x": 385.68, "y": 86.92 }, + "blocks": [ + { + "id": "cl96ns9qr00053b6igebgtl5q", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "If you have a question about our product, you're in the right place 😊" + } + ] + } + ] + } + }, + { + "id": "cl96nv877000b3b6i7p69ss2o", + "type": "choice input", + "items": [ + { + "id": "cl96nv877000c3b6idyepv694", + "outgoingEdgeId": "cl96o2u6h000t3b6izmh4pguj", + "content": "What's Analyzr?" + }, + { + "id": "cl96nvcwi000d3b6ipyfzcyaw", + "outgoingEdgeId": "cl96o6hxh00173b6ix83nn581", + "content": "Can I use your tool for free?" + }, + { + "id": "cl96obwgy001k3b6ir1a8qk5w", + "outgoingEdgeId": "cl96ofn4s001q3b6i482xx6jp", + "content": "Tell me about the company" + }, + { + "id": "cl96nvstv000e3b6itm8cj1s5", + "outgoingEdgeId": "cl96ogaa0001x3b6izae2alxq", + "content": "I have another question" + } + ] + } + ] + }, + { + "id": "cl96nt9ob00063b6ii2pktlxq", + "title": "Welcom", + "graphCoordinates": { "x": 43.5, "y": 89.92 }, + "blocks": [ + { + "id": "cl96nt9ob00073b6ionlvakha", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Hey there 👋" }] } + ] + } + }, + { + "id": "cl96ntraa00083b6ij922v2qh", + "outgoingEdgeId": "cl96nv51s000a3b6i3wmlcmdt", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "I'm John, head of the customer success Team at Analyzr" + } + ] + } + ] + } + } + ] + }, + { + "id": "cl96o2cgi000r3b6iljr1iwdl", + "title": "What's Analyzr", + "graphCoordinates": { "x": 774.53, "y": -513.14 }, + "blocks": [ + { + "id": "cl96o2cgi000s3b6ikdv6iogz", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Analyzr is a simple and privacy-friendly analytics tool for your website" + } + ] + } + ] + } + }, + { + "id": "cl96o3260000u3b6i9czqm52g", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "It is:" }] }, + { "type": "p", "children": [{ "text": "✅ Lightweight" }] }, + { "type": "p", "children": [{ "text": "✅ Open-source" }] }, + { + "type": "p", + "children": [{ "text": "✅ Fully compliant with GDPR" }] + } + ] + } + }, + { + "id": "cl96o55z3000x3b6ikq14g2tu", + "type": "choice input", + "items": [ + { "id": "cl96o55z3000y3b6idpn54byw", "content": "Sounds good!" } + ] + }, + { + "id": "qrg1xtxxbmyo8a6mztma3dvr", + "type": "Jump", + "options": { + "groupId": "cl96ns9qr00043b6ii07bo25o", + "blockId": "cl96nv877000b3b6i7p69ss2o" + } + } + ] + }, + { + "id": "cl96o6a2700123b6ie4efb6bb", + "title": "Use for free", + "graphCoordinates": { "x": 775.05, "y": 7.42 }, + "blocks": [ + { + "id": "cl96o6a2700133b6ii5n027h2", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "You can!" }] }] + } + }, + { + "id": "cl96o6a2700143b6ija9jqhky", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Analyzr has a generous free plan that allows you to store 1,000,000 events/mo 🚀" + } + ] + } + ] + } + }, + { + "id": "cl96o6a2700153b6il1wj2aev", + "type": "choice input", + "items": [ + { + "id": "cl96o6a2700163b6i818ywnqv", + "outgoingEdgeId": "n4rgj2fmqrmnkvo9m9ebzak7", + "content": "Awesome!" + }, + { + "id": "cl96o83lo00183b6igen42ivq", + "outgoingEdgeId": "cl96oa83f001h3b6i81wodnjx", + "content": "What's an event?" + } + ] + } + ] + }, + { + "id": "cl96o8eym001a3b6i3lxh7kw0", + "title": "User event", + "graphCoordinates": { "x": 1158.01, "y": 322.44 }, + "blocks": [ + { + "id": "cl96o8eyn001b3b6icmbgg7lw", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "An event is a user event on your website." } + ] + } + ] + } + }, + { + "id": "cl96o990s001c3b6ie2jjefhf", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "It can be \"User visited this URL\" or \"User clicked on this button\"" + } + ] + } + ] + } + }, + { + "id": "cl96o9xba001d3b6i9004l33e", + "type": "choice input", + "items": [ + { "id": "cl96o9xbd001e3b6i6ag5ooo7", "content": "Ok, got it!" } + ] + }, + { + "id": "bkmgmgxa96k5261su12hv58k", + "type": "Jump", + "options": { + "groupId": "cl96ns9qr00043b6ii07bo25o", + "blockId": "cl96nv877000b3b6i7p69ss2o" + } + } + ] + }, + { + "id": "cl96oc274001m3b6ig3beli9v", + "title": "Company", + "graphCoordinates": { "x": 772.59, "y": 432 }, + "blocks": [ + { + "id": "cl96ods3i001o3b6iiyboljuf", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "The company was founded in 2020 by Josh Corn" } + ] + } + ] + } + }, + { + "id": "cl96oc277001n3b6if8wv6hzl", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "We are now a team of 15" }] + } + ] + } + }, + { + "id": "cl96oenlh001p3b6iutaiw9wl", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Our core values are:" }] }, + { "type": "p", "children": [{ "text": "" }] }, + { "type": "p", "children": [{ "text": "🔍 Transparency" }] }, + { "type": "p", "children": [{ "text": "⚡ Ship fast" }] }, + { + "type": "p", + "children": [{ "text": "💙 Awesome customer support" }] + } + ] + } + }, + { + "id": "cl96oftnv001r3b6ixen8g0bv", + "type": "choice input", + "items": [{ "id": "cl96oftnv001s3b6i7kjyq7me", "content": "Cool!" }] + }, + { + "id": "js5pbqj76g67yvs6wz99rcbm", + "type": "Jump", + "options": { + "groupId": "cl96ns9qr00043b6ii07bo25o", + "blockId": "cl96nv877000b3b6i7p69ss2o" + } + } + ] + }, + { + "id": "cl96og2yr001v3b6ivhzb1x34", + "title": "Question", + "graphCoordinates": { "x": 773.69, "y": 1020.26 }, + "blocks": [ + { + "id": "cl96og2yu001w3b6ijqgstubu", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Sure, no problem!" }] } + ] + } + }, + { + "id": "cl96ogmjx001y3b6iwfosloet", + "outgoingEdgeId": "cl96ohn9900213b6ibex8g6my", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your question..." + }, + "isLong": true + } + } + ] + }, + { + "id": "cl96oh3mn001z3b6i2b0no81w", + "title": "Bye", + "graphCoordinates": { "x": 1174.378083740756, "y": 1049.08556420999 }, + "blocks": [ + { + "id": "cl96oh3mn00203b6iahw2x1ns", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Alright, we'll reach out to you very soon. Thank you so much 💙" + } + ] + } + ] + } + } + ] + }, + { + "id": "pqldfrkh43ncm39lzyeartv3", + "title": "", + "graphCoordinates": { "x": 1151.09, "y": 194.39 }, + "blocks": [ + { + "id": "ifaxemnkm6ikjfv2ozzeg1o3", + "type": "Jump", + "options": { + "groupId": "cl96ns9qr00043b6ii07bo25o", + "blockId": "cl96nv877000b3b6i7p69ss2o" + } + } + ] + } + ], + "edges": [ + { + "id": "cl96nv0ij00093b6id4t83dvu", + "from": { "eventId": "cl96ns7za000309kyewk56s22" }, + "to": { "groupId": "cl96nt9ob00063b6ii2pktlxq" } + }, + { + "id": "cl96nv51s000a3b6i3wmlcmdt", + "from": { "blockId": "cl96ntraa00083b6ij922v2qh" }, + "to": { "groupId": "cl96ns9qr00043b6ii07bo25o" } + }, + { + "id": "cl96o2u6h000t3b6izmh4pguj", + "from": { + "blockId": "cl96nv877000b3b6i7p69ss2o", + "itemId": "cl96nv877000c3b6idyepv694" + }, + "to": { "groupId": "cl96o2cgi000r3b6iljr1iwdl" } + }, + { + "id": "cl96o6hxh00173b6ix83nn581", + "from": { + "blockId": "cl96nv877000b3b6i7p69ss2o", + "itemId": "cl96nvcwi000d3b6ipyfzcyaw" + }, + "to": { "groupId": "cl96o6a2700123b6ie4efb6bb" } + }, + { + "id": "cl96oa83f001h3b6i81wodnjx", + "from": { + "blockId": "cl96o6a2700153b6il1wj2aev", + "itemId": "cl96o83lo00183b6igen42ivq" + }, + "to": { "groupId": "cl96o8eym001a3b6i3lxh7kw0" } + }, + { + "id": "cl96ofn4s001q3b6i482xx6jp", + "from": { + "blockId": "cl96nv877000b3b6i7p69ss2o", + "itemId": "cl96obwgy001k3b6ir1a8qk5w" + }, + "to": { "groupId": "cl96oc274001m3b6ig3beli9v" } + }, + { + "id": "cl96ogaa0001x3b6izae2alxq", + "from": { + "blockId": "cl96nv877000b3b6i7p69ss2o", + "itemId": "cl96nvstv000e3b6itm8cj1s5" + }, + "to": { "groupId": "cl96og2yr001v3b6ivhzb1x34" } + }, + { + "id": "cl96ohn9900213b6ibex8g6my", + "from": { "blockId": "cl96ogmjx001y3b6iwfosloet" }, + "to": { "groupId": "cl96oh3mn001z3b6i2b0no81w" } + }, + { + "id": "n4rgj2fmqrmnkvo9m9ebzak7", + "from": { + "blockId": "cl96o6a2700153b6il1wj2aev", + "itemId": "cl96o6a2700163b6i818ywnqv" + }, + "to": { "groupId": "pqldfrkh43ncm39lzyeartv3" } + } + ], + "variables": [], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:31:34.987Z", + "updatedAt": "2023-11-07T07:34:11.360Z", + "icon": "💬", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/lead-gen-ai.json b/apps/builder/public/templates/lead-gen-ai.json new file mode 100644 index 0000000..e89480c --- /dev/null +++ b/apps/builder/public/templates/lead-gen-ai.json @@ -0,0 +1,424 @@ +{ + "version": "6", + "id": "clon6cteb000i1avnrdaj92au", + "name": "Lead Gen with AI", + "events": [ + { + "id": "i6xofskq0vdlnfyvf28hzcle", + "outgoingEdgeId": "dkgy7qanybx0d9zl2ke2aa03", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "nmlij3lrk42cymsu1tj6b9nv", + "title": "Welcome", + "graphCoordinates": { "x": 1, "y": 148 }, + "blocks": [ + { + "id": "sc1y8VwDabNJgiVTBi4qtif", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hey 👋" }] }] + } + }, + { + "id": "s7YqZTBeyCa4Hp3wN2j922c", + "type": "image", + "content": { + "url": "https://media0.giphy.com/media/2f7RQiiWMJc40/giphy.gif?cid=fe3852a34jqk83z51tbm8a1jxmqpuckxxwef79p5myafdlw5&rid=giphy.gif&ct=g" + } + }, + { + "id": "z5tydv4qcam6xnh1ehm8hask", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Thank you for your interest in our marketing services." + } + ] + } + ] + } + }, + { + "id": "ygo5cubnk50m5jt6ull3bn0i", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Let's have a quick chat about your current situation 🙏" + } + ] + } + ] + } + }, + { + "id": "vw9s76hgwu749gw15bqk4vd3", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }] + } + }, + { + "id": "sbjZWLJGVkHAkDqS4JQeGow", + "outgoingEdgeId": "vgi4r3yjle17balwlhpas25t", + "type": "choice input", + "items": [{ "id": "hQw2zbp7FDX7XYK9cFpbgC", "content": "Yes!" }] + } + ] + }, + { + "id": "vrv6xoriyl74wcz34gqlvc0q", + "title": "Email", + "graphCoordinates": { "x": 666.07421875, "y": 141 }, + "blocks": [ + { + "id": "scQ5kduafAtfP9T8SHUJnGi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "What's the best email we can reach you at?" } + ] + } + ] + } + }, + { + "id": "snbsad18Bgry8yZ8DZCfdFD", + "outgoingEdgeId": "piew4sf9dpafiweghqvucmax", + "type": "email input", + "options": { + "variableId": "v3VFChNVSCXQ2rXv4DrJ8Ah" + } + } + ] + }, + { + "id": "wlcaalj5zej2sl1t9kkq55se", + "title": "Company", + "graphCoordinates": { "x": 325.22265625, "y": 144.37890625 }, + "blocks": [ + { + "id": "sgtE2Sy7cKykac9B223Kq9R", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What company do you work for?" }] + } + ] + } + }, + { + "id": "sqEsMo747LTDnY9FjQcEwUv", + "outgoingEdgeId": "wlzesf38jzeyf65i1aj6j517", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your answer...", + "button": "Send" + }, + "variableId": "giiLFGw5xXBCHzvp1qAbdX" + } + } + ] + }, + { + "id": "trcslng32mdxkjmrw8zxpnpj", + "title": "Services", + "graphCoordinates": { "x": 999.90625, "y": 143.7578125 }, + "blocks": [ + { + "id": "su7HceVXWyTCzi2vv3m4QbK", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What services are you interested in?" }] + } + ] + } + }, + { + "id": "s5VQGsVF4hQgziQsXVdwPDW", + "outgoingEdgeId": "wtw2lm86g46ehgvp43fcfks6", + "type": "choice input", + "items": [ + { "id": "fnLCBF4NdraSwcubnBhk8H", "content": "Website dev" }, + { "id": "a782h8ynMouY84QjH7XSnR", "content": "Content Marketing" }, + { "id": "jGvh94zBByvVFpSS3w97zY", "content": "Social Media" }, + { "id": "6PRLbKUezuFmwWtLVbvAQ7", "content": "UI / UX Design" } + ], + "options": { + "variableId": "vi0mmx9o2m4s8z9cccsjcvpj5", + "isMultipleChoice": true + } + } + ] + }, + { + "id": "m4oxxhg9wfv3wc6n8rhzy6ga", + "title": "[AI] Additional information", + "graphCoordinates": { "x": 1340.59, "y": 41.79 }, + "blocks": [ + { + "id": "px8ciz2nu2frvdqjporqpg95", + "type": "Condition", + "items": [ + { + "id": "w1cg5txczy2qmn4kbh1eybkk", + "outgoingEdgeId": "tfixdvay6mxj4g7z7bfmjthc", + "content": { + "comparisons": [ + { + "id": "r9ju98p1i6tevti45tt6jwk8", + "variableId": "vi5ta5lktses2h6skf5ky2zs0", + "comparisonOperator": "Greater than", + "value": "5" + } + ] + } + } + ] + }, + { + "id": "dc58mxvcstc2rdwnlg4yd2aa", + "type": "OpenAI", + "options": { + "task": "Create chat completion", + "model": "gpt-3.5-turbo", + "messages": [ + { + "id": "i522qy1dzn42qy7rkw79uk9n", + "role": "user", + "content": "You are a marketing agency, and I am a prospect.\n\nAsk simple questions to understand my needs." + }, + { + "id": "d6a2qfsdo251q0iopi77gtpd", + "role": "assistant", + "content": "What company do you work for?" + }, + { + "id": "ba3objkk8jp8piyxlbe9diu6", + "role": "user", + "content": "{{Company}}" + }, + { + "id": "bqqgavh96n76l9ma987km87y", + "role": "assistant", + "content": "What services are you interested in?" + }, + { + "id": "zdsbh8wrmhqop24kg3t9b08f", + "role": "user", + "content": "{{Services}}" + }, + { + "id": "j1pgsjm0snn3pz034h8y91vg", + "role": "Dialogue", + "dialogueVariableId": "vi5ta5lktses2h6skf5ky2zs0", + "startsBy": "assistant" + } + ], + "responseMapping": [ + { + "id": "krixyhr7qw5ow52yf3i11y3a", + "valueToExtract": "Message content", + "variableId": "vpvkbogoj3rmogz0ssh5odmnn" + } + ], + "credentialsId": "clocxtxlc00031an2uc59hdpb" + } + }, + { + "id": "vssvfz99ain77sc5w07ci5a1", + "type": "Set variable", + "options": { + "variableId": "vi5ta5lktses2h6skf5ky2zs0", + "type": "Append value(s)", + "item": "{{AI reply}}" + } + }, + { + "id": "ieopf79666ug1tmld46ac1rw", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{AI reply}}" }] } + ] + } + }, + { + "id": "sqFy2G3C1mh9p6s3QBdSS5x", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your answer...", + "button": "Send" + }, + "variableId": "vhp0ymgwq4id82l97g0kliglf" + } + }, + { + "id": "t8s54i11vfebpp5cbc7xukn5", + "outgoingEdgeId": "buwcxt81dfrh6prteij8cvo8", + "type": "Set variable", + "options": { + "variableId": "vi5ta5lktses2h6skf5ky2zs0", + "type": "Append value(s)", + "item": "{{Additional information}}" + } + } + ] + }, + { + "id": "gjahzyusg4mlpvpaeov0awtm", + "title": "Bye", + "graphCoordinates": { "x": 1676.6171875, "y": 142.7109375 }, + "blocks": [ + { + "id": "seLegenCgUwMopRFeAefqZ7", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Perfect!" }] }] + } + }, + { + "id": "s779Q1y51aVaDUJVrFb16vv", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "We'll get back to you at {{Email}}" }] + } + ] + } + } + ] + }, + { + "id": "l0223zmqvndj1irhk68yh10v", + "title": "", + "graphCoordinates": { "x": 1342.76, "y": 692.3 }, + "blocks": [ + { + "id": "l7r996nrnqb937nzyrprcvs0", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your OpenAI credentials to make this bot work. 🪄" + } + ] + } + ] + } + }, + { + "id": "jxrp7xdzmnqnfmzfvid2u4s1", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, delete this group and connect the " + }, + { "bold": true, "text": "Services" }, + { "text": " group with " }, + { "bold": true, "text": "[AI] Additional Information" }, + { "text": " 🚀" } + ] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "dkgy7qanybx0d9zl2ke2aa03", + "from": { "eventId": "i6xofskq0vdlnfyvf28hzcle" }, + "to": { "groupId": "nmlij3lrk42cymsu1tj6b9nv" } + }, + { + "id": "vgi4r3yjle17balwlhpas25t", + "from": { "blockId": "sbjZWLJGVkHAkDqS4JQeGow" }, + "to": { "groupId": "wlcaalj5zej2sl1t9kkq55se" } + }, + { + "id": "wlzesf38jzeyf65i1aj6j517", + "from": { "blockId": "sqEsMo747LTDnY9FjQcEwUv" }, + "to": { "groupId": "vrv6xoriyl74wcz34gqlvc0q" } + }, + { + "id": "piew4sf9dpafiweghqvucmax", + "from": { "blockId": "snbsad18Bgry8yZ8DZCfdFD" }, + "to": { "groupId": "trcslng32mdxkjmrw8zxpnpj" } + }, + { + "id": "tfixdvay6mxj4g7z7bfmjthc", + "from": { + "blockId": "px8ciz2nu2frvdqjporqpg95", + "itemId": "w1cg5txczy2qmn4kbh1eybkk" + }, + "to": { "groupId": "gjahzyusg4mlpvpaeov0awtm" } + }, + { + "id": "buwcxt81dfrh6prteij8cvo8", + "from": { "blockId": "t8s54i11vfebpp5cbc7xukn5" }, + "to": { "groupId": "m4oxxhg9wfv3wc6n8rhzy6ga" } + }, + { + "from": { + "blockId": "s5VQGsVF4hQgziQsXVdwPDW", + "groupId": "trcslng32mdxkjmrw8zxpnpj" + }, + "to": { "groupId": "l0223zmqvndj1irhk68yh10v" }, + "id": "wtw2lm86g46ehgvp43fcfks6" + } + ], + "variables": [ + { "id": "giiLFGw5xXBCHzvp1qAbdX", "name": "Company" }, + { "id": "v3VFChNVSCXQ2rXv4DrJ8Ah", "name": "Email" }, + { "id": "vi0mmx9o2m4s8z9cccsjcvpj5", "name": "Services" }, + { "id": "vpvkbogoj3rmogz0ssh5odmnn", "name": "AI reply" }, + { "id": "vhp0ymgwq4id82l97g0kliglf", "name": "Additional information" }, + { "id": "vi5ta5lktses2h6skf5ky2zs0", "name": "AI Dialogue" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-06T17:26:59.795Z", + "updatedAt": "2023-11-07T06:50:56.154Z", + "icon": "🦾", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/lead-gen.json b/apps/builder/public/templates/lead-gen.json new file mode 100644 index 0000000..5d7187a --- /dev/null +++ b/apps/builder/public/templates/lead-gen.json @@ -0,0 +1,268 @@ +{ + "version": "6", + "id": "cloiafj9e00091aqj6o9nfrww", + "name": "Lead Generation", + "events": [ + { + "id": "k6kY6gwRE6noPoYQNGzgUq", + "outgoingEdgeId": "oNvqaqNExdSH2kKEhKZHuE", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "kinRXxYop2X4d7F9qt8WNB", + "title": "Welcome", + "graphCoordinates": { "x": 1, "y": 148 }, + "blocks": [ + { + "id": "sc1y8VwDabNJgiVTBi4qtif", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Welcome to " }, + { "bold": true, "text": "AA" }, + { "text": " (Awesome Agency)" } + ] + } + ] + } + }, + { + "id": "s7YqZTBeyCa4Hp3wN2j922c", + "type": "image", + "content": { + "url": "https://media2.giphy.com/media/XD9o33QG9BoMis7iM4/giphy.gif?cid=fe3852a3ihg8rvipzzky5lybmdyq38fhke2tkrnshwk52c7d&rid=giphy.gif&ct=g" + } + }, + { + "id": "sbjZWLJGVkHAkDqS4JQeGow", + "outgoingEdgeId": "i51YhHpk1dtSyduFNf5Wim", + "type": "choice input", + "items": [ + { + "id": "hQw2zbp7FDX7XYK9cFpbgC", + "content": "Hi!" + } + ] + } + ] + }, + { + "id": "o4SH1UtKANnW5N5D67oZUz", + "title": "Email", + "graphCoordinates": { "x": 669, "y": 141 }, + "blocks": [ + { + "id": "sxeYubYN6XzhAfG7m9Fivhc", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Great! Nice to meet you {{Name}}" }] + } + ] + } + }, + { + "id": "scQ5kduafAtfP9T8SHUJnGi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "What's the best email we can reach you at?" } + ] + } + ] + } + }, + { + "id": "snbsad18Bgry8yZ8DZCfdFD", + "outgoingEdgeId": "w3MiN1Ct38jT5NykVsgmb5", + "type": "email input", + "options": { + "variableId": "v3VFChNVSCXQ2rXv4DrJ8Ah" + } + } + ] + }, + { + "id": "q5dAhqSTCaNdiGSJm9B9Rw", + "title": "Name", + "graphCoordinates": { "x": 340, "y": 143 }, + "blocks": [ + { + "id": "sgtE2Sy7cKykac9B223Kq9R", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your name?" }] } + ] + } + }, + { + "id": "sqEsMo747LTDnY9FjQcEwUv", + "outgoingEdgeId": "4tYbERpi5Po4goVgt6rWXg", + "type": "text input", + "options": { + "variableId": "giiLFGw5xXBCHzvp1qAbdX" + } + } + ] + }, + { + "id": "fKqRz7iswk7ULaj5PJocZL", + "title": "Services", + "graphCoordinates": { "x": 1002, "y": 144 }, + "blocks": [ + { + "id": "su7HceVXWyTCzi2vv3m4QbK", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What services are you interested in?" }] + } + ] + } + }, + { + "id": "s5VQGsVF4hQgziQsXVdwPDW", + "outgoingEdgeId": "ohTRakmcYJ7GdFWRZrWRjk", + "type": "choice input", + "items": [ + { + "id": "fnLCBF4NdraSwcubnBhk8H", + "content": "Website dev" + }, + { + "id": "a782h8ynMouY84QjH7XSnR", + "content": "Content Marketing" + }, + { + "id": "jGvh94zBByvVFpSS3w97zY", + "content": "Social Media" + }, + { + "id": "6PRLbKUezuFmwWtLVbvAQ7", + "content": "UI / UX Design" + } + ] + } + ] + }, + { + "id": "7qHBEyCMvKEJryBHzPmHjV", + "title": "Additional information", + "graphCoordinates": { "x": 1337, "y": 145 }, + "blocks": [ + { + "id": "sqR8Sz9gW21aUYKtUikq7qZ", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Can you tell me a bit more about your needs?" } + ] + } + ] + } + }, + { + "id": "sqFy2G3C1mh9p6s3QBdSS5x", + "outgoingEdgeId": "sH5nUssG2XQbm6ZidGv9BY", + "type": "text input", + "options": { + "isLong": true + } + } + ] + }, + { + "id": "vF7AD7zSAj7SNvN3gr9N94", + "title": "Bye", + "graphCoordinates": { "x": 1668, "y": 143 }, + "blocks": [ + { + "id": "seLegenCgUwMopRFeAefqZ7", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Perfect!" }] }] + } + }, + { + "id": "s779Q1y51aVaDUJVrFb16vv", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "We'll get back to you at {{Email}}" }] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "oNvqaqNExdSH2kKEhKZHuE", + "from": { "eventId": "k6kY6gwRE6noPoYQNGzgUq" }, + "to": { "groupId": "kinRXxYop2X4d7F9qt8WNB" } + }, + { + "id": "i51YhHpk1dtSyduFNf5Wim", + "from": { "blockId": "sbjZWLJGVkHAkDqS4JQeGow" }, + "to": { "groupId": "q5dAhqSTCaNdiGSJm9B9Rw" } + }, + { + "id": "4tYbERpi5Po4goVgt6rWXg", + "from": { "blockId": "sqEsMo747LTDnY9FjQcEwUv" }, + "to": { "groupId": "o4SH1UtKANnW5N5D67oZUz" } + }, + { + "id": "w3MiN1Ct38jT5NykVsgmb5", + "from": { "blockId": "snbsad18Bgry8yZ8DZCfdFD" }, + "to": { "groupId": "fKqRz7iswk7ULaj5PJocZL" } + }, + { + "id": "ohTRakmcYJ7GdFWRZrWRjk", + "from": { "blockId": "s5VQGsVF4hQgziQsXVdwPDW" }, + "to": { "groupId": "7qHBEyCMvKEJryBHzPmHjV" } + }, + { + "id": "sH5nUssG2XQbm6ZidGv9BY", + "from": { "blockId": "sqFy2G3C1mh9p6s3QBdSS5x" }, + "to": { "groupId": "vF7AD7zSAj7SNvN3gr9N94" } + } + ], + "variables": [ + { "id": "giiLFGw5xXBCHzvp1qAbdX", "name": "Name" }, + { "id": "v3VFChNVSCXQ2rXv4DrJ8Ah", "name": "Email" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-03T07:22:14.210Z", + "updatedAt": "2023-11-03T07:22:14.210Z", + "icon": "🤝", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/lead-magnet.json b/apps/builder/public/templates/lead-magnet.json new file mode 100644 index 0000000..9fca15b --- /dev/null +++ b/apps/builder/public/templates/lead-magnet.json @@ -0,0 +1,491 @@ +{ + "version": "6", + "id": "clon5n2yo00091avnmbju5698", + "name": "Lead magnet", + "events": [ + { + "id": "emejg92oa3743x6z556xi1ig", + "outgoingEdgeId": "hfugjlwxkt5eqvxe5poimt6w", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "gr9wedxcqxie11ki9yss1h5o", + "title": "Intro", + "graphCoordinates": { "x": 209.12109375, "y": 176.5703125 }, + "blocks": [ + { + "id": "uaks8b01ec3fln8g5iq9gnv7", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Hi there! 👋" }] } + ] + } + }, + { + "id": "iy9brewiabfhv7ctsvdd5fg6", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Sign up for the newsletter and " }, + { + "bold": true, + "text": "get free access to our exclusive 'Community Bundle'." + } + ] + } + ] + } + }, + { + "id": "immlrmjc0tnvc0rd1552c0ey", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "This bundle helps you create the best Community possible for your project." + } + ] + } + ] + } + }, + { + "id": "i1pv6t8sj9wdzoheplwj1cnr", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your name?" }] } + ] + } + }, + { + "id": "uocaxxtg26btl2zytwy09jh9", + "outgoingEdgeId": "rczh7k3r065okzax6za00lvh", + "type": "text input", + "options": { + "labels": { "placeholder": "Your first name" }, + "variableId": "vyu4paeim4jcjgmxr26bdk286" + } + } + ] + }, + { + "id": "xaloto3qrrbtcdcrob013xcx", + "title": "Email", + "graphCoordinates": { "x": 563.2421875, "y": 177.484375 }, + "blocks": [ + { + "id": "pcx0bo7egsq3il16707mkuzc", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Ok, {{Name}}. What email would you like to sign up with?" + } + ] + } + ] + } + }, + { + "id": "nu9ibw4r4q9piwl3b308bezp", + "groupId": "xaloto3qrrbtcdcrob013xcx", + "type": "email input", + "options": { "variableId": "vrhd0bug6b6dzgijevfoonvo2" }, + "outgoingEdgeId": "dxj0x2miwwkxsesp4chyjqek" + } + ] + }, + { + "id": "tp9r95ay5vm9zlgzw8twtxn3", + "title": "Goal", + "graphCoordinates": { "x": 1243.07421875, "y": 172.2421875 }, + "blocks": [ + { + "id": "o6helbp9c682dur5e8bt9yov", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What's your goal with the community?" }] + } + ] + } + }, + { + "id": "wq7yofni4bqr9rt5qrzk6928", + "outgoingEdgeId": "on3al6xuczmckpu3roboo9te", + "type": "choice input", + "items": [ + { "id": "ux0ly8ocxfm8i8ivdbwjnmnt", "content": "Win loyal fans" }, + { + "id": "izz0nwo2iy2kmlif5fav2oc5", + "content": "Competitive advantage" + }, + { "id": "jtkx9v5uqjw84hapq3umqlb5", "content": "Better product" }, + { "id": "k7a7rkpoigrtrulilap7q6fw", "content": "Support" } + ], + "options": { + "variableId": "vf49immob0ih3kxn5b0nraqkq" + } + } + ] + }, + { + "id": "cszciavjonb2qp0ga0pladoj", + "title": "Goal", + "graphCoordinates": { "x": 1590.85546875, "y": 164.02734375 }, + "blocks": [ + { + "id": "tfqqveo72xt7i7ii9imztcd4", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Perfect, your bundle will be emailed to you right away 🚀" + } + ] + } + ] + } + }, + { + "id": "yxuk1bhfas07i4bxq64hi0vj", + "type": "Condition", + "items": [ + { + "id": "qn6w72jgckfz777e9ehb421v", + "outgoingEdgeId": "yml7f2btr9q4hptk06cqn2xv", + "content": { + "comparisons": [ + { + "id": "nt0c7o7w0elbbrfde8nned76", + "variableId": "vf49immob0ih3kxn5b0nraqkq", + "comparisonOperator": "Equal to", + "value": "Win loyal fans" + } + ] + } + }, + { + "id": "vuun8mijpfzcu0o9qk0vtift", + "outgoingEdgeId": "qhpximatxzjmmm1njwoqzplw", + "content": { + "comparisons": [ + { + "id": "yf6asq9i97ap9y2jxibmjylv", + "variableId": "vf49immob0ih3kxn5b0nraqkq", + "comparisonOperator": "Equal to", + "value": "Competitive advantage" + } + ] + } + }, + { + "id": "dg28mo88efs00p8ech81qxmu", + "outgoingEdgeId": "xa5z7a7en5vfevqk5e5q05go", + "content": { + "comparisons": [ + { + "id": "x7tbo8q47r1wdlg6w3c48mru", + "variableId": "vf49immob0ih3kxn5b0nraqkq", + "comparisonOperator": "Equal to", + "value": "Better product" + } + ] + } + }, + { + "id": "lrj50vf8c0cj46jrtxid5a60", + "outgoingEdgeId": "ogpmoxw3lrt12rgxnq0wajrj", + "content": { + "comparisons": [ + { + "id": "hkb9qy6un3yrhhxtm0s6c8rg", + "variableId": "vf49immob0ih3kxn5b0nraqkq", + "comparisonOperator": "Equal to", + "value": "Support" + } + ] + } + } + ] + } + ] + }, + { + "id": "vvlecgglxadq0x2eg7ozr535", + "title": "Send bundle", + "graphCoordinates": { "x": 901.6953125, "y": 180.0546875 }, + "blocks": [ + { + "id": "w53cmmn4iowq753r8jmvk7o7", + "outgoingEdgeId": "qkrpdn1z0bv1xvsa3wrdyyn3", + "type": "Email", + "options": { + "isCustomBody": true, + "recipients": ["{{Email}}"], + "subject": "Here is your community bundle ✨", + "body": "Hey {{Name}},\n\nHere is a link to download the community bundle:\n\nhttps://typebot.io\n\nI hope it will help you create the right community for your project 🚀\n\nBest,\nTypebot team." + } + } + ] + }, + { + "id": "k2sbuizycrpuyf44v9eebebr", + "title": "Win loyal fans video", + "graphCoordinates": { "x": 1969.18359375, "y": -205.76171875 }, + "blocks": [ + { + "id": "dzcw0vwo23vhp2nwyxl99va8", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Want to know how to win loyal fans?" }] + } + ] + } + }, + { + "id": "yh8ueuio717ceybrcsqa1ekq", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Check out this video:" }] } + ] + } + }, + { + "id": "z3ffqugex7gipsb4ke6ov874", + "type": "video", + "content": { + "url": "https://www.youtube.com/watch?v=jp3ggg_42-M&t=22s", + "id": "jp3ggg_42-M", + "type": "youtube" + } + } + ] + }, + { + "id": "v6s5yza7kgretdmbke7lg5u7", + "title": "Competitive advantage video", + "graphCoordinates": { "x": 1968.1484375, "y": 181.5703125 }, + "blocks": [ + { + "id": "anu87wo53n3ihq4xl8smprwg", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Want to know how to have a great competitive advantage with your community?" + } + ] + } + ] + } + }, + { + "id": "ku2scubf21eqnip3ig3rc7n9", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Check out this video:" }] } + ] + } + }, + { + "id": "rvdh4tk0ebg7t9tdga9aw8ao", + "type": "video", + "content": { + "url": "https://www.youtube.com/watch?v=jp3ggg_42-M&t=22s", + "id": "jp3ggg_42-M", + "type": "youtube" + } + } + ] + }, + { + "id": "l3pc0992zp0hw8ea83b7aky3", + "title": "Better product", + "graphCoordinates": { "x": 1968.703125, "y": 600.07421875 }, + "blocks": [ + { + "id": "ysedrtj5q17usk5ezpa5g88e", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Want to know how to improve your product by leveraging a community?" + } + ] + } + ] + } + }, + { + "id": "xy08sticb76u82sgcfaeqpe2", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Check out this video:" }] } + ] + } + }, + { + "id": "jiz2uvo89456jpy081hazkd4", + "type": "video", + "content": { + "url": "https://www.youtube.com/watch?v=jp3ggg_42-M&t=22s", + "id": "jp3ggg_42-M", + "type": "youtube" + } + } + ] + }, + { + "id": "f4hlh2oq8viwxrpl9ppq5d42", + "title": "Support", + "graphCoordinates": { "x": 1970.0234375, "y": 1025.99609375 }, + "blocks": [ + { + "id": "lu0bevnjfkor1ugbnbkev7t3", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Want to offer better support with a community?" } + ] + } + ] + } + }, + { + "id": "jrhdfrdn4gdstpktq1q0gk1q", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Check out this video:" }] } + ] + } + }, + { + "id": "e3tlj1y4vyhtwcabzifv63q2", + "type": "video", + "content": { + "url": "https://www.youtube.com/watch?v=jp3ggg_42-M&t=22s", + "id": "jp3ggg_42-M", + "type": "youtube" + } + } + ] + } + ], + "edges": [ + { + "id": "hfugjlwxkt5eqvxe5poimt6w", + "from": { "eventId": "emejg92oa3743x6z556xi1ig" }, + "to": { "groupId": "gr9wedxcqxie11ki9yss1h5o" } + }, + { + "id": "rczh7k3r065okzax6za00lvh", + "from": { "blockId": "uocaxxtg26btl2zytwy09jh9" }, + "to": { "groupId": "xaloto3qrrbtcdcrob013xcx" } + }, + { + "id": "on3al6xuczmckpu3roboo9te", + "from": { "blockId": "wq7yofni4bqr9rt5qrzk6928" }, + "to": { "groupId": "cszciavjonb2qp0ga0pladoj" } + }, + { + "id": "qkrpdn1z0bv1xvsa3wrdyyn3", + "from": { "blockId": "w53cmmn4iowq753r8jmvk7o7" }, + "to": { "groupId": "tp9r95ay5vm9zlgzw8twtxn3" } + }, + { + "id": "yml7f2btr9q4hptk06cqn2xv", + "from": { + "blockId": "yxuk1bhfas07i4bxq64hi0vj", + "itemId": "qn6w72jgckfz777e9ehb421v" + }, + "to": { "groupId": "k2sbuizycrpuyf44v9eebebr" } + }, + { + "id": "qhpximatxzjmmm1njwoqzplw", + "from": { + "blockId": "yxuk1bhfas07i4bxq64hi0vj", + "itemId": "vuun8mijpfzcu0o9qk0vtift" + }, + "to": { "groupId": "v6s5yza7kgretdmbke7lg5u7" } + }, + { + "id": "xa5z7a7en5vfevqk5e5q05go", + "from": { + "blockId": "yxuk1bhfas07i4bxq64hi0vj", + "itemId": "dg28mo88efs00p8ech81qxmu" + }, + "to": { "groupId": "l3pc0992zp0hw8ea83b7aky3" } + }, + { + "id": "ogpmoxw3lrt12rgxnq0wajrj", + "from": { + "blockId": "yxuk1bhfas07i4bxq64hi0vj", + "itemId": "lrj50vf8c0cj46jrtxid5a60" + }, + "to": { "groupId": "f4hlh2oq8viwxrpl9ppq5d42" } + }, + { + "from": { + "blockId": "nu9ibw4r4q9piwl3b308bezp", + "groupId": "xaloto3qrrbtcdcrob013xcx" + }, + "to": { "groupId": "vvlecgglxadq0x2eg7ozr535" }, + "id": "dxj0x2miwwkxsesp4chyjqek" + } + ], + "variables": [ + { "id": "vyu4paeim4jcjgmxr26bdk286", "name": "Name" }, + { "id": "vf49immob0ih3kxn5b0nraqkq", "name": "Goal" }, + { "id": "vrhd0bug6b6dzgijevfoonvo2", "name": "Email" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-06T17:06:59.136Z", + "updatedAt": "2023-11-06T17:06:59.136Z", + "icon": "🧲", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/lead-scoring.json b/apps/builder/public/templates/lead-scoring.json new file mode 100644 index 0000000..89ae24a --- /dev/null +++ b/apps/builder/public/templates/lead-scoring.json @@ -0,0 +1,630 @@ +{ + "version": "6", + "id": "clon58wkg00051avnkor66u6m", + "name": "Lead Scoring", + "events": [ + { + "id": "cl1seoz560000xk1ags8s67b0", + "outgoingEdgeId": "cl1seraz9001z2e6e85zrx08l", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "cl1sep1c5001w2e6e77bb1uwb", + "title": "Welcome", + "graphCoordinates": { "x": 0, "y": 171 }, + "blocks": [ + { + "id": "cl1sep1cc001x2e6eikrwf9jy", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hi! 👋" }] }] + } + }, + { + "id": "cl1sep7jn001y2e6ez7ee7eiw", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "I'm glad you are intersted in our services." } + ] + } + ] + } + }, + { + "id": "cl1seyazl00252e6e3zsbosvm", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "I'll need to know a little more about you" } + ] + } + ] + } + }, + { + "id": "cl1sezuul002a2e6ex7nc444j", + "outgoingEdgeId": "cl1sf8v96003k2e6e2rbcfjmz", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "0" + } + } + ] + }, + { + "id": "cl1sern8w00202e6ez69l190j", + "title": "Q1", + "graphCoordinates": { "x": 377, "y": 166 }, + "blocks": [ + { + "id": "cl1sern9200212e6esrid307i", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Do you work with a specific company?" }] + } + ] + } + }, + { + "id": "cl1ses31000222e6ebrb4wxo0", + "type": "choice input", + "items": [ + { + "id": "cl1ses31100232e6eq3nnp2mm", + "outgoingEdgeId": "cl1sezo4z00292e6ean8s487x", + "content": "Yes" + }, + { + "id": "cl1ses3y400242e6e1qjwkhq4", + "outgoingEdgeId": "cl1sfertf004i2e6epf68fwri", + "content": "No" + } + ] + } + ] + }, + { + "id": "cl1sez6zd00262e6ebh59k1bs", + "title": "Company", + "graphCoordinates": { "x": 748, "y": 135 }, + "blocks": [ + { + "id": "cl1sf04yl002c2e6eaeu463cq", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "{{Lead Score}} + 10" + } + }, + { + "id": "cl1sez6zt00272e6ecsefq05y", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Which company?" }] } + ] + } + }, + { + "id": "cl1sezlw700282e6eozkzmed0", + "outgoingEdgeId": "cl1sf1mm0002h2e6eurv21l5n", + "type": "text input", + "options": { + "variableId": "vcl1sf93s2003l2e6eojomb66g" + } + } + ] + }, + { + "id": "cl1sf0ogu002d2e6edyhcuu6f", + "title": "Q2", + "graphCoordinates": { "x": 1096, "y": -62 }, + "blocks": [ + { + "id": "cl1sf0ohc002e2e6egrjoj10z", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "How many employees is your team composed of?" } + ] + } + ] + } + }, + { + "id": "cl1sf1er7002f2e6eakhc25yy", + "type": "number input", + "options": { + "variableId": "vcl1sf1ko5002g2e6egjmyb16v" + } + }, + { + "id": "cl1sf1vkf002j2e6e971somqx", + "type": "Condition", + "items": [ + { + "id": "cl1sf1vkg002k2e6ec54p0s4v", + "outgoingEdgeId": "cl1sf35fh002t2e6e8u68r9gz", + "content": { + "comparisons": [ + { + "id": "cl1sf1y2a002l2e6eum6kcapg", + "variableId": "vcl1sf1ko5002g2e6egjmyb16v", + "comparisonOperator": "Greater than", + "value": "30" + } + ] + } + } + ] + }, + { + "id": "cl1sf2iix002n2e6egibs95yb", + "outgoingEdgeId": "cl1sfen6a004f2e6estkfooss", + "type": "Condition", + "items": [ + { + "id": "cl1sf2iix002o2e6eai567rnj", + "outgoingEdgeId": "cl1sf37rv002x2e6e7wz3lawd", + "content": { + "comparisons": [ + { + "id": "cl1sf2jmf002p2e6exertfrjq", + "variableId": "vcl1sf1ko5002g2e6egjmyb16v", + "value": "10" + } + ] + } + } + ] + } + ] + }, + { + "id": "cl1sf2wnu002r2e6ehdp859qv", + "title": "Add 20", + "graphCoordinates": { "x": 1458, "y": -72 }, + "blocks": [ + { + "id": "cl1sf2wom002s2e6e8cmcnhpn", + "outgoingEdgeId": "cl1sfeq3f004h2e6eglhjyx2o", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "{{Lead Score}} + 20" + } + } + ] + }, + { + "id": "cl1sf36ia002u2e6e16ifow0z", + "title": "Add 10", + "graphCoordinates": { "x": 1458, "y": 88 }, + "blocks": [ + { + "id": "cl1sf36ib002v2e6ejyyrrjnh", + "outgoingEdgeId": "cl1sfeog5004g2e6eiil842nb", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "{{Lead Score}} + 10" + } + } + ] + }, + { + "id": "cl1sf4qk500332e6e8gs5mn3t", + "title": "Q4", + "graphCoordinates": { "x": 2442.929831215626, "y": 391 }, + "blocks": [ + { + "id": "cl1sf4ql500342e6ebj863aex", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Where are you based?" }] } + ] + } + }, + { + "id": "cl1sf4z8n00352e6ejypaeinl", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type your country..." + }, + "variableId": "vcl1sf525q00362e6eoyosycte" + } + }, + { + "id": "cl1sf738d003c2e6eswslikio", + "outgoingEdgeId": "cl1sf9acz003n2e6ekwjq7209", + "type": "Condition", + "items": [ + { + "id": "cl1sf738d003d2e6eqpzlxh8f", + "outgoingEdgeId": "cl1sf7qlx003h2e6e60635qrt", + "content": { + "comparisons": [ + { + "id": "cl1sf7704003e2e6e0r3j22bg", + "variableId": "vcl1sf525q00362e6eoyosycte", + "comparisonOperator": "Equal to", + "value": "United States" + } + ] + } + } + ] + } + ] + }, + { + "id": "cl1sf7jbi003f2e6euy48woy4", + "title": "Add 10", + "graphCoordinates": { "x": 2765.429799608067, "y": 386.7142676528225 }, + "blocks": [ + { + "id": "cl1sf7jcx003g2e6ec1z9xh0w", + "outgoingEdgeId": "cl1sf99bb003m2e6eywy661ww", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "10" + } + } + ] + }, + { + "id": "cl1sf85am003i2e6e1yq8eoa7", + "title": "Filtering", + "graphCoordinates": { "x": 2953.786585751312, "y": 570.3154133255522 }, + "blocks": [ + { + "id": "cl1sf85bm003j2e6e04d210vs", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Thank you for answering these questions" } + ] + } + ] + } + }, + { + "id": "cl1sfat0h003p2e6e7j0hpilh", + "outgoingEdgeId": "cl1sfgtau004n2e6ev68sikcr", + "type": "Condition", + "items": [ + { + "id": "cl1sfat0h003q2e6eyx6vxe0f", + "outgoingEdgeId": "cl1sfg9fc004k2e6egywpim9v", + "content": { + "comparisons": [ + { + "id": "cl1sfau7i003r2e6e3me45rr3", + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "comparisonOperator": "Greater than", + "value": "20" + } + ] + } + } + ] + } + ] + }, + { + "id": "cl1sfbbv0003s2e6eheyhv7ke", + "title": "Q3", + "graphCoordinates": { "x": 1632.857386686895, "y": 465.7855110942534 }, + "blocks": [ + { + "id": "cl1sfcqjw003z2e6ebmyzey4o", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your job role?" }] } + ] + } + }, + { + "id": "cl1sfbbw3003t2e6e16ec9w29", + "outgoingEdgeId": "cl1sfek9r004e2e6elkh3h7a2", + "type": "choice input", + "items": [ + { "id": "cl1sfbbw3003u2e6e7luhj0n1", "content": "UI/UX Designer" }, + { "id": "cl1sfbq6z003v2e6egnctk2n2", "content": "Product Owner" }, + { + "id": "cl1sfbtz8003w2e6eodbt4ogs", + "outgoingEdgeId": "cl1sfebs9004a2e6ere0zokyo", + "content": "Marketing Officer" + }, + { + "id": "cl1sfc545003x2e6e833juo6m", + "outgoingEdgeId": "cl1sfedcd004b2e6eerh8hz33", + "content": "Developer" + } + ] + } + ] + }, + { + "id": "cl1sfdroa00452e6e5o458z9h", + "title": "Add 20", + "graphCoordinates": { "x": 1983.143182249194, "y": 82.85612238447435 }, + "blocks": [ + { + "id": "cl1sfdrpi00462e6emfd9sj14", + "outgoingEdgeId": "cl1sfeg2k004c2e6eu9rjnski", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "{{Lead Score}} + 20" + } + } + ] + }, + { + "id": "cl1sfe2kn00472e6ead4qs2d9", + "title": "Add 10", + "graphCoordinates": { "x": 1984.285605916936, "y": 240.8562488147158 }, + "blocks": [ + { + "id": "cl1sfe2kn00482e6eukp8r9bj", + "outgoingEdgeId": "cl1sfeik5004d2e6ejj03f1gn", + "type": "Set variable", + "options": { + "variableId": "vcl1sezzln002b2e6e6ssxh9bf", + "expressionToEvaluate": "{{Lead Score}} + 20" + } + } + ] + }, + { + "id": "cl1sffxet004j2e6ec6gfbffh", + "title": "Conclusion - Qualified", + "graphCoordinates": { "x": 3350.087494027719, "y": 509.7735663944507 }, + "blocks": [ + { + "id": "cl1sfgwox004o2e6evzi0n7hk", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Our service is specifically designed for your situation." + } + ] + } + ] + } + }, + { + "id": "cl1sfhz4f004p2e6esidqktmr", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "We'll get back to you ASAP. 👋" }] + } + ] + } + } + ] + }, + { + "id": "cl1sfgjlr004l2e6erykli1ud", + "title": "Conclusion - Not qualified", + "graphCoordinates": { "x": 3352.894339234574, "y": 786.5865419115444 }, + "blocks": [ + { + "id": "cl1sfgjnr004m2e6e63sqh0dh", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Our service doesn't seem to suit your need." } + ] + } + ] + } + }, + { + "id": "cl1sfikh5004q2e6elyvzgd0s", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "We'll still send you valuable content by email." } + ] + } + ] + } + }, + { + "id": "cl1sfitz4004r2e6e3ge4x7uy", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Bye bye 👋" }] } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "cl1seraz9001z2e6e85zrx08l", + "from": { "eventId": "cl1seoz560000xk1ags8s67b0" }, + "to": { "groupId": "cl1sep1c5001w2e6e77bb1uwb" } + }, + { + "id": "cl1sezo4z00292e6ean8s487x", + "from": { + "blockId": "cl1ses31000222e6ebrb4wxo0", + "itemId": "cl1ses31100232e6eq3nnp2mm" + }, + "to": { "groupId": "cl1sez6zd00262e6ebh59k1bs" } + }, + { + "id": "cl1sf1mm0002h2e6eurv21l5n", + "from": { "blockId": "cl1sezlw700282e6eozkzmed0" }, + "to": { "groupId": "cl1sf0ogu002d2e6edyhcuu6f" } + }, + { + "id": "cl1sf35fh002t2e6e8u68r9gz", + "from": { + "blockId": "cl1sf1vkf002j2e6e971somqx", + "itemId": "cl1sf1vkg002k2e6ec54p0s4v" + }, + "to": { "groupId": "cl1sf2wnu002r2e6ehdp859qv" } + }, + { + "id": "cl1sf37rv002x2e6e7wz3lawd", + "from": { + "blockId": "cl1sf2iix002n2e6egibs95yb", + "itemId": "cl1sf2iix002o2e6eai567rnj" + }, + "to": { "groupId": "cl1sf36ia002u2e6e16ifow0z" } + }, + { + "id": "cl1sf7qlx003h2e6e60635qrt", + "from": { + "blockId": "cl1sf738d003c2e6eswslikio", + "itemId": "cl1sf738d003d2e6eqpzlxh8f" + }, + "to": { "groupId": "cl1sf7jbi003f2e6euy48woy4" } + }, + { + "id": "cl1sf8v96003k2e6e2rbcfjmz", + "from": { "blockId": "cl1sezuul002a2e6ex7nc444j" }, + "to": { "groupId": "cl1sern8w00202e6ez69l190j" } + }, + { + "id": "cl1sf99bb003m2e6eywy661ww", + "from": { "blockId": "cl1sf7jcx003g2e6ec1z9xh0w" }, + "to": { "groupId": "cl1sf85am003i2e6e1yq8eoa7" } + }, + { + "id": "cl1sf9acz003n2e6ekwjq7209", + "from": { "blockId": "cl1sf738d003c2e6eswslikio" }, + "to": { "groupId": "cl1sf85am003i2e6e1yq8eoa7" } + }, + { + "id": "cl1sfebs9004a2e6ere0zokyo", + "from": { + "blockId": "cl1sfbbw3003t2e6e16ec9w29", + "itemId": "cl1sfbtz8003w2e6eodbt4ogs" + }, + "to": { "groupId": "cl1sfdroa00452e6e5o458z9h" } + }, + { + "id": "cl1sfedcd004b2e6eerh8hz33", + "from": { + "blockId": "cl1sfbbw3003t2e6e16ec9w29", + "itemId": "cl1sfc545003x2e6e833juo6m" + }, + "to": { "groupId": "cl1sfe2kn00472e6ead4qs2d9" } + }, + { + "id": "cl1sfeg2k004c2e6eu9rjnski", + "from": { "blockId": "cl1sfdrpi00462e6emfd9sj14" }, + "to": { "groupId": "cl1sf4qk500332e6e8gs5mn3t" } + }, + { + "id": "cl1sfeik5004d2e6ejj03f1gn", + "from": { "blockId": "cl1sfe2kn00482e6eukp8r9bj" }, + "to": { "groupId": "cl1sf4qk500332e6e8gs5mn3t" } + }, + { + "id": "cl1sfek9r004e2e6elkh3h7a2", + "from": { "blockId": "cl1sfbbw3003t2e6e16ec9w29" }, + "to": { "groupId": "cl1sf4qk500332e6e8gs5mn3t" } + }, + { + "id": "cl1sfen6a004f2e6estkfooss", + "from": { "blockId": "cl1sf2iix002n2e6egibs95yb" }, + "to": { "groupId": "cl1sfbbv0003s2e6eheyhv7ke" } + }, + { + "id": "cl1sfeog5004g2e6eiil842nb", + "from": { "blockId": "cl1sf36ib002v2e6ejyyrrjnh" }, + "to": { "groupId": "cl1sfbbv0003s2e6eheyhv7ke" } + }, + { + "id": "cl1sfeq3f004h2e6eglhjyx2o", + "from": { "blockId": "cl1sf2wom002s2e6e8cmcnhpn" }, + "to": { "groupId": "cl1sfbbv0003s2e6eheyhv7ke" } + }, + { + "id": "cl1sfertf004i2e6epf68fwri", + "from": { + "blockId": "cl1ses31000222e6ebrb4wxo0", + "itemId": "cl1ses3y400242e6e1qjwkhq4" + }, + "to": { "groupId": "cl1sfbbv0003s2e6eheyhv7ke" } + }, + { + "id": "cl1sfg9fc004k2e6egywpim9v", + "from": { + "blockId": "cl1sfat0h003p2e6e7j0hpilh", + "itemId": "cl1sfat0h003q2e6eyx6vxe0f" + }, + "to": { "groupId": "cl1sffxet004j2e6ec6gfbffh" } + }, + { + "id": "cl1sfgtau004n2e6ev68sikcr", + "from": { "blockId": "cl1sfat0h003p2e6e7j0hpilh" }, + "to": { "groupId": "cl1sfgjlr004l2e6erykli1ud" } + } + ], + "variables": [ + { "id": "vcl1sezzln002b2e6e6ssxh9bf", "name": "Lead Score" }, + { "id": "vcl1sf1ko5002g2e6egjmyb16v", "name": "Team size" }, + { "id": "vcl1sf525q00362e6eoyosycte", "name": "Country" }, + { "id": "vcl1sf93s2003l2e6eojomb66g", "name": "Company" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-06T16:55:57.664Z", + "updatedAt": "2023-11-06T16:55:57.664Z", + "icon": "🏆", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/movie-recommendation.json b/apps/builder/public/templates/movie-recommendation.json new file mode 100644 index 0000000..369b6f0 --- /dev/null +++ b/apps/builder/public/templates/movie-recommendation.json @@ -0,0 +1,582 @@ +{ + "version": "6", + "id": "cloo0wet7000h1aor38uwjxjw", + "name": "Movie recommendation", + "events": [ + { + "id": "u6lpjibfjhyoqij5wjf9kvnl", + "outgoingEdgeId": "wfec8f4e1jtden2wqna6nrso", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "mjnkukpkpvf4ha2g4n5m804v", + "title": "Menu", + "graphCoordinates": { "x": 243.1, "y": 12.32 }, + "blocks": [ + { + "id": "kjlf184vxf0uorniwje28iqb", + "type": "Set variable", + "options": { + "variableId": "vh5bxx07kl3016wr1undh2yb3", + "expressionToEvaluate": "2f584d1ffe2b7fb082dd4e05038e9bd7" + } + }, + { + "id": "f5rr5wi9zldun13tw79u9z2n", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Welcome to our film recommendation bot 👋" } + ] + } + ] + } + }, + { + "id": "c7swi84rmdvrul0wz5kxtplm", + "type": "image", + "content": { + "url": "https://media3.giphy.com/media/BElb9DVpHezcZufOhl/giphy-downsized.gif?cid=fe3852a3uwhsp1sc3j6avr625v5e94h1v8o3wfb1ii3xwswk&rid=giphy-downsized.gif&ct=g" + } + }, + { + "id": "nlihfc4ptxnxoktqblh6mcql", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "It is powered by The Movie DB API 🚀" }] + } + ] + } + }, + { + "id": "vr73urm54d9mq2oqg7ey1xh8", + "type": "image", + "content": { + "url": "https://www.themoviedb.org/assets/2/v4/logos/v2/blue_square_1-5bdc75aaebeb75dc7ae79426ddd9be3b2be1e342510f8202baf6bffa71d7f5c4.svg" + } + }, + { + "id": "g5yyuh9g75x7xa7fgqhhi1zz", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How can I we help?" }] } + ] + } + }, + { + "id": "tzf45bvd8iquoxz7qgta8v94", + "type": "choice input", + "items": [ + { + "id": "kaimvzg9igdtktgou5m3s1bw", + "outgoingEdgeId": "t8qyjpigrz7cdl8gxl1wxlwj", + "content": "Select a genre 💅" + }, + { + "id": "i8ls2f8inq2ovuijj6l7rbcq", + "outgoingEdgeId": "tjn2ljosqyd4aj9dk8mnifsu", + "content": "See what's trending 🔝" + } + ] + } + ] + }, + { + "id": "kq1g5z6pz4buot7sawqdrr3s", + "title": "Genre", + "graphCoordinates": { "x": 607.85, "y": 295.32 }, + "blocks": [ + { + "id": "ecwz96cghzp4ji3lyx7taxt1", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }] + } + }, + { + "id": "gd4lt2pcljer6zaf7v9hkr1k", + "type": "Webhook", + "options": { + "variablesForTest": [ + { + "id": "oqbhwya4cewto5pfjmftjmpn", + "variableId": "vh5bxx07kl3016wr1undh2yb3", + "value": "2f584d1ffe2b7fb082dd4e05038e9bd7" + } + ], + "responseVariableMapping": [ + { + "id": "bm186wvb4e2aqj1myx5gc251", + "variableId": "vx0bbqzug4vk3zpc31ly8k7al", + "bodyPath": "data.genres.flatMap(item => item.name)" + }, + { + "id": "xsrhvxf3hv74e2hkokmdflbc", + "variableId": "vwc00rydyp035vtb0nlaqyzwr", + "bodyPath": "data.genres.flatMap(item => item.id)" + } + ], + "isAdvancedConfig": true, + "webhook": { + "queryParams": [ + { + "id": "gq6m7x2k20qzrj752qi2zpmu", + "key": "api_key", + "value": "{{API Key}}" + } + ], + "method": "GET", + "url": "https://api.themoviedb.org/3/genre/movie/list" + } + } + }, + { + "id": "qeyvu7uq5tkvo7uo8iaj87z5", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Select your desired genre 👇" }] + } + ] + } + }, + { + "id": "nwuk2clo78hmnh4d0g31u9xg", + "type": "choice input", + "items": [ + { "id": "ri3avm9p0i96p8gx4028b6ye", "content": "Click to edit" } + ], + "options": { + "variableId": "vkmbb3rb2hcfd2io1fhf7rz5x", + "dynamicVariableId": "vx0bbqzug4vk3zpc31ly8k7al" + } + }, + { + "id": "j7pm34um4piuyabwlobjc356", + "outgoingEdgeId": "tfuuwjnpn7mftd5s65mbhytd", + "type": "Set variable", + "options": { + "variableId": "vwewa4yugqch2sswdpneszk3i", + "type": "Map item with same index", + "mapListItemParams": { + "baseItemVariableId": "vkmbb3rb2hcfd2io1fhf7rz5x", + "baseListVariableId": "vx0bbqzug4vk3zpc31ly8k7al", + "targetListVariableId": "vwc00rydyp035vtb0nlaqyzwr" + } + } + } + ] + }, + { + "id": "d6v9lh83c7zuwrhf2mmo6nxo", + "title": "Trending", + "graphCoordinates": { "x": 599.83, "y": 880.98 }, + "blocks": [ + { + "id": "edokvbp15ubqeuydw9n7wf4w", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }] + } + }, + { + "id": "pwxb57b8nc2bp764vcdstois", + "type": "Webhook", + "options": { + "variablesForTest": [ + { + "id": "oqbhwya4cewto5pfjmftjmpn", + "variableId": "vh5bxx07kl3016wr1undh2yb3", + "value": "2f584d1ffe2b7fb082dd4e05038e9bd7" + } + ], + "responseVariableMapping": [ + { + "id": "g5ga79m1dzgp28chaxlj2i72", + "variableId": "vkzk96oh1pmdjv2bt5ps60qc0", + "bodyPath": "data.results.flatMap(item => item.title)" + }, + { + "id": "albmykstahw37np5gjuafxie", + "variableId": "vcmybxcoaytd2geo5sqx7v8hw", + "bodyPath": "data.results.flatMap(item => item.id)" + } + ], + "isAdvancedConfig": true, + "webhook": { + "queryParams": [ + { + "id": "x9nxr63itm2lvbe8dmi53mi7", + "key": "api_key", + "value": "{{API Key}}" + } + ], + "method": "GET", + "url": "https://api.themoviedb.org/3/trending/movie/week" + } + } + }, + { + "id": "ruhgtbpv18cy2g5ujavljkku", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Here are popular movies this week 👇" }] + } + ] + } + }, + { + "id": "krcvvncnqtn99v0qe1dzudrk", + "type": "choice input", + "items": [ + { "id": "dicb6lnv5kapkq0tygnx1abh", "content": "Click to edit" } + ], + "options": { + "variableId": "vulnb1om2fk8mvkcesl8s15cr", + "dynamicVariableId": "vkzk96oh1pmdjv2bt5ps60qc0" + } + }, + { + "id": "mgn6uuw2yebmengsukjramjx", + "outgoingEdgeId": "ual6xszx6tfcxqrnihc6zrvx", + "type": "Set variable", + "options": { + "variableId": "vzslfw8oyo1f08uo5rpkegn0x", + "type": "Map item with same index", + "mapListItemParams": { + "baseItemVariableId": "vulnb1om2fk8mvkcesl8s15cr", + "baseListVariableId": "vkzk96oh1pmdjv2bt5ps60qc0", + "targetListVariableId": "vcmybxcoaytd2geo5sqx7v8hw" + } + } + } + ] + }, + { + "id": "v35sky44jzz9fkwwul2qxufl", + "title": "Movies by genre", + "graphCoordinates": { "x": 952.84, "y": 294.85 }, + "blocks": [ + { + "id": "g2pgwx5yr1ou9vkoy6gdwuor", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Here are trending movies for the {{Selected genre}} genre" + } + ] + } + ] + } + }, + { + "id": "a2datk3pv8o6xgitwjsq61m2", + "type": "Webhook", + "options": { + "variablesForTest": [ + { + "id": "oqbhwya4cewto5pfjmftjmpn", + "variableId": "vh5bxx07kl3016wr1undh2yb3", + "value": "2f584d1ffe2b7fb082dd4e05038e9bd7" + }, + { + "id": "rofxlzwrcv1ksy8aub8cfi6p", + "variableId": "vwewa4yugqch2sswdpneszk3i", + "value": "16" + } + ], + "responseVariableMapping": [ + { + "id": "w8k1bxjsfkjxt64eev1ib96w", + "variableId": "vad8vq3jfyybxo4la57hfd529", + "bodyPath": "data.results.flatMap(item => item.title)" + }, + { + "id": "zysikjyevakboax3czzec7nt", + "variableId": "vhc2pc1sv4xc778r9od2ctooz", + "bodyPath": "data.results.flatMap(item => item.id)" + } + ], + "isAdvancedConfig": true, + "webhook": { + "queryParams": [ + { + "id": "mgwlp399a056o9jo93tjqp02", + "key": "api_key", + "value": "{{API Key}}" + }, + { + "id": "dv4wioynywqo57jq8lakq3yr", + "key": "with_genres", + "value": "{{Selected genre ID}}" + } + ], + "method": "GET", + "url": "https://api.themoviedb.org/3/discover/movie" + } + } + }, + { + "id": "tr5y76tx9ca336f8ob9odfa6", + "type": "choice input", + "items": [ + { "id": "uy2xwxoqhqol852cqsq17r9l", "content": "Click to edit" } + ], + "options": { + "variableId": "vyyr3j2pu76uzvf88laai8snl", + "dynamicVariableId": "vad8vq3jfyybxo4la57hfd529" + } + }, + { + "id": "vudr8jrv2k3x0ubemt39tv7a", + "outgoingEdgeId": "r4wyd2185zhen98r5pmx53g9", + "type": "Set variable", + "options": { + "variableId": "vzslfw8oyo1f08uo5rpkegn0x", + "type": "Map item with same index", + "mapListItemParams": { + "baseItemVariableId": "vyyr3j2pu76uzvf88laai8snl", + "baseListVariableId": "vad8vq3jfyybxo4la57hfd529", + "targetListVariableId": "vhc2pc1sv4xc778r9od2ctooz" + } + } + } + ] + }, + { + "id": "uozlg88loeb8xegu6y4le6k8", + "title": "Movie details", + "graphCoordinates": { "x": 1151.05, "y": 913.34 }, + "blocks": [ + { + "id": "ve9m7fromxw4tbm8558n8520", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Excellent choice 🔥" }] } + ] + } + }, + { + "id": "xag9d5i5td40kdt3poyq5g4b", + "type": "Webhook", + "options": { + "variablesForTest": [ + { + "id": "oqbhwya4cewto5pfjmftjmpn", + "variableId": "vh5bxx07kl3016wr1undh2yb3", + "value": "2f584d1ffe2b7fb082dd4e05038e9bd7" + }, + { + "id": "ja5qwkznouhm00x8zvlghuk4", + "variableId": "vzslfw8oyo1f08uo5rpkegn0x", + "value": "965839" + } + ], + "responseVariableMapping": [ + { + "id": "dsfek7nejs1a7qqs4v61z709", + "variableId": "vdvjx1w1sorma4zq0qtsdqrdi", + "bodyPath": "data.imdb_id" + }, + { + "id": "dtd0rrmz04m5gsi1gq855v1d", + "variableId": "vzns0wpumgo8vxjdty2w5t54a", + "bodyPath": "data.overview" + }, + { + "id": "y53g06r3xml0f3jmpctlsgm1", + "variableId": "vzf5ryexokpr4dihiur2spm8z", + "bodyPath": "data.poster_path" + } + ], + "isAdvancedConfig": true, + "webhook": { + "queryParams": [ + { + "id": "f33u3unbezibfdv54kbkien3", + "key": "api_key", + "value": "{{API Key}}" + } + ], + "method": "GET", + "url": "https://api.themoviedb.org/3/movie/{{Selected Movie ID}}" + } + } + }, + { + "id": "d0rsus9shxj8iowczbcaw53i", + "type": "Set variable", + "options": { + "variableId": "vwitf3um5uweynypc0hxxwm14", + "expressionToEvaluate": "https://image.tmdb.org/t/p/w185{{Poster path}}" + } + }, + { + "id": "nqnry4c1z3wwcni8rwpduuhe", + "type": "image", + "content": { "url": "{{Poster URL}}" } + }, + { + "id": "lhljw54rdykyqtjiuh6jsl5c", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "{{Movie Overview}}" }] } + ] + } + }, + { + "id": "yifjhiamifo1y4ay7vols0mm", + "type": "choice input", + "items": [ + { + "id": "n4818dnrb4arw1xh5v0ot8vz", + "outgoingEdgeId": "fteu5frsbj8wejfhhwzuv8t1", + "content": "Watch the movie" + }, + { + "id": "j9d1pf2tndax0itezys7t73c", + "outgoingEdgeId": "zb79atxs2itliks4d00e35uy", + "content": "Find something else" + } + ] + } + ] + }, + { + "id": "x4d8cdsyzoqz6vzsurnb8twc", + "title": "Redirect to IMDB", + "graphCoordinates": { "x": 1523.21, "y": 1433.33 }, + "blocks": [ + { + "id": "mw0e0bzwiokhndkkncp9niu2", + "type": "Redirect", + "options": { + "url": "https://m.imdb.com/title/{{IMDB ID}}" + } + } + ] + }, + { + "id": "x9610wtdv125hg56wicm2qmv", + "title": "", + "graphCoordinates": { "x": 1523.2, "y": 1620.1 }, + "blocks": [ + { + "id": "efto9jivvcvomj3kltf57hbb", + "type": "Jump", + "options": { + "groupId": "mjnkukpkpvf4ha2g4n5m804v", + "blockId": "tzf45bvd8iquoxz7qgta8v94" + } + } + ] + } + ], + "edges": [ + { + "id": "wfec8f4e1jtden2wqna6nrso", + "from": { "eventId": "u6lpjibfjhyoqij5wjf9kvnl" }, + "to": { "groupId": "mjnkukpkpvf4ha2g4n5m804v" } + }, + { + "id": "t8qyjpigrz7cdl8gxl1wxlwj", + "from": { + "blockId": "tzf45bvd8iquoxz7qgta8v94", + "itemId": "kaimvzg9igdtktgou5m3s1bw" + }, + "to": { "groupId": "kq1g5z6pz4buot7sawqdrr3s" } + }, + { + "id": "tfuuwjnpn7mftd5s65mbhytd", + "from": { "blockId": "j7pm34um4piuyabwlobjc356" }, + "to": { "groupId": "v35sky44jzz9fkwwul2qxufl" } + }, + { + "id": "r4wyd2185zhen98r5pmx53g9", + "from": { "blockId": "vudr8jrv2k3x0ubemt39tv7a" }, + "to": { "groupId": "uozlg88loeb8xegu6y4le6k8" } + }, + { + "id": "fteu5frsbj8wejfhhwzuv8t1", + "from": { + "blockId": "yifjhiamifo1y4ay7vols0mm", + "itemId": "n4818dnrb4arw1xh5v0ot8vz" + }, + "to": { "groupId": "x4d8cdsyzoqz6vzsurnb8twc" } + }, + { + "id": "tjn2ljosqyd4aj9dk8mnifsu", + "from": { + "blockId": "tzf45bvd8iquoxz7qgta8v94", + "itemId": "i8ls2f8inq2ovuijj6l7rbcq" + }, + "to": { "groupId": "d6v9lh83c7zuwrhf2mmo6nxo" } + }, + { + "id": "ual6xszx6tfcxqrnihc6zrvx", + "from": { "blockId": "mgn6uuw2yebmengsukjramjx" }, + "to": { "groupId": "uozlg88loeb8xegu6y4le6k8" } + }, + { + "id": "zb79atxs2itliks4d00e35uy", + "from": { + "blockId": "yifjhiamifo1y4ay7vols0mm", + "itemId": "j9d1pf2tndax0itezys7t73c" + }, + "to": { "groupId": "x9610wtdv125hg56wicm2qmv" } + } + ], + "variables": [ + { "id": "vh5bxx07kl3016wr1undh2yb3", "name": "API Key" }, + { "id": "vx0bbqzug4vk3zpc31ly8k7al", "name": "Genres" }, + { "id": "vkmbb3rb2hcfd2io1fhf7rz5x", "name": "Selected genre" }, + { "id": "vwc00rydyp035vtb0nlaqyzwr", "name": "Genre IDs" }, + { "id": "vwewa4yugqch2sswdpneszk3i", "name": "Selected genre ID" }, + { "id": "vad8vq3jfyybxo4la57hfd529", "name": "Movies" }, + { "id": "vhc2pc1sv4xc778r9od2ctooz", "name": "Movie IDs" }, + { "id": "vyyr3j2pu76uzvf88laai8snl", "name": "Selected Movie" }, + { "id": "vzslfw8oyo1f08uo5rpkegn0x", "name": "Selected Movie ID" }, + { "id": "vdvjx1w1sorma4zq0qtsdqrdi", "name": "IMDB ID" }, + { "id": "vzns0wpumgo8vxjdty2w5t54a", "name": "Movie Overview" }, + { "id": "vzf5ryexokpr4dihiur2spm8z", "name": "Poster path" }, + { "id": "vwitf3um5uweynypc0hxxwm14", "name": "Poster URL" }, + { "id": "vkzk96oh1pmdjv2bt5ps60qc0", "name": "Trending Movies" }, + { "id": "vcmybxcoaytd2geo5sqx7v8hw", "name": "Trending IDs" }, + { "id": "vulnb1om2fk8mvkcesl8s15cr", "name": "Selected Trending Movie" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:42:02.490Z", + "updatedAt": "2023-11-07T07:55:03.222Z", + "icon": "🍿", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/nps.json b/apps/builder/public/templates/nps.json new file mode 100644 index 0000000..0525722 --- /dev/null +++ b/apps/builder/public/templates/nps.json @@ -0,0 +1,595 @@ +{ + "version": "6", + "id": "cloo0bge500071aorb4dadsju", + "name": "NPS Survey", + "events": [ + { + "id": "yu8qfeteutmum1ghb0wqshu9", + "outgoingEdgeId": "qtd5p5sya9w8yoknvbhy493i", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "g7l1tc86ty1r6x0yn0r2g1xo", + "title": "Intro", + "graphCoordinates": { "x": 10.99, "y": 85.96 }, + "blocks": [ + { + "id": "vep990mmfbe64nqczp66xebw", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hey! 👋" }] }] + } + }, + { + "id": "u1oeokc5j8bzwi4lwqyf7c8q", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Since you are part of our daily users, can I ask you " + }, + { "bold": true, "text": "2 questions" }, + { "text": "?" } + ] + } + ] + } + }, + { + "id": "d3asw3zs2gahpxs3usun6lm5", + "type": "choice input", + "items": [ + { + "id": "wvjhc2vrkqy8512y0wvmciex", + "outgoingEdgeId": "sjeyoptun1yu805ry37je1ni", + "content": "Sure!" + } + ] + } + ] + }, + { + "id": "xgqei015z6d58gefpviz8053", + "title": "Recommendation", + "graphCoordinates": { "x": 360.5, "y": 86.64 }, + "blocks": [ + { + "id": "jcp3qhpb4wf95g0ylrp4e8zb", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "How likely will you recommend our product" }, + { "bold": true, "text": " " }, + { "text": "to a friend or colleague?" } + ] + } + ] + } + }, + { + "id": "bfvv74k8oz57kaqeqek3uen7", + "type": "rating input", + "options": { + "variableId": "vwqc8tzl0380h30vxh07fekmm", + "labels": { + "left": "Very unlikely", + "right": "Very likely" + }, + "isOneClickSubmitEnabled": true + } + }, + { + "id": "z76m5qjuy15sa6b0p1re0nkp", + "outgoingEdgeId": "niec249stbfa2obm9mkd1pgw", + "type": "Condition", + "items": [ + { + "id": "xy6ni2aj5dxys27itzbtvdzw", + "outgoingEdgeId": "zug5c4jy98sywgp1amtms6oc", + "content": { + "comparisons": [ + { + "id": "r7s1l7ljsv7ugnbaz4u3gy5a", + "variableId": "vwqc8tzl0380h30vxh07fekmm", + "comparisonOperator": "Greater than", + "value": "8" + } + ] + } + }, + { + "id": "vrhf4u4dt6u146eywqybgrk2", + "outgoingEdgeId": "qb38wjfqzksaujoppzrrto25", + "content": { + "comparisons": [ + { + "id": "chowr4hsu9butjlwo0ul874g", + "variableId": "vwqc8tzl0380h30vxh07fekmm", + "comparisonOperator": "Greater than", + "value": "6" + } + ] + } + } + ] + } + ] + }, + { + "id": "rp2r31gn1w5t1aeej96bhjj3", + "title": "Good", + "graphCoordinates": { "x": 1078.85, "y": 292.9 }, + "blocks": [ + { + "id": "izehojk23xug74tylpm0wbib", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "I'm glad to hear that 😍" }] + } + ] + } + }, + { + "id": "qj3e1cxwjub800r6g3lfa4ei", + "outgoingEdgeId": "hycn6wx0j9ug4wf5vzz9aytx", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Could you tell us why?" }] + } + ] + } + } + ] + }, + { + "id": "sk1n3wpfit3uvfrh42fgcykm", + "title": "Why?", + "graphCoordinates": { "x": 1425.22, "y": 445.48 }, + "blocks": [ + { + "id": "ro6a6dt7j3x99unduh5jm6an", + "outgoingEdgeId": "y6gsa6pjrfeu8zi6evtzirs1", + "type": "text input", + "options": { + "isLong": true + } + } + ] + }, + { + "id": "qj9qgsbfv6u1f5oe1bjnwnu9", + "title": "Bad", + "graphCoordinates": { "x": 1067.22, "y": 575.86 }, + "blocks": [ + { + "id": "ou7airondk1mxm4inzzyyr1x", + "outgoingEdgeId": "glj5ishgke8i6s6eyjnmbel1", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Could you tell us what went wrong?" }] + } + ] + } + } + ] + }, + { + "id": "tavt0nuh54ck1hvq74kt74vf", + "title": "Set type", + "graphCoordinates": { "x": 726.83, "y": 234.02 }, + "blocks": [ + { + "id": "vdythdfi91vr47ipbfalddc6", + "outgoingEdgeId": "r74zv3gamsln3dbmp1gvxpa2", + "type": "Set variable", + "options": { + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "expressionToEvaluate": "Promoter" + } + } + ] + }, + { + "id": "e887eoxfamv45hj8bz47jize", + "title": "Set type", + "graphCoordinates": { "x": 722.39, "y": 399.91 }, + "blocks": [ + { + "id": "w40rjuv0avoetpdj6l5nbiz6", + "outgoingEdgeId": "x62wj4inzidyj03ktiyu0g81", + "type": "Set variable", + "options": { + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "expressionToEvaluate": "Neutral" + } + } + ] + }, + { + "id": "z4qtvedlz3mzcj4jdnfet2dc", + "title": "Set type", + "graphCoordinates": { "x": 722.56, "y": 566.11 }, + "blocks": [ + { + "id": "melr0p8nxssxe1qyat748uyy", + "outgoingEdgeId": "q5xllqzy4x1q3tdvpr1piwgi", + "type": "Set variable", + "options": { + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "expressionToEvaluate": "Detractor" + } + } + ] + }, + { + "id": "l7fupza0yi6os0ix6heyd7jz", + "title": "Final segmentation", + "graphCoordinates": { "x": 1777.5859375, "y": 396.8453917968819 }, + "blocks": [ + { + "id": "z4gsshsckqdu6m1umartgxgb", + "type": "Condition", + "items": [ + { + "id": "vd6ls562brvt5kld746ao63x", + "outgoingEdgeId": "fcels3dp2kabntjscmirxtl7", + "content": { + "comparisons": [ + { + "id": "gclfcip3hr0p4vzk5o8n60ru", + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "comparisonOperator": "Equal to", + "value": "Promoter" + } + ] + } + }, + { + "id": "vey2i7kouphj3dgzz1rtwuxb", + "outgoingEdgeId": "jyen1rcq5cxek118gkio0u6d", + "content": { + "comparisons": [ + { + "id": "p7shnc0g3b377oip57r7xneq", + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "comparisonOperator": "Equal to", + "value": "Neutral" + } + ] + } + }, + { + "id": "cdi4c43wbyi3ajdns5klfg1g", + "outgoingEdgeId": "jjymvdpeyfqu2qpo6hh2zxeo", + "content": { + "comparisons": [ + { + "id": "iy13qo2guletobbkauklye7a", + "variableId": "vcgkjbh8intf2cql1oteyj4mu", + "comparisonOperator": "Equal to", + "value": "Detractor" + } + ] + } + } + ] + } + ] + }, + { + "id": "pp1ncsdaki07pfq5pjl53v6r", + "title": "Capterra?", + "graphCoordinates": { "x": 2160.71875, "y": 69.58984375 }, + "blocks": [ + { + "id": "eixinwxcgsng6v8blw6jdgwy", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Thank you! 🙏" }] } + ] + } + }, + { + "id": "cjqu4wje2zr8i5ehivxv5567", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Would you be ok to leave a review on Capterra?" } + ] + } + ] + } + }, + { + "id": "v9pf4n5kcwon4g0yvwwc6vk3", + "type": "choice input", + "items": [ + { + "id": "y34d4iij8y9qrt28y240x7vm", + "outgoingEdgeId": "lw33kviri91z1mvxb87kaew0", + "content": "Sure!" + }, + { + "id": "l7txnq6jtm0niynklcpzb21u", + "outgoingEdgeId": "wjcvbnj1drs6if1p21a8yokf", + "content": "Maybe later" + } + ] + } + ] + }, + { + "id": "znljx8q0q2ggih0ipu28ryby", + "title": "Bye cheerful", + "graphCoordinates": { "x": 2167.570274174784, "y": 543.712381679639 }, + "blocks": [ + { + "id": "m1my2b6gqq2hgfecw1vs2vcm", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Thank you for taking the time to answer!" } + ] + } + ] + } + }, + { + "id": "fyl3k7qc6jdmc8t38b9wkcrh", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Have a beautiful day!" }] } + ] + } + }, + { + "id": "qobvos2ihgxb8e729ur8b2rv", + "type": "image", + "content": { + "url": "https://media3.giphy.com/media/qC2REWsp3fQ1v2mm74/giphy.gif?cid=fe3852a38k350b15tly68dp7plh5iskmlonklrofvce975cq&rid=giphy.gif&ct=g" + } + } + ] + }, + { + "id": "vvbtgh5ptk49shyjn3zn6d71", + "title": "Bye sad", + "graphCoordinates": { "x": 2173.366603864535, "y": 949.7063235658585 }, + "blocks": [ + { + "id": "dfisk4xq8csn0t2aute6hbsd", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Sorry that your experience hasn't been amazing 🙁" + } + ] + } + ] + } + }, + { + "id": "u6vs0akagfjg63zq8z1rcc14", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Here is a promo code if you'd like to give our product another chance: " + }, + { "bold": true, "text": "PROMO123" } + ] + } + ] + } + }, + { + "id": "lfk1wt96u8yrtfkof6lrianc", + "type": "image", + "content": { + "url": "https://media1.giphy.com/media/kaBU6pgv0OsPHz2yxy/giphy-downsized.gif?cid=fe3852a30aonhd3he63idx7116fsc1sydsan2ggr9uq4hs9j&rid=giphy-downsized.gif&ct=g" + } + } + ] + }, + { + "id": "mwfu8ot0z37zfq2fbo5rcyrl", + "title": "Redirect Capterra", + "graphCoordinates": { "x": 2531.28515625, "y": 300.828125 }, + "blocks": [ + { + "id": "cd8ftyg6tkjggncxuo242u3j", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Amazing 🤩" }] } + ] + } + }, + { + "id": "nigypz7fhnt07440o0829o81", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Let me take you there..." }] + } + ] + } + }, + { + "id": "xr1or6dcptogabyvv6zepmw8", + "type": "Wait", + "options": { "secondsToWaitFor": "1" } + }, + { + "id": "bfyw1eabougkp2aqlrcrf6lz", + "type": "Redirect", + "options": { + "url": "https://www.capterra.com/p/233968/Typebot/" + } + } + ] + } + ], + "edges": [ + { + "id": "qtd5p5sya9w8yoknvbhy493i", + "from": { "eventId": "yu8qfeteutmum1ghb0wqshu9" }, + "to": { "groupId": "g7l1tc86ty1r6x0yn0r2g1xo" } + }, + { + "id": "glj5ishgke8i6s6eyjnmbel1", + "from": { "blockId": "ou7airondk1mxm4inzzyyr1x" }, + "to": { "groupId": "sk1n3wpfit3uvfrh42fgcykm" } + }, + { + "id": "hycn6wx0j9ug4wf5vzz9aytx", + "from": { "blockId": "qj3e1cxwjub800r6g3lfa4ei" }, + "to": { "groupId": "sk1n3wpfit3uvfrh42fgcykm" } + }, + { + "id": "zug5c4jy98sywgp1amtms6oc", + "from": { + "blockId": "z76m5qjuy15sa6b0p1re0nkp", + "itemId": "xy6ni2aj5dxys27itzbtvdzw" + }, + "to": { "groupId": "tavt0nuh54ck1hvq74kt74vf" } + }, + { + "id": "niec249stbfa2obm9mkd1pgw", + "from": { "blockId": "z76m5qjuy15sa6b0p1re0nkp" }, + "to": { "groupId": "z4qtvedlz3mzcj4jdnfet2dc" } + }, + { + "id": "qb38wjfqzksaujoppzrrto25", + "from": { + "blockId": "z76m5qjuy15sa6b0p1re0nkp", + "itemId": "vrhf4u4dt6u146eywqybgrk2" + }, + "to": { "groupId": "e887eoxfamv45hj8bz47jize" } + }, + { + "id": "r74zv3gamsln3dbmp1gvxpa2", + "from": { "blockId": "vdythdfi91vr47ipbfalddc6" }, + "to": { "groupId": "rp2r31gn1w5t1aeej96bhjj3" } + }, + { + "id": "x62wj4inzidyj03ktiyu0g81", + "from": { "blockId": "w40rjuv0avoetpdj6l5nbiz6" }, + "to": { + "groupId": "rp2r31gn1w5t1aeej96bhjj3", + "blockId": "qj3e1cxwjub800r6g3lfa4ei" + } + }, + { + "id": "q5xllqzy4x1q3tdvpr1piwgi", + "from": { "blockId": "melr0p8nxssxe1qyat748uyy" }, + "to": { "groupId": "qj9qgsbfv6u1f5oe1bjnwnu9" } + }, + { + "id": "y6gsa6pjrfeu8zi6evtzirs1", + "from": { "blockId": "ro6a6dt7j3x99unduh5jm6an" }, + "to": { "groupId": "l7fupza0yi6os0ix6heyd7jz" } + }, + { + "id": "jjymvdpeyfqu2qpo6hh2zxeo", + "from": { + "blockId": "z4gsshsckqdu6m1umartgxgb", + "itemId": "cdi4c43wbyi3ajdns5klfg1g" + }, + "to": { "groupId": "vvbtgh5ptk49shyjn3zn6d71" } + }, + { + "id": "jyen1rcq5cxek118gkio0u6d", + "from": { + "blockId": "z4gsshsckqdu6m1umartgxgb", + "itemId": "vey2i7kouphj3dgzz1rtwuxb" + }, + "to": { "groupId": "znljx8q0q2ggih0ipu28ryby" } + }, + { + "id": "wjcvbnj1drs6if1p21a8yokf", + "from": { + "blockId": "v9pf4n5kcwon4g0yvwwc6vk3", + "itemId": "l7txnq6jtm0niynklcpzb21u" + }, + "to": { "groupId": "znljx8q0q2ggih0ipu28ryby" } + }, + { + "id": "lw33kviri91z1mvxb87kaew0", + "from": { + "blockId": "v9pf4n5kcwon4g0yvwwc6vk3", + "itemId": "y34d4iij8y9qrt28y240x7vm" + }, + "to": { "groupId": "mwfu8ot0z37zfq2fbo5rcyrl" } + }, + { + "id": "sjeyoptun1yu805ry37je1ni", + "from": { + "blockId": "d3asw3zs2gahpxs3usun6lm5", + "itemId": "wvjhc2vrkqy8512y0wvmciex" + }, + "to": { "groupId": "xgqei015z6d58gefpviz8053" } + }, + { + "id": "fcels3dp2kabntjscmirxtl7", + "from": { + "blockId": "z4gsshsckqdu6m1umartgxgb", + "itemId": "vd6ls562brvt5kld746ao63x" + }, + "to": { "groupId": "pp1ncsdaki07pfq5pjl53v6r" } + } + ], + "variables": [ + { "id": "vwqc8tzl0380h30vxh07fekmm", "name": "Recommend rate" }, + { "id": "vcgkjbh8intf2cql1oteyj4mu", "name": "Type" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:25:44.765Z", + "updatedAt": "2023-11-07T07:26:12.044Z", + "icon": "⭐", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/onboarding.json b/apps/builder/public/templates/onboarding.json new file mode 100644 index 0000000..ff0d425 --- /dev/null +++ b/apps/builder/public/templates/onboarding.json @@ -0,0 +1,343 @@ +{ + "version": "6", + "id": "cloo0gjvx00091aoryw72ns37", + "name": "Onboarding copy", + "events": [ + { + "id": "yp9qsayuwzhihxc7gzt68osm", + "outgoingEdgeId": "qehono05saho85xk59apfvtr", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "az9nafw4tu9b6dyh3cvutlek", + "title": "Name", + "graphCoordinates": { "x": 247.01, "y": 1.45 }, + "blocks": [ + { + "id": "cl1267q2c000e2e6dynjeg83n", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Welcome 👋" }] } + ] + } + }, + { + "id": "cl1267y1u000f2e6d4rlglv6g", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your name?" }] } + ] + } + }, + { + "id": "cl126820m000g2e6dfleq78bt", + "outgoingEdgeId": "j6x356fbxo32zd9ezje77t4j", + "type": "text input", + "options": { + "variableId": "cl126f4hf000i2e6d8zvzc3t1" + } + } + ] + }, + { + "id": "s3hgjtmb1bzq6ip2bm9w1r53", + "title": "Company", + "graphCoordinates": { "x": 603.62, "y": 1.09 }, + "blocks": [ + { + "id": "cl1266v6f000a2e6db7wj3ux7", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Welcome {{Name}} 👋" }] } + ] + } + }, + { + "id": "cl126hb9m000l2e6d5qk3mohn", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "I'm super pumped that you've decided to try out Typebot 😍" + } + ] + } + ] + } + }, + { + "id": "cl126hpw1000m2e6dneousygl", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You are small steps away from meaningful, hyper-personalized experience for your users" + } + ] + } + ] + } + }, + { + "id": "cl126guhd000k2e6d6ypkex9z", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Let's get you set up for your Typebot journey." } + ] + } + ] + } + }, + { + "id": "cl126ixp9000q2e6dslh0zypi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Do you work for a specific company?" }] + } + ] + } + }, + { + "id": "cl126jb2q000r2e6dgqlnxnt8", + "type": "choice input", + "items": [ + { "id": "cl126jb2q000s2e6dm60yq5p2", "content": "Yes" }, + { + "id": "cl126jc5a000t2e6dqv91w7j6", + "outgoingEdgeId": "dhva247te6v1cwfbte78bx4v", + "content": "No" + } + ] + }, + { + "id": "cl126jioz000v2e6dwrk1f2cb", + "outgoingEdgeId": "c5qdoivxsbhu1mkxkmw9yxft", + "type": "text input", + "options": { + "labels": { + "placeholder": "Type the company name..." + }, + "variableId": "cl126jqww000w2e6dq9yv4ifq" + } + } + ] + }, + { + "id": "m8k3pv1rjckh3arxgitwo43i", + "title": "Bot category", + "graphCoordinates": { "x": 972.94, "y": -0.07 }, + "blocks": [ + { + "id": "cl126krck00112e6d1m6ctxpn", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "What type of bots are you planning to build with Typebot?" + } + ] + } + ] + } + }, + { + "id": "cl126lb8v00142e6duv5qe08l", + "type": "choice input", + "items": [ + { + "id": "cl126onz9001g2e6dk0nbjeu6", + "content": "Lead qualification" + }, + { + "id": "cl126lm6c00172e6d1pfvdiju", + "content": "Customer support" + }, + { + "id": "cl126orr2001h2e6d0fqs7737", + "content": "Customer research" + }, + { "id": "cl126oudu001i2e6dktwi7qwv", "content": "User onboarding" }, + { "id": "cl126luv500192e6dl317ssyr", "content": "Quizzes" }, + { + "id": "cl126lz8q001a2e6d8b9lb3b5", + "content": "Content distribution" + }, + { "id": "cl126nf7k001d2e6dg2zczjgz", "content": "FAQ" }, + { "id": "cl126ngy8001e2e6ddfo5s9fm", "content": "Other" } + ], + "options": { + "variableId": "cl126mo3t001b2e6dvyi16bkd", + "isMultipleChoice": true + } + }, + { + "id": "cl1278gyk002w2e6d744eb87n", + "outgoingEdgeId": "zvr4qou4drmkvyyikya9y6ku", + "type": "Condition", + "items": [ + { + "id": "cl1278gyk002x2e6dwmpzs3nf", + "outgoingEdgeId": "mgsnzw7w104odi0mz9qjg8hf", + "content": { + "comparisons": [ + { + "id": "cl1278irq002y2e6dv4965diw", + "variableId": "cl126mo3t001b2e6dvyi16bkd", + "comparisonOperator": "Contains", + "value": "Other" + } + ] + } + } + ] + } + ] + }, + { + "id": "cnf2ljrlt875d005783ju7hc", + "title": "Bye", + "graphCoordinates": { "x": 1522.31, "y": 220.27 }, + "blocks": [ + { + "id": "cl126p76d001k2e6dbhnf2ysq", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Thank you for answering those questions!" } + ] + } + ] + } + }, + { + "id": "cl126rfy6001t2e6d21gcb6b0", + "type": "image", + "content": { + "url": "https://media4.giphy.com/media/l0amJzVHIAfl7jMDos/giphy.gif?cid=fe3852a3i4c33635xdtj3nesr9uq4zteujaab6b0jr42gpxx&rid=giphy.gif&ct=g" + } + }, + { + "id": "agi2i9xxed4jvv40rnrkf23r", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "See you soon 🚀" }] } + ] + } + } + ] + }, + { + "id": "hduy797g246pj8qnhsxy5kt5", + "title": "Other category", + "graphCoordinates": { "x": 1310.68, "y": -6.8 }, + "blocks": [ + { + "id": "cl127yxym000b2e6d9hksxo6h", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What else?" }] } + ] + } + }, + { + "id": "cl126pv7n001o2e6dajltc4qz", + "outgoingEdgeId": "vk0mgizwhw761s9eo9lx88yv", + "type": "text input", + "options": { + "variableId": "cl126q38p001q2e6d0hj23f6b" + } + } + ] + } + ], + "edges": [ + { + "id": "qehono05saho85xk59apfvtr", + "from": { "eventId": "yp9qsayuwzhihxc7gzt68osm" }, + "to": { "groupId": "az9nafw4tu9b6dyh3cvutlek" } + }, + { + "id": "dhva247te6v1cwfbte78bx4v", + "from": { + "blockId": "cl126jb2q000r2e6dgqlnxnt8", + "itemId": "cl126jc5a000t2e6dqv91w7j6" + }, + "to": { "groupId": "m8k3pv1rjckh3arxgitwo43i" } + }, + { + "id": "mgsnzw7w104odi0mz9qjg8hf", + "from": { + "blockId": "cl1278gyk002w2e6d744eb87n", + "itemId": "cl1278gyk002x2e6dwmpzs3nf" + }, + "to": { "groupId": "hduy797g246pj8qnhsxy5kt5" } + }, + { + "id": "zvr4qou4drmkvyyikya9y6ku", + "from": { "blockId": "cl1278gyk002w2e6d744eb87n" }, + "to": { "groupId": "cnf2ljrlt875d005783ju7hc" } + }, + { + "id": "c5qdoivxsbhu1mkxkmw9yxft", + "from": { "blockId": "cl126jioz000v2e6dwrk1f2cb" }, + "to": { "groupId": "m8k3pv1rjckh3arxgitwo43i" } + }, + { + "id": "j6x356fbxo32zd9ezje77t4j", + "from": { "blockId": "cl126820m000g2e6dfleq78bt" }, + "to": { "groupId": "s3hgjtmb1bzq6ip2bm9w1r53" } + }, + { + "id": "vk0mgizwhw761s9eo9lx88yv", + "from": { "blockId": "cl126pv7n001o2e6dajltc4qz" }, + "to": { "groupId": "cnf2ljrlt875d005783ju7hc" } + } + ], + "variables": [ + { "id": "cl126f4hf000i2e6d8zvzc3t1", "name": "Name" }, + { "id": "cl126jqww000w2e6dq9yv4ifq", "name": "Company" }, + { "id": "cl126mo3t001b2e6dvyi16bkd", "name": "Categories" }, + { "id": "cl126q38p001q2e6d0hj23f6b", "name": "Other categories" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-11-07T07:29:42.573Z", + "updatedAt": "2023-11-07T07:30:16.347Z", + "icon": null, + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/openai-conditions.json b/apps/builder/public/templates/openai-conditions.json new file mode 100644 index 0000000..283516f --- /dev/null +++ b/apps/builder/public/templates/openai-conditions.json @@ -0,0 +1,269 @@ +{ + "version": "6", + "id": "clpnu4plq00051abo2487q86h", + "name": "ChatGPT condition", + "events": [ + { + "id": "ewnfbo0exlu7ihfu2lu2lusm", + "outgoingEdgeId": "q2fpvz66ei3gd6k3wwq6w8f2", + "graphCoordinates": { "x": -228.25, "y": -123.31 }, + "type": "start" + } + ], + "groups": [ + { + "id": "qfrz5nwm63g12dajsjxothb5", + "title": "User input", + "graphCoordinates": { "x": -107.01, "y": -53.23 }, + "blocks": [ + { + "id": "emjcjxlvzm2xex10exq4wf5h", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "How can we help?" }] } + ] + } + }, + { + "id": "ovgk70u0kfxrbtz9dy4e040o", + "outgoingEdgeId": "n396v90ad7quz0gwygr6n5fc", + "type": "text input", + "options": { "variableId": "vudksu3zyrat6s1bq6qne0rx3" } + } + ] + }, + { + "id": "bh3uva3254p0jgp46gj92way", + "title": "Condition 🧠", + "graphCoordinates": { "x": 228.67, "y": -50.67 }, + "blocks": [ + { + "id": "ufwpq6z392ebsu5tda0md77a", + "type": "openai", + "options": { + "action": "Create chat completion", + "messages": [ + { + "role": "system", + "content": "You are helpful assistant doing customer support for a software called Typebot.\n\nIf the user is asking a question about his account, please say \"ACCOUNT\".\n\nIf the user wants to talk to a human, please say \"HUMAN\".\n\nOtherwise, say \"OK\"" + }, + { "role": "user", "content": "Can I talk to a human?" }, + { "role": "assistant", "content": "HUMAN" }, + { "role": "user", "content": "I need to check my account" }, + { "role": "assistant", "content": "ACCOUNT" }, + { "role": "user", "content": "{{User Message}}" } + ], + "credentialsId": "clpjnjrbt00051aliw6610w1z", + "responseMapping": [ + { + "item": "Message content", + "variableId": "vni6kwbch8zlq92dclgcivzyr" + } + ] + } + }, + { + "id": "b63f0et5y70mragfcrmezifh", + "outgoingEdgeId": "wkecv7zg757mbsnbfdej6uph", + "type": "Condition", + "items": [ + { + "id": "d0bax1yf18x2bj5zt38vr6xs", + "outgoingEdgeId": "optu30rn5vjiwueijh0utvoi", + "content": { + "comparisons": [ + { + "id": "iiv6h6ssgusrfza4vped0iqe", + "variableId": "vni6kwbch8zlq92dclgcivzyr", + "comparisonOperator": "Contains", + "value": "ACCOUNT" + } + ] + } + }, + { + "id": "ulf15sjzk9b7df95rzaqe40j", + "outgoingEdgeId": "ft02qowy1n8uy2k5dzdo0j22", + "content": { + "comparisons": [ + { + "id": "qekpq2av325h7rkmnrvtumxn", + "variableId": "vni6kwbch8zlq92dclgcivzyr", + "comparisonOperator": "Contains", + "value": "HUMAN" + } + ] + } + } + ] + } + ] + }, + { + "id": "flt2vtb4pb6mvlvyrrxonzwf", + "title": "Account", + "graphCoordinates": { "x": 585.48, "y": -214.13 }, + "blocks": [ + { + "id": "h45t9e5yxc2fpfiv49gvmwjj", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Ok feel free to check your account here" } + ] + } + ] + } + }, + { + "id": "fn0s0ezabail96c5n0xs24aq", + "type": "choice input", + "items": [{ "id": "tslv59v8oqbfpnd21la8qnz4", "content": "Account" }] + }, + { + "id": "r16g3avw7mwzi12srqisuex0", + "type": "Redirect", + "options": { "url": "https://google.com" } + } + ] + }, + { + "id": "jn9w80afa6a66czzjfto8tmt", + "title": "Human", + "graphCoordinates": { "x": 586.68, "y": 153.73 }, + "blocks": [ + { + "id": "nvkp4zm7f24b0g3b25u3rb59", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "I'm a human" }] } + ] + } + } + ] + }, + { + "id": "el01d0j1db9kp6v8wlrk9dob", + "title": "Else", + "graphCoordinates": { "x": 581.46, "y": 315.66 }, + "blocks": [ + { + "id": "tpy9wjrwmhw16xjgs8htao04", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Else" }] }] + } + } + ] + }, + { + "id": "vafybpsjqcbrbbhi8pwl0gic", + "title": "", + "graphCoordinates": { "x": 6.52, "y": -346.17 }, + "blocks": [ + { + "id": "q1tc6z6xfl4jtrxdvv8phgil", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You need to add your OpenAI credentials to make this bot work. 🪄\n" + } + ] + } + ] + } + }, + { + "id": "b3ahk7pzsh4abp3bkdlijc0v", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Once it's done, delete this group and connect the " + }, + { "bold": true, "text": "Start" }, + { "text": " event with " }, + { "bold": true, "text": "Intro" }, + { "text": " 🚀\n" } + ] + } + ] + } + } + ] + } + ], + "edges": [ + { + "id": "h5sk58j0ryrxmfv4gmw7r4dw", + "from": { "blockId": "gphm5wy1md9cunwkdtbzg6nq" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "id": "y8ml9ljnsydol9b42fd9zdve", + "from": { "blockId": "myldn1l1nfdwwm8qvza71rwv" }, + "to": { "groupId": "qfrz5nwm63g12dajsjxothb5" } + }, + { + "id": "optu30rn5vjiwueijh0utvoi", + "from": { + "blockId": "b63f0et5y70mragfcrmezifh", + "itemId": "d0bax1yf18x2bj5zt38vr6xs" + }, + "to": { "groupId": "flt2vtb4pb6mvlvyrrxonzwf" } + }, + { + "id": "ft02qowy1n8uy2k5dzdo0j22", + "from": { + "blockId": "b63f0et5y70mragfcrmezifh", + "itemId": "ulf15sjzk9b7df95rzaqe40j" + }, + "to": { "groupId": "jn9w80afa6a66czzjfto8tmt" } + }, + { + "id": "wkecv7zg757mbsnbfdej6uph", + "from": { "blockId": "b63f0et5y70mragfcrmezifh" }, + "to": { "groupId": "el01d0j1db9kp6v8wlrk9dob" } + }, + { + "id": "n396v90ad7quz0gwygr6n5fc", + "from": { "blockId": "ovgk70u0kfxrbtz9dy4e040o" }, + "to": { "groupId": "bh3uva3254p0jgp46gj92way" } + }, + { + "from": { "eventId": "ewnfbo0exlu7ihfu2lu2lusm" }, + "to": { "groupId": "vafybpsjqcbrbbhi8pwl0gic" }, + "id": "q2fpvz66ei3gd6k3wwq6w8f2" + } + ], + "variables": [ + { "id": "vni6kwbch8zlq92dclgcivzyr", "name": "Assistant Message" }, + { "id": "vudksu3zyrat6s1bq6qne0rx3", "name": "User Message" } + ], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": {}, + "createdAt": "2023-12-02T09:12:14.750Z", + "updatedAt": "2023-12-02T09:14:20.047Z", + "icon": "🧠", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/product-recommendation.json b/apps/builder/public/templates/product-recommendation.json new file mode 100644 index 0000000..5a18fd7 --- /dev/null +++ b/apps/builder/public/templates/product-recommendation.json @@ -0,0 +1,1186 @@ +{ + "version": "6", + "id": "clon5zh7w000e1avnec16apet", + "name": "Product recommendation", + "events": [ + { + "id": "af8ny8rpbejnlkitr2s29ro1", + "outgoingEdgeId": "aj9vphwwva87uh9f1w7mm999", + "graphCoordinates": { "x": 0, "y": 0 }, + "type": "start" + } + ], + "groups": [ + { + "id": "buk5exhk13g3npkaiaw87tvs", + "title": "Continent", + "graphCoordinates": { "x": 367.8151290581508, "y": 175.39453125 }, + "blocks": [ + { + "id": "ub5tforva9nlqky5lbrfrsdb", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Ok {{Name}}" }] } + ] + } + }, + { + "id": "jaj0pyfmlf4hb4suglr3v0be", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Because all products are not available everywhere, I need to know..." + } + ] + } + ] + } + }, + { + "id": "x6lj1mhze2xtc0h3ln42xg84", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Where do you live?" }] } + ] + } + }, + { + "id": "lwtynqjykiem5zdtns3fwhu2", + "outgoingEdgeId": "zlab2pp5tfih56jcw6vtjs03", + "type": "choice input", + "items": [ + { "id": "b6mg694wlrmx4k1fgc46co57", "content": "North America" }, + { "id": "fpey0ohbvgvg7b86y4ol8wr7", "content": "Europe" } + ], + "options": { + "variableId": "vma96g9rw8oaosc0ei2iacqig" + } + } + ] + }, + { + "id": "gafkgilrandk3cwydpzq21oy", + "title": "Name", + "graphCoordinates": { "x": 21.63671875, "y": 176.3203125 }, + "blocks": [ + { + "id": "mu6ygqqpi48dacy1n4xj6x4y", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Let's determine what Näak's products suit you best. 💪" + } + ] + } + ] + } + }, + { + "id": "w9rc4yf0ytnzqy16r938h094", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your name?" }] } + ] + } + }, + { + "id": "xobx3g928f9zj220n5qe1ih6", + "outgoingEdgeId": "gnh6uloe0a8ciwahgq0gnx4k", + "type": "text input", + "options": { + "variableId": "vp1r2yrb6xgmi2aq3x6x73vaz" + } + } + ] + }, + { + "id": "z40ynhndj5r4038u3ha39c14", + "title": "Sport", + "graphCoordinates": { "x": 721.140625, "y": 173.953125 }, + "blocks": [ + { + "id": "xpbrytz3gucp0xzf1qs8mlwe", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your sport?" }] } + ] + } + }, + { + "id": "zesp4ro7ltjmh64sn8d4912c", + "outgoingEdgeId": "hwbbi48q0u8xnlqbpq53cdju", + "type": "picture choice input", + "items": [ + { + "id": "l4y5s4rz63g3kl91sq5h6401", + "pictureSrc": "https://images.unsplash.com/photo-1456613820599-bfe244172af5?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHw0fHx0cmFpbHxlbnwwfDB8fHwxNjg1MzYyOTQ2fDA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Running" + }, + { + "id": "urqlzmsiixatiamg06pexhsn", + "pictureSrc": "https://images.unsplash.com/photo-1545575439-3261931f52f1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHw3fHxjeWNsaW5nfGVufDB8MHx8fDE2ODUzNjI5NjJ8MA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Cycling" + }, + { + "id": "go2ko2zs5haeairrtfw7jqb2", + "pictureSrc": "https://images.unsplash.com/photo-1627900258552-50850df9dbc5?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHw0fHxUcmlhdGhsb258ZW58MHwwfHx8MTY4NTM2Mjk3N3ww&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Triathlon" + }, + { + "id": "ctvsb2gsogkbaj9sxsgw25p9", + "pictureSrc": "https://images.unsplash.com/photo-1551632811-561732d1e306?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHwyfHxIaWtpbmd8ZW58MHwwfHx8MTY4NTM2Mjk5NXww&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Hiking" + } + ] + } + ] + }, + { + "id": "mncr0l180vs07gc1difaovjx", + "title": "Gender", + "graphCoordinates": { "x": 1071, "y": 173.953125 }, + "blocks": [ + { + "id": "ahuasm8oa058gl4np96qadox", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Nice! 😎" }] }] + } + }, + { + "id": "phbeq3fg1jp2ktmz2blr6bzf", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What's your gender?" }] } + ] + } + }, + { + "id": "mfz600vwgfjcisahf5tdnz7l", + "outgoingEdgeId": "bf16js59cs2hmicrkbc7nv1q", + "type": "choice input", + "items": [ + { + "id": "zv2np66vgqoruntfh9h9vidx", + "content": "♂️ Men" + }, + { "id": "w5e2h4n10u1l2pap1vtm68ma", "content": "♀️ Women" }, + { "id": "m1t9qrfs4z998ogqd4ttueus", "content": "Other" } + ] + } + ] + }, + { + "id": "mqt2qcyld5du8ecmbphjxpwu", + "title": "Goals", + "graphCoordinates": { "x": 1412.34375, "y": 174.76953125 }, + "blocks": [ + { + "id": "pksck9ppag8q24ou26ewgodw", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "How can Näak help you achieve your goals?" } + ] + } + ] + } + }, + { + "id": "cx2v8nfb4kxvk58bbu6w85uy", + "outgoingEdgeId": "drxu7gyz2trqjtv5nnfv1x9l", + "type": "picture choice input", + "items": [ + { + "id": "fmhwukhd2112743tgrmv85st", + "pictureSrc": "https://images.unsplash.com/photo-1615845522103-82f98cd2a9de?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHw5fHxlbmR1cmFuY2V8ZW58MHwwfHx8MTY4NTM2MzY3Nnww&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Energy" + }, + { + "id": "hkzoroc6mf9tt9g2uxppweay", + "pictureSrc": "https://images.unsplash.com/photo-1536044635785-467d51fc5880?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHwxMnx8ZHJpbmslMjBzcG9ydHxlbnwwfDB8fHwxNjg1MzYzNzIxfDA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Hydration" + }, + { + "id": "nn5629jaux41qo0fhl1yj3zi", + "pictureSrc": "https://images.unsplash.com/photo-1531403939386-c08a16cd7eef?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0MjU2MDR8MHwxfHNlYXJjaHw3fHxzdHJldGNofGVufDB8MHx8fDE2ODUzNjM2OTl8MA&ixlib=rb-4.0.3&q=80&w=1080", + "title": "Recovery" + } + ], + "options": { + "variableId": "vgz8fr5u7q0p4jdef1krz2vm3", + "isMultipleChoice": true + } + } + ] + }, + { + "id": "n3zqahk50kb05th7zbycin5w", + "title": "Protein source", + "graphCoordinates": { "x": 1745.61328125, "y": 183.87109375 }, + "blocks": [ + { + "id": "ife4ujh1l5ljpp3x4gnram1z", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "What protein source are you interested in?" } + ] + } + ] + } + }, + { + "id": "ogy9ng7q9jglxg2ivb39tzeh", + "outgoingEdgeId": "umuilo9l4t27kcpnx5ybnr08", + "type": "choice input", + "items": [ + { "id": "exj60v3j83wx9yjbdsm8gwzj", "content": "Cricket-based" }, + { "id": "kvqeznudz85jbqwxzfpwz8z8", "content": "Plant-based" } + ], + "options": { + "variableId": "vlgo7i0r514jkd9a9f24otm4m", + "isMultipleChoice": true + } + } + ] + }, + { + "id": "y2jfx62oea6q0rxjby9tzqi6", + "title": "Flavours", + "graphCoordinates": { "x": 2077.765625, "y": 182.74609375 }, + "blocks": [ + { + "id": "muy0ptwahuy20bhs5b9npz2m", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What are flavors do you enjoy?" }] + } + ] + } + }, + { + "id": "p71conb1ln7f3m41ca6pxetz", + "outgoingEdgeId": "i3za7jvz8g7m7588g7i1ue9i", + "type": "choice input", + "items": [ + { + "id": "t7fkowjzn7eygfn6q1r4a8l9", + "content": "Chocolate" + }, + { "id": "b1a0qlhtirnxqaqudskc4hnb", "content": "Vanilla" }, + { "id": "vef4uodxrj05lp2i5k3uhdd5", "content": "Berries" }, + { "id": "oyyx5j4j5fee37rc47adb5m8", "content": "Caramel" }, + { "id": "myapux2pojdtbdy0gyc47rhq", "content": "Nuts" }, + { "id": "aegltvuw163qqx88rwzjrg3v", "content": "Coffee" }, + { "id": "zql5o66rry2ab3ofxa1y8kll", "content": "Lime" }, + { "id": "ecvbkdakesh18zn5bfkylvt1", "content": "Watermelon" }, + { "id": "b1xcrk5tv1b1rkjy40uhp44d", "content": "Maple Syrup" } + ], + "options": { + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "isMultipleChoice": true, + "buttonLabel": "Next" + } + } + ] + }, + { + "id": "x14lejru0gv2c7afc68nuezy", + "title": "Diet restrictions", + "graphCoordinates": { "x": 2424.828125, "y": 184.4765625 }, + "blocks": [ + { + "id": "bwqiy7w4x6egwozthsvraeup", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Great choice 😋" }] } + ] + } + }, + { + "id": "n6ns6i9z8qyk83wg5f8bn2j8", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Do you have any dietary restrictions?" } + ] + } + ] + } + }, + { + "id": "cbcz08dj67rkx8k1cbj2ybz8", + "outgoingEdgeId": "erx9wo3svpfxs2cteknbhfaz", + "type": "choice input", + "items": [ + { "id": "u9gi0gnaza6ottid74l82wlm", "content": "Non GMO" }, + { "id": "yr7q8fcyi6l1sw83t37fjosj", "content": "No palm oil" }, + { "id": "gckqnnt2but4d6wwsfia3035", "content": "Gluten free" }, + { "id": "m3qdwzep7uugpejvga0yqorg", "content": "Nut free" } + ], + "options": { + "variableId": "vz4fqc40gkk99h0qeus2tjwhx" + } + } + ] + }, + { + "id": "q9z4xrzf9z7sgl69rrrhiyoh", + "title": "Email", + "graphCoordinates": { "x": 2765.89453125, "y": 187.64453125 }, + "blocks": [ + { + "id": "fynckthiy3zq7selucjvp44q", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Alright {{Name}}, I think we know exactly what you need." + } + ] + } + ] + } + }, + { + "id": "pbn0oib7yt3uspici7to3i9f", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Sign up to our email list to receive a copy of your product recommendations." + } + ] + } + ] + } + }, + { + "id": "rez1phkqpkeoj7u2kzmde653", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "We will also send a little gift 🎁" }] + } + ] + } + }, + { + "id": "vdzzxwdocfxdvqnqwwvjymzw", + "outgoingEdgeId": "vnqu52ld3usezpnrgu2l7ul0", + "type": "email input" + } + ] + }, + { + "id": "g27q0psplvzht5xg9erxw738", + "title": "If cricket", + "graphCoordinates": { "x": 3107.953125, "y": 187.3515625 }, + "blocks": [ + { + "id": "l16y2qzslakgl2up4jybj5m4", + "outgoingEdgeId": "j6d1kch478t4ov4bbz1yshhl", + "type": "Condition", + "items": [ + { + "id": "yffl8ja17g5fr9rpi4d0cl36", + "outgoingEdgeId": "iszgvtfetursv4ktm9mdtxhy", + "content": { + "comparisons": [ + { + "id": "g995jwhkyj8e5tv4ci7gd5fi", + "variableId": "vlgo7i0r514jkd9a9f24otm4m", + "comparisonOperator": "Contains", + "value": "Cricket-based" + }, + { + "id": "qjhmaage7fe1i5e0nscr0954", + "variableId": "vma96g9rw8oaosc0ei2iacqig", + "comparisonOperator": "Equal to", + "value": "Europe" + } + ] + } + } + ] + } + ] + }, + { + "id": "qjoc17kdjrpkaoxesoeqzmjt", + "title": "No cricket in Europe", + "graphCoordinates": { "x": 3452.45703125, "y": 113.35546875 }, + "blocks": [ + { + "id": "c3m4f1kcyf3dnsdlykjrxytm", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Unfortunately, cricket-based products are not available in Europe. 😢" + } + ] + } + ] + } + }, + { + "id": "pxb59zd4bjqmva9er47l6x15", + "outgoingEdgeId": "apvktyu7x3wks4z9xflecu91", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "We'll make sure to let you know once it's available!" + } + ] + } + ] + } + } + ] + }, + { + "id": "b94nqmbqp0ezfazu0kekqioa", + "title": "If Energy", + "graphCoordinates": { "x": 3646.396113301624, "y": 447.8859463616741 }, + "blocks": [ + { + "id": "okl6akklm8djknl7lofqr3cm", + "outgoingEdgeId": "xblzklrcdkmxeu8y5xbicz09", + "type": "Condition", + "items": [ + { + "id": "vyjgfexvyrijez06kpxi1mva", + "outgoingEdgeId": "lk5ghbqljt2f43w1d47rowns", + "content": { + "comparisons": [ + { + "id": "w3ii2flw8vz608pm45j92nli", + "variableId": "vgz8fr5u7q0p4jdef1krz2vm3", + "comparisonOperator": "Contains", + "value": "Energy" + } + ] + } + } + ] + } + ] + }, + { + "id": "co7gxaoxtf1xukmgbby73u6v", + "title": "If hydration", + "graphCoordinates": { "x": 4165.908336104726, "y": 568.072108305734 }, + "blocks": [ + { + "id": "styhci2fh3yi17b7cmv3x8cc", + "outgoingEdgeId": "dyvib6xwm0jieqp37mac1diq", + "type": "Condition", + "items": [ + { + "id": "okd2sbmr1mgoubpf7kdjr9ey", + "outgoingEdgeId": "r2cx0lm6xkzjgv1hycekcp25", + "content": { + "comparisons": [ + { + "id": "w3ii2flw8vz608pm45j92nli", + "variableId": "vgz8fr5u7q0p4jdef1krz2vm3", + "comparisonOperator": "Contains", + "value": "Hydration" + } + ] + } + } + ] + } + ] + }, + { + "id": "rcr9zqm4lnevx5dqf9k23m5u", + "title": "If recovery", + "graphCoordinates": { "x": 4634.078450031568, "y": 886.3561931535737 }, + "blocks": [ + { + "id": "m8o93n92t5wcy5bi8tgauc5f", + "type": "Condition", + "items": [ + { + "id": "yw3cil1rvf3iduc0mko0c8og", + "outgoingEdgeId": "choo26oflyx4c2em6msd7bum", + "content": { + "comparisons": [ + { + "id": "w3ii2flw8vz608pm45j92nli", + "variableId": "vgz8fr5u7q0p4jdef1krz2vm3", + "comparisonOperator": "Contains", + "value": "Recovery" + } + ] + } + } + ] + } + ] + }, + { + "id": "ho2hskojxz8ac631driot5kh", + "title": "Energy", + "graphCoordinates": { "x": 4001.801919721875, "y": -860.9371698075208 }, + "blocks": [ + { + "id": "v4tvmb615jdg52vofgzlz7ai", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "Let's talk about " }, + { "bold": true, "text": "Energy. ⚡" } + ] + } + ] + } + }, + { + "id": "vxadalubq6hnsywwt7w9tzoc", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Here is a selection for you based on your answers." + } + ] + } + ] + } + }, + { + "id": "zzws62fe3zha7x7kln3kp0ko", + "outgoingEdgeId": "pk7d58d6qmxrylte434czz4x", + "type": "Condition", + "items": [ + { + "id": "kb6eovh6di5xqnkegms0ljee", + "outgoingEdgeId": "achb4p7q0hnox3hy62ru7dtx", + "content": { + "comparisons": [ + { + "id": "ysu7q0adna5tyhaghtq9qzrj", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Chocolate" + }, + { + "id": "j7sune97lh32xukeil8poeif", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Berries" + }, + { + "id": "tsrm85u8demtuc95aootakrj", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Caramel" + }, + { + "id": "gfqvik3txgrinlslj0jvs9gt", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Nuts" + }, + { + "id": "yv3jre55h7w9qp55t5m8ax2p", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Coffee" + }, + { + "id": "xksf2b1la2h8yy9lvn96yqo1", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Vanilla" + } + ] + } + } + ] + } + ] + }, + { + "id": "w3f8ya4hmkuab55dh2ogsvtz", + "title": "Hydration", + "graphCoordinates": { "x": 4604.393180386735, "y": 102.6192979908871 }, + "blocks": [ + { + "id": "qsd35sfqjq1eskoovubrjc7k", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "About " }, + { "bold": true, "text": "Hydration. 💧" } + ] + } + ] + } + }, + { + "id": "eobb04nb37ezx24go2iipm85", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Here is a selection for you based on your answers." + } + ] + } + ] + } + }, + { + "id": "ph2jgb8r0lyui0j6v3jtifo2", + "outgoingEdgeId": "l8g4gblcmzmiv4fsgjufviws", + "type": "picture choice input", + "items": [ + { + "id": "pkv4omwvnr338lkhwh6jglh6", + "pictureSrc": "https://www.naak.com/cdn/shop/files/naak-energy-drink-mix-energy-drink-mix-lime-42434407891248_600x.png?v=1692717400", + "title": "Lime Energy Drink Mix", + "description": "- 250 calories: get all your calories in a liquid form\n- 55g carbohydrates: simple and complex natural carbohydrates\n- 650mg electrolytes: replenish minerals lost in sweat\n- 1300mg BCAAs: prevent muscle breakdown during exercise\n- 8g protein: all essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "ntnhk9cqrvogutrldgpm7d56", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Lime" + } + ] + } + } + }, + { + "id": "s6nx86xyuclsjtqmr53ijea1", + "pictureSrc": "https://eu.naak.com/cdn/shop/files/NewDrinkMixWatermelonBulk-Front_5_600x.png?v=1692716818", + "title": "Watermelon Energy Drink Mix", + "description": "- 250 calories: get all your calories in a liquid form\n- 55g carbohydrates: simple and complex natural carbohydrates\n- 650mg electrolytes: replenish minerals lost in sweat\n- 1300mg BCAAs: prevent muscle breakdown during exercise\n- 8g protein: all essential amino acids to reduce muscle fatigue" + } + ], + "options": { + "isMultipleChoice": true, + "buttonLabel": "Next" + } + } + ] + }, + { + "id": "jdd417tfj6hdu4pj6bkksgwa", + "title": "Recovery", + "graphCoordinates": { "x": 5092.137492973015, "y": 286.5579598199387 }, + "blocks": [ + { + "id": "xbbsd6xsl44fukz2ygdpjbd1", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "bold": true, "text": "Recovery 🧘‍♂️ " }, + { + "text": "is crucial to perform at your highest level on the field." + } + ] + } + ] + } + }, + { + "id": "cgb8mt2krmq3mdddwjehtrzu", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Here is a selection for you based on your answers." + } + ] + } + ] + } + }, + { + "id": "mtj2j6zgnp50wpw9ewuwui5u", + "type": "picture choice input", + "items": [ + { + "id": "s9nop23fmq55jilo9mntgpn8", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/naak-breakfast-340g-protein-nut-butter-peanut-40637318365488_600x.png?v=1678033822", + "title": "Protein Nut Butter", + "description": "- 500mg super fats: promote heart and gut health\n- 640mg BCAAs: reduce muscle damage & soreness\n- 120mg electrolytes: replenish minerals lost in sweat\n- 4.3g protein: build & repair muscle post-workout", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "rm8omv5htisk7s4nzvmsvc5c", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Nuts" + }, + { + "id": "xde05nklbld4u80qhs422y47", + "variableId": "vz4fqc40gkk99h0qeus2tjwhx", + "comparisonOperator": "Does not contain", + "value": "Nut free" + } + ] + } + } + }, + { + "id": "snr3wam9c0p1f191rf2587wz", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/naak-protein-powder-1-bag-2-75-serving-protein-powder-vanilla-29774755954774_600x.png?v=1677355777", + "title": "Vanilla Protein Powder", + "description": "- 25g complete protein: build & repair muscle post-workout\n- 4g BCAAs: reduce muscle damage & soreness\n- 430mg electrolytes: replenish minerals lost in sweat\n- 1g carbohydrates: no added sugar" + } + ], + "options": { + "isMultipleChoice": true + } + } + ] + }, + { + "id": "nh69j0kgfd5wdqshpdpjgqdh", + "title": "", + "graphCoordinates": { "x": 4425.493571638971, "y": -1989.578763047769 }, + "blocks": [ + { + "id": "bqq8o994nr8ltkkdc8bax01i", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Since you like all these flavors you could try our discovery packs" + } + ] + } + ] + } + }, + { + "id": "np8236cce7e79h8i21hg5ncp", + "outgoingEdgeId": "u57y4cl6042u5r34dahfhwus", + "type": "picture choice input", + "items": [ + { + "id": "smabu9g31qcovytdu2yyi86n", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/PACKS_8_600x.png?v=1680032168", + "title": "Bars - Variety pack", + "description": "- 180 calories: long-lasting energy with no sugar crash\n- 65mg caffeine: increase focus and stamina\n- 29g carbohydrates: simple and complex natural carbohydrates\n- 480mg electrolytes: replenish minerals lost in sweat\n- 7g protein: essential amino acids to reduce muscle fatigue" + }, + { + "id": "f8rm4b7ic73nq92u52717th5", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/PACKS_7_600x.png?v=1680032183", + "title": "Waffle - Variety pack", + "description": "- 140 calories: quick energy boost from high-quality ingredients\n- 16g carbohydrates: simple and complex natural carbohydrates\n- 200mg electrolytes: replenish minerals lost in sweat\n- 3g protein: all essential amino acids to reduce muscle fatigue" + } + ], + "options": { + "isMultipleChoice": true + } + } + ] + }, + { + "id": "oq9jemd1endd8naxzatkkjbb", + "title": "", + "graphCoordinates": { "x": 4431.336411421283, "y": -1425.83493478683 }, + "blocks": [ + { + "id": "r5hq4sr8iovxqyixejparma7", + "outgoingEdgeId": "xevaekw7nv6zfmkijsortgk5", + "type": "picture choice input", + "items": [ + { + "id": "zc1c5ahukxhalbu9p6oqz4tw", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/naak-energy-waffle-energy-waffle-chocolate-40633672728880_600x.png?v=1677355844", + "title": "Chocolate Energy Waffle", + "description": "- 140 calories: quick energy boost from high-quality ingredients\n- 17g carbohydrates: simple and complex natural carbohydrates\n- 200mg electrolytes: replenish minerals lost in sweat\n- 3g protein: all essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "pkmq8tabhm9nqi5oo8cmz2gz", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Chocolate" + } + ] + } + } + }, + { + "id": "j953heg9dx2xzdhwk773fha0", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/naak-energy-waffle-energy-waffle-vanilla-40633799246128_600x.png?v=1677355758", + "title": "Vanilla Energy Waffle", + "description": "- 140 calories: quick energy boost from high-quality ingredients\n- 16g carbohydrates: simple and complex natural carbohydrates\n- 210mg electrolytes: replenish minerals lost in sweat\n- 4g protein: all essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "l4cye2ndoqcdmhiylc4zyho9", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Vanilla" + } + ] + } + } + }, + { + "id": "z8brrxkvbxfxfwryit6bjqb9", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/naak-energy-waffle-energy-waffle-maple-syrup-40633783877936_600x.png?v=1678034628", + "title": "Maple Syrup Energy Waffle", + "description": "- 140 calories: quick energy boost from high-quality ingredients\n- 16g carbohydrates: simple and complex natural carbohydrates\n- 210mg electrolytes: replenish minerals lost in sweat\n- 4g protein: all essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "l4cye2ndoqcdmhiylc4zyho9", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Maple Syrup" + } + ] + } + } + }, + { + "id": "ex1l3ynwk2iiz6wmavsr3l8y", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/PACKS_600x.png?v=1678223153", + "title": "Peanut Butter & Chocolate Bar", + "description": "- 200 calories: long-lasting energy with no sugar crash\n- 27g carbohydrates: simple and complex natural carbohydrates\n- 445mg electrolytes: replenish minerals lost in sweat\n- 7g protein: essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "ez9ppwlsy77hzum27l7vxnu6", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Nuts" + }, + { + "id": "s4khjdtxicrwpdelg41fs6d8", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Chocolate" + } + ] + } + } + }, + { + "id": "x2octz0rxe0s8ach4zdf2gch", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/98_600x.png?v=1678223518", + "title": "Mocha Energy Bar", + "description": "- 180 calories: long-lasting energy with no sugar crash\n- 65mg caffeine: increase focus and stamina\n- 29g carbohydrates: simple and complex natural carbohydrates\n- 480mg electrolytes: replenish minerals lost in sweat\n- 7g protein: essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "mz7hwzkpjycizegz5216as63", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Coffee" + } + ] + } + } + }, + { + "id": "hxcd05xn9rzhrvreh9bjqdbr", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/101_600x.png?v=1678223652", + "title": "Caramel Macchiato Bar", + "description": "- 180 calories: long-lasting energy with no sugar crash\n- 65mg caffeine: increase focus and stamina\n- 29g carbohydrates: simple and complex natural carbohydrates\n- 480mg electrolytes: replenish minerals lost in sweat\n- 7g protein: essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "mz7hwzkpjycizegz5216as63", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Caramel" + } + ] + } + } + }, + { + "id": "qw9p8xrmvli4xsn019cddxbh", + "pictureSrc": "https://cdn.shopify.com/s/files/1/0704/1744/9254/products/92_600x.png?v=1678222928", + "title": "Berries & Nuts Bar", + "description": "- 200 calories: long-lasting energy with no sugar crash\n- 28g carbohydrates: simple and complex natural carbohydrates\n- 405mg electrolytes: replenish minerals lost in sweat\n- 7g protein: essential amino acids to reduce muscle fatigue", + "displayCondition": { + "isEnabled": true, + "condition": { + "comparisons": [ + { + "id": "mz7hwzkpjycizegz5216as63", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Berries" + }, + { + "id": "m48fa084tvurk9nzcibm0d2d", + "variableId": "vhbd5800sc98l1lk8wf7fe742", + "comparisonOperator": "Contains", + "value": "Nuts" + } + ] + } + } + } + ], + "options": { + "isMultipleChoice": true + } + } + ] + } + ], + "edges": [ + { + "id": "aj9vphwwva87uh9f1w7mm999", + "from": { "eventId": "af8ny8rpbejnlkitr2s29ro1" }, + "to": { "groupId": "gafkgilrandk3cwydpzq21oy" } + }, + { + "id": "gnh6uloe0a8ciwahgq0gnx4k", + "from": { "blockId": "xobx3g928f9zj220n5qe1ih6" }, + "to": { "groupId": "buk5exhk13g3npkaiaw87tvs" } + }, + { + "id": "zlab2pp5tfih56jcw6vtjs03", + "from": { "blockId": "lwtynqjykiem5zdtns3fwhu2" }, + "to": { "groupId": "z40ynhndj5r4038u3ha39c14" } + }, + { + "id": "hwbbi48q0u8xnlqbpq53cdju", + "from": { "blockId": "zesp4ro7ltjmh64sn8d4912c" }, + "to": { "groupId": "mncr0l180vs07gc1difaovjx" } + }, + { + "id": "bf16js59cs2hmicrkbc7nv1q", + "from": { "blockId": "mfz600vwgfjcisahf5tdnz7l" }, + "to": { "groupId": "mqt2qcyld5du8ecmbphjxpwu" } + }, + { + "id": "umuilo9l4t27kcpnx5ybnr08", + "from": { "blockId": "ogy9ng7q9jglxg2ivb39tzeh" }, + "to": { "groupId": "y2jfx62oea6q0rxjby9tzqi6" } + }, + { + "id": "i3za7jvz8g7m7588g7i1ue9i", + "from": { "blockId": "p71conb1ln7f3m41ca6pxetz" }, + "to": { "groupId": "x14lejru0gv2c7afc68nuezy" } + }, + { + "id": "erx9wo3svpfxs2cteknbhfaz", + "from": { "blockId": "cbcz08dj67rkx8k1cbj2ybz8" }, + "to": { "groupId": "q9z4xrzf9z7sgl69rrrhiyoh" } + }, + { + "id": "drxu7gyz2trqjtv5nnfv1x9l", + "from": { "blockId": "cx2v8nfb4kxvk58bbu6w85uy" }, + "to": { "groupId": "n3zqahk50kb05th7zbycin5w" } + }, + { + "id": "iszgvtfetursv4ktm9mdtxhy", + "from": { + "blockId": "l16y2qzslakgl2up4jybj5m4", + "itemId": "yffl8ja17g5fr9rpi4d0cl36" + }, + "to": { "groupId": "qjoc17kdjrpkaoxesoeqzmjt" } + }, + { + "id": "vnqu52ld3usezpnrgu2l7ul0", + "from": { "blockId": "vdzzxwdocfxdvqnqwwvjymzw" }, + "to": { "groupId": "g27q0psplvzht5xg9erxw738" } + }, + { + "id": "apvktyu7x3wks4z9xflecu91", + "from": { "blockId": "pxb59zd4bjqmva9er47l6x15" }, + "to": { "groupId": "b94nqmbqp0ezfazu0kekqioa" } + }, + { + "id": "j6d1kch478t4ov4bbz1yshhl", + "from": { "blockId": "l16y2qzslakgl2up4jybj5m4" }, + "to": { "groupId": "b94nqmbqp0ezfazu0kekqioa" } + }, + { + "id": "lk5ghbqljt2f43w1d47rowns", + "from": { + "blockId": "okl6akklm8djknl7lofqr3cm", + "itemId": "vyjgfexvyrijez06kpxi1mva" + }, + "to": { "groupId": "ho2hskojxz8ac631driot5kh" } + }, + { + "id": "xblzklrcdkmxeu8y5xbicz09", + "from": { "blockId": "okl6akklm8djknl7lofqr3cm" }, + "to": { "groupId": "co7gxaoxtf1xukmgbby73u6v" } + }, + { + "id": "r2cx0lm6xkzjgv1hycekcp25", + "from": { + "blockId": "styhci2fh3yi17b7cmv3x8cc", + "itemId": "okd2sbmr1mgoubpf7kdjr9ey" + }, + "to": { "groupId": "w3f8ya4hmkuab55dh2ogsvtz" } + }, + { + "id": "dyvib6xwm0jieqp37mac1diq", + "from": { "blockId": "styhci2fh3yi17b7cmv3x8cc" }, + "to": { "groupId": "rcr9zqm4lnevx5dqf9k23m5u" } + }, + { + "id": "choo26oflyx4c2em6msd7bum", + "from": { + "blockId": "m8o93n92t5wcy5bi8tgauc5f", + "itemId": "yw3cil1rvf3iduc0mko0c8og" + }, + "to": { "groupId": "jdd417tfj6hdu4pj6bkksgwa" } + }, + { + "id": "l8g4gblcmzmiv4fsgjufviws", + "from": { "blockId": "ph2jgb8r0lyui0j6v3jtifo2" }, + "to": { "groupId": "rcr9zqm4lnevx5dqf9k23m5u" } + }, + { + "id": "achb4p7q0hnox3hy62ru7dtx", + "from": { + "blockId": "zzws62fe3zha7x7kln3kp0ko", + "itemId": "kb6eovh6di5xqnkegms0ljee" + }, + "to": { "groupId": "nh69j0kgfd5wdqshpdpjgqdh" } + }, + { + "id": "pk7d58d6qmxrylte434czz4x", + "from": { "blockId": "zzws62fe3zha7x7kln3kp0ko" }, + "to": { "groupId": "oq9jemd1endd8naxzatkkjbb" } + }, + { + "id": "xevaekw7nv6zfmkijsortgk5", + "from": { "blockId": "r5hq4sr8iovxqyixejparma7" }, + "to": { "groupId": "w3f8ya4hmkuab55dh2ogsvtz" } + }, + { + "id": "u57y4cl6042u5r34dahfhwus", + "from": { "blockId": "np8236cce7e79h8i21hg5ncp" }, + "to": { "groupId": "w3f8ya4hmkuab55dh2ogsvtz" } + } + ], + "variables": [ + { "id": "vp1r2yrb6xgmi2aq3x6x73vaz", "name": "Name" }, + { "id": "vhbd5800sc98l1lk8wf7fe742", "name": "Flavour" }, + { "id": "vma96g9rw8oaosc0ei2iacqig", "name": "Continent" }, + { "id": "vlgo7i0r514jkd9a9f24otm4m", "name": "Protein source" }, + { "id": "vgz8fr5u7q0p4jdef1krz2vm3", "name": "Goals" }, + { "id": "vz4fqc40gkk99h0qeus2tjwhx", "name": "Diet restrictions" } + ], + "theme": { + "general": { + "background": { "type": "Color", "content": "#010000" } + }, + "chat": { + "hostBubbles": { "backgroundColor": "#1B1A1A", "color": "#ffffff" }, + "guestBubbles": { "color": "#010000", "backgroundColor": "#FFFFFF" }, + "buttons": { "backgroundColor": "#FFEF02", "color": "#010000" }, + "inputs": { + "backgroundColor": "#1B1A1A", + "color": "#ffffff", + "placeholderColor": "#9095A0" + } + } + }, + "selectedThemeTemplateId": "typebot-dark", + "settings": {}, + "createdAt": "2023-11-06T17:16:37.483Z", + "updatedAt": "2023-11-06T17:20:11.754Z", + "icon": "🍫", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/templates/quiz.json b/apps/builder/public/templates/quiz.json new file mode 100644 index 0000000..4e1a6c1 --- /dev/null +++ b/apps/builder/public/templates/quiz.json @@ -0,0 +1,756 @@ +{ + "version": "6", + "id": "clon582of00031avnefkrpwrl", + "name": "Digital Marketing Quiz", + "events": [ + { + "id": "cl1qz4lui00017w1a505z15p0", + "outgoingEdgeId": "cl1r17gv3006h2e6dc9e7xob7", + "graphCoordinates": { "x": -541.1926699141732, "y": -27.36367432150308 }, + "type": "start" + } + ], + "groups": [ + { + "id": "cl1r09bc6000h2e6dqml18p4p", + "title": "Q1", + "graphCoordinates": { "x": 3, "y": 180 }, + "blocks": [ + { + "id": "cl1r0bva2000y2e6d2g88vmjk", + "type": "Set variable", + "options": { + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "expressionToEvaluate": "0" + } + }, + { + "id": "cl1r09bcc000i2e6dyyvskx75", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What does SEO stand for?" }] + } + ] + } + }, + { + "id": "cl1r09dl9000j2e6dhkc2h97y", + "outgoingEdgeId": "cl1r0cfjt00122e6dzwtamycl", + "type": "choice input", + "items": [ + { "id": "cl1r09dl9000k2e6dvf7llzkd", "content": "Send Email Out" }, + { + "id": "cl1r0a80k000l2e6dngppwyhm", + "content": "Serial Editorial Output" + }, + { + "id": "cl1r0adei000m2e6dfc8w5y4k", + "outgoingEdgeId": "cl1r0dfip00152e6doo9duexn", + "content": "Search Engine Optimization" + }, + { + "id": "cl1r0aiks000n2e6dc31e2db6", + "content": "Search Expectation Order" + } + ] + } + ] + }, + { + "id": "cl1r0b3ww000q2e6d4aihat41", + "title": "Q2", + "graphCoordinates": { "x": 457.878775226166, "y": 159.8383669682208 }, + "blocks": [ + { + "id": "cl1r0e8gq00172e6dq0bpxqsc", + "type": "Set variable", + "options": { + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "expressionToEvaluate": "{{Score}} + 5" + } + }, + { + "id": "cl1r0d8zi00142e6d4tl2yenk", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Well done!" }] } + ] + } + }, + { + "id": "cl1r0bgit000x2e6dvdre9wsj", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What is anchor text?" }] } + ] + } + }, + { + "id": "cl1r0b3x5000r2e6dqk8gzoim", + "outgoingEdgeId": "cl1r0f53y001q2e6dvuq434ru", + "type": "choice input", + "items": [ + { + "id": "cl1r0b3x5000s2e6dyq6bklbf", + "outgoingEdgeId": "cl1r0i4dj001r2e6dgb96tx9q", + "content": "The visible text that is hyperlinked to another page" + }, + { + "id": "cl1r0b6jd000t2e6dkp3dxpp9", + "content": "The text in the top left of a webpage" + }, + { + "id": "cl1r0b835000u2e6d22rw2gb5", + "content": "The most prominent text on a page, used by search engines to assign a title to the page" + }, + { + "id": "cl1r0b9tl000v2e6dkligryj3", + "content": "A slogan that sticks in a consumer’s mind" + } + ] + } + ] + }, + { + "id": "cl1r0erik00182e6dfzezujj0", + "title": "Q3", + "graphCoordinates": { "x": 876.6414289028069, "y": 165.4393876130828 }, + "blocks": [ + { + "id": "cl1r0eril00192e6d9yrtownz", + "type": "Set variable", + "options": { + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "expressionToEvaluate": "{{Score}} + 5" + } + }, + { + "id": "cl1r0eril001b2e6dh43cqhv5", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Well done!" }] } + ] + } + }, + { + "id": "cl1r0eril001d2e6d3gay9cls", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "What is a persona ?" }] } + ] + } + }, + { + "id": "cl1r0eril001f2e6dk0fd0qpw", + "outgoingEdgeId": "cl1r0khb6002c2e6ddssbpj9z", + "type": "choice input", + "items": [ + { + "id": "cl1r0erim001g2e6d5zzn8q22", + "content": "Your target audience" + }, + { + "id": "cl1r0erim001h2e6dnwtiturl", + "content": "Someone who joins your mailing list" + }, + { + "id": "cl1r0erim001i2e6dbfhck09o", + "content": "A repeat customer" + }, + { + "id": "cl1r0erim001j2e6d2waa3374", + "outgoingEdgeId": "cl1r0k27y00262e6dflgcp3wa", + "content": "A fictional representation of a group of customers" + } + ] + } + ] + }, + { + "id": "cl1r0j8u1001t2e6d42mjfcqo", + "title": "Q4", + "graphCoordinates": { "x": 1262.722245418697, "y": 156.2726513569937 }, + "blocks": [ + { + "id": "cl1r0j8u2001u2e6dgdpvrnz5", + "type": "Set variable", + "options": { + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "expressionToEvaluate": "{{Score}} + 5" + } + }, + { + "id": "cl1r0j8u2001w2e6d3wnpzcj5", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Well done!" }] } + ] + } + }, + { + "id": "cl1r0j8u2001y2e6dr24ieifw", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "What does CTA stand for?" }] + } + ] + } + }, + { + "id": "cl1r0j8u200202e6dun2d04gu", + "outgoingEdgeId": "cl1r0ktet002i2e6d5sh8gd2b", + "type": "choice input", + "items": [ + { + "id": "cl1r0j8u200212e6dov1xy5m4", + "content": "Consequence To Advert" + }, + { + "id": "cl1r0j8u300222e6dnj0i5fm8", + "outgoingEdgeId": "cl1r0lm4e002m2e6d0g3h9pm7", + "content": "Call To Action" + }, + { + "id": "cl1r0j8u300232e6dxd8abojt", + "content": "Computer Tracked Actions" + }, + { + "id": "cl1r0j8u300242e6d0pki60w6", + "content": "Characteristic Tracking Advert" + } + ] + } + ] + }, + { + "id": "cl1r0c85100102e6d7uohf0cu", + "title": "Q1 - Wrong", + "graphCoordinates": { "x": 79.08, "y": 821.49 }, + "blocks": [ + { + "id": "cl1r0c85i00112e6d8iwtrpvb", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "WRONG!" }] }] + } + }, + { + "id": "cl1r0crx600132e6d0u54j506", + "outgoingEdgeId": "cl1r0dibf00162e6dwuvli71j", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "SEO stands for Search Engine Optimization" } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r0exdi001l2e6drdwj3u96", + "title": "Q2 - Wrong", + "graphCoordinates": { "x": 542.94, "y": 996.75 }, + "blocks": [ + { + "id": "cl1r0exdi001m2e6d7kge562x", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "WRONG!" }] }] + } + }, + { + "id": "cl1r0exdi001o2e6d70s7si5y", + "outgoingEdgeId": "cl1r0ic5f001s2e6dw777scrq", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Anchor text is the visible text that is hyperlinked to another page" + } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r0k3tq00272e6d1fwyajjx", + "title": "Q3 - Wrong", + "graphCoordinates": { "x": 916.73, "y": 925.61 }, + "blocks": [ + { + "id": "cl1r0k3tq00282e6dl0av81kz", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "WRONG!" }] }] + } + }, + { + "id": "cl1r0k3tq002a2e6dv3s1eb6d", + "outgoingEdgeId": "cl1r0l7oa002j2e6dgtx0y1gh", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "A persona is a fictional representation of a group of customers" + } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r0kqof002d2e6doqhpnuqy", + "title": "Q4 - Wrong", + "graphCoordinates": { "x": 1316.88, "y": 861.75 }, + "blocks": [ + { + "id": "cl1r0kqof002e2e6dzjcw0kvs", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "WRONG!" }] }] + } + }, + { + "id": "cl1r0kqog002g2e6dizmxvz64", + "outgoingEdgeId": "cl1r0p4my00312e6d1wsgwohi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Anchor text is the visible text that is hyperlinked to another page" + } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r0lfb5002k2e6dd6as5kj5", + "title": "Filter", + "graphCoordinates": { "x": 1647.16, "y": 167.69 }, + "blocks": [ + { + "id": "cl1r0lo97002n2e6dfx7fohju", + "type": "Set variable", + "options": { + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "expressionToEvaluate": "{{Score}} + 5" + } + }, + { + "id": "cl1r0oqrr002y2e6dsg0sa64g", + "type": "Condition", + "items": [ + { + "id": "cl1r0oqrr002z2e6dl821aaow", + "outgoingEdgeId": "cl1r0rt88003a2e6dgq6beaq1", + "content": { + "logicalOperator": "AND", + "comparisons": [ + { + "id": "cl1r0osjs00302e6dc60nuk4y", + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "comparisonOperator": "Greater than", + "value": "14" + } + ] + } + } + ] + }, + { + "id": "cl1r0qvwy00342e6d7ww0oqar", + "outgoingEdgeId": "cl1r0sg9m003i2e6dbsc4cqjn", + "type": "Condition", + "items": [ + { + "id": "cl1r0qvwy00352e6dui5itgd1", + "outgoingEdgeId": "cl1r0s6qt003d2e6d5tk2um7y", + "content": { + "logicalOperator": "AND", + "comparisons": [ + { + "id": "cl1r0qx3k00362e6dg30jgpdt", + "variableId": "vcl1r0bxdj000z2e6d65u7n41b", + "comparisonOperator": "Greater than", + "value": "9" + } + ] + } + } + ] + } + ] + }, + { + "id": "cl1r0mn2p002p2e6dijqbjzlh", + "title": "Result", + "graphCoordinates": { "x": 2508.594129051806, "y": 405.664166830421 }, + "blocks": [ + { + "id": "cl1r0mn3t002q2e6dcmv4bzth", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "Your score is {{Score}}/20." }] + } + ] + } + }, + { + "id": "cl1r0nkdx002r2e6dwv0wclo0", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Try again?" }] } + ] + } + }, + { + "id": "cl1r0nt85002s2e6dloupnhdq", + "type": "choice input", + "items": [ + { + "id": "cl1r0nt85002t2e6dvb7si7ny", + "outgoingEdgeId": "cl1r15gko005i2e6dn6rhifwe", + "content": "Yes!" + }, + { "id": "cl1r0nveb002u2e6dotjk6nuf", "content": "No, bye!" } + ] + } + ] + }, + { + "id": "cl1r0rgex00382e6dkayjbys6", + "title": "Great score", + "graphCoordinates": { "x": 1999.325745846056, "y": 159.3910979368924 }, + "blocks": [ + { + "id": "cl1r0rggf00392e6dcc941700", + "outgoingEdgeId": "cl1r0s9g8003e2e6d5if2ywz9", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "text": "Well done 👏" }] } + ] + } + } + ] + }, + { + "id": "cl1r0rvak003b2e6dejcdrooq", + "title": "Medium score", + "graphCoordinates": { "x": 2008.44697061989, "y": 315.9721232210492 }, + "blocks": [ + { + "id": "cl1r0rvce003c2e6diusd3pxq", + "outgoingEdgeId": "cl1r0sarx003f2e6dbzmed9te", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { "text": "You could do better but that's alright!" } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r0seuj003h2e6dandwc43r", + "title": "Bad score", + "graphCoordinates": { "x": 2009.967174748862, "y": 499.9168228267089 }, + "blocks": [ + { + "id": "cl1r0pe0x00332e6dxg6xdt2f", + "outgoingEdgeId": "cl1r0sbzh003g2e6dsqs48aoz", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "Aouch, you need to improve your Digital Marketing game." + } + ] + } + ] + } + } + ] + }, + { + "id": "cl1r15f68005f2e6dvdtal7cp", + "title": "Restart", + "graphCoordinates": { "x": 2850.766985281865, "y": 609.1892251509271 }, + "blocks": [ + { + "id": "cl1r15f87005g2e6dp3srll8r", + "type": "Typebot link", + "options": { + "typebotId": "current", + "groupId": "cl1r09bc6000h2e6dqml18p4p", + "mergeResults": false + } + } + ] + }, + { + "id": "cl1r15w3o005s2e6dr5l7csao", + "title": "Welcome", + "graphCoordinates": { "x": -361.5512664480758, "y": 166.9921185817542 }, + "blocks": [ + { + "id": "cl1r16nes005z2e6d3aj23kfz", + "type": "text", + "content": { + "richText": [{ "type": "p", "children": [{ "text": "Hi there!" }] }] + } + }, + { + "id": "cl1r15w5p005t2e6d670v9nbi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [ + { + "text": "You're about to answer a Quiz about Digital Marketing" + } + ] + } + ] + } + }, + { + "id": "cl1r16rt400622e6d32uta7mi", + "type": "text", + "content": { + "richText": [ + { + "type": "p", + "children": [{ "text": "It is composed of only 4 questions." }] + } + ] + } + }, + { + "id": "cl1r1708n00662e6dv8900ixk", + "type": "text", + "content": { + "richText": [ + { "type": "p", "children": [{ "bold": true, "text": "Ready?" }] } + ] + } + }, + { + "id": "cl1r176e900692e6d8u3k6sdq", + "type": "choice input", + "items": [ + { + "id": "cl1r176e9006a2e6dpvp0974z", + "outgoingEdgeId": "cl1r17pzv006n2e6dpibxp9th", + "content": "Go!" + } + ] + } + ] + } + ], + "edges": [ + { + "id": "cl1r17gv3006h2e6dc9e7xob7", + "from": { "eventId": "cl1qz4lui00017w1a505z15p0" }, + "to": { "groupId": "cl1r15w3o005s2e6dr5l7csao" } + }, + { + "id": "cl1r0cfjt00122e6dzwtamycl", + "from": { "blockId": "cl1r09dl9000j2e6dhkc2h97y" }, + "to": { "groupId": "cl1r0c85100102e6d7uohf0cu" } + }, + { + "id": "cl1r0dfip00152e6doo9duexn", + "from": { + "blockId": "cl1r09dl9000j2e6dhkc2h97y", + "itemId": "cl1r0adei000m2e6dfc8w5y4k" + }, + "to": { "groupId": "cl1r0b3ww000q2e6d4aihat41" } + }, + { + "id": "cl1r0dibf00162e6dwuvli71j", + "from": { "blockId": "cl1r0crx600132e6d0u54j506" }, + "to": { + "groupId": "cl1r0b3ww000q2e6d4aihat41", + "blockId": "cl1r0bgit000x2e6dvdre9wsj" + } + }, + { + "id": "cl1r0f53y001q2e6dvuq434ru", + "from": { "blockId": "cl1r0b3x5000r2e6dqk8gzoim" }, + "to": { "groupId": "cl1r0exdi001l2e6drdwj3u96" } + }, + { + "id": "cl1r0i4dj001r2e6dgb96tx9q", + "from": { + "blockId": "cl1r0b3x5000r2e6dqk8gzoim", + "itemId": "cl1r0b3x5000s2e6dyq6bklbf" + }, + "to": { "groupId": "cl1r0erik00182e6dfzezujj0" } + }, + { + "id": "cl1r0ic5f001s2e6dw777scrq", + "from": { "blockId": "cl1r0exdi001o2e6d70s7si5y" }, + "to": { + "groupId": "cl1r0erik00182e6dfzezujj0", + "blockId": "cl1r0eril001d2e6d3gay9cls" + } + }, + { + "id": "cl1r0k27y00262e6dflgcp3wa", + "from": { + "blockId": "cl1r0eril001f2e6dk0fd0qpw", + "itemId": "cl1r0erim001j2e6d2waa3374" + }, + "to": { "groupId": "cl1r0j8u1001t2e6d42mjfcqo" } + }, + { + "id": "cl1r0khb6002c2e6ddssbpj9z", + "from": { "blockId": "cl1r0eril001f2e6dk0fd0qpw" }, + "to": { "groupId": "cl1r0k3tq00272e6d1fwyajjx" } + }, + { + "id": "cl1r0ktet002i2e6d5sh8gd2b", + "from": { "blockId": "cl1r0j8u200202e6dun2d04gu" }, + "to": { "groupId": "cl1r0kqof002d2e6doqhpnuqy" } + }, + { + "id": "cl1r0l7oa002j2e6dgtx0y1gh", + "from": { "blockId": "cl1r0k3tq002a2e6dv3s1eb6d" }, + "to": { + "groupId": "cl1r0j8u1001t2e6d42mjfcqo", + "blockId": "cl1r0j8u2001y2e6dr24ieifw" + } + }, + { + "id": "cl1r0lm4e002m2e6d0g3h9pm7", + "from": { + "blockId": "cl1r0j8u200202e6dun2d04gu", + "itemId": "cl1r0j8u300222e6dnj0i5fm8" + }, + "to": { "groupId": "cl1r0lfb5002k2e6dd6as5kj5" } + }, + { + "id": "cl1r0p4my00312e6d1wsgwohi", + "from": { "blockId": "cl1r0kqog002g2e6dizmxvz64" }, + "to": { + "groupId": "cl1r0lfb5002k2e6dd6as5kj5", + "blockId": "cl1r0oqrr002y2e6dsg0sa64g" + } + }, + { + "id": "cl1r0rt88003a2e6dgq6beaq1", + "from": { + "blockId": "cl1r0oqrr002y2e6dsg0sa64g", + "itemId": "cl1r0oqrr002z2e6dl821aaow" + }, + "to": { "groupId": "cl1r0rgex00382e6dkayjbys6" } + }, + { + "id": "cl1r0s6qt003d2e6d5tk2um7y", + "from": { + "blockId": "cl1r0qvwy00342e6d7ww0oqar", + "itemId": "cl1r0qvwy00352e6dui5itgd1" + }, + "to": { "groupId": "cl1r0rvak003b2e6dejcdrooq" } + }, + { + "id": "cl1r0s9g8003e2e6d5if2ywz9", + "from": { "blockId": "cl1r0rggf00392e6dcc941700" }, + "to": { "groupId": "cl1r0mn2p002p2e6dijqbjzlh" } + }, + { + "id": "cl1r0sarx003f2e6dbzmed9te", + "from": { "blockId": "cl1r0rvce003c2e6diusd3pxq" }, + "to": { "groupId": "cl1r0mn2p002p2e6dijqbjzlh" } + }, + { + "id": "cl1r0sbzh003g2e6dsqs48aoz", + "from": { "blockId": "cl1r0pe0x00332e6dxg6xdt2f" }, + "to": { "groupId": "cl1r0mn2p002p2e6dijqbjzlh" } + }, + { + "id": "cl1r0sg9m003i2e6dbsc4cqjn", + "from": { "blockId": "cl1r0qvwy00342e6d7ww0oqar" }, + "to": { "groupId": "cl1r0seuj003h2e6dandwc43r" } + }, + { + "id": "cl1r15gko005i2e6dn6rhifwe", + "from": { + "blockId": "cl1r0nt85002s2e6dloupnhdq", + "itemId": "cl1r0nt85002t2e6dvb7si7ny" + }, + "to": { "groupId": "cl1r15f68005f2e6dvdtal7cp" } + }, + { + "id": "cl1r17pzv006n2e6dpibxp9th", + "from": { + "blockId": "cl1r176e900692e6d8u3k6sdq", + "itemId": "cl1r176e9006a2e6dpvp0974z" + }, + "to": { "groupId": "cl1r09bc6000h2e6dqml18p4p" } + } + ], + "variables": [{ "id": "vcl1r0bxdj000z2e6d65u7n41b", "name": "Score" }], + "theme": {}, + "selectedThemeTemplateId": null, + "settings": { "general": {} }, + "createdAt": "2023-11-06T16:55:18.927Z", + "updatedAt": "2023-11-06T16:55:18.927Z", + "icon": "🕹️", + "folderId": null, + "publicId": null, + "customDomain": null, + "workspaceId": "proWorkspace", + "resultsTablePreferences": null, + "isArchived": false, + "isClosed": false, + "whatsAppCredentialsId": null +} diff --git a/apps/builder/public/viewer-preview.png b/apps/builder/public/viewer-preview.png new file mode 100644 index 0000000..895cdb3 Binary files /dev/null and b/apps/builder/public/viewer-preview.png differ diff --git a/apps/builder/sentry.client.config.ts b/apps/builder/sentry.client.config.ts new file mode 100644 index 0000000..96c8e4c --- /dev/null +++ b/apps/builder/sentry.client.config.ts @@ -0,0 +1,12 @@ +import * as Sentry from '@sentry/nextjs' + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + ignoreErrors: [ + 'ResizeObserver loop limit exceeded', + 'ResizeObserver loop completed with undelivered notifications.', + 'ResizeObserver is not defined', + "Can't find variable: ResizeObserver", + ], + release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder', +}) diff --git a/apps/builder/sentry.properties b/apps/builder/sentry.properties new file mode 100644 index 0000000..179de4a --- /dev/null +++ b/apps/builder/sentry.properties @@ -0,0 +1,3 @@ +defaults.url=https://sentry.io/ +defaults.org=typebot +defaults.project=builder diff --git a/apps/builder/sentry.server.config.ts b/apps/builder/sentry.server.config.ts new file mode 100644 index 0000000..a0092a1 --- /dev/null +++ b/apps/builder/sentry.server.config.ts @@ -0,0 +1,12 @@ +import * as Sentry from '@sentry/nextjs' +import prisma from '@typebot.io/lib/prisma' + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder', + integrations: [ + new Sentry.Integrations.Prisma({ + client: prisma, + }), + ], +}) diff --git a/apps/builder/src/assets/styles/custom.css b/apps/builder/src/assets/styles/custom.css new file mode 100644 index 0000000..7f0a6e2 --- /dev/null +++ b/apps/builder/src/assets/styles/custom.css @@ -0,0 +1,32 @@ +.disable-scroll-x-behavior { + overscroll-behavior-x: none; +} + +.grabbing * { + cursor: grabbing !important; +} + +/* Hide scrollbar for Chrome, Safari and Opera */ +.hide-scrollbar::-webkit-scrollbar { + display: none; +} + +/* Hide scrollbar for IE, Edge and Firefox */ +.hide-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} + +/* * { + outline: 1px solid #f00 !important; + opacity: 1 !important; + visibility: visible !important; +} */ + +/*Hide track timeline in audio tag in Windows*/ +audio::-webkit-media-controls-timeline{ + display:none; +} +audio::-webkit-media-controls-panel{ + justify-content:space-between; +} diff --git a/apps/builder/src/assets/styles/md.css b/apps/builder/src/assets/styles/md.css new file mode 100644 index 0000000..83e09ce --- /dev/null +++ b/apps/builder/src/assets/styles/md.css @@ -0,0 +1,3 @@ +.md-link { + text-decoration: underline; +} diff --git a/apps/builder/src/assets/styles/plate.css b/apps/builder/src/assets/styles/plate.css new file mode 100644 index 0000000..72845f8 --- /dev/null +++ b/apps/builder/src/assets/styles/plate.css @@ -0,0 +1,42 @@ +.slate-inline-code { + background-color: #a1a1aa; + color: white; + padding: 0.125rem 0.25rem; + border-radius: 0.35rem; + font-size: small; +} + +.slate-variable { + background-color: #ff8b1a; + color: #ffffff; + padding: 0.125rem 0.25rem; + border-radius: 0.35rem; +} + +.slate-bold { + font-weight: bold; +} + +.slate-italic { + font-style: oblique; +} + +.slate-underline { + text-decoration: underline; +} + +.slate-ToolbarButton-active > svg { + stroke-width: 2px; +} + +.slate-ToolbarButton { + color: gray; +} + +.slate-a { + text-decoration: underline; +} + +.slate-html-container > div { + min-height: 24px; +} diff --git a/apps/builder/src/assets/styles/resultsTable.css b/apps/builder/src/assets/styles/resultsTable.css new file mode 100644 index 0000000..1931ba0 --- /dev/null +++ b/apps/builder/src/assets/styles/resultsTable.css @@ -0,0 +1,11 @@ +.table-wrapper { + background-image: linear-gradient(to right, white, white), + linear-gradient(to right, white, white), + linear-gradient(to right, rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0)), + linear-gradient(to left, rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0)); + background-position: left center, right center, left center, right center; + background-repeat: no-repeat; + background-color: white; + background-size: 30px 100%, 30px 100%, 15px 100%, 15px 100%; + background-attachment: local, local, scroll, scroll; +} diff --git a/apps/builder/src/assets/styles/routerProgressBar.css b/apps/builder/src/assets/styles/routerProgressBar.css new file mode 100644 index 0000000..681503a --- /dev/null +++ b/apps/builder/src/assets/styles/routerProgressBar.css @@ -0,0 +1,40 @@ +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: var(--chakra-colors-blue-500); + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px var(--chakra-colors-blue-500), + 0 0 5px var(--chakra-colors-blue-500); + opacity: 1; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +.chakra-ui-dark #nprogress .bar { + background: var(--chakra-colors-blue-300); +} + +.chakra-ui-dark #nprogress .peg { + background: var(--chakra-colors-blue-300); +} diff --git a/apps/builder/src/components/AlertInfo.tsx b/apps/builder/src/components/AlertInfo.tsx new file mode 100644 index 0000000..44fcd11 --- /dev/null +++ b/apps/builder/src/components/AlertInfo.tsx @@ -0,0 +1,8 @@ +import { AlertProps, Alert, AlertIcon } from '@chakra-ui/react' + +export const AlertInfo = (props: AlertProps) => ( + + + {props.children} + +) diff --git a/apps/builder/src/components/ColorPicker.tsx b/apps/builder/src/components/ColorPicker.tsx new file mode 100644 index 0000000..66842b3 --- /dev/null +++ b/apps/builder/src/components/ColorPicker.tsx @@ -0,0 +1,141 @@ +import { + Popover, + PopoverTrigger, + PopoverContent, + PopoverArrow, + PopoverCloseButton, + PopoverHeader, + Center, + PopoverBody, + SimpleGrid, + Input, + Button, + Stack, + ButtonProps, + Box, +} from '@chakra-ui/react' +import React, { ChangeEvent, useState } from 'react' +import tinyColor from 'tinycolor2' + +const colorsSelection: `#${string}`[] = [ + '#666460', + '#FFFFFF', + '#A87964', + '#D09C46', + '#DE8031', + '#598E71', + '#4A8BB2', + '#9B74B7', + '#C75F96', + '#0042DA', +] + +type Props = { + value?: string + defaultValue?: string + onColorChange: (color: string) => void +} + +export const ColorPicker = ({ value, defaultValue, onColorChange }: Props) => { + const [color, setColor] = useState(defaultValue ?? '') + const displayedValue = value ?? color + + const handleColorChange = (e: ChangeEvent) => { + setColor(e.target.value) + onColorChange(e.target.value) + } + + const handleClick = (color: string) => () => { + setColor(color) + onColorChange(color) + } + + return ( + + + + + + + + +
{displayedValue}
+
+ + + {colorsSelection.map((color) => ( + + + + ) +} diff --git a/apps/builder/src/components/ConfirmModal.tsx b/apps/builder/src/components/ConfirmModal.tsx new file mode 100644 index 0000000..59e94a8 --- /dev/null +++ b/apps/builder/src/components/ConfirmModal.tsx @@ -0,0 +1,79 @@ +import { useRef, useState } from 'react' +import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, + Button, +} from '@chakra-ui/react' +import { useTranslate } from '@tolgee/react' + +type ConfirmDeleteModalProps = { + isOpen: boolean + onConfirm: () => Promise + onClose: () => void + message: JSX.Element + title?: string + confirmButtonLabel: string + confirmButtonColor?: 'blue' | 'red' +} + +export const ConfirmModal = ({ + title, + message, + isOpen, + onClose, + confirmButtonLabel, + onConfirm, + confirmButtonColor = 'red', +}: ConfirmDeleteModalProps) => { + const { t } = useTranslate() + const [confirmLoading, setConfirmLoading] = useState(false) + const cancelRef = useRef(null) + + const onConfirmClick = async () => { + setConfirmLoading(true) + try { + await onConfirm() + } catch (e) { + setConfirmLoading(false) + return setConfirmLoading(false) + } + setConfirmLoading(false) + onClose() + } + + return ( + + + + + {title ?? t('confirmModal.defaultTitle')} + + + {message} + + + + + + + + + ) +} diff --git a/apps/builder/src/components/ContextMenu.tsx b/apps/builder/src/components/ContextMenu.tsx new file mode 100644 index 0000000..8f563aa --- /dev/null +++ b/apps/builder/src/components/ContextMenu.tsx @@ -0,0 +1,108 @@ +import * as React from 'react' +import { + MutableRefObject, + useCallback, + useEffect, + useRef, + useState, +} from 'react' +import { + useEventListener, + Portal, + Menu, + MenuButton, + PortalProps, + MenuButtonProps, + MenuProps, +} from '@chakra-ui/react' + +export interface ContextMenuProps { + renderMenu: () => JSX.Element | null + children: ( + ref: MutableRefObject, + isOpened: boolean + ) => JSX.Element | null + menuProps?: MenuProps + portalProps?: PortalProps + menuButtonProps?: MenuButtonProps + isDisabled?: boolean +} + +export function ContextMenu( + props: ContextMenuProps +) { + const [isOpened, setIsOpened] = useState(false) + const [isRendered, setIsRendered] = useState(false) + const [isDeferredOpen, setIsDeferredOpen] = useState(false) + const [position, setPosition] = useState<[number, number]>([0, 0]) + const targetRef = useRef(null) + + useEffect(() => { + if (isOpened) { + setTimeout(() => { + setIsRendered(true) + setTimeout(() => { + setIsDeferredOpen(true) + }) + }) + } else { + setIsDeferredOpen(false) + const timeout = setTimeout(() => { + setIsRendered(isOpened) + }, 1000) + return () => clearTimeout(timeout) + } + }, [isOpened]) + + useEventListener( + 'contextmenu', + (e) => { + if (props.isDisabled) return + if (e.currentTarget === targetRef.current) { + e.preventDefault() + e.stopPropagation() + setIsOpened(true) + setPosition([e.pageX, e.pageY]) + } else { + setIsOpened(false) + } + }, + targetRef.current + ) + + const onCloseHandler = useCallback(() => { + props.menuProps?.onClose?.() + setIsOpened(false) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [props.menuProps?.onClose, setIsOpened]) + + return ( + <> + {props.children(targetRef, isOpened)} + {isRendered && ( + + + + {props.renderMenu()} + + + )} + + ) +} diff --git a/apps/builder/src/components/CopyButton.tsx b/apps/builder/src/components/CopyButton.tsx new file mode 100644 index 0000000..d21c2a3 --- /dev/null +++ b/apps/builder/src/components/CopyButton.tsx @@ -0,0 +1,33 @@ +import React, { useEffect } from 'react' +import { ButtonProps, Button, useClipboard } from '@chakra-ui/react' + +interface CopyButtonProps extends ButtonProps { + textToCopy: string + onCopied?: () => void + text?: { + copy: string + copied: string + } +} + +export const CopyButton = (props: CopyButtonProps) => { + const { textToCopy, onCopied, ...buttonProps } = props + const { hasCopied, onCopy, setValue } = useClipboard(textToCopy) + + useEffect(() => { + setValue(textToCopy) + }, [setValue, textToCopy]) + + return ( + + ) +} diff --git a/apps/builder/src/components/DropdownList.tsx b/apps/builder/src/components/DropdownList.tsx new file mode 100644 index 0000000..b878bd7 --- /dev/null +++ b/apps/builder/src/components/DropdownList.tsx @@ -0,0 +1,101 @@ +import { + Button, + ButtonProps, + chakra, + FormControl, + FormHelperText, + FormLabel, + HStack, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + Stack, +} from '@chakra-ui/react' +import { ChevronLeftIcon } from '@/components/icons' +import React, { ReactNode } from 'react' +import { MoreInfoTooltip } from './MoreInfoTooltip' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type Props = { + currentItem: T[number] | undefined + onItemSelect: (item: T[number]) => void + items: T + placeholder?: string + label?: string + isRequired?: boolean + direction?: 'row' | 'column' + helperText?: ReactNode + moreInfoTooltip?: string +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const DropdownList = ({ + currentItem, + onItemSelect, + items, + placeholder, + label, + isRequired, + direction = 'column', + helperText, + moreInfoTooltip, + ...props +}: Props & ButtonProps) => { + const handleMenuItemClick = (operator: T[number]) => () => { + onItemSelect(operator) + } + return ( + + {label && ( + + {label}{' '} + {moreInfoTooltip && ( + {moreInfoTooltip} + )} + + )} + + } + colorScheme="gray" + justifyContent="space-between" + textAlign="left" + w="full" + {...props} + > + + {currentItem ?? placeholder ?? 'Select an item'} + + + + + + {items.map((item) => ( + + {item} + + ))} + + + + + {helperText && {helperText}} + + ) +} diff --git a/apps/builder/src/components/EditableEmojiOrImageIcon.tsx b/apps/builder/src/components/EditableEmojiOrImageIcon.tsx new file mode 100644 index 0000000..6d04d33 --- /dev/null +++ b/apps/builder/src/components/EditableEmojiOrImageIcon.tsx @@ -0,0 +1,70 @@ +import { + Popover, + Tooltip, + chakra, + PopoverTrigger, + PopoverContent, + Flex, + useColorModeValue, +} from '@chakra-ui/react' +import React from 'react' +import { EmojiOrImageIcon } from './EmojiOrImageIcon' +import { ImageUploadContent } from './ImageUploadContent' +import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl' + +type Props = { + uploadFileProps: FilePathUploadProps + icon?: string | null + onChangeIcon: (icon: string) => void + boxSize?: string +} + +export const EditableEmojiOrImageIcon = ({ + uploadFileProps, + icon, + onChangeIcon, + boxSize, +}: Props) => { + const bg = useColorModeValue('gray.100', 'gray.700') + + return ( + + {({ onClose }: { onClose: () => void }) => ( + <> + + + + + + + + + + + + + + )} + + ) +} diff --git a/apps/builder/src/components/EmojiOrImageIcon.tsx b/apps/builder/src/components/EmojiOrImageIcon.tsx new file mode 100644 index 0000000..f68da2f --- /dev/null +++ b/apps/builder/src/components/EmojiOrImageIcon.tsx @@ -0,0 +1,40 @@ +import { ToolIcon } from '@/components/icons' +import React from 'react' +import { chakra, IconProps, Image } from '@chakra-ui/react' +import { isSvgSrc } from '@typebot.io/lib/utils' + +type Props = { + icon?: string | null + emojiFontSize?: string + boxSize?: string + defaultIcon?: (props: IconProps) => JSX.Element +} + +export const EmojiOrImageIcon = ({ + icon, + boxSize = '25px', + emojiFontSize, + defaultIcon = ToolIcon, +}: Props) => { + return ( + <> + {icon ? ( + icon.startsWith('http') || isSvgSrc(icon) ? ( + typebot icon + ) : ( + + {icon} + + ) + ) : ( + defaultIcon({ boxSize }) + )} + + ) +} diff --git a/apps/builder/src/components/GoogleLogo.tsx b/apps/builder/src/components/GoogleLogo.tsx new file mode 100644 index 0000000..91f2ca0 --- /dev/null +++ b/apps/builder/src/components/GoogleLogo.tsx @@ -0,0 +1,24 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const GoogleLogo = (props: IconProps) => ( + + + + + + + + +) diff --git a/apps/builder/src/components/ImageUploadContent/GiphyPicker.tsx b/apps/builder/src/components/ImageUploadContent/GiphyPicker.tsx new file mode 100644 index 0000000..afdcf79 --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/GiphyPicker.tsx @@ -0,0 +1,52 @@ +import { Flex, Stack, Text } from '@chakra-ui/react' +import { GiphyFetch } from '@giphy/js-fetch-api' +import { Grid } from '@giphy/react-components' +import { GiphyLogo } from '../logos/GiphyLogo' +import React, { useState } from 'react' +import { TextInput } from '../inputs' +import { env } from '@typebot.io/env' + +type GiphySearchFormProps = { + onSubmit: (url: string) => void +} + +const giphyFetch = new GiphyFetch(env.NEXT_PUBLIC_GIPHY_API_KEY ?? '') + +export const GiphyPicker = ({ onSubmit }: GiphySearchFormProps) => { + const [inputValue, setInputValue] = useState('') + + const fetchGifs = (offset: number) => + giphyFetch.search(inputValue, { offset, limit: 10 }) + + const fetchGifsTrending = (offset: number) => + giphyFetch.trending({ offset, limit: 10 }) + + return !env.NEXT_PUBLIC_GIPHY_API_KEY ? ( + NEXT_PUBLIC_GIPHY_API_KEY is missing in environment + ) : ( + + + + + + + { + e.preventDefault() + onSubmit(gif.images.downsized.url) + }} + fetchGifs={inputValue === '' ? fetchGifsTrending : fetchGifs} + width={475} + columns={3} + className="my-4" + /> + + + ) +} diff --git a/apps/builder/src/components/ImageUploadContent/IconPicker.tsx b/apps/builder/src/components/ImageUploadContent/IconPicker.tsx new file mode 100644 index 0000000..23b67cc --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/IconPicker.tsx @@ -0,0 +1,201 @@ +import { + Button, + Stack, + Image, + HStack, + useColorModeValue, + SimpleGrid, + Text, +} from '@chakra-ui/react' +import { useEffect, useMemo, useRef, useState } from 'react' +import { iconNames } from './iconNames' +import { TextInput } from '../inputs' +import { ColorPicker } from '../ColorPicker' + +const batchSize = 200 + +type Props = { + onIconSelected: (url: string) => void +} + +const localStorageRecentIconNamesKey = 'recentIconNames' +const localStorageDefaultIconColorKey = 'defaultIconColor' + +export const IconPicker = ({ onIconSelected }: Props) => { + const initialIconColor = useColorModeValue('#222222', '#ffffff') + const scrollContainer = useRef(null) + const bottomElement = useRef(null) + const [displayedIconNames, setDisplayedIconNames] = useState( + iconNames.slice(0, batchSize) + ) + const searchQuery = useRef('') + const [selectedColor, setSelectedColor] = useState(initialIconColor) + const isWhite = useMemo( + () => + initialIconColor === '#222222' && + (selectedColor.toLowerCase() === '#ffffff' || + selectedColor.toLowerCase() === '#fff' || + selectedColor === 'white'), + [initialIconColor, selectedColor] + ) + const [recentIconNames, setRecentIconNames] = useState([]) + + useEffect(() => { + const recentIconNames = localStorage.getItem(localStorageRecentIconNamesKey) + const defaultIconColor = localStorage.getItem( + localStorageDefaultIconColorKey + ) + if (recentIconNames) setRecentIconNames(JSON.parse(recentIconNames)) + if (defaultIconColor) setSelectedColor(defaultIconColor) + }, []) + + useEffect(() => { + if (!bottomElement.current) return + const observer = new IntersectionObserver(handleObserver, { + root: scrollContainer.current, + rootMargin: '200px', + }) + if (bottomElement.current) observer.observe(bottomElement.current) + return () => { + observer.disconnect() + } + }, []) + + const handleObserver = (entities: IntersectionObserverEntry[]) => { + const target = entities[0] + if (target.isIntersecting && searchQuery.current.length <= 2) + setDisplayedIconNames((displayedIconNames) => [ + ...displayedIconNames, + ...iconNames.slice( + displayedIconNames.length, + displayedIconNames.length + batchSize + ), + ]) + } + + const searchIcon = async (query: string) => { + searchQuery.current = query + if (query.length <= 2) + return setDisplayedIconNames(iconNames.slice(0, batchSize)) + const filteredIconNames = iconNames.filter((iconName) => + iconName.toLowerCase().includes(query.toLowerCase()) + ) + setDisplayedIconNames(filteredIconNames) + } + + const updateColor = (color: string) => { + if (!color.startsWith('#')) return + localStorage.setItem(localStorageDefaultIconColorKey, color) + setSelectedColor(color) + } + + const selectIcon = async (iconName: string) => { + localStorage.setItem( + localStorageRecentIconNamesKey, + JSON.stringify([...new Set([iconName, ...recentIconNames].slice(0, 30))]) + ) + const svg = await (await fetch(`/icons/${iconName}.svg`)).text() + const dataUri = `data:image/svg+xml;utf8,${svg + .replace(' + + + + + + + {recentIconNames.length > 0 && ( + + + RECENT + + + {recentIconNames.map((iconName) => ( + + ))} + + + )} + + {recentIconNames.length > 0 && ( + + ICONS + + )} + + {displayedIconNames.map((iconName) => ( + + ))} + + + +
+ + + ) +} + +const Icon = ({ name, color }: { name: string; color: string }) => { + const [svg, setSvg] = useState('') + + const dataUri = useMemo( + () => + `data:image/svg+xml;utf8,${svg.replace( + ' { + fetch(`/icons/${name}.svg`) + .then((response) => response.text()) + .then((text) => setSvg(text)) + }, [name]) + + if (!svg) return null + + return {name} +} diff --git a/apps/builder/src/components/ImageUploadContent/ImageUploadContent.tsx b/apps/builder/src/components/ImageUploadContent/ImageUploadContent.tsx new file mode 100644 index 0000000..317d6bb --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/ImageUploadContent.tsx @@ -0,0 +1,204 @@ +import { useState } from 'react' +import { Button, Flex, HStack, Stack } from '@chakra-ui/react' +import { UploadButton } from './UploadButton' +import { GiphyPicker } from './GiphyPicker' +import { TextInput } from '../inputs/TextInput' +import { EmojiSearchableList } from './emoji/EmojiSearchableList' +import { UnsplashPicker } from './UnsplashPicker' +import { IconPicker } from './IconPicker' +import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl' + +type Tabs = 'link' | 'upload' | 'giphy' | 'emoji' | 'unsplash' | 'icon' + +type Props = { + uploadFileProps: FilePathUploadProps | undefined + defaultUrl?: string + imageSize?: 'small' | 'regular' | 'thumb' + initialTab?: Tabs + onSubmit: (url: string) => void + onClose?: () => void +} & ( + | { + includedTabs?: Tabs[] + } + | { + excludedTabs?: Tabs[] + } +) + +const defaultDisplayedTabs: Tabs[] = [ + 'link', + 'upload', + 'giphy', + 'emoji', + 'unsplash', + 'icon', +] + +export const ImageUploadContent = ({ + uploadFileProps, + defaultUrl, + onSubmit, + imageSize = 'regular', + onClose, + initialTab, + ...props +}: Props) => { + const includedTabs = + 'includedTabs' in props + ? props.includedTabs ?? defaultDisplayedTabs + : defaultDisplayedTabs + const excludedTabs = 'excludedTabs' in props ? props.excludedTabs ?? [] : [] + const displayedTabs = defaultDisplayedTabs.filter( + (tab) => !excludedTabs.includes(tab) && includedTabs.includes(tab) + ) + + const [currentTab, setCurrentTab] = useState( + initialTab ?? displayedTabs[0] + ) + + const handleSubmit = (url: string) => { + onSubmit(url) + onClose && onClose() + } + + return ( + + + {displayedTabs.includes('link') && ( + + )} + {displayedTabs.includes('upload') && ( + + )} + {displayedTabs.includes('emoji') && ( + + )} + {displayedTabs.includes('giphy') && ( + + )} + {displayedTabs.includes('unsplash') && ( + + )} + {displayedTabs.includes('icon') && ( + + )} + + + + + ) +} + +const BodyContent = ({ + uploadFileProps, + tab, + defaultUrl, + imageSize, + onSubmit, +}: { + uploadFileProps?: FilePathUploadProps + tab: Tabs + defaultUrl?: string + imageSize: 'small' | 'regular' | 'thumb' + onSubmit: (url: string) => void +}) => { + switch (tab) { + case 'upload': { + if (!uploadFileProps) return null + return ( + + ) + } + case 'link': + return + case 'giphy': + return + case 'emoji': + return + case 'unsplash': + return + case 'icon': + return + } +} + +type ContentProps = { onNewUrl: (url: string) => void } + +const UploadFileContent = ({ + uploadFileProps, + onNewUrl, +}: ContentProps & { uploadFileProps: FilePathUploadProps }) => ( + + + Choose an image + + +) + +const EmbedLinkContent = ({ + defaultUrl, + onNewUrl, +}: ContentProps & { defaultUrl?: string }) => ( + + + +) + +const GiphyContent = ({ onNewUrl }: ContentProps) => ( + +) diff --git a/apps/builder/src/components/ImageUploadContent/UnsplashPicker.tsx b/apps/builder/src/components/ImageUploadContent/UnsplashPicker.tsx new file mode 100644 index 0000000..5721769 --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/UnsplashPicker.tsx @@ -0,0 +1,235 @@ +/* eslint-disable @next/next/no-img-element */ +import { + Alert, + AlertIcon, + Box, + Flex, + Grid, + GridItem, + HStack, + Image, + Link, + Spinner, + Stack, + Text, + useColorModeValue, +} from '@chakra-ui/react' +import { isDefined } from '@typebot.io/lib' +import { useCallback, useEffect, useRef, useState } from 'react' +import { createApi } from 'unsplash-js' +import { Basic as UnsplashImage } from 'unsplash-js/dist/methods/photos/types' +import { TextInput } from '../inputs' +import { UnsplashLogo } from '../logos/UnsplashLogo' +import { TextLink } from '../TextLink' +import { env } from '@typebot.io/env' + +const api = createApi({ + accessKey: env.NEXT_PUBLIC_UNSPLASH_ACCESS_KEY ?? '', +}) + +type Props = { + imageSize: 'regular' | 'small' | 'thumb' + onImageSelect: (imageUrl: string) => void +} + +export const UnsplashPicker = ({ imageSize, onImageSelect }: Props) => { + const unsplashLogoFillColor = useColorModeValue('black', 'white') + const [isFetching, setIsFetching] = useState(false) + const [images, setImages] = useState([]) + const [error, setError] = useState(null) + const [searchQuery, setSearchQuery] = useState('') + const scrollContainer = useRef(null) + const bottomAnchor = useRef(null) + + const [nextPage, setNextPage] = useState(0) + + const fetchNewImages = useCallback(async (query: string, page: number) => { + if (query === '') return searchRandomImages() + if (query.length <= 2) return + setError(null) + setIsFetching(true) + try { + const result = await api.search.getPhotos({ + query, + perPage: 30, + orientation: 'landscape', + page, + }) + if (result.errors) setError(result.errors[0]) + if (isDefined(result.response)) { + if (page === 0) setImages(result.response.results) + else + setImages((images) => [ + ...images, + ...(result.response?.results ?? []), + ]) + setNextPage((page) => page + 1) + } + } catch (err) { + if (err && typeof err === 'object' && 'message' in err) + setError(err.message as string) + setError('Something went wrong') + } + setIsFetching(false) + }, []) + + useEffect(() => { + if (!bottomAnchor.current) return + const observer = new IntersectionObserver( + (entities: IntersectionObserverEntry[]) => { + const target = entities[0] + if (target.isIntersecting) fetchNewImages(searchQuery, nextPage + 1) + }, + { + root: scrollContainer.current, + } + ) + if (bottomAnchor.current && nextPage > 0) + observer.observe(bottomAnchor.current) + return () => { + observer.disconnect() + } + }, [fetchNewImages, nextPage, searchQuery]) + + const searchRandomImages = async () => { + setError(null) + setIsFetching(true) + try { + const result = await api.photos.getRandom({ + count: 30, + orientation: 'landscape', + }) + + if (result.errors) setError(result.errors[0]) + if (isDefined(result.response)) + setImages( + Array.isArray(result.response) ? result.response : [result.response] + ) + } catch (err) { + if (err && typeof err === 'object' && 'message' in err) + setError(err.message as string) + setError('Something went wrong') + } + setIsFetching(false) + } + + const selectImage = (image: UnsplashImage) => { + const url = image.urls[imageSize] + api.photos.trackDownload({ + downloadLocation: image.links.download_location, + }) + if (isDefined(url)) onImageSelect(url) + } + + useEffect(() => { + searchRandomImages() + }, []) + + if (!env.NEXT_PUBLIC_UNSPLASH_ACCESS_KEY) + return ( + NEXT_PUBLIC_UNSPLASH_ACCESS_KEY is missing in environment + ) + + return ( + + + { + setSearchQuery(query) + fetchNewImages(query, 0) + }} + withVariableButton={false} + /> + + + + + {isDefined(error) && ( + + + {error} + + )} + + {images.length > 0 && ( + + {images.map((image, index) => ( + + selectImage(image)} + /> + + ))} + + )} + {isFetching && ( + + + + )} + + + ) +} + +type UnsplashImageProps = { + image: UnsplashImage + onClick: () => void +} + +const UnsplashImage = ({ image, onClick }: UnsplashImageProps) => { + const [isImageHovered, setIsImageHovered] = useState(false) + + const { user, urls, alt_description } = image + + return ( + setIsImageHovered(true)} + onMouseLeave={() => setIsImageHovered(false)} + h="full" + > + {alt_description + + + {user.name} + + + + ) +} diff --git a/apps/builder/src/components/ImageUploadContent/UploadButton.tsx b/apps/builder/src/components/ImageUploadContent/UploadButton.tsx new file mode 100644 index 0000000..f73e003 --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/UploadButton.tsx @@ -0,0 +1,84 @@ +import { useToast } from '@/hooks/useToast' +import { Button, ButtonProps, chakra } from '@chakra-ui/react' +import { ChangeEvent, useState } from 'react' +import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl' +import { trpc } from '@/lib/trpc' +import { compressFile } from '@/helpers/compressFile' + +type UploadButtonProps = { + fileType: 'image' | 'audio' + filePathProps: FilePathUploadProps + onFileUploaded: (url: string) => void +} & ButtonProps + +export const UploadButton = ({ + fileType, + filePathProps, + onFileUploaded, + ...props +}: UploadButtonProps) => { + const [isUploading, setIsUploading] = useState(false) + const { showToast } = useToast() + const [file, setFile] = useState() + + const { mutate } = trpc.generateUploadUrl.useMutation({ + onSettled: () => { + setIsUploading(false) + }, + onSuccess: async (data) => { + if (!file) return + const formData = new FormData() + Object.entries(data.formData).forEach(([key, value]) => { + formData.append(key, value) + }) + formData.append('file', file) + const upload = await fetch(data.presignedUrl, { + method: 'POST', + body: formData, + }) + + if (!upload.ok) { + showToast({ description: 'Error while trying to upload the file.' }) + return + } + + onFileUploaded(data.fileUrl + '?v=' + Date.now()) + }, + }) + + const handleInputChange = async (e: ChangeEvent) => { + if (!e.target?.files) return + setIsUploading(true) + const file = e.target.files[0] as File | undefined + if (!file) + return showToast({ description: 'Could not read file.', status: 'error' }) + setFile(await compressFile(file)) + mutate({ + filePathProps, + fileType: file.type, + }) + } + + return ( + <> + + + + ) +} diff --git a/apps/builder/src/components/ImageUploadContent/emoji/EmojiSearchableList.tsx b/apps/builder/src/components/ImageUploadContent/emoji/EmojiSearchableList.tsx new file mode 100644 index 0000000..9b27dff --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/emoji/EmojiSearchableList.tsx @@ -0,0 +1,215 @@ +import emojis from './emojiList.json' +import emojiTagsData from 'emojilib' +import { + Stack, + SimpleGrid, + GridItem, + Button, + Input as ClassicInput, + Text, +} from '@chakra-ui/react' +import { useState, ChangeEvent, useEffect, useRef } from 'react' + +const emojiTags = emojiTagsData as Record + +const people = emojis['Smileys & Emotion'].concat(emojis['People & Body']) +const nature = emojis['Animals & Nature'] +const food = emojis['Food & Drink'] +const activities = emojis['Activities'] +const travel = emojis['Travel & Places'] +const objects = emojis['Objects'] +const symbols = emojis['Symbols'] +const flags = emojis['Flags'] + +const localStorageRecentEmojisKey = 'recentEmojis' + +export const EmojiSearchableList = ({ + onEmojiSelected, +}: { + onEmojiSelected: (emoji: string) => void +}) => { + const scrollContainer = useRef(null) + const bottomElement = useRef(null) + const [isSearching, setIsSearching] = useState(false) + const [filteredPeople, setFilteredPeople] = useState(people) + const [filteredAnimals, setFilteredAnimals] = useState(nature) + const [filteredFood, setFilteredFood] = useState(food) + const [filteredTravel, setFilteredTravel] = useState(travel) + const [filteredActivities, setFilteredActivities] = useState(activities) + const [filteredObjects, setFilteredObjects] = useState(objects) + const [filteredSymbols, setFilteredSymbols] = useState(symbols) + const [filteredFlags, setFilteredFlags] = useState(flags) + const [totalDisplayedCategories, setTotalDisplayedCategories] = useState(1) + const [recentEmojis, setRecentEmojis] = useState([]) + + useEffect(() => { + const recentIconNames = localStorage.getItem(localStorageRecentEmojisKey) + if (!recentIconNames) return + setRecentEmojis(JSON.parse(recentIconNames)) + }, []) + + useEffect(() => { + if (!bottomElement.current) return + const observer = new IntersectionObserver(handleObserver, { + root: scrollContainer.current, + }) + if (bottomElement.current) observer.observe(bottomElement.current) + return () => { + observer.disconnect() + } + }, []) + + const handleObserver = (entities: IntersectionObserverEntry[]) => { + const target = entities[0] + if (target.isIntersecting) setTotalDisplayedCategories((c) => c + 1) + } + + const handleSearchChange = async (e: ChangeEvent) => { + const searchValue = e.target.value + if (searchValue.length <= 2 && isSearching) return resetEmojiList() + setIsSearching(true) + setTotalDisplayedCategories(8) + const byTag = (emoji: string) => + emojiTags[emoji].find((tag) => tag.includes(searchValue)) + setFilteredPeople(people.filter(byTag)) + setFilteredAnimals(nature.filter(byTag)) + setFilteredFood(food.filter(byTag)) + setFilteredTravel(travel.filter(byTag)) + setFilteredActivities(activities.filter(byTag)) + setFilteredObjects(objects.filter(byTag)) + setFilteredSymbols(symbols.filter(byTag)) + setFilteredFlags(flags.filter(byTag)) + } + + const resetEmojiList = () => { + setTotalDisplayedCategories(1) + setIsSearching(false) + setFilteredPeople(people) + setFilteredAnimals(nature) + setFilteredFood(food) + setFilteredTravel(travel) + setFilteredActivities(activities) + setFilteredObjects(objects) + setFilteredSymbols(symbols) + setFilteredFlags(flags) + } + + const selectEmoji = (emoji: string) => { + localStorage.setItem( + localStorageRecentEmojisKey, + JSON.stringify([...new Set([emoji, ...recentEmojis].slice(0, 30))]) + ) + onEmojiSelected(emoji) + } + + return ( + + + + {recentEmojis.length > 0 && ( + + + RECENT + + + + )} + {filteredPeople.length > 0 && ( + + + PEOPLE + + + + )} + {filteredAnimals.length > 0 && totalDisplayedCategories >= 2 && ( + + + ANIMALS & NATURE + + + + )} + {filteredFood.length > 0 && totalDisplayedCategories >= 3 && ( + + + FOOD & DRINK + + + + )} + {filteredTravel.length > 0 && totalDisplayedCategories >= 4 && ( + + + TRAVEL & PLACES + + + + )} + {filteredActivities.length > 0 && totalDisplayedCategories >= 5 && ( + + + ACTIVITIES + + + + )} + {filteredObjects.length > 0 && totalDisplayedCategories >= 6 && ( + + + OBJECTS + + + + )} + {filteredSymbols.length > 0 && totalDisplayedCategories >= 7 && ( + + + SYMBOLS + + + + )} + {filteredFlags.length > 0 && totalDisplayedCategories >= 8 && ( + + + FLAGS + + + + )} +
+ + + ) +} + +const EmojiGrid = ({ + emojis, + onEmojiClick, +}: { + emojis: string[] + onEmojiClick: (emoji: string) => void +}) => { + const handleClick = (emoji: string) => () => onEmojiClick(emoji) + return ( + + {emojis.map((emoji) => ( + + {emoji} + + ))} + + ) +} diff --git a/apps/builder/src/components/ImageUploadContent/emoji/emojiList.json b/apps/builder/src/components/ImageUploadContent/emoji/emojiList.json new file mode 100644 index 0000000..3ed1c0c --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/emoji/emojiList.json @@ -0,0 +1 @@ +{"Smileys & Emotion":["😀","😃","😄","😁","😆","😅","🤣","😂","🙂","🙃","😉","😊","😇","🥰","😍","🤩","😘","😗","☺️","😚","😙","🥲","😋","😛","😜","🤪","😝","🤑","🤗","🤭","🤫","🤔","🤐","🤨","😐","😑","😶","😶‍🌫️","😏","😒","🙄","😬","😮‍💨","🤥","😌","😔","😪","🤤","😴","😷","🤒","🤕","🤢","🤮","🤧","🥵","🥶","🥴","😵","😵‍💫","🤯","🤠","🥳","🥸","😎","🤓","🧐","😕","😟","🙁","☹️","😮","😯","😲","😳","🥺","😦","😧","😨","😰","😥","😢","😭","😱","😖","😣","😞","😓","😩","😫","🥱","😤","😡","😠","🤬","😈","👿","💀","☠️","💩","🤡","👹","👺","👻","👽","👾","🤖","😺","😸","😹","😻","😼","😽","🙀","😿","😾","🙈","🙉","🙊","💋","💌","💘","💝","💖","💗","💓","💞","💕","💟","❣️","💔","❤️‍🔥","❤️‍🩹","❤️","🧡","💛","💚","💙","💜","🤎","🖤","🤍","💯","💢","💥","💫","💦","💨","🕳️","💣","💬","👁️‍🗨️","🗨️","🗯️","💭","💤"],"People & Body":["👋","🤚","🖐️","✋","🖖","👌","🤌","🤏","✌️","🤞","🤟","🤘","🤙","👈","👉","👆","🖕","👇","☝️","👍","👎","✊","👊","🤛","🤜","👏","🙌","👐","🤲","🤝","🙏","✍️","💅","🤳","💪","🦾","🦿","🦵","🦶","👂","🦻","👃","🧠","🫀","🫁","🦷","🦴","👀","👁️","👅","👄","🫦","👶","🧒","👦","👧","🧑","👱","👨","🧔","🧔‍♂️","🧔‍♀️","👨‍🦰","👨‍🦱","👨‍🦳","👨‍🦲","👩","👩‍🦰","🧑‍🦰","👩‍🦱","🧑‍🦱","👩‍🦳","🧑‍🦳","👩‍🦲","🧑‍🦲","👱‍♀️","👱‍♂️","🧓","👴","👵","🙍","🙍‍♂️","🙍‍♀️","🙎","🙎‍♂️","🙎‍♀️","🙅","🙅‍♂️","🙅‍♀️","🙆","🙆‍♂️","🙆‍♀️","💁","💁‍♂️","💁‍♀️","🙋","🙋‍♂️","🙋‍♀️","🧏","🧏‍♂️","🧏‍♀️","🙇","🙇‍♂️","🙇‍♀️","🤦","🤦‍♂️","🤦‍♀️","🤷","🤷‍♂️","🤷‍♀️","🧑‍⚕️","👨‍⚕️","👩‍⚕️","🧑‍🎓","👨‍🎓","👩‍🎓","🧑‍🏫","👨‍🏫","👩‍🏫","🧑‍⚖️","👨‍⚖️","👩‍⚖️","🧑‍🌾","👨‍🌾","👩‍🌾","🧑‍🍳","👨‍🍳","👩‍🍳","🧑‍🔧","👨‍🔧","👩‍🔧","🧑‍🏭","👨‍🏭","👩‍🏭","🧑‍💼","👨‍💼","👩‍💼","🧑‍🔬","👨‍🔬","👩‍🔬","🧑‍💻","👨‍💻","👩‍💻","🧑‍🎤","👨‍🎤","👩‍🎤","🧑‍🎨","👨‍🎨","👩‍🎨","🧑‍✈️","👨‍✈️","👩‍✈️","🧑‍🚀","👨‍🚀","👩‍🚀","🧑‍🚒","👨‍🚒","👩‍🚒","👮","👮‍♂️","👮‍♀️","🕵️","🕵️‍♂️","🕵️‍♀️","💂","💂‍♂️","💂‍♀️","🥷","👷","👷‍♂️","👷‍♀️","🤴","👸","👳","👳‍♂️","👳‍♀️","👲","🧕","🤵","🤵‍♂️","🤵‍♀️","👰","👰‍♂️","👰‍♀️","🤰","🤱","👩‍🍼","👨‍🍼","🧑‍🍼","👼","🎅","🤶","🧑‍🎄","🦸","🦸‍♂️","🦸‍♀️","🦹","🦹‍♂️","🦹‍♀️","🧙","🧙‍♂️","🧙‍♀️","🧚","🧚‍♂️","🧚‍♀️","🧛","🧛‍♂️","🧛‍♀️","🧜","🧜‍♂️","🧜‍♀️","🧝","🧝‍♂️","🧝‍♀️","🧞","🧞‍♂️","🧞‍♀️","🧟","🧟‍♂️","🧟‍♀️","🧌","💆","💆‍♂️","💆‍♀️","💇","💇‍♂️","💇‍♀️","🚶","🚶‍♂️","🚶‍♀️","🧍","🧍‍♂️","🧍‍♀️","🧎","🧎‍♂️","🧎‍♀️","🧑‍🦯","👨‍🦯","👩‍🦯","🧑‍🦼","👨‍🦼","👩‍🦼","🧑‍🦽","👨‍🦽","👩‍🦽","🏃","🏃‍♂️","🏃‍♀️","💃","🕺","🕴️","👯","👯‍♂️","👯‍♀️","🧖","🧖‍♂️","🧖‍♀️","🧗","🧗‍♂️","🧗‍♀️","🤺","🏇","⛷️","🏂","🏌️","🏌️‍♂️","🏌️‍♀️","🏄","🏄‍♂️","🏄‍♀️","🚣","🚣‍♂️","🚣‍♀️","🏊","🏊‍♂️","🏊‍♀️","⛹️","⛹️‍♂️","⛹️‍♀️","🏋️","🏋️‍♂️","🏋️‍♀️","🚴","🚴‍♂️","🚴‍♀️","🚵","🚵‍♂️","🚵‍♀️","🤸","🤸‍♂️","🤸‍♀️","🤼","🤼‍♂️","🤼‍♀️","🤽","🤽‍♂️","🤽‍♀️","🤾","🤾‍♂️","🤾‍♀️","🤹","🤹‍♂️","🤹‍♀️","🧘","🧘‍♂️","🧘‍♀️","🛀","🛌","🧑‍🤝‍🧑","👭","👫","👬","💏","👩‍❤️‍💋‍👨","👨‍❤️‍💋‍👨","👩‍❤️‍💋‍👩","💑","👩‍❤️‍👨","👨‍❤️‍👨","👩‍❤️‍👩","👪","👨‍👩‍👦","👨‍👩‍👧","👨‍👩‍👧‍👦","👨‍👩‍👦‍👦","👨‍👩‍👧‍👧","👨‍👨‍👦","👨‍👨‍👧","👨‍👨‍👧‍👦","👨‍👨‍👦‍👦","👨‍👨‍👧‍👧","👩‍👩‍👦","👩‍👩‍👧","👩‍👩‍👧‍👦","👩‍👩‍👦‍👦","👩‍👩‍👧‍👧","👨‍👦","👨‍👦‍👦","👨‍👧","👨‍👧‍👦","👨‍👧‍👧","👩‍👦","👩‍👦‍👦","👩‍👧","👩‍👧‍👦","👩‍👧‍👧","🗣️","👤","👥","🫂","👣"],"Animals & Nature":["🐵","🐒","🦍","🦧","🐶","🐕","🦮","🐕‍🦺","🐩","🐺","🦊","🦝","🐱","🐈","🐈‍⬛","🦁","🐯","🐅","🐆","🐴","🐎","🦄","🦓","🦌","🦬","🐮","🐂","🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🦙","🦒","🐘","🦣","🦏","🦛","🐭","🐁","🐀","🐹","🐰","🐇","🐿️","🦫","🦔","🦇","🐻","🐻‍❄️","🐨","🐼","🦥","🦦","🦨","🦘","🦡","🐾","🦃","🐔","🐓","🐣","🐤","🐥","🐦","🐧","🕊️","🦅","🦆","🦢","🦉","🦤","🪶","🦩","🦚","🦜","🐸","🐊","🐢","🦎","🐍","🐲","🐉","🦕","🦖","🐳","🐋","🐬","🦭","🐟","🐠","🐡","🦈","🐙","🐚","🐌","🦋","🐛","🐜","🐝","🪲","🐞","🦗","🪳","🕷️","🕸️","🦂","🦟","🪰","🪱","🦠","💐","🌸","💮","🏵️","🌹","🥀","🌺","🌻","🌼","🌷","🌱","🪴","🌲","🌳","🌴","🌵","🌾","🌿","☘️","🍀","🍁","🍂","🍃"],"Food & Drink":["🍇","🍈","🍉","🍊","🍋","🍌","🍍","🥭","🍎","🍏","🍐","🍑","🍒","🍓","🫐","🥝","🍅","🫒","🥥","🥑","🍆","🥔","🥕","🌽","🌶️","🫑","🥒","🥬","🥦","🧄","🧅","🍄","🥜","🫘","🌰","🍞","🥐","🥖","🫓","🥨","🥯","🥞","🧇","🧀","🍖","🍗","🥩","🥓","🍔","🍟","🍕","🌭","🥪","🌮","🌯","🫔","🥙","🧆","🥚","🍳","🥘","🍲","🫕","🥣","🥗","🍿","🧈","🧂","🥫","🍱","🍘","🍙","🍚","🍛","🍜","🍝","🍠","🍢","🍣","🍤","🍥","🥮","🍡","🥟","🥠","🥡","🦀","🦞","🦐","🦑","🦪","🍦","🍧","🍨","🍩","🍪","🎂","🍰","🧁","🥧","🍫","🍬","🍭","🍮","🍯","🍼","🥛","☕","🫖","🍵","🍶","🍾","🍷","🍸","🍹","🍺","🍻","🥂","🥃","🥤","🧋","🧃","🧉","🧊","🥢","🍽️","🍴","🥄","🔪","🏺"],"Travel & Places":["🌍","🌎","🌏","🌐","🗺️","🗾","🧭","🏔️","⛰️","🌋","🗻","🏕️","🏖️","🏜️","🏝️","🏞️","🏟️","🏛️","🏗️","🧱","🪨","🪵","🛖","🏘️","🏚️","🏠","🏡","🏢","🏣","🏤","🏥","🏦","🏨","🏩","🏪","🏫","🏬","🏭","🏯","🏰","💒","🗼","🗽","⛪","🕌","🛕","🕍","⛩️","🕋","⛲","⛺","🌁","🌃","🏙️","🌄","🌅","🌆","🌇","🌉","♨️","🎠","🛝","🎡","🎢","💈","🎪","🚂","🚃","🚄","🚅","🚆","🚇","🚈","🚉","🚊","🚝","🚞","🚋","🚌","🚍","🚎","🚐","🚑","🚒","🚓","🚔","🚕","🚖","🚗","🚘","🚙","🛻","🚚","🚛","🚜","🏎️","🏍️","🛵","🦽","🦼","🛺","🚲","🛴","🛹","🛼","🚏","🛣️","🛤️","🛢️","⛽","🚨","🚥","🚦","🛑","🚧","⚓","⛵","🛶","🚤","🛳️","⛴️","🛥️","🚢","✈️","🛩️","🛫","🛬","🪂","💺","🚁","🚟","🚠","🚡","🛰️","🚀","🛸","🛎️","🧳","⌛","⏳","⌚","⏰","⏱️","⏲️","🕰️","🕛","🕧","🕐","🕜","🕑","🕝","🕒","🕞","🕓","🕟","🕔","🕠","🕕","🕡","🕖","🕢","🕗","🕣","🕘","🕤","🕙","🕥","🕚","🕦","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚","🌛","🌜","🌡️","☀️","🌝","🌞","🪐","⭐","🌟","🌠","🌌","☁️","⛅","⛈️","🌤️","🌥️","🌦️","🌧️","🌨️","🌩️","🌪️","🌫️","🌬️","🌀","🌈","🌂","☂️","☔","⛱️","⚡","❄️","☃️","⛄","☄️","🔥","💧","🌊"],"Activities":["🎃","🎄","🎆","🎇","🧨","✨","🎈","🎉","🎊","🎋","🎍","🎎","🎏","🎐","🎑","🧧","🎀","🎁","🎗️","🎟️","🎫","🎖️","🏆","🏅","🥇","🥈","🥉","⚽","⚾","🥎","🏀","🏐","🏈","🏉","🎾","🥏","🎳","🏏","🏑","🏒","🥍","🏓","🏸","🥊","🥋","🥅","⛳","⛸️","🎣","🤿","🎽","🎿","🛷","🥌","🎯","🪀","🪁","🎱","🔮","🪄","🧿","🎮","🕹️","🎰","🎲","🧩","🧸","🪅","🪩","🪆","♠️","♥️","♦️","♣️","♟️","🃏","🀄","🎴","🎭","🖼️","🎨","🧵","🪡","🧶","🪢"],"Objects":["👓","🕶️","🥽","🥼","🦺","👔","👕","👖","🧣","🧤","🧥","🧦","👗","👘","🥻","🩱","🩲","🩳","👙","👚","👛","👜","👝","🛍️","🎒","🩴","👞","👟","🥾","🥿","👠","👡","🩰","👢","👑","👒","🎩","🎓","🧢","🪖","⛑️","📿","💄","💍","💎","🔇","🔈","🔉","🔊","📢","📣","📯","🔔","🔕","🎼","🎵","🎶","🎙️","🎚️","🎛️","🎤","🎧","📻","🎷","🪗","🎸","🎹","🎺","🎻","🪕","🥁","🪘","📱","📲","☎️","📞","📟","📠","🔋","🪫","🔌","💻","🖥️","🖨️","⌨️","🖱️","🖲️","💽","💾","💿","📀","🧮","🎥","🎞️","📽️","🎬","📺","📷","📸","📹","📼","🔍","🔎","🕯️","💡","🔦","🏮","🪔","📔","📕","📖","📗","📘","📙","📚","📓","📒","📃","📜","📄","📰","🗞️","📑","🔖","🏷️","💰","🪙","💴","💵","💶","💷","💸","💳","🧾","💹","✉️","📧","📨","📩","📤","📥","📦","📫","📪","📬","📭","📮","🗳️","✏️","✒️","🖋️","🖊️","🖌️","🖍️","📝","💼","📁","📂","🗂️","📅","📆","🗒️","🗓️","📇","📈","📉","📊","📋","📌","📍","📎","🖇️","📏","📐","✂️","🗃️","🗄️","🗑️","🔒","🔓","🔏","🔐","🔑","🗝️","🔨","🪓","⛏️","⚒️","🛠️","🗡️","⚔️","🔫","🪃","🏹","🛡️","🪚","🔧","🪛","🔩","⚙️","🗜️","⚖️","🦯","🔗","⛓️","🪝","🧰","🧲","🪜","⚗️","🧪","🧫","🧬","🔬","🔭","📡","💉","🩸","💊","🩹","🩺","🚪","🛗","🪞","🪟","🛏️","🛋️","🪑","🚽","🪠","🚿","🛁","🪤","🪒","🧴","🧷","🧹","🧺","🧻","🪣","🧼","🫧","🪥","🧽","🧯","🛒","🚬","⚰️","🪦","⚱️","🗿","🪧"],"Symbols":["🏧","🚮","🚰","♿","🚹","🚺","🚻","🚼","🚾","🛂","🛃","🛄","🛅","⚠️","🚸","⛔","🚫","🚳","🚭","🚯","🚱","🚷","📵","🔞","☢️","☣️","⬆️","↗️","➡️","↘️","⬇️","↙️","⬅️","↖️","↕️","↔️","↩️","↪️","⤴️","⤵️","🔃","🔄","🔙","🔚","🔛","🔜","🔝","🛐","⚛️","🕉️","✡️","☸️","☯️","✝️","☦️","☪️","☮️","🕎","🔯","♈","♉","♊","♋","♌","♍","♎","♏","♐","♑","♒","♓","⛎","🔀","🔁","🔂","▶️","⏩","⏭️","⏯️","◀️","⏪","⏮️","🔼","⏫","🔽","⏬","⏸️","⏹️","⏺️","⏏️","🎦","🔅","🔆","📶","📳","📴","♀️","♂️","⚧️","✖️","➕","➖","➗","♾️","‼️","⁉️","❓","❔","❕","❗","〰️","💱","💲","⚕️","♻️","⚜️","🔱","📛","🔰","⭕","✅","☑️","✔️","❌","❎","➰","➿","〽️","✳️","✴️","❇️","©️","®️","™️","#️⃣","*️⃣","0️⃣","1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣","8️⃣","9️⃣","🔟","🔠","🔡","🔢","🔣","🔤","🅰️","🆎","🅱️","🆑","🆒","🆓","ℹ️","🆔","Ⓜ️","🆕","🆖","🅾️","🆗","🅿️","🆘","🆙","🆚","🈁","🈂️","🈷️","🈶","🈯","🉐","🈹","🈚","🈲","🉑","🈸","🈴","🈳","㊗️","㊙️","🈺","🈵","🔴","🟠","🟡","🟢","🔵","🟣","🟤","⚫","⚪","🟥","🟧","🟨","🟩","🟦","🟪","🟫","⬛","⬜","◼️","◻️","◾","◽","▪️","▫️","🔶","🔷","🔸","🔹","🔺","🔻","💠","🔘","🔳","🔲"],"Flags":["🏁","🚩","🎌","🏴","🏳️","🏳️‍🌈","🏳️‍⚧️","🏴‍☠️","🇦🇨","🇦🇩","🇦🇪","🇦🇫","🇦🇬","🇦🇮","🇦🇱","🇦🇲","🇦🇴","🇦🇶","🇦🇷","🇦🇸","🇦🇹","🇦🇺","🇦🇼","🇦🇽","🇦🇿","🇧🇦","🇧🇧","🇧🇩","🇧🇪","🇧🇫","🇧🇬","🇧🇭","🇧🇮","🇧🇯","🇧🇱","🇧🇲","🇧🇳","🇧🇴","🇧🇶","🇧🇷","🇧🇸","🇧🇹","🇧🇻","🇧🇼","🇧🇾","🇧🇿","🇨🇦","🇨🇨","🇨🇩","🇨🇫","🇨🇬","🇨🇭","🇨🇮","🇨🇰","🇨🇱","🇨🇲","🇨🇳","🇨🇴","🇨🇵","🇨🇷","🇨🇺","🇨🇻","🇨🇼","🇨🇽","🇨🇾","🇨🇿","🇩🇪","🇩🇬","🇩🇯","🇩🇰","🇩🇲","🇩🇴","🇩🇿","🇪🇦","🇪🇨","🇪🇪","🇪🇬","🇪🇭","🇪🇷","🇪🇸","🇪🇹","🇪🇺","🇫🇮","🇫🇯","🇫🇰","🇫🇲","🇫🇴","🇫🇷","🇬🇦","🇬🇧","🇬🇩","🇬🇪","🇬🇫","🇬🇬","🇬🇭","🇬🇮","🇬🇱","🇬🇲","🇬🇳","🇬🇵","🇬🇶","🇬🇷","🇬🇸","🇬🇹","🇬🇺","🇬🇼","🇬🇾","🇭🇰","🇭🇲","🇭🇳","🇭🇷","🇭🇹","🇭🇺","🇮🇨","🇮🇩","🇮🇪","🇮🇱","🇮🇲","🇮🇳","🇮🇴","🇮🇶","🇮🇷","🇮🇸","🇮🇹","🇯🇪","🇯🇲","🇯🇴","🇯🇵","🇰🇪","🇰🇬","🇰🇭","🇰🇮","🇰🇲","🇰🇳","🇰🇵","🇰🇷","🇰🇼","🇰🇾","🇰🇿","🇱🇦","🇱🇧","🇱🇨","🇱🇮","🇱🇰","🇱🇷","🇱🇸","🇱🇹","🇱🇺","🇱🇻","🇱🇾","🇲🇦","🇲🇨","🇲🇩","🇲🇪","🇲🇫","🇲🇬","🇲🇭","🇲🇰","🇲🇱","🇲🇲","🇲🇳","🇲🇴","🇲🇵","🇲🇶","🇲🇷","🇲🇸","🇲🇹","🇲🇺","🇲🇻","🇲🇼","🇲🇽","🇲🇾","🇲🇿","🇳🇦","🇳🇨","🇳🇪","🇳🇫","🇳🇬","🇳🇮","🇳🇱","🇳🇴","🇳🇵","🇳🇷","🇳🇺","🇳🇿","🇴🇲","🇵🇦","🇵🇪","🇵🇫","🇵🇬","🇵🇭","🇵🇰","🇵🇱","🇵🇲","🇵🇳","🇵🇷","🇵🇸","🇵🇹","🇵🇼","🇵🇾","🇶🇦","🇷🇪","🇷🇴","🇷🇸","🇷🇺","🇷🇼","🇸🇦","🇸🇧","🇸🇨","🇸🇩","🇸🇪","🇸🇬","🇸🇭","🇸🇮","🇸🇯","🇸🇰","🇸🇱","🇸🇲","🇸🇳","🇸🇴","🇸🇷","🇸🇸","🇸🇹","🇸🇻","🇸🇽","🇸🇾","🇸🇿","🇹🇦","🇹🇨","🇹🇩","🇹🇫","🇹🇬","🇹🇭","🇹🇯","🇹🇰","🇹🇱","🇹🇲","🇹🇳","🇹🇴","🇹🇷","🇹🇹","🇹🇻","🇹🇼","🇹🇿","🇺🇦","🇺🇬","🇺🇲","🇺🇳","🇺🇸","🇺🇾","🇺🇿","🇻🇦","🇻🇨","🇻🇪","🇻🇬","🇻🇮","🇻🇳","🇻🇺","🇼🇫","🇼🇸","🇽🇰","🇾🇪","🇾🇹","🇿🇦","🇿🇲","🇿🇼","🏴󠁧󠁢󠁥󠁮󠁧󠁿","🏴󠁧󠁢󠁳󠁣󠁴󠁿","🏴󠁧󠁢󠁷󠁬󠁳󠁿"]} \ No newline at end of file diff --git a/apps/builder/src/components/ImageUploadContent/iconNames.ts b/apps/builder/src/components/ImageUploadContent/iconNames.ts new file mode 100644 index 0000000..e54e9ca --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/iconNames.ts @@ -0,0 +1 @@ +export const iconNames = ["0","1","2","3","4","5","6","7","8","9","a","address-book","address-card","align-center","align-justify","align-left","align-right","anchor-circle-check","anchor-circle-exclamation","anchor-circle-xmark","anchor-lock","anchor","angle-down","angle-left","angle-right","angle-up","angles-down","angles-left","angles-right","angles-up","ankh","apple-whole","archway","arrow-down-1-9","arrow-down-9-1","arrow-down-a-z","arrow-down-long","arrow-down-short-wide","arrow-down-up-across-line","arrow-down-up-lock","arrow-down-wide-short","arrow-down-z-a","arrow-down","arrow-left-long","arrow-left","arrow-pointer","arrow-right-arrow-left","arrow-right-from-bracket","arrow-right-long","arrow-right-to-bracket","arrow-right-to-city","arrow-right","arrow-rotate-left","arrow-rotate-right","arrow-trend-down","arrow-trend-up","arrow-turn-down","arrow-turn-up","arrow-up-1-9","arrow-up-9-1","arrow-up-a-z","arrow-up-from-bracket","arrow-up-from-ground-water","arrow-up-from-water-pump","arrow-up-long","arrow-up-right-dots","arrow-up-right-from-square","arrow-up-short-wide","arrow-up-wide-short","arrow-up-z-a","arrow-up","arrows-down-to-line","arrows-down-to-people","arrows-left-right-to-line","arrows-left-right","arrows-rotate","arrows-spin","arrows-split-up-and-left","arrows-to-circle","arrows-to-dot","arrows-to-eye","arrows-turn-right","arrows-turn-to-dots","arrows-up-down-left-right","arrows-up-down","arrows-up-to-line","asterisk","at","atom","audio-description","austral-sign","award","b","baby-carriage","baby","backward-fast","backward-step","backward","bacon","bacteria","bacterium","bag-shopping","bahai","baht-sign","ban-smoking","ban","bandage","bangladeshi-taka-sign","barcode","bars-progress","bars-staggered","bars","baseball-bat-ball","baseball","basket-shopping","basketball","bath","battery-empty","battery-full","battery-half","battery-quarter","battery-three-quarters","bed-pulse","bed","beer-mug-empty","bell-concierge","bell-slash","bell","bezier-curve","bicycle","binoculars","biohazard","bitcoin-sign","blender-phone","blender","blog","bold","bolt-lightning","bolt","bomb","bone","bong","book-atlas","book-bible","book-bookmark","book-journal-whills","book-medical","book-open-reader","book-open","book-quran","book-skull","book-tanakh","book","bookmark","border-all","border-none","border-top-left","bore-hole","bottle-droplet","bottle-water","bowl-food","bowl-rice","bowling-ball","box-archive","box-open","box-tissue","box","boxes-packing","boxes-stacked","braille","brain","brazilian-real-sign","bread-slice","bridge-circle-check","bridge-circle-exclamation","bridge-circle-xmark","bridge-lock","bridge-water","bridge","briefcase-medical","briefcase","broom-ball","broom","brush","bucket","bug-slash","bug","bugs","building-circle-arrow-right","building-circle-check","building-circle-exclamation","building-circle-xmark","building-columns","building-flag","building-lock","building-ngo","building-shield","building-un","building-user","building-wheat","building","bullhorn","bullseye","burger","burst","bus-simple","bus","business-time","c","cable-car","cake-candles","calculator","calendar-check","calendar-day","calendar-days","calendar-minus","calendar-plus","calendar-week","calendar-xmark","calendar","camera-retro","camera-rotate","camera","campground","candy-cane","cannabis","capsules","car-battery","car-burst","car-on","car-rear","car-side","car-tunnel","car","caravan","caret-down","caret-left","caret-right","caret-up","carrot","cart-arrow-down","cart-flatbed-suitcase","cart-flatbed","cart-plus","cart-shopping","cash-register","cat","cedi-sign","cent-sign","certificate","chair","chalkboard-user","chalkboard","champagne-glasses","charging-station","chart-area","chart-bar","chart-column","chart-gantt","chart-line","chart-pie","chart-simple","check-double","check-to-slot","check","cheese","chess-bishop","chess-board","chess-king","chess-knight","chess-pawn","chess-queen","chess-rook","chess","chevron-down","chevron-left","chevron-right","chevron-up","child-combatant","child-dress","child-reaching","child","children","church","circle-arrow-down","circle-arrow-left","circle-arrow-right","circle-arrow-up","circle-check","circle-chevron-down","circle-chevron-left","circle-chevron-right","circle-chevron-up","circle-dollar-to-slot","circle-dot","circle-down","circle-exclamation","circle-h","circle-half-stroke","circle-info","circle-left","circle-minus","circle-nodes","circle-notch","circle-pause","circle-play","circle-plus","circle-question","circle-radiation","circle-right","circle-stop","circle-up","circle-user","circle-xmark","circle","city","clapperboard","clipboard-check","clipboard-list","clipboard-question","clipboard-user","clipboard","clock-rotate-left","clock","clone","closed-captioning","cloud-arrow-down","cloud-arrow-up","cloud-bolt","cloud-meatball","cloud-moon-rain","cloud-moon","cloud-rain","cloud-showers-heavy","cloud-showers-water","cloud-sun-rain","cloud-sun","cloud","clover","code-branch","code-commit","code-compare","code-fork","code-merge","code-pull-request","code","coins","colon-sign","comment-dollar","comment-dots","comment-medical","comment-slash","comment-sms","comment","comments-dollar","comments","compact-disc","compass-drafting","compass","compress","computer-mouse","computer","cookie-bite","cookie","copy","copyright","couch","cow","credit-card","crop-simple","crop","cross","crosshairs","crow","crown","crutch","cruzeiro-sign","cube","cubes-stacked","cubes","d","database","delete-left","democrat","desktop","dharmachakra","diagram-next","diagram-predecessor","diagram-project","diagram-successor","diamond-turn-right","diamond","dice-d20","dice-d6","dice-five","dice-four","dice-one","dice-six","dice-three","dice-two","dice","disease","display","divide","dna","dog","dollar-sign","dolly","dong-sign","door-closed","door-open","dove","down-left-and-up-right-to-center","down-long","download","dragon","draw-polygon","droplet-slash","droplet","drum-steelpan","drum","drumstick-bite","dumbbell","dumpster-fire","dumpster","dungeon","e","ear-deaf","ear-listen","earth-africa","earth-americas","earth-asia","earth-europe","earth-oceania","egg","eject","elevator","ellipsis-vertical","ellipsis","envelope-circle-check","envelope-open-text","envelope-open","envelope","envelopes-bulk","equals","eraser","ethernet","euro-sign","exclamation","expand","explosion","eye-dropper","eye-low-vision","eye-slash","eye","f","face-angry","face-dizzy","face-flushed","face-frown-open","face-frown","face-grimace","face-grin-beam-sweat","face-grin-beam","face-grin-hearts","face-grin-squint-tears","face-grin-squint","face-grin-stars","face-grin-tears","face-grin-tongue-squint","face-grin-tongue-wink","face-grin-tongue","face-grin-wide","face-grin-wink","face-grin","face-kiss-beam","face-kiss-wink-heart","face-kiss","face-laugh-beam","face-laugh-squint","face-laugh-wink","face-laugh","face-meh-blank","face-meh","face-rolling-eyes","face-sad-cry","face-sad-tear","face-smile-beam","face-smile-wink","face-smile","face-surprise","face-tired","fan","faucet-drip","faucet","fax","feather-pointed","feather","ferry","file-arrow-down","file-arrow-up","file-audio","file-circle-check","file-circle-exclamation","file-circle-minus","file-circle-plus","file-circle-question","file-circle-xmark","file-code","file-contract","file-csv","file-excel","file-export","file-image","file-import","file-invoice-dollar","file-invoice","file-lines","file-medical","file-pdf","file-pen","file-powerpoint","file-prescription","file-shield","file-signature","file-video","file-waveform","file-word","file-zipper","file","fill-drip","fill","film","filter-circle-dollar","filter-circle-xmark","filter","fingerprint","fire-burner","fire-extinguisher","fire-flame-curved","fire-flame-simple","fire","fish-fins","fish","flag-checkered","flag-usa","flag","flask-vial","flask","floppy-disk","florin-sign","folder-closed","folder-minus","folder-open","folder-plus","folder-tree","folder","font-awesome","font","football","forward-fast","forward-step","forward","franc-sign","frog","futbol","g","gamepad","gas-pump","gauge-high","gauge-simple-high","gauge-simple","gauge","gavel","gear","gears","gem","genderless","ghost","gift","gifts","glass-water-droplet","glass-water","glasses","globe","golf-ball-tee","gopuram","graduation-cap","greater-than-equal","greater-than","grip-lines-vertical","grip-lines","grip-vertical","grip","group-arrows-rotate","guarani-sign","guitar","gun","h","hammer","hamsa","hand-back-fist","hand-dots","hand-fist","hand-holding-dollar","hand-holding-droplet","hand-holding-hand","hand-holding-heart","hand-holding-medical","hand-holding","hand-lizard","hand-middle-finger","hand-peace","hand-point-down","hand-point-left","hand-point-right","hand-point-up","hand-pointer","hand-scissors","hand-sparkles","hand-spock","hand","handcuffs","hands-asl-interpreting","hands-bound","hands-bubbles","hands-clapping","hands-holding-child","hands-holding-circle","hands-holding","hands-praying","hands","handshake-angle","handshake-simple-slash","handshake-simple","handshake-slash","handshake","hanukiah","hard-drive","hashtag","hat-cowboy-side","hat-cowboy","hat-wizard","head-side-cough-slash","head-side-cough","head-side-mask","head-side-virus","heading","headphones-simple","headphones","headset","heart-circle-bolt","heart-circle-check","heart-circle-exclamation","heart-circle-minus","heart-circle-plus","heart-circle-xmark","heart-crack","heart-pulse","heart","helicopter-symbol","helicopter","helmet-safety","helmet-un","highlighter","hill-avalanche","hill-rockslide","hippo","hockey-puck","holly-berry","horse-head","horse","hospital-user","hospital","hot-tub-person","hotdog","hotel","hourglass-end","hourglass-half","hourglass-start","hourglass","house-chimney-crack","house-chimney-medical","house-chimney-user","house-chimney-window","house-chimney","house-circle-check","house-circle-exclamation","house-circle-xmark","house-crack","house-fire","house-flag","house-flood-water-circle-arrow-right","house-flood-water","house-laptop","house-lock","house-medical-circle-check","house-medical-circle-exclamation","house-medical-circle-xmark","house-medical-flag","house-medical","house-signal","house-tsunami","house-user","house","hryvnia-sign","hurricane","i-cursor","i","ice-cream","icicles","icons","id-badge","id-card-clip","id-card","igloo","image-portrait","image","images","inbox","indent","indian-rupee-sign","industry","infinity","info","italic","j","jar-wheat","jar","jedi","jet-fighter-up","jet-fighter","joint","jug-detergent","k","kaaba","key","keyboard","khanda","kip-sign","kit-medical","kitchen-set","kiwi-bird","l","land-mine-on","landmark-dome","landmark-flag","landmark","language","laptop-code","laptop-file","laptop-medical","laptop","lari-sign","layer-group","leaf","left-long","left-right","lemon","less-than-equal","less-than","life-ring","lightbulb","lines-leaning","link-slash","link","lira-sign","list-check","list-ol","list-ul","list","litecoin-sign","location-arrow","location-crosshairs","location-dot","location-pin-lock","location-pin","lock-open","lock","locust","lungs-virus","lungs","m","magnet","magnifying-glass-arrow-right","magnifying-glass-chart","magnifying-glass-dollar","magnifying-glass-location","magnifying-glass-minus","magnifying-glass-plus","magnifying-glass","manat-sign","map-location-dot","map-location","map-pin","map","marker","mars-and-venus-burst","mars-and-venus","mars-double","mars-stroke-right","mars-stroke-up","mars-stroke","mars","martini-glass-citrus","martini-glass-empty","martini-glass","mask-face","mask-ventilator","mask","masks-theater","mattress-pillow","maximize","medal","memory","menorah","mercury","message","meteor","microchip","microphone-lines-slash","microphone-lines","microphone-slash","microphone","microscope","mill-sign","minimize","minus","mitten","mobile-button","mobile-retro","mobile-screen-button","mobile-screen","mobile","money-bill-1-wave","money-bill-1","money-bill-transfer","money-bill-trend-up","money-bill-wave","money-bill-wheat","money-bill","money-bills","money-check-dollar","money-check","monument","moon","mortar-pestle","mosque","mosquito-net","mosquito","motorcycle","mound","mountain-city","mountain-sun","mountain","mug-hot","mug-saucer","music","n","naira-sign","network-wired","neuter","newspaper","not-equal","notdef","note-sticky","notes-medical","o","object-group","object-ungroup","oil-can","oil-well","om","otter","outdent","p","pager","paint-roller","paintbrush","palette","pallet","panorama","paper-plane","paperclip","parachute-box","paragraph","passport","paste","pause","paw","peace","pen-clip","pen-fancy","pen-nib","pen-ruler","pen-to-square","pen","pencil","people-arrows","people-carry-box","people-group","people-line","people-pulling","people-robbery","people-roof","pepper-hot","percent","person-arrow-down-to-line","person-arrow-up-from-line","person-biking","person-booth","person-breastfeeding","person-burst","person-cane","person-chalkboard","person-circle-check","person-circle-exclamation","person-circle-minus","person-circle-plus","person-circle-question","person-circle-xmark","person-digging","person-dots-from-line","person-dress-burst","person-dress","person-drowning","person-falling-burst","person-falling","person-half-dress","person-harassing","person-hiking","person-military-pointing","person-military-rifle","person-military-to-person","person-praying","person-pregnant","person-rays","person-rifle","person-running","person-shelter","person-skating","person-skiing-nordic","person-skiing","person-snowboarding","person-swimming","person-through-window","person-walking-arrow-loop-left","person-walking-arrow-right","person-walking-dashed-line-arrow-right","person-walking-luggage","person-walking-with-cane","person-walking","person","peseta-sign","peso-sign","phone-flip","phone-slash","phone-volume","phone","photo-film","piggy-bank","pills","pizza-slice","place-of-worship","plane-arrival","plane-circle-check","plane-circle-exclamation","plane-circle-xmark","plane-departure","plane-lock","plane-slash","plane-up","plane","plant-wilt","plate-wheat","play","plug-circle-bolt","plug-circle-check","plug-circle-exclamation","plug-circle-minus","plug-circle-plus","plug-circle-xmark","plug","plus-minus","plus","podcast","poo-storm","poo","poop","power-off","prescription-bottle-medical","prescription-bottle","prescription","print","pump-medical","pump-soap","puzzle-piece","q","qrcode","question","quote-left","quote-right","r","radiation","radio","rainbow","ranking-star","receipt","record-vinyl","rectangle-ad","rectangle-list","rectangle-xmark","recycle","registered","repeat","reply-all","reply","republican","restroom","retweet","ribbon","right-from-bracket","right-left","right-long","right-to-bracket","ring","road-barrier","road-bridge","road-circle-check","road-circle-exclamation","road-circle-xmark","road-lock","road-spikes","road","robot","rocket","rotate-left","rotate-right","rotate","route","rss","ruble-sign","rug","ruler-combined","ruler-horizontal","ruler-vertical","ruler","rupee-sign","rupiah-sign","s","sack-dollar","sack-xmark","sailboat","satellite-dish","satellite","scale-balanced","scale-unbalanced-flip","scale-unbalanced","school-circle-check","school-circle-exclamation","school-circle-xmark","school-flag","school-lock","school","scissors","screwdriver-wrench","screwdriver","scroll-torah","scroll","sd-card","section","seedling","server","shapes","share-from-square","share-nodes","share","sheet-plastic","shekel-sign","shield-cat","shield-dog","shield-halved","shield-heart","shield-virus","shield","ship","shirt","shoe-prints","shop-lock","shop-slash","shop","shower","shrimp","shuffle","shuttle-space","sign-hanging","signal","signature","signs-post","sim-card","sink","sitemap","skull-crossbones","skull","slash","sleigh","sliders","smog","smoking","snowflake","snowman","snowplow","soap","socks","solar-panel","sort-down","sort-up","sort","spa","spaghetti-monster-flying","spell-check","spider","spinner","splotch","spoon","spray-can-sparkles","spray-can","square-arrow-up-right","square-caret-down","square-caret-left","square-caret-right","square-caret-up","square-check","square-envelope","square-full","square-h","square-minus","square-nfi","square-parking","square-pen","square-person-confined","square-phone-flip","square-phone","square-plus","square-poll-horizontal","square-poll-vertical","square-root-variable","square-rss","square-share-nodes","square-up-right","square-virus","square-xmark","square","staff-snake","stairs","stamp","stapler","star-and-crescent","star-half-stroke","star-half","star-of-david","star-of-life","star","sterling-sign","stethoscope","stop","stopwatch-20","stopwatch","store-slash","store","street-view","strikethrough","stroopwafel","subscript","suitcase-medical","suitcase-rolling","suitcase","sun-plant-wilt","sun","superscript","swatchbook","synagogue","syringe","t","table-cells-large","table-cells","table-columns","table-list","table-tennis-paddle-ball","table","tablet-button","tablet-screen-button","tablet","tablets","tachograph-digital","tag","tags","tape","tarp-droplet","tarp","taxi","teeth-open","teeth","temperature-arrow-down","temperature-arrow-up","temperature-empty","temperature-full","temperature-half","temperature-high","temperature-low","temperature-quarter","temperature-three-quarters","tenge-sign","tent-arrow-down-to-line","tent-arrow-left-right","tent-arrow-turn-left","tent-arrows-down","tent","tents","terminal","text-height","text-slash","text-width","thermometer","thumbs-down","thumbs-up","thumbtack","ticket-simple","ticket","timeline","toggle-off","toggle-on","toilet-paper-slash","toilet-paper","toilet-portable","toilet","toilets-portable","toolbox","tooth","torii-gate","tornado","tower-broadcast","tower-cell","tower-observation","tractor","trademark","traffic-light","trailer","train-subway","train-tram","train","transgender","trash-arrow-up","trash-can-arrow-up","trash-can","trash","tree-city","tree","triangle-exclamation","trophy","trowel-bricks","trowel","truck-arrow-right","truck-droplet","truck-fast","truck-field-un","truck-field","truck-front","truck-medical","truck-monster","truck-moving","truck-pickup","truck-plane","truck-ramp-box","truck","tty","turkish-lira-sign","turn-down","turn-up","tv","u","umbrella-beach","umbrella","underline","universal-access","unlock-keyhole","unlock","up-down-left-right","up-down","up-long","up-right-and-down-left-from-center","up-right-from-square","upload","user-astronaut","user-check","user-clock","user-doctor","user-gear","user-graduate","user-group","user-injured","user-large-slash","user-large","user-lock","user-minus","user-ninja","user-nurse","user-pen","user-plus","user-secret","user-shield","user-slash","user-tag","user-tie","user-xmark","user","users-between-lines","users-gear","users-line","users-rays","users-rectangle","users-slash","users-viewfinder","users","utensils","v","van-shuttle","vault","vector-square","venus-double","venus-mars","venus","vest-patches","vest","vial-circle-check","vial-virus","vial","vials","video-slash","video","vihara","virus-covid-slash","virus-covid","virus-slash","virus","viruses","voicemail","volcano","volleyball","volume-high","volume-low","volume-off","volume-xmark","vr-cardboard","w","walkie-talkie","wallet","wand-magic-sparkles","wand-magic","wand-sparkles","warehouse","water-ladder","water","wave-square","weight-hanging","weight-scale","wheat-awn-circle-exclamation","wheat-awn","wheelchair-move","wheelchair","whiskey-glass","wifi","wind","window-maximize","window-minimize","window-restore","wine-bottle","wine-glass-empty","wine-glass","won-sign","worm","wrench","x-ray","x","xmark","xmarks-lines","y","yen-sign","yin-yang","z"] \ No newline at end of file diff --git a/apps/builder/src/components/ImageUploadContent/index.tsx b/apps/builder/src/components/ImageUploadContent/index.tsx new file mode 100644 index 0000000..7bbc1a5 --- /dev/null +++ b/apps/builder/src/components/ImageUploadContent/index.tsx @@ -0,0 +1 @@ +export { ImageUploadContent } from './ImageUploadContent' diff --git a/apps/builder/src/components/MoreInfoTooltip.tsx b/apps/builder/src/components/MoreInfoTooltip.tsx new file mode 100644 index 0000000..28e79c1 --- /dev/null +++ b/apps/builder/src/components/MoreInfoTooltip.tsx @@ -0,0 +1,16 @@ +import { Tooltip, chakra } from '@chakra-ui/react' +import { HelpCircleIcon } from './icons' + +type Props = { + children: React.ReactNode +} + +export const MoreInfoTooltip = ({ children }: Props) => { + return ( + + + + + + ) +} diff --git a/apps/builder/src/components/MotionStack.tsx b/apps/builder/src/components/MotionStack.tsx new file mode 100644 index 0000000..cfc73e7 --- /dev/null +++ b/apps/builder/src/components/MotionStack.tsx @@ -0,0 +1,12 @@ +import { forwardRef, Stack, StackProps } from '@chakra-ui/react' +import { motion, MotionProps, isValidMotionProp } from 'framer-motion' + +export const MotionStack = motion( + forwardRef((props, ref) => { + const chakraProps = Object.fromEntries( + Object.entries(props).filter(([key]) => !isValidMotionProp(key)) + ) + + return + }) +) diff --git a/apps/builder/src/components/NewVersionPopup.tsx b/apps/builder/src/components/NewVersionPopup.tsx new file mode 100644 index 0000000..0a4580d --- /dev/null +++ b/apps/builder/src/components/NewVersionPopup.tsx @@ -0,0 +1,84 @@ +import { useTypebot } from '@/features/editor/providers/TypebotProvider' +import { trpc } from '@/lib/trpc' +import { + Button, + DarkMode, + Flex, + HStack, + SlideFade, + Stack, + Text, +} from '@chakra-ui/react' +import { useEffect, useState } from 'react' +import { PackageIcon } from './icons' + +export const NewVersionPopup = () => { + const { typebot, save } = useTypebot() + const [isReloading, setIsReloading] = useState(false) + const { data } = trpc.getAppVersionProcedure.useQuery() + const [currentVersion, setCurrentVersion] = useState() + const [isNewVersionAvailable, setIsNewVersionAvailable] = useState(false) + + useEffect(() => { + if (!data?.commitSha) return + if (currentVersion === data.commitSha) return + setCurrentVersion(data.commitSha) + if (currentVersion === undefined) return + setIsNewVersionAvailable(true) + }, [data, currentVersion]) + + const saveAndReload = async () => { + if (isReloading) return + setIsReloading(true) + if (save) await save() + window.location.reload() + } + + return ( + + + + + + + + {' '} + New version available! + + + + An improved version of Typebot is available. Please reload now + to upgrade. + + + + + + + + + + + ) +} diff --git a/apps/builder/src/components/Seo.tsx b/apps/builder/src/components/Seo.tsx new file mode 100644 index 0000000..34dd9f8 --- /dev/null +++ b/apps/builder/src/components/Seo.tsx @@ -0,0 +1,42 @@ +import { env } from '@typebot.io/env' +import Head from 'next/head' + +const getOrigin = () => { + if (typeof window !== 'undefined') { + return window.location.origin + } + + return env.NEXTAUTH_URL +} + +export const Seo = ({ + title, + description = 'Create and publish conversational forms that collect 4 times more answers and feel native to your product', + imagePreviewUrl = `${getOrigin()}/images/og.png`, +}: { + title: string + description?: string + currentUrl?: string + imagePreviewUrl?: string +}) => { + const formattedTitle = `${title} | Typebot` + + return ( + + {formattedTitle} + + + + + + + + + + + + + + + ) +} diff --git a/apps/builder/src/components/SetVariableLabel.tsx b/apps/builder/src/components/SetVariableLabel.tsx new file mode 100644 index 0000000..2bf7e48 --- /dev/null +++ b/apps/builder/src/components/SetVariableLabel.tsx @@ -0,0 +1,27 @@ +import { useColorModeValue, HStack, Tag, Text } from '@chakra-ui/react' +import { Variable } from '@typebot.io/schemas' + +export const SetVariableLabel = ({ + variableId, + variables, +}: { + variableId: string + variables?: Variable[] +}) => { + const textColor = useColorModeValue('gray.600', 'gray.400') + const variableName = variables?.find( + (variable) => variable.id === variableId + )?.name + + if (!variableName) return null + return ( + + + Set + + + {variableName} + + + ) +} diff --git a/apps/builder/src/components/SupportBubble.tsx b/apps/builder/src/components/SupportBubble.tsx new file mode 100644 index 0000000..0ef1912 --- /dev/null +++ b/apps/builder/src/components/SupportBubble.tsx @@ -0,0 +1,40 @@ +import { useTypebot } from '@/features/editor/providers/TypebotProvider' +import { useUser } from '@/features/account/hooks/useUser' +import { useWorkspace } from '@/features/workspace/WorkspaceProvider' +import React, { useEffect, useState } from 'react' +import { Bubble, BubbleProps } from '@typebot.io/nextjs' +import { planToReadable } from '@/features/billing/helpers/planToReadable' + +export const SupportBubble = (props: Omit) => { + const { typebot } = useTypebot() + const { user } = useUser() + const { workspace } = useWorkspace() + + const [lastViewedTypebotId, setLastViewedTypebotId] = useState(typebot?.id) + + useEffect(() => { + if (!typebot?.id) return + if (lastViewedTypebotId === typebot?.id) return + setLastViewedTypebotId(typebot?.id) + }, [lastViewedTypebotId, typebot?.id]) + + return ( + + ) +} diff --git a/apps/builder/src/components/SwitchWithRelatedSettings.tsx b/apps/builder/src/components/SwitchWithRelatedSettings.tsx new file mode 100644 index 0000000..9e26394 --- /dev/null +++ b/apps/builder/src/components/SwitchWithRelatedSettings.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import { SwitchWithLabel, SwitchWithLabelProps } from './inputs/SwitchWithLabel' +import { Stack } from '@chakra-ui/react' + +type Props = SwitchWithLabelProps + +export const SwitchWithRelatedSettings = ({ children, ...props }: Props) => ( + + + {props.initialValue && children} + +) diff --git a/apps/builder/src/components/TableList.tsx b/apps/builder/src/components/TableList.tsx new file mode 100644 index 0000000..89d2ef5 --- /dev/null +++ b/apps/builder/src/components/TableList.tsx @@ -0,0 +1,185 @@ +import { + Box, + Button, + Fade, + Flex, + IconButton, + SlideFade, + Stack, +} from '@chakra-ui/react' +import { TrashIcon, PlusIcon } from '@/components/icons' +import { createId } from '@paralleldrive/cuid2' +import React, { useEffect, useState } from 'react' + +const defaultItem = { + id: createId(), +} + +type ItemWithId = T & { id: string } + +export type TableListItemProps = { + item: T + onItemChange: (item: T) => void +} + +type Props = { + initialItems?: ItemWithId[] + isOrdered?: boolean + addLabel?: string + newItemDefaultProps?: Partial + hasDefaultItem?: boolean + ComponentBetweenItems?: (props: unknown) => JSX.Element + onItemsChange: (items: ItemWithId[]) => void + children: (props: TableListItemProps) => JSX.Element +} + +export const TableList = ({ + initialItems, + isOrdered, + addLabel = 'Add', + newItemDefaultProps, + hasDefaultItem, + children, + ComponentBetweenItems, + onItemsChange, +}: Props) => { + const [items, setItems] = useState( + initialItems ?? (hasDefaultItem ? ([defaultItem] as ItemWithId[]) : []) + ) + const [showDeleteIndex, setShowDeleteIndex] = useState(null) + + useEffect(() => { + if (items.length && initialItems && initialItems?.length === 0) + setItems(initialItems) + }, [initialItems, items.length]) + + const createItem = () => { + const id = createId() + const newItem = { id, ...newItemDefaultProps } as ItemWithId + setItems([...items, newItem]) + onItemsChange([...items, newItem]) + } + + const insertItem = (itemIndex: number) => () => { + const id = createId() + const newItem = { id } as ItemWithId + const newItems = [...items] + newItems.splice(itemIndex + 1, 0, newItem) + setItems(newItems) + onItemsChange(newItems) + } + + const updateItem = (itemIndex: number, updates: Partial) => { + const newItems = items.map((item, idx) => + idx === itemIndex ? { ...item, ...updates } : item + ) + setItems(newItems) + onItemsChange(newItems) + } + + const deleteItem = (itemIndex: number) => () => { + const newItems = [...items] + newItems.splice(itemIndex, 1) + setItems([...newItems]) + onItemsChange([...newItems]) + } + + const handleMouseEnter = (itemIndex: number) => () => + setShowDeleteIndex(itemIndex) + + const handleCellChange = (itemIndex: number) => (item: T) => + updateItem(itemIndex, item) + + const handleMouseLeave = () => setShowDeleteIndex(null) + + return ( + + {items.map((item, itemIndex) => ( + + {itemIndex !== 0 && ComponentBetweenItems && ( + + )} + + {children({ item, onItemChange: handleCellChange(itemIndex) })} + + } + aria-label="Remove cell" + onClick={deleteItem(itemIndex)} + size="sm" + shadow="md" + /> + + {isOrdered && ( + <> + {itemIndex === 0 && ( + + } + size="xs" + shadow="md" + colorScheme="blue" + onClick={insertItem(itemIndex - 1)} + /> + + )} + + } + size="xs" + shadow="md" + colorScheme="blue" + onClick={insertItem(itemIndex)} + /> + + + )} + + + ))} + {(!isOrdered || items.length === 0) && ( + + )} + + ) +} diff --git a/apps/builder/src/components/TextLink.tsx b/apps/builder/src/components/TextLink.tsx new file mode 100644 index 0000000..5bd28d2 --- /dev/null +++ b/apps/builder/src/components/TextLink.tsx @@ -0,0 +1,40 @@ +import Link, { LinkProps } from 'next/link' +import React from 'react' +import { chakra, HStack, TextProps } from '@chakra-ui/react' +import { ExternalLinkIcon } from '@/components/icons' + +type TextLinkProps = LinkProps & TextProps & { isExternal?: boolean } + +export const TextLink = ({ + children, + href, + shallow, + replace, + scroll, + prefetch, + isExternal, + noOfLines, + ...textProps +}: TextLinkProps) => ( + + + {isExternal ? ( + + + {children} + + + + ) : ( + children + )} + + +) diff --git a/apps/builder/src/components/Toast.tsx b/apps/builder/src/components/Toast.tsx new file mode 100644 index 0000000..47b1b6d --- /dev/null +++ b/apps/builder/src/components/Toast.tsx @@ -0,0 +1,171 @@ +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Flex, + HStack, + IconButton, + Stack, + Text, + useColorModeValue, +} from '@chakra-ui/react' +import { AlertIcon, CloseIcon, InfoIcon, SmileIcon } from './icons' +import { CodeEditor } from './inputs/CodeEditor' +import { LanguageName } from '@uiw/codemirror-extensions-langs' + +export type ToastProps = { + title?: string + description?: string + details?: { + content: string + lang: LanguageName + } + status?: 'info' | 'error' | 'success' + icon?: React.ReactNode + primaryButton?: React.ReactNode + secondaryButton?: React.ReactNode + onClose: () => void +} + +export const Toast = ({ + status = 'error', + title, + description, + details, + icon, + primaryButton, + secondaryButton, + onClose, +}: ToastProps) => { + const bgColor = useColorModeValue('white', 'gray.800') + const detailsLabelColor = useColorModeValue('gray.600', 'gray.400') + + return ( + + + {' '} + + + {title && {title}} + {description && {description}} + + + {details && ( + + + + Details + + + + + + + + )} + {(secondaryButton || primaryButton) && ( + + {secondaryButton} + {primaryButton} + + )} + + + + } + size="sm" + onClick={onClose} + variant="ghost" + pos="absolute" + top={1} + right={1} + /> + + ) +} + +const Icon = ({ + customIcon, + status, +}: { + customIcon?: React.ReactNode + status: ToastProps['status'] +}) => { + const accentColor = useColorModeValue('50', '0') + const color = parseColor(status) + const icon = parseIcon(status, customIcon) + return ( + + + {icon} + + + ) +} + +const parseColor = (status: ToastProps['status']) => { + if (!status) return 'red' + switch (status) { + case 'error': + return 'red' + case 'success': + return 'green' + case 'info': + return 'blue' + } +} + +const parseIcon = ( + status: ToastProps['status'], + customIcon?: React.ReactNode +) => { + if (customIcon) return customIcon + switch (status) { + case 'error': + return + case 'success': + return + case 'info': + return + } +} diff --git a/apps/builder/src/components/TypebotLogo.tsx b/apps/builder/src/components/TypebotLogo.tsx new file mode 100644 index 0000000..96a22d0 --- /dev/null +++ b/apps/builder/src/components/TypebotLogo.tsx @@ -0,0 +1,45 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const TypebotLogo = ({ + isDark, + ...props +}: { isDark?: boolean } & IconProps) => ( + + + + + + + +) diff --git a/apps/builder/src/components/UnlockPlanAlertInfo.tsx b/apps/builder/src/components/UnlockPlanAlertInfo.tsx new file mode 100644 index 0000000..29d726c --- /dev/null +++ b/apps/builder/src/components/UnlockPlanAlertInfo.tsx @@ -0,0 +1,58 @@ +import { + Alert, + AlertIcon, + AlertProps, + Button, + HStack, + Text, + useDisclosure, +} from '@chakra-ui/react' +import React from 'react' +import { + ChangePlanModal, + ChangePlanModalProps, +} from '@/features/billing/components/ChangePlanModal' +import { useTranslate } from '@tolgee/react' + +type Props = { + buttonLabel?: string +} & AlertProps & + Pick + +export const UnlockPlanAlertInfo = ({ + buttonLabel, + type, + excludedPlans, + ...props +}: Props) => { + const { t } = useTranslate() + const { isOpen, onOpen, onClose } = useDisclosure() + return ( + + + + {props.children} + + + + + ) +} diff --git a/apps/builder/src/components/icons.tsx b/apps/builder/src/components/icons.tsx new file mode 100644 index 0000000..87b4ce2 --- /dev/null +++ b/apps/builder/src/components/icons.tsx @@ -0,0 +1,645 @@ +import { IconProps, Icon, useColorModeValue } from '@chakra-ui/react' + +export const featherIconsBaseProps: IconProps = { + fill: 'none', + stroke: 'currentColor', + strokeWidth: '2px', + strokeLinecap: 'round', + strokeLinejoin: 'round', +} + +// 99% of these icons are from Feather icons (https://feathericons.com/) + +export const SettingsIcon = (props: IconProps) => ( + + + + +) + +export const LogOutIcon = (props: IconProps) => ( + + + + + +) + +export const ChevronLeftIcon = (props: IconProps) => ( + + + +) + +export const ChevronRightIcon = (props: IconProps) => ( + + + +) + +export const ChevronDownIcon = (props: IconProps) => ( + + + +) + +export const PlusIcon = (props: IconProps) => ( + + + + +) + +export const FolderIcon = (props: IconProps) => ( + + + +) + +export const MoreVerticalIcon = (props: IconProps) => ( + + + + + +) + +export const MoreHorizontalIcon = (props: IconProps) => ( + + + + + +) + +export const GlobeIcon = (props: IconProps) => ( + + + + + +) + +export const ToolIcon = (props: IconProps) => ( + + + +) + +export const FolderPlusIcon = (props: IconProps) => ( + + + + + +) + +export const TextIcon = (props: IconProps) => ( + + + + + +) + +export const ImageIcon = (props: IconProps) => ( + + + + + +) + +export const CalendarIcon = (props: IconProps) => ( + + + + + + +) + +export const FlagIcon = (props: IconProps) => ( + + + + +) + +export const BoldIcon = (props: IconProps) => ( + + + + +) + +export const ItalicIcon = (props: IconProps) => ( + + + + + +) + +export const UnderlineIcon = (props: IconProps) => ( + + + + +) + +export const LinkIcon = (props: IconProps) => ( + + + + +) + +export const SaveIcon = (props: IconProps) => ( + + + + + +) + +export const CheckIcon = (props: IconProps) => ( + + + +) + +export const ChatIcon = (props: IconProps) => ( + + + +) + +export const TrashIcon = (props: IconProps) => ( + + + + +) + +export const LayoutIcon = (props: IconProps) => ( + + + + + +) + +export const CodeIcon = (props: IconProps) => ( + + + + +) + +export const EditIcon = (props: IconProps) => ( + + + +) + +export const UploadIcon = (props: IconProps) => ( + + + + + + +) + +export const DownloadIcon = (props: IconProps) => ( + + + + + +) + +export const NumberIcon = (props: IconProps) => ( + + + + + + +) + +export const EmailIcon = (props: IconProps) => ( + + + + +) + +export const PhoneIcon = (props: IconProps) => ( + + + +) + +export const CheckSquareIcon = (props: IconProps) => ( + + + + +) + +export const FilterIcon = (props: IconProps) => ( + + + +) + +export const UserIcon = (props: IconProps) => ( + + + + +) + +export const ExpandIcon = (props: IconProps) => ( + + + + + + +) + +export const ExternalLinkIcon = (props: IconProps) => ( + + + + + +) + +export const FilmIcon = (props: IconProps) => ( + + + + + + + + + + +) + +export const WebhookIcon = (props: IconProps) => ( + + + +) + +export const GripIcon = (props: IconProps) => ( + + + + + + + + +) + +export const LockedIcon = (props: IconProps) => ( + + + + +) + +export const UnlockedIcon = (props: IconProps) => ( + + + + +) + +export const UndoIcon = (props: IconProps) => ( + + + + +) + +export const RedoIcon = (props: IconProps) => ( + + + + +) + +export const FileIcon = (props: IconProps) => ( + + + + +) + +export const EyeIcon = (props: IconProps) => ( + + + + +) + +export const SendEmailIcon = (props: IconProps) => ( + + + + +) + +export const GithubIcon = (props: IconProps) => ( + + + +) + +export const UsersIcon = (props: IconProps) => ( + + + + + + +) + +export const AlignLeftTextIcon = (props: IconProps) => ( + + + + + + +) + +export const BoxIcon = (props: IconProps) => ( + + + + + +) + +export const HelpCircleIcon = (props: IconProps) => ( + + + + + +) + +export const CopyIcon = (props: IconProps) => ( + + + + +) + +export const TemplateIcon = (props: IconProps) => ( + + + + + + +) + +export const MinusIcon = (props: IconProps) => ( + + + +) + +export const LaptopIcon = (props: IconProps) => ( + + + + +) + +export const MouseIcon = (props: IconProps) => ( + + + +) + +export const HardDriveIcon = (props: IconProps) => ( + + + + + + +) + +export const CreditCardIcon = (props: IconProps) => ( + + + + +) + +export const PlayIcon = (props: IconProps) => ( + + + +) + +export const StarIcon = (props: IconProps) => ( + + + +) +export const BuoyIcon = (props: IconProps) => ( + + + + + + + + + +) + +export const EyeOffIcon = (props: IconProps) => ( + + + + +) + +export const AlertIcon = (props: IconProps) => ( + + + + + +) + +export const CloudOffIcon = (props: IconProps) => ( + + + + +) + +export const ListIcon = (props: IconProps) => ( + + + + + + + + +) + +export const PackageIcon = (props: IconProps) => ( + + + + + + +) + +export const CloseIcon = (props: IconProps) => ( + + + + +) + +export const NoRadiusIcon = (props: IconProps) => ( + + + + + + +) + +export const MediumRadiusIcon = (props: IconProps) => ( + + + + + + +) + +export const LargeRadiusIcon = (props: IconProps) => ( + + + + + + +) + +export const DropletIcon = (props: IconProps) => ( + + + +) + +export const TableIcon = (props: IconProps) => ( + + + +) + +export const ShuffleIcon = (props: IconProps) => ( + + + + + + + +) + +export const InfoIcon = (props: IconProps) => ( + + + + + +) + +export const SmileIcon = (props: IconProps) => ( + + + + + + +) + +export const BookIcon = (props: IconProps) => ( + + + + +) + +export const ChevronLastIcon = (props: IconProps) => ( + + + + +) + +export const XCircleIcon = (props: IconProps) => ( + + + + + +) diff --git a/apps/builder/src/components/inputs/AutocompleteInput.tsx b/apps/builder/src/components/inputs/AutocompleteInput.tsx new file mode 100644 index 0000000..8e85cf5 --- /dev/null +++ b/apps/builder/src/components/inputs/AutocompleteInput.tsx @@ -0,0 +1,224 @@ +import { + useDisclosure, + Popover, + PopoverContent, + Button, + useColorModeValue, + PopoverAnchor, + Portal, + Input, + HStack, + FormControl, +} from '@chakra-ui/react' +import { useState, useRef, useEffect } from 'react' +import { useDebouncedCallback } from 'use-debounce' +import { isDefined } from '@typebot.io/lib' +import { useOutsideClick } from '@/hooks/useOutsideClick' +import { useParentModal } from '@/features/graph/providers/ParentModalProvider' +import { VariablesButton } from '@/features/variables/components/VariablesButton' +import { Variable } from '@typebot.io/schemas' +import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput' +import { focusInput } from '@/helpers/focusInput' +import { env } from '@typebot.io/env' + +type Props = { + items: string[] | undefined + value?: string + defaultValue?: string + debounceTimeout?: number + placeholder?: string + withVariableButton?: boolean + moreInfoTooltip?: string + isRequired?: boolean + onChange: (value: string) => void +} + +export const AutocompleteInput = ({ + items, + onChange: _onChange, + debounceTimeout, + placeholder, + withVariableButton = true, + value, + defaultValue, + isRequired, +}: Props) => { + const bg = useColorModeValue('gray.200', 'gray.700') + const { onOpen, onClose, isOpen } = useDisclosure() + const [isTouched, setIsTouched] = useState(false) + const [inputValue, setInputValue] = useState(defaultValue ?? '') + const [carretPosition, setCarretPosition] = useState( + inputValue.length ?? 0 + ) + + const onChange = useDebouncedCallback( + _onChange, + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + useEffect(() => { + if (isTouched || inputValue !== '' || !defaultValue || defaultValue === '') + return + setInputValue(defaultValue ?? '') + }, [defaultValue, inputValue, isTouched]) + + const [keyboardFocusIndex, setKeyboardFocusIndex] = useState< + number | undefined + >() + const dropdownRef = useRef(null) + const itemsRef = useRef<(HTMLButtonElement | null)[]>([]) + const inputRef = useRef(null) + const { ref: parentModalRef } = useParentModal() + + const filteredItems = ( + inputValue === '' + ? items ?? [] + : [ + ...(items ?? []).filter( + (item) => + item.toLowerCase().startsWith((inputValue ?? '').toLowerCase()) && + item.toLowerCase() !== inputValue.toLowerCase() + ), + ] + ).slice(0, 50) + + useOutsideClick({ + ref: dropdownRef, + handler: onClose, + isEnabled: isOpen, + }) + + useEffect( + () => () => { + onChange.flush() + }, + [onChange] + ) + + const changeValue = (value: string) => { + if (!isTouched) setIsTouched(true) + if (!isOpen) onOpen() + setInputValue(value) + onChange(value) + } + + const handleItemClick = (value: string) => () => { + setInputValue(value) + onChange(value) + setKeyboardFocusIndex(undefined) + inputRef.current?.focus() + } + + const updateFocusedDropdownItem = ( + e: React.KeyboardEvent + ) => { + if (e.key === 'Enter' && isDefined(keyboardFocusIndex)) { + handleItemClick(filteredItems[keyboardFocusIndex])() + return setKeyboardFocusIndex(undefined) + } + if (e.key === 'ArrowDown') { + if (keyboardFocusIndex === undefined) return setKeyboardFocusIndex(0) + if (keyboardFocusIndex === filteredItems.length - 1) + return setKeyboardFocusIndex(0) + itemsRef.current[keyboardFocusIndex + 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + return setKeyboardFocusIndex(keyboardFocusIndex + 1) + } + if (e.key === 'ArrowUp') { + if (keyboardFocusIndex === 0 || keyboardFocusIndex === undefined) + return setKeyboardFocusIndex(filteredItems.length - 1) + itemsRef.current[keyboardFocusIndex - 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + setKeyboardFocusIndex(keyboardFocusIndex - 1) + } + } + + const handleVariableSelected = (variable?: Variable) => { + if (!variable) return + const { text, carretPosition: newCarretPosition } = injectVariableInText({ + variable, + text: inputValue, + at: carretPosition, + }) + changeValue(text) + focusInput({ at: newCarretPosition, input: inputRef.current }) + } + + const updateCarretPosition = (e: React.FocusEvent) => { + const carretPosition = e.target.selectionStart + if (!carretPosition) return + setCarretPosition(carretPosition) + } + + return ( + + + + + changeValue(e.target.value)} + onFocus={onOpen} + onBlur={updateCarretPosition} + onKeyDown={updateFocusedDropdownItem} + placeholder={!items ? 'Loading...' : placeholder} + isDisabled={!items} + /> + + {filteredItems.length > 0 && ( + + e.stopPropagation()} + onPointerDown={(e) => e.stopPropagation()} + > + <> + {filteredItems.map((item, idx) => { + return ( + + ) + })} + + + + )} + + {withVariableButton && ( + + )} + + + ) +} diff --git a/apps/builder/src/components/inputs/CodeEditor.tsx b/apps/builder/src/components/inputs/CodeEditor.tsx new file mode 100644 index 0000000..a569d07 --- /dev/null +++ b/apps/builder/src/components/inputs/CodeEditor.tsx @@ -0,0 +1,156 @@ +import { + BoxProps, + Fade, + HStack, + useColorModeValue, + useDisclosure, +} from '@chakra-ui/react' +import { useEffect, useRef, useState } from 'react' +import { useDebouncedCallback } from 'use-debounce' +import { VariablesButton } from '@/features/variables/components/VariablesButton' +import { Variable } from '@typebot.io/schemas' +import { env } from '@typebot.io/env' +import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror' +import { tokyoNight } from '@uiw/codemirror-theme-tokyo-night' +import { githubLight } from '@uiw/codemirror-theme-github' +import { LanguageName, loadLanguage } from '@uiw/codemirror-extensions-langs' +import { isDefined } from '@udecode/plate-common' +import { CopyButton } from '../CopyButton' + +type Props = { + value?: string + defaultValue?: string + lang: LanguageName + isReadOnly?: boolean + debounceTimeout?: number + withVariableButton?: boolean + height?: string + maxHeight?: string + minWidth?: string + onChange?: (value: string) => void +} +export const CodeEditor = ({ + defaultValue, + lang, + onChange, + height = '250px', + maxHeight = '70vh', + minWidth, + withVariableButton = true, + isReadOnly = false, + debounceTimeout = 1000, + ...props +}: Props & Omit) => { + const theme = useColorModeValue(githubLight, tokyoNight) + const codeEditor = useRef(null) + const [carretPosition, setCarretPosition] = useState(0) + const isVariableButtonDisplayed = withVariableButton && !isReadOnly + const [value, _setValue] = useState(defaultValue ?? '') + const { onOpen, onClose, isOpen } = useDisclosure() + + const setValue = useDebouncedCallback( + (value) => { + _setValue(value) + onChange && onChange(value) + }, + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + const handleVariableSelected = (variable?: Pick) => { + codeEditor.current?.view?.focus() + const insert = `{{${variable?.name}}}` + codeEditor.current?.view?.dispatch({ + changes: { + from: carretPosition, + insert, + }, + selection: { anchor: carretPosition + insert.length }, + }) + } + + const handleChange = (newValue: string) => { + setValue(newValue) + } + + const rememberCarretPosition = () => { + setCarretPosition( + codeEditor.current?.view?.state?.selection.asSingle().main.head ?? 0 + ) + } + + useEffect( + () => () => { + setValue.flush() + }, + [setValue] + ) + + return ( + + + {isVariableButtonDisplayed && ( + + )} + {isReadOnly && ( + + + + )} + + ) +} diff --git a/apps/builder/src/components/inputs/NumberInput.tsx b/apps/builder/src/components/inputs/NumberInput.tsx new file mode 100644 index 0000000..e127055 --- /dev/null +++ b/apps/builder/src/components/inputs/NumberInput.tsx @@ -0,0 +1,137 @@ +import { VariablesButton } from '@/features/variables/components/VariablesButton' +import { + NumberInputProps, + NumberInput as ChakraNumberInput, + NumberInputField, + NumberInputStepper, + NumberIncrementStepper, + NumberDecrementStepper, + HStack, + FormControl, + FormLabel, + Stack, + Text, + FormHelperText, +} from '@chakra-ui/react' +import { Variable, VariableString } from '@typebot.io/schemas' +import { ReactNode, useEffect, useState } from 'react' +import { useDebouncedCallback } from 'use-debounce' +import { env } from '@typebot.io/env' +import { MoreInfoTooltip } from '../MoreInfoTooltip' + +type Value = HasVariable extends true | undefined + ? number | VariableString + : number + +type Props = { + defaultValue: Value | undefined + debounceTimeout?: number + withVariableButton?: HasVariable + label?: string + moreInfoTooltip?: string + isRequired?: boolean + direction?: 'row' | 'column' + suffix?: string + helperText?: ReactNode + onValueChange: (value?: Value) => void +} & Omit + +export const NumberInput = ({ + defaultValue, + onValueChange, + withVariableButton, + debounceTimeout = 1000, + label, + moreInfoTooltip, + isRequired, + direction = 'column', + suffix, + helperText, + ...props +}: Props) => { + const [value, setValue] = useState(defaultValue?.toString() ?? '') + + const onValueChangeDebounced = useDebouncedCallback( + onValueChange, + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + useEffect( + () => () => { + onValueChangeDebounced.flush() + }, + [onValueChangeDebounced] + ) + + const handleValueChange = (newValue: string) => { + if (value.startsWith('{{') && value.endsWith('}}') && newValue !== '') + return + setValue(newValue) + if (newValue.endsWith('.') || newValue.endsWith(',')) return + if (newValue === '') return onValueChangeDebounced(undefined) + if ( + newValue.startsWith('{{') && + newValue.endsWith('}}') && + newValue.length > 4 && + (withVariableButton ?? true) + ) { + onValueChangeDebounced(newValue as Value) + return + } + const numberedValue = parseFloat(newValue) + if (isNaN(numberedValue)) return + onValueChangeDebounced(numberedValue) + } + + const handleVariableSelected = (variable?: Variable) => { + if (!variable) return + const newValue = `{{${variable.name}}}` + handleValueChange(newValue) + } + + const Input = ( + + + + + + + + ) + + return ( + + {label && ( + + {label}{' '} + {moreInfoTooltip && ( + {moreInfoTooltip} + )} + + )} + + {withVariableButton ?? true ? ( + + {Input} + + + ) : ( + Input + )} + {suffix ? {suffix} : null} + + {helperText ? {helperText} : null} + + ) +} diff --git a/apps/builder/src/components/inputs/RadioButtons.tsx b/apps/builder/src/components/inputs/RadioButtons.tsx new file mode 100644 index 0000000..a31134e --- /dev/null +++ b/apps/builder/src/components/inputs/RadioButtons.tsx @@ -0,0 +1,86 @@ +import { + Box, + Flex, + Stack, + useColorModeValue, + useRadio, + useRadioGroup, + UseRadioProps, +} from '@chakra-ui/react' +import { ReactNode } from 'react' + +type Props = { + options: (T | { value: T; label: ReactNode })[] + value?: T + defaultValue?: T + direction?: 'row' | 'column' + onSelect: (newValue: T) => void +} +export const RadioButtons = ({ + options, + value, + defaultValue, + direction = 'row', + onSelect, +}: Props) => { + const { getRootProps, getRadioProps } = useRadioGroup({ + value, + defaultValue, + onChange: onSelect, + }) + + const group = getRootProps() + + return ( + + {options.map((item) => { + const radio = getRadioProps({ value: parseValue(item) }) + return ( + + {parseLabel(item)} + + ) + })} + + ) +} + +export const RadioCard = (props: UseRadioProps & { children: ReactNode }) => { + const { getInputProps, getCheckboxProps } = useRadio(props) + + const input = getInputProps() + const checkbox = getCheckboxProps() + + return ( + + + + {props.children} + + + ) +} + +const parseValue = (item: string | { value: string; label: ReactNode }) => + typeof item === 'string' ? item : item.value + +const parseLabel = (item: string | { value: string; label: ReactNode }) => + typeof item === 'string' ? item : item.label diff --git a/apps/builder/src/components/inputs/Select.tsx b/apps/builder/src/components/inputs/Select.tsx new file mode 100644 index 0000000..63b6bdc --- /dev/null +++ b/apps/builder/src/components/inputs/Select.tsx @@ -0,0 +1,277 @@ +import { + useDisclosure, + Flex, + Popover, + Input, + PopoverContent, + Button, + useColorModeValue, + PopoverAnchor, + Portal, + InputGroup, + InputRightElement, + Text, + Box, + IconButton, + HStack, +} from '@chakra-ui/react' +import { useState, useRef, ChangeEvent } from 'react' +import { isDefined } from '@typebot.io/lib' +import { useOutsideClick } from '@/hooks/useOutsideClick' +import { useParentModal } from '@/features/graph/providers/ParentModalProvider' +import { ChevronDownIcon, CloseIcon } from '../icons' + +const dropdownCloseAnimationDuration = 300 + +type Item = + | string + | { + icon?: JSX.Element + label: string + value: string + extras?: Record + } + +type Props = { + isPopoverMatchingInputWidth?: boolean + selectedItem?: string + items: readonly T[] | undefined + placeholder?: string + onSelect?: (value: string | undefined, item?: T) => void +} + +export const Select = ({ + isPopoverMatchingInputWidth = true, + selectedItem, + placeholder, + items, + onSelect, +}: Props) => { + const focusedItemBgColor = useColorModeValue('gray.200', 'gray.700') + const selectedItemBgColor = useColorModeValue('blue.50', 'blue.400') + const [isTouched, setIsTouched] = useState(false) + const { onOpen, onClose, isOpen } = useDisclosure() + const [inputValue, setInputValue] = useState( + getItemLabel( + items?.find((item) => + typeof item === 'string' + ? selectedItem === item + : selectedItem === item.value + ) ?? selectedItem + ) + ) + + const [keyboardFocusIndex, setKeyboardFocusIndex] = useState< + number | undefined + >() + const dropdownRef = useRef(null) + const itemsRef = useRef<(HTMLButtonElement | null)[]>([]) + const inputRef = useRef(null) + const { ref: parentModalRef } = useParentModal() + + const filteredItems = ( + isTouched + ? [ + ...(items ?? []).filter((item) => + getItemLabel(item) + .toLowerCase() + .includes((inputValue ?? '').toLowerCase()) + ), + ] + : items ?? [] + ).slice(0, 50) + + const closeDropdown = () => { + onClose() + setTimeout(() => { + setIsTouched(false) + }, dropdownCloseAnimationDuration) + } + + useOutsideClick({ + ref: dropdownRef, + handler: closeDropdown, + isEnabled: isOpen, + }) + + const updateInputValue = (e: ChangeEvent) => { + if (!isOpen) onOpen() + if (!isTouched) setIsTouched(true) + setInputValue(e.target.value) + } + + const handleItemClick = (item: T) => () => { + if (!isTouched) setIsTouched(true) + setInputValue(getItemLabel(item)) + onSelect?.(getItemValue(item), item) + setKeyboardFocusIndex(undefined) + closeDropdown() + } + + const updateFocusedDropdownItem = ( + e: React.KeyboardEvent + ) => { + if (e.key === 'Enter' && isDefined(keyboardFocusIndex)) { + e.preventDefault() + handleItemClick(filteredItems[keyboardFocusIndex])() + return setKeyboardFocusIndex(undefined) + } + if (e.key === 'ArrowDown') { + e.preventDefault() + if (keyboardFocusIndex === undefined) return setKeyboardFocusIndex(0) + if (keyboardFocusIndex === filteredItems.length - 1) + return setKeyboardFocusIndex(0) + itemsRef.current[keyboardFocusIndex + 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + return setKeyboardFocusIndex(keyboardFocusIndex + 1) + } + if (e.key === 'ArrowUp') { + e.preventDefault() + if (keyboardFocusIndex === 0 || keyboardFocusIndex === undefined) + return setKeyboardFocusIndex(filteredItems.length - 1) + itemsRef.current[keyboardFocusIndex - 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + setKeyboardFocusIndex(keyboardFocusIndex - 1) + } + } + + const clearSelection = (e: React.MouseEvent) => { + e.preventDefault() + setInputValue('') + onSelect?.(undefined) + setKeyboardFocusIndex(undefined) + closeDropdown() + } + + return ( + + + + + + {!isTouched && items && ( + + {inputValue} + + )} + + + + + + {selectedItem && isOpen && ( + } + aria-label={'Clear'} + size="sm" + variant="ghost" + pointerEvents="all" + /> + )} + + + + + + + e.stopPropagation()} + onPointerDown={(e) => e.stopPropagation()} + > + {filteredItems.length > 0 && ( + <> + {filteredItems.map((item, idx) => { + return ( + + ) + })} + + )} + + + + + ) +} + +const getItemLabel = (item?: Item) => { + if (!item) return '' + if (typeof item === 'object') return item.label + return item +} + +const getItemValue = (item: Item) => { + if (typeof item === 'object') return item.value + return item +} diff --git a/apps/builder/src/components/inputs/SwitchWithLabel.tsx b/apps/builder/src/components/inputs/SwitchWithLabel.tsx new file mode 100644 index 0000000..0a50c5b --- /dev/null +++ b/apps/builder/src/components/inputs/SwitchWithLabel.tsx @@ -0,0 +1,48 @@ +import { + FormControl, + FormControlProps, + FormLabel, + HStack, + Switch, + SwitchProps, +} from '@chakra-ui/react' +import React, { useState } from 'react' +import { MoreInfoTooltip } from '../MoreInfoTooltip' + +export type SwitchWithLabelProps = { + label: string + initialValue: boolean + moreInfoContent?: string + onCheckChange?: (isChecked: boolean) => void + justifyContent?: FormControlProps['justifyContent'] +} & Omit + +export const SwitchWithLabel = ({ + label, + initialValue, + moreInfoContent, + onCheckChange, + justifyContent = 'space-between', + ...switchProps +}: SwitchWithLabelProps) => { + const [isChecked, setIsChecked] = useState(initialValue) + + const handleChange = () => { + setIsChecked(!isChecked) + if (onCheckChange) onCheckChange(!isChecked) + } + + return ( + + + {label} + {moreInfoContent && ( + <> +  {moreInfoContent} + + )} + + + + ) +} diff --git a/apps/builder/src/components/inputs/TextInput.tsx b/apps/builder/src/components/inputs/TextInput.tsx new file mode 100644 index 0000000..3c2a404 --- /dev/null +++ b/apps/builder/src/components/inputs/TextInput.tsx @@ -0,0 +1,166 @@ +import { VariablesButton } from '@/features/variables/components/VariablesButton' +import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput' +import { focusInput } from '@/helpers/focusInput' +import { + FormControl, + FormHelperText, + FormLabel, + HStack, + Input as ChakraInput, + InputProps, + Stack, +} from '@chakra-ui/react' +import { Variable } from '@typebot.io/schemas' +import React, { + forwardRef, + ReactNode, + useEffect, + useImperativeHandle, + useRef, + useState, +} from 'react' +import { useDebouncedCallback } from 'use-debounce' +import { env } from '@typebot.io/env' +import { MoreInfoTooltip } from '../MoreInfoTooltip' + +export type TextInputProps = { + defaultValue?: string + onChange?: (value: string) => void + debounceTimeout?: number + label?: ReactNode + helperText?: ReactNode + moreInfoTooltip?: string + withVariableButton?: boolean + isRequired?: boolean + placeholder?: string + isDisabled?: boolean + direction?: 'row' | 'column' +} & Pick< + InputProps, + | 'autoComplete' + | 'onFocus' + | 'onKeyUp' + | 'type' + | 'autoFocus' + | 'size' + | 'maxWidth' +> + +export const TextInput = forwardRef(function TextInput( + { + type, + defaultValue, + debounceTimeout = 1000, + label, + helperText, + moreInfoTooltip, + withVariableButton = true, + isRequired, + placeholder, + autoComplete, + isDisabled, + autoFocus, + onChange: _onChange, + onFocus, + onKeyUp, + size, + maxWidth, + direction = 'column', + }: TextInputProps, + ref +) { + const inputRef = useRef(null) + useImperativeHandle(ref, () => inputRef.current) + const [isTouched, setIsTouched] = useState(false) + const [localValue, setLocalValue] = useState(defaultValue ?? '') + const [carretPosition, setCarretPosition] = useState( + localValue.length ?? 0 + ) + const onChange = useDebouncedCallback( + // eslint-disable-next-line @typescript-eslint/no-empty-function + _onChange ?? (() => {}), + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + useEffect(() => { + if (isTouched || localValue !== '' || !defaultValue || defaultValue === '') + return + setLocalValue(defaultValue ?? '') + }, [defaultValue, isTouched, localValue]) + + useEffect( + () => () => { + onChange.flush() + }, + [onChange] + ) + + const changeValue = (value: string) => { + if (!isTouched) setIsTouched(true) + setLocalValue(value) + onChange(value) + } + + const handleVariableSelected = (variable?: Variable) => { + if (!variable) return + const { text, carretPosition: newCarretPosition } = injectVariableInText({ + variable, + text: localValue, + at: carretPosition, + }) + changeValue(text) + focusInput({ at: newCarretPosition, input: inputRef.current }) + } + + const updateCarretPosition = (e: React.FocusEvent) => { + const carretPosition = e.target.selectionStart + if (!carretPosition) return + setCarretPosition(carretPosition) + } + + const Input = ( + changeValue(e.target.value)} + size={size} + maxWidth={maxWidth} + /> + ) + + return ( + + {label && ( + + {label}{' '} + {moreInfoTooltip && ( + {moreInfoTooltip} + )} + + )} + {withVariableButton ? ( + + {Input} + + + ) : ( + Input + )} + {helperText && {helperText}} + + ) +}) diff --git a/apps/builder/src/components/inputs/Textarea.tsx b/apps/builder/src/components/inputs/Textarea.tsx new file mode 100644 index 0000000..cb87831 --- /dev/null +++ b/apps/builder/src/components/inputs/Textarea.tsx @@ -0,0 +1,133 @@ +import { VariablesButton } from '@/features/variables/components/VariablesButton' +import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput' +import { focusInput } from '@/helpers/focusInput' +import { + FormControl, + FormLabel, + HStack, + Textarea as ChakraTextarea, + TextareaProps, + FormHelperText, + Stack, +} from '@chakra-ui/react' +import { Variable } from '@typebot.io/schemas' +import React, { ReactNode, useEffect, useRef, useState } from 'react' +import { useDebouncedCallback } from 'use-debounce' +import { env } from '@typebot.io/env' +import { MoreInfoTooltip } from '../MoreInfoTooltip' + +type Props = { + id?: string + defaultValue?: string + debounceTimeout?: number + label?: string + moreInfoTooltip?: string + withVariableButton?: boolean + isRequired?: boolean + placeholder?: string + helperText?: ReactNode + onChange: (value: string) => void + direction?: 'row' | 'column' +} & Pick + +export const Textarea = ({ + id, + defaultValue, + onChange: _onChange, + debounceTimeout = 1000, + label, + moreInfoTooltip, + placeholder, + withVariableButton = true, + isRequired, + minH, + helperText, + direction = 'column', +}: Props) => { + const inputRef = useRef(null) + const [isTouched, setIsTouched] = useState(false) + const [localValue, setLocalValue] = useState(defaultValue ?? '') + const [carretPosition, setCarretPosition] = useState( + localValue.length ?? 0 + ) + const onChange = useDebouncedCallback( + _onChange, + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + useEffect(() => { + if (isTouched || localValue !== '' || !defaultValue || defaultValue === '') + return + setLocalValue(defaultValue ?? '') + }, [defaultValue, isTouched, localValue]) + + useEffect( + () => () => { + onChange.flush() + }, + [onChange] + ) + + const changeValue = (value: string) => { + if (!isTouched) setIsTouched(true) + setLocalValue(value) + onChange(value) + } + + const handleVariableSelected = (variable?: Variable) => { + if (!variable) return + const { text, carretPosition: newCarretPosition } = injectVariableInText({ + variable, + text: localValue, + at: carretPosition, + }) + changeValue(text) + focusInput({ at: newCarretPosition, input: inputRef.current }) + } + + const updateCarretPosition = (e: React.FocusEvent) => { + const carretPosition = e.target.selectionStart + if (!carretPosition) return + setCarretPosition(carretPosition) + } + + const Textarea = ( + changeValue(e.target.value)} + placeholder={placeholder} + minH={minH ?? '150px'} + /> + ) + + return ( + + {label && ( + + {label}{' '} + {moreInfoTooltip && ( + {moreInfoTooltip} + )} + + )} + {withVariableButton ? ( + + {Textarea} + + + ) : ( + Textarea + )} + {helperText && {helperText}} + + ) +} diff --git a/apps/builder/src/components/inputs/VariableSearchInput.tsx b/apps/builder/src/components/inputs/VariableSearchInput.tsx new file mode 100644 index 0000000..6071145 --- /dev/null +++ b/apps/builder/src/components/inputs/VariableSearchInput.tsx @@ -0,0 +1,322 @@ +import { + useDisclosure, + Flex, + Popover, + Input, + PopoverContent, + Button, + InputProps, + IconButton, + HStack, + useColorModeValue, + PopoverAnchor, + Portal, + Tag, + Text, + FormControl, + FormLabel, + FormHelperText, + Stack, +} from '@chakra-ui/react' +import { EditIcon, PlusIcon, TrashIcon } from '@/components/icons' +import { useTypebot } from '@/features/editor/providers/TypebotProvider' +import { createId } from '@paralleldrive/cuid2' +import { Variable } from '@typebot.io/schemas' +import React, { + useState, + useRef, + ChangeEvent, + useEffect, + ReactNode, +} from 'react' +import { byId, isDefined, isNotDefined } from '@typebot.io/lib' +import { useOutsideClick } from '@/hooks/useOutsideClick' +import { useParentModal } from '@/features/graph/providers/ParentModalProvider' +import { MoreInfoTooltip } from '../MoreInfoTooltip' + +type Props = { + initialVariableId: string | undefined + autoFocus?: boolean + onSelectVariable: ( + variable: Pick | undefined + ) => void + label?: string + placeholder?: string + helperText?: ReactNode + moreInfoTooltip?: string + direction?: 'row' | 'column' +} & Omit + +export const VariableSearchInput = ({ + initialVariableId, + onSelectVariable, + autoFocus, + placeholder, + label, + helperText, + moreInfoTooltip, + direction = 'column', + isRequired, + ...inputProps +}: Props) => { + const focusedItemBgColor = useColorModeValue('gray.200', 'gray.700') + const { onOpen, onClose, isOpen } = useDisclosure() + const { typebot, createVariable, deleteVariable, updateVariable } = + useTypebot() + const variables = typebot?.variables ?? [] + const [inputValue, setInputValue] = useState( + variables.find(byId(initialVariableId))?.name ?? '' + ) + const [filteredItems, setFilteredItems] = useState( + variables ?? [] + ) + const [keyboardFocusIndex, setKeyboardFocusIndex] = useState< + number | undefined + >() + const dropdownRef = useRef(null) + const inputRef = useRef(null) + const createVariableItemRef = useRef(null) + const itemsRef = useRef<(HTMLButtonElement | null)[]>([]) + const { ref: parentModalRef } = useParentModal() + + useOutsideClick({ + ref: dropdownRef, + handler: onClose, + isEnabled: isOpen, + }) + + useEffect(() => { + if (autoFocus) onOpen() + }, [autoFocus, onOpen]) + + const onInputChange = (e: ChangeEvent) => { + setInputValue(e.target.value) + if (e.target.value === '') { + if (inputValue.length > 0) { + onSelectVariable(undefined) + } + setFilteredItems([...variables.slice(0, 50)]) + return + } + setFilteredItems([ + ...variables + .filter((item) => + item.name.toLowerCase().includes((e.target.value ?? '').toLowerCase()) + ) + .slice(0, 50), + ]) + } + + const handleVariableNameClick = (variable: Variable) => () => { + setInputValue(variable.name) + onSelectVariable(variable) + setKeyboardFocusIndex(undefined) + inputRef.current?.blur() + onClose() + } + + const handleCreateNewVariableClick = () => { + if (!inputValue || inputValue === '') return + const id = 'v' + createId() + onSelectVariable({ id, name: inputValue }) + createVariable({ id, name: inputValue }) + inputRef.current?.blur() + onClose() + } + + const handleDeleteVariableClick = + (variable: Variable) => (e: React.MouseEvent) => { + e.stopPropagation() + deleteVariable(variable.id) + setFilteredItems(filteredItems.filter((item) => item.id !== variable.id)) + if (variable.name === inputValue) { + setInputValue('') + } + } + + const handleRenameVariableClick = + (variable: Variable) => (e: React.MouseEvent) => { + e.stopPropagation() + const name = prompt('Rename variable', variable.name) + if (!name) return + updateVariable(variable.id, { name }) + setFilteredItems( + filteredItems.map((item) => + item.id === variable.id ? { ...item, name } : item + ) + ) + } + + const isCreateVariableButtonDisplayed = + (inputValue?.length ?? 0) > 0 && + isNotDefined(variables.find((v) => v.name === inputValue)) + + const handleKeyUp = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && isDefined(keyboardFocusIndex)) { + if (keyboardFocusIndex === 0 && isCreateVariableButtonDisplayed) + handleCreateNewVariableClick() + else + handleVariableNameClick( + filteredItems[ + keyboardFocusIndex - (isCreateVariableButtonDisplayed ? 1 : 0) + ] + )() + return setKeyboardFocusIndex(undefined) + } + if (e.key === 'ArrowDown') { + if (keyboardFocusIndex === undefined) return setKeyboardFocusIndex(0) + if (keyboardFocusIndex >= filteredItems.length) return + itemsRef.current[keyboardFocusIndex + 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + return setKeyboardFocusIndex(keyboardFocusIndex + 1) + } + if (e.key === 'ArrowUp') { + if (keyboardFocusIndex === undefined) return + if (keyboardFocusIndex <= 0) return setKeyboardFocusIndex(undefined) + itemsRef.current[keyboardFocusIndex - 1]?.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }) + return setKeyboardFocusIndex(keyboardFocusIndex - 1) + } + return setKeyboardFocusIndex(undefined) + } + + const openDropdown = () => { + if (inputValue === '') setFilteredItems(variables) + onOpen() + } + + return ( + + {label && ( + + {label}{' '} + {moreInfoTooltip && ( + {moreInfoTooltip} + )} + + )} + + + + + + + e.stopPropagation()} + onPointerDown={(e) => e.stopPropagation()} + > + {isCreateVariableButtonDisplayed && ( + + )} + {filteredItems.length > 0 && ( + <> + {filteredItems.map((item, idx) => { + const indexInList = isCreateVariableButtonDisplayed + ? idx + 1 + : idx + return ( + + ) + })} + + )} + + + + + {helperText && {helperText}} + + ) +} diff --git a/apps/builder/src/components/inputs/index.tsx b/apps/builder/src/components/inputs/index.tsx new file mode 100644 index 0000000..9db702e --- /dev/null +++ b/apps/builder/src/components/inputs/index.tsx @@ -0,0 +1,3 @@ +export { TextInput } from './TextInput' +export { Textarea } from './Textarea' +export { NumberInput } from './NumberInput' diff --git a/apps/builder/src/components/logos/AzureAdLogo.tsx b/apps/builder/src/components/logos/AzureAdLogo.tsx new file mode 100644 index 0000000..c66fe8f --- /dev/null +++ b/apps/builder/src/components/logos/AzureAdLogo.tsx @@ -0,0 +1,31 @@ +import { Icon, IconProps } from '@chakra-ui/react' + +export const AzureAdLogo = (props: IconProps) => { + return ( + + + + + + + + + ) +} diff --git a/apps/builder/src/components/logos/FacebookLogo.tsx b/apps/builder/src/components/logos/FacebookLogo.tsx new file mode 100644 index 0000000..5e29e1d --- /dev/null +++ b/apps/builder/src/components/logos/FacebookLogo.tsx @@ -0,0 +1,11 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const FacebookLogo = (props: IconProps) => ( + + + + +) diff --git a/apps/builder/src/components/logos/GiphyLogo.tsx b/apps/builder/src/components/logos/GiphyLogo.tsx new file mode 100644 index 0000000..8e41c57 --- /dev/null +++ b/apps/builder/src/components/logos/GiphyLogo.tsx @@ -0,0 +1,23 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const GiphyLogo = (props: IconProps) => ( + + + + + + + + + + + + + + + +) diff --git a/apps/builder/src/components/logos/GitlabLogo.tsx b/apps/builder/src/components/logos/GitlabLogo.tsx new file mode 100644 index 0000000..97d0253 --- /dev/null +++ b/apps/builder/src/components/logos/GitlabLogo.tsx @@ -0,0 +1,13 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const GitlabLogo = (props: IconProps) => ( + + + + + + + + + +) diff --git a/apps/builder/src/components/logos/UnsplashLogo.tsx b/apps/builder/src/components/logos/UnsplashLogo.tsx new file mode 100644 index 0000000..82571fa --- /dev/null +++ b/apps/builder/src/components/logos/UnsplashLogo.tsx @@ -0,0 +1,7 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const UnsplashLogo = (props: IconProps) => ( + + + +) diff --git a/apps/builder/src/components/logos/WhatsAppLogo.tsx b/apps/builder/src/components/logos/WhatsAppLogo.tsx new file mode 100644 index 0000000..a5b9a7d --- /dev/null +++ b/apps/builder/src/components/logos/WhatsAppLogo.tsx @@ -0,0 +1,14 @@ +import { IconProps, Icon } from '@chakra-ui/react' + +export const whatsAppBrandColor = '#25D366' + +export const WhatsAppLogo = (props: IconProps) => ( + + + +) diff --git a/apps/builder/src/features/account/UserProvider.tsx b/apps/builder/src/features/account/UserProvider.tsx new file mode 100644 index 0000000..df4edef --- /dev/null +++ b/apps/builder/src/features/account/UserProvider.tsx @@ -0,0 +1,137 @@ +import { signOut, useSession } from 'next-auth/react' +import { useRouter } from 'next/router' +import { createContext, ReactNode, useEffect, useState } from 'react' +import { isDefined, isNotDefined } from '@typebot.io/lib' +import { User } from '@typebot.io/prisma' +import { setUser as setSentryUser } from '@sentry/nextjs' +import { useToast } from '@/hooks/useToast' +import { updateUserQuery } from './queries/updateUserQuery' +import { useDebouncedCallback } from 'use-debounce' +import { env } from '@typebot.io/env' +import { identifyUser } from '../telemetry/posthog' +import { useColorMode } from '@chakra-ui/react' + +export const userContext = createContext<{ + user?: User + isLoading: boolean + currentWorkspaceId?: string + logOut: () => void + updateUser: (newUser: Partial) => void +}>({ + isLoading: false, + logOut: () => {}, + updateUser: () => {}, +}) + +const debounceTimeout = 1000 + +export const UserProvider = ({ children }: { children: ReactNode }) => { + const router = useRouter() + const { data: session, status } = useSession() + const [user, setUser] = useState() + const { showToast } = useToast() + const [currentWorkspaceId, setCurrentWorkspaceId] = useState() + const { setColorMode } = useColorMode() + + useEffect(() => { + const currentColorScheme = localStorage.getItem('chakra-ui-color-mode') as + | 'light' + | 'dark' + | null + if (!currentColorScheme) return + const systemColorScheme = window.matchMedia('(prefers-color-scheme: dark)') + .matches + ? 'dark' + : 'light' + const userPrefersSystemMode = + !user?.preferredAppAppearance || user.preferredAppAppearance === 'system' + const computedColorMode = userPrefersSystemMode + ? systemColorScheme + : user?.preferredAppAppearance + if (computedColorMode === currentColorScheme) return + setColorMode(computedColorMode) + }, [setColorMode, user?.preferredAppAppearance]) + + useEffect(() => { + if (isDefined(user) || isNotDefined(session)) return + setCurrentWorkspaceId( + localStorage.getItem('currentWorkspaceId') ?? undefined + ) + const parsedUser = session.user as User + setUser(parsedUser) + + if (parsedUser?.id) { + setSentryUser({ id: parsedUser.id }) + identifyUser(parsedUser.id) + } + }, [session, user]) + + useEffect(() => { + if (!router.isReady) return + if (status === 'loading') return + const isSignInPath = ['/signin', '/register'].includes(router.pathname) + const isPathPublicFriendly = /\/typebots\/.+\/(edit|theme|settings)/.test( + router.pathname + ) + if (isSignInPath || isPathPublicFriendly) return + if (!user && status === 'unauthenticated') + router.replace({ + pathname: '/signin', + query: { + redirectPath: router.asPath, + }, + }) + }, [router, status, user]) + + const updateUser = (updates: Partial) => { + if (isNotDefined(user)) return + const newUser = { ...user, ...updates } + setUser(newUser) + saveUser(newUser) + } + + const saveUser = useDebouncedCallback( + async (newUser?: Partial) => { + if (isNotDefined(user)) return + const { error } = await updateUserQuery(user.id, { ...user, ...newUser }) + if (error) showToast({ title: error.name, description: error.message }) + await refreshUser() + }, + env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout + ) + + const logOut = () => { + signOut() + setUser(undefined) + } + + useEffect(() => { + return () => { + saveUser.flush() + } + }, [saveUser]) + + return ( + + {children} + + ) +} + +export const refreshUser = async () => { + await fetch('/api/auth/session?update') + reloadSession() +} + +const reloadSession = () => { + const event = new Event('visibilitychange') + document.dispatchEvent(event) +} diff --git a/apps/builder/src/features/account/account.spec.ts b/apps/builder/src/features/account/account.spec.ts new file mode 100644 index 0000000..588e81e --- /dev/null +++ b/apps/builder/src/features/account/account.spec.ts @@ -0,0 +1,47 @@ +import { getTestAsset } from '@/test/utils/playwright' +import test, { expect } from '@playwright/test' +import { env } from '@typebot.io/env' +import { userId } from '@typebot.io/lib/playwright/databaseSetup' + +test.describe.configure({ mode: 'parallel' }) + +test('should display user info properly', async ({ page }) => { + await page.goto('/typebots') + await page.click('text=Settings & Members') + expect( + page.locator('input[type="email"]').getAttribute('disabled') + ).toBeDefined() + await page.getByRole('textbox', { name: 'Name:' }).fill('John Doe') + await page.setInputFiles('input[type="file"]', getTestAsset('avatar.jpg')) + await expect(page.locator('img >> nth=1')).toHaveAttribute( + 'src', + new RegExp( + `${env.S3_ENDPOINT}${env.S3_PORT ? `:${env.S3_PORT}` : ''}/${ + env.S3_BUCKET + }/public/users/${userId}/avatar`, + 'gm' + ) + ) + await page.click('text="Preferences"') + await expect(page.locator('text=Trackpad')).toBeVisible() +}) + +test('should be able to create and delete api tokens', async ({ page }) => { + await page.goto('/typebots') + await page.click('text=Settings & Members') + await expect(page.locator('text=Github')).toBeVisible() + await page.click('text="Create"') + await expect(page.locator('button >> text="Create token"')).toBeDisabled() + await page.fill('[placeholder="I.e. Zapier, Github, Make.com"]', 'CLI') + await expect(page.locator('button >> text="Create token"')).toBeEnabled() + await page.click('button >> text="Create token"') + await expect(page.locator('text=Please copy your token')).toBeVisible() + await expect(page.locator('button >> text="Copy"')).toBeVisible() + await page.click('button >> text="Done"') + await expect(page.locator('text=CLI')).toBeVisible() + await page.click('text="Delete" >> nth=2') + await expect(page.locator('strong >> text="Github"')).toBeVisible() + await page.click('button >> text="Delete" >> nth=-1') + await expect(page.locator('button >> text="Delete" >> nth=-1')).toBeEnabled() + await expect(page.locator('text="Github"')).toBeHidden() +}) diff --git a/apps/builder/src/features/account/components/ApiTokensList.tsx b/apps/builder/src/features/account/components/ApiTokensList.tsx new file mode 100644 index 0000000..18836db --- /dev/null +++ b/apps/builder/src/features/account/components/ApiTokensList.tsx @@ -0,0 +1,137 @@ +import { + TableContainer, + Table, + Thead, + Tr, + Th, + Tbody, + Td, + Button, + Text, + Heading, + Checkbox, + Skeleton, + Stack, + Flex, + useDisclosure, +} from '@chakra-ui/react' +import { ConfirmModal } from '@/components/ConfirmModal' +import { useToast } from '@/hooks/useToast' +import { User } from '@typebot.io/prisma' +import React, { useState } from 'react' +import { byId, isDefined } from '@typebot.io/lib' +import { CreateTokenModal } from './CreateTokenModal' +import { useApiTokens } from '../hooks/useApiTokens' +import { ApiTokenFromServer } from '../types' +import { parseTimeSince } from '@/helpers/parseTimeSince' +import { deleteApiTokenQuery } from '../queries/deleteApiTokenQuery' +import { T, useTranslate } from '@tolgee/react' + +type Props = { user: User } + +export const ApiTokensList = ({ user }: Props) => { + const { t } = useTranslate() + const { showToast } = useToast() + const { apiTokens, isLoading, mutate } = useApiTokens({ + userId: user.id, + onError: (e) => + showToast({ title: 'Failed to fetch tokens', description: e.message }), + }) + const { + isOpen: isCreateOpen, + onOpen: onCreateOpen, + onClose: onCreateClose, + } = useDisclosure() + const [deletingId, setDeletingId] = useState() + + const refreshListWithNewToken = (token: ApiTokenFromServer) => { + if (!apiTokens) return + mutate({ apiTokens: [token, ...apiTokens] }) + } + + const deleteToken = async (tokenId?: string) => { + if (!apiTokens || !tokenId) return + const { error } = await deleteApiTokenQuery({ userId: user.id, tokenId }) + if (!error) mutate({ apiTokens: apiTokens.filter((t) => t.id !== tokenId) }) + } + + return ( + + {t('account.apiTokens.heading')} + {t('account.apiTokens.description')} + + + + + + + + + + + + + + + {apiTokens?.map((token) => ( + + + + + + ))} + {isLoading && + Array.from({ length: 3 }).map((_, idx) => ( + + + + + + ))} + +
{t('account.apiTokens.table.nameHeader')}{t('account.apiTokens.table.createdHeader')} +
{token.name}{parseTimeSince(token.createdAt)} ago + +
+ + + + + +
+
+ deleteToken(deletingId)} + onClose={() => setDeletingId(undefined)} + message={ + + {apiTokens?.find(byId(deletingId))?.name} + ), + }} + /> + + } + confirmButtonLabel={t('account.apiTokens.deleteButton.label')} + /> +
+ ) +} diff --git a/apps/builder/src/features/account/components/ApiTokensModal.tsx b/apps/builder/src/features/account/components/ApiTokensModal.tsx new file mode 100644 index 0000000..1073d3c --- /dev/null +++ b/apps/builder/src/features/account/components/ApiTokensModal.tsx @@ -0,0 +1,32 @@ +import { + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, +} from '@chakra-ui/react' +import { ApiTokensList } from './ApiTokensList' +import { useUser } from '../hooks/useUser' + +type Props = { + isOpen: boolean + onClose: () => void +} +export const ApiTokensModal = ({ isOpen, onClose }: Props) => { + const { user } = useUser() + + if (!user) return + return ( + + + + + + + + + + + ) +} diff --git a/apps/builder/src/features/account/components/AppearanceRadioGroup.tsx b/apps/builder/src/features/account/components/AppearanceRadioGroup.tsx new file mode 100644 index 0000000..ea7b604 --- /dev/null +++ b/apps/builder/src/features/account/components/AppearanceRadioGroup.tsx @@ -0,0 +1,71 @@ +import { + RadioGroup, + HStack, + VStack, + Stack, + Radio, + Text, + Image, +} from '@chakra-ui/react' +import { useTranslate } from '@tolgee/react' + +type Props = { + defaultValue: string + onChange: (value: string) => void +} + +export const AppearanceRadioGroup = ({ defaultValue, onChange }: Props) => { + const { t } = useTranslate() + + const appearanceData = [ + { + value: 'light', + label: t('account.preferences.appearance.lightLabel'), + image: '/images/light-mode.png', + }, + { + value: 'dark', + label: t('account.preferences.appearance.darkLabel'), + image: '/images/dark-mode.png', + }, + { + value: 'system', + label: t('account.preferences.appearance.systemLabel'), + image: '/images/system-mode.png', + }, + ] + return ( + + + {appearanceData.map((option) => ( + + + Theme preview + + {option.label} + + + + + + ))} + + + ) +} diff --git a/apps/builder/src/features/account/components/CreateTokenModal.tsx b/apps/builder/src/features/account/components/CreateTokenModal.tsx new file mode 100644 index 0000000..4c1c631 --- /dev/null +++ b/apps/builder/src/features/account/components/CreateTokenModal.tsx @@ -0,0 +1,111 @@ +import { CopyButton } from '@/components/CopyButton' +import { useTranslate } from '@tolgee/react' +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalCloseButton, + ModalBody, + Stack, + Input, + ModalFooter, + Button, + Text, + InputGroup, + InputRightElement, +} from '@chakra-ui/react' +import React, { FormEvent, useRef, useState } from 'react' +import { createApiTokenQuery } from '../queries/createApiTokenQuery' +import { ApiTokenFromServer } from '../types' + +type Props = { + userId: string + isOpen: boolean + onNewToken: (token: ApiTokenFromServer) => void + onClose: () => void +} + +export const CreateTokenModal = ({ + userId, + isOpen, + onClose, + onNewToken, +}: Props) => { + const inputRef = useRef(null) + const { t } = useTranslate() + const [name, setName] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + const [newTokenValue, setNewTokenValue] = useState() + + const createToken = async (e: FormEvent) => { + e.preventDefault() + setIsSubmitting(true) + const { data } = await createApiTokenQuery(userId, { name }) + if (data?.apiToken) { + setNewTokenValue(data.apiToken.token) + onNewToken(data.apiToken) + } + setIsSubmitting(false) + } + + return ( + + + + + {newTokenValue + ? t('account.apiTokens.createModal.createdHeading') + : t('account.apiTokens.createModal.createHeading')} + + + {newTokenValue ? ( + + + {t('account.apiTokens.createModal.copyInstruction')}{' '} + + {t('account.apiTokens.createModal.securityWarning')} + + + + + + + + + + ) : ( + + + {t('account.apiTokens.createModal.nameInput.label')} + + setName(e.target.value)} + /> + + )} + + + {newTokenValue ? ( + + ) : ( + + )} + + + + ) +} diff --git a/apps/builder/src/features/account/components/GraphNavigationRadioGroup.tsx b/apps/builder/src/features/account/components/GraphNavigationRadioGroup.tsx new file mode 100644 index 0000000..e662050 --- /dev/null +++ b/apps/builder/src/features/account/components/GraphNavigationRadioGroup.tsx @@ -0,0 +1,68 @@ +import { MouseIcon, LaptopIcon } from '@/components/icons' +import { useTranslate } from '@tolgee/react' +import { + HStack, + Radio, + RadioGroup, + Stack, + VStack, + Text, +} from '@chakra-ui/react' +import { GraphNavigation } from '@typebot.io/prisma' + +type Props = { + defaultValue: string + onChange: (value: string) => void +} +export const GraphNavigationRadioGroup = ({ + defaultValue, + onChange, +}: Props) => { + const { t } = useTranslate() + const graphNavigationData = [ + { + value: GraphNavigation.MOUSE, + label: t('account.preferences.graphNavigation.mouse.label'), + description: t('account.preferences.graphNavigation.mouse.description'), + icon: , + }, + { + value: GraphNavigation.TRACKPAD, + label: t('account.preferences.graphNavigation.trackpad.label'), + description: t( + 'account.preferences.graphNavigation.trackpad.description' + ), + icon: , + }, + ] + return ( + + + {graphNavigationData.map((option) => ( + + + {option.icon} + + {option.label} + {option.description} + + + + + + ))} + + + ) +} diff --git a/apps/builder/src/features/account/components/MyAccountForm.tsx b/apps/builder/src/features/account/components/MyAccountForm.tsx new file mode 100644 index 0000000..8979f01 --- /dev/null +++ b/apps/builder/src/features/account/components/MyAccountForm.tsx @@ -0,0 +1,83 @@ +import { Stack, HStack, Avatar, Text, Tooltip } from '@chakra-ui/react' +import { UploadIcon } from '@/components/icons' +import React, { useState } from 'react' +import { ApiTokensList } from './ApiTokensList' +import { UploadButton } from '@/components/ImageUploadContent/UploadButton' +import { useUser } from '../hooks/useUser' +import { TextInput } from '@/components/inputs/TextInput' +import { useTranslate } from '@tolgee/react' + +export const MyAccountForm = () => { + const { t } = useTranslate() + const { user, updateUser } = useUser() + const [name, setName] = useState(user?.name ?? '') + const [email, setEmail] = useState(user?.email ?? '') + + const handleFileUploaded = async (url: string) => { + updateUser({ image: url }) + } + + const handleNameChange = (newName: string) => { + setName(newName) + updateUser({ name: newName }) + } + + const handleEmailChange = (newEmail: string) => { + setEmail(newEmail) + updateUser({ email: newEmail }) + } + + return ( + + + + + {user?.id && ( + } + onFileUploaded={handleFileUploaded} + > + {t('account.myAccount.changePhotoButton.label')} + + )} + + {t('account.myAccount.changePhotoButton.specification')} + + + + + + + + + + + + {user && } + + ) +} diff --git a/apps/builder/src/features/account/components/UserPreferencesForm.tsx b/apps/builder/src/features/account/components/UserPreferencesForm.tsx new file mode 100644 index 0000000..e2d2d9a --- /dev/null +++ b/apps/builder/src/features/account/components/UserPreferencesForm.tsx @@ -0,0 +1,125 @@ +import { + Stack, + Heading, + useColorMode, + Menu, + MenuButton, + MenuList, + MenuItem, + Button, + HStack, +} from '@chakra-ui/react' +import { GraphNavigation } from '@typebot.io/prisma' +import React, { useEffect } from 'react' +import { GraphNavigationRadioGroup } from './GraphNavigationRadioGroup' +import { AppearanceRadioGroup } from './AppearanceRadioGroup' +import { useUser } from '../hooks/useUser' +import { ChevronDownIcon } from '@/components/icons' +import { MoreInfoTooltip } from '@/components/MoreInfoTooltip' +import { useTranslate, useTolgee } from '@tolgee/react' +import { useRouter } from 'next/router' + +const localeHumanReadable = { + en: 'English', + fr: 'Français', + de: 'Deutsch', + pt: 'Português', + 'pt-BR': 'Português (BR)', + ro: 'Română', + es: 'Español', +} as const + +export const UserPreferencesForm = () => { + const { getLanguage } = useTolgee() + const router = useRouter() + const { t } = useTranslate() + const { colorMode } = useColorMode() + const { user, updateUser } = useUser() + + useEffect(() => { + if (!user?.graphNavigation) + updateUser({ graphNavigation: GraphNavigation.TRACKPAD }) + }, [updateUser, user?.graphNavigation]) + + const changeGraphNavigation = async (value: string) => { + updateUser({ graphNavigation: value as GraphNavigation }) + } + + const changeAppearance = async (value: string) => { + updateUser({ preferredAppAppearance: value }) + } + + const updateLocale = (locale: keyof typeof localeHumanReadable) => () => { + document.cookie = `NEXT_LOCALE=${locale}; path=/; max-age=31536000` + router.replace( + { + pathname: router.pathname, + query: router.query, + }, + undefined, + { locale } + ) + } + + const currentLanguage = getLanguage() + + return ( + + + {t('account.preferences.language.heading')} + + }> + {currentLanguage + ? localeHumanReadable[ + currentLanguage as keyof typeof localeHumanReadable + ] + : 'Loading...'} + + + {Object.keys(localeHumanReadable).map((locale) => ( + + { + localeHumanReadable[ + locale as keyof typeof localeHumanReadable + ] + } + + ))} + + + {currentLanguage !== 'en' && ( + + {t('account.preferences.language.tooltip')} + + )} + + + + {t('account.preferences.graphNavigation.heading')} + + + + + + {t('account.preferences.appearance.heading')} + + + + + ) +} diff --git a/apps/builder/src/features/account/hooks/useApiTokens.ts b/apps/builder/src/features/account/hooks/useApiTokens.ts new file mode 100644 index 0000000..d38aafd --- /dev/null +++ b/apps/builder/src/features/account/hooks/useApiTokens.ts @@ -0,0 +1,30 @@ +import { fetcher } from '@/helpers/fetcher' +import useSWR from 'swr' +import { env } from '@typebot.io/env' +import { ApiTokenFromServer } from '../types' + +type ServerResponse = { + apiTokens: ApiTokenFromServer[] +} + +export const useApiTokens = ({ + userId, + onError, +}: { + userId?: string + onError: (error: Error) => void +}) => { + const { data, error, mutate } = useSWR( + userId ? `/api/users/${userId}/api-tokens` : null, + fetcher, + { + dedupingInterval: env.NEXT_PUBLIC_E2E_TEST ? 0 : undefined, + } + ) + if (error) onError(error) + return { + apiTokens: data?.apiTokens, + isLoading: !error && !data, + mutate, + } +} diff --git a/apps/builder/src/features/account/hooks/useUser.ts b/apps/builder/src/features/account/hooks/useUser.ts new file mode 100644 index 0000000..c484569 --- /dev/null +++ b/apps/builder/src/features/account/hooks/useUser.ts @@ -0,0 +1,4 @@ +import { useContext } from 'react' +import { userContext } from '../UserProvider' + +export const useUser = () => useContext(userContext) diff --git a/apps/builder/src/features/account/queries/createApiTokenQuery.ts b/apps/builder/src/features/account/queries/createApiTokenQuery.ts new file mode 100644 index 0000000..fba8971 --- /dev/null +++ b/apps/builder/src/features/account/queries/createApiTokenQuery.ts @@ -0,0 +1,14 @@ +import { sendRequest } from '@typebot.io/lib' +import { ApiTokenFromServer } from '../types' + +export const createApiTokenQuery = ( + userId: string, + { name }: { name: string } +) => + sendRequest<{ apiToken: ApiTokenFromServer & { token: string } }>({ + url: `/api/users/${userId}/api-tokens`, + method: 'POST', + body: { + name, + }, + }) diff --git a/apps/builder/src/features/account/queries/deleteApiTokenQuery.ts b/apps/builder/src/features/account/queries/deleteApiTokenQuery.ts new file mode 100644 index 0000000..0de20af --- /dev/null +++ b/apps/builder/src/features/account/queries/deleteApiTokenQuery.ts @@ -0,0 +1,14 @@ +import { ApiToken } from '@typebot.io/prisma' +import { sendRequest } from '@typebot.io/lib' + +export const deleteApiTokenQuery = ({ + userId, + tokenId, +}: { + userId: string + tokenId: string +}) => + sendRequest<{ apiToken: ApiToken }>({ + url: `/api/users/${userId}/api-tokens/${tokenId}`, + method: 'DELETE', + }) diff --git a/apps/builder/src/features/account/queries/updateUserQuery.ts b/apps/builder/src/features/account/queries/updateUserQuery.ts new file mode 100644 index 0000000..2927551 --- /dev/null +++ b/apps/builder/src/features/account/queries/updateUserQuery.ts @@ -0,0 +1,9 @@ +import { User } from '@typebot.io/prisma' +import { sendRequest } from '@typebot.io/lib' + +export const updateUserQuery = async (id: string, user: User) => + sendRequest({ + url: `/api/users/${id}`, + method: 'PUT', + body: user, + }) diff --git a/apps/builder/src/features/account/types.ts b/apps/builder/src/features/account/types.ts new file mode 100644 index 0000000..4daf9a6 --- /dev/null +++ b/apps/builder/src/features/account/types.ts @@ -0,0 +1 @@ +export type ApiTokenFromServer = { id: string; name: string; createdAt: string } diff --git a/apps/builder/src/features/analytics/analytics.spec.ts b/apps/builder/src/features/analytics/analytics.spec.ts new file mode 100644 index 0000000..cf89104 --- /dev/null +++ b/apps/builder/src/features/analytics/analytics.spec.ts @@ -0,0 +1,32 @@ +import { getTestAsset } from '@/test/utils/playwright' +import test, { expect } from '@playwright/test' +import { createId } from '@paralleldrive/cuid2' +import { + importTypebotInDatabase, + injectFakeResults, +} from '@typebot.io/lib/playwright/databaseActions' +import { starterWorkspaceId } from '@typebot.io/lib/playwright/databaseSetup' + +test('analytics are not available for non-pro workspaces', async ({ page }) => { + const typebotId = createId() + await importTypebotInDatabase( + getTestAsset('typebots/results/submissionHeader.json'), + { + id: typebotId, + workspaceId: starterWorkspaceId, + } + ) + await injectFakeResults({ typebotId, count: 10 }) + await page.goto(`/typebots/${typebotId}/results/analytics`) + const firstDropoffBox = page.locator('text="%" >> nth=0') + await firstDropoffBox.hover() + await expect( + page.locator('text="Upgrade your plan to PRO to reveal drop-off rate."') + ).toBeVisible() + await firstDropoffBox.click() + await expect( + page.locator( + 'text="You need to upgrade your plan in order to unlock in-depth analytics"' + ) + ).toBeVisible() +}) diff --git a/apps/builder/src/features/analytics/api/getTotalAnswers.ts b/apps/builder/src/features/analytics/api/getTotalAnswers.ts new file mode 100644 index 0000000..878071e --- /dev/null +++ b/apps/builder/src/features/analytics/api/getTotalAnswers.ts @@ -0,0 +1,60 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { z } from 'zod' +import { canReadTypebots } from '@/helpers/databaseRules' +import { totalAnswersSchema } from '@typebot.io/schemas/features/analytics' +import { parseGroups } from '@typebot.io/schemas' +import { isInputBlock } from '@typebot.io/lib' + +export const getTotalAnswers = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/typebots/{typebotId}/analytics/totalAnswersInBlocks', + protect: true, + summary: 'List total answers in blocks', + tags: ['Analytics'], + }, + }) + .input( + z.object({ + typebotId: z.string(), + }) + ) + .output(z.object({ totalAnswers: z.array(totalAnswersSchema) })) + .query(async ({ input: { typebotId }, ctx: { user } }) => { + const typebot = await prisma.typebot.findFirst({ + where: canReadTypebots(typebotId, user), + select: { publishedTypebot: true }, + }) + if (!typebot?.publishedTypebot) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Published typebot not found', + }) + + const totalAnswersPerBlock = await prisma.answer.groupBy({ + by: ['blockId'], + where: { + result: { + typebotId: typebot.publishedTypebot.typebotId, + }, + blockId: { + in: parseGroups(typebot.publishedTypebot.groups, { + typebotVersion: typebot.publishedTypebot.version, + }).flatMap((group) => + group.blocks.filter(isInputBlock).map((block) => block.id) + ), + }, + }, + _count: { _all: true }, + }) + + return { + totalAnswers: totalAnswersPerBlock.map((a) => ({ + blockId: a.blockId, + total: a._count._all, + })), + } + }) diff --git a/apps/builder/src/features/analytics/api/getTotalVisitedEdges.ts b/apps/builder/src/features/analytics/api/getTotalVisitedEdges.ts new file mode 100644 index 0000000..e421376 --- /dev/null +++ b/apps/builder/src/features/analytics/api/getTotalVisitedEdges.ts @@ -0,0 +1,55 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { z } from 'zod' +import { canReadTypebots } from '@/helpers/databaseRules' +import { totalVisitedEdgesSchema } from '@typebot.io/schemas' + +export const getTotalVisitedEdges = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/typebots/{typebotId}/analytics/totalVisitedEdges', + protect: true, + summary: 'List total edges used in results', + tags: ['Analytics'], + }, + }) + .input( + z.object({ + typebotId: z.string(), + }) + ) + .output( + z.object({ + totalVisitedEdges: z.array(totalVisitedEdgesSchema), + }) + ) + .query(async ({ input: { typebotId }, ctx: { user } }) => { + const typebot = await prisma.typebot.findFirst({ + where: canReadTypebots(typebotId, user), + select: { id: true }, + }) + if (!typebot?.id) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Published typebot not found', + }) + + const edges = await prisma.visitedEdge.groupBy({ + by: ['edgeId'], + where: { + result: { + typebotId: typebot.id, + }, + }, + _count: { resultId: true }, + }) + + return { + totalVisitedEdges: edges.map((e) => ({ + edgeId: e.edgeId, + total: e._count.resultId, + })), + } + }) diff --git a/apps/builder/src/features/analytics/api/router.ts b/apps/builder/src/features/analytics/api/router.ts new file mode 100644 index 0000000..d51c3d0 --- /dev/null +++ b/apps/builder/src/features/analytics/api/router.ts @@ -0,0 +1,8 @@ +import { router } from '@/helpers/server/trpc' +import { getTotalAnswers } from './getTotalAnswers' +import { getTotalVisitedEdges } from './getTotalVisitedEdges' + +export const analyticsRouter = router({ + getTotalAnswers, + getTotalVisitedEdges, +}) diff --git a/apps/builder/src/features/analytics/components/AnalyticsGraphContainer.tsx b/apps/builder/src/features/analytics/components/AnalyticsGraphContainer.tsx new file mode 100644 index 0000000..eeec583 --- /dev/null +++ b/apps/builder/src/features/analytics/components/AnalyticsGraphContainer.tsx @@ -0,0 +1,85 @@ +import { + Flex, + Spinner, + useColorModeValue, + useDisclosure, +} from '@chakra-ui/react' +import { useTypebot } from '@/features/editor/providers/TypebotProvider' +import { Stats } from '@typebot.io/schemas' +import React from 'react' +import { StatsCards } from './StatsCards' +import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal' +import { Graph } from '@/features/graph/components/Graph' +import { GraphProvider } from '@/features/graph/providers/GraphProvider' +import { GroupsCoordinatesProvider } from '@/features/graph/providers/GroupsCoordinateProvider' +import { useTranslate } from '@tolgee/react' +import { trpc } from '@/lib/trpc' +import { isDefined } from '@typebot.io/lib' +import { EventsCoordinatesProvider } from '@/features/graph/providers/EventsCoordinateProvider' + +export const AnalyticsGraphContainer = ({ stats }: { stats?: Stats }) => { + const { t } = useTranslate() + const { isOpen, onOpen, onClose } = useDisclosure() + const { typebot, publishedTypebot } = useTypebot() + const { data } = trpc.analytics.getTotalAnswers.useQuery( + { + typebotId: typebot?.id as string, + }, + { enabled: isDefined(publishedTypebot) } + ) + + const { data: edgesData } = trpc.analytics.getTotalVisitedEdges.useQuery( + { + typebotId: typebot?.id as string, + }, + { enabled: isDefined(publishedTypebot) } + ) + + return ( + + {publishedTypebot && stats ? ( + + + + + + + + ) : ( + + + + )} + + + + ) +} diff --git a/apps/builder/src/features/analytics/components/StatsCards.tsx b/apps/builder/src/features/analytics/components/StatsCards.tsx new file mode 100644 index 0000000..f63e64e --- /dev/null +++ b/apps/builder/src/features/analytics/components/StatsCards.tsx @@ -0,0 +1,61 @@ +import { useTranslate } from '@tolgee/react' +import { + GridProps, + SimpleGrid, + Skeleton, + Stat, + StatLabel, + StatNumber, + useColorModeValue, +} from '@chakra-ui/react' +import { Stats } from '@typebot.io/schemas' +import React from 'react' + +const computeCompletionRate = + (notAvailableLabel: string) => + (totalCompleted: number, totalStarts: number): string => { + if (totalStarts === 0) return notAvailableLabel + return `${Math.round((totalCompleted / totalStarts) * 100)}%` + } + +export const StatsCards = ({ + stats, + ...props +}: { stats?: Stats } & GridProps) => { + const { t } = useTranslate() + const bg = useColorModeValue('white', 'gray.900') + + return ( + + + {t('analytics.viewsLabel')} + {stats ? ( + {stats.totalViews} + ) : ( + + )} + + + {t('analytics.startsLabel')} + {stats ? ( + {stats.totalStarts} + ) : ( + + )} + + + {t('analytics.completionRateLabel')} + {stats ? ( + + {computeCompletionRate(t('analytics.notAvailableLabel'))( + stats.totalCompleted, + stats.totalStarts + )} + + ) : ( + + )} + + + ) +} diff --git a/apps/builder/src/features/analytics/helpers/computeTotalUsersAtBlock.ts b/apps/builder/src/features/analytics/helpers/computeTotalUsersAtBlock.ts new file mode 100644 index 0000000..e2c944c --- /dev/null +++ b/apps/builder/src/features/analytics/helpers/computeTotalUsersAtBlock.ts @@ -0,0 +1,60 @@ +import { isInputBlock, isNotDefined } from '@typebot.io/lib' +import { PublicTypebotV6 } from '@typebot.io/schemas' +import { + TotalAnswers, + TotalVisitedEdges, +} from '@typebot.io/schemas/features/analytics' + +export const computeTotalUsersAtBlock = ( + currentBlockId: string, + { + publishedTypebot, + totalVisitedEdges, + totalAnswers, + }: { + publishedTypebot: PublicTypebotV6 + totalVisitedEdges: TotalVisitedEdges[] + totalAnswers: TotalAnswers[] + } +): number => { + let totalUsers = 0 + const currentGroup = publishedTypebot.groups.find((group) => + group.blocks.find((block) => block.id === currentBlockId) + ) + if (!currentGroup) return 0 + const currentBlockIndex = currentGroup.blocks.findIndex( + (block) => block.id === currentBlockId + ) + const previousBlocks = currentGroup.blocks.slice(0, currentBlockIndex + 1) + for (const block of previousBlocks.reverse()) { + if (currentBlockId !== block.id && isInputBlock(block)) + return totalAnswers.find((t) => t.blockId === block.id)?.total ?? 0 + const incomingEdges = publishedTypebot.edges.filter( + (edge) => edge.to.blockId === block.id + ) + if (!incomingEdges.length) continue + totalUsers += incomingEdges.reduce( + (acc, incomingEdge) => + acc + + (totalVisitedEdges.find( + (totalEdge) => totalEdge.edgeId === incomingEdge.id + )?.total ?? 0), + 0 + ) + } + const edgesConnectedToGroup = publishedTypebot.edges.filter( + (edge) => + edge.to.groupId === currentGroup.id && isNotDefined(edge.to.blockId) + ) + + totalUsers += edgesConnectedToGroup.reduce( + (acc, connectedEdge) => + acc + + (totalVisitedEdges.find( + (totalEdge) => totalEdge.edgeId === connectedEdge.id + )?.total ?? 0), + 0 + ) + + return totalUsers +} diff --git a/apps/builder/src/features/analytics/helpers/getTotalAnswersAtBlock.ts b/apps/builder/src/features/analytics/helpers/getTotalAnswersAtBlock.ts new file mode 100644 index 0000000..c17769e --- /dev/null +++ b/apps/builder/src/features/analytics/helpers/getTotalAnswersAtBlock.ts @@ -0,0 +1,20 @@ +import { byId } from '@typebot.io/lib' +import { PublicTypebotV6 } from '@typebot.io/schemas' +import { TotalAnswers } from '@typebot.io/schemas/features/analytics' + +export const getTotalAnswersAtBlock = ( + currentBlockId: string, + { + publishedTypebot, + totalAnswers, + }: { + publishedTypebot: PublicTypebotV6 + totalAnswers: TotalAnswers[] + } +): number => { + const block = publishedTypebot.groups + .flatMap((g) => g.blocks) + .find(byId(currentBlockId)) + if (!block) throw new Error(`Block ${currentBlockId} not found`) + return totalAnswers.find((t) => t.blockId === block.id)?.total ?? 0 +} diff --git a/apps/builder/src/features/auth/api/customAdapter.ts b/apps/builder/src/features/auth/api/customAdapter.ts new file mode 100644 index 0000000..828ea8f --- /dev/null +++ b/apps/builder/src/features/auth/api/customAdapter.ts @@ -0,0 +1,153 @@ +// Forked from https://github.com/nextauthjs/adapters/blob/main/packages/prisma/src/index.ts +import { + PrismaClient, + Prisma, + WorkspaceRole, + Session, +} from '@typebot.io/prisma' +import type { Adapter, AdapterUser } from 'next-auth/adapters' +import { createId } from '@paralleldrive/cuid2' +import { generateId } from '@typebot.io/lib' +import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent' +import { TelemetryEvent } from '@typebot.io/schemas/features/telemetry' +import { convertInvitationsToCollaborations } from '@/features/auth/helpers/convertInvitationsToCollaborations' +import { getNewUserInvitations } from '@/features/auth/helpers/getNewUserInvitations' +import { joinWorkspaces } from '@/features/auth/helpers/joinWorkspaces' +import { parseWorkspaceDefaultPlan } from '@/features/workspace/helpers/parseWorkspaceDefaultPlan' +import { env } from '@typebot.io/env' + +export function customAdapter(p: PrismaClient): Adapter { + return { + createUser: async (data: Omit) => { + if (!data.email) + throw Error('Provider did not forward email but it is required') + const user = { id: createId(), email: data.email as string } + const { invitations, workspaceInvitations } = await getNewUserInvitations( + p, + user.email + ) + if ( + env.DISABLE_SIGNUP && + env.ADMIN_EMAIL !== user.email && + invitations.length === 0 && + workspaceInvitations.length === 0 + ) + throw Error('New users are forbidden') + + const newWorkspaceData = { + name: data.name ? `${data.name}'s workspace` : `My workspace`, + plan: parseWorkspaceDefaultPlan(data.email), + } + const createdUser = await p.user.create({ + data: { + ...data, + id: user.id, + apiTokens: { + create: { name: 'Default', token: generateId(24) }, + }, + workspaces: + workspaceInvitations.length > 0 + ? undefined + : { + create: { + role: WorkspaceRole.ADMIN, + workspace: { + create: newWorkspaceData, + }, + }, + }, + onboardingCategories: [], + }, + include: { + workspaces: { select: { workspaceId: true } }, + }, + }) + const newWorkspaceId = createdUser.workspaces.pop()?.workspaceId + const events: TelemetryEvent[] = [] + if (newWorkspaceId) { + events.push({ + name: 'Workspace created', + workspaceId: newWorkspaceId, + userId: createdUser.id, + data: newWorkspaceData, + }) + } + events.push({ + name: 'User created', + userId: createdUser.id, + data: { + email: data.email, + name: data.name ? (data.name as string).split(' ')[0] : undefined, + }, + }) + await sendTelemetryEvents(events) + if (invitations.length > 0) + await convertInvitationsToCollaborations(p, user, invitations) + if (workspaceInvitations.length > 0) + await joinWorkspaces(p, user, workspaceInvitations) + return createdUser as AdapterUser + }, + getUser: async (id) => + (await p.user.findUnique({ where: { id } })) as AdapterUser, + getUserByEmail: async (email) => + (await p.user.findUnique({ where: { email } })) as AdapterUser, + async getUserByAccount(provider_providerAccountId) { + const account = await p.account.findUnique({ + where: { provider_providerAccountId }, + select: { user: true }, + }) + return (account?.user ?? null) as AdapterUser | null + }, + updateUser: async (data) => + (await p.user.update({ where: { id: data.id }, data })) as AdapterUser, + deleteUser: async (id) => + (await p.user.delete({ where: { id } })) as AdapterUser, + linkAccount: async (data) => { + await p.account.create({ + data: { + userId: data.userId, + type: data.type, + provider: data.provider, + providerAccountId: data.providerAccountId, + refresh_token: data.refresh_token, + access_token: data.access_token, + expires_at: data.expires_at, + token_type: data.token_type, + scope: data.scope, + id_token: data.id_token, + session_state: data.session_state, + oauth_token_secret: data.oauth_token_secret as string, + oauth_token: data.oauth_token as string, + refresh_token_expires_in: data.refresh_token_expires_in as number, + }, + }) + }, + unlinkAccount: async (provider_providerAccountId) => { + await p.account.delete({ where: { provider_providerAccountId } }) + }, + async getSessionAndUser(sessionToken) { + const userAndSession = await p.session.findUnique({ + where: { sessionToken }, + include: { user: true }, + }) + if (!userAndSession) return null + const { user, ...session } = userAndSession + return { user, session } as { user: AdapterUser; session: Session } + }, + createSession: (data) => p.session.create({ data }), + updateSession: (data) => + p.session.update({ data, where: { sessionToken: data.sessionToken } }), + deleteSession: (sessionToken) => + p.session.delete({ where: { sessionToken } }), + createVerificationToken: (data) => p.verificationToken.create({ data }), + async useVerificationToken(identifier_token) { + try { + return await p.verificationToken.delete({ where: { identifier_token } }) + } catch (error) { + if ((error as Prisma.PrismaClientKnownRequestError).code === 'P2025') + return null + throw error + } + }, + } +} diff --git a/apps/builder/src/features/auth/components/DividerWithText.tsx b/apps/builder/src/features/auth/components/DividerWithText.tsx new file mode 100644 index 0000000..c6e9c17 --- /dev/null +++ b/apps/builder/src/features/auth/components/DividerWithText.tsx @@ -0,0 +1,31 @@ +import { + FlexProps, + Flex, + Box, + Divider, + Text, + useColorModeValue, +} from '@chakra-ui/react' +import React from 'react' + +export const DividerWithText = (props: FlexProps) => { + const { children, ...flexProps } = props + return ( + + + + + + {children} + + + + + + ) +} diff --git a/apps/builder/src/features/auth/components/OnboardingPage.tsx b/apps/builder/src/features/auth/components/OnboardingPage.tsx new file mode 100644 index 0000000..75424db --- /dev/null +++ b/apps/builder/src/features/auth/components/OnboardingPage.tsx @@ -0,0 +1,186 @@ +import { ChevronLastIcon } from '@/components/icons' +import { + Button, + Flex, + HStack, + StackProps, + VStack, + chakra, + useColorModeValue, +} from '@chakra-ui/react' +import { Standard } from '@typebot.io/nextjs' +import { useRouter } from 'next/router' +import { useEffect, useRef, useState } from 'react' +import confetti from 'canvas-confetti' +import { useUser } from '@/features/account/hooks/useUser' +import { useTranslate } from '@tolgee/react' +import { env } from '@typebot.io/env' + +const totalSteps = 5 + +export const OnboardingPage = () => { + const { t } = useTranslate() + const { replace, query } = useRouter() + const confettiCanvaContainer = useRef(null) + const confettiCanon = useRef() + const { user, updateUser } = useUser() + const [currentStep, setCurrentStep] = useState(user?.name ? 2 : 1) + + const isNewUser = + user && + new Date(user.createdAt as unknown as string).toDateString() === + new Date().toDateString() + + useEffect(() => { + initConfettis() + }) + + useEffect(() => { + if (!user?.createdAt) return + if (isNewUser === false || !env.NEXT_PUBLIC_ONBOARDING_TYPEBOT_ID) + replace({ pathname: '/typebots', query }) + }, [isNewUser, query, replace, user?.createdAt]) + + const initConfettis = () => { + if (!confettiCanvaContainer.current || confettiCanon.current) return + confettiCanon.current = confetti.create(confettiCanvaContainer.current, { + resize: true, + useWorker: true, + }) + } + + const updateUserInfo = async (answer: { + message: string + blockId: string + }) => { + const isOtherItem = [ + 'cl126pv7n001o2e6dajltc4qz', + 'saw904bfzgspmt0l24achtiy', + ].includes(answer.blockId) + if (isOtherItem) return + const isName = answer.blockId === 'cl126820m000g2e6dfleq78bt' + const isCompany = answer.blockId === 'cl126jioz000v2e6dwrk1f2cb' + const isCategories = answer.blockId === 'cl126lb8v00142e6duv5qe08l' + if (isName) updateUser({ name: answer.message }) + if (isCategories) { + const onboardingCategories = answer.message.split(', ') + updateUser({ onboardingCategories }) + } + if (isCompany) { + updateUser({ company: answer.message }) + if (confettiCanon.current) shootConfettis(confettiCanon.current) + } + setCurrentStep((prev) => prev + 1) + } + + if (!isNewUser) return null + return ( + + + + + { + setTimeout(() => { + replace({ + pathname: '/typebots', + query: { ...query, isFirstBot: true }, + }) + }, 2000) + }} + onAnswer={updateUserInfo} + /> + + + + ) +} + +const Dots = ({ + currentStep, + ...props +}: { currentStep: number } & StackProps) => { + const highlightedBgColor = useColorModeValue('gray.500', 'gray.100') + const baseBgColor = useColorModeValue('gray.200', 'gray.700') + return ( + + {Array.from({ length: totalSteps }).map((_, index) => ( + + ))} + + ) +} + +const shootConfettis = (confettiCanon: confetti.CreateTypes) => { + const count = 200 + const defaults = { + origin: { y: 0.7 }, + } + + const fire = ( + particleRatio: number, + opts: { + spread: number + startVelocity?: number + decay?: number + scalar?: number + } + ) => { + confettiCanon( + Object.assign({}, defaults, opts, { + particleCount: Math.floor(count * particleRatio), + }) + ) + } + + fire(0.25, { + spread: 26, + startVelocity: 55, + }) + fire(0.2, { + spread: 60, + }) + fire(0.35, { + spread: 100, + decay: 0.91, + scalar: 0.8, + }) + fire(0.1, { + spread: 120, + startVelocity: 25, + decay: 0.92, + scalar: 1.2, + }) + fire(0.1, { + spread: 120, + startVelocity: 45, + }) +} diff --git a/apps/builder/src/features/auth/components/SignInError.tsx b/apps/builder/src/features/auth/components/SignInError.tsx new file mode 100644 index 0000000..e2496f5 --- /dev/null +++ b/apps/builder/src/features/auth/components/SignInError.tsx @@ -0,0 +1,25 @@ +import { useTranslate } from '@tolgee/react' +import { Alert } from '@chakra-ui/react' + +type Props = { + error: string +} + +export const SignInError = ({ error }: Props) => { + const { t } = useTranslate() + const errors: Record = { + Signin: t('auth.error.default'), + OAuthSignin: t('auth.error.default'), + OAuthCallback: t('auth.error.default'), + OAuthCreateAccount: t('auth.error.email'), + EmailCreateAccount: t('auth.error.default'), + Callback: t('auth.error.default'), + OAuthAccountNotLinked: t('auth.error.oauthNotLinked'), + default: t('auth.error.unknown'), + } + return ( + + {errors[error] ?? errors[error]} + + ) +} diff --git a/apps/builder/src/features/auth/components/SignInForm.tsx b/apps/builder/src/features/auth/components/SignInForm.tsx new file mode 100644 index 0000000..475bbe2 --- /dev/null +++ b/apps/builder/src/features/auth/components/SignInForm.tsx @@ -0,0 +1,172 @@ +import { + Button, + HTMLChakraProps, + Input, + Stack, + HStack, + Text, + Spinner, + Alert, + Flex, + AlertIcon, + SlideFade, +} from '@chakra-ui/react' +import React, { ChangeEvent, FormEvent, useEffect } from 'react' +import { useState } from 'react' +import { + ClientSafeProvider, + getProviders, + LiteralUnion, + signIn, + useSession, +} from 'next-auth/react' +import { DividerWithText } from './DividerWithText' +import { SocialLoginButtons } from './SocialLoginButtons' +import { useRouter } from 'next/router' +import { BuiltInProviderType } from 'next-auth/providers' +import { useToast } from '@/hooks/useToast' +import { TextLink } from '@/components/TextLink' +import { SignInError } from './SignInError' +import { useTranslate } from '@tolgee/react' + +type Props = { + defaultEmail?: string +} +export const SignInForm = ({ + defaultEmail, +}: Props & HTMLChakraProps<'form'>) => { + const { t } = useTranslate() + const router = useRouter() + const { status } = useSession() + const [authLoading, setAuthLoading] = useState(false) + const [isLoadingProviders, setIsLoadingProviders] = useState(true) + + const [emailValue, setEmailValue] = useState(defaultEmail ?? '') + const [isMagicLinkSent, setIsMagicLinkSent] = useState(false) + + const { showToast } = useToast() + const [providers, setProviders] = + useState< + Record, ClientSafeProvider> + >() + + const hasNoAuthProvider = + !isLoadingProviders && Object.keys(providers ?? {}).length === 0 + + useEffect(() => { + if (status === 'authenticated') { + router.replace(router.query.redirectPath?.toString() ?? '/typebots') + return + } + ;(async () => { + const providers = await getProviders() + setProviders(providers ?? undefined) + setIsLoadingProviders(false) + })() + }, [status, router]) + + const handleEmailChange = (e: ChangeEvent) => + setEmailValue(e.target.value) + + const handleEmailSubmit = async (e: FormEvent) => { + e.preventDefault() + if (isMagicLinkSent) return + setAuthLoading(true) + try { + const response = await signIn('email', { + email: emailValue, + redirect: false, + }) + if (response?.error) { + if (response.error.includes('ip-banned')) + showToast({ + status: 'info', + description: + 'Your account has suspicious activity and is being reviewed by our team. Feel free to contact us.', + }) + else if (response.error.includes('rate-limited')) + showToast({ + status: 'info', + description: t('auth.signinErrorToast.tooManyRequests'), + }) + else + showToast({ + title: t('auth.signinErrorToast.title'), + description: t('auth.signinErrorToast.description'), + }) + } else { + setIsMagicLinkSent(true) + } + } catch (e) { + showToast({ + status: 'info', + description: 'An error occured while signing in', + }) + } + setAuthLoading(false) + } + + if (isLoadingProviders) return + if (hasNoAuthProvider) + return ( + + {t('auth.noProvider.preLink')}{' '} + + {t('auth.noProvider.link')} + + + ) + return ( + + {!isMagicLinkSent && ( + <> + + {providers?.email && ( + <> + {t('auth.orEmailLabel')} + + + + + + )} + + )} + {router.query.error && ( + + )} + + + + + + + {t('auth.magicLink.title')} + {t('auth.magicLink.description')} + + + + + + + ) +} diff --git a/apps/builder/src/features/auth/components/SignInPage.tsx b/apps/builder/src/features/auth/components/SignInPage.tsx new file mode 100644 index 0000000..c05f9eb --- /dev/null +++ b/apps/builder/src/features/auth/components/SignInPage.tsx @@ -0,0 +1,66 @@ +import { Seo } from '@/components/Seo' +import { TextLink } from '@/components/TextLink' +import { T, useTranslate } from '@tolgee/react' +import { VStack, Heading, Text } from '@chakra-ui/react' +import { useRouter } from 'next/router' +import { SignInForm } from './SignInForm' + +type Props = { + type: 'signin' | 'signup' + defaultEmail?: string +} + +export const SignInPage = ({ type }: Props) => { + const { t } = useTranslate() + const { query } = useRouter() + + return ( + + + { + throw new Error('Sentry is working') + }} + > + {type === 'signin' + ? t('auth.signin.heading') + : t('auth.register.heading')} + + {type === 'signin' ? ( + + {t('auth.signin.noAccountLabel.preLink')}{' '} + + {t('auth.signin.noAccountLabel.link')} + + + ) : ( + + {t('auth.register.alreadyHaveAccountLabel.preLink')}{' '} + + {t('auth.register.alreadyHaveAccountLabel.link')} + + + )} + + {type === 'signup' ? ( + + , + privacy: ( + + ), + }} + /> + + ) : null} + + ) +} diff --git a/apps/builder/src/features/auth/components/SocialLoginButtons.tsx b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx new file mode 100644 index 0000000..662398c --- /dev/null +++ b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx @@ -0,0 +1,147 @@ +import { Stack, Button } from '@chakra-ui/react' +import { GithubIcon } from '@/components/icons' +import { + ClientSafeProvider, + LiteralUnion, + signIn, + useSession, +} from 'next-auth/react' +import { useRouter } from 'next/router' +import React, { useState } from 'react' +import { stringify } from 'qs' +import { BuiltInProviderType } from 'next-auth/providers' +import { GoogleLogo } from '@/components/GoogleLogo' +import { omit } from '@typebot.io/lib' +import { AzureAdLogo } from '@/components/logos/AzureAdLogo' +import { FacebookLogo } from '@/components/logos/FacebookLogo' +import { GitlabLogo } from '@/components/logos/GitlabLogo' +import { useTranslate } from '@tolgee/react' + +type Props = { + providers: + | Record, ClientSafeProvider> + | undefined +} + +export const SocialLoginButtons = ({ providers }: Props) => { + const { t } = useTranslate() + const { query } = useRouter() + const { status } = useSession() + const [authLoading, setAuthLoading] = + useState>() + + const handleSignIn = async (provider: string) => { + setAuthLoading(provider) + await signIn(provider, { + callbackUrl: + query.callbackUrl?.toString() ?? + `/typebots?${stringify(omit(query, 'error', 'callbackUrl'))}`, + }) + setTimeout(() => setAuthLoading(undefined), 3000) + } + + const handleGitHubClick = () => handleSignIn('github') + + const handleGoogleClick = () => handleSignIn('google') + + const handleFacebookClick = () => handleSignIn('facebook') + + const handleGitlabClick = () => handleSignIn('gitlab') + + const handleAzureAdClick = () => handleSignIn('azure-ad') + + const handleCustomOAuthClick = () => handleSignIn('custom-oauth') + + return ( + + {providers?.github && ( + + )} + {providers?.google && ( + + )} + {providers?.facebook && ( + + )} + {providers?.gitlab && ( + + )} + {providers?.['azure-ad'] && ( + + )} + {providers?.['custom-oauth'] && ( + + )} + + ) +} diff --git a/apps/builder/src/features/auth/helpers/convertInvitationsToCollaborations.ts b/apps/builder/src/features/auth/helpers/convertInvitationsToCollaborations.ts new file mode 100644 index 0000000..f90c08a --- /dev/null +++ b/apps/builder/src/features/auth/helpers/convertInvitationsToCollaborations.ts @@ -0,0 +1,48 @@ +import { Invitation, PrismaClient, WorkspaceRole } from '@typebot.io/prisma' + +export type InvitationWithWorkspaceId = Invitation & { + typebot: { + workspaceId: string | null + } +} + +export const convertInvitationsToCollaborations = async ( + p: PrismaClient, + { id, email }: { id: string; email: string }, + invitations: InvitationWithWorkspaceId[] +) => { + await p.collaboratorsOnTypebots.createMany({ + data: invitations.map((invitation) => ({ + typebotId: invitation.typebotId, + type: invitation.type, + userId: id, + })), + }) + const workspaceInvitations = invitations.reduce( + (acc, invitation) => + acc.some( + (inv) => inv.typebot.workspaceId === invitation.typebot.workspaceId + ) + ? acc + : [...acc, invitation], + [] + ) + for (const invitation of workspaceInvitations) { + if (!invitation.typebot.workspaceId) continue + await p.memberInWorkspace.createMany({ + data: [ + { + userId: id, + workspaceId: invitation.typebot.workspaceId, + role: WorkspaceRole.GUEST, + }, + ], + skipDuplicates: true, + }) + } + return p.invitation.deleteMany({ + where: { + email, + }, + }) +} diff --git a/apps/builder/src/features/auth/helpers/getAuthenticatedUser.ts b/apps/builder/src/features/auth/helpers/getAuthenticatedUser.ts new file mode 100644 index 0000000..38b456a --- /dev/null +++ b/apps/builder/src/features/auth/helpers/getAuthenticatedUser.ts @@ -0,0 +1,38 @@ +import prisma from '@typebot.io/lib/prisma' +import { getAuthOptions } from '@/pages/api/auth/[...nextauth]' +import * as Sentry from '@sentry/nextjs' +import { User } from '@typebot.io/prisma' +import { NextApiRequest, NextApiResponse } from 'next' +import { getServerSession } from 'next-auth' +import { env } from '@typebot.io/env' +import { mockedUser } from '@typebot.io/lib/mockedUser' + +export const getAuthenticatedUser = async ( + req: NextApiRequest, + res: NextApiResponse +): Promise => { + const bearerToken = extractBearerToken(req) + if (bearerToken) return authenticateByToken(bearerToken) + const user = env.NEXT_PUBLIC_E2E_TEST + ? mockedUser + : ((await getServerSession(req, res, getAuthOptions({})))?.user as + | User + | undefined) + if (!user || !('id' in user)) return + Sentry.setUser({ id: user.id }) + return user +} + +const authenticateByToken = async ( + apiToken: string +): Promise => { + if (typeof window !== 'undefined') return + const user = (await prisma.user.findFirst({ + where: { apiTokens: { some: { token: apiToken } } }, + })) as User + Sentry.setUser({ id: user.id }) + return user +} + +const extractBearerToken = (req: NextApiRequest) => + req.headers['authorization']?.slice(7) diff --git a/apps/builder/src/features/auth/helpers/getNewUserInvitations.ts b/apps/builder/src/features/auth/helpers/getNewUserInvitations.ts new file mode 100644 index 0000000..014d1c4 --- /dev/null +++ b/apps/builder/src/features/auth/helpers/getNewUserInvitations.ts @@ -0,0 +1,22 @@ +import { PrismaClient, WorkspaceInvitation } from '@typebot.io/prisma' +import { InvitationWithWorkspaceId } from './convertInvitationsToCollaborations' + +export const getNewUserInvitations = async ( + p: PrismaClient, + email: string +): Promise<{ + invitations: InvitationWithWorkspaceId[] + workspaceInvitations: WorkspaceInvitation[] +}> => { + const [invitations, workspaceInvitations] = await p.$transaction([ + p.invitation.findMany({ + where: { email }, + include: { typebot: { select: { workspaceId: true } } }, + }), + p.workspaceInvitation.findMany({ + where: { email }, + }), + ]) + + return { invitations, workspaceInvitations } +} diff --git a/apps/builder/src/features/auth/helpers/joinWorkspaces.ts b/apps/builder/src/features/auth/helpers/joinWorkspaces.ts new file mode 100644 index 0000000..0332260 --- /dev/null +++ b/apps/builder/src/features/auth/helpers/joinWorkspaces.ts @@ -0,0 +1,23 @@ +import { PrismaClient, WorkspaceInvitation } from '@typebot.io/prisma' + +export const joinWorkspaces = async ( + p: PrismaClient, + { id, email }: { id: string; email: string }, + invitations: WorkspaceInvitation[] +) => { + await p.$transaction([ + p.memberInWorkspace.createMany({ + data: invitations.map((invitation) => ({ + workspaceId: invitation.workspaceId, + role: invitation.type, + userId: id, + })), + skipDuplicates: true, + }), + p.workspaceInvitation.deleteMany({ + where: { + email, + }, + }), + ]) +} diff --git a/apps/builder/src/features/auth/helpers/sendVerificationRequest.ts b/apps/builder/src/features/auth/helpers/sendVerificationRequest.ts new file mode 100644 index 0000000..ef36944 --- /dev/null +++ b/apps/builder/src/features/auth/helpers/sendVerificationRequest.ts @@ -0,0 +1,14 @@ +import { sendMagicLinkEmail } from '@typebot.io/emails' + +type Props = { + identifier: string + url: string +} + +export const sendVerificationRequest = async ({ identifier, url }: Props) => { + try { + await sendMagicLinkEmail({ url, to: identifier }) + } catch (err) { + throw new Error(`Email(s) could not be sent`) + } +} diff --git a/apps/builder/src/features/billing/api/createCheckoutSession.ts b/apps/builder/src/features/billing/api/createCheckoutSession.ts new file mode 100644 index 0000000..9d44f8e --- /dev/null +++ b/apps/builder/src/features/billing/api/createCheckoutSession.ts @@ -0,0 +1,167 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { Plan } from '@typebot.io/prisma' +import Stripe from 'stripe' +import { z } from 'zod' +import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden' +import { env } from '@typebot.io/env' + +export const createCheckoutSession = authenticatedProcedure + .meta({ + openapi: { + method: 'POST', + path: '/v1/billing/subscription/checkout', + protect: true, + summary: 'Create checkout session to create a new subscription', + tags: ['Billing'], + }, + }) + .input( + z.object({ + email: z.string(), + company: z.string(), + workspaceId: z.string(), + currency: z.enum(['usd', 'eur']), + plan: z.enum([Plan.STARTER, Plan.PRO]), + returnUrl: z.string(), + vat: z + .object({ + type: z.string(), + value: z.string(), + }) + .optional(), + }) + ) + .output( + z.object({ + checkoutUrl: z.string(), + }) + ) + .mutation( + async ({ + input: { vat, email, company, workspaceId, currency, plan, returnUrl }, + ctx: { user }, + }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe environment variables are missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + members: { + select: { + userId: true, + role: true, + }, + }, + }, + }) + + if (!workspace || isAdminWriteWorkspaceForbidden(workspace, user)) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + if (workspace.stripeId) + throw new TRPCError({ + code: 'BAD_REQUEST', + message: 'Customer already exists, use updateSubscription endpoint.', + }) + + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + + await prisma.user.updateMany({ + where: { + id: user.id, + }, + data: { + company, + }, + }) + + const customer = await stripe.customers.create({ + email, + name: company, + metadata: { workspaceId }, + tax_id_data: vat + ? [vat as Stripe.CustomerCreateParams.TaxIdDatum] + : undefined, + }) + + const checkoutUrl = await createCheckoutSessionUrl(stripe)({ + customerId: customer.id, + userId: user.id, + workspaceId, + currency, + plan, + returnUrl, + }) + + if (!checkoutUrl) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe checkout session creation failed', + }) + + return { + checkoutUrl, + } + } + ) + +type Props = { + customerId: string + workspaceId: string + currency: 'usd' | 'eur' + plan: 'STARTER' | 'PRO' + returnUrl: string + userId: string +} + +export const createCheckoutSessionUrl = + (stripe: Stripe) => + async ({ customerId, workspaceId, currency, plan, returnUrl }: Props) => { + const session = await stripe.checkout.sessions.create({ + success_url: `${returnUrl}?stripe=${plan}&success=true`, + cancel_url: `${returnUrl}?stripe=cancel`, + allow_promotion_codes: true, + customer: customerId, + customer_update: { + address: 'auto', + name: 'never', + }, + mode: 'subscription', + metadata: { + workspaceId, + plan, + }, + currency, + billing_address_collection: 'required', + automatic_tax: { enabled: true }, + line_items: [ + { + price: + plan === 'STARTER' + ? env.STRIPE_STARTER_PRICE_ID + : env.STRIPE_PRO_PRICE_ID, + quantity: 1, + }, + { + price: + plan === 'STARTER' + ? env.STRIPE_STARTER_CHATS_PRICE_ID + : env.STRIPE_PRO_CHATS_PRICE_ID, + }, + ], + }) + + return session.url + } diff --git a/apps/builder/src/features/billing/api/createCustomCheckoutSession.ts b/apps/builder/src/features/billing/api/createCustomCheckoutSession.ts new file mode 100644 index 0000000..697214d --- /dev/null +++ b/apps/builder/src/features/billing/api/createCustomCheckoutSession.ts @@ -0,0 +1,183 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { Plan } from '@typebot.io/prisma' +import Stripe from 'stripe' +import { z } from 'zod' +import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden' +import { env } from '@typebot.io/env' + +export const createCustomCheckoutSession = authenticatedProcedure + .meta({ + openapi: { + method: 'POST', + path: '/v1/billing/subscription/custom-checkout', + protect: true, + summary: + 'Create custom checkout session to make a workspace pay for a custom plan', + tags: ['Billing'], + }, + }) + .input( + z.object({ + email: z.string(), + workspaceId: z.string(), + returnUrl: z.string(), + }) + ) + .output( + z.object({ + checkoutUrl: z.string(), + }) + ) + .mutation( + async ({ input: { email, workspaceId, returnUrl }, ctx: { user } }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe environment variables are missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + claimableCustomPlan: true, + name: true, + members: { + select: { + userId: true, + role: true, + }, + }, + }, + }) + if ( + !workspace?.claimableCustomPlan || + workspace.claimableCustomPlan.claimedAt || + isAdminWriteWorkspaceForbidden(workspace, user) + ) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Custom plan not found', + }) + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + + const vat = + workspace.claimableCustomPlan.vatValue && + workspace.claimableCustomPlan.vatType + ? ({ + type: workspace.claimableCustomPlan.vatType, + value: workspace.claimableCustomPlan.vatValue, + } as Stripe.CustomerCreateParams.TaxIdDatum) + : undefined + + const customer = workspace.stripeId + ? await stripe.customers.retrieve(workspace.stripeId) + : await stripe.customers.create({ + email, + name: workspace.claimableCustomPlan.companyName ?? workspace.name, + metadata: { workspaceId }, + tax_id_data: vat ? [vat] : undefined, + }) + + const session = await stripe.checkout.sessions.create({ + success_url: `${returnUrl}?stripe=${Plan.CUSTOM}&success=true`, + cancel_url: `${returnUrl}?stripe=cancel`, + allow_promotion_codes: true, + customer: customer.id, + customer_update: { + address: 'auto', + name: 'never', + }, + mode: 'subscription', + metadata: { + claimableCustomPlanId: workspace.claimableCustomPlan.id, + }, + currency: workspace.claimableCustomPlan.currency, + billing_address_collection: 'required', + automatic_tax: { enabled: true }, + line_items: [ + { + price_data: { + currency: workspace.claimableCustomPlan.currency, + tax_behavior: 'exclusive', + recurring: { + interval: workspace.claimableCustomPlan.isYearly + ? 'year' + : 'month', + }, + product_data: { + name: workspace.claimableCustomPlan.name, + description: + workspace.claimableCustomPlan.description ?? undefined, + }, + unit_amount: workspace.claimableCustomPlan.price * 100, + }, + quantity: 1, + }, + { + price_data: { + currency: workspace.claimableCustomPlan.currency, + tax_behavior: 'exclusive', + recurring: { + interval: workspace.claimableCustomPlan.isYearly + ? 'year' + : 'month', + }, + product_data: { + name: 'Included chats per month', + }, + unit_amount: 0, + }, + quantity: workspace.claimableCustomPlan.chatsLimit, + }, + { + price_data: { + currency: workspace.claimableCustomPlan.currency, + tax_behavior: 'exclusive', + recurring: { + interval: workspace.claimableCustomPlan.isYearly + ? 'year' + : 'month', + }, + product_data: { + name: 'Included storage per month', + }, + unit_amount: 0, + }, + quantity: workspace.claimableCustomPlan.storageLimit, + }, + { + price_data: { + currency: workspace.claimableCustomPlan.currency, + tax_behavior: 'exclusive', + recurring: { + interval: workspace.claimableCustomPlan.isYearly + ? 'year' + : 'month', + }, + product_data: { + name: 'Included seats', + }, + unit_amount: 0, + }, + quantity: workspace.claimableCustomPlan.seatsLimit, + }, + ], + }) + + if (!session.url) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe checkout session creation failed', + }) + + return { + checkoutUrl: session.url, + } + } + ) diff --git a/apps/builder/src/features/billing/api/getBillingPortalUrl.ts b/apps/builder/src/features/billing/api/getBillingPortalUrl.ts new file mode 100644 index 0000000..48bb840 --- /dev/null +++ b/apps/builder/src/features/billing/api/getBillingPortalUrl.ts @@ -0,0 +1,64 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import Stripe from 'stripe' +import { z } from 'zod' +import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden' +import { env } from '@typebot.io/env' + +export const getBillingPortalUrl = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/billing/subscription/portal', + protect: true, + summary: 'Get Stripe billing portal URL', + tags: ['Billing'], + }, + }) + .input( + z.object({ + workspaceId: z.string(), + }) + ) + .output( + z.object({ + billingPortalUrl: z.string(), + }) + ) + .query(async ({ input: { workspaceId }, ctx: { user } }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'STRIPE_SECRET_KEY var is missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + members: { + select: { + userId: true, + role: true, + }, + }, + }, + }) + if (!workspace?.stripeId || isAdminWriteWorkspaceForbidden(workspace, user)) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + const portalSession = await stripe.billingPortal.sessions.create({ + customer: workspace.stripeId, + return_url: `${env.NEXTAUTH_URL}/typebots`, + }) + return { + billingPortalUrl: portalSession.url, + } + }) diff --git a/apps/builder/src/features/billing/api/getSubscription.ts b/apps/builder/src/features/billing/api/getSubscription.ts new file mode 100644 index 0000000..bc71790 --- /dev/null +++ b/apps/builder/src/features/billing/api/getSubscription.ts @@ -0,0 +1,91 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import Stripe from 'stripe' +import { z } from 'zod' +import { subscriptionSchema } from '@typebot.io/schemas/features/billing/subscription' +import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden' +import { env } from '@typebot.io/env' + +export const getSubscription = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/billing/subscription', + protect: true, + summary: 'List invoices', + tags: ['Billing'], + }, + }) + .input( + z.object({ + workspaceId: z.string(), + }) + ) + .output( + z.object({ + subscription: subscriptionSchema.or(z.null()), + }) + ) + .query(async ({ input: { workspaceId }, ctx: { user } }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe environment variables are missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + members: { + select: { + userId: true, + }, + }, + }, + }) + if (!workspace || isReadWorkspaceFobidden(workspace, user)) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + if (!workspace?.stripeId) + return { + subscription: null, + } + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + const subscriptions = await stripe.subscriptions.list({ + customer: workspace.stripeId, + }) + + const currentSubscription = subscriptions.data + .filter((sub) => ['past_due', 'active'].includes(sub.status)) + .sort((a, b) => a.created - b.created) + .shift() + + if (!currentSubscription) + return { + subscription: null, + } + + return { + subscription: { + currentBillingPeriod: + subscriptionSchema.shape.currentBillingPeriod.parse({ + start: new Date(currentSubscription.current_period_start), + end: new Date(currentSubscription.current_period_end), + }), + status: subscriptionSchema.shape.status.parse( + currentSubscription.status + ), + currency: currentSubscription.currency as 'usd' | 'eur', + cancelDate: currentSubscription.cancel_at + ? new Date(currentSubscription.cancel_at * 1000) + : undefined, + }, + } + }) diff --git a/apps/builder/src/features/billing/api/getUsage.ts b/apps/builder/src/features/billing/api/getUsage.ts new file mode 100644 index 0000000..438e67f --- /dev/null +++ b/apps/builder/src/features/billing/api/getUsage.ts @@ -0,0 +1,108 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { z } from 'zod' +import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden' +import { env } from '@typebot.io/env' +import Stripe from 'stripe' + +export const getUsage = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/billing/usage', + protect: true, + summary: 'Get current plan usage', + tags: ['Billing'], + }, + }) + .input( + z.object({ + workspaceId: z.string(), + }) + ) + .output(z.object({ totalChatsUsed: z.number(), resetsAt: z.date() })) + .query(async ({ input: { workspaceId }, ctx: { user } }) => { + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + plan: true, + members: { + select: { + userId: true, + }, + }, + typebots: { + select: { id: true }, + }, + }, + }) + if (!workspace || isReadWorkspaceFobidden(workspace, user)) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + + if ( + !env.STRIPE_SECRET_KEY || + !workspace.stripeId || + (workspace.plan !== 'STARTER' && workspace.plan !== 'PRO') + ) { + const now = new Date() + const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1) + + const totalChatsUsed = await prisma.result.count({ + where: { + typebotId: { in: workspace.typebots.map((typebot) => typebot.id) }, + hasStarted: true, + createdAt: { + gte: firstDayOfMonth, + }, + }, + }) + + const firstDayOfNextMonth = new Date( + firstDayOfMonth.getFullYear(), + firstDayOfMonth.getMonth() + 1, + 1 + ) + return { totalChatsUsed, resetsAt: firstDayOfNextMonth } + } + + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + + const subscriptions = await stripe.subscriptions.list({ + customer: workspace.stripeId, + }) + + const currentSubscription = subscriptions.data + .filter((sub) => ['past_due', 'active'].includes(sub.status)) + .sort((a, b) => a.created - b.created) + .shift() + + if (!currentSubscription) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: `No subscription found on workspace: ${workspaceId}`, + }) + + const totalChatsUsed = await prisma.result.count({ + where: { + typebotId: { in: workspace.typebots.map((typebot) => typebot.id) }, + hasStarted: true, + createdAt: { + gte: new Date(currentSubscription.current_period_start * 1000), + }, + }, + }) + + return { + totalChatsUsed, + resetsAt: new Date(currentSubscription.current_period_end * 1000), + } + }) diff --git a/apps/builder/src/features/billing/api/listInvoices.ts b/apps/builder/src/features/billing/api/listInvoices.ts new file mode 100644 index 0000000..d520b7d --- /dev/null +++ b/apps/builder/src/features/billing/api/listInvoices.ts @@ -0,0 +1,75 @@ +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import Stripe from 'stripe' +import { isDefined } from '@typebot.io/lib' +import { z } from 'zod' +import { invoiceSchema } from '@typebot.io/schemas/features/billing/invoice' +import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden' +import { env } from '@typebot.io/env' + +export const listInvoices = authenticatedProcedure + .meta({ + openapi: { + method: 'GET', + path: '/v1/billing/invoices', + protect: true, + summary: 'List invoices', + tags: ['Billing'], + }, + }) + .input( + z.object({ + workspaceId: z.string(), + }) + ) + .output( + z.object({ + invoices: z.array(invoiceSchema), + }) + ) + .query(async ({ input: { workspaceId }, ctx: { user } }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'STRIPE_SECRET_KEY var is missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + stripeId: true, + members: { + select: { + userId: true, + role: true, + }, + }, + }, + }) + if (!workspace?.stripeId || isAdminWriteWorkspaceForbidden(workspace, user)) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + const invoices = await stripe.invoices.list({ + customer: workspace.stripeId, + }) + return { + invoices: invoices.data + .filter( + (invoice) => isDefined(invoice.invoice_pdf) && isDefined(invoice.id) + ) + .map((invoice) => ({ + id: invoice.number as string, + url: invoice.invoice_pdf as string, + amount: invoice.subtotal, + currency: invoice.currency, + date: invoice.status_transitions.paid_at, + })), + } + }) diff --git a/apps/builder/src/features/billing/api/router.ts b/apps/builder/src/features/billing/api/router.ts new file mode 100644 index 0000000..de4cd53 --- /dev/null +++ b/apps/builder/src/features/billing/api/router.ts @@ -0,0 +1,18 @@ +import { router } from '@/helpers/server/trpc' +import { createCheckoutSession } from './createCheckoutSession' +import { getBillingPortalUrl } from './getBillingPortalUrl' +import { getSubscription } from './getSubscription' +import { getUsage } from './getUsage' +import { listInvoices } from './listInvoices' +import { updateSubscription } from './updateSubscription' +import { createCustomCheckoutSession } from './createCustomCheckoutSession' + +export const billingRouter = router({ + getBillingPortalUrl, + listInvoices, + createCheckoutSession, + updateSubscription, + getSubscription, + getUsage, + createCustomCheckoutSession, +}) diff --git a/apps/builder/src/features/billing/api/updateSubscription.ts b/apps/builder/src/features/billing/api/updateSubscription.ts new file mode 100644 index 0000000..7070357 --- /dev/null +++ b/apps/builder/src/features/billing/api/updateSubscription.ts @@ -0,0 +1,167 @@ +import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent' +import prisma from '@typebot.io/lib/prisma' +import { authenticatedProcedure } from '@/helpers/server/trpc' +import { TRPCError } from '@trpc/server' +import { Plan } from '@typebot.io/prisma' +import { workspaceSchema } from '@typebot.io/schemas' +import Stripe from 'stripe' +import { z } from 'zod' +import { createCheckoutSessionUrl } from './createCheckoutSession' +import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden' +import { env } from '@typebot.io/env' + +export const updateSubscription = authenticatedProcedure + .meta({ + openapi: { + method: 'PATCH', + path: '/v1/billing/subscription', + protect: true, + summary: 'Update subscription', + tags: ['Billing'], + }, + }) + .input( + z.object({ + returnUrl: z.string(), + workspaceId: z.string(), + plan: z.enum([Plan.STARTER, Plan.PRO]), + currency: z.enum(['usd', 'eur']), + }) + ) + .output( + z.object({ + workspace: workspaceSchema.nullish(), + checkoutUrl: z.string().nullish(), + }) + ) + .mutation( + async ({ + input: { workspaceId, plan, currency, returnUrl }, + ctx: { user }, + }) => { + if (!env.STRIPE_SECRET_KEY) + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: 'Stripe environment variables are missing', + }) + const workspace = await prisma.workspace.findFirst({ + where: { + id: workspaceId, + }, + select: { + isQuarantined: true, + stripeId: true, + members: { + select: { + userId: true, + role: true, + }, + }, + }, + }) + if ( + !workspace?.stripeId || + isAdminWriteWorkspaceForbidden(workspace, user) + ) + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Workspace not found', + }) + + const stripe = new Stripe(env.STRIPE_SECRET_KEY, { + apiVersion: '2022-11-15', + }) + const { data } = await stripe.subscriptions.list({ + customer: workspace.stripeId, + limit: 1, + status: 'active', + }) + const subscription = data[0] as Stripe.Subscription | undefined + const currentPlanItemId = subscription?.items.data.find((item) => + [env.STRIPE_STARTER_PRICE_ID, env.STRIPE_PRO_PRICE_ID].includes( + item.price.id + ) + )?.id + const currentUsageItemId = subscription?.items.data.find( + (item) => + item.price.id === env.STRIPE_STARTER_CHATS_PRICE_ID || + item.price.id === env.STRIPE_PRO_CHATS_PRICE_ID + )?.id + + const items = [ + { + id: currentPlanItemId, + price: + plan === Plan.STARTER + ? env.STRIPE_STARTER_PRICE_ID + : env.STRIPE_PRO_PRICE_ID, + quantity: 1, + }, + { + id: currentUsageItemId, + price: + plan === Plan.STARTER + ? env.STRIPE_STARTER_CHATS_PRICE_ID + : env.STRIPE_PRO_CHATS_PRICE_ID, + }, + ] + + if (subscription) { + if (plan === 'STARTER') { + const totalChatsUsed = await prisma.result.count({ + where: { + typebot: { workspaceId }, + hasStarted: true, + createdAt: { + gte: new Date(subscription.current_period_start * 1000), + }, + }, + }) + if (totalChatsUsed >= 4000) { + throw new TRPCError({ + code: 'BAD_REQUEST', + message: + "You have collected more than 4000 chats during this billing cycle. You can't downgrade to the Starter.", + }) + } + } + + await stripe.subscriptions.update(subscription.id, { + items, + proration_behavior: 'always_invoice', + }) + } else { + const checkoutUrl = await createCheckoutSessionUrl(stripe)({ + customerId: workspace.stripeId, + userId: user.id, + workspaceId, + currency, + plan, + returnUrl, + }) + + return { checkoutUrl } + } + + const updatedWorkspace = await prisma.workspace.update({ + where: { id: workspaceId }, + data: { + plan, + isQuarantined: false, + }, + }) + + await sendTelemetryEvents([ + { + name: 'Subscription updated', + workspaceId, + userId: user.id, + data: { + plan, + }, + }, + ]) + + return { workspace: updatedWorkspace } + } + ) diff --git a/apps/builder/src/features/billing/billing.spec.ts b/apps/builder/src/features/billing/billing.spec.ts new file mode 100644 index 0000000..a703f3f --- /dev/null +++ b/apps/builder/src/features/billing/billing.spec.ts @@ -0,0 +1,219 @@ +import { + addSubscriptionToWorkspace, + cancelSubscription, + createClaimableCustomPlan, +} from '@/test/utils/databaseActions' +import test, { expect } from '@playwright/test' +import { createId } from '@paralleldrive/cuid2' +import { Plan } from '@typebot.io/prisma' +import { + createTypebots, + createWorkspaces, + deleteWorkspaces, + injectFakeResults, +} from '@typebot.io/lib/playwright/databaseActions' +import { env } from '@typebot.io/env' + +const usageWorkspaceId = createId() +const usageTypebotId = createId() +const planChangeWorkspaceId = createId() +const enterpriseWorkspaceId = createId() + +test.beforeAll(async () => { + await createWorkspaces([ + { + id: usageWorkspaceId, + name: 'Usage Workspace', + plan: Plan.STARTER, + }, + { + id: planChangeWorkspaceId, + name: 'Plan Change Workspace', + }, + { + id: enterpriseWorkspaceId, + name: 'Enterprise Workspace', + }, + ]) + await createTypebots([{ id: usageTypebotId, workspaceId: usageWorkspaceId }]) +}) + +test.afterAll(async () => { + await deleteWorkspaces([ + usageWorkspaceId, + planChangeWorkspaceId, + enterpriseWorkspaceId, + ]) +}) + +test('should display valid usage', async ({ page }) => { + await page.goto('/typebots') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="/ 10,000"')).toBeVisible() + await page.getByText('Members', { exact: true }).click() + await expect( + page.getByRole('heading', { name: 'Members (1/5)' }) + ).toBeVisible() + await page.click('text=Pro workspace', { force: true }) + + await page.click('text=Pro workspace') + await page.click('text="Custom workspace"') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="/ 100,000"')).toBeVisible() + await expect(page.getByText('Upgrade to Starter')).toBeHidden() + await expect(page.getByText('Upgrade to Pro')).toBeHidden() + await expect(page.getByText('Need custom limits?')).toBeHidden() + await page.getByText('Members', { exact: true }).click() + await expect( + page.getByRole('heading', { name: 'Members (1/20)' }) + ).toBeVisible() + await page.click('text=Custom workspace', { force: true }) + + await page.click('text=Custom workspace') + await page.click('text="Free workspace"') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="/ 200"')).toBeVisible() + await page.getByText('Members', { exact: true }).click() + await expect( + page.getByRole('heading', { name: 'Members (1/1)' }) + ).toBeVisible() + await page.click('text=Free workspace', { force: true }) + + await injectFakeResults({ + count: 10, + typebotId: usageTypebotId, + }) + await page.click('text=Free workspace') + await page.click('text="Usage Workspace"') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="/ 2,000"')).toBeVisible() + await expect(page.locator('text="10" >> nth=0')).toBeVisible() + await expect(page.locator('[role="progressbar"] >> nth=0')).toHaveAttribute( + 'aria-valuenow', + '1' + ) + + await injectFakeResults({ + typebotId: usageTypebotId, + count: 1090, + }) + await page.click('text="Settings"') + await page.click('text="Billing & Usage"') + await expect(page.locator('text="/ 2,000"')).toBeVisible() + await expect(page.locator('text="1,100"')).toBeVisible() + await expect(page.locator('[aria-valuenow="55"]')).toBeVisible() +}) + +test('plan changes should work', async ({ page }) => { + test.setTimeout(80000) + // Upgrade to STARTER + await page.goto('/typebots') + await page.click('text=Pro workspace') + await page.click('text=Plan Change Workspace') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="$39"')).toBeVisible() + await page.click('button >> text=Upgrade >> nth=0') + await page.getByLabel('Company name').fill('Company LLC') + await page.getByRole('button', { name: 'Go to checkout' }).click() + await page.waitForNavigation() + expect(page.url()).toContain('https://checkout.stripe.com') + await expect(page.locator('text=$39 >> nth=0')).toBeVisible() + const stripeId = await addSubscriptionToWorkspace( + planChangeWorkspaceId, + [ + { + price: env.STRIPE_STARTER_PRICE_ID, + quantity: 1, + }, + { + price: env.STRIPE_STARTER_CHATS_PRICE_ID, + }, + ], + { plan: Plan.STARTER } + ) + + // Update plan with additional quotas + await page.goto('/typebots') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="/ 2,000"')).toBeVisible() + await expect(page.getByText('/ 2,000')).toBeVisible() + + // Upgrade to PRO + await expect(page.locator('text="$89"')).toBeVisible() + await page.click('button >> text=Upgrade') + await expect( + page.locator('text="Workspace PRO plan successfully updated 🎉" >> nth=0') + ).toBeVisible() + + // Go to customer portal + await Promise.all([ + page.waitForNavigation(), + page.click('text="Billing portal"'), + ]) + await expect(page.getByText('$39.00')).toBeVisible({ + timeout: 10000, + }) + await expect(page.getByText('$50.00')).toBeVisible({ + timeout: 10000, + }) + await expect(page.locator('text="Add payment method"')).toBeVisible() + await cancelSubscription(stripeId) + + // Cancel subscription + await page.goto('/typebots') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect( + page.getByTestId('current-subscription').getByTestId('pro-plan-tag') + ).toBeVisible() + await expect(page.getByText('Will be cancelled on')).toBeVisible() +}) + +test('should display invoices', async ({ page }) => { + await page.goto('/typebots') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="Invoices"')).toBeHidden() + await page.click('text=Pro workspace', { force: true }) + + await page.click('text=Pro workspace') + await page.click('text=Plan Change Workspace') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.locator('text="Invoices"')).toBeVisible() + await expect(page.locator('tr')).toHaveCount(4) + await expect(page.getByText('$39.00')).toBeVisible() + await expect(page.getByText('$50.00')).toBeVisible() +}) + +test('custom plans should work', async ({ page }) => { + await page.goto('/typebots') + await page.click('text=Pro workspace') + await page.click('text=Enterprise Workspace') + await page.click('text=Settings & Members') + await page.click('text=Billing & Usage') + await expect(page.getByTestId('current-subscription')).toHaveText( + 'Current workspace subscription: Free' + ) + await createClaimableCustomPlan({ + currency: 'usd', + price: 239, + workspaceId: enterpriseWorkspaceId, + chatsLimit: 100000, + storageLimit: 50, + seatsLimit: 10, + name: 'Acme custom plan', + description: 'Description of the deal', + }) + + await page.goto('/typebots?claimCustomPlan=true') + + await expect(page.getByRole('list').getByText('$239.00')).toBeVisible() + await expect(page.getByText('Subscribe to Acme custom plan')).toBeVisible() +}) diff --git a/apps/builder/src/features/billing/components/BillingPortalButton.tsx b/apps/builder/src/features/billing/components/BillingPortalButton.tsx new file mode 100644 index 0000000..747dc4e --- /dev/null +++ b/apps/builder/src/features/billing/components/BillingPortalButton.tsx @@ -0,0 +1,35 @@ +import { useToast } from '@/hooks/useToast' +import { trpc } from '@/lib/trpc' +import { useTranslate } from '@tolgee/react' +import { Button, ButtonProps, Link } from '@chakra-ui/react' + +type Props = { + workspaceId: string +} & Pick + +export const BillingPortalButton = ({ workspaceId, colorScheme }: Props) => { + const { t } = useTranslate() + const { showToast } = useToast() + const { data } = trpc.billing.getBillingPortalUrl.useQuery( + { + workspaceId, + }, + { + onError: (error) => { + showToast({ + description: error.message, + }) + }, + } + ) + return ( + + ) +} diff --git a/apps/builder/src/features/billing/components/BillingSettingsLayout.tsx b/apps/builder/src/features/billing/components/BillingSettingsLayout.tsx new file mode 100644 index 0000000..c6ada09 --- /dev/null +++ b/apps/builder/src/features/billing/components/BillingSettingsLayout.tsx @@ -0,0 +1,30 @@ +import { Stack } from '@chakra-ui/react' +import { useWorkspace } from '@/features/workspace/WorkspaceProvider' +import { Plan } from '@typebot.io/prisma' +import React from 'react' +import { InvoicesList } from './InvoicesList' +import { ChangePlanForm } from './ChangePlanForm' +import { UsageProgressBars } from './UsageProgressBars' +import { CurrentSubscriptionSummary } from './CurrentSubscriptionSummary' + +export const BillingSettingsLayout = () => { + const { workspace } = useWorkspace() + + if (!workspace) return null + return ( + + + + + {workspace.plan !== Plan.CUSTOM && + workspace.plan !== Plan.LIFETIME && + workspace.plan !== Plan.UNLIMITED && + workspace.plan !== Plan.OFFERED && ( + + )} + + + {workspace.stripeId && } + + ) +} diff --git a/apps/builder/src/features/billing/components/ChangePlanForm.tsx b/apps/builder/src/features/billing/components/ChangePlanForm.tsx new file mode 100644 index 0000000..30c9b78 --- /dev/null +++ b/apps/builder/src/features/billing/components/ChangePlanForm.tsx @@ -0,0 +1,138 @@ +import { Stack, HStack, Text } from '@chakra-ui/react' +import { Plan } from '@typebot.io/prisma' +import { TextLink } from '@/components/TextLink' +import { useToast } from '@/hooks/useToast' +import { trpc } from '@/lib/trpc' +import { Workspace } from '@typebot.io/schemas' +import { PreCheckoutModal, PreCheckoutModalProps } from './PreCheckoutModal' +import { useState } from 'react' +import { ParentModalProvider } from '@/features/graph/providers/ParentModalProvider' +import { useUser } from '@/features/account/hooks/useUser' +import { StarterPlanPricingCard } from './StarterPlanPricingCard' +import { ProPlanPricingCard } from './ProPlanPricingCard' +import { useTranslate } from '@tolgee/react' +import { StripeClimateLogo } from './StripeClimateLogo' +import { guessIfUserIsEuropean } from '@typebot.io/lib/billing/guessIfUserIsEuropean' + +type Props = { + workspace: Workspace + excludedPlans?: ('STARTER' | 'PRO')[] +} + +export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => { + const { t } = useTranslate() + + const { user } = useUser() + const { showToast } = useToast() + const [preCheckoutPlan, setPreCheckoutPlan] = + useState() + + const trpcContext = trpc.useContext() + + const { data, refetch } = trpc.billing.getSubscription.useQuery({ + workspaceId: workspace.id, + }) + + const { mutate: updateSubscription, isLoading: isUpdatingSubscription } = + trpc.billing.updateSubscription.useMutation({ + onError: (error) => { + showToast({ + description: error.message, + }) + }, + onSuccess: ({ workspace, checkoutUrl }) => { + if (checkoutUrl) { + window.location.href = checkoutUrl + return + } + refetch() + trpcContext.workspace.getWorkspace.invalidate() + showToast({ + status: 'success', + description: t('billing.updateSuccessToast.description', { + plan: workspace?.plan, + }), + }) + }, + }) + + const handlePayClick = async (plan: 'STARTER' | 'PRO') => { + if (!user) return + + const newSubscription = { + plan, + workspaceId: workspace.id, + currency: + data?.subscription?.currency ?? + (guessIfUserIsEuropean() ? 'eur' : 'usd'), + } as const + if (workspace.stripeId) { + updateSubscription({ + ...newSubscription, + returnUrl: window.location.href, + }) + } else { + setPreCheckoutPlan(newSubscription) + } + } + + if ( + data?.subscription?.cancelDate || + data?.subscription?.status === 'past_due' + ) + return null + + return ( + + + + + {t('billing.contribution.preLink')}{' '} + + {t('billing.contribution.link')} + + + + {!workspace.stripeId && ( + + setPreCheckoutPlan(undefined)} + /> + + )} + {data && ( + + + {excludedPlans?.includes('STARTER') ? null : ( + handlePayClick(Plan.STARTER)} + isLoading={isUpdatingSubscription} + currency={data.subscription?.currency} + /> + )} + + {excludedPlans?.includes('PRO') ? null : ( + handlePayClick(Plan.PRO)} + isLoading={isUpdatingSubscription} + currency={data.subscription?.currency} + /> + )} + + + )} + + + {t('billing.customLimit.preLink')}{' '} + + {t('billing.customLimit.link')} + + + + ) +} diff --git a/apps/builder/src/features/billing/components/ChangePlanModal.tsx b/apps/builder/src/features/billing/components/ChangePlanModal.tsx new file mode 100644 index 0000000..5bd8bb5 --- /dev/null +++ b/apps/builder/src/features/billing/components/ChangePlanModal.tsx @@ -0,0 +1,63 @@ +import { AlertInfo } from '@/components/AlertInfo' +import { useWorkspace } from '@/features/workspace/WorkspaceProvider' +import { useTranslate } from '@tolgee/react' +import { + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalOverlay, + Stack, + Button, + HStack, +} from '@chakra-ui/react' +import { ChangePlanForm } from './ChangePlanForm' + +export type ChangePlanModalProps = { + type?: string + isOpen: boolean + excludedPlans?: ('STARTER' | 'PRO')[] + onClose: () => void +} + +export const ChangePlanModal = ({ + onClose, + isOpen, + type, + excludedPlans, +}: ChangePlanModalProps) => { + const { t } = useTranslate() + const { workspace } = useWorkspace() + return ( + + + + + {type && ( + + {t('billing.upgradeLimitLabel', { type: type })} + + )} + {workspace && ( + + )} + + + + + + + + + + ) +} diff --git a/apps/builder/src/features/billing/components/ChatsProTiersModal.tsx b/apps/builder/src/features/billing/components/ChatsProTiersModal.tsx new file mode 100644 index 0000000..2116787 --- /dev/null +++ b/apps/builder/src/features/billing/components/ChatsProTiersModal.tsx @@ -0,0 +1,90 @@ +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalCloseButton, + ModalBody, + Stack, + ModalFooter, + Heading, + Table, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, +} from '@chakra-ui/react' +import { useTranslate } from '@tolgee/react' +import { proChatTiers } from '@typebot.io/lib/billing/constants' +import { formatPrice } from '@typebot.io/lib/billing/formatPrice' + +type Props = { + isOpen: boolean + onClose: () => void +} + +export const ChatsProTiersModal = ({ isOpen, onClose }: Props) => { + const { t } = useTranslate() + + return ( + + + + + {t('billing.tiersModal.heading')} + + + + + + + + + + + + + + {proChatTiers.map((tier, index) => { + const pricePerMonth = + (tier.flat_amount ?? + proChatTiers.at(-2)?.flat_amount ?? + 0) / 100 + return ( + + + + + + ) + })} + +
Max chatsPrice per monthPrice per 1k chats
+ {tier.up_to === 'inf' + ? '2,000,000+' + : tier.up_to.toLocaleString()} + + {index === 0 ? 'included' : formatPrice(pricePerMonth)} + + {index === proChatTiers.length - 1 + ? formatPrice(4.42, { maxFractionDigits: 2 }) + : index === 0 + ? 'included' + : formatPrice( + (((pricePerMonth * 100) / + ((tier.up_to as number) - + (proChatTiers.at(0)?.up_to as number))) * + 1000) / + 100, + { maxFractionDigits: 2 } + )} +
+
+
+ +
+
+ ) +} diff --git a/apps/builder/src/features/billing/components/CurrentSubscriptionSummary.tsx b/apps/builder/src/features/billing/components/CurrentSubscriptionSummary.tsx new file mode 100644 index 0000000..13dedd0 --- /dev/null +++ b/apps/builder/src/features/billing/components/CurrentSubscriptionSummary.tsx @@ -0,0 +1,64 @@ +import { + Text, + HStack, + Stack, + Heading, + Alert, + AlertIcon, +} from '@chakra-ui/react' +import { Plan } from '@typebot.io/prisma' +import React from 'react' +import { PlanTag } from './PlanTag' +import { BillingPortalButton } from './BillingPortalButton' +import { trpc } from '@/lib/trpc' +import { Workspace } from '@typebot.io/schemas' +import { useTranslate } from '@tolgee/react' + +type Props = { + workspace: Pick +} + +export const CurrentSubscriptionSummary = ({ workspace }: Props) => { + const { t } = useTranslate() + + const { data } = trpc.billing.getSubscription.useQuery({ + workspaceId: workspace.id, + }) + + const isSubscribed = + (workspace.plan === Plan.STARTER || workspace.plan === Plan.PRO) && + workspace.stripeId + + return ( + + + {t('billing.currentSubscription.heading')} + + + {t('billing.currentSubscription.subheading')} + + {data?.subscription?.cancelDate && ( + + ({t('billing.currentSubscription.cancelDate')}{' '} + {data.subscription.cancelDate.toDateString()}) + + )} + + {data?.subscription?.status === 'past_due' && ( + + + {t('billing.currentSubscription.pastDueAlert')} + + )} + + {isSubscribed && ( + + )} + + ) +} diff --git a/apps/builder/src/features/billing/components/FeaturesList.tsx b/apps/builder/src/features/billing/components/FeaturesList.tsx new file mode 100644 index 0000000..11e2015 --- /dev/null +++ b/apps/builder/src/features/billing/components/FeaturesList.tsx @@ -0,0 +1,21 @@ +import { + ListProps, + UnorderedList, + Flex, + ListItem, + ListIcon, +} from '@chakra-ui/react' +import { CheckIcon } from '@/components/icons' + +type FeaturesListProps = { features: (string | JSX.Element)[] } & ListProps + +export const FeaturesList = ({ features, ...props }: FeaturesListProps) => ( + + {features.map((feat, idx) => ( + + + {feat} + + ))} + +) diff --git a/apps/builder/src/features/billing/components/InvoicesList.tsx b/apps/builder/src/features/billing/components/InvoicesList.tsx new file mode 100644 index 0000000..9c1e003 --- /dev/null +++ b/apps/builder/src/features/billing/components/InvoicesList.tsx @@ -0,0 +1,115 @@ +import { + Stack, + Heading, + Checkbox, + Skeleton, + Table, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, + IconButton, + Text, +} from '@chakra-ui/react' +import { DownloadIcon, FileIcon } from '@/components/icons' +import Link from 'next/link' +import React from 'react' +import { trpc } from '@/lib/trpc' +import { useToast } from '@/hooks/useToast' +import { useTranslate } from '@tolgee/react' + +type Props = { + workspaceId: string +} + +export const InvoicesList = ({ workspaceId }: Props) => { + const { t } = useTranslate() + const { showToast } = useToast() + const { data, status } = trpc.billing.listInvoices.useQuery( + { + workspaceId, + }, + { + onError: (error) => { + showToast({ description: error.message }) + }, + } + ) + + return ( + + {t('billing.invoices.heading')} + {data?.invoices.length === 0 && status !== 'loading' ? ( + {t('billing.invoices.empty')} + ) : ( + + + + + + + + + + + {data?.invoices.map((invoice) => ( + + + + + + + + ))} + {status === 'loading' && + Array.from({ length: 3 }).map((_, idx) => ( + + + + + + ))} + +
+ #{t('billing.invoices.paidAt')}{t('billing.invoices.subtotal')} +
+ + {invoice.id} + {invoice.date + ? new Date(invoice.date * 1000).toDateString() + : ''} + {getFormattedPrice(invoice.amount, invoice.currency)} + {invoice.url && ( + } + variant="outline" + href={invoice.url} + target="_blank" + aria-label={'Download invoice'} + /> + )} +
+ + + + + +
+
+ )} +
+ ) +} + +const getFormattedPrice = (amount: number, currency: string) => { + const formatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency, + }) + + return formatter.format(amount / 100) +} diff --git a/apps/builder/src/features/billing/components/LockTag.tsx b/apps/builder/src/features/billing/components/LockTag.tsx new file mode 100644 index 0000000..8b6a171 --- /dev/null +++ b/apps/builder/src/features/billing/components/LockTag.tsx @@ -0,0 +1,14 @@ +import { Tag, TagProps } from '@chakra-ui/react' +import { LockedIcon } from '@/components/icons' +import { Plan } from '@typebot.io/prisma' +import { planColorSchemes } from './PlanTag' + +export const LockTag = ({ plan, ...props }: { plan?: Plan } & TagProps) => ( + + + +) diff --git a/apps/builder/src/features/billing/components/PlanTag.tsx b/apps/builder/src/features/billing/components/PlanTag.tsx new file mode 100644 index 0000000..c4e4f17 --- /dev/null +++ b/apps/builder/src/features/billing/components/PlanTag.tsx @@ -0,0 +1,87 @@ +import { Tag, TagProps, ThemeTypings } from '@chakra-ui/react' +import { Plan } from '@typebot.io/prisma' + +export const planColorSchemes: Record = { + [Plan.LIFETIME]: 'purple', + [Plan.PRO]: 'blue', + [Plan.OFFERED]: 'orange', + [Plan.STARTER]: 'orange', + [Plan.FREE]: 'gray', + [Plan.CUSTOM]: 'yellow', + [Plan.UNLIMITED]: 'yellow', +} + +export const PlanTag = ({ + plan, + ...props +}: { plan: Plan } & TagProps): JSX.Element => { + switch (plan) { + case Plan.LIFETIME: { + return ( + + Lifetime + + ) + } + case Plan.PRO: { + return ( + + Pro + + ) + } + case Plan.OFFERED: + case Plan.STARTER: { + return ( + + Starter + + ) + } + case Plan.FREE: { + return ( + + Free + + ) + } + case Plan.CUSTOM: { + return ( + + Custom + + ) + } + case Plan.UNLIMITED: { + return ( + + Unlimited + + ) + } + } +} diff --git a/apps/builder/src/features/billing/components/PreCheckoutModal.tsx b/apps/builder/src/features/billing/components/PreCheckoutModal.tsx new file mode 100644 index 0000000..3a03221 --- /dev/null +++ b/apps/builder/src/features/billing/components/PreCheckoutModal.tsx @@ -0,0 +1,181 @@ +import { TextInput } from '@/components/inputs' +import { Select } from '@/components/inputs/Select' +import { useParentModal } from '@/features/graph/providers/ParentModalProvider' +import { useToast } from '@/hooks/useToast' +import { trpc } from '@/lib/trpc' +import { + Button, + FormControl, + FormLabel, + HStack, + Modal, + ModalBody, + ModalContent, + ModalOverlay, + Stack, +} from '@chakra-ui/react' +import { useRouter } from 'next/router' +import React, { FormEvent, useState } from 'react' +import { isDefined } from '@typebot.io/lib' +import { taxIdTypes } from '../taxIdTypes' +import { useTranslate } from '@tolgee/react' + +export type PreCheckoutModalProps = { + selectedSubscription: + | { + plan: 'STARTER' | 'PRO' + workspaceId: string + currency: 'eur' | 'usd' + } + | undefined + existingCompany?: string + existingEmail?: string + onClose: () => void +} + +const vatCodeLabels = taxIdTypes.map((taxIdType) => ({ + label: `${taxIdType.emoji} ${taxIdType.name} (${taxIdType.code})`, + value: taxIdType.type, + extras: { + placeholder: taxIdType.placeholder, + }, +})) + +export const PreCheckoutModal = ({ + selectedSubscription, + existingCompany, + existingEmail, + onClose, +}: PreCheckoutModalProps) => { + const { t } = useTranslate() + const { ref } = useParentModal() + const vatValueInputRef = React.useRef(null) + const router = useRouter() + const { showToast } = useToast() + const { mutate: createCheckoutSession, isLoading: isCreatingCheckout } = + trpc.billing.createCheckoutSession.useMutation({ + onError: (error) => { + showToast({ + description: error.message, + }) + }, + onSuccess: ({ checkoutUrl }) => { + router.push(checkoutUrl) + }, + }) + + const [customer, setCustomer] = useState({ + company: existingCompany ?? '', + email: existingEmail ?? '', + vat: { + type: undefined as string | undefined, + value: '', + }, + }) + const [vatValuePlaceholder, setVatValuePlaceholder] = useState('') + + const updateCustomerCompany = (company: string) => { + setCustomer((customer) => ({ ...customer, company })) + } + + const updateCustomerEmail = (email: string) => { + setCustomer((customer) => ({ ...customer, email })) + } + + const updateVatType = ( + type: string | undefined, + vatCode?: (typeof vatCodeLabels)[number] + ) => { + setCustomer((customer) => ({ + ...customer, + vat: { + ...customer.vat, + type, + }, + })) + setVatValuePlaceholder(vatCode?.extras?.placeholder ?? '') + vatValueInputRef.current?.focus() + } + + const updateVatValue = (value: string) => { + setCustomer((customer) => ({ + ...customer, + vat: { + ...customer.vat, + value, + }, + })) + } + + const goToCheckout = (e: FormEvent) => { + e.preventDefault() + if (!selectedSubscription) return + const { email, company, vat } = customer + createCheckoutSession({ + ...selectedSubscription, + email, + company, + returnUrl: window.location.href, + vat: + vat.value && vat.type + ? { type: vat.type, value: vat.value } + : undefined, + }) + } + + return ( + + + + + + + + + {t('billing.preCheckoutModal.taxId.label')} + + + {currencies.map((currency) => ( + + ))} + + + + + + + + + Additional information + + + + + + + + + + + + + +
+ ) +} diff --git a/apps/builder/src/features/blocks/inputs/payment/components/StripeConfigModal.tsx b/apps/builder/src/features/blocks/inputs/payment/components/StripeConfigModal.tsx new file mode 100644 index 0000000..5028d4b --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/payment/components/StripeConfigModal.tsx @@ -0,0 +1,208 @@ +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalCloseButton, + ModalBody, + ModalFooter, + Button, + FormControl, + FormLabel, + Stack, + Text, + HStack, +} from '@chakra-ui/react' +import React, { useState } from 'react' +import { useWorkspace } from '@/features/workspace/WorkspaceProvider' +import { useToast } from '@/hooks/useToast' +import { TextInput } from '@/components/inputs' +import { MoreInfoTooltip } from '@/components/MoreInfoTooltip' +import { TextLink } from '@/components/TextLink' +import { StripeCredentials } from '@typebot.io/schemas' +import { trpc } from '@/lib/trpc' +import { isNotEmpty } from '@typebot.io/lib' +import { useUser } from '@/features/account/hooks/useUser' + +type Props = { + isOpen: boolean + onClose: () => void + onNewCredentials: (id: string) => void +} + +export const StripeConfigModal = ({ + isOpen, + onNewCredentials, + onClose, +}: Props) => { + const { user } = useUser() + const { workspace } = useWorkspace() + const [isCreating, setIsCreating] = useState(false) + const { showToast } = useToast() + const [stripeConfig, setStripeConfig] = useState< + StripeCredentials['data'] & { name: string } + >({ + name: '', + live: { publicKey: '', secretKey: '' }, + test: { publicKey: '', secretKey: '' }, + }) + const { + credentials: { + listCredentials: { refetch: refetchCredentials }, + }, + } = trpc.useContext() + const { mutate } = trpc.credentials.createCredentials.useMutation({ + onMutate: () => setIsCreating(true), + onSettled: () => setIsCreating(false), + onError: (err) => { + showToast({ + description: err.message, + status: 'error', + }) + }, + onSuccess: (data) => { + refetchCredentials() + onNewCredentials(data.credentialsId) + onClose() + }, + }) + + const handleNameChange = (name: string) => + setStripeConfig({ + ...stripeConfig, + name, + }) + + const handlePublicKeyChange = (publicKey: string) => + setStripeConfig({ + ...stripeConfig, + live: { ...stripeConfig.live, publicKey }, + }) + + const handleSecretKeyChange = (secretKey: string) => + setStripeConfig({ + ...stripeConfig, + live: { ...stripeConfig.live, secretKey }, + }) + + const handleTestPublicKeyChange = (publicKey: string) => + setStripeConfig({ + ...stripeConfig, + test: { ...stripeConfig.test, publicKey }, + }) + + const handleTestSecretKeyChange = (secretKey: string) => + setStripeConfig({ + ...stripeConfig, + test: { ...stripeConfig.test, secretKey }, + }) + + const createCredentials = async () => { + if (!user?.email || !workspace?.id) return + mutate({ + credentials: { + data: { + live: stripeConfig.live, + test: { + publicKey: isNotEmpty(stripeConfig.test.publicKey) + ? stripeConfig.test.publicKey + : undefined, + secretKey: isNotEmpty(stripeConfig.test.secretKey) + ? stripeConfig.test.secretKey + : undefined, + }, + }, + name: stripeConfig.name, + type: 'stripe', + workspaceId: workspace.id, + }, + }) + } + return ( + + + + Connect Stripe account + + + + + + + Test keys:{' '} + + Will be used when previewing the bot. + + + + + + + + + Live keys: + + + + + + + + + + + + (You can find your keys{' '} + + here + + ) + + + + + + + + + + ) +} diff --git a/apps/builder/src/features/blocks/inputs/payment/currencies.tsx b/apps/builder/src/features/blocks/inputs/payment/currencies.tsx new file mode 100644 index 0000000..c185183 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/payment/currencies.tsx @@ -0,0 +1,545 @@ +// The STRIPE-supported currencies, sorted by code +// https://gist.github.com/chrisdavies/9e3f00889fb764013339632bd3f2a71b + +export const currencies = [ + { + code: 'AED', + description: 'United Arab Emirates Dirham', + }, + { + code: 'AFN', + description: 'Afghan Afghani**', + }, + { + code: 'ALL', + description: 'Albanian Lek', + }, + { + code: 'AMD', + description: 'Armenian Dram', + }, + { + code: 'ANG', + description: 'Netherlands Antillean Gulden', + }, + { + code: 'AOA', + description: 'Angolan Kwanza**', + }, + { + code: 'ARS', + description: 'Argentine Peso**', + }, + { + code: 'AUD', + description: 'Australian Dollar', + }, + { + code: 'AWG', + description: 'Aruban Florin', + }, + { + code: 'AZN', + description: 'Azerbaijani Manat', + }, + { + code: 'BAM', + description: 'Bosnia & Herzegovina Convertible Mark', + }, + { + code: 'BBD', + description: 'Barbadian Dollar', + }, + { + code: 'BDT', + description: 'Bangladeshi Taka', + }, + { + code: 'BGN', + description: 'Bulgarian Lev', + }, + { + code: 'BIF', + description: 'Burundian Franc', + }, + { + code: 'BMD', + description: 'Bermudian Dollar', + }, + { + code: 'BND', + description: 'Brunei Dollar', + }, + { + code: 'BOB', + description: 'Bolivian Boliviano**', + }, + { + code: 'BRL', + description: 'Brazilian Real**', + }, + { + code: 'BSD', + description: 'Bahamian Dollar', + }, + { + code: 'BWP', + description: 'Botswana Pula', + }, + { + code: 'BZD', + description: 'Belize Dollar', + }, + { + code: 'CAD', + description: 'Canadian Dollar', + }, + { + code: 'CDF', + description: 'Congolese Franc', + }, + { + code: 'CHF', + description: 'Swiss Franc', + }, + { + code: 'CLP', + description: 'Chilean Peso**', + }, + { + code: 'CNY', + description: 'Chinese Renminbi Yuan', + }, + { + code: 'COP', + description: 'Colombian Peso**', + }, + { + code: 'CRC', + description: 'Costa Rican Colón**', + }, + { + code: 'CVE', + description: 'Cape Verdean Escudo**', + }, + { + code: 'CZK', + description: 'Czech Koruna**', + }, + { + code: 'DJF', + description: 'Djiboutian Franc**', + }, + { + code: 'DKK', + description: 'Danish Krone', + }, + { + code: 'DOP', + description: 'Dominican Peso', + }, + { + code: 'DZD', + description: 'Algerian Dinar', + }, + { + code: 'EGP', + description: 'Egyptian Pound', + }, + { + code: 'ETB', + description: 'Ethiopian Birr', + }, + { + code: 'EUR', + description: 'Euro', + }, + { + code: 'FJD', + description: 'Fijian Dollar', + }, + { + code: 'FKP', + description: 'Falkland Islands Pound**', + }, + { + code: 'GBP', + description: 'British Pound', + }, + { + code: 'GEL', + description: 'Georgian Lari', + }, + { + code: 'GIP', + description: 'Gibraltar Pound', + }, + { + code: 'GMD', + description: 'Gambian Dalasi', + }, + { + code: 'GNF', + description: 'Guinean Franc**', + }, + { + code: 'GTQ', + description: 'Guatemalan Quetzal**', + }, + { + code: 'GYD', + description: 'Guyanese Dollar', + }, + { + code: 'HKD', + description: 'Hong Kong Dollar', + }, + { + code: 'HNL', + description: 'Honduran Lempira**', + }, + { + code: 'HRK', + description: 'Croatian Kuna', + }, + { + code: 'HTG', + description: 'Haitian Gourde', + }, + { + code: 'HUF', + description: 'Hungarian Forint**', + }, + { + code: 'IDR', + description: 'Indonesian Rupiah', + }, + { + code: 'ILS', + description: 'Israeli New Sheqel', + }, + { + code: 'INR', + description: 'Indian Rupee**', + }, + { + code: 'ISK', + description: 'Icelandic Króna', + }, + { + code: 'JMD', + description: 'Jamaican Dollar', + }, + { + code: 'JPY', + description: 'Japanese Yen', + }, + { + code: 'KES', + description: 'Kenyan Shilling', + }, + { + code: 'KGS', + description: 'Kyrgyzstani Som', + }, + { + code: 'KHR', + description: 'Cambodian Riel', + }, + { + code: 'KMF', + description: 'Comorian Franc', + }, + { + code: 'KRW', + description: 'South Korean Won', + }, + { + code: 'KYD', + description: 'Cayman Islands Dollar', + }, + { + code: 'KZT', + description: 'Kazakhstani Tenge', + }, + { + code: 'LAK', + description: 'Lao Kip**', + }, + { + code: 'LBP', + description: 'Lebanese Pound', + }, + { + code: 'LKR', + description: 'Sri Lankan Rupee', + }, + { + code: 'LRD', + description: 'Liberian Dollar', + }, + { + code: 'LSL', + description: 'Lesotho Loti', + }, + { + code: 'MAD', + description: 'Moroccan Dirham', + }, + { + code: 'MDL', + description: 'Moldovan Leu', + }, + { + code: 'MGA', + description: 'Malagasy Ariary', + }, + { + code: 'MKD', + description: 'Macedonian Denar', + }, + { + code: 'MNT', + description: 'Mongolian Tögrög', + }, + { + code: 'MOP', + description: 'Macanese Pataca', + }, + { + code: 'MRO', + description: 'Mauritanian Ouguiya', + }, + { + code: 'MUR', + description: 'Mauritian Rupee**', + }, + { + code: 'MVR', + description: 'Maldivian Rufiyaa', + }, + { + code: 'MWK', + description: 'Malawian Kwacha', + }, + { + code: 'MXN', + description: 'Mexican Peso**', + }, + { + code: 'MYR', + description: 'Malaysian Ringgit', + }, + { + code: 'MZN', + description: 'Mozambican Metical', + }, + { + code: 'NAD', + description: 'Namibian Dollar', + }, + { + code: 'NGN', + description: 'Nigerian Naira', + }, + { + code: 'NIO', + description: 'Nicaraguan Córdoba**', + }, + { + code: 'NOK', + description: 'Norwegian Krone', + }, + { + code: 'NPR', + description: 'Nepalese Rupee', + }, + { + code: 'NZD', + description: 'New Zealand Dollar', + }, + { + code: 'PAB', + description: 'Panamanian Balboa**', + }, + { + code: 'PEN', + description: 'Peruvian Nuevo Sol**', + }, + { + code: 'PGK', + description: 'Papua New Guinean Kina', + }, + { + code: 'PHP', + description: 'Philippine Peso', + }, + { + code: 'PKR', + description: 'Pakistani Rupee', + }, + { + code: 'PLN', + description: 'Polish Złoty', + }, + { + code: 'PYG', + description: 'Paraguayan Guaraní**', + }, + { + code: 'QAR', + description: 'Qatari Riyal', + }, + { + code: 'RON', + description: 'Romanian Leu', + }, + { + code: 'RSD', + description: 'Serbian Dinar', + }, + { + code: 'RUB', + description: 'Russian Ruble', + }, + { + code: 'RWF', + description: 'Rwandan Franc', + }, + { + code: 'SAR', + description: 'Saudi Riyal', + }, + { + code: 'SBD', + description: 'Solomon Islands Dollar', + }, + { + code: 'SCR', + description: 'Seychellois Rupee', + }, + { + code: 'SEK', + description: 'Swedish Krona', + }, + { + code: 'SGD', + description: 'Singapore Dollar', + }, + { + code: 'SHP', + description: 'Saint Helenian Pound**', + }, + { + code: 'SLL', + description: 'Sierra Leonean Leone', + }, + { + code: 'SOS', + description: 'Somali Shilling', + }, + { + code: 'SRD', + description: 'Surinamese Dollar**', + }, + { + code: 'STD', + description: 'São Tomé and Príncipe Dobra', + }, + { + code: 'SVC', + description: 'Salvadoran Colón**', + }, + { + code: 'SZL', + description: 'Swazi Lilangeni', + }, + { + code: 'THB', + description: 'Thai Baht', + }, + { + code: 'TJS', + description: 'Tajikistani Somoni', + }, + { + code: 'TOP', + description: 'Tongan Paʻanga', + }, + { + code: 'TRY', + description: 'Turkish Lira', + }, + { + code: 'TTD', + description: 'Trinidad and Tobago Dollar', + }, + { + code: 'TWD', + description: 'New Taiwan Dollar', + }, + { + code: 'TZS', + description: 'Tanzanian Shilling', + }, + { + code: 'UAH', + description: 'Ukrainian Hryvnia', + }, + { + code: 'UGX', + description: 'Ugandan Shilling', + }, + { + code: 'USD', + description: 'United States Dollar', + }, + { + code: 'UYU', + description: 'Uruguayan Peso**', + }, + { + code: 'UZS', + description: 'Uzbekistani Som', + }, + { + code: 'VND', + description: 'Vietnamese Đồng', + }, + { + code: 'VUV', + description: 'Vanuatu Vatu', + }, + { + code: 'WST', + description: 'Samoan Tala', + }, + { + code: 'XAF', + description: 'Central African Cfa Franc', + }, + { + code: 'XCD', + description: 'East Caribbean Dollar', + }, + { + code: 'XOF', + description: 'West African Cfa Franc**', + }, + { + code: 'XPF', + description: 'Cfp Franc**', + }, + { + code: 'YER', + description: 'Yemeni Rial', + }, + { + code: 'ZAR', + description: 'South African Rand', + }, + { + code: 'ZMW', + description: 'Zambian Kwacha', + }, +] diff --git a/apps/builder/src/features/blocks/inputs/payment/payment.spec.ts b/apps/builder/src/features/blocks/inputs/payment/payment.spec.ts new file mode 100644 index 0000000..df1242f --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/payment/payment.spec.ts @@ -0,0 +1,67 @@ +import test, { expect } from '@playwright/test' +import { createTypebots } from '@typebot.io/lib/playwright/databaseActions' +import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers' +import { createId } from '@paralleldrive/cuid2' +import { stripePaymentForm } from '@/test/utils/selectorUtils' +import { env } from '@typebot.io/env' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' + +test.describe('Payment input block', () => { + test('Can configure Stripe account', async ({ page }) => { + const typebotId = createId() + await createTypebots([ + { + id: typebotId, + ...parseDefaultGroupWithBlock({ + type: InputBlockType.PAYMENT, + }), + }, + ]) + + await page.goto(`/typebots/${typebotId}/edit`) + await page.click('text=Configure...') + await page.getByRole('button', { name: 'Add Stripe account' }).click() + await page.fill('[placeholder="Typebot"]', 'My Stripe Account') + await page.fill('[placeholder="sk_test_..."]', env.STRIPE_SECRET_KEY ?? '') + await page.fill('[placeholder="sk_live_..."]', env.STRIPE_SECRET_KEY ?? '') + await page.fill( + '[placeholder="pk_test_..."]', + env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY ?? '' + ) + await page.fill( + '[placeholder="pk_live_..."]', + env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY ?? '' + ) + await expect(page.locator('button >> text="Connect"')).toBeEnabled() + await page.click('button >> text="Connect"') + await expect(page.locator('text="Secret test key:"')).toBeHidden() + await expect(page.locator('text="My Stripe Account"')).toBeVisible() + await page.fill('[placeholder="30.00"] >> nth=-1', '30.00') + await page.selectOption('select', 'EUR') + await page.click('text=Additional information') + await page.fill('[placeholder="John Smith"]', 'Baptiste') + await page.fill('[placeholder="john@gmail.com"]', 'test@typebot.io') + await expect(page.locator('text="Phone number:"')).toBeVisible() + + await page.click('text=Test') + await stripePaymentForm(page) + .locator(`[placeholder="1234 1234 1234 1234"]`) + .fill('4000000000000002') + await stripePaymentForm(page) + .locator(`[placeholder="MM / YY"]`) + .fill('12 / 25') + await stripePaymentForm(page).locator(`[placeholder="CVC"]`).fill('240') + await page.getByRole('button', { name: 'Pay 30,00 €' }).click() + await expect( + page.locator(`text="Your card has been declined."`) + ).toBeVisible() + await stripePaymentForm(page) + .locator(`[placeholder="1234 1234 1234 1234"]`) + .fill('4242424242424242') + const zipInput = stripePaymentForm(page).getByPlaceholder('90210') + const isZipInputVisible = await zipInput.isVisible() + if (isZipInputVisible) await zipInput.fill('12345') + await page.getByRole('button', { name: 'Pay 30,00 €' }).click() + await expect(page.locator(`text="Success"`)).toBeVisible() + }) +}) diff --git a/apps/builder/src/features/blocks/inputs/phone/components/CountryCodeSelect.tsx b/apps/builder/src/features/blocks/inputs/phone/components/CountryCodeSelect.tsx new file mode 100644 index 0000000..1f2b200 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/phone/components/CountryCodeSelect.tsx @@ -0,0 +1,236 @@ +import { Select } from '@chakra-ui/react' +import React, { ChangeEvent } from 'react' + +type Props = { + countryCode?: string + onSelect: (countryCode: string) => void +} + +export const CountryCodeSelect = ({ countryCode, onSelect }: Props) => { + const handleOnChange = (e: ChangeEvent) => { + onSelect(e.target.value) + } + return ( + + ) +} diff --git a/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputIcon.tsx b/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputIcon.tsx new file mode 100644 index 0000000..342a746 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputIcon.tsx @@ -0,0 +1,7 @@ +import { PhoneIcon } from '@/components/icons' +import { IconProps } from '@chakra-ui/react' +import React from 'react' + +export const PhoneInputIcon = (props: IconProps) => ( + +) diff --git a/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputSettings.tsx b/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputSettings.tsx new file mode 100644 index 0000000..a4b906c --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/phone/components/PhoneInputSettings.tsx @@ -0,0 +1,71 @@ +import { TextInput } from '@/components/inputs' +import { VariableSearchInput } from '@/components/inputs/VariableSearchInput' +import { FormLabel, Stack } from '@chakra-ui/react' +import { PhoneNumberInputBlock, Variable } from '@typebot.io/schemas' +import React from 'react' +import { CountryCodeSelect } from './CountryCodeSelect' +import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants' + +type Props = { + options: PhoneNumberInputBlock['options'] + onOptionsChange: (options: PhoneNumberInputBlock['options']) => void +} + +export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => { + const handlePlaceholderChange = (placeholder: string) => + onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } }) + const handleButtonLabelChange = (button: string) => + onOptionsChange({ ...options, labels: { ...options?.labels, button } }) + const handleVariableChange = (variable?: Variable) => + onOptionsChange({ ...options, variableId: variable?.id }) + const handleRetryMessageChange = (retryMessageContent: string) => + onOptionsChange({ ...options, retryMessageContent }) + const handleDefaultCountryChange = (defaultCountryCode: string) => + onOptionsChange({ ...options, defaultCountryCode }) + + return ( + + + + + + Default country: + + + + + + + Save answer in a variable: + + + + + ) +} diff --git a/apps/builder/src/features/blocks/inputs/phone/components/PhoneNodeContent.tsx b/apps/builder/src/features/blocks/inputs/phone/components/PhoneNodeContent.tsx new file mode 100644 index 0000000..178721e --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/phone/components/PhoneNodeContent.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { Text } from '@chakra-ui/react' +import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent' +import { PhoneNumberInputBlock } from '@typebot.io/schemas' +import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants' + +type Props = { + options: PhoneNumberInputBlock['options'] +} + +export const PhoneNodeContent = ({ + options: { variableId, labels } = {}, +}: Props) => + variableId ? ( + + ) : ( + + {labels?.placeholder ?? defaultPhoneInputOptions.labels.placeholder} + + ) diff --git a/apps/builder/src/features/blocks/inputs/phone/phone.spec.ts b/apps/builder/src/features/blocks/inputs/phone/phone.spec.ts new file mode 100644 index 0000000..02c2c32 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/phone/phone.spec.ts @@ -0,0 +1,49 @@ +import test, { expect } from '@playwright/test' +import { createTypebots } from '@typebot.io/lib/playwright/databaseActions' +import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers' +import { createId } from '@paralleldrive/cuid2' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' +import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants' + +test.describe('Phone input block', () => { + test('options should work', async ({ page }) => { + const typebotId = createId() + await createTypebots([ + { + id: typebotId, + ...parseDefaultGroupWithBlock({ + type: InputBlockType.PHONE, + }), + }, + ]) + + await page.goto(`/typebots/${typebotId}/edit`) + + await page.click('text=Test') + await expect( + page.locator( + `input[placeholder="${defaultPhoneInputOptions.labels.placeholder}"]` + ) + ).toHaveAttribute('type', 'tel') + await expect(page.getByRole('button', { name: 'Send' })).toBeDisabled() + + await page.click(`text=${defaultPhoneInputOptions.labels.placeholder}`) + await page.getByLabel('Placeholder:').fill('+33 XX XX XX XX') + await page.getByLabel('Button label:').fill('Go') + await page.fill( + `input[value="${defaultPhoneInputOptions.retryMessageContent}"]`, + 'Try again bro' + ) + + await page.click('text=Restart') + await page.locator(`input[placeholder="+33 XX XX XX XX"]`).type('+33 6 73') + await expect(page.getByText('🇫🇷')).toBeVisible() + await page.locator('button >> text="Go"').click() + await expect(page.locator('text=Try again bro')).toBeVisible() + await page + .locator(`input[placeholder="+33 XX XX XX XX"]`) + .fill('+33 6 73 54 45 67') + await page.locator('button >> text="Go"').click() + await expect(page.locator('text=+33 6 73 54 45 67')).toBeVisible() + }) +}) diff --git a/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceIcon.tsx b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceIcon.tsx new file mode 100644 index 0000000..d9a4d34 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceIcon.tsx @@ -0,0 +1,7 @@ +import { ImageIcon } from '@/components/icons' +import { IconProps } from '@chakra-ui/react' +import React from 'react' + +export const PictureChoiceIcon = (props: IconProps) => ( + +) diff --git a/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemNode.tsx b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemNode.tsx new file mode 100644 index 0000000..d6cba62 --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemNode.tsx @@ -0,0 +1,152 @@ +import { + Fade, + IconButton, + Flex, + Image, + Popover, + Portal, + PopoverContent, + PopoverArrow, + PopoverBody, + PopoverAnchor, + useEventListener, + useColorModeValue, +} from '@chakra-ui/react' +import { ImageIcon, PlusIcon } from '@/components/icons' +import { useTypebot } from '@/features/editor/providers/TypebotProvider' +import { ItemIndices } from '@typebot.io/schemas' +import React, { useRef } from 'react' +import { PictureChoiceItem } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice' +import { useGraph } from '@/features/graph/providers/GraphProvider' +import { PictureChoiceItemSettings } from './PictureChoiceItemSettings' +import { isSvgSrc } from '@typebot.io/lib' + +type Props = { + item: PictureChoiceItem + indices: ItemIndices + isMouseOver: boolean +} + +export const PictureChoiceItemNode = ({ + item, + indices, + isMouseOver, +}: Props) => { + const emptyImageBgColor = useColorModeValue('gray.100', 'gray.700') + const { openedItemId, setOpenedItemId } = useGraph() + const { updateItem, createItem, typebot } = useTypebot() + const ref = useRef(null) + + const handlePlusClick = (e: React.MouseEvent) => { + e.stopPropagation() + const itemIndex = indices.itemIndex + 1 + createItem({}, { ...indices, itemIndex }) + } + + const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation() + + const openPopover = () => { + setOpenedItemId(item.id) + } + + const handleItemChange = (updates: Partial) => { + updateItem(indices, { ...item, ...updates }) + } + + const handleMouseWheel = (e: WheelEvent) => { + e.stopPropagation() + } + useEventListener('wheel', handleMouseWheel, ref.current) + + return ( + + + + {item.pictureSrc ? ( + Picture choice image + ) : ( + + + + )} + + } + size="xs" + shadow="md" + colorScheme="gray" + borderWidth={1} + onClick={handlePlusClick} + /> + + + + + + + + {typebot && ( + + )} + + + + + ) +} diff --git a/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemSettings.tsx b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemSettings.tsx new file mode 100644 index 0000000..8edbbee --- /dev/null +++ b/apps/builder/src/features/blocks/inputs/pictureChoice/components/PictureChoiceItemSettings.tsx @@ -0,0 +1,120 @@ +import React from 'react' +import { TextInput, Textarea } from '@/components/inputs' +import { PictureChoiceItem } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice' +import { + Button, + HStack, + Popover, + PopoverContent, + PopoverTrigger, + Stack, + Text, +} from '@chakra-ui/react' +import { ImageUploadContent } from '@/components/ImageUploadContent' +import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings' +import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm' +import { Condition } from '@typebot.io/schemas' +import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants' + +type Props = { + workspaceId: string + typebotId: string + blockId: string + item: PictureChoiceItem + onItemChange: (updates: Partial) => void +} + +export const PictureChoiceItemSettings = ({ + workspaceId, + typebotId, + blockId, + item, + onItemChange, +}: Props) => { + const updateTitle = (title: string) => onItemChange({ ...item, title }) + + const updateImage = (pictureSrc: string) => { + onItemChange({ ...item, pictureSrc }) + } + + const updateDescription = (description: string) => + onItemChange({ ...item, description }) + + const updateIsDisplayConditionEnabled = (isEnabled: boolean) => + onItemChange({ + ...item, + displayCondition: { + ...item.displayCondition, + isEnabled, + }, + }) + + const updateDisplayCondition = (condition: Condition) => + onItemChange({ + ...item, + displayCondition: { + ...item.displayCondition, + condition, + }, + }) + + return ( + + + Image: + + {({ onClose }) => ( + <> + + + + + { + updateImage(url) + onClose() + }} + excludedTabs={['emoji']} + /> + + + )} + + + + +
+ +
+ +

Example: /app/*, /user/*, /admin/settings, /app?param=*

+ +
+ +
+
+ +
+
+ + + +
\ No newline at end of file diff --git a/packages/embeds/wordpress/trunk/includes/class-typebot-activator.php b/packages/embeds/wordpress/trunk/includes/class-typebot-activator.php new file mode 100644 index 0000000..c670d2e --- /dev/null +++ b/packages/embeds/wordpress/trunk/includes/class-typebot-activator.php @@ -0,0 +1,8 @@ +actions = array(); + $this->filters = array(); + $this->shortcodes = array(); + } + + public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) + { + $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args); + } + + public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) + { + $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args); + } + + private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) + { + + $hooks[] = array( + 'hook' => $hook, + 'component' => $component, + 'callback' => $callback, + 'priority' => $priority, + 'accepted_args' => $accepted_args + ); + + return $hooks; + } + + public function run() + { + + foreach ($this->filters as $hook) { + add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']); + } + + foreach ($this->actions as $hook) { + add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']); + } + + foreach ($this->shortcodes as $hook) { + add_shortcode($hook['hook'], array($hook['component'], $hook['callback'])); + } + } + + public function add_shortcode($tag, $component, $callback, $priority = 10, $accepted_args = 2) + { + $this->shortcodes = $this->add($this->shortcodes, $tag, $component, $callback, $priority, $accepted_args); + } +} diff --git a/packages/embeds/wordpress/trunk/includes/class-typebot.php b/packages/embeds/wordpress/trunk/includes/class-typebot.php new file mode 100644 index 0000000..e3f14ec --- /dev/null +++ b/packages/embeds/wordpress/trunk/includes/class-typebot.php @@ -0,0 +1,75 @@ +version = TYPEBOT_VERSION; + } else { + $this->version = '1.0.0'; + } + $this->plugin_name = 'typebot'; + + $this->load_dependencies(); + $this->set_locale(); + $this->define_admin_hooks(); + $this->define_public_hooks(); + } + + private function load_dependencies() + { + + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-typebot-loader.php'; + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-typebot-i18n.php'; + require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-typebot-admin.php'; + require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-typebot-public.php'; + + $this->loader = new Typebot_Loader(); + } + + private function set_locale() + { + $plugin_i18n = new Typebot_i18n(); + $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain'); + } + + private function define_admin_hooks() + { + $plugin_admin = new Typebot_Admin($this->get_version()); + $this->loader->add_action('admin_menu', $plugin_admin, 'my_admin_menu'); + $this->loader->add_action('admin_init', $plugin_admin, 'register_typebot_settings'); + } + + private function define_public_hooks() + { + $plugin_public = new Typebot_Public($this->get_plugin_name(), $this->get_version()); + $this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'add_head_code'); + $this->loader->add_shortcode('typebot', $plugin_public, 'add_typebot_container'); + } + + public function run() + { + $this->loader->run(); + } + + public function get_plugin_name() + { + return $this->plugin_name; + } + + public function get_loader() + { + return $this->loader; + } + + public function get_version() + { + return $this->version; + } +} diff --git a/packages/embeds/wordpress/trunk/includes/index.php b/packages/embeds/wordpress/trunk/includes/index.php new file mode 100644 index 0000000..e71af0e --- /dev/null +++ b/packages/embeds/wordpress/trunk/includes/index.php @@ -0,0 +1 @@ + + if(typeof window.typebotWpUser === "undefined"){ + window.typebotWpUser = { + "WP ID":"' . + $wp_user->ID . + '", + "WP Username":"' . + $wp_user->user_login . + '", + "WP Email":"' . + $wp_user->user_email . + '", + "WP First name":"' . + $wp_user->user_firstname . + '", + "WP Last name":"' . + $wp_user->user_lastname . + '" + } + } + '; + } + + public function add_head_code() + { + $this->parse_wp_user(); + } + + function typebot_script() + { + echo ''; + } + + public function add_typebot_container($attributes = []) + { + $lib_version = '0.2'; + if(array_key_exists('lib_version', $attributes)) { + $lib_version = sanitize_text_field($attributes['lib_version']); + } + $lib_url = "https://cdn.jsdelivr.net/npm/@typebot.io/js@". $lib_version ."/dist/web.js"; + $width = '100%'; + $height = '500px'; + $api_host = 'https://typebot.io'; + if (array_key_exists('width', $attributes)) { + $width = sanitize_text_field($attributes['width']); + } + if (array_key_exists('height', $attributes)) { + $height = sanitize_text_field($attributes['height']); + } + if (array_key_exists('typebot', $attributes)) { + $typebot = sanitize_text_field($attributes['typebot']); + } + if (array_key_exists('host', $attributes)) { + $api_host = sanitize_text_field($attributes['host']); + } + if (!$typebot) { + return; + } + + $id = $this->generateRandomString(); + + $bot_initializer = ''; + + return '' . $bot_initializer; + } + + private function generateRandomString($length = 10) + { + return substr( + str_shuffle( + str_repeat( + $x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', + ceil($length / strlen($x)) + ) + ), + 1, + $length + ); + } +} diff --git a/packages/embeds/wordpress/trunk/public/index.php b/packages/embeds/wordpress/trunk/public/index.php new file mode 100644 index 0000000..e71af0e --- /dev/null +++ b/packages/embeds/wordpress/trunk/public/index.php @@ -0,0 +1 @@ +run(); +} +run_typebot(); diff --git a/packages/embeds/wordpress/trunk/uninstall.php b/packages/embeds/wordpress/trunk/uninstall.php new file mode 100644 index 0000000..86ddbb4 --- /dev/null +++ b/packages/embeds/wordpress/trunk/uninstall.php @@ -0,0 +1,5 @@ + { + if ( + (val && typeof val === 'string' && val.length > 0) || + process.env.VERCEL_ENV !== 'preview' || + !process.env.VERCEL_BUILDER_PROJECT_NAME || + !process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) + return val + const isBuilder = (process.env.VERCEL_BRANCH_URL as string).includes( + process.env.VERCEL_BUILDER_PROJECT_NAME + ) + if (isBuilder) return `https://${process.env.VERCEL_BRANCH_URL}` + return `https://${process.env.VERCEL_BRANCH_URL}`.replace( + process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME, + process.env.VERCEL_BUILDER_PROJECT_NAME + ) +} + +const guessViewerUrlForVercelPreview = (val: unknown) => { + if ( + (val && typeof val === 'string' && val.length > 0) || + process.env.VERCEL_ENV !== 'preview' || + !process.env.VERCEL_BUILDER_PROJECT_NAME || + !process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) + return val + const isViewer = (process.env.VERCEL_BRANCH_URL as string).includes( + process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) + if (isViewer) return `https://${process.env.VERCEL_BRANCH_URL}` + return `https://${process.env.VERCEL_BRANCH_URL}`.replace( + process.env.VERCEL_BUILDER_PROJECT_NAME, + process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME + ) +} + +const boolean = z.enum(['true', 'false']).transform((value) => value === 'true') + +const baseEnv = { + server: { + NODE_ENV: z.enum(['development', 'production', 'test']).optional(), + DATABASE_URL: z + .string() + .url() + .refine((url) => url.startsWith('postgres') || url.startsWith('mysql')), + ENCRYPTION_SECRET: z.string().length(32), + NEXTAUTH_URL: z.preprocess( + guessNextAuthUrlForVercelPreview, + z.string().url() + ), + DISABLE_SIGNUP: boolean.optional().default('false'), + ADMIN_EMAIL: z.string().email().optional(), + DEFAULT_WORKSPACE_PLAN: z + .enum(['FREE', 'STARTER', 'PRO', 'LIFETIME', 'UNLIMITED']) + .refine((str) => + ['FREE', 'STARTER', 'PRO', 'LIFETIME', 'UNLIMITED'].includes(str) + ) + .default('FREE'), + DEBUG: boolean.optional().default('false'), + CHAT_API_TIMEOUT: z.coerce.number().optional(), + RADAR_HIGH_RISK_KEYWORDS: z + .string() + .min(1) + .transform((val) => val.split(',')) + .optional(), + RADAR_INTERMEDIATE_RISK_KEYWORDS: z + .string() + .min(1) + .transform((val) => val.split(',')) + .optional(), + }, + client: { + NEXT_PUBLIC_E2E_TEST: boolean.optional(), + NEXT_PUBLIC_VIEWER_URL: z.preprocess( + guessViewerUrlForVercelPreview, + z + .string() + .min(1) + .transform((val) => val.split(',')) + ), + NEXT_PUBLIC_ONBOARDING_TYPEBOT_ID: z.string().min(1).optional(), + NEXT_PUBLIC_BOT_FILE_UPLOAD_MAX_SIZE: z.coerce.number().optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_E2E_TEST: getRuntimeVariable('NEXT_PUBLIC_E2E_TEST'), + NEXT_PUBLIC_VIEWER_URL: getRuntimeVariable('NEXT_PUBLIC_VIEWER_URL'), + NEXT_PUBLIC_ONBOARDING_TYPEBOT_ID: getRuntimeVariable( + 'NEXT_PUBLIC_ONBOARDING_TYPEBOT_ID' + ), + NEXT_PUBLIC_BOT_FILE_UPLOAD_MAX_SIZE: getRuntimeVariable( + 'NEXT_PUBLIC_BOT_FILE_UPLOAD_MAX_SIZE' + ), + }, +} +const githubEnv = { + server: { + GITHUB_CLIENT_ID: z.string().min(1).optional(), + GITHUB_CLIENT_SECRET: z.string().min(1).optional(), + }, +} + +const facebookEnv = { + server: { + FACEBOOK_CLIENT_ID: z.string().min(1).optional(), + FACEBOOK_CLIENT_SECRET: z.string().min(1).optional(), + }, +} + +const smtpEnv = { + server: { + SMTP_USERNAME: z.string().min(1).optional(), + SMTP_PASSWORD: z.string().min(1).optional(), + SMTP_HOST: z.string().min(1).optional(), + SMTP_PORT: z.coerce.number().optional().default(25), + SMTP_AUTH_DISABLED: boolean.optional().default('false'), + SMTP_SECURE: boolean.optional().default('false'), + }, + client: { + NEXT_PUBLIC_SMTP_FROM: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_SMTP_FROM: getRuntimeVariable('NEXT_PUBLIC_SMTP_FROM'), + }, +} + +const gitlabEnv = { + server: { + GITLAB_CLIENT_ID: z.string().min(1).optional(), + GITLAB_CLIENT_SECRET: z.string().min(1).optional(), + GITLAB_BASE_URL: z.string().url().optional().default('https://gitlab.com'), + GITLAB_NAME: z.string().min(1).optional().default('GitLab'), + GITLAB_REQUIRED_GROUPS: z + .string() + .transform((string) => (string ? string.split(',') : undefined)) + .optional(), + }, +} + +const azureEnv = { + server: { + AZURE_AD_CLIENT_ID: z.string().min(1).optional(), + AZURE_AD_CLIENT_SECRET: z.string().min(1).optional(), + AZURE_AD_TENANT_ID: z.string().min(1).optional(), + }, +} + +const customOAuthEnv = { + server: { + CUSTOM_OAUTH_NAME: z.string().min(1).optional().default('Custom OAuth'), + CUSTOM_OAUTH_SCOPE: z + .string() + .min(1) + .optional() + .default('openid profile email'), + CUSTOM_OAUTH_CLIENT_ID: z.string().min(1).optional(), + CUSTOM_OAUTH_CLIENT_SECRET: z.string().min(1).optional(), + CUSTOM_OAUTH_WELL_KNOWN_URL: z.string().url().optional(), + CUSTOM_OAUTH_USER_ID_PATH: z.string().min(1).optional().default('id'), + CUSTOM_OAUTH_USER_EMAIL_PATH: z.string().min(1).optional().default('email'), + CUSTOM_OAUTH_USER_NAME_PATH: z.string().min(1).optional().default('name'), + CUSTOM_OAUTH_USER_IMAGE_PATH: z.string().min(1).optional().default('image'), + }, +} + +const googleEnv = { + server: { + GOOGLE_CLIENT_ID: z.string().min(1).optional(), + GOOGLE_CLIENT_SECRET: z.string().min(1).optional(), + }, + client: { + NEXT_PUBLIC_GOOGLE_API_KEY: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_GOOGLE_API_KEY: getRuntimeVariable( + 'NEXT_PUBLIC_GOOGLE_API_KEY' + ), + }, +} + +const stripeEnv = { + server: { + STRIPE_SECRET_KEY: z.string().min(1).optional(), + STRIPE_WEBHOOK_SECRET: z.string().min(1).optional(), + STRIPE_STARTER_PRICE_ID: z.string().min(1).optional(), + STRIPE_STARTER_CHATS_PRICE_ID: z.string().min(1).optional(), + STRIPE_PRO_PRICE_ID: z.string().min(1).optional(), + STRIPE_PRO_CHATS_PRICE_ID: z.string().min(1).optional(), + }, + client: { + NEXT_PUBLIC_STRIPE_PUBLIC_KEY: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_STRIPE_PUBLIC_KEY: getRuntimeVariable( + 'NEXT_PUBLIC_STRIPE_PUBLIC_KEY' + ), + }, +} + +const s3Env = { + server: { + S3_ACCESS_KEY: z.string().min(1).optional(), + S3_SECRET_KEY: z.string().min(1).optional(), + S3_BUCKET: z.string().min(1).optional().default('typebot'), + S3_PORT: z.coerce.number().optional(), + S3_ENDPOINT: z.string().min(1).optional(), + S3_SSL: boolean.optional().default('true'), + S3_REGION: z.string().min(1).optional(), + S3_PUBLIC_CUSTOM_DOMAIN: z.string().url().optional(), + }, +} + +const giphyEnv = { + client: { + NEXT_PUBLIC_GIPHY_API_KEY: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_GIPHY_API_KEY: getRuntimeVariable('NEXT_PUBLIC_GIPHY_API_KEY'), + }, +} + +const vercelEnv = { + server: { + VERCEL_TOKEN: z.string().min(1).optional(), + VERCEL_TEAM_ID: z.string().min(1).optional(), + VERCEL_GIT_COMMIT_SHA: z.string().min(1).optional(), + VERCEL_BUILDER_PROJECT_NAME: z.string().min(1).optional(), + }, + client: { + NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME: z.string().min(1).optional(), + NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: z.string().min(1).optional(), + NEXT_PUBLIC_VERCEL_ENV: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME: getRuntimeVariable( + 'NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME' + ), + NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: getRuntimeVariable( + 'NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA' + ), + NEXT_PUBLIC_VERCEL_ENV: getRuntimeVariable('NEXT_PUBLIC_VERCEL_ENV'), + }, +} + +const sleekPlanEnv = { + server: { + SLEEKPLAN_SSO_KEY: z.string().min(1).optional(), + }, +} + +const unsplashEnv = { + client: { + NEXT_PUBLIC_UNSPLASH_APP_NAME: z.string().min(1).optional(), + NEXT_PUBLIC_UNSPLASH_ACCESS_KEY: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_UNSPLASH_APP_NAME: getRuntimeVariable( + 'NEXT_PUBLIC_UNSPLASH_APP_NAME' + ), + NEXT_PUBLIC_UNSPLASH_ACCESS_KEY: getRuntimeVariable( + 'NEXT_PUBLIC_UNSPLASH_ACCESS_KEY' + ), + }, +} + +const whatsAppEnv = { + server: { + META_SYSTEM_USER_TOKEN: z.string().min(1).optional(), + WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID: z.string().min(1).optional(), + WHATSAPP_PREVIEW_TEMPLATE_NAME: z.string().min(1).optional(), + WHATSAPP_PREVIEW_TEMPLATE_LANG: z.string().min(1).optional().default('en'), + }, +} + +const upstashRedis = { + server: { + UPSTASH_REDIS_REST_URL: z.string().url().optional(), + UPSTASH_REDIS_REST_TOKEN: z.string().min(1).optional(), + }, +} + +const sentryEnv = { + client: { + NEXT_PUBLIC_SENTRY_DSN: z.string().min(1).optional(), + }, + server: { + SENTRY_AUTH_TOKEN: z.string().min(1).optional(), + SENTRY_PROJECT: z.string().min(1).optional(), + SENTRY_ORG: z.string().min(1).optional(), + }, + runtimeEnv: { + NEXT_PUBLIC_SENTRY_DSN: getRuntimeVariable('NEXT_PUBLIC_SENTRY_DSN'), + }, +} + +const telemetryEnv = { + server: { + TELEMETRY_WEBHOOK_URL: z.string().url().optional(), + TELEMETRY_WEBHOOK_BEARER_TOKEN: z.string().min(1).optional(), + MESSAGE_WEBHOOK_URL: z.string().url().optional(), + USER_CREATED_WEBHOOK_URL: z.string().url().optional(), + }, +} + +const posthogEnv = { + client: { + NEXT_PUBLIC_POSTHOG_KEY: z.string().min(1).optional(), + NEXT_PUBLIC_POSTHOG_HOST: z + .string() + .min(1) + .optional() + .default('https://app.posthog.com'), + }, + runtimeEnv: { + NEXT_PUBLIC_POSTHOG_KEY: getRuntimeVariable('NEXT_PUBLIC_POSTHOG_KEY'), + NEXT_PUBLIC_POSTHOG_HOST: getRuntimeVariable('NEXT_PUBLIC_POSTHOG_HOST'), + }, +} + +const tolgeeEnv = { + client: { + NEXT_PUBLIC_TOLGEE_API_KEY: z.string().min(1).optional(), + NEXT_PUBLIC_TOLGEE_API_URL: z + .string() + .url() + .optional() + .default('https://tolgee.server.baptistearno.com"'), + }, + runtimeEnv: { + NEXT_PUBLIC_TOLGEE_API_KEY: getRuntimeVariable( + 'NEXT_PUBLIC_TOLGEE_API_KEY' + ), + NEXT_PUBLIC_TOLGEE_API_URL: getRuntimeVariable( + 'NEXT_PUBLIC_TOLGEE_API_URL', + 'https://tolgee.server.baptistearno.com' + ), + }, +} + +export const env = createEnv({ + server: { + ...baseEnv.server, + ...githubEnv.server, + ...facebookEnv.server, + ...smtpEnv.server, + ...googleEnv.server, + ...stripeEnv.server, + ...s3Env.server, + ...vercelEnv.server, + ...sleekPlanEnv.server, + ...whatsAppEnv.server, + ...upstashRedis.server, + ...gitlabEnv.server, + ...azureEnv.server, + ...customOAuthEnv.server, + ...sentryEnv.server, + ...telemetryEnv.server, + }, + client: { + ...baseEnv.client, + ...smtpEnv.client, + ...googleEnv.client, + ...stripeEnv.client, + ...giphyEnv.client, + ...vercelEnv.client, + ...unsplashEnv.client, + ...sentryEnv.client, + ...posthogEnv.client, + ...tolgeeEnv.client, + }, + experimental__runtimeEnv: { + ...baseEnv.runtimeEnv, + ...smtpEnv.runtimeEnv, + ...googleEnv.runtimeEnv, + ...stripeEnv.runtimeEnv, + ...giphyEnv.runtimeEnv, + ...vercelEnv.runtimeEnv, + ...unsplashEnv.runtimeEnv, + ...sentryEnv.runtimeEnv, + ...posthogEnv.runtimeEnv, + ...tolgeeEnv.runtimeEnv, + }, + skipValidation: + process.env.SKIP_ENV_CHECK === 'true' || + (typeof window !== 'undefined' && window.__ENV === undefined), + onValidationError(error) { + console.error( + '❌ Invalid environment variables:', + error.flatten().fieldErrors + ) + throw new Error( + `Invalid environment variables: ${JSON.stringify( + error.flatten().fieldErrors + )}` + ) + }, + onInvalidAccess: (variable: string) => { + throw new Error( + `❌ Attempted to access a server-side environment variable on the client: ${variable}` + ) + }, +}) diff --git a/packages/env/getRuntimeVariable.ts b/packages/env/getRuntimeVariable.ts new file mode 100644 index 0000000..7841564 --- /dev/null +++ b/packages/env/getRuntimeVariable.ts @@ -0,0 +1,10 @@ +declare const window: { + __ENV?: any +} + +export const getRuntimeVariable = (key: string, defaultValue?: string) => { + if (typeof window !== 'undefined') + return window.__ENV ? window.__ENV[key] ?? defaultValue : undefined + if (typeof process === 'undefined') return undefined + return process.env[key] ?? defaultValue +} diff --git a/packages/env/package.json b/packages/env/package.json new file mode 100644 index 0000000..2cddff3 --- /dev/null +++ b/packages/env/package.json @@ -0,0 +1,20 @@ +{ + "name": "@typebot.io/env", + "version": "1.0.0", + "license": "AGPL-3.0-or-later", + "private": true, + "main": "./env.ts", + "types": "./env.ts", + "dependencies": { + "@t3-oss/env-nextjs": "^0.7.0", + "zod": "3.22.4" + }, + "devDependencies": { + "@typebot.io/tsconfig": "workspace:*", + "@types/node": "20.4.9", + "esbuild": "0.19.5" + }, + "scripts": { + "build": "esbuild env.ts --bundle --packages=external --format=esm --outfile=dist/env.mjs" + } +} diff --git a/packages/env/tsconfig.json b/packages/env/tsconfig.json new file mode 100644 index 0000000..57c1b52 --- /dev/null +++ b/packages/env/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/eslint-config-custom/index.js b/packages/eslint-config-custom/index.js new file mode 100644 index 0000000..a57c925 --- /dev/null +++ b/packages/eslint-config-custom/index.js @@ -0,0 +1,18 @@ +module.exports = { + extends: [ + 'next', + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + settings: { + react: { + version: 'detect', + }, + }, + rules: { + '@typescript-eslint/no-namespace': 'off', + }, +} diff --git a/packages/eslint-config-custom/package.json b/packages/eslint-config-custom/package.json new file mode 100644 index 0000000..30fec07 --- /dev/null +++ b/packages/eslint-config-custom/package.json @@ -0,0 +1,15 @@ +{ + "name": "eslint-config-custom", + "version": "0.0.1", + "main": "index.js", + "dependencies": { + "eslint": "8.44.0", + "eslint-config-next": "13.4.9", + "eslint-config-prettier": "8.8.0", + "eslint-plugin-react": "7.32.2" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "6.0.0", + "@typescript-eslint/parser": "6.0.0" + } +} diff --git a/packages/forge/blocks/calCom/actions/bookEvent.ts b/packages/forge/blocks/calCom/actions/bookEvent.ts new file mode 100644 index 0000000..5ce62de --- /dev/null +++ b/packages/forge/blocks/calCom/actions/bookEvent.ts @@ -0,0 +1,126 @@ +import { createAction, option } from '@typebot.io/forge' +import { baseOptions } from '../baseOptions' +import { defaultBaseUrl } from '../constants' + +export const bookEvent = createAction({ + name: 'Book event', + baseOptions, + options: option.object({ + link: option.string.layout({ + label: 'Event link', + placeholder: 'https://cal.com/...', + }), + layout: option + .enum(['Month', 'Weekly', 'Columns']) + .layout({ label: 'Layout:', defaultValue: 'Month', direction: 'row' }), + name: option.string.layout({ + accordion: 'Prefill information', + label: 'Name', + placeholder: 'John Doe', + }), + email: option.string.layout({ + accordion: 'Prefill information', + label: 'Email', + placeholder: 'johndoe@gmail.com', + }), + saveBookedDateInVariableId: option.string.layout({ + label: 'Save booked date', + input: 'variableDropdown', + }), + }), + getSetVariableIds: ({ saveBookedDateInVariableId }) => + saveBookedDateInVariableId ? [saveBookedDateInVariableId] : [], + run: { + web: { + displayEmbedBubble: { + waitForEvent: { + getSaveVariableId: ({ saveBookedDateInVariableId }) => + saveBookedDateInVariableId, + parseFunction: () => { + return { + args: {}, + content: `Cal("on", { + action: "bookingSuccessful", + callback: (e) => { + continueFlow(e.detail.data.date) + } + })`, + } + }, + }, + parseInitFunction: ({ options }) => { + if (!options.link) throw new Error('Missing link') + const baseUrl = options.baseUrl ?? defaultBaseUrl + const link = options.link?.startsWith('http') + ? options.link.replace(/http.+:\/\/[^\/]+\//, '') + : options.link + return { + args: { + baseUrl, + link: link ?? '', + name: options.name ?? null, + email: options.email ?? null, + layout: parseLayoutAttr(options.layout), + }, + content: `(function (C, A, L) { + let p = function (a, ar) { + a.q.push(ar); + }; + let d = C.document; + C.Cal = + C.Cal || + function () { + let cal = C.Cal; + let ar = arguments; + if (!cal.loaded) { + cal.ns = {}; + cal.q = cal.q || []; + d.head.appendChild(d.createElement("script")).src = A; + cal.loaded = true; + } + if (ar[0] === L) { + const api = function () { + p(api, arguments); + }; + const namespace = ar[1]; + api.q = api.q || []; + typeof namespace === "string" + ? (cal.ns[namespace] = api) && p(api, ar) + : p(cal, ar); + return; + } + p(cal, ar); + }; + })(window, baseUrl + "/embed/embed.js", "init"); + Cal("init", { origin: baseUrl }); + + Cal("inline", { + elementOrSelector: typebotElement, + calLink: link, + layout, + config: { + name: name ?? undefined, + email: email ?? undefined, + } + }); + + Cal("ui", {"hideEventTypeDetails":false,layout});`, + } + }, + }, + }, + }, +}) + +const parseLayoutAttr = ( + layout?: 'Month' | 'Weekly' | 'Columns' +): 'month_view' | 'week_view' | 'column_view' => { + switch (layout) { + case 'Weekly': + return 'week_view' + case 'Columns': + return 'column_view' + default: + return 'month_view' + } +} diff --git a/packages/forge/blocks/calCom/baseOptions.ts b/packages/forge/blocks/calCom/baseOptions.ts new file mode 100644 index 0000000..cc423e5 --- /dev/null +++ b/packages/forge/blocks/calCom/baseOptions.ts @@ -0,0 +1,11 @@ +import { option } from '@typebot.io/forge' +import { defaultBaseUrl } from './constants' + +export const baseOptions = option.object({ + baseUrl: option.string.layout({ + label: 'Base origin', + placeholder: 'https://cal.com', + defaultValue: defaultBaseUrl, + accordion: 'Customize host', + }), +}) diff --git a/packages/forge/blocks/calCom/constants.ts b/packages/forge/blocks/calCom/constants.ts new file mode 100644 index 0000000..4b8747b --- /dev/null +++ b/packages/forge/blocks/calCom/constants.ts @@ -0,0 +1 @@ +export const defaultBaseUrl = 'https://app.cal.com' diff --git a/packages/forge/blocks/calCom/index.ts b/packages/forge/blocks/calCom/index.ts new file mode 100644 index 0000000..d965419 --- /dev/null +++ b/packages/forge/blocks/calCom/index.ts @@ -0,0 +1,13 @@ +import { createBlock } from '@typebot.io/forge' +import { CalComLogo } from './logo' +import { bookEvent } from './actions/bookEvent' +import { baseOptions } from './baseOptions' + +export const calCom = createBlock({ + id: 'cal-com', + name: 'Cal.com', + tags: ['calendar', 'scheduling', 'meetings'], + LightLogo: CalComLogo, + options: baseOptions, + actions: [bookEvent], +}) diff --git a/packages/forge/blocks/calCom/logo.tsx b/packages/forge/blocks/calCom/logo.tsx new file mode 100644 index 0000000..39f211a --- /dev/null +++ b/packages/forge/blocks/calCom/logo.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +export const CalComLogo = (props: React.SVGProps) => ( + + + + + + +) diff --git a/packages/forge/blocks/calCom/package.json b/packages/forge/blocks/calCom/package.json new file mode 100644 index 0000000..b4e4ef7 --- /dev/null +++ b/packages/forge/blocks/calCom/package.json @@ -0,0 +1,15 @@ +{ + "name": "@typebot.io/cal-com-block", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "license": "ISC", + "devDependencies": { + "@typebot.io/forge": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@types/react": "18.2.15", + "typescript": "5.3.2", + "@typebot.io/lib": "workspace:*" + } +} diff --git a/packages/forge/blocks/calCom/tsconfig.json b/packages/forge/blocks/calCom/tsconfig.json new file mode 100644 index 0000000..1eb9c77 --- /dev/null +++ b/packages/forge/blocks/calCom/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "noEmit": true, + "jsx": "react" + } +} diff --git a/packages/forge/blocks/chatNode/actions/sendMessage.ts b/packages/forge/blocks/chatNode/actions/sendMessage.ts new file mode 100644 index 0000000..01e2ecd --- /dev/null +++ b/packages/forge/blocks/chatNode/actions/sendMessage.ts @@ -0,0 +1,63 @@ +import { createAction, option } from '@typebot.io/forge' +import { isDefined, isEmpty } from '@typebot.io/lib' +import { got } from 'got' +import { apiBaseUrl } from '../constants' +import { auth } from '../auth' +import { ChatNodeResponse } from '../types' + +export const sendMessage = createAction({ + auth, + name: 'Send Message', + options: option.object({ + botId: option.string.layout({ + label: 'Bot ID', + placeholder: '68c052c5c3680f63', + moreInfoTooltip: + 'The bot_id you want to ask question to. You can find it at the end of your ChatBot URl in your dashboard', + }), + threadId: option.string.layout({ + label: 'Thread ID', + moreInfoTooltip: + 'Used to remember the conversation with the user. If empty, a new thread is created.', + }), + message: option.string.layout({ + label: 'Message', + placeholder: 'Hi, what can I do with ChatNode', + input: 'textarea', + }), + responseMapping: option.saveResponseArray(['Message', 'Thread ID']).layout({ + accordion: 'Save response', + }), + }), + getSetVariableIds: ({ responseMapping }) => + responseMapping?.map((r) => r.variableId).filter(isDefined) ?? [], + run: { + server: async ({ + credentials: { apiKey }, + options: { botId, message, responseMapping, threadId }, + variables, + }) => { + const res: ChatNodeResponse = await got + .post(apiBaseUrl + botId, { + headers: { + Authorization: `Bearer ${apiKey}`, + }, + json: { + message, + chat_session_id: isEmpty(threadId) ? undefined : threadId, + }, + }) + .json() + + responseMapping?.forEach((mapping) => { + if (!mapping.variableId) return + + const item = mapping.item ?? 'Message' + if (item === 'Message') variables.set(mapping.variableId, res.message) + + if (item === 'Thread ID') + variables.set(mapping.variableId, res.chat_session_id) + }) + }, + }, +}) diff --git a/packages/forge/blocks/chatNode/auth.ts b/packages/forge/blocks/chatNode/auth.ts new file mode 100644 index 0000000..204f086 --- /dev/null +++ b/packages/forge/blocks/chatNode/auth.ts @@ -0,0 +1,15 @@ +import { option, AuthDefinition } from '@typebot.io/forge' + +export const auth = { + type: 'encryptedCredentials', + name: 'ChatNode account', + schema: option.object({ + apiKey: option.string.layout({ + label: 'API key', + isRequired: true, + helperText: + 'You can generate an API key [here](https://go.chatnode.ai/typebot).', + input: 'password', + }), + }), +} satisfies AuthDefinition diff --git a/packages/forge/blocks/chatNode/constants.ts b/packages/forge/blocks/chatNode/constants.ts new file mode 100644 index 0000000..b465cee --- /dev/null +++ b/packages/forge/blocks/chatNode/constants.ts @@ -0,0 +1 @@ +export const apiBaseUrl = 'https://api.public.chatnode.ai/v1/' diff --git a/packages/forge/blocks/chatNode/index.ts b/packages/forge/blocks/chatNode/index.ts new file mode 100644 index 0000000..6a8c902 --- /dev/null +++ b/packages/forge/blocks/chatNode/index.ts @@ -0,0 +1,13 @@ +import { createBlock } from '@typebot.io/forge' +import { ChatNodeLogo } from './logo' +import { auth } from './auth' +import { sendMessage } from './actions/sendMessage' + +export const chatNode = createBlock({ + id: 'chat-node', + name: 'ChatNode', + tags: ['ai', 'openai', 'document', 'url'], + LightLogo: ChatNodeLogo, + auth, + actions: [sendMessage], +}) diff --git a/packages/forge/blocks/chatNode/logo.tsx b/packages/forge/blocks/chatNode/logo.tsx new file mode 100644 index 0000000..965455d --- /dev/null +++ b/packages/forge/blocks/chatNode/logo.tsx @@ -0,0 +1,10 @@ +import React from 'react' + +export const ChatNodeLogo = (props: React.SVGProps) => ( + + + +) diff --git a/packages/forge/blocks/chatNode/package.json b/packages/forge/blocks/chatNode/package.json new file mode 100644 index 0000000..d1eb640 --- /dev/null +++ b/packages/forge/blocks/chatNode/package.json @@ -0,0 +1,16 @@ +{ + "name": "@typebot.io/chat-node-block", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "license": "ISC", + "devDependencies": { + "@typebot.io/forge": "workspace:*", + "@typebot.io/lib": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@types/react": "18.2.15", + "typescript": "5.3.2", + "got": "12.6.0" + } +} diff --git a/packages/forge/blocks/chatNode/tsconfig.json b/packages/forge/blocks/chatNode/tsconfig.json new file mode 100644 index 0000000..1eb9c77 --- /dev/null +++ b/packages/forge/blocks/chatNode/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "noEmit": true, + "jsx": "react" + } +} diff --git a/packages/forge/blocks/chatNode/types.ts b/packages/forge/blocks/chatNode/types.ts new file mode 100644 index 0000000..d3c0b91 --- /dev/null +++ b/packages/forge/blocks/chatNode/types.ts @@ -0,0 +1,4 @@ +export type ChatNodeResponse = { + message: string + chat_session_id: string +} diff --git a/packages/forge/blocks/openai/actions/createChatCompletion.tsx b/packages/forge/blocks/openai/actions/createChatCompletion.tsx new file mode 100644 index 0000000..54d6396 --- /dev/null +++ b/packages/forge/blocks/openai/actions/createChatCompletion.tsx @@ -0,0 +1,181 @@ +import { option, createAction } from '@typebot.io/forge' +import OpenAI, { ClientOptions } from 'openai' +import { defaultOpenAIOptions } from '../constants' +import { OpenAIStream } from 'ai' +import { parseChatCompletionMessages } from '../helpers/parseChatCompletionMessages' +import { isDefined } from '@typebot.io/lib' +import { auth } from '../auth' +import { baseOptions } from '../baseOptions' + +const nativeMessageContentSchema = { + content: option.string.layout({ input: 'textarea', placeholder: 'Content' }), +} + +const systemMessageItemSchema = option + .object({ + role: option.literal('system'), + }) + .extend(nativeMessageContentSchema) + +const userMessageItemSchema = option + .object({ + role: option.literal('user'), + }) + .extend(nativeMessageContentSchema) + +const assistantMessageItemSchema = option + .object({ + role: option.literal('assistant'), + }) + .extend(nativeMessageContentSchema) + +const dialogueMessageItemSchema = option.object({ + role: option.literal('Dialogue'), + dialogueVariableId: option.string.layout({ + input: 'variableDropdown', + placeholder: 'Dialogue variable', + }), + startsBy: option.enum(['user', 'assistant']).layout({ + label: 'starts by', + direction: 'row', + defaultValue: 'user', + }), +}) + +export const options = option.object({ + model: option.string.layout({ + placeholder: 'Select a model', + defaultValue: defaultOpenAIOptions.model, + fetcher: 'fetchModels', + }), + messages: option + .array( + option.discriminatedUnion('role', [ + systemMessageItemSchema, + userMessageItemSchema, + assistantMessageItemSchema, + dialogueMessageItemSchema, + ]) + ) + .layout({ accordion: 'Messages', itemLabel: 'message', isOrdered: true }), + temperature: option.number.layout({ + accordion: 'Advanced settings', + label: 'Temperature', + direction: 'row', + defaultValue: defaultOpenAIOptions.temperature, + }), + responseMapping: option + .saveResponseArray(['Message content', 'Total tokens']) + .layout({ + accordion: 'Save response', + }), +}) + +export const createChatCompletion = createAction({ + name: 'Create chat completion', + auth, + baseOptions, + getSetVariableIds: (options) => + options.responseMapping?.map((res) => res.variableId).filter(isDefined) ?? + [], + fetchers: [ + { + id: 'fetchModels', + dependencies: ['baseUrl', 'apiVersion'], + fetch: async ({ credentials, options }) => { + const baseUrl = options?.baseUrl ?? defaultOpenAIOptions.baseUrl + const config = { + apiKey: credentials.apiKey, + baseURL: baseUrl ?? defaultOpenAIOptions.baseUrl, + defaultHeaders: { + 'api-key': credentials.apiKey, + }, + defaultQuery: options?.apiVersion + ? { + 'api-version': options.apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + const models = await openai.models.list() + + return ( + models.data + .filter((model) => model.id.includes('gpt')) + .sort((a, b) => b.created - a.created) + .map((model) => model.id) ?? [] + ) + }, + }, + ], + run: { + server: async ({ credentials: { apiKey }, options, variables }) => { + const config = { + apiKey, + baseURL: options.baseUrl, + defaultHeaders: { + 'api-key': apiKey, + }, + defaultQuery: options.apiVersion + ? { + 'api-version': options.apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + const response = await openai.chat.completions.create({ + model: options.model ?? defaultOpenAIOptions.model, + temperature: options.temperature + ? Number(options.temperature) + : undefined, + messages: parseChatCompletionMessages({ options, variables }), + }) + + options.responseMapping?.forEach((mapping) => { + if (!mapping.variableId) return + if (!mapping.item || mapping.item === 'Message content') + variables.set(mapping.variableId, response.choices[0].message.content) + if (mapping.item === 'Total tokens') + variables.set(mapping.variableId, response.usage?.total_tokens) + }) + }, + stream: { + getStreamVariableId: (options) => + options.responseMapping?.find( + (res) => res.item === 'Message content' || !res.item + )?.variableId, + run: async ({ credentials: { apiKey }, options, variables }) => { + const config = { + apiKey, + baseURL: options.baseUrl, + defaultHeaders: { + 'api-key': apiKey, + }, + defaultQuery: options.apiVersion + ? { + 'api-version': options.apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + const response = await openai.chat.completions.create({ + model: options.model ?? defaultOpenAIOptions.model, + temperature: options.temperature + ? Number(options.temperature) + : undefined, + stream: true, + messages: parseChatCompletionMessages({ options, variables }), + }) + + return OpenAIStream(response) + }, + }, + }, + options, +}) diff --git a/packages/forge/blocks/openai/actions/createSpeech.tsx b/packages/forge/blocks/openai/actions/createSpeech.tsx new file mode 100644 index 0000000..0229ecf --- /dev/null +++ b/packages/forge/blocks/openai/actions/createSpeech.tsx @@ -0,0 +1,106 @@ +import { option, createAction } from '@typebot.io/forge' +import { defaultOpenAIOptions, openAIVoices } from '../constants' +import OpenAI, { ClientOptions } from 'openai' +import { isNotEmpty } from '@typebot.io/lib' +import { createId } from '@typebot.io/lib/createId' +import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket' +import { auth } from '../auth' +import { baseOptions } from '../baseOptions' + +export const createSpeech = createAction({ + name: 'Create speech', + auth, + baseOptions, + options: option.object({ + model: option.string.layout({ + fetcher: 'fetchSpeechModels', + defaultValue: 'tts-1', + placeholder: 'Select a model', + }), + input: option.string.layout({ + label: 'Input', + input: 'textarea', + }), + voice: option.enum(openAIVoices).layout({ + label: 'Voice', + placeholder: 'Select a voice', + }), + saveUrlInVariableId: option.string.layout({ + input: 'variableDropdown', + label: 'Save URL in variable', + }), + }), + getSetVariableIds: (options) => + options.saveUrlInVariableId ? [options.saveUrlInVariableId] : [], + fetchers: [ + { + id: 'fetchSpeechModels', + dependencies: ['baseUrl', 'apiVersion'], + fetch: async ({ credentials, options }) => { + const baseUrl = options?.baseUrl ?? defaultOpenAIOptions.baseUrl + const config = { + apiKey: credentials.apiKey, + baseURL: baseUrl ?? defaultOpenAIOptions.baseUrl, + defaultHeaders: { + 'api-key': credentials.apiKey, + }, + defaultQuery: options?.apiVersion + ? { + 'api-version': options.apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + const models = await openai.models.list() + + return ( + models.data + .filter((model) => model.id.includes('tts')) + .sort((a, b) => b.created - a.created) + .map((model) => model.id) ?? [] + ) + }, + }, + ], + run: { + server: async ({ credentials: { apiKey }, options, variables, logs }) => { + if (!options.input) return logs.add('Create speech input is empty') + if (!options.voice) return logs.add('Create speech voice is empty') + if (!options.saveUrlInVariableId) + return logs.add('Create speech save variable is empty') + + const config = { + apiKey, + baseURL: options.baseUrl ?? defaultOpenAIOptions.baseUrl, + defaultHeaders: { + 'api-key': apiKey, + }, + defaultQuery: isNotEmpty(options.apiVersion) + ? { + 'api-version': options.apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + const model = options.model ?? defaultOpenAIOptions.voiceModel + + const rawAudio = (await openai.audio.speech.create({ + input: options.input, + voice: options.voice, + model, + })) as any + + const url = await uploadFileToBucket({ + file: Buffer.from((await rawAudio.arrayBuffer()) as ArrayBuffer), + key: `tmp/openai/audio/${createId() + createId()}.mp3`, + mimeType: 'audio/mpeg', + }) + + variables.set(options.saveUrlInVariableId, url) + }, + }, +}) diff --git a/packages/forge/blocks/openai/auth.ts b/packages/forge/blocks/openai/auth.ts new file mode 100644 index 0000000..7cfda29 --- /dev/null +++ b/packages/forge/blocks/openai/auth.ts @@ -0,0 +1,16 @@ +import { createAuth, option } from '@typebot.io/forge' + +export const auth = createAuth({ + type: 'encryptedCredentials', + name: 'OpenAI account', + schema: option.object({ + apiKey: option.string.layout({ + isRequired: true, + label: 'API key', + placeholder: 'sk-...', + helperText: + 'You can generate an API key [here](https://platform.openai.com/account/api-keys)', + withVariableButton: false, + }), + }), +}) diff --git a/packages/forge/blocks/openai/baseOptions.ts b/packages/forge/blocks/openai/baseOptions.ts new file mode 100644 index 0000000..f2db40c --- /dev/null +++ b/packages/forge/blocks/openai/baseOptions.ts @@ -0,0 +1,14 @@ +import { option } from '@typebot.io/forge' +import { defaultOpenAIOptions } from './constants' + +export const baseOptions = option.object({ + baseUrl: option.string.layout({ + accordion: 'Customize provider', + label: 'Base URL', + defaultValue: defaultOpenAIOptions.baseUrl, + }), + apiVersion: option.string.layout({ + accordion: 'Customize provider', + label: 'API version', + }), +}) diff --git a/packages/forge/blocks/openai/constants.ts b/packages/forge/blocks/openai/constants.ts new file mode 100644 index 0000000..a1754df --- /dev/null +++ b/packages/forge/blocks/openai/constants.ts @@ -0,0 +1,15 @@ +export const openAIVoices = [ + 'alloy', + 'echo', + 'fable', + 'onyx', + 'nova', + 'shimmer', +] as const + +export const defaultOpenAIOptions = { + baseUrl: 'https://api.openai.com/v1', + model: 'gpt-3.5-turbo', + voiceModel: 'tts-1', + temperature: 1, +} as const diff --git a/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts b/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts new file mode 100644 index 0000000..186069a --- /dev/null +++ b/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts @@ -0,0 +1,54 @@ +import type { OpenAI } from 'openai' +import { options as createChatCompletionOption } from '../actions/createChatCompletion' +import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { isNotEmpty } from '@typebot.io/lib' +import { z } from '@typebot.io/forge/zod' + +export const parseChatCompletionMessages = ({ + options: { messages }, + variables, +}: { + options: Pick, 'messages'> + variables: ReadOnlyVariableStore +}): OpenAI.Chat.ChatCompletionMessageParam[] => { + const parsedMessages = messages + ?.flatMap((message) => { + if (!message.role) return + + if (message.role === 'Dialogue') { + if (!message.dialogueVariableId) return + const dialogue = variables.get(message.dialogueVariableId) ?? [] + const dialogueArr = Array.isArray(dialogue) ? dialogue : [dialogue] + + return dialogueArr.map( + (dialogueItem, index) => { + if (index === 0 && message.startsBy === 'assistant') + return { + role: 'assistant', + content: dialogueItem, + } + return { + role: + index % (message.startsBy === 'assistant' ? 1 : 2) === 0 + ? 'user' + : 'assistant', + content: dialogueItem, + } + } + ) + } + + if (!message.content) return + + return { + role: message.role, + content: variables.parse(message.content), + } satisfies OpenAI.Chat.ChatCompletionMessageParam + }) + .filter( + (message) => + isNotEmpty(message?.role) && isNotEmpty(message?.content?.toString()) + ) as OpenAI.Chat.ChatCompletionMessageParam[] + + return parsedMessages +} diff --git a/packages/forge/blocks/openai/index.ts b/packages/forge/blocks/openai/index.ts new file mode 100644 index 0000000..9b292fb --- /dev/null +++ b/packages/forge/blocks/openai/index.ts @@ -0,0 +1,17 @@ +import { OpenAILightLogo, OpenAIDarkLogo } from './logo' +import { createChatCompletion } from './actions/createChatCompletion' +import { createSpeech } from './actions/createSpeech' +import { createBlock } from '@typebot.io/forge' +import { auth } from './auth' +import { baseOptions } from './baseOptions' + +export const openAIBlock = createBlock({ + id: 'openai' as const, + name: 'OpenAI', + tags: ['openai'], + LightLogo: OpenAILightLogo, + DarkLogo: OpenAIDarkLogo, + auth, + options: baseOptions, + actions: [createChatCompletion, createSpeech], +}) diff --git a/packages/forge/blocks/openai/logo.tsx b/packages/forge/blocks/openai/logo.tsx new file mode 100644 index 0000000..bfc4df3 --- /dev/null +++ b/packages/forge/blocks/openai/logo.tsx @@ -0,0 +1,13 @@ +import React from 'react' + +export const OpenAILightLogo = (props: React.SVGProps) => ( + + + +) + +export const OpenAIDarkLogo = (props: React.SVGProps) => ( + + + +) diff --git a/packages/forge/blocks/openai/package.json b/packages/forge/blocks/openai/package.json new file mode 100644 index 0000000..b7ad30b --- /dev/null +++ b/packages/forge/blocks/openai/package.json @@ -0,0 +1,20 @@ +{ + "name": "@typebot.io/openai-block", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "author": "Baptiste Arnaud", + "license": "ISC", + "dependencies": { + "ai": "2.2.24", + "openai": "4.19.0" + }, + "devDependencies": { + "@typebot.io/forge": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@types/react": "18.2.15", + "typescript": "5.3.2", + "@typebot.io/lib": "workspace:*" + } +} diff --git a/packages/forge/blocks/openai/tsconfig.json b/packages/forge/blocks/openai/tsconfig.json new file mode 100644 index 0000000..1eb9c77 --- /dev/null +++ b/packages/forge/blocks/openai/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "noEmit": true, + "jsx": "react" + } +} diff --git a/packages/forge/blocks/zemanticAi/actions/searchDocuments.ts b/packages/forge/blocks/zemanticAi/actions/searchDocuments.ts new file mode 100644 index 0000000..e118e30 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/actions/searchDocuments.ts @@ -0,0 +1,110 @@ +import { createAction, option } from '@typebot.io/forge' +import { isDefined } from '@typebot.io/lib' +import { ZemanticAiResponse } from '../types' +import { got } from 'got' +import { apiBaseUrl } from '../constants' +import { auth } from '../auth' +import { baseOptions } from '../baseOptions' + +export const searchDocuments = createAction({ + baseOptions, + auth, + name: 'Search documents', + options: option.object({ + query: option.string.layout({ + label: 'Query', + placeholder: 'Content', + moreInfoTooltip: + 'The question you want to ask or search against the documents in the project.', + }), + maxResults: option.number.layout({ + label: 'Max results', + placeholder: 'i.e. 3', + defaultValue: 3, + moreInfoTooltip: + 'The maximum number of document chunk results to return from your search.', + }), + systemPrompt: option.string.layout({ + accordion: 'Advanced settings', + label: 'System prompt', + moreInfoTooltip: + 'System prompt to send to the summarization LLM. This is prepended to the prompt and helps guide system behavior.', + input: 'textarea', + }), + prompt: option.string.layout({ + accordion: 'Advanced settings', + label: 'Prompt', + moreInfoTooltip: 'Prompt to send to the summarization LLM.', + input: 'textarea', + }), + responseMapping: option + .saveResponseArray([ + 'Summary', + 'Document IDs', + 'Texts', + 'Scores', + ] as const) + .layout({ + accordion: 'Save response', + }), + }), + getSetVariableIds: ({ responseMapping }) => + responseMapping?.map((r) => r.variableId).filter(isDefined) ?? [], + run: { + server: async ({ + credentials: { apiKey }, + options: { + maxResults, + projectId, + prompt, + query, + responseMapping, + systemPrompt, + }, + variables, + }) => { + const res: ZemanticAiResponse = await got + .post(apiBaseUrl, { + headers: { + Authorization: `Bearer ${apiKey}`, + }, + json: { + projectId, + query, + maxResults, + summarize: true, + summaryOptions: { + system_prompt: systemPrompt, + prompt: prompt, + }, + }, + }) + .json() + + responseMapping?.forEach((mapping) => { + if (!mapping.variableId || !mapping.item) return + + if (mapping.item === 'Document IDs') + variables.set( + mapping.variableId, + res.results.map((r) => r.documentId) + ) + + if (mapping.item === 'Texts') + variables.set( + mapping.variableId, + res.results.map((r) => r.text) + ) + + if (mapping.item === 'Scores') + variables.set( + mapping.variableId, + res.results.map((r) => r.score) + ) + + if (mapping.item === 'Summary') + variables.set(mapping.variableId, res.summary) + }) + }, + }, +}) diff --git a/packages/forge/blocks/zemanticAi/auth.ts b/packages/forge/blocks/zemanticAi/auth.ts new file mode 100644 index 0000000..1cedf55 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/auth.ts @@ -0,0 +1,15 @@ +import { AuthDefinition, option } from '@typebot.io/forge' + +export const auth = { + type: 'encryptedCredentials', + name: 'Zemantic AI account', + schema: option.object({ + apiKey: option.string.layout({ + label: 'API key', + isRequired: true, + placeholder: 'ze...', + helperText: + 'You can generate an API key [here](https://zemantic.ai/dashboard/settings).', + }), + }), +} satisfies AuthDefinition diff --git a/packages/forge/blocks/zemanticAi/baseOptions.ts b/packages/forge/blocks/zemanticAi/baseOptions.ts new file mode 100644 index 0000000..c343e4b --- /dev/null +++ b/packages/forge/blocks/zemanticAi/baseOptions.ts @@ -0,0 +1,8 @@ +import { option } from '@typebot.io/forge' + +export const baseOptions = option.object({ + projectId: option.string.layout({ + placeholder: 'Select a project', + fetcher: 'fetchProjects', + }), +}) diff --git a/packages/forge/blocks/zemanticAi/constants.ts b/packages/forge/blocks/zemanticAi/constants.ts new file mode 100644 index 0000000..5c3ce59 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/constants.ts @@ -0,0 +1 @@ +export const apiBaseUrl = 'https://api.zemantic.ai/v1/search-documents' diff --git a/packages/forge/blocks/zemanticAi/index.ts b/packages/forge/blocks/zemanticAi/index.ts new file mode 100644 index 0000000..94ba4f7 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/index.ts @@ -0,0 +1,43 @@ +import { createBlock } from '@typebot.io/forge' +import { ZemanticAiLogo } from './logo' +import { got } from 'got' +import { searchDocuments } from './actions/searchDocuments' +import { auth } from './auth' +import { baseOptions } from './baseOptions' + +export const zemanticAi = createBlock({ + id: 'zemantic-ai', + name: 'Zemantic AI', + tags: [], + LightLogo: ZemanticAiLogo, + auth, + options: baseOptions, + fetchers: [ + { + id: 'fetchProjects', + dependencies: [], + fetch: async ({ credentials: { apiKey } }) => { + const url = 'https://api.zemantic.ai/v1/projects' + + const response = await got + .get(url, { + headers: { + Authorization: `Bearer ${apiKey}`, + }, + }) + .json() + + const projectsData = response as { + id: string + name: string + }[] + + return projectsData.map((project) => ({ + label: project.name, + value: project.id, + })) + }, + }, + ], + actions: [searchDocuments], +}) diff --git a/packages/forge/blocks/zemanticAi/logo.tsx b/packages/forge/blocks/zemanticAi/logo.tsx new file mode 100644 index 0000000..c6875c3 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/logo.tsx @@ -0,0 +1,21 @@ +import React from 'react' + +export const ZemanticAiLogo = (props: React.SVGProps) => ( + + + + + + + + + +) diff --git a/packages/forge/blocks/zemanticAi/package.json b/packages/forge/blocks/zemanticAi/package.json new file mode 100644 index 0000000..b8ca467 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/package.json @@ -0,0 +1,16 @@ +{ + "name": "@typebot.io/zemantic-ai-block", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "license": "ISC", + "devDependencies": { + "@typebot.io/forge": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@types/react": "18.2.15", + "typescript": "5.3.2", + "@typebot.io/lib": "workspace:*", + "got": "12.6.0" + } +} diff --git a/packages/forge/blocks/zemanticAi/tsconfig.json b/packages/forge/blocks/zemanticAi/tsconfig.json new file mode 100644 index 0000000..1eb9c77 --- /dev/null +++ b/packages/forge/blocks/zemanticAi/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "noEmit": true, + "jsx": "react" + } +} diff --git a/packages/forge/blocks/zemanticAi/types.ts b/packages/forge/blocks/zemanticAi/types.ts new file mode 100644 index 0000000..256600e --- /dev/null +++ b/packages/forge/blocks/zemanticAi/types.ts @@ -0,0 +1,4 @@ +export type ZemanticAiResponse = { + results: { documentId: string; text: string; score: number }[] + summary: string +} diff --git a/packages/forge/cli/index.ts b/packages/forge/cli/index.ts new file mode 100644 index 0000000..960d16b --- /dev/null +++ b/packages/forge/cli/index.ts @@ -0,0 +1,295 @@ +import * as p from '@clack/prompts' +import { spinner } from '@clack/prompts' +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs' +import { join } from 'path' +import prettier from 'prettier' +import { spawn } from 'child_process' +import builderPackageJson from '../../../apps/builder/package.json' + +const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/ + +const prettierRc = { + trailingComma: 'es5', + tabWidth: 2, + semi: false, + singleQuote: true, +} as const + +type PromptResult = { + name: string + id: string + auth: 'apiKey' | 'encryptedData' | 'none' + camelCaseId: string +} + +const main = async () => { + p.intro('Create a new Typebot integration block') + const { name, id } = await p.group( + { + name: () => + p.text({ + message: 'Integration name?', + placeholder: 'Short name like: Sheets, Analytics, Cal.com', + }), + id: ({ results }) => + p.text({ + message: + 'Integration ID? (should be a slug like: cal-com, openai...)', + placeholder: 'my-integration', + initialValue: slugify(results.name ?? ''), + validate: (val) => { + if (!slugRegex.test(val)) + return 'Invalid ID. Must be a slug, like: "google-sheets".' + }, + }), + }, + { + onCancel: () => { + p.cancel('Operation cancelled.') + process.exit(0) + }, + } + ) + + const auth = (await p.select({ + message: 'Does this integration require authentication to work?', + options: [ + { value: 'apiKey', label: 'API key or token' }, + { value: 'encryptedData', label: 'Custom encrypted data' }, + { value: 'none', label: 'None' }, + ], + })) as 'apiKey' | 'encryptedData' | 'none' + + const prompt: PromptResult = { + name, + id: id as string, + auth, + camelCaseId: camelize(id as string), + } + + const s = spinner() + s.start('Creating files...') + const newBlockPath = join(process.cwd(), `../blocks/${prompt.camelCaseId}`) + if (existsSync(newBlockPath)) { + s.stop('Creating files...') + p.log.error( + `An integration with the ID "${prompt.id}" already exists. Please choose a different ID.` + ) + process.exit(1) + } + mkdirSync(newBlockPath) + await createPackageJson(newBlockPath, prompt) + await createTsConfig(newBlockPath) + await createIndexFile(newBlockPath, prompt) + await createLogoFile(newBlockPath, prompt) + if (prompt.auth !== 'none') await createAuthFile(newBlockPath, prompt) + await addNewIntegrationToRepository(prompt) + s.stop('Creating files...') + s.start('Installing dependencies...') + await new Promise((resolve, reject) => { + const ls = spawn('pnpm', ['install']) + ls.stderr.on('data', (data) => { + reject(data) + }) + ls.on('error', (error) => { + reject(error) + }) + ls.on('close', () => { + resolve() + }) + }) + s.stop('Installing dependencies...') + p.outro( + `Done! 🎉 Head over to packages/forge/blocks/${prompt.camelCaseId} and start coding!` + ) +} + +const slugify = (str: string): string => { + return String(str) + .normalize('NFKD') // split accented characters into their base characters and diacritical marks + .replace(/[\u0300-\u036f]/g, '') // remove all the accents, which happen to be all in the \u03xx UNICODE block. + .trim() // trim leading or trailing whitespace + .toLowerCase() // convert to lowercase + .replace(/[^a-z0-9\. -]/g, '') // remove non-alphanumeric characters + .replace(/[\s\.]+/g, '-') // replace spaces and dots with hyphens + .replace(/-+/g, '-') // remove consecutive hyphens +} + +const camelize = (str: string) => + str.replace(/-([a-z])/g, function (g) { + return g[1].toUpperCase() + }) + +const capitalize = (str: string) => { + const [fst] = str + + return `${fst.toUpperCase()}${str.slice(1)}` +} + +const createIndexFile = async ( + path: string, + { id, camelCaseId, name, auth }: PromptResult +) => { + const camelCaseName = camelize(id as string) + writeFileSync( + join(path, 'index.ts'), + await prettier.format( + `import { createBlock } from '@typebot.io/forge' +import { ${capitalize(camelCaseId)}Logo } from './logo' +${auth !== 'none' ? `import { auth } from './auth'` : ''} + +export const ${camelCaseName} = createBlock({ + id: '${id}', + name: '${name}', + tags: [], + LightLogo: ${capitalize(camelCaseName)}Logo,${auth !== 'none' ? `auth,` : ''} + actions: [], +}) +`, + { parser: 'typescript', ...prettierRc } + ) + ) +} + +const createPackageJson = async (path: string, { id }: { id: unknown }) => { + writeFileSync( + join(path, 'package.json'), + await prettier.format( + JSON.stringify({ + name: `@typebot.io/${id}-block`, + version: '1.0.0', + description: '', + main: 'index.ts', + keywords: [], + license: 'ISC', + devDependencies: { + '@typebot.io/forge': 'workspace:*', + '@typebot.io/tsconfig': 'workspace:*', + '@types/react': builderPackageJson.devDependencies['@types/react'], + typescript: builderPackageJson.devDependencies['typescript'], + '@typebot.io/lib': 'workspace:*', + }, + }), + { parser: 'json', ...prettierRc } + ) + ) +} + +const addNewIntegrationToRepository = async ({ + camelCaseId, + id, +}: { + camelCaseId: string + id: string +}) => { + const schemasPath = join(process.cwd(), `../schemas`) + const packageJson = require(join(schemasPath, 'package.json')) + packageJson.devDependencies[`@typebot.io/${id}-block`] = 'workspace:*' + writeFileSync( + join(schemasPath, 'package.json'), + await prettier.format(JSON.stringify(packageJson, null, 2), { + parser: 'json', + ...prettierRc, + }) + ) + const repoIndexFile = readFileSync(join(schemasPath, 'index.ts')).toString() + writeFileSync( + join(schemasPath, 'index.ts'), + await prettier.format( + repoIndexFile + .replace( + '] as BlockDefinition<(typeof enabledBlocks)[number], any, any>[]', + `${camelCaseId},] as BlockDefinition<(typeof enabledBlocks)[number], any, any>[]` + ) + .replace( + '// Do not edit this file manually', + `// Do not edit this file manually\nimport {${camelCaseId}} from '@typebot.io/${id}-block'` + ), + { parser: 'typescript', ...prettierRc } + ) + ) + + const repoPath = join(process.cwd(), `../repository`) + const enabledIndexFile = readFileSync(join(repoPath, 'index.ts')).toString() + writeFileSync( + join(repoPath, 'index.ts'), + await prettier.format( + enabledIndexFile.replace('] as const', `'${id}'] as const`), + { parser: 'typescript', ...prettierRc } + ) + ) +} + +const createTsConfig = async (path: string) => { + writeFileSync( + join(path, 'tsconfig.json'), + await prettier.format( + JSON.stringify({ + extends: '@typebot.io/tsconfig/base.json', + include: ['**/*.ts', '**/*.tsx'], + exclude: ['node_modules'], + compilerOptions: { + lib: ['ESNext', 'DOM'], + noEmit: true, + jsx: 'react', + }, + }), + { parser: 'json', ...prettierRc } + ) + ) +} + +const createLogoFile = async ( + path: string, + { camelCaseId }: { camelCaseId: string } +) => { + writeFileSync( + join(path, 'logo.tsx'), + await prettier.format( + `import React from 'react' + + export const ${capitalize( + camelCaseId + )}Logo = (props: React.SVGProps) => + `, + { parser: 'typescript', ...prettierRc } + ) + ) +} + +const createAuthFile = async ( + path: string, + { name, auth }: { name: string; auth: 'apiKey' | 'encryptedData' | 'none' } +) => + writeFileSync( + join(path, 'auth.ts'), + await prettier.format( + `import { option, AuthDefinition } from '@typebot.io/forge' + + export const auth = { + type: 'encryptedCredentials', + name: '${name} account', + ${ + auth === 'apiKey' + ? `schema: option.object({ + apiKey: option.string.layout({ + label: 'API key', + isRequired: true, + input: 'password', + helperText: + 'You can generate an API key [here]().', + }), + }),` + : '' + } + } satisfies AuthDefinition`, + { parser: 'typescript', ...prettierRc } + ) + ) + +main() + .then() + .catch((err) => { + console.error(err) + process.exit(1) + }) diff --git a/packages/forge/cli/package.json b/packages/forge/cli/package.json new file mode 100644 index 0000000..8766f7d --- /dev/null +++ b/packages/forge/cli/package.json @@ -0,0 +1,19 @@ +{ + "name": "forge-cli", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "tsx ./index.ts" + }, + "keywords": [], + "author": "Baptiste Arnaud", + "license": "ISC", + "devDependencies": { + "@clack/prompts": "^0.7.0", + "@typebot.io/tsconfig": "workspace:*", + "@types/node": "^20.10.1", + "tsx": "^4.6.1", + "prettier": "3.0.0" + } +} diff --git a/packages/forge/cli/tsconfig.json b/packages/forge/cli/tsconfig.json new file mode 100644 index 0000000..66ba1ed --- /dev/null +++ b/packages/forge/cli/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["./**/*.ts"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ESNext"], + "resolveJsonModule": true + } +} diff --git a/packages/forge/core/index.ts b/packages/forge/core/index.ts new file mode 100644 index 0000000..f24bf04 --- /dev/null +++ b/packages/forge/core/index.ts @@ -0,0 +1,133 @@ +import { AuthDefinition, BlockDefinition, ActionDefinition } from './types' +import { z } from './zod' + +export const variableStringSchema = z.custom<`{{${string}}}`>((val) => + /^{{.+}}$/g.test(val as string) +) + +export const createAuth = (authDefinition: A) => + authDefinition + +export const createBlock = < + I extends string, + A extends AuthDefinition, + O extends z.ZodObject +>( + blockDefinition: BlockDefinition +): BlockDefinition => blockDefinition + +export const createAction = < + A extends AuthDefinition, + BaseOptions extends z.ZodObject, + O extends z.ZodObject +>( + actionDefinition: { + auth?: A + baseOptions?: BaseOptions + } & ActionDefinition +) => actionDefinition + +export const parseBlockSchema = < + I extends string, + A extends AuthDefinition, + O extends z.ZodObject +>( + blockDefinition: BlockDefinition +) => { + const options = z.discriminatedUnion('action', [ + blockDefinition.options + ? blockDefinition.options.extend({ + credentialsId: z.string().optional(), + action: z.undefined(), + }) + : z.object({ + credentialsId: z.string().optional(), + action: z.undefined(), + }), + ...blockDefinition.actions.map((action) => + blockDefinition.options + ? (blockDefinition.options + .extend({ + credentialsId: z.string().optional(), + }) + .extend({ + action: z.literal(action.name), + }) + .merge(action.options ?? z.object({})) as any) + : z + .object({ + credentialsId: z.string().optional(), + }) + .extend({ + action: z.literal(action.name), + }) + .merge(action.options ?? z.object({})) + ), + ]) + return z.object({ + id: z.string(), + outgoingEdgeId: z.string().optional(), + type: z.literal(blockDefinition.id), + options: options.optional(), + }) +} + +export const parseBlockCredentials = < + I extends string, + A extends AuthDefinition, + O extends z.ZodObject +>( + blockDefinition: BlockDefinition +) => { + if (!blockDefinition.auth) throw new Error('Block has no auth definition') + return z.object({ + id: z.string(), + type: z.literal(blockDefinition.id), + createdAt: z.date(), + workspaceId: z.string(), + name: z.string(), + iv: z.string(), + data: blockDefinition.auth.schema, + }) +} + +export const option = { + object: (schema: T) => z.object(schema), + literal: (value: T) => z.literal(value), + string: z.string().optional(), + enum: (values: readonly [T, ...T[]]) => + z.enum(values).optional(), + number: z.number().or(variableStringSchema).optional(), + array: (schema: T) => z.array(schema).optional(), + discriminatedUnion: < + T extends string, + J extends [ + z.ZodDiscriminatedUnionOption, + ...z.ZodDiscriminatedUnionOption[] + ] + >( + field: T, + schemas: J + ) => + // @ts-expect-error + z.discriminatedUnion(field, [ + z.object({ [field]: z.undefined() }), + ...schemas, + ]), + saveResponseArray: (items: I) => + z + .array( + z.object({ + item: z.enum(items).optional().layout({ + placeholder: 'Select a response', + defaultValue: items[0], + }), + variableId: z.string().optional().layout({ + input: 'variableDropdown', + }), + }) + ) + .optional(), +} + +export type * from './types' diff --git a/packages/forge/core/package.json b/packages/forge/core/package.json new file mode 100644 index 0000000..173ff86 --- /dev/null +++ b/packages/forge/core/package.json @@ -0,0 +1,16 @@ +{ + "name": "@typebot.io/forge", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "author": "Baptiste Arnaud", + "license": "ISC", + "dependencies": { + "zod": "3.22.4" + }, + "devDependencies": { + "@typebot.io/tsconfig": "workspace:*", + "@types/react": "18.2.15" + } +} diff --git a/packages/forge/core/tsconfig.json b/packages/forge/core/tsconfig.json new file mode 100644 index 0000000..bfb0ffa --- /dev/null +++ b/packages/forge/core/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/packages/forge/core/types.ts b/packages/forge/core/types.ts new file mode 100644 index 0000000..f69ad39 --- /dev/null +++ b/packages/forge/core/types.ts @@ -0,0 +1,133 @@ +import { SVGProps } from 'react' +import { z } from './zod' + +export type VariableStore = { + get: (variableId: string) => string | (string | null)[] | null | undefined + set: (variableId: string, value: unknown) => void + parse: (value: string) => string +} + +export type LogsStore = { + add: ( + log: + | string + | { + status: 'error' | 'success' | 'info' + description: string + details?: unknown + } + ) => void +} + +export type FunctionToExecute = { + args: Record + content: string +} + +export type ReadOnlyVariableStore = Omit + +export type ActionDefinition< + A extends AuthDefinition, + BaseOptions extends z.ZodObject, + Options extends z.ZodObject = z.ZodObject<{}> +> = { + name: string + fetchers?: FetcherDefinition & z.infer>[] + options?: Options + getSetVariableIds?: (options: z.infer) => string[] + run?: { + server?: (params: { + credentials: CredentialsFromAuthDef + options: z.infer & z.infer + variables: VariableStore + logs: LogsStore + }) => Promise | void + /** + * Used to stream a text bubble. Will only be used if the block following the integration block is a text bubble containing the variable returned by `getStreamVariableId`. + */ + stream?: { + getStreamVariableId: (options: z.infer) => string | undefined + run: (params: { + credentials: CredentialsFromAuthDef + options: z.infer & z.infer + variables: ReadOnlyVariableStore + }) => Promise | undefined> + } + web?: { + displayEmbedBubble?: { + waitForEvent?: { + getSaveVariableId?: ( + options: z.infer & z.infer + ) => string | undefined + parseFunction: (params: { + options: z.infer & z.infer + }) => FunctionToExecute + } + parseInitFunction: (params: { + options: z.infer & z.infer + }) => FunctionToExecute + } + parseFunction?: (params: { + options: z.infer & z.infer + }) => FunctionToExecute + } + } +} + +export type FetcherDefinition = { + id: string + /** + * List of option keys to determine if the fetcher should be re-executed whenever these options are updated. + */ + dependencies: (keyof T)[] + fetch: (params: { + credentials: CredentialsFromAuthDef + options: T + }) => Promise<(string | { label: string; value: string })[]> +} + +export type AuthDefinition = { + type: 'encryptedCredentials' + name: string + schema: z.ZodObject +} + +export type CredentialsFromAuthDef = A extends { + type: 'encryptedCredentials' + schema: infer S extends z.ZodObject +} + ? z.infer + : never + +export type BlockDefinition< + Id extends string, + Auth extends AuthDefinition, + Options extends z.ZodObject +> = { + id: Id + name: string + fullName?: string + /** + * Keywords used when searching for a block. + */ + tags?: string[] + LightLogo: (props: SVGProps) => JSX.Element + DarkLogo?: (props: SVGProps) => JSX.Element + docsUrl?: string + auth?: Auth + options?: Options | undefined + fetchers?: FetcherDefinition[] + isDisabledInPreview?: boolean + actions: ActionDefinition[] +} + +export type FetchItemsParams = T extends ActionDefinition< + infer A, + infer BaseOptions, + infer Options +> + ? { + credentials: CredentialsFromAuthDef + options: BaseOptions & Options + } + : never diff --git a/packages/forge/core/zod/extendWithTypebotLayout.ts b/packages/forge/core/zod/extendWithTypebotLayout.ts new file mode 100644 index 0000000..2fc7161 --- /dev/null +++ b/packages/forge/core/zod/extendWithTypebotLayout.ts @@ -0,0 +1,48 @@ +import { ZodArray, ZodDate, ZodOptional, ZodString, ZodTypeAny, z } from 'zod' + +type OptionableZodType = T | ZodOptional + +export interface ZodLayoutMetadata< + T extends ZodTypeAny, + TInferred = z.input | z.output +> { + accordion?: string + label?: string + input?: 'variableDropdown' | 'textarea' | 'password' + defaultValue?: T extends ZodDate ? string : TInferred + placeholder?: string + helperText?: string + direction?: 'row' | 'column' + isRequired?: boolean + withVariableButton?: boolean + fetcher?: T extends OptionableZodType ? string : never + itemLabel?: T extends OptionableZodType> ? string : never + isOrdered?: T extends OptionableZodType> ? boolean : never + isHidden?: boolean + moreInfoTooltip?: string +} + +declare module 'zod' { + interface ZodType { + layout(this: T, metadata: ZodLayoutMetadata): T + } + + interface ZodTypeDef { + layout?: ZodLayoutMetadata + } +} + +export const extendWithTypebotLayout = (zod: typeof z) => { + if (typeof zod.ZodType.prototype.layout !== 'undefined') { + return + } + + zod.ZodType.prototype.layout = function (layout) { + const result = new (this as any).constructor({ + ...this._def, + layout, + }) + + return result + } +} diff --git a/packages/forge/core/zod/index.ts b/packages/forge/core/zod/index.ts new file mode 100644 index 0000000..fcc43e2 --- /dev/null +++ b/packages/forge/core/zod/index.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' +import { + extendWithTypebotLayout, + ZodLayoutMetadata, +} from './extendWithTypebotLayout' + +extendWithTypebotLayout(z) + +export { z } +export type { ZodLayoutMetadata } diff --git a/packages/forge/repository/index.ts b/packages/forge/repository/index.ts new file mode 100644 index 0000000..8726429 --- /dev/null +++ b/packages/forge/repository/index.ts @@ -0,0 +1,7 @@ +// Do not edit this file manually +export const enabledBlocks = [ + 'openai', + 'zemantic-ai', + 'cal-com', + 'chat-node', +] as const diff --git a/packages/forge/repository/package.json b/packages/forge/repository/package.json new file mode 100644 index 0000000..5c5f010 --- /dev/null +++ b/packages/forge/repository/package.json @@ -0,0 +1,9 @@ +{ + "name": "@typebot.io/forge-repository", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "author": "Baptiste Arnaud", + "license": "ISC" +} diff --git a/packages/forge/schemas/index.ts b/packages/forge/schemas/index.ts new file mode 100644 index 0000000..90d8a3f --- /dev/null +++ b/packages/forge/schemas/index.ts @@ -0,0 +1,28 @@ +// Do not edit this file manually +import { chatNode } from '@typebot.io/chat-node-block' +import { calCom } from '@typebot.io/cal-com-block' +import { zemanticAi } from '@typebot.io/zemantic-ai-block' +import { openAIBlock } from '@typebot.io/openai-block' +import { + BlockDefinition, + parseBlockCredentials, + parseBlockSchema, +} from '@typebot.io/forge' +import { enabledBlocks } from '@typebot.io/forge-repository' +import { z } from '@typebot.io/forge/zod' + +export const forgedBlocks = [ + openAIBlock, + zemanticAi, + calCom, + chatNode, +] as BlockDefinition<(typeof enabledBlocks)[number], any, any>[] + +export type ForgedBlockDefinition = (typeof forgedBlocks)[number] + +export const forgedBlockSchemas = forgedBlocks.map(parseBlockSchema) +export type ForgedBlock = z.infer<(typeof forgedBlockSchemas)[number]> + +export const forgedCredentialsSchemas = forgedBlocks + .filter((b) => b.auth) + .map(parseBlockCredentials) diff --git a/packages/forge/schemas/package.json b/packages/forge/schemas/package.json new file mode 100644 index 0000000..8540163 --- /dev/null +++ b/packages/forge/schemas/package.json @@ -0,0 +1,17 @@ +{ + "name": "@typebot.io/forge-schemas", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "keywords": [], + "author": "Baptiste Arnaud", + "license": "ISC", + "devDependencies": { + "@typebot.io/forge": "workspace:*", + "@typebot.io/forge-repository": "workspace:*", + "@typebot.io/openai-block": "workspace:*", + "@typebot.io/zemantic-ai-block": "workspace:*", + "@typebot.io/cal-com-block": "workspace:*", + "@typebot.io/chat-node-block": "workspace:*" + } +} diff --git a/packages/lib/.eslintrc.js b/packages/lib/.eslintrc.js new file mode 100644 index 0000000..b56159e --- /dev/null +++ b/packages/lib/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['custom'], +} diff --git a/packages/lib/api/encryption/decrypt.ts b/packages/lib/api/encryption/decrypt.ts new file mode 100644 index 0000000..0a0871c --- /dev/null +++ b/packages/lib/api/encryption/decrypt.ts @@ -0,0 +1,10 @@ +import { decryptV1 } from './decryptV1' +import { decryptV2 } from './decryptV2' + +export const decrypt = async ( + encryptedData: string, + ivHex: string +): Promise => { + if (ivHex.length !== 24) return decryptV1(encryptedData, ivHex) + return decryptV2(encryptedData, ivHex) +} diff --git a/packages/lib/api/encryption/decryptV1.ts b/packages/lib/api/encryption/decryptV1.ts new file mode 100644 index 0000000..628a7a2 --- /dev/null +++ b/packages/lib/api/encryption/decryptV1.ts @@ -0,0 +1,21 @@ +import { env } from '@typebot.io/env' +import { createDecipheriv } from 'crypto' + +const algorithm = 'aes-256-gcm' +const secretKey = env.ENCRYPTION_SECRET + +export const decryptV1 = (encryptedData: string, auth: string): object => { + if (!secretKey) throw new Error(`ENCRYPTION_SECRET is not in environment`) + const [iv, tag] = auth.split('.') + const decipher = createDecipheriv( + algorithm, + secretKey, + Buffer.from(iv, 'hex') + ) + decipher.setAuthTag(Buffer.from(tag, 'hex')) + return JSON.parse( + ( + decipher.update(Buffer.from(encryptedData, 'hex')) + decipher.final('hex') + ).toString() + ) +} diff --git a/packages/lib/api/encryption/decryptV2.ts b/packages/lib/api/encryption/decryptV2.ts new file mode 100644 index 0000000..b2c368e --- /dev/null +++ b/packages/lib/api/encryption/decryptV2.ts @@ -0,0 +1,35 @@ +import { env } from '@typebot.io/env' + +const algorithm = 'AES-GCM' +const secretKey = env.ENCRYPTION_SECRET + +export const decryptV2 = async ( + encryptedData: string, + ivHex: string +): Promise => { + if (!secretKey) throw new Error('ENCRYPTION_SECRET is not in environment') + const iv = new Uint8Array( + ivHex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) ?? [] + ) + + const key = await crypto.subtle.importKey( + 'raw', + new TextEncoder().encode(secretKey), + algorithm, + false, + ['decrypt'] + ) + + const encryptedBuffer = new Uint8Array( + Array.from(atob(encryptedData)).map((char) => char.charCodeAt(0)) + ) + + const decryptedBuffer = await crypto.subtle.decrypt( + { name: algorithm, iv }, + key, + encryptedBuffer + ) + + const decryptedData = new TextDecoder().decode(decryptedBuffer) + return JSON.parse(decryptedData) +} diff --git a/packages/lib/api/encryption/encrypt.ts b/packages/lib/api/encryption/encrypt.ts new file mode 100644 index 0000000..60f1594 --- /dev/null +++ b/packages/lib/api/encryption/encrypt.ts @@ -0,0 +1,39 @@ +import { env } from '@typebot.io/env' + +const algorithm = 'AES-GCM' +const secretKey = env.ENCRYPTION_SECRET + +export const encrypt = async ( + data: object +): Promise<{ encryptedData: string; iv: string }> => { + if (!secretKey) throw new Error('ENCRYPTION_SECRET is not in environment') + const iv = crypto.getRandomValues(new Uint8Array(12)) + const encodedData = new TextEncoder().encode(JSON.stringify(data)) + + const key = await crypto.subtle.importKey( + 'raw', + new TextEncoder().encode(secretKey), + algorithm, + false, + ['encrypt'] + ) + + const encryptedBuffer = await crypto.subtle.encrypt( + { name: algorithm, iv }, + key, + encodedData + ) + + const encryptedData = btoa( + String.fromCharCode.apply(null, Array.from(new Uint8Array(encryptedBuffer))) + ) + + const ivHex = Array.from(iv) + .map((byte) => byte.toString(16).padStart(2, '0')) + .join('') + + return { + encryptedData, + iv: ivHex, + } +} diff --git a/packages/lib/api/helpers/archiveResults.ts b/packages/lib/api/helpers/archiveResults.ts new file mode 100644 index 0000000..53abeaa --- /dev/null +++ b/packages/lib/api/helpers/archiveResults.ts @@ -0,0 +1,92 @@ +import { Prisma, PrismaClient } from '@typebot.io/prisma' +import { Block, Typebot } from '@typebot.io/schemas' +import { deleteFilesFromBucket } from '../../s3/deleteFilesFromBucket' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' + +type ArchiveResultsProps = { + typebot: Pick + resultsFilter?: Omit & { + typebotId: string + } +} + +export const archiveResults = + (prisma: PrismaClient) => + async ({ typebot, resultsFilter }: ArchiveResultsProps) => { + const batchSize = 100 + const fileUploadBlockIds = typebot.groups + .flatMap((group) => group.blocks) + .filter((block) => block.type === InputBlockType.FILE) + .map((block) => block.id) + + let currentTotalResults = 0 + + const resultsCount = await prisma.result.count({ + where: { + ...resultsFilter, + OR: [{ isArchived: false }, { isArchived: null }], + }, + }) + + if (resultsCount === 0) return { success: true } + + let progress = 0 + + do { + progress += batchSize + console.log(`Archiving ${progress} / ${resultsCount} results...`) + const resultsToDelete = await prisma.result.findMany({ + where: { + ...resultsFilter, + OR: [{ isArchived: false }, { isArchived: null }], + }, + select: { + id: true, + }, + take: batchSize, + }) + + if (resultsToDelete.length === 0) break + + currentTotalResults = resultsToDelete.length + + const resultIds = resultsToDelete.map((result) => result.id) + + if (fileUploadBlockIds.length > 0) { + const filesToDelete = await prisma.answer.findMany({ + where: { + resultId: { in: resultIds }, + blockId: { in: fileUploadBlockIds }, + }, + }) + if (filesToDelete.length > 0) + await deleteFilesFromBucket({ + urls: filesToDelete.flatMap((a) => a.content.split(', ')), + }) + } + + await prisma.$transaction([ + prisma.log.deleteMany({ + where: { + resultId: { in: resultIds }, + }, + }), + prisma.answer.deleteMany({ + where: { + resultId: { in: resultIds }, + }, + }), + prisma.result.updateMany({ + where: { + id: { in: resultIds }, + }, + data: { + isArchived: true, + variables: [], + }, + }), + ]) + } while (currentTotalResults >= batchSize) + + return { success: true } + } diff --git a/packages/lib/api/index.ts b/packages/lib/api/index.ts new file mode 100644 index 0000000..9c56149 --- /dev/null +++ b/packages/lib/api/index.ts @@ -0,0 +1 @@ +export * from './utils' diff --git a/packages/lib/api/utils.ts b/packages/lib/api/utils.ts new file mode 100644 index 0000000..2bca602 --- /dev/null +++ b/packages/lib/api/utils.ts @@ -0,0 +1,38 @@ +import { NextApiRequest, NextApiResponse } from 'next' + +export const methodNotAllowed = ( + res: NextApiResponse, + customMessage?: string +) => res.status(405).json({ message: customMessage ?? 'Method Not Allowed' }) + +export const notAuthenticated = ( + res: NextApiResponse, + customMessage?: string +) => res.status(401).json({ message: customMessage ?? 'Not authenticated' }) + +export const notFound = (res: NextApiResponse, customMessage?: string) => + res.status(404).json({ message: customMessage ?? 'Not found' }) + +export const badRequest = (res: NextApiResponse, customMessage?: any) => + res.status(400).json({ message: customMessage ?? 'Bad Request' }) + +export const forbidden = (res: NextApiResponse, customMessage?: string) => + res.status(403).json({ message: customMessage ?? 'Forbidden' }) + +export const initMiddleware = + ( + handler: ( + req: NextApiRequest, + res: NextApiResponse, + middleware: (result: any) => void + ) => void + ) => + (req: any, res: any) => + new Promise((resolve, reject) => { + handler(req, res, (result) => { + if (result instanceof Error) { + return reject(result) + } + return resolve(result) + }) + }) diff --git a/packages/lib/billing/constants.ts b/packages/lib/billing/constants.ts new file mode 100644 index 0000000..8cf7f68 --- /dev/null +++ b/packages/lib/billing/constants.ts @@ -0,0 +1,167 @@ +import { Plan } from '@typebot.io/prisma' +import type { Stripe } from 'stripe' + +export const prices = { + [Plan.STARTER]: 39, + [Plan.PRO]: 89, +} as const + +export const chatsLimits = { + [Plan.FREE]: 200, + [Plan.STARTER]: 2000, + [Plan.PRO]: 10000, +} as const + +export const seatsLimits = { + [Plan.FREE]: 1, + [Plan.OFFERED]: 1, + [Plan.STARTER]: 2, + [Plan.PRO]: 5, + [Plan.LIFETIME]: 8, +} as const + +export const starterChatTiers = [ + { + up_to: 2000, + flat_amount: 0, + }, + { + up_to: 2500, + flat_amount: 1000, + }, + { + up_to: 3000, + flat_amount: 2000, + }, + { + up_to: 3500, + flat_amount: 3000, + }, + { + up_to: 4000, + flat_amount: 4000, + }, + { + up_to: 'inf', + unit_amount: 2, + }, +] satisfies Stripe.PriceCreateParams.Tier[] + +export const proChatTiers = [ + { + up_to: 10000, + flat_amount: 0, + }, + { + up_to: 15000, + flat_amount: 5000, + }, + { + up_to: 20000, + flat_amount: 9500, + }, + { + up_to: 30000, + flat_amount: 18000, + }, + { + up_to: 40000, + flat_amount: 26000, + }, + { + up_to: 50000, + flat_amount: 33500, + }, + { + up_to: 60000, + flat_amount: 40700, + }, + { + up_to: 70000, + flat_amount: 47700, + }, + { + up_to: 80000, + flat_amount: 54500, + }, + { + up_to: 90000, + flat_amount: 61100, + }, + { + up_to: 100000, + flat_amount: 67500, + }, + { + up_to: 120000, + flat_amount: 79900, + }, + { + up_to: 140000, + flat_amount: 91900, + }, + { + up_to: 160000, + flat_amount: 103700, + }, + { + up_to: 180000, + flat_amount: 115300, + }, + { + up_to: 200000, + flat_amount: 126700, + }, + { + up_to: 300000, + flat_amount: 181700, + }, + { + up_to: 400000, + flat_amount: 234700, + }, + { + up_to: 500000, + flat_amount: 285700, + }, + { + up_to: 600000, + flat_amount: 335700, + }, + { + up_to: 700000, + flat_amount: 384700, + }, + { + up_to: 800000, + flat_amount: 432700, + }, + { + up_to: 900000, + flat_amount: 479700, + }, + { + up_to: 1000000, + flat_amount: 525700, + }, + { + up_to: 1200000, + flat_amount: 617100, + }, + { + up_to: 1400000, + flat_amount: 707900, + }, + { + up_to: 1600000, + flat_amount: 797900, + }, + { + up_to: 1800000, + flat_amount: 887300, + }, + { + up_to: 'inf', + unit_amount_decimal: '0.442', + }, +] satisfies Stripe.PriceCreateParams.Tier[] diff --git a/packages/lib/billing/formatPrice.ts b/packages/lib/billing/formatPrice.ts new file mode 100644 index 0000000..d8b1730 --- /dev/null +++ b/packages/lib/billing/formatPrice.ts @@ -0,0 +1,21 @@ +import { guessIfUserIsEuropean } from './guessIfUserIsEuropean' + +type FormatPriceParams = { + currency?: 'eur' | 'usd' + maxFractionDigits?: number +} + +export const formatPrice = ( + price: number, + { currency, maxFractionDigits = 0 }: FormatPriceParams = { + maxFractionDigits: 0, + } +) => { + const isEuropean = guessIfUserIsEuropean() + const formatter = new Intl.NumberFormat(isEuropean ? 'fr-FR' : 'en-US', { + style: 'currency', + currency: currency?.toUpperCase() ?? (isEuropean ? 'EUR' : 'USD'), + maximumFractionDigits: maxFractionDigits, + }) + return formatter.format(price) +} diff --git a/packages/lib/billing/getChatsLimit.ts b/packages/lib/billing/getChatsLimit.ts new file mode 100644 index 0000000..b5227e4 --- /dev/null +++ b/packages/lib/billing/getChatsLimit.ts @@ -0,0 +1,19 @@ +import { Plan } from '@typebot.io/prisma' +import { chatsLimits } from './constants' +import { Workspace } from '@typebot.io/schemas' + +export const getChatsLimit = ({ + plan, + customChatsLimit, +}: Pick & { + customChatsLimit?: Workspace['customChatsLimit'] +}) => { + if ( + plan === Plan.UNLIMITED || + plan === Plan.LIFETIME || + plan === Plan.OFFERED + ) + return 'inf' + if (plan === Plan.CUSTOM) return customChatsLimit ?? 'inf' + return chatsLimits[plan] +} diff --git a/packages/lib/billing/getSeatsLimit.ts b/packages/lib/billing/getSeatsLimit.ts new file mode 100644 index 0000000..0843f05 --- /dev/null +++ b/packages/lib/billing/getSeatsLimit.ts @@ -0,0 +1,12 @@ +import { Workspace } from '@typebot.io/schemas' +import { seatsLimits } from './constants' +import { Plan } from '@typebot.io/prisma' + +export const getSeatsLimit = ({ + plan, + customSeatsLimit, +}: Pick) => { + if (plan === Plan.UNLIMITED) return 'inf' + if (plan === Plan.CUSTOM) return customSeatsLimit ? customSeatsLimit : 'inf' + return seatsLimits[plan] +} diff --git a/packages/lib/billing/guessIfUserIsEuropean.ts b/packages/lib/billing/guessIfUserIsEuropean.ts new file mode 100644 index 0000000..9cd5148 --- /dev/null +++ b/packages/lib/billing/guessIfUserIsEuropean.ts @@ -0,0 +1,56 @@ +const europeanUnionCountryCodes = [ + 'AT', + 'BE', + 'BG', + 'CY', + 'CZ', + 'DE', + 'DK', + 'EE', + 'ES', + 'FI', + 'FR', + 'GR', + 'HR', + 'HU', + 'IE', + 'IT', + 'LT', + 'LU', + 'LV', + 'MT', + 'NL', + 'PL', + 'PT', + 'RO', + 'SE', + 'SI', + 'SK', +] + +const europeanUnionExclusiveLanguageCodes = [ + 'fr', + 'de', + 'it', + 'el', + 'pl', + 'fi', + 'nl', + 'hr', + 'cs', + 'hu', + 'ro', + 'sl', + 'sv', + 'bg', +] + +export const guessIfUserIsEuropean = () => { + if (typeof window === 'undefined') return false + return window.navigator.languages.some((language) => { + const [languageCode, countryCode] = language.split('-') + return countryCode + ? europeanUnionCountryCodes.includes(countryCode) + : europeanUnionExclusiveLanguageCodes.includes(languageCode) + }) +} diff --git a/packages/lib/createId.ts b/packages/lib/createId.ts new file mode 100644 index 0000000..c05948f --- /dev/null +++ b/packages/lib/createId.ts @@ -0,0 +1 @@ +export { createId } from '@paralleldrive/cuid2' diff --git a/packages/lib/getBlockById.ts b/packages/lib/getBlockById.ts new file mode 100644 index 0000000..a361952 --- /dev/null +++ b/packages/lib/getBlockById.ts @@ -0,0 +1,24 @@ +import { Block, Group } from '@typebot.io/schemas' + +export const getBlockById = ( + blockId: string, + groups: Group[] +): { block: Block; group: Group; blockIndex: number; groupIndex: number } => { + for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) { + for ( + let blockIndex = 0; + blockIndex < groups[groupIndex].blocks.length; + blockIndex++ + ) { + if (groups[groupIndex].blocks[blockIndex].id === blockId) { + return { + block: groups[groupIndex].blocks[blockIndex], + group: groups[groupIndex], + blockIndex, + groupIndex, + } + } + } + } + throw new Error(`Block with id ${blockId} was not found`) +} diff --git a/packages/lib/getIp.ts b/packages/lib/getIp.ts new file mode 100644 index 0000000..fe1397a --- /dev/null +++ b/packages/lib/getIp.ts @@ -0,0 +1,14 @@ +import { NextApiRequest } from 'next' + +export const getIp = (req: NextApiRequest): string | undefined => { + let ip = req.headers['x-real-ip'] as string | undefined + if (!ip) { + const forwardedFor = req.headers['x-forwarded-for'] + if (Array.isArray(forwardedFor)) { + ip = forwardedFor.at(0) + } else { + ip = forwardedFor?.split(',').at(0) + } + } + return ip +} diff --git a/packages/lib/google.ts b/packages/lib/google.ts new file mode 100644 index 0000000..e4c7d9b --- /dev/null +++ b/packages/lib/google.ts @@ -0,0 +1,63 @@ +import { env } from '@typebot.io/env' +import { Credentials as CredentialsFromDb } from '@typebot.io/prisma' +import { GoogleSheetsCredentials } from '@typebot.io/schemas' +import { GoogleCalendarCredentials } from '@typebot.io/schemas' +import { decrypt } from './api/encryption/decrypt' +import { encrypt } from './api/encryption/encrypt' +import prisma from './prisma' +import { isDefined } from './utils' +import { OAuth2Client, Credentials } from 'google-auth-library' + +export const getAuthenticatedGoogleClient = async ( + credentialsId: string, + credentialType: 'google sheets' | 'google calendar' +): Promise => { + const credentials = (await prisma.credentials.findFirst({ + where: { id: credentialsId }, + })) as CredentialsFromDb | undefined + if (!credentials) return + + let data; + let callbackUrl; + if (credentialType === 'google sheets') { + data = (await decrypt(credentials.data, credentials.iv)) as GoogleSheetsCredentials['data']; + callbackUrl = `${env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`; + } else if (credentialType === 'google calendar') { + data = (await decrypt(credentials.data, credentials.iv)) as GoogleCalendarCredentials['data']; + callbackUrl = `${env.NEXTAUTH_URL}/api/credentials/google-calendar/callback`; + } else { + throw new Error(`Unsupported credential type: ${credentialType}`); + } + + const oauth2Client = new OAuth2Client( + env.GOOGLE_CLIENT_ID, + env.GOOGLE_CLIENT_SECRET, + `${env.NEXTAUTH_URL}/api/credentials/google-sheets/callback` + ) + oauth2Client.setCredentials(data) + oauth2Client.on('tokens', updateTokens(credentialsId, data)) + return oauth2Client +} + +const updateTokens = + ( + credentialsId: string, + existingCredentials: GoogleSheetsCredentials['data'] | GoogleCalendarCredentials['data'] + ) => + async (credentials: Credentials) => { + if ( + isDefined(existingCredentials.id_token) && + credentials.id_token !== existingCredentials.id_token + ) + return + const newCredentials: GoogleSheetsCredentials['data'] = { + ...existingCredentials, + expiry_date: credentials.expiry_date, + access_token: credentials.access_token, + } + const { encryptedData, iv } = await encrypt(newCredentials) + await prisma.credentials.updateMany({ + where: { id: credentialsId }, + data: { data: encryptedData, iv }, + }) + } diff --git a/packages/lib/hexToRgb.ts b/packages/lib/hexToRgb.ts new file mode 100644 index 0000000..db693a7 --- /dev/null +++ b/packages/lib/hexToRgb.ts @@ -0,0 +1,20 @@ +export const hexToRgb = (hex: string): [r: number, g: number, b: number] => { + const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i + hex = hex.replace(shorthandRegex, (_m, r, g, b) => { + return r + r + g + g + b + b + }) + + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) + return result + ? [ + parseInt(result[1], 16), + parseInt(result[2], 16), + parseInt(result[3], 16), + ] + : [0, 0, 0] +} + +export const isLight = (hexColor: string) => + (([r, g, b]) => (r * 299 + g * 587 + b * 114) / 1000 > 155)( + hexToRgb(hexColor) + ) diff --git a/packages/lib/index.ts b/packages/lib/index.ts new file mode 100644 index 0000000..9c56149 --- /dev/null +++ b/packages/lib/index.ts @@ -0,0 +1 @@ +export * from './utils' diff --git a/packages/lib/isPlanetScale.ts b/packages/lib/isPlanetScale.ts new file mode 100644 index 0000000..9b89619 --- /dev/null +++ b/packages/lib/isPlanetScale.ts @@ -0,0 +1,3 @@ +import { env } from '@typebot.io/env' + +export const isPlaneteScale = () => env.DATABASE_URL?.includes('pscale_pw') diff --git a/packages/lib/migrations/migratePublicTypebot.ts b/packages/lib/migrations/migratePublicTypebot.ts new file mode 100644 index 0000000..5c52693 --- /dev/null +++ b/packages/lib/migrations/migratePublicTypebot.ts @@ -0,0 +1,15 @@ +import { PublicTypebot, PublicTypebotV6 } from '@typebot.io/schemas' +import { migrateTypebotFromV3ToV4 } from './migrateTypebotFromV3ToV4' +import { migrateTypebotFromV5ToV6 } from './migrateTypebotFromV5ToV6' + +export const migrateTypebot = async ( + typebot: PublicTypebot +): Promise => { + if (typebot.version === '6') return typebot + let migratedTypebot: any = typebot + if (migratedTypebot.version === '3') + migratedTypebot = await migrateTypebotFromV3ToV4(typebot) + if (migratedTypebot.version === '4' || migratedTypebot.version === '5') + migratedTypebot = migrateTypebotFromV5ToV6(migratedTypebot) + return migratedTypebot +} diff --git a/packages/lib/migrations/migrateTypebot.ts b/packages/lib/migrations/migrateTypebot.ts new file mode 100644 index 0000000..d05012b --- /dev/null +++ b/packages/lib/migrations/migrateTypebot.ts @@ -0,0 +1,30 @@ +import { + PublicTypebot, + PublicTypebotV6, + Typebot, + TypebotV6, +} from '@typebot.io/schemas' +import { migrateTypebotFromV3ToV4 } from './migrateTypebotFromV3ToV4' +import { migrateTypebotFromV5ToV6 } from './migrateTypebotFromV5ToV6' + +export const migrateTypebot = async (typebot: Typebot): Promise => { + if (typebot.version === '6') return typebot + let migratedTypebot: any = typebot + if (migratedTypebot.version === '3') + migratedTypebot = await migrateTypebotFromV3ToV4(typebot) + if (migratedTypebot.version === '4' || migratedTypebot.version === '5') + migratedTypebot = migrateTypebotFromV5ToV6(migratedTypebot) + return migratedTypebot +} + +export const migratePublicTypebot = async ( + typebot: PublicTypebot +): Promise => { + if (typebot.version === '6') return typebot + let migratedTypebot: any = typebot + if (migratedTypebot.version === '3') + migratedTypebot = await migrateTypebotFromV3ToV4(typebot) + if (migratedTypebot.version === '4' || migratedTypebot.version === '5') + migratedTypebot = migrateTypebotFromV5ToV6(migratedTypebot) + return migratedTypebot +} diff --git a/packages/lib/migrations/migrateTypebotFromV3ToV4.ts b/packages/lib/migrations/migrateTypebotFromV3ToV4.ts new file mode 100644 index 0000000..e475d2d --- /dev/null +++ b/packages/lib/migrations/migrateTypebotFromV3ToV4.ts @@ -0,0 +1,68 @@ +import { Webhook as WebhookFromDb } from '@typebot.io/prisma' +import { + Block, + BlockV5, + PublicTypebotV5, + TypebotV5, + Webhook, +} from '@typebot.io/schemas' +import { isWebhookBlock, isDefined } from '../utils' +import prisma from '../prisma' +import { + HttpMethod, + defaultWebhookAttributes, +} from '@typebot.io/schemas/features/blocks/integrations/webhook/constants' + +export const migrateTypebotFromV3ToV4 = async ( + typebot: TypebotV5 | PublicTypebotV5 +): Promise & { version: '4' }> => { + if (typebot.version === '4') + return typebot as Omit & { version: '4' } + const webhookBlocks = typebot.groups + .flatMap((group) => group.blocks) + .filter(isWebhookBlock) + const webhooks = await prisma.webhook.findMany({ + where: { + id: { + in: webhookBlocks + .map((block) => ('webhookId' in block ? block.webhookId : undefined)) + .filter(isDefined), + }, + }, + }) + return { + ...typebot, + version: '4', + groups: typebot.groups.map((group) => ({ + ...group, + blocks: group.blocks.map(migrateWebhookBlock(webhooks)), + })), + } +} + +const migrateWebhookBlock = + (webhooks: WebhookFromDb[]) => + (block: BlockV5): BlockV5 => { + if (!isWebhookBlock(block)) return block + const webhook = webhooks.find((webhook) => webhook.id === block.webhookId) + return { + ...block, + webhookId: undefined, + options: { + ...block.options, + webhook: webhook + ? { + id: webhook.id, + url: webhook.url ?? undefined, + method: (webhook.method as Webhook['method']) ?? HttpMethod.POST, + headers: (webhook.headers as Webhook['headers']) ?? [], + queryParams: (webhook.queryParams as Webhook['headers']) ?? [], + body: webhook.body ?? undefined, + } + : { + ...defaultWebhookAttributes, + id: 'webhookId' in block ? block.webhookId ?? '' : '', + }, + }, + } + } diff --git a/packages/lib/migrations/migrateTypebotFromV5ToV6.ts b/packages/lib/migrations/migrateTypebotFromV5ToV6.ts new file mode 100644 index 0000000..7733b1a --- /dev/null +++ b/packages/lib/migrations/migrateTypebotFromV5ToV6.ts @@ -0,0 +1,125 @@ +import { + BlockV5, + BlockV6, + GoogleSheetsBlockV5, + GoogleSheetsBlockV6, + PublicTypebotV5, + PublicTypebotV6, + TypebotV5, + TypebotV6, +} from '@typebot.io/schemas' +import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants' +import { GoogleSheetsAction } from '@typebot.io/schemas/features/blocks/integrations/googleSheets/constants' +import { ComparisonOperators } from '@typebot.io/schemas/features/blocks/logic/condition/constants' +import { createId } from '@paralleldrive/cuid2' +import { EventType } from '@typebot.io/schemas/features/events/constants' +import { byId } from '../utils' + +export const migrateTypebotFromV5ToV6 = async ( + typebot: TypebotV5 | PublicTypebotV5 +): Promise => { + const startGroup = typebot.groups.find((group) => + group.blocks.some((b) => b.type === 'start') + ) + + if (!startGroup) throw new Error('Start group not found') + + const startBlock = startGroup?.blocks.find((b) => b.type === 'start') + + if (!startBlock) throw new Error('Start block not found') + + const startOutgoingEdge = typebot.edges.find(byId(startBlock.outgoingEdgeId)) + + return { + ...typebot, + groups: migrateGroups( + typebot.groups.filter((g) => g.blocks.some((b) => b.type !== 'start')) + ), + version: '6', + events: [ + { + id: startGroup.id, + type: EventType.START, + graphCoordinates: startGroup.graphCoordinates, + outgoingEdgeId: startBlock.outgoingEdgeId, + }, + ], + edges: startOutgoingEdge + ? [ + { + ...startOutgoingEdge, + from: { + eventId: startGroup.id, + }, + }, + ...typebot.edges.filter((e) => e.id !== startOutgoingEdge.id), + ] + : typebot.edges, + } +} + +const migrateGroups = (groups: TypebotV5['groups']): TypebotV6['groups'] => + groups.map((group) => ({ + ...group, + blocks: migrateBlocksFromV1ToV2(group.blocks), + })) + +const migrateBlocksFromV1ToV2 = ( + blocks: TypebotV5['groups'][0]['blocks'] +): BlockV6[] => + ( + blocks.filter((block) => block.type !== 'start') as Exclude< + BlockV5, + { type: 'start' } + >[] + ).map((block) => { + if (block.type === IntegrationBlockType.GOOGLE_SHEETS) { + return { + ...block, + options: migrateGoogleSheetsOptions(block.options), + } + } + return block + }) + +const migrateGoogleSheetsOptions = ( + options: GoogleSheetsBlockV5['options'] +): GoogleSheetsBlockV6['options'] => { + if (!options) return + if (options.action === GoogleSheetsAction.GET) { + if (options.filter || !options.referenceCell) return options + return { + ...options, + filter: { + comparisons: [ + { + id: createId(), + column: options.referenceCell?.column, + comparisonOperator: ComparisonOperators.EQUAL, + value: options.referenceCell?.value, + }, + ], + }, + } + } + if (options.action === GoogleSheetsAction.INSERT_ROW) { + return options + } + if (options.action === GoogleSheetsAction.UPDATE_ROW) { + if (options.filter || !options.referenceCell) return options + return { + ...options, + filter: { + comparisons: [ + { + id: createId(), + column: options.referenceCell?.column, + comparisonOperator: ComparisonOperators.EQUAL, + value: options.referenceCell?.value, + }, + ], + }, + } + } + return options +} diff --git a/packages/lib/mockedUser.ts b/packages/lib/mockedUser.ts new file mode 100644 index 0000000..944815c --- /dev/null +++ b/packages/lib/mockedUser.ts @@ -0,0 +1,16 @@ +import { User } from '@typebot.io/prisma' + +export const mockedUser: User = { + id: 'userId', + name: 'John Doe', + email: 'user@email.com', + company: null, + createdAt: new Date('2022-01-01'), + emailVerified: null, + graphNavigation: 'TRACKPAD', + preferredAppAppearance: null, + image: 'https://avatars.githubusercontent.com/u/16015833?v=4', + lastActivityAt: new Date('2022-01-01'), + onboardingCategories: [], + updatedAt: new Date('2022-01-01'), +} diff --git a/packages/lib/package.json b/packages/lib/package.json new file mode 100644 index 0000000..2c2dd28 --- /dev/null +++ b/packages/lib/package.json @@ -0,0 +1,36 @@ +{ + "name": "@typebot.io/lib", + "version": "1.0.0", + "license": "AGPL-3.0-or-later", + "private": true, + "main": "./index.ts", + "types": "./index.ts", + "devDependencies": { + "@paralleldrive/cuid2": "2.2.1", + "@playwright/test": "1.36.0", + "@typebot.io/env": "workspace:*", + "@typebot.io/prisma": "workspace:*", + "@typebot.io/schemas": "workspace:*", + "@typebot.io/tsconfig": "workspace:*", + "@types/nodemailer": "6.4.8", + "next": "14.0.3", + "nodemailer": "6.9.3", + "typescript": "5.3.2", + "@typebot.io/forge-repository": "workspace:*" + }, + "peerDependencies": { + "next": "14.0.0", + "nodemailer": "6.7.8" + }, + "dependencies": { + "@sentry/nextjs": "7.77.0", + "@trpc/server": "10.40.0", + "@udecode/plate-common": "21.1.5", + "google-auth-library": "8.9.0", + "got": "12.6.0", + "minio": "7.1.3", + "remark-slate": "1.8.6", + "stripe": "12.13.0", + "zod": "3.22.4" + } +} diff --git a/packages/lib/parseVideoUrl.ts b/packages/lib/parseVideoUrl.ts new file mode 100644 index 0000000..870cb35 --- /dev/null +++ b/packages/lib/parseVideoUrl.ts @@ -0,0 +1,74 @@ +import { VideoBubbleBlock } from '@typebot.io/schemas' +import { + VideoBubbleContentType, + gumletRegex, + horizontalVideoSuggestionSize, + tiktokRegex, + verticalVideoSuggestionSize, + vimeoRegex, + youtubeRegex, +} from '@typebot.io/schemas/features/blocks/bubbles/video/constants' + +export const parseVideoUrl = ( + url: string +): { + type: VideoBubbleContentType + url: string + id?: string + videoSizeSuggestion?: Pick< + NonNullable, + 'aspectRatio' | 'maxWidth' + > +} => { + if (youtubeRegex.test(url)) { + const match = url.match(youtubeRegex) + const id = match?.at(2) ?? match?.at(3) + const parsedUrl = match?.at(0) ?? url + if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl } + return { + type: VideoBubbleContentType.YOUTUBE, + url: parsedUrl, + id, + videoSizeSuggestion: url.includes('shorts') + ? verticalVideoSuggestionSize + : horizontalVideoSuggestionSize, + } + } + if (vimeoRegex.test(url)) { + const match = url.match(vimeoRegex) + const id = match?.at(1) + const parsedUrl = match?.at(0) ?? url + if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl } + return { + type: VideoBubbleContentType.VIMEO, + url: parsedUrl, + id, + videoSizeSuggestion: horizontalVideoSuggestionSize, + } + } + if (tiktokRegex.test(url)) { + const match = url.match(tiktokRegex) + const id = url.match(tiktokRegex)?.at(1) + const parsedUrl = match?.at(0) ?? url + if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl } + return { + type: VideoBubbleContentType.TIKTOK, + url: parsedUrl, + id, + videoSizeSuggestion: verticalVideoSuggestionSize, + } + } + if (gumletRegex.test(url)) { + const match = url.match(gumletRegex) + const id = match?.at(1) + const parsedUrl = match?.at(0) ?? url + if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl } + return { + type: VideoBubbleContentType.GUMLET, + url: parsedUrl, + id, + videoSizeSuggestion: horizontalVideoSuggestionSize, + } + } + return { type: VideoBubbleContentType.URL, url } +} diff --git a/packages/lib/phoneCountries.ts b/packages/lib/phoneCountries.ts new file mode 100644 index 0000000..9ab6599 --- /dev/null +++ b/packages/lib/phoneCountries.ts @@ -0,0 +1,1484 @@ +export const phoneCountries = [ + { + name: 'International', + flag: '🌐', + code: 'INT', + dial_code: null, + }, + { + name: 'Afghanistan', + flag: '🇦🇫', + code: 'AF', + dial_code: '+93', + }, + { + name: 'Åland Islands', + flag: '🇦🇽', + code: 'AX', + dial_code: '+358', + }, + { + name: 'Albania', + flag: '🇦🇱', + code: 'AL', + dial_code: '+355', + }, + { + name: 'Algeria', + flag: '🇩🇿', + code: 'DZ', + dial_code: '+213', + }, + { + name: 'American Samoa', + flag: '🇦🇸', + code: 'AS', + dial_code: '+1684', + }, + { + name: 'Andorra', + flag: '🇦🇩', + code: 'AD', + dial_code: '+376', + }, + { + name: 'Angola', + flag: '🇦🇴', + code: 'AO', + dial_code: '+244', + }, + { + name: 'Anguilla', + flag: '🇦🇮', + code: 'AI', + dial_code: '+1264', + }, + { + name: 'Antarctica', + flag: '🇦🇶', + code: 'AQ', + dial_code: '+672', + }, + { + name: 'Antigua and Barbuda', + flag: '🇦🇬', + code: 'AG', + dial_code: '+1268', + }, + { + name: 'Argentina', + flag: '🇦🇷', + code: 'AR', + dial_code: '+54', + }, + { + name: 'Armenia', + flag: '🇦🇲', + code: 'AM', + dial_code: '+374', + }, + { + name: 'Aruba', + flag: '🇦🇼', + code: 'AW', + dial_code: '+297', + }, + { + name: 'Australia', + flag: '🇦🇺', + code: 'AU', + dial_code: '+61', + }, + { + name: 'Austria', + flag: '🇦🇹', + code: 'AT', + dial_code: '+43', + }, + { + name: 'Azerbaijan', + flag: '🇦🇿', + code: 'AZ', + dial_code: '+994', + }, + { + name: 'Bahamas', + flag: '🇧🇸', + code: 'BS', + dial_code: '+1242', + }, + { + name: 'Bahrain', + flag: '🇧🇭', + code: 'BH', + dial_code: '+973', + }, + { + name: 'Bangladesh', + flag: '🇧🇩', + code: 'BD', + dial_code: '+880', + }, + { + name: 'Barbados', + flag: '🇧🇧', + code: 'BB', + dial_code: '+1246', + }, + { + name: 'Belarus', + flag: '🇧🇾', + code: 'BY', + dial_code: '+375', + }, + { + name: 'Belgium', + flag: '🇧🇪', + code: 'BE', + dial_code: '+32', + }, + { + name: 'Belize', + flag: '🇧🇿', + code: 'BZ', + dial_code: '+501', + }, + { + name: 'Benin', + flag: '🇧🇯', + code: 'BJ', + dial_code: '+229', + }, + { + name: 'Bermuda', + flag: '🇧🇲', + code: 'BM', + dial_code: '+1441', + }, + { + name: 'Bhutan', + flag: '🇧🇹', + code: 'BT', + dial_code: '+975', + }, + { + name: 'Bolivia, Plurinational State of bolivia', + flag: '🇧🇴', + code: 'BO', + dial_code: '+591', + }, + { + name: 'Bosnia and Herzegovina', + flag: '🇧🇦', + code: 'BA', + dial_code: '+387', + }, + { + name: 'Botswana', + flag: '🇧🇼', + code: 'BW', + dial_code: '+267', + }, + { + name: 'Bouvet Island', + flag: '🇧🇻', + code: 'BV', + dial_code: '+47', + }, + { + name: 'Brazil', + flag: '🇧🇷', + code: 'BR', + dial_code: '+55', + }, + { + name: 'British Indian Ocean Territory', + flag: '🇮🇴', + code: 'IO', + dial_code: '+246', + }, + { + name: 'Brunei Darussalam', + flag: '🇧🇳', + code: 'BN', + dial_code: '+673', + }, + { + name: 'Bulgaria', + flag: '🇧🇬', + code: 'BG', + dial_code: '+359', + }, + { + name: 'Burkina Faso', + flag: '🇧🇫', + code: 'BF', + dial_code: '+226', + }, + { + name: 'Burundi', + flag: '🇧🇮', + code: 'BI', + dial_code: '+257', + }, + { + name: 'Cambodia', + flag: '🇰🇭', + code: 'KH', + dial_code: '+855', + }, + { + name: 'Cameroon', + flag: '🇨🇲', + code: 'CM', + dial_code: '+237', + }, + { + name: 'Canada', + flag: '🇨🇦', + code: 'CA', + dial_code: '+1', + }, + { + name: 'Cape Verde', + flag: '🇨🇻', + code: 'CV', + dial_code: '+238', + }, + { + name: 'Cayman Islands', + flag: '🇰🇾', + code: 'KY', + dial_code: '+345', + }, + { + name: 'Central African Republic', + flag: '🇨🇫', + code: 'CF', + dial_code: '+236', + }, + { + name: 'Chad', + flag: '🇹🇩', + code: 'TD', + dial_code: '+235', + }, + { + name: 'Chile', + flag: '🇨🇱', + code: 'CL', + dial_code: '+56', + }, + { + name: 'China', + flag: '🇨🇳', + code: 'CN', + dial_code: '+86', + }, + { + name: 'Christmas Island', + flag: '🇨🇽', + code: 'CX', + dial_code: '+61', + }, + { + name: 'Cocos (Keeling) Islands', + flag: '🇨🇨', + code: 'CC', + dial_code: '+61', + }, + { + name: 'Colombia', + flag: '🇨🇴', + code: 'CO', + dial_code: '+57', + }, + { + name: 'Comoros', + flag: '🇰🇲', + code: 'KM', + dial_code: '+269', + }, + { + name: 'Congo', + flag: '🇨🇬', + code: 'CG', + dial_code: '+242', + }, + { + name: 'Congo, The Democratic Republic of the Congo', + flag: '🇨🇩', + code: 'CD', + dial_code: '+243', + }, + { + name: 'Cook Islands', + flag: '🇨🇰', + code: 'CK', + dial_code: '+682', + }, + { + name: 'Costa Rica', + flag: '🇨🇷', + code: 'CR', + dial_code: '+506', + }, + { + name: "Cote d'Ivoire", + flag: '🇨🇮', + code: 'CI', + dial_code: '+225', + }, + { + name: 'Croatia', + flag: '🇭🇷', + code: 'HR', + dial_code: '+385', + }, + { + name: 'Cuba', + flag: '🇨🇺', + code: 'CU', + dial_code: '+53', + }, + { + name: 'Cyprus', + flag: '🇨🇾', + code: 'CY', + dial_code: '+357', + }, + { + name: 'Czech Republic', + flag: '🇨🇿', + code: 'CZ', + dial_code: '+420', + }, + { + name: 'Denmark', + flag: '🇩🇰', + code: 'DK', + dial_code: '+45', + }, + { + name: 'Djibouti', + flag: '🇩🇯', + code: 'DJ', + dial_code: '+253', + }, + { + name: 'Dominica', + flag: '🇩🇲', + code: 'DM', + dial_code: '+1767', + }, + { + name: 'Dominican Republic', + flag: '🇩🇴', + code: 'DO', + dial_code: '+1849', + }, + { + name: 'Ecuador', + flag: '🇪🇨', + code: 'EC', + dial_code: '+593', + }, + { + name: 'Egypt', + flag: '🇪🇬', + code: 'EG', + dial_code: '+20', + }, + { + name: 'El Salvador', + flag: '🇸🇻', + code: 'SV', + dial_code: '+503', + }, + { + name: 'Equatorial Guinea', + flag: '🇬🇶', + code: 'GQ', + dial_code: '+240', + }, + { + name: 'Eritrea', + flag: '🇪🇷', + code: 'ER', + dial_code: '+291', + }, + { + name: 'Estonia', + flag: '🇪🇪', + code: 'EE', + dial_code: '+372', + }, + { + name: 'Ethiopia', + flag: '🇪🇹', + code: 'ET', + dial_code: '+251', + }, + { + name: 'Falkland Islands (Malvinas)', + flag: '🇫🇰', + code: 'FK', + dial_code: '+500', + }, + { + name: 'Faroe Islands', + flag: '🇫🇴', + code: 'FO', + dial_code: '+298', + }, + { + name: 'Fiji', + flag: '🇫🇯', + code: 'FJ', + dial_code: '+679', + }, + { + name: 'Finland', + flag: '🇫🇮', + code: 'FI', + dial_code: '+358', + }, + { + name: 'France', + flag: '🇫🇷', + code: 'FR', + dial_code: '+33', + }, + { + name: 'French Guiana', + flag: '🇬🇫', + code: 'GF', + dial_code: '+594', + }, + { + name: 'French Polynesia', + flag: '🇵🇫', + code: 'PF', + dial_code: '+689', + }, + { + name: 'French Southern Territories', + flag: '🇹🇫', + code: 'TF', + dial_code: '+262', + }, + { + name: 'Gabon', + flag: '🇬🇦', + code: 'GA', + dial_code: '+241', + }, + { + name: 'Gambia', + flag: '🇬🇲', + code: 'GM', + dial_code: '+220', + }, + { + name: 'Georgia', + flag: '🇬🇪', + code: 'GE', + dial_code: '+995', + }, + { + name: 'Germany', + flag: '🇩🇪', + code: 'DE', + dial_code: '+49', + }, + { + name: 'Ghana', + flag: '🇬🇭', + code: 'GH', + dial_code: '+233', + }, + { + name: 'Gibraltar', + flag: '🇬🇮', + code: 'GI', + dial_code: '+350', + }, + { + name: 'Greece', + flag: '🇬🇷', + code: 'GR', + dial_code: '+30', + }, + { + name: 'Greenland', + flag: '🇬🇱', + code: 'GL', + dial_code: '+299', + }, + { + name: 'Grenada', + flag: '🇬🇩', + code: 'GD', + dial_code: '+1473', + }, + { + name: 'Guadeloupe', + flag: '🇬🇵', + code: 'GP', + dial_code: '+590', + }, + { + name: 'Guam', + flag: '🇬🇺', + code: 'GU', + dial_code: '+1671', + }, + { + name: 'Guatemala', + flag: '🇬🇹', + code: 'GT', + dial_code: '+502', + }, + { + name: 'Guernsey', + flag: '🇬🇬', + code: 'GG', + dial_code: '+44', + }, + { + name: 'Guinea', + flag: '🇬🇳', + code: 'GN', + dial_code: '+224', + }, + { + name: 'Guinea-Bissau', + flag: '🇬🇼', + code: 'GW', + dial_code: '+245', + }, + { + name: 'Guyana', + flag: '🇬🇾', + code: 'GY', + dial_code: '+592', + }, + { + name: 'Haiti', + flag: '🇭🇹', + code: 'HT', + dial_code: '+509', + }, + { + name: 'Heard Island and Mcdonald Islands', + flag: '🇭🇲', + code: 'HM', + dial_code: '+672', + }, + { + name: 'Holy See (Vatican City State)', + flag: '🇻🇦', + code: 'VA', + dial_code: '+379', + }, + { + name: 'Honduras', + flag: '🇭🇳', + code: 'HN', + dial_code: '+504', + }, + { + name: 'Hong Kong', + flag: '🇭🇰', + code: 'HK', + dial_code: '+852', + }, + { + name: 'Hungary', + flag: '🇭🇺', + code: 'HU', + dial_code: '+36', + }, + { + name: 'Iceland', + flag: '🇮🇸', + code: 'IS', + dial_code: '+354', + }, + { + name: 'India', + flag: '🇮🇳', + code: 'IN', + dial_code: '+91', + }, + { + name: 'Indonesia', + flag: '🇮🇩', + code: 'ID', + dial_code: '+62', + }, + { + name: 'Iran, Islamic Republic of Persian Gulf', + flag: '🇮🇷', + code: 'IR', + dial_code: '+98', + }, + { + name: 'Iraq', + flag: '🇮🇶', + code: 'IQ', + dial_code: '+964', + }, + { + name: 'Ireland', + flag: '🇮🇪', + code: 'IE', + dial_code: '+353', + }, + { + name: 'Isle of Man', + flag: '🇮🇲', + code: 'IM', + dial_code: '+44', + }, + { + name: 'Israel', + flag: '🇮🇱', + code: 'IL', + dial_code: '+972', + }, + { + name: 'Italy', + flag: '🇮🇹', + code: 'IT', + dial_code: '+39', + }, + { + name: 'Jamaica', + flag: '🇯🇲', + code: 'JM', + dial_code: '+1876', + }, + { + name: 'Japan', + flag: '🇯🇵', + code: 'JP', + dial_code: '+81', + }, + { + name: 'Jersey', + flag: '🇯🇪', + code: 'JE', + dial_code: '+44', + }, + { + name: 'Jordan', + flag: '🇯🇴', + code: 'JO', + dial_code: '+962', + }, + { + name: 'Kazakhstan', + flag: '🇰🇿', + code: 'KZ', + dial_code: '+7', + }, + { + name: 'Kenya', + flag: '🇰🇪', + code: 'KE', + dial_code: '+254', + }, + { + name: 'Kiribati', + flag: '🇰🇮', + code: 'KI', + dial_code: '+686', + }, + { + name: "Korea, Democratic People's Republic of Korea", + flag: '🇰🇵', + code: 'KP', + dial_code: '+850', + }, + { + name: 'Korea, Republic of South Korea', + flag: '🇰🇷', + code: 'KR', + dial_code: '+82', + }, + { + name: 'Kosovo', + flag: '🇽🇰', + code: 'XK', + dial_code: '+383', + }, + { + name: 'Kuwait', + flag: '🇰🇼', + code: 'KW', + dial_code: '+965', + }, + { + name: 'Kyrgyzstan', + flag: '🇰🇬', + code: 'KG', + dial_code: '+996', + }, + { + name: 'Laos', + flag: '🇱🇦', + code: 'LA', + dial_code: '+856', + }, + { + name: 'Latvia', + flag: '🇱🇻', + code: 'LV', + dial_code: '+371', + }, + { + name: 'Lebanon', + flag: '🇱🇧', + code: 'LB', + dial_code: '+961', + }, + { + name: 'Lesotho', + flag: '🇱🇸', + code: 'LS', + dial_code: '+266', + }, + { + name: 'Liberia', + flag: '🇱🇷', + code: 'LR', + dial_code: '+231', + }, + { + name: 'Libyan Arab Jamahiriya', + flag: '🇱🇾', + code: 'LY', + dial_code: '+218', + }, + { + name: 'Liechtenstein', + flag: '🇱🇮', + code: 'LI', + dial_code: '+423', + }, + { + name: 'Lithuania', + flag: '🇱🇹', + code: 'LT', + dial_code: '+370', + }, + { + name: 'Luxembourg', + flag: '🇱🇺', + code: 'LU', + dial_code: '+352', + }, + { + name: 'Macao', + flag: '🇲🇴', + code: 'MO', + dial_code: '+853', + }, + { + name: 'Macedonia', + flag: '🇲🇰', + code: 'MK', + dial_code: '+389', + }, + { + name: 'Madagascar', + flag: '🇲🇬', + code: 'MG', + dial_code: '+261', + }, + { + name: 'Malawi', + flag: '🇲🇼', + code: 'MW', + dial_code: '+265', + }, + { + name: 'Malaysia', + flag: '🇲🇾', + code: 'MY', + dial_code: '+60', + }, + { + name: 'Maldives', + flag: '🇲🇻', + code: 'MV', + dial_code: '+960', + }, + { + name: 'Mali', + flag: '🇲🇱', + code: 'ML', + dial_code: '+223', + }, + { + name: 'Malta', + flag: '🇲🇹', + code: 'MT', + dial_code: '+356', + }, + { + name: 'Marshall Islands', + flag: '🇲🇭', + code: 'MH', + dial_code: '+692', + }, + { + name: 'Martinique', + flag: '🇲🇶', + code: 'MQ', + dial_code: '+596', + }, + { + name: 'Mauritania', + flag: '🇲🇷', + code: 'MR', + dial_code: '+222', + }, + { + name: 'Mauritius', + flag: '🇲🇺', + code: 'MU', + dial_code: '+230', + }, + { + name: 'Mayotte', + flag: '🇾🇹', + code: 'YT', + dial_code: '+262', + }, + { + name: 'Mexico', + flag: '🇲🇽', + code: 'MX', + dial_code: '+52', + }, + { + name: 'Micronesia, Federated States of Micronesia', + flag: '🇫🇲', + code: 'FM', + dial_code: '+691', + }, + { + name: 'Moldova', + flag: '🇲🇩', + code: 'MD', + dial_code: '+373', + }, + { + name: 'Monaco', + flag: '🇲🇨', + code: 'MC', + dial_code: '+377', + }, + { + name: 'Mongolia', + flag: '🇲🇳', + code: 'MN', + dial_code: '+976', + }, + { + name: 'Montenegro', + flag: '🇲🇪', + code: 'ME', + dial_code: '+382', + }, + { + name: 'Montserrat', + flag: '🇲🇸', + code: 'MS', + dial_code: '+1664', + }, + { + name: 'Morocco', + flag: '🇲🇦', + code: 'MA', + dial_code: '+212', + }, + { + name: 'Mozambique', + flag: '🇲🇿', + code: 'MZ', + dial_code: '+258', + }, + { + name: 'Myanmar', + flag: '🇲🇲', + code: 'MM', + dial_code: '+95', + }, + { + name: 'Namibia', + flag: '🇳🇦', + code: 'NA', + dial_code: '+264', + }, + { + name: 'Nauru', + flag: '🇳🇷', + code: 'NR', + dial_code: '+674', + }, + { + name: 'Nepal', + flag: '🇳🇵', + code: 'NP', + dial_code: '+977', + }, + { + name: 'Netherlands', + flag: '🇳🇱', + code: 'NL', + dial_code: '+31', + }, + { + name: 'Netherlands Antilles', + flag: '', + code: 'AN', + dial_code: '+599', + }, + { + name: 'New Caledonia', + flag: '🇳🇨', + code: 'NC', + dial_code: '+687', + }, + { + name: 'New Zealand', + flag: '🇳🇿', + code: 'NZ', + dial_code: '+64', + }, + { + name: 'Nicaragua', + flag: '🇳🇮', + code: 'NI', + dial_code: '+505', + }, + { + name: 'Niger', + flag: '🇳🇪', + code: 'NE', + dial_code: '+227', + }, + { + name: 'Nigeria', + flag: '🇳🇬', + code: 'NG', + dial_code: '+234', + }, + { + name: 'Niue', + flag: '🇳🇺', + code: 'NU', + dial_code: '+683', + }, + { + name: 'Norfolk Island', + flag: '🇳🇫', + code: 'NF', + dial_code: '+672', + }, + { + name: 'Northern Mariana Islands', + flag: '🇲🇵', + code: 'MP', + dial_code: '+1670', + }, + { + name: 'Norway', + flag: '🇳🇴', + code: 'NO', + dial_code: '+47', + }, + { + name: 'Oman', + flag: '🇴🇲', + code: 'OM', + dial_code: '+968', + }, + { + name: 'Pakistan', + flag: '🇵🇰', + code: 'PK', + dial_code: '+92', + }, + { + name: 'Palau', + flag: '🇵🇼', + code: 'PW', + dial_code: '+680', + }, + { + name: 'Palestinian Territory, Occupied', + flag: '🇵🇸', + code: 'PS', + dial_code: '+970', + }, + { + name: 'Panama', + flag: '🇵🇦', + code: 'PA', + dial_code: '+507', + }, + { + name: 'Papua New Guinea', + flag: '🇵🇬', + code: 'PG', + dial_code: '+675', + }, + { + name: 'Paraguay', + flag: '🇵🇾', + code: 'PY', + dial_code: '+595', + }, + { + name: 'Peru', + flag: '🇵🇪', + code: 'PE', + dial_code: '+51', + }, + { + name: 'Philippines', + flag: '🇵🇭', + code: 'PH', + dial_code: '+63', + }, + { + name: 'Pitcairn', + flag: '🇵🇳', + code: 'PN', + dial_code: '+64', + }, + { + name: 'Poland', + flag: '🇵🇱', + code: 'PL', + dial_code: '+48', + }, + { + name: 'Portugal', + flag: '🇵🇹', + code: 'PT', + dial_code: '+351', + }, + { + name: 'Puerto Rico', + flag: '🇵🇷', + code: 'PR', + dial_code: '+1939', + }, + { + name: 'Qatar', + flag: '🇶🇦', + code: 'QA', + dial_code: '+974', + }, + { + name: 'Romania', + flag: '🇷🇴', + code: 'RO', + dial_code: '+40', + }, + { + name: 'Russia', + flag: '🇷🇺', + code: 'RU', + dial_code: '+7', + }, + { + name: 'Rwanda', + flag: '🇷🇼', + code: 'RW', + dial_code: '+250', + }, + { + name: 'Reunion', + flag: '🇷🇪', + code: 'RE', + dial_code: '+262', + }, + { + name: 'Saint Barthelemy', + flag: '🇧🇱', + code: 'BL', + dial_code: '+590', + }, + { + name: 'Saint Helena, Ascension and Tristan Da Cunha', + flag: '🇸🇭', + code: 'SH', + dial_code: '+290', + }, + { + name: 'Saint Kitts and Nevis', + flag: '🇰🇳', + code: 'KN', + dial_code: '+1869', + }, + { + name: 'Saint Lucia', + flag: '🇱🇨', + code: 'LC', + dial_code: '+1758', + }, + { + name: 'Saint Martin', + flag: '🇲🇫', + code: 'MF', + dial_code: '+590', + }, + { + name: 'Saint Pierre and Miquelon', + flag: '🇵🇲', + code: 'PM', + dial_code: '+508', + }, + { + name: 'Saint Vincent and the Grenadines', + flag: '🇻🇨', + code: 'VC', + dial_code: '+1784', + }, + { + name: 'Samoa', + flag: '🇼🇸', + code: 'WS', + dial_code: '+685', + }, + { + name: 'San Marino', + flag: '🇸🇲', + code: 'SM', + dial_code: '+378', + }, + { + name: 'Sao Tome and Principe', + flag: '🇸🇹', + code: 'ST', + dial_code: '+239', + }, + { + name: 'Saudi Arabia', + flag: '🇸🇦', + code: 'SA', + dial_code: '+966', + }, + { + name: 'Senegal', + flag: '🇸🇳', + code: 'SN', + dial_code: '+221', + }, + { + name: 'Serbia', + flag: '🇷🇸', + code: 'RS', + dial_code: '+381', + }, + { + name: 'Seychelles', + flag: '🇸🇨', + code: 'SC', + dial_code: '+248', + }, + { + name: 'Sierra Leone', + flag: '🇸🇱', + code: 'SL', + dial_code: '+232', + }, + { + name: 'Singapore', + flag: '🇸🇬', + code: 'SG', + dial_code: '+65', + }, + { + name: 'Slovakia', + flag: '🇸🇰', + code: 'SK', + dial_code: '+421', + }, + { + name: 'Slovenia', + flag: '🇸🇮', + code: 'SI', + dial_code: '+386', + }, + { + name: 'Solomon Islands', + flag: '🇸🇧', + code: 'SB', + dial_code: '+677', + }, + { + name: 'Somalia', + flag: '🇸🇴', + code: 'SO', + dial_code: '+252', + }, + { + name: 'South Africa', + flag: '🇿🇦', + code: 'ZA', + dial_code: '+27', + }, + { + name: 'South Sudan', + flag: '🇸🇸', + code: 'SS', + dial_code: '+211', + }, + { + name: 'South Georgia and the South Sandwich Islands', + flag: '🇬🇸', + code: 'GS', + dial_code: '+500', + }, + { + name: 'Spain', + flag: '🇪🇸', + code: 'ES', + dial_code: '+34', + }, + { + name: 'Sri Lanka', + flag: '🇱🇰', + code: 'LK', + dial_code: '+94', + }, + { + name: 'Sudan', + flag: '🇸🇩', + code: 'SD', + dial_code: '+249', + }, + { + name: 'Suriname', + flag: '🇸🇷', + code: 'SR', + dial_code: '+597', + }, + { + name: 'Svalbard and Jan Mayen', + flag: '🇸🇯', + code: 'SJ', + dial_code: '+47', + }, + { + name: 'Swaziland', + flag: '🇸🇿', + code: 'SZ', + dial_code: '+268', + }, + { + name: 'Sweden', + flag: '🇸🇪', + code: 'SE', + dial_code: '+46', + }, + { + name: 'Switzerland', + flag: '🇨🇭', + code: 'CH', + dial_code: '+41', + }, + { + name: 'Syrian Arab Republic', + flag: '🇸🇾', + code: 'SY', + dial_code: '+963', + }, + { + name: 'Taiwan', + flag: '🇹🇼', + code: 'TW', + dial_code: '+886', + }, + { + name: 'Tajikistan', + flag: '🇹🇯', + code: 'TJ', + dial_code: '+992', + }, + { + name: 'Tanzania, United Republic of Tanzania', + flag: '🇹🇿', + code: 'TZ', + dial_code: '+255', + }, + { + name: 'Thailand', + flag: '🇹🇭', + code: 'TH', + dial_code: '+66', + }, + { + name: 'Timor-Leste', + flag: '🇹🇱', + code: 'TL', + dial_code: '+670', + }, + { + name: 'Togo', + flag: '🇹🇬', + code: 'TG', + dial_code: '+228', + }, + { + name: 'Tokelau', + flag: '🇹🇰', + code: 'TK', + dial_code: '+690', + }, + { + name: 'Tonga', + flag: '🇹🇴', + code: 'TO', + dial_code: '+676', + }, + { + name: 'Trinidad and Tobago', + flag: '🇹🇹', + code: 'TT', + dial_code: '+1868', + }, + { + name: 'Tunisia', + flag: '🇹🇳', + code: 'TN', + dial_code: '+216', + }, + { + name: 'Turkey', + flag: '🇹🇷', + code: 'TR', + dial_code: '+90', + }, + { + name: 'Turkmenistan', + flag: '🇹🇲', + code: 'TM', + dial_code: '+993', + }, + { + name: 'Turks and Caicos Islands', + flag: '🇹🇨', + code: 'TC', + dial_code: '+1649', + }, + { + name: 'Tuvalu', + flag: '🇹🇻', + code: 'TV', + dial_code: '+688', + }, + { + name: 'Uganda', + flag: '🇺🇬', + code: 'UG', + dial_code: '+256', + }, + { + name: 'Ukraine', + flag: '🇺🇦', + code: 'UA', + dial_code: '+380', + }, + { + name: 'United Arab Emirates', + flag: '🇦🇪', + code: 'AE', + dial_code: '+971', + }, + { + name: 'United Kingdom', + flag: '🇬🇧', + code: 'GB', + dial_code: '+44', + }, + { + name: 'United States', + flag: '🇺🇸', + code: 'US', + dial_code: '+1', + }, + { + name: 'Uruguay', + flag: '🇺🇾', + code: 'UY', + dial_code: '+598', + }, + { + name: 'Uzbekistan', + flag: '🇺🇿', + code: 'UZ', + dial_code: '+998', + }, + { + name: 'Vanuatu', + flag: '🇻🇺', + code: 'VU', + dial_code: '+678', + }, + { + name: 'Venezuela, Bolivarian Republic of Venezuela', + flag: '🇻🇪', + code: 'VE', + dial_code: '+58', + }, + { + name: 'Vietnam', + flag: '🇻🇳', + code: 'VN', + dial_code: '+84', + }, + { + name: 'Virgin Islands, British', + flag: '🇻🇬', + code: 'VG', + dial_code: '+1284', + }, + { + name: 'Virgin Islands, U.S.', + flag: '🇻🇮', + code: 'VI', + dial_code: '+1340', + }, + { + name: 'Wallis and Futuna', + flag: '🇼🇫', + code: 'WF', + dial_code: '+681', + }, + { + name: 'Yemen', + flag: '🇾🇪', + code: 'YE', + dial_code: '+967', + }, + { + name: 'Zambia', + flag: '🇿🇲', + code: 'ZM', + dial_code: '+260', + }, + { + name: 'Zimbabwe', + flag: '🇿🇼', + code: 'ZW', + dial_code: '+263', + }, +] as const diff --git a/packages/lib/playwright/baseConfig.ts b/packages/lib/playwright/baseConfig.ts new file mode 100644 index 0000000..4a6ea08 --- /dev/null +++ b/packages/lib/playwright/baseConfig.ts @@ -0,0 +1,32 @@ +import { PlaywrightTestConfig } from '@playwright/test' +import path from 'path' + +export const playwrightBaseConfig: PlaywrightTestConfig = { + globalSetup: require.resolve(path.join(__dirname, 'globalSetup')), + timeout: process.env.CI ? 50 * 1000 : 40 * 1000, + expect: { + timeout: process.env.CI ? 10 * 1000 : 5 * 1000, + }, + retries: process.env.NO_RETRIES ? 0 : 1, + workers: process.env.CI ? 2 : 3, + reporter: [ + [process.env.CI ? 'github' : 'list'], + ['html', { outputFolder: 'src/test/reporters' }], + ], + maxFailures: process.env.CI ? 10 : undefined, + webServer: process.env.CI + ? { + command: 'pnpm run start', + timeout: 60_000, + reuseExistingServer: true, + } + : undefined, + outputDir: './src/test/results', + use: { + trace: 'on-first-retry', + video: 'retain-on-failure', + locale: 'en-US', + browserName: 'chromium', + viewport: { width: 1400, height: 1000 }, + }, +} diff --git a/packages/lib/playwright/databaseActions.ts b/packages/lib/playwright/databaseActions.ts new file mode 100644 index 0000000..2f9062d --- /dev/null +++ b/packages/lib/playwright/databaseActions.ts @@ -0,0 +1,234 @@ +import { + Plan, + Prisma, + PrismaClient, + User, + Workspace, + WorkspaceRole, +} from '@typebot.io/prisma' +import { createId } from '@paralleldrive/cuid2' +import { Typebot, TypebotV6, Webhook } from '@typebot.io/schemas' +import { readFileSync } from 'fs' +import { proWorkspaceId, userId } from './databaseSetup' +import { + parseTestTypebot, + parseTypebotToPublicTypebot, +} from './databaseHelpers' + +const prisma = new PrismaClient() + +type CreateFakeResultsProps = { + typebotId: string + count: number + customResultIdPrefix?: string + isChronological?: boolean +} + +export const injectFakeResults = async ({ + count, + customResultIdPrefix, + typebotId, + isChronological, +}: CreateFakeResultsProps) => { + const resultIdPrefix = customResultIdPrefix ?? createId() + await prisma.result.createMany({ + data: [ + ...Array.from(Array(count)).map((_, idx) => { + const today = new Date() + const rand = Math.random() + return { + id: `${resultIdPrefix}-result${idx}`, + typebotId, + createdAt: isChronological + ? new Date( + today.setTime(today.getTime() + 1000 * 60 * 60 * 24 * idx) + ) + : new Date(), + isCompleted: rand > 0.5, + hasStarted: true, + variables: [], + } satisfies Prisma.ResultCreateManyInput + }), + ], + }) + return createAnswers({ resultIdPrefix, count }) +} + +const createAnswers = ({ + count, + resultIdPrefix, +}: { resultIdPrefix: string } & Pick) => { + return prisma.answer.createMany({ + data: [ + ...Array.from(Array(count)).map((_, idx) => ({ + resultId: `${resultIdPrefix}-result${idx}`, + content: `content${idx}`, + blockId: 'block1', + groupId: 'group1', + })), + ], + }) +} + +export const importTypebotInDatabase = async ( + path: string, + updates?: Partial +) => { + const typebotFile = JSON.parse(readFileSync(path).toString()) + const typebot = { + events: null, + ...typebotFile, + workspaceId: proWorkspaceId, + ...updates, + } + await prisma.typebot.create({ + data: parseCreateTypebot(typebot), + }) + return prisma.publicTypebot.create({ + data: { + ...parseTypebotToPublicTypebot( + updates?.id ? `${updates?.id}-public` : 'publicBot', + typebot + ), + events: typebot.events === null ? Prisma.DbNull : typebot.events, + }, + }) +} + +export const deleteWorkspaces = async (workspaceIds: string[]) => { + await prisma.workspace.deleteMany({ + where: { id: { in: workspaceIds } }, + }) +} + +export const deleteTypebots = async (typebotIds: string[]) => { + await prisma.typebot.deleteMany({ + where: { id: { in: typebotIds } }, + }) +} + +export const deleteCredentials = async (credentialIds: string[]) => { + await prisma.credentials.deleteMany({ + where: { id: { in: credentialIds } }, + }) +} + +export const deleteWebhooks = async (webhookIds: string[]) => { + await prisma.webhook.deleteMany({ + where: { id: { in: webhookIds } }, + }) +} + +export const createWorkspaces = async (workspaces: Partial[]) => { + const workspaceIds = workspaces.map((workspace) => workspace.id ?? createId()) + await prisma.workspace.createMany({ + data: workspaces.map((workspace, index) => ({ + id: workspaceIds[index], + name: 'Free workspace', + plan: Plan.FREE, + ...workspace, + })), + }) + await prisma.memberInWorkspace.createMany({ + data: workspaces.map((_, index) => ({ + userId, + workspaceId: workspaceIds[index], + role: WorkspaceRole.ADMIN, + })), + }) + return workspaceIds +} + +export const updateUser = (data: Partial) => + prisma.user.update({ + data: { + ...data, + onboardingCategories: data.onboardingCategories ?? [], + }, + where: { + id: userId, + }, + }) + +export const createWebhook = async ( + typebotId: string, + webhookProps?: Partial +) => { + try { + await prisma.webhook.delete({ where: { id: 'webhook1' } }) + } catch {} + return prisma.webhook.create({ + data: { + method: 'GET', + typebotId, + id: 'webhook1', + ...webhookProps, + queryParams: webhookProps?.queryParams ?? [], + headers: webhookProps?.headers ?? [], + }, + }) +} + +export const createTypebots = async (partialTypebots: Partial[]) => { + const typebotsWithId = partialTypebots.map((typebot) => { + const typebotId = typebot.id ?? createId() + return { + ...typebot, + id: typebotId, + publicId: typebot.publicId ?? typebotId + '-public', + } + }) + await prisma.typebot.createMany({ + data: typebotsWithId.map(parseTestTypebot).map(parseCreateTypebot), + }) + return prisma.publicTypebot.createMany({ + data: typebotsWithId.map((t) => ({ + ...parseTypebotToPublicTypebot(t.publicId, parseTestTypebot(t)), + })) as any, + }) +} + +export const updateTypebot = async ( + partialTypebot: Partial & { id: string } +) => { + await prisma.typebot.updateMany({ + where: { id: partialTypebot.id }, + data: parseUpdateTypebot(partialTypebot), + }) + return prisma.publicTypebot.updateMany({ + where: { typebotId: partialTypebot.id }, + data: { + ...partialTypebot, + events: + partialTypebot.events === null ? Prisma.DbNull : partialTypebot.events, + }, + }) +} + +export const updateWorkspace = async ( + id: string, + data: Prisma.WorkspaceUncheckedUpdateManyInput +) => { + await prisma.workspace.updateMany({ + where: { id: proWorkspaceId }, + data, + }) +} + +export const parseCreateTypebot = (typebot: Typebot) => ({ + ...typebot, + resultsTablePreferences: + typebot.resultsTablePreferences === null + ? Prisma.DbNull + : typebot.resultsTablePreferences, + events: typebot.events === null ? Prisma.DbNull : typebot.events, +}) + +const parseUpdateTypebot = (typebot: Partial) => ({ + ...typebot, + resultsTablePreferences: + typebot.resultsTablePreferences === null + ? Prisma.DbNull + : typebot.resultsTablePreferences, + events: typebot.events === null ? Prisma.DbNull : typebot.events, +}) diff --git a/packages/lib/playwright/databaseHelpers.ts b/packages/lib/playwright/databaseHelpers.ts new file mode 100644 index 0000000..b66476e --- /dev/null +++ b/packages/lib/playwright/databaseHelpers.ts @@ -0,0 +1,129 @@ +import { createId } from '@paralleldrive/cuid2' +import { + BlockV5, + BlockV6, + Group, + PublicTypebot, + Typebot, + TypebotV6, +} from '@typebot.io/schemas' +import { isDefined } from '../utils' +import { proWorkspaceId } from './databaseSetup' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' +import { EventType } from '@typebot.io/schemas/features/events/constants' + +export const parseTestTypebot = (partialTypebot: Partial): Typebot => { + const version = partialTypebot.version ?? ('3' as any) + + return { + id: createId(), + version, + workspaceId: proWorkspaceId, + folderId: null, + name: 'My typebot', + theme: {}, + settings: {}, + publicId: null, + updatedAt: new Date(), + createdAt: new Date(), + customDomain: null, + icon: null, + selectedThemeTemplateId: null, + isArchived: false, + isClosed: false, + resultsTablePreferences: null, + whatsAppCredentialsId: null, + riskLevel: null, + events: + version === '6' + ? [ + { + id: 'group1', + type: EventType.START, + graphCoordinates: { x: 0, y: 0 }, + outgoingEdgeId: 'edge1', + }, + ] + : null, + variables: [{ id: 'var1', name: 'var1' }], + ...partialTypebot, + edges: [ + { + id: 'edge1', + from: { blockId: 'block0' }, + to: { groupId: 'group1' }, + }, + ], + groups: (version === '6' + ? partialTypebot.groups ?? [] + : [ + { + id: 'group0', + title: 'Group #0', + blocks: [ + { + id: 'block0', + type: 'start', + label: 'Start', + outgoingEdgeId: 'edge1', + }, + ], + graphCoordinates: { x: 0, y: 0 }, + }, + ...(partialTypebot.groups ?? []), + ]) as any[], + } +} + +export const parseTypebotToPublicTypebot = ( + id: string, + typebot: Typebot +): Omit => ({ + id, + version: typebot.version, + groups: typebot.groups, + typebotId: typebot.id, + theme: typebot.theme, + settings: typebot.settings, + variables: typebot.variables, + edges: typebot.edges, + events: typebot.events, +}) + +type Options = { + withGoButton?: boolean +} + +export const parseDefaultGroupWithBlock = ( + block: Partial, + options?: Options +): Pick => ({ + groups: [ + { + graphCoordinates: { x: 200, y: 200 }, + id: 'group1', + blocks: [ + options?.withGoButton + ? { + id: 'block1', + groupId: 'group1', + type: InputBlockType.CHOICE, + items: [ + { + id: 'item1', + blockId: 'block1', + content: 'Go', + }, + ], + options: {}, + } + : undefined, + { + id: 'block2', + ...block, + } as BlockV5, + ].filter(isDefined) as BlockV6[], + title: 'Group #1', + }, + ], +}) diff --git a/packages/lib/playwright/databaseSetup.ts b/packages/lib/playwright/databaseSetup.ts new file mode 100644 index 0000000..03f7826 --- /dev/null +++ b/packages/lib/playwright/databaseSetup.ts @@ -0,0 +1,191 @@ +import { + GraphNavigation, + Plan, + PrismaClient, + WorkspaceRole, +} from '@typebot.io/prisma' +import { encrypt } from '../api/encryption/encrypt' + +const prisma = new PrismaClient() + +export const apiToken = 'jirowjgrwGREHE' + +export const userId = 'userId' +export const otherUserId = 'otherUserId' + +export const proWorkspaceId = 'proWorkspace' +export const freeWorkspaceId = 'freeWorkspace' +export const starterWorkspaceId = 'starterWorkspace' +export const lifetimeWorkspaceId = 'lifetimeWorkspaceId' +export const customWorkspaceId = 'customWorkspaceId' + +const setupWorkspaces = async () => { + await prisma.workspace.createMany({ + data: [ + { + id: freeWorkspaceId, + name: 'Free workspace', + plan: Plan.FREE, + }, + { + id: starterWorkspaceId, + name: 'Starter workspace', + stripeId: 'cus_LnPDugJfa18N41', + plan: Plan.STARTER, + }, + { + id: proWorkspaceId, + name: 'Pro workspace', + plan: Plan.PRO, + }, + { + id: lifetimeWorkspaceId, + name: 'Lifetime workspace', + plan: Plan.LIFETIME, + }, + { + id: customWorkspaceId, + name: 'Custom workspace', + plan: Plan.CUSTOM, + customChatsLimit: 100000, + customStorageLimit: 50, + customSeatsLimit: 20, + }, + ], + }) +} + +export const setupUsers = async () => { + await prisma.user.create({ + data: { + id: userId, + email: 'user@email.com', + name: 'John Doe', + graphNavigation: GraphNavigation.TRACKPAD, + onboardingCategories: [], + apiTokens: { + createMany: { + data: [ + { + name: 'Token 1', + token: apiToken, + createdAt: new Date(2022, 1, 1), + }, + { + name: 'Github', + token: 'jirowjgrwGREHEgdrgithub', + createdAt: new Date(2022, 1, 2), + }, + { + name: 'N8n', + token: 'jirowjgrwGREHrgwhrwn8n', + createdAt: new Date(2022, 1, 3), + }, + ], + }, + }, + }, + }) + await prisma.user.create({ + data: { + id: otherUserId, + email: 'other-user@email.com', + name: 'James Doe', + onboardingCategories: [], + }, + }) + return prisma.memberInWorkspace.createMany({ + data: [ + { + role: WorkspaceRole.ADMIN, + userId, + workspaceId: freeWorkspaceId, + }, + { + role: WorkspaceRole.ADMIN, + userId, + workspaceId: starterWorkspaceId, + }, + { + role: WorkspaceRole.ADMIN, + userId, + workspaceId: proWorkspaceId, + }, + { + role: WorkspaceRole.ADMIN, + userId, + workspaceId: lifetimeWorkspaceId, + }, + { + role: WorkspaceRole.ADMIN, + userId, + workspaceId: customWorkspaceId, + }, + ], + }) +} + +const setupCredentials = async () => { + const { encryptedData, iv } = await encrypt({ + expiry_date: 1642441058842, + access_token: + 'ya29.A0ARrdaM--PV_87ebjywDJpXKb77NBFJl16meVUapYdfNv6W6ZzqqC47fNaPaRjbDbOIIcp6f49cMaX5ndK9TAFnKwlVqz3nrK9nLKqgyDIhYsIq47smcAIZkK56SWPx3X3DwAFqRu2UPojpd2upWwo-3uJrod', + // This token is linked to a test Google account (typebot.test.user@gmail.com) + refresh_token: + '1//039xWRt8YaYa3CgYIARAAGAMSNwF-L9Iru9FyuTrDSa7lkSceggPho83kJt2J29G69iEhT1C6XV1vmo6bQS9puL_R2t8FIwR3gek', + }) + return prisma.credentials.createMany({ + data: [ + { + name: 'pro-user@email.com', + type: 'google sheets', + data: encryptedData, + workspaceId: proWorkspaceId, + iv, + }, + ], + }) +} + +export const setupDatabase = async () => { + await setupWorkspaces() + await setupUsers() + return setupCredentials() +} + +export const teardownDatabase = async () => { + await prisma.webhook.deleteMany({ + where: { + typebot: { + workspace: { + members: { + some: { userId: { in: [userId, otherUserId] } }, + }, + }, + }, + }, + }) + await prisma.workspace.deleteMany({ + where: { + members: { + some: { userId: { in: [userId, otherUserId] } }, + }, + }, + }) + await prisma.workspace.deleteMany({ + where: { + id: { + in: [ + proWorkspaceId, + freeWorkspaceId, + starterWorkspaceId, + lifetimeWorkspaceId, + customWorkspaceId, + ], + }, + }, + }) + await prisma.user.deleteMany({ + where: { id: { in: [userId, otherUserId] } }, + }) +} diff --git a/packages/lib/playwright/globalSetup.ts b/packages/lib/playwright/globalSetup.ts new file mode 100644 index 0000000..0a92188 --- /dev/null +++ b/packages/lib/playwright/globalSetup.ts @@ -0,0 +1,11 @@ +import { FullConfig } from '@playwright/test' +import { setupDatabase, teardownDatabase } from './databaseSetup' + +async function globalSetup(config: FullConfig) { + const { baseURL } = config.projects[0].use + if (!baseURL) throw new Error('baseURL is missing') + await teardownDatabase() + await setupDatabase() +} + +export default globalSetup diff --git a/packages/lib/playwright/testHelpers.ts b/packages/lib/playwright/testHelpers.ts new file mode 100644 index 0000000..ad2b79c --- /dev/null +++ b/packages/lib/playwright/testHelpers.ts @@ -0,0 +1,30 @@ +import type { Page } from '@playwright/test' + +export const mockSessionResponsesToOtherUser = async (page: Page) => + page.route('/api/auth/session', (route) => { + if (route.request().method() === 'GET') { + return route.fulfill({ + status: 200, + body: '{"user":{"id":"otherUserId","name":"James Doe","email":"other-user@email.com","emailVerified":null,"image":"https://avatars.githubusercontent.com/u/16015833?v=4","stripeId":null,"graphNavigation": "TRACKPAD"}}', + }) + } + return route.continue() + }) + +export const typebotViewer = (page: Page) => + page.frameLocator('#typebot-iframe') + +export const waitForSuccessfulPutRequest = (page: Page) => + page.waitForResponse( + (resp) => resp.request().method() === 'PUT' && resp.status() === 200 + ) + +export const waitForSuccessfulPostRequest = (page: Page) => + page.waitForResponse( + (resp) => resp.request().method() === 'POST' && resp.status() === 200 + ) + +export const waitForSuccessfulDeleteRequest = (page: Page) => + page.waitForResponse( + (resp) => resp.request().method() === 'DELETE' && resp.status() === 200 + ) diff --git a/packages/lib/prisma.ts b/packages/lib/prisma.ts new file mode 100644 index 0000000..2a53681 --- /dev/null +++ b/packages/lib/prisma.ts @@ -0,0 +1,16 @@ +import { env } from '@typebot.io/env' +import { PrismaClient } from '@typebot.io/prisma' + +declare const global: { prisma: PrismaClient } +let prisma: PrismaClient + +if (env.NODE_ENV === 'production') { + prisma = new PrismaClient() +} else { + if (!global.prisma) { + global.prisma = new PrismaClient() + } + prisma = global.prisma +} + +export default prisma diff --git a/packages/lib/results.ts b/packages/lib/results.ts new file mode 100644 index 0000000..feec9a5 --- /dev/null +++ b/packages/lib/results.ts @@ -0,0 +1,248 @@ +import { + Group, + Variable, + InputBlock, + ResultHeaderCell, + VariableWithValue, + Typebot, + ResultWithAnswers, + AnswerInSessionState, +} from '@typebot.io/schemas' +import { isInputBlock, isDefined, byId, isNotEmpty, isEmpty } from './utils' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' + +export const parseResultHeader = ( + typebot: Pick, + linkedTypebots: Pick[] | undefined, + results?: ResultWithAnswers[] +): ResultHeaderCell[] => { + const parsedGroups = [ + ...typebot.groups, + ...(linkedTypebots ?? []).flatMap( + (linkedTypebot) => linkedTypebot.groups as Group[] + ), + ] + const parsedVariables = [ + ...typebot.variables, + ...(linkedTypebots ?? []).flatMap( + (linkedTypebot) => linkedTypebot.variables + ), + ] + const inputsResultHeader = parseInputsResultHeader({ + groups: parsedGroups, + variables: parsedVariables, + }) + return [ + { label: 'Submitted at', id: 'date' }, + ...inputsResultHeader, + ...parseVariablesHeaders(parsedVariables, inputsResultHeader), + ...parseResultsFromPreviousBotVersions(results ?? [], inputsResultHeader), + ] +} + +type ResultHeaderCellWithBlock = Omit & { + blocks: NonNullable +} + +const parseInputsResultHeader = ({ + groups, + variables, +}: { + groups: Group[] + variables: Variable[] +}): ResultHeaderCellWithBlock[] => + ( + groups + .flatMap((group) => + group.blocks.map((block) => ({ + ...block, + groupTitle: group.title, + groupId: group.id, + })) + ) + .filter((block) => isInputBlock(block)) as (InputBlock & { + groupId: string + groupTitle: string + })[] + ).reduce((existingHeaders, inputBlock) => { + if ( + existingHeaders.some( + (existingHeader) => + inputBlock.options?.variableId && + existingHeader.variableIds?.includes(inputBlock.options.variableId) + ) + ) + return existingHeaders + const matchedVariableName = + inputBlock.options?.variableId && + variables.find(byId(inputBlock.options.variableId))?.name + + let label = matchedVariableName ?? inputBlock.groupTitle + const headerWithSameLabel = existingHeaders.find((h) => h.label === label) + if (headerWithSameLabel) { + const shouldMerge = headerWithSameLabel.blocks?.some( + (block) => block.id === inputBlock.id + ) + if (shouldMerge) { + const updatedHeaderCell: ResultHeaderCellWithBlock = { + ...headerWithSameLabel, + variableIds: + headerWithSameLabel.variableIds && inputBlock.options?.variableId + ? headerWithSameLabel.variableIds.concat([ + inputBlock.options.variableId, + ]) + : undefined, + blocks: headerWithSameLabel.blocks.concat({ + id: inputBlock.id, + groupId: inputBlock.groupId, + }), + } + return [ + ...existingHeaders.filter( + (existingHeader) => existingHeader.label !== label + ), + updatedHeaderCell, + ] + } + const totalPrevious = existingHeaders.filter((h) => + h.label.includes(label) + ).length + const newHeaderCell: ResultHeaderCellWithBlock = { + id: inputBlock.id, + label: label + ` (${totalPrevious})`, + blocks: [ + { + id: inputBlock.id, + groupId: inputBlock.groupId, + }, + ], + blockType: inputBlock.type, + variableIds: inputBlock.options?.variableId + ? [inputBlock.options.variableId] + : undefined, + } + return [...existingHeaders, newHeaderCell] + } + + const newHeaderCell: ResultHeaderCellWithBlock = { + id: inputBlock.id, + label, + blocks: [ + { + id: inputBlock.id, + groupId: inputBlock.groupId, + }, + ], + blockType: inputBlock.type, + variableIds: inputBlock.options?.variableId + ? [inputBlock.options.variableId] + : undefined, + } + + return [...existingHeaders, newHeaderCell] + }, []) + +const parseVariablesHeaders = ( + variables: Variable[], + existingInputResultHeaders: ResultHeaderCell[] +) => + variables.reduce((existingHeaders, variable) => { + if ( + existingInputResultHeaders.some((existingInputResultHeader) => + existingInputResultHeader.variableIds?.includes(variable.id) + ) + ) + return existingHeaders + + const headerCellWithSameLabel = existingHeaders.find( + (existingHeader) => existingHeader.label === variable.name + ) + if (headerCellWithSameLabel) { + const updatedHeaderCell: ResultHeaderCell = { + ...headerCellWithSameLabel, + variableIds: headerCellWithSameLabel.variableIds?.concat([variable.id]), + } + return [ + ...existingHeaders.filter((h) => h.label !== variable.name), + updatedHeaderCell, + ] + } + const newHeaderCell: ResultHeaderCell = { + id: variable.id, + label: variable.name, + variableIds: [variable.id], + } + + return [...existingHeaders, newHeaderCell] + }, []) + +const parseResultsFromPreviousBotVersions = ( + results: ResultWithAnswers[], + existingInputResultHeaders: ResultHeaderCell[] +): ResultHeaderCell[] => + results + .flatMap((result) => result.answers) + .filter( + (answer) => + !answer.variableId && + existingInputResultHeaders.every( + (header) => header.id !== answer.blockId + ) && + isNotEmpty(answer.content) + ) + .reduce((existingHeaders, answer) => { + if ( + existingHeaders.some( + (existingHeader) => existingHeader.id === answer.blockId + ) + ) + return existingHeaders + return [ + ...existingHeaders, + { + id: answer.blockId, + label: `${answer.blockId} (deleted block)`, + blocks: [ + { + id: answer.blockId, + groupId: answer.groupId, + }, + ], + blockType: InputBlockType.TEXT, + }, + ] + }, []) + +export const parseAnswers = ({ + answers, + variables: resultVariables, +}: { + answers: AnswerInSessionState[] + variables: VariableWithValue[] +}): { + [key: string]: string +} => { + return { + submittedAt: new Date().toISOString(), + ...[...answers, ...resultVariables].reduce<{ + [key: string]: string + }>((o, answerOrVariable) => { + if ('id' in answerOrVariable) { + const variable = answerOrVariable + if (variable.value === null) return o + return { ...o, [variable.name]: variable.value.toString() } + } + const answer = answerOrVariable as AnswerInSessionState + if (isEmpty(answer.key)) return o + return { + ...o, + [answer.key]: answer.value, + } + }, {}), + } +} + +export const getDefinedVariables = (variables: Variable[]) => + variables.filter((variable) => + isDefined(variable.value) + ) as VariableWithValue[] diff --git a/packages/lib/s3/deleteFilesFromBucket.ts b/packages/lib/s3/deleteFilesFromBucket.ts new file mode 100644 index 0000000..aaed76a --- /dev/null +++ b/packages/lib/s3/deleteFilesFromBucket.ts @@ -0,0 +1,31 @@ +import { env } from '@typebot.io/env' +import { Client } from 'minio' + +export const deleteFilesFromBucket = async ({ + urls, +}: { + urls: string[] +}): Promise => { + if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY) + throw new Error( + 'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY' + ) + + const minioClient = new Client({ + endPoint: env.S3_ENDPOINT, + port: env.S3_PORT, + useSSL: env.S3_SSL, + accessKey: env.S3_ACCESS_KEY, + secretKey: env.S3_SECRET_KEY, + region: env.S3_REGION, + }) + + const bucket = env.S3_BUCKET + + return minioClient.removeObjects( + bucket, + urls + .filter((url) => url.includes(env.S3_ENDPOINT as string)) + .map((url) => url.split(`/${bucket}/`)[1]) + ) +} diff --git a/packages/lib/s3/deprecated/generatePresignedUrl.ts b/packages/lib/s3/deprecated/generatePresignedUrl.ts new file mode 100644 index 0000000..2003cf8 --- /dev/null +++ b/packages/lib/s3/deprecated/generatePresignedUrl.ts @@ -0,0 +1,32 @@ +import { env } from '@typebot.io/env' +import { Client } from 'minio' + +type GeneratePresignedUrlProps = { + filePath: string + fileType?: string +} + +const tenMinutes = 10 * 60 + +export const generatePresignedUrl = async ({ + filePath, + fileType, +}: GeneratePresignedUrlProps): Promise => { + if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY) + throw new Error( + 'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY' + ) + + const minioClient = new Client({ + endPoint: env.S3_ENDPOINT, + port: env.S3_PORT, + useSSL: env.S3_SSL, + accessKey: env.S3_ACCESS_KEY, + secretKey: env.S3_SECRET_KEY, + region: env.S3_REGION, + }) + + return minioClient.presignedUrl('PUT', env.S3_BUCKET, filePath, tenMinutes, { + 'Content-Type': fileType, + }) +} diff --git a/packages/lib/s3/generatePresignedPostPolicy.ts b/packages/lib/s3/generatePresignedPostPolicy.ts new file mode 100644 index 0000000..13e6dc4 --- /dev/null +++ b/packages/lib/s3/generatePresignedPostPolicy.ts @@ -0,0 +1,46 @@ +import { env } from '@typebot.io/env' +import { Client, PostPolicyResult } from 'minio' + +type Props = { + filePath: string + fileType?: string + maxFileSize?: number +} + +const tenMinutes = 10 * 60 + +export const generatePresignedPostPolicy = async ({ + filePath, + fileType, + maxFileSize, +}: Props): Promise => { + if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY) + throw new Error( + 'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY' + ) + + const minioClient = new Client({ + endPoint: env.S3_ENDPOINT, + port: env.S3_PORT, + useSSL: env.S3_SSL, + accessKey: env.S3_ACCESS_KEY, + secretKey: env.S3_SECRET_KEY, + region: env.S3_REGION, + }) + + const postPolicy = minioClient.newPostPolicy() + if (maxFileSize) + postPolicy.setContentLengthRange(0, maxFileSize * 1024 * 1024) + postPolicy.setKey(filePath) + postPolicy.setBucket(env.S3_BUCKET) + postPolicy.setExpires(new Date(Date.now() + tenMinutes * 1000)) + postPolicy.formData['Cache-Control'] = 'public, max-age=86400' + postPolicy.policy.conditions.push([ + 'eq', + '$Cache-Control', + 'public, max-age=86400', + ]) + if (fileType) postPolicy.setContentType(fileType) + + return minioClient.presignedPostPolicy(postPolicy) +} diff --git a/packages/lib/s3/getFolderSize.ts b/packages/lib/s3/getFolderSize.ts new file mode 100644 index 0000000..309331f --- /dev/null +++ b/packages/lib/s3/getFolderSize.ts @@ -0,0 +1,42 @@ +import { env } from '@typebot.io/env' +import { Client } from 'minio' + +type Props = { + folderPath: string +} + +export const getFolderSize = async ({ folderPath }: Props) => { + if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY) + throw new Error( + 'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY' + ) + + const minioClient = new Client({ + endPoint: env.S3_ENDPOINT, + port: env.S3_PORT, + useSSL: env.S3_SSL, + accessKey: env.S3_ACCESS_KEY, + secretKey: env.S3_SECRET_KEY, + region: env.S3_REGION, + }) + + return new Promise((resolve, reject) => { + let totalSize = 0 + + const stream = minioClient.listObjectsV2( + env.S3_BUCKET, + 'public/' + folderPath, + true + ) + + stream.on('data', function (obj) { + totalSize += obj.size + }) + stream.on('error', function (err) { + reject(err) + }) + stream.on('end', function () { + resolve(totalSize) + }) + }) +} diff --git a/packages/lib/s3/uploadFileToBucket.ts b/packages/lib/s3/uploadFileToBucket.ts new file mode 100644 index 0000000..20caac3 --- /dev/null +++ b/packages/lib/s3/uploadFileToBucket.ts @@ -0,0 +1,39 @@ +import { env } from '@typebot.io/env' +import { Client } from 'minio' + +type Props = { + key: string + file: Buffer + mimeType: string +} + +export const uploadFileToBucket = async ({ + key, + file, + mimeType, +}: Props): Promise => { + if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY) + throw new Error( + 'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY' + ) + + const minioClient = new Client({ + endPoint: env.S3_ENDPOINT, + port: env.S3_PORT, + useSSL: env.S3_SSL, + accessKey: env.S3_ACCESS_KEY, + secretKey: env.S3_SECRET_KEY, + region: env.S3_REGION, + }) + + await minioClient.putObject(env.S3_BUCKET, 'public/' + key, file, { + 'Content-Type': mimeType, + 'Cache-Control': 'public, max-age=86400', + }) + + return env.S3_PUBLIC_CUSTOM_DOMAIN + ? `${env.S3_PUBLIC_CUSTOM_DOMAIN}/public/${key}` + : `http${env.S3_SSL ? 's' : ''}://${env.S3_ENDPOINT}${ + env.S3_PORT ? `:${env.S3_PORT}` : '' + }/${env.S3_BUCKET}/public/${key}` +} diff --git a/packages/lib/safeStringify.ts b/packages/lib/safeStringify.ts new file mode 100644 index 0000000..16e33ed --- /dev/null +++ b/packages/lib/safeStringify.ts @@ -0,0 +1,12 @@ +import { isNotDefined } from './utils' + +export const safeStringify = (val: unknown): string | null => { + if (isNotDefined(val)) return null + if (typeof val === 'string') return val + try { + return JSON.stringify(val) + } catch { + console.warn('Failed to safely stringify variable value', val) + return null + } +} diff --git a/packages/lib/telemetry/sendTelemetryEvent.ts b/packages/lib/telemetry/sendTelemetryEvent.ts new file mode 100644 index 0000000..24ef2b5 --- /dev/null +++ b/packages/lib/telemetry/sendTelemetryEvent.ts @@ -0,0 +1,29 @@ +import got from 'got' +import { TelemetryEvent } from '@typebot.io/schemas/features/telemetry' +import { env } from '@typebot.io/env' + +export const sendTelemetryEvents = async (events: TelemetryEvent[]) => { + if (events.length === 0) return { message: 'No events to send' } + if (!env.TELEMETRY_WEBHOOK_URL) return { message: 'Telemetry not enabled' } + + try { + await got.post(env.TELEMETRY_WEBHOOK_URL, { + json: { events }, + headers: { + authorization: env.TELEMETRY_WEBHOOK_BEARER_TOKEN + ? `Bearer ${env.TELEMETRY_WEBHOOK_BEARER_TOKEN}` + : undefined, + }, + }) + } catch (err) { + console.error('Failed to send event', err) + return { + message: 'Failed to send event', + error: err instanceof Error ? err.message : 'Unknown error', + } + } + + return { + message: 'Event sent', + } +} diff --git a/packages/lib/tsconfig.json b/packages/lib/tsconfig.json new file mode 100644 index 0000000..075fbaa --- /dev/null +++ b/packages/lib/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@typebot.io/tsconfig/base.json", + "include": ["**/*.ts"], + "exclude": ["node_modules"], + "compilerOptions": { + "lib": ["ES2021", "DOM"] + } +} diff --git a/packages/lib/utils.ts b/packages/lib/utils.ts new file mode 100644 index 0000000..2f10ea4 --- /dev/null +++ b/packages/lib/utils.ts @@ -0,0 +1,259 @@ +import type { + BubbleBlock, + ChoiceInputBlock, + ConditionBlock, + InputBlock, + IntegrationBlock, + LogicBlock, + Block, + TextInputBlock, + TextBubbleBlock, + WebhookBlock, + ImageBubbleBlock, + VideoBubbleBlock, + BlockWithOptionsType, +} from '@typebot.io/schemas' +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' +import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' +import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice' +import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants' +import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants' +import { defaultChoiceInputOptions } from '@typebot.io/schemas/features/blocks/inputs/choice/constants' +import { enabledBlocks } from '@typebot.io/forge-repository' + +export const sendRequest = async ( + params: + | { + url: string + method: string + body?: Record | FormData + } + | string +): Promise<{ data?: ResponseData; error?: Error; response?: Response }> => { + let response + try { + const url = typeof params === 'string' ? params : params.url + response = await fetch(url, { + method: typeof params === 'string' ? 'GET' : params.method, + mode: 'cors', + headers: + typeof params !== 'string' && isDefined(params.body) + ? { + 'Content-Type': 'application/json', + } + : undefined, + body: + typeof params !== 'string' && isDefined(params.body) + ? JSON.stringify(params.body) + : undefined, + }) + const data = await response.json() + if (!response.ok) throw 'error' in data ? data.error : data + return { data, response } + } catch (e) { + console.error(e) + return { error: e as Error, response } + } +} + +export const isDefined = ( + value: T | undefined | null +): value is NonNullable => value !== undefined && value !== null + +export const isNotDefined = ( + value: T | undefined | null +): value is undefined | null => value === undefined || value === null + +export const isEmpty = ( + value: string | undefined | null +): value is undefined | null => + value === undefined || value === null || value === '' + +export const isNotEmpty = (value: string | undefined | null): value is string => + value !== undefined && value !== null && value !== '' + +export const isInputBlock = (block: Block): block is InputBlock => + (Object.values(InputBlockType) as string[]).includes(block.type) + +export const isBubbleBlock = (block: Block): block is BubbleBlock => + (Object.values(BubbleBlockType) as string[]).includes(block.type) + +export const isLogicBlock = (block: Block): block is LogicBlock => + (Object.values(LogicBlockType) as string[]).includes(block.type) + +export const isTextBubbleBlock = (block: Block): block is TextBubbleBlock => + block.type === BubbleBlockType.TEXT + +export const isMediaBubbleBlock = ( + block: Block +): block is ImageBubbleBlock | VideoBubbleBlock => + block.type === BubbleBlockType.IMAGE || block.type === BubbleBlockType.VIDEO + +export const isTextInputBlock = (block: Block): block is TextInputBlock => + block.type === InputBlockType.TEXT + +export const isChoiceInput = (block: Block): block is ChoiceInputBlock => + block.type === InputBlockType.CHOICE + +export const isPictureChoiceInput = ( + block: Block +): block is PictureChoiceBlock => block.type === InputBlockType.PICTURE_CHOICE + +export const isSingleChoiceInput = (block: Block): block is ChoiceInputBlock => + block.type === InputBlockType.CHOICE && + 'options' in block && + !( + block.options?.isMultipleChoice ?? + defaultChoiceInputOptions.isMultipleChoice + ) + +export const isConditionBlock = (block: Block): block is ConditionBlock => + block.type === LogicBlockType.CONDITION + +export const isIntegrationBlock = (block: Block): block is IntegrationBlock => + ( + Object.values(IntegrationBlockType).concat( + enabledBlocks as readonly any[] + ) as any[] + ).includes(block.type) + +export const isWebhookBlock = (block: Block): block is WebhookBlock => + [ + IntegrationBlockType.WEBHOOK, + IntegrationBlockType.PABBLY_CONNECT, + IntegrationBlockType.ZAPIER, + IntegrationBlockType.MAKE_COM, + ].includes(block.type as IntegrationBlockType) + +export const isBubbleBlockType = ( + type: Block['type'] +): type is BubbleBlockType => + (Object.values(BubbleBlockType) as string[]).includes(type) + +export const blockTypeHasOption = ( + type: Block['type'] +): type is BlockWithOptionsType => + (Object.values(InputBlockType) as string[]) + .concat(Object.values(LogicBlockType)) + .concat(Object.values(IntegrationBlockType)) + .includes(type) + +export const blockTypeHasItems = ( + type: Block['type'] +): type is + | LogicBlockType.CONDITION + | InputBlockType.CHOICE + | LogicBlockType.AB_TEST => + type === LogicBlockType.CONDITION || + type === InputBlockType.CHOICE || + type === LogicBlockType.AB_TEST || + type === InputBlockType.PICTURE_CHOICE + +export const blockHasItems = ( + block: Block +): block is ConditionBlock | ChoiceInputBlock => + 'items' in block && isDefined(block.items) + +export const byId = (id?: string) => (obj: { id: string }) => obj.id === id + +export const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1) + +interface Omit { + // eslint-disable-next-line @typescript-eslint/ban-types + (obj: T, ...keys: K): { + [K2 in Exclude]: T[K2] + } +} + +export const omit: Omit = (obj, ...keys) => { + const ret = {} as { + [K in keyof typeof obj]: (typeof obj)[K] + } + let key: keyof typeof obj + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key] + } + } + return ret +} + +const isVariableString = (str: string): boolean => /^\{\{.*\}\}$/.test(str) + +export const sanitizeUrl = (url: string): string => + url.startsWith('http') || + url.startsWith('mailto:') || + url.startsWith('tel:') || + url.startsWith('sms:') || + isVariableString(url) + ? url + : `https://${url}` + +export const toTitleCase = (str: string) => + str.replace( + /\w\S*/g, + (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase() + ) + +export const generateId = (idDesiredLength: number): string => { + const getRandomCharFromAlphabet = (alphabet: string): string => { + return alphabet.charAt(Math.floor(Math.random() * alphabet.length)) + } + + return Array.from({ length: idDesiredLength }) + .map(() => { + return getRandomCharFromAlphabet( + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + ) + }) + .join('') +} + +export const hasValue = ( + value: string | undefined | null +): value is NonNullable => + value !== undefined && + value !== null && + value !== '' && + value !== 'undefined' && + value !== 'null' + +export const parseNumberWithCommas = (num: number) => + num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') + +export const injectCustomHeadCode = (customHeadCode: string) => { + const headCodes = customHeadCode.split('') + headCodes.forEach((headCode) => { + const [codeToInject, noScriptContentToInject] = headCode.split('