diff --git a/apps/hq/package.json b/apps/hq/package.json index c4ea1d5736..1c7b250b24 100644 --- a/apps/hq/package.json +++ b/apps/hq/package.json @@ -20,6 +20,7 @@ "next": "^13.0.5", "next-auth": "^4.17.0", "nodemailer": "^6.8.0", + "prismjs": "^1.29.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.6.0", diff --git a/apps/hq/src/app/app/layout.tsx b/apps/hq/src/app/app/layout.tsx index 300b7708f5..f6b74e9f55 100644 --- a/apps/hq/src/app/app/layout.tsx +++ b/apps/hq/src/app/app/layout.tsx @@ -1,16 +1,16 @@ "use client"; +import AvatarPlaceholder from "@/images/avatar-placeholder.png"; import { Disclosure, Menu, Transition } from "@headlessui/react"; -import { Bars3Icon, BellIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline"; +import clsx from "clsx"; import { signOut, useSession } from "next-auth/react"; import Image from "next/image"; -import { useRouter } from "next/navigation"; -import { Fragment, useMemo } from "react"; -import { Logo } from "../Logo"; -import AvatarPlaceholder from "@/images/avatar-placeholder.png"; import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { Fragment } from "react"; import LoadingSpinner from "../LoadingSpinner"; -import clsx from "clsx"; +import { Logo } from "../Logo"; export default function ProjectsLayout({ params, children }) { const router = useRouter(); diff --git a/apps/hq/src/app/app/me/settings/page.tsx b/apps/hq/src/app/app/me/settings/page.tsx index eb213534b3..1c5388df9f 100644 --- a/apps/hq/src/app/app/me/settings/page.tsx +++ b/apps/hq/src/app/app/me/settings/page.tsx @@ -13,7 +13,7 @@ export default function MeSettingsPage() { const [openNewApiKeyModal, setOpenNewApiKeyModal] = useState(false); return ( -
+

Account Settings

diff --git a/apps/hq/src/app/app/teams/[teamId]/forms/FormsList.tsx b/apps/hq/src/app/app/teams/[teamId]/forms/FormsList.tsx index 4b0c91e4ad..34a4347411 100644 --- a/apps/hq/src/app/app/teams/[teamId]/forms/FormsList.tsx +++ b/apps/hq/src/app/app/teams/[teamId]/forms/FormsList.tsx @@ -3,7 +3,7 @@ import EmptyPageFiller from "@/components/EmptyPageFiller"; import { deleteForm, useForms } from "@/lib/forms"; import { Menu, Transition } from "@headlessui/react"; -import { CommandLineIcon, DocumentPlusIcon, PlusIcon, SquaresPlusIcon } from "@heroicons/react/24/outline"; +import { DocumentPlusIcon, PlusIcon } from "@heroicons/react/24/outline"; import { EllipsisHorizontalIcon, TrashIcon } from "@heroicons/react/24/solid"; import clsx from "clsx"; import Link from "next/link"; @@ -11,7 +11,7 @@ import { Fragment, useState } from "react"; import NewFormModal from "./NewFormModal"; export default function FormsList({ teamId }) { - const { forms, mutateForms } = useForms(teamId); + const { forms, mutateForms, isLoadingForms } = useForms(teamId); const [openNewFormModal, setOpenNewFormModal] = useState(false); const newForm = async () => { diff --git a/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/layout.tsx b/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/layout.tsx new file mode 100644 index 0000000000..22d0d51fb2 --- /dev/null +++ b/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/layout.tsx @@ -0,0 +1,62 @@ +"use client"; + +import { Disclosure } from "@headlessui/react"; +import { BellIcon } from "@heroicons/react/24/outline"; +import clsx from "clsx"; + +export default function FormLayout({ params, children }) { + const navigation = [ + { name: "Form", href: `/teams/${params.teamId}/forms/${params.formId}/`, current: true }, + { name: "Pipelines", href: `/teams/${params.teamId}/forms/${params.formId}/pipelines/`, current: false }, + { name: "Results", href: `/teams/${params.teamId}/forms/${params.formId}/results/`, current: false }, + ]; + return ( + <> + + {({ open }) => ( + <> +
+ +
+ + +
+ {navigation.map((item) => ( + + {item.name} + + ))} +
+
+ + )} +
+ {children} + + ); +} diff --git a/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/page.tsx b/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/page.tsx index 0a50e34264..ec196ae92b 100644 --- a/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/page.tsx +++ b/apps/hq/src/app/app/teams/[teamId]/forms/[formId]/page.tsx @@ -3,10 +3,56 @@ import LoadingSpinner from "@/app/LoadingSpinner"; import { useForm } from "@/lib/forms"; import { useTeam } from "@/lib/teams"; +import { Button } from "@formbricks/ui"; +import { DocumentMagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import clsx from "clsx"; +import Link from "next/link"; +import { useEffect, useMemo } from "react"; +import { FaReact, FaVuejs } from "react-icons/fa"; +import { toast } from "react-toastify"; +import Prism from "prismjs"; + +require("prismjs/components/prism-javascript"); + +const getLibs = (formId: string) => [ + { + id: "react", + name: "React", + href: `https://formbricks.com/docs/react-form-library/introduction`, + bgColor: "bg-brand-dark", + target: "_blank", + icon: FaReact, + }, + { + id: "reactNative", + name: "React Native", + comingSoon: true, + href: "#", + disabled: true, + icon: FaReact, + }, + { + id: "vue", + name: "Vue.js", + comingSoon: true, + href: "#", + disabled: true, + icon: FaVuejs, + }, +]; export default function FormsPage({ params }) { const { form, isLoadingForm, isErrorForm } = useForm(params.formId, params.teamId); const { team, isLoadingTeam, isErrorTeam } = useTeam(params.teamId); + const libs = useMemo(() => { + if (form) { + return getLibs(form.id); + } + }, [form]); + + useEffect(() => { + Prism.highlightAll(); + }, []); if (isLoadingForm || isLoadingTeam) { return ( @@ -29,6 +75,131 @@ export default function FormsPage({ params }) { +
+
+

Connect your form

+
+
+

+ To send all form submissions to this dashboard, update the form ID in the{" "} + {""} component. +

+
+
+
+ +
+ + + +
+
+
+
+              
+                {`import { Form, Text, Email, Checkbox, Submit, sendToHQ } from "@formbricks/react";
+import "@formbricks/react/styles.css";
+
+export default function WaitlistForm() {
+  return (
+    
+ + + + + + ); +}`} +
+
+
+
+
+

Code your form

+
+

+ Build your form with the code library of your choice. Manage your data in this dashboard. +

+
+
    + {libs.map((lib) => ( + +
  • +
    + +
    +
    +
    +

    {lib.name}

    + {lib.comingSoon && ( +
    +

    coming soon

    +
    + )} +
    +
    +
  • + + ))} +
+ +
+

+ Your form is running? Go to{" "} + + Pipelines + +

+
+
+
); } diff --git a/apps/hq/src/app/app/teams/[teamId]/forms/page.tsx b/apps/hq/src/app/app/teams/[teamId]/forms/page.tsx index 90758d5c6b..f48b6fae91 100644 --- a/apps/hq/src/app/app/teams/[teamId]/forms/page.tsx +++ b/apps/hq/src/app/app/teams/[teamId]/forms/page.tsx @@ -6,7 +6,7 @@ import { useTeam } from "@/lib/teams"; import FormsList from "./FormsList"; export default function FormsPage({ params }) { - const { forms, isLoadingForms, isErrorForms } = useForms(params.teamId); + const { isLoadingForms, isErrorForms } = useForms(params.teamId); const { team, isLoadingTeam, isErrorTeam } = useTeam(params.teamId); if (isLoadingForms || isLoadingTeam) { diff --git a/apps/hq/src/app/app/teams/[teamId]/layout.tsx b/apps/hq/src/app/app/teams/[teamId]/layout.tsx index 4ee4a7568d..0921486a39 100644 --- a/apps/hq/src/app/app/teams/[teamId]/layout.tsx +++ b/apps/hq/src/app/app/teams/[teamId]/layout.tsx @@ -2,14 +2,11 @@ import { Dialog, Transition } from "@headlessui/react"; import { Cog8ToothIcon, RectangleStackIcon, UsersIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import clsx from "clsx"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { Fragment, useMemo, useState } from "react"; -function classNames(...classes) { - return classes.filter(Boolean).join(" "); -} - export default function Example({ children, params }) { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const pathname = usePathname(); @@ -39,14 +36,6 @@ export default function Example({ children, params }) { return ( <> - {/* - This example requires updating your template: - - ``` - - - ``` - */}
{/* Narrow sidebar */}
@@ -56,7 +45,7 @@ export default function Example({ children, params }) { { +export const useForms = (teamId: string) => { const { data, error, mutate } = useSWR(`/api/teams/${teamId}/forms`, fetcher); return { @@ -35,7 +35,7 @@ export const persistForm = async (form) => { } }; -export const createForm = async (teamId, form = {}) => { +export const createForm = async (teamId: string, form = {}) => { try { const res = await fetch(`/api/teams/${teamId}/forms`, { method: "POST", @@ -49,7 +49,7 @@ export const createForm = async (teamId, form = {}) => { } }; -export const deleteForm = async (teamId, formId) => { +export const deleteForm = async (teamId: string, formId: string) => { try { await fetch(`/api/teams/${teamId}/forms/${formId}`, { method: "DELETE", diff --git a/apps/hq/src/pages/api/teams/[teamId]/forms/[formId]/index.ts b/apps/hq/src/pages/api/teams/[teamId]/forms/[formId]/index.ts index 82bcf3963e..7eaebbaf97 100644 --- a/apps/hq/src/pages/api/teams/[teamId]/forms/[formId]/index.ts +++ b/apps/hq/src/pages/api/teams/[teamId]/forms/[formId]/index.ts @@ -9,15 +9,9 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) return res.status(401).json({ message: "Not authenticated" }); } - const teamId = parseInt(req.query.teamId.toString()); - if (isNaN(teamId)) { - return res.status(400).json({ message: "Invalid teamId" }); - } + const teamId = req.query.teamId.toString(); - const formId = parseInt(req.query.formId.toString()); - if (isNaN(formId)) { - return res.status(400).json({ message: "Invalid formId" }); - } + const formId = req.query.formId.toString(); // check team permission const membership = await prisma.membership.findUnique({ diff --git a/apps/hq/src/pages/api/teams/[teamId]/forms/index.ts b/apps/hq/src/pages/api/teams/[teamId]/forms/index.ts index fd3801b1e5..7172a4cf49 100644 --- a/apps/hq/src/pages/api/teams/[teamId]/forms/index.ts +++ b/apps/hq/src/pages/api/teams/[teamId]/forms/index.ts @@ -9,10 +9,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) return res.status(401).json({ message: "Not authenticated" }); } - const teamId = parseInt(req.query.teamId.toString()); - if (isNaN(teamId)) { - return res.status(400).json({ message: "Invalid teamId" }); - } + const teamId = req.query.teamId.toString(); // check team permission const membership = await prisma.membership.findUnique({ diff --git a/apps/hq/src/pages/api/teams/[teamId]/index.ts b/apps/hq/src/pages/api/teams/[teamId]/index.ts index ce91033ae6..7bb1df8c72 100644 --- a/apps/hq/src/pages/api/teams/[teamId]/index.ts +++ b/apps/hq/src/pages/api/teams/[teamId]/index.ts @@ -1,8 +1,6 @@ -import { getSessionOrUser, hashApiKey } from "@/lib/apiHelper"; +import { getSessionOrUser } from "@/lib/apiHelper"; import { prisma } from "@formbricks/database"; -import { randomBytes } from "crypto"; import type { NextApiRequest, NextApiResponse } from "next"; -import { unstable_getServerSession } from "next-auth"; export default async function handle(req: NextApiRequest, res: NextApiResponse) { // Check Authentication @@ -11,10 +9,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) return res.status(401).json({ message: "Not authenticated" }); } - const teamId = parseInt(req.query.teamId.toString()); - if (isNaN(teamId)) { - return res.status(400).json({ message: "Invalid teamId" }); - } + const teamId = req.query.teamId.toString(); // GET /api/teams[teamId] // Get a specific team diff --git a/apps/hq/src/styles/prism.css b/apps/hq/src/styles/prism.css new file mode 100644 index 0000000000..dab40c9783 --- /dev/null +++ b/apps/hq/src/styles/prism.css @@ -0,0 +1,90 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+clike+javascript */ +code[class*="language-"], +pre[class*="language-"] { + color: #f8f8f2; + background: 0 0; + text-shadow: 0 1px rgba(0, 0, 0, 0.3); + font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} +pre[class*="language-"] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; + border-radius: 0.3em; +} +:not(pre) > code[class*="language-"], +.token.doctype, +.token.prolog { + color: #8292a2; +} +.token.punctuation { + color: #f8f8f2; +} +.token.namespace { + opacity: 0.7; +} +.token.constant, +.token.deleted, +.token.property, +.token.symbol, +.token.tag { + color: #f92672; +} +.token.boolean, +.token.number { + color: #ae81ff; +} +.token.attr-name, +.token.builtin, +.token.char, +.token.inserted, +.token.selector, +.token.string { + color: #a6e22e; +} +.language-css .token.string, +.style .token.string, +.token.entity, +.token.operator, +.token.url, +.token.variable { + color: #f8f8f2; +} +.token.atrule, +.token.attr-value, +.token.class-name, +.token.function { + color: #e6db74; +} +.token.keyword { + color: #66d9ef; +} +.token.important, +.token.regex { + color: #fd971f; +} +.token.bold, +.token.important { + font-weight: 700; +} +.token.italic { + font-style: italic; +} +.token.entity { + cursor: help; +} diff --git a/packages/database/prisma/migrations/20221128173035_init/migration.sql b/packages/database/prisma/migrations/20221129111859_init/migration.sql similarity index 87% rename from packages/database/prisma/migrations/20221128173035_init/migration.sql rename to packages/database/prisma/migrations/20221129111859_init/migration.sql index 921aaa56b1..69ab011852 100644 --- a/packages/database/prisma/migrations/20221128173035_init/migration.sql +++ b/packages/database/prisma/migrations/20221129111859_init/migration.sql @@ -9,12 +9,12 @@ CREATE TYPE "IdentityProvider" AS ENUM ('EMAIL', 'GITHUB'); -- CreateTable CREATE TABLE "Pipeline" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, "name" TEXT NOT NULL, "type" "PipelineType" NOT NULL, - "formId" INTEGER NOT NULL, + "formId" TEXT NOT NULL, "enabled" BOOLEAN NOT NULL DEFAULT false, "config" JSONB NOT NULL DEFAULT '{}', @@ -26,7 +26,7 @@ CREATE TABLE "Customer" ( "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, - "teamId" INTEGER NOT NULL, + "teamId" TEXT NOT NULL, "data" JSONB NOT NULL DEFAULT '{}', CONSTRAINT "Customer_pkey" PRIMARY KEY ("id","teamId") @@ -34,11 +34,11 @@ CREATE TABLE "Customer" ( -- CreateTable CREATE TABLE "Form" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, "label" TEXT NOT NULL, - "teamId" INTEGER NOT NULL, + "teamId" TEXT NOT NULL, "schema" JSONB NOT NULL DEFAULT '{}', CONSTRAINT "Form_pkey" PRIMARY KEY ("id") @@ -46,12 +46,12 @@ CREATE TABLE "Form" ( -- CreateTable CREATE TABLE "Submission" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, - "formId" INTEGER NOT NULL, + "formId" TEXT NOT NULL, "customerId" TEXT, - "teamId" INTEGER, + "teamId" TEXT, "data" JSONB NOT NULL DEFAULT '{}', CONSTRAINT "Submission_pkey" PRIMARY KEY ("id") @@ -59,7 +59,7 @@ CREATE TABLE "Submission" ( -- CreateTable CREATE TABLE "Team" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, "name" TEXT NOT NULL, @@ -69,8 +69,8 @@ CREATE TABLE "Team" ( -- CreateTable CREATE TABLE "Membership" ( - "teamId" INTEGER NOT NULL, - "userId" INTEGER NOT NULL, + "teamId" TEXT NOT NULL, + "userId" TEXT NOT NULL, "accepted" BOOLEAN NOT NULL DEFAULT false, "role" "MembershipRole" NOT NULL, @@ -79,22 +79,22 @@ CREATE TABLE "Membership" ( -- CreateTable CREATE TABLE "ApiKey" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "lastUsedAt" TIMESTAMP(3), "label" TEXT, "hashedKey" TEXT NOT NULL, - "userId" INTEGER NOT NULL, + "userId" TEXT NOT NULL, CONSTRAINT "ApiKey_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Account" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, - "userId" INTEGER NOT NULL, + "userId" TEXT NOT NULL, "type" TEXT NOT NULL, "provider" TEXT NOT NULL, "providerAccountId" TEXT NOT NULL, @@ -111,7 +111,7 @@ CREATE TABLE "Account" ( -- CreateTable CREATE TABLE "User" ( - "id" SERIAL NOT NULL, + "id" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, "name" TEXT, diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index f32450114a..bcb4075d71 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -18,13 +18,13 @@ enum PipelineType { } model Pipeline { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") name String type PipelineType form Form @relation(fields: [formId], references: [id], onDelete: Cascade) - formId Int + formId String enabled Boolean @default(false) config Json @default("{}") } @@ -34,7 +34,7 @@ model Customer { createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) - teamId Int + teamId String submissions Submission[] data Json @default("{}") @@ -42,31 +42,31 @@ model Customer { } model Form { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") label String team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) - teamId Int + teamId String schema Json @default("{}") submissions Submission[] pipelines Pipeline[] } model Submission { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") form Form @relation(fields: [formId], references: [id], onDelete: Cascade) - formId Int + formId String customer Customer? @relation(fields: [customerId, teamId], references: [id, teamId]) customerId String? - teamId Int? + teamId String? data Json @default("{}") } model Team { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") name String @@ -83,9 +83,9 @@ enum MembershipRole { model Membership { team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) - teamId Int + teamId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int + userId String accepted Boolean @default(false) role MembershipRole @@ -93,13 +93,13 @@ model Membership { } model ApiKey { - id Int @id @unique @default(autoincrement()) + id String @id @unique @default(cuid()) createdAt DateTime @default(now()) lastUsedAt DateTime? label String? hashedKey String @unique() user User @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int + userId String } enum IdentityProvider { @@ -108,11 +108,11 @@ enum IdentityProvider { } model Account { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int + userId String type String provider String providerAccountId String @@ -128,7 +128,7 @@ model Account { } model User { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @updatedAt @map(name: "updated_at") name String? diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 232706d09c..e4d9097c4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,43 +14,6 @@ importers: tsx: 3.9.0 turbo: 1.6.3 - apps/examples: - specifiers: - '@formbricks/react': workspace:* - '@formbricks/tailwind-config': workspace:* - '@formbricks/tsconfig': workspace:* - '@formbricks/ui': workspace:* - '@heroicons/react': ^2.0.13 - '@types/node': ^18.11.9 - '@types/react': ^18.0.25 - '@types/react-dom': ^18.0.8 - autoprefixer: ^10.4.12 - eslint-config-formbricks: workspace:* - next: latest - postcss: ^8.4.18 - react: ^18.2.0 - react-dom: ^18.2.0 - tailwindcss: ^3.2.2 - typescript: ^4.8.4 - dependencies: - '@formbricks/react': link:../../packages/react - '@formbricks/ui': link:../../packages/ui - '@heroicons/react': 2.0.13_react@18.2.0 - next: 13.0.5_biqbaboplfbrettd7655fr4n2y - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - devDependencies: - '@formbricks/tailwind-config': link:../../packages/tailwind-config - '@formbricks/tsconfig': link:../../packages/tsconfig - '@types/node': 18.11.9 - '@types/react': 18.0.25 - '@types/react-dom': 18.0.9 - autoprefixer: 10.4.12_postcss@8.4.18 - eslint-config-formbricks: link:../../packages/eslint-config-formbricks - postcss: 8.4.18 - tailwindcss: 3.2.4_postcss@8.4.18 - typescript: 4.9.3 - apps/formbricks-com: specifiers: '@docsearch/react': ^3.3.0 @@ -137,6 +100,7 @@ importers: next-auth: ^4.17.0 nodemailer: ^6.8.0 postcss: ^8.4.19 + prismjs: ^1.29.0 react: ^18.2.0 react-dom: ^18.2.0 react-icons: ^4.6.0 @@ -156,6 +120,7 @@ importers: next: 13.0.5_biqbaboplfbrettd7655fr4n2y next-auth: 4.17.0_2xoejpawkzgot77rbv5mbik6ve nodemailer: 6.8.0 + prismjs: 1.29.0 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 react-icons: 4.6.0_react@18.2.0 @@ -12966,6 +12931,11 @@ packages: engines: {node: '>=6'} dev: false + /prismjs/1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true