diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..4d765f2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,3 @@ { - "extends": "next/core-web-vitals" + "extends": ["next/core-web-vitals", "prettier"] } diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5c18675 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +package.json +package-lock.json +.next diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..275f5ea --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,18 @@ +module.exports = { + printWidth: 100, + trailingComma: "all", + importOrder: [ + "^(next)|(next/(.*))$", + "^(react)|(react/(.*))$", + "", + "^@/components/(.*)$", + "^@/types/(.*)$", + "^@/lib/(.*)$", + "^@/styles/(.*)$", + "^@/images/(.*)$", + "^@/svgs/(.*)$", + "^[./]", + ], + importOrderSeparation: true, + importOrderSortSpecifiers: true, +}; diff --git a/.vscode/settings.json b/.vscode/settings.json index c5fdf8f..8d1dae4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,21 @@ { - "editor.defaultFormatter": "dbaeumer.vscode-eslint", - "editor.formatOnSave": true -} \ No newline at end of file + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "editor.rulers": [100] +} diff --git a/package-lock.json b/package-lock.json index 4725072..7d3feed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,12 +19,14 @@ "@paralleldrive/cuid2": "^2.2.2", "@react-email/components": "0.0.22", "axios": "^1.7.4", + "chakra-react-select": "^4.10.1", "date-fns": "^3.6.0", "framer-motion": "^11.5.4", "next": "14.2.8", + "next-plausible": "^3.12.2", "react": "^18", "react-code-block": "^1.0.0", - "react-color": "^2.19.3", + "react-color-palette": "^7.3.0", "react-dom": "^18", "react-hook-form": "^7.53.0", "react-icons": "^5.2.1", @@ -38,7 +40,9 @@ "@types/react-dom": "^18", "eslint": "^8", "eslint-config-next": "14.2.5", + "eslint-config-prettier": "^9.1.0", "postcss": "^8", + "prettier": "^3.3.3", "tailwindcss": "^3.4.1", "typescript": "^5" } @@ -1689,14 +1693,6 @@ "deprecated": "Use @eslint/object-schema instead", "dev": true }, - "node_modules/@icons/material": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", - "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", - "peerDependencies": { - "react": "*" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2791,14 +2787,12 @@ "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "devOptional": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2813,6 +2807,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", @@ -3542,6 +3544,20 @@ } ] }, + "node_modules/chakra-react-select": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/chakra-react-select/-/chakra-react-select-4.10.1.tgz", + "integrity": "sha512-0d7lubrmcm7molVYNYWEYi7o71W8wn/WruINon+m23XQLYvJ+bZlYVawDdWYdJjX8O1nzJlTDo4b7CB6zTsr4A==", + "dependencies": { + "react-select": "5.8.x" + }, + "peerDependencies": { + "@chakra-ui/react": "2.x", + "@emotion/react": "^11.8.1", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4069,6 +4085,15 @@ "node": ">=6.0.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -4507,6 +4532,18 @@ } } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -6382,11 +6419,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -6444,11 +6476,6 @@ "node": ">= 16" } }, - "node_modules/material-colors": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", - "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" - }, "node_modules/md-to-react-email": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.2.tgz", @@ -6465,6 +6492,11 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -6664,6 +6696,19 @@ } } }, + "node_modules/next-plausible": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/next-plausible/-/next-plausible-3.12.2.tgz", + "integrity": "sha512-jyOYLAdwaZZR6nrzFhN9xfVjzYOG6mIQ/LLDCfdAS99ELy759cKfNxluGo+pI2Xh9cYxTFYYZGlnkyR3IPy4yg==", + "funding": { + "url": "https://github.com/4lejandrito/next-plausible?sponsor=1" + }, + "peerDependencies": { + "next": "^11.1.0 || ^12.0.0 || ^13.0.0 || ^14.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -7287,6 +7332,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prism-react-renderer": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz", @@ -7388,21 +7448,15 @@ "react-dom": "^18" } }, - "node_modules/react-color": { - "version": "2.19.3", - "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", - "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", - "dependencies": { - "@icons/material": "^0.2.4", - "lodash": "^4.17.15", - "lodash-es": "^4.17.15", - "material-colors": "^1.2.1", - "prop-types": "^15.5.10", - "reactcss": "^1.2.0", - "tinycolor2": "^1.4.1" + "node_modules/react-color-palette": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-color-palette/-/react-color-palette-7.3.0.tgz", + "integrity": "sha512-GCgz+XEcbyFkq5wVvrPiXp8mUnOI3oObtmOtsZBCpDXgzHcDCJdssW8lTtVXbUqodo6pOw6pwYQRlXpi/ekkzQ==", + "engines": { + "node": ">=10" }, "peerDependencies": { - "react": "*" + "react": ">=16.8" } }, "node_modules/react-dom": { @@ -7530,6 +7584,26 @@ } } }, + "node_modules/react-select": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.1.tgz", + "integrity": "sha512-RT1CJmuc+ejqm5MPgzyZujqDskdvB9a9ZqrdnVLsvAHjJ3Tj0hELnLeVPQlmYdVKCdCpxanepl6z7R5KhXhWzg==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -7552,6 +7626,21 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -7591,14 +7680,6 @@ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" }, - "node_modules/reactcss": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", - "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", - "dependencies": { - "lodash": "^4.0.1" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -8589,11 +8670,6 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -8852,6 +8928,19 @@ } } }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", diff --git a/package.json b/package.json index b1face3..3bca07b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "format": "prettier --write \"**/*.{css,js,jsx,ts,tsx,json}\"" }, "dependencies": { "@chakra-ui/icons": "^2.1.1", @@ -20,12 +21,14 @@ "@paralleldrive/cuid2": "^2.2.2", "@react-email/components": "0.0.22", "axios": "^1.7.4", + "chakra-react-select": "^4.10.1", "date-fns": "^3.6.0", "framer-motion": "^11.5.4", "next": "14.2.8", + "next-plausible": "^3.12.2", "react": "^18", "react-code-block": "^1.0.0", - "react-color": "^2.19.3", + "react-color-palette": "^7.3.0", "react-dom": "^18", "react-hook-form": "^7.53.0", "react-icons": "^5.2.1", @@ -39,7 +42,9 @@ "@types/react-dom": "^18", "eslint": "^8", "eslint-config-next": "14.2.5", + "eslint-config-prettier": "^9.1.0", "postcss": "^8", + "prettier": "^3.3.3", "tailwindcss": "^3.4.1", "typescript": "^5" } diff --git a/public/fonts/brother-1816/brother-1816-book.woff2 b/public/fonts/brother-1816/brother-1816-book.woff2 new file mode 100644 index 0000000..e7a2ece Binary files /dev/null and b/public/fonts/brother-1816/brother-1816-book.woff2 differ diff --git a/public/fonts/brother-1816/brother-1816-light.woff2 b/public/fonts/brother-1816/brother-1816-light.woff2 new file mode 100644 index 0000000..2ef1228 Binary files /dev/null and b/public/fonts/brother-1816/brother-1816-light.woff2 differ diff --git a/public/fonts/brother-1816/brother-1816-medium.woff2 b/public/fonts/brother-1816/brother-1816-medium.woff2 new file mode 100644 index 0000000..cb196d0 Binary files /dev/null and b/public/fonts/brother-1816/brother-1816-medium.woff2 differ diff --git a/public/fonts/brother-1816/brother-1816-regular.woff2 b/public/fonts/brother-1816/brother-1816-regular.woff2 new file mode 100644 index 0000000..5a0eb84 Binary files /dev/null and b/public/fonts/brother-1816/brother-1816-regular.woff2 differ diff --git a/public/images/blur.svg b/public/images/blur.svg new file mode 100644 index 0000000..6cb8a26 --- /dev/null +++ b/public/images/blur.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/dots.svg b/public/images/dots.svg new file mode 100644 index 0000000..1b9850c --- /dev/null +++ b/public/images/dots.svg @@ -0,0 +1,778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/playground-bg.svg b/public/images/playground-bg.svg new file mode 100644 index 0000000..3885cf2 --- /dev/null +++ b/public/images/playground-bg.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/shine.svg b/public/images/shine.svg new file mode 100644 index 0000000..23e0713 --- /dev/null +++ b/public/images/shine.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/novuLogo.svg b/public/novuLogo.svg index e6c07ca..0adcb2c 100644 --- a/public/novuLogo.svg +++ b/public/novuLogo.svg @@ -1,49 +1,24 @@ - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - + - + - + - - - diff --git a/src/app/components/ButtonGithubStars.tsx b/src/app/components/ButtonGithubStars.tsx new file mode 100644 index 0000000..c975c54 --- /dev/null +++ b/src/app/components/ButtonGithubStars.tsx @@ -0,0 +1,36 @@ +"use client"; + +import { Button } from "@chakra-ui/react"; +import { usePlausible } from "next-plausible"; +import NextLink from "next/link"; +import { GitHubIcon } from "./icons/GitHub"; + +const ButtonGithubStars = ({ starsCount }: { starsCount: number }) => { + const plausible = usePlausible(); + return ( + Star us + + {`${(starsCount / 1000).toFixed(1)}k`} + + + ); +}; + +export default ButtonGithubStars; diff --git a/src/app/components/ColorPickerField.tsx b/src/app/components/ColorPickerField.tsx new file mode 100644 index 0000000..b20c54f --- /dev/null +++ b/src/app/components/ColorPickerField.tsx @@ -0,0 +1,71 @@ +"use client"; +import React, { useRef, useState, useEffect } from "react"; +import { PickerIcon } from "./icons/Picker"; +import useClickOutside from "../hooks/useClickOutside"; +import { UseFormRegister, UseFormSetValue } from "react-hook-form"; +import { ColorPicker, useColor } from "react-color-palette"; +import "react-color-palette/css"; +import { FormControl, FormLabel, Box, Input } from "@chakra-ui/react"; + +function ColorPickerField({ + register, + setValue, + placeholder, + name, + label, +}: { + register: UseFormRegister; + setValue: UseFormSetValue; + placeholder: string; + name: string; + label: string; +}) { + const [color, setColor] = useColor(placeholder); + const [openColorPicker, setOpenColorPicker] = useState(false); + const pickerRef = useRef(null); + + useClickOutside([pickerRef], () => setOpenColorPicker(false)); + + useEffect(() => { + setValue(name, color.hex); + }, [color, name, setValue]); + + const handleColorChange = (newColor: any) => { + setColor(newColor); + setValue(name, newColor.hex); + }; + + return ( + + + {label} + + + setOpenColorPicker(!openColorPicker)} + cursor="pointer" + /> + + + + {openColorPicker && ( + + + + )} + + + ); +} + +export default ColorPickerField; diff --git a/src/app/components/InboxDesignForm.tsx b/src/app/components/InboxDesignForm.tsx index 09d6eee..451d81b 100644 --- a/src/app/components/InboxDesignForm.tsx +++ b/src/app/components/InboxDesignForm.tsx @@ -1,8 +1,9 @@ "use client"; import React from "react"; +import dynamic from "next/dynamic"; import { useTheme } from "../contexts/ThemeContext"; - +import { Select } from "chakra-react-select"; import { VStack, Text, @@ -10,15 +11,70 @@ import { FormLabel, Switch, SimpleGrid, - Select, Input, + Flex, } from "@chakra-ui/react"; +import { Controller } from "react-hook-form"; + +const ColorPickerField = dynamic(() => import("./ColorPickerField"), { + ssr: false, +}); + +const items = [ + { + label: "Primary Color", + name: "colorPrimary", + placeholder: "#0081F1", + }, + { + label: "Primary Foreground", + name: "colorPrimaryForeground", + placeholder: "white", + }, + { + label: "Secondary Color", + name: "colorSecondary", + placeholder: "#F3F3F3", + }, + { + label: "Secondary Foreground", + name: "colorSecondaryForeground", + placeholder: "#1A1523", + }, + { + label: "Counter Color", + name: "colorCounter", + placeholder: "#E5484D", + }, + { + label: "Counter Foreground", + name: "colorCounterForeground", + placeholder: "white", + }, + { + label: "Background Color", + name: "colorBackground", + placeholder: "#FCFCFC", + }, + { + label: "Foreground Color", + name: "colorForeground", + placeholder: "#1A1523", + }, + { + label: "Neutral Color", + name: "colorNeutral", + placeholder: "black", + }, +]; export function InboxDesignForm() { const { inboxThemeForm: { handleSubmit, register, + setValue, + control, formState: { errors, isSubmitting }, getValues, }, @@ -43,124 +99,96 @@ export function InboxDesignForm() { return (
- - - Configure And Design Inbox Component - - - Click on the "Apply Changes" button to see the changes in - the Inbox component. - + + + + Configure And Design Inbox Component + + + Click on the "Apply Changes" button to see the changes in the Inbox component. + + - + Keep Inbox Open - + - - Inbox Language - + + Select the language for your inbox notifications. - - + + ( + - - - Primary Foreground - - - - Secondary Color - - - - Secondary Foreground - - - - Counter Color - - - - Counter Foreground - - - - Background Color - - - - Foreground Color - - - - Neutral Color - - - - Font Size + + Font Size + - Border Radius - + + Border Radius + + diff --git a/src/app/components/Navbar.tsx b/src/app/components/Navbar.tsx index e47c095..25f3465 100644 --- a/src/app/components/Navbar.tsx +++ b/src/app/components/Navbar.tsx @@ -1,21 +1,10 @@ "use client"; -import { - Box, - Flex, - Text, - HStack, - Button, - Image, - VStack, - useDisclosure, - useColorModeValue, -} from "@chakra-ui/react"; -import CodeModal from "./CodeModal"; +import NextLink from "next/link"; +import { Box, Flex, HStack, Button, Image, useColorModeValue } from "@chakra-ui/react"; -const Navbar = () => { - const { isOpen, onOpen, onClose } = useDisclosure(); - const bgColor = useColorModeValue("white", "gray.800"); +const Navbar = ({ children }: { children: React.ReactNode }) => { + const bgColor = useColorModeValue("", "gray.800"); const textColor = useColorModeValue("gray.10", "gray.200"); return ( @@ -23,64 +12,43 @@ const Navbar = () => { as="nav" position="sticky" top={0} - zIndex={10} bg={bgColor} boxShadow="sm" transition="box-shadow 0.2s" _hover={{ boxShadow: "md" }} > - + Novu Logo - window.open( - "https://novu.co?utm_source=sourceInboxPlayground", - "_blank" - ) + window.open("https://novu.co?utm_source=sourceInboxPlayground", "_blank") } cursor="pointer" /> - - - Inbox Component Playground - - - In-app notifications powered by Novu - - - + + {children} - - ); }; diff --git a/src/app/components/NotificationContentForm.tsx b/src/app/components/NotificationContentForm.tsx index 68db65e..de03cf3 100644 --- a/src/app/components/NotificationContentForm.tsx +++ b/src/app/components/NotificationContentForm.tsx @@ -1,5 +1,5 @@ "use client"; - +import { Select, OptionBase } from "chakra-react-select"; import React, { useEffect } from "react"; import { Controller } from "react-hook-form"; import { @@ -10,7 +10,6 @@ import { Switch, Text, VStack, - Select, Heading, Flex, Divider, @@ -22,6 +21,11 @@ interface Workflow { title: string; } +interface WorkflowOption extends OptionBase { + label: string; + value: string; +} + interface NotificationFormState { subscriberFirstName: string; subscriberLastName: string; @@ -52,6 +56,11 @@ const NotificationContentForm: React.FC = ({ selectedTheme, } = useTheme(); + const workflowOptions: WorkflowOption[] = workflows.map((workflow) => ({ + label: workflow.title, + value: workflow.id, + })); + const formValues = watch(); const selectedWorkflowId = watch("selectedWorkflow"); @@ -63,7 +72,7 @@ const NotificationContentForm: React.FC = ({ useEffect(() => { const selectedWorkflow = selectedTheme.workflows.find( - (workflow) => workflow.id === selectedWorkflowId + (workflow) => workflow.id === selectedWorkflowId, ); if (selectedWorkflow && selectedWorkflow.data) { @@ -100,8 +109,17 @@ const NotificationContentForm: React.FC = ({
- Subscriber - + + Subscriber + + The recipient of the notification, change the details to customize.
@@ -125,66 +143,94 @@ const NotificationContentForm: React.FC = ({ render={({ field }) => ( Last Name - + )} />
- - - ( - - Workflow - - Select a workflow to customize the notification content. - - - - )} - /> - - ( - - Subject - - - )} - /> + + + ( + + + Workflow + + + Select a workflow to customize the notification content. + +