diff --git a/.eslintrc.json b/.eslintrc.json index 94186d2e0a2..9ddc3f12bc5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,7 +21,7 @@ } ] }, - "extends": ["next/core-web-vitals", "prettier"], + "extends": ["next", "next/core-web-vitals", "prettier"], "plugins": ["prettier", "unused-imports"], "ignorePatterns": ["src/enums"] } diff --git a/next.config.js b/next.config.js index a4ecd94d6f2..211ca052c8d 100644 --- a/next.config.js +++ b/next.config.js @@ -14,11 +14,13 @@ const config = { compiler: { styledComponents: true, }, + experimental: { + optimizePackageImports: ["@mantine/core", "@mantine/hooks"], + }, webpack: config => { config.resolve.fallback = { fs: false }; config.output.webassemblyModuleFilename = "static/wasm/[modulehash].wasm"; - config.experiments = { asyncWebAssembly: true }; - + config.experiments = { asyncWebAssembly: true, layers: true }; return config; }, }; diff --git a/package.json b/package.json index 711f31a8a2f..d530c1e16aa 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "tsc --project tsconfig.json && eslint src && prettier --check src", + "lint": "tsc --project tsconfig.json && eslint src && prettier --check src && next lint", "lint:fix": "eslint --fix src & prettier --write src", "analyze": "ANALYZE=true npm run build" }, @@ -29,14 +29,16 @@ "dayjs": "^1.11.10", "gofmt.js": "^0.0.2", "html-to-image": "^1.11.11", + "impl": "^1.3.0", "jq-in-the-browser": "^0.7.2", "jq-web": "^0.5.1", "js-yaml": "^4.1.0", "json-2-csv": "^5.0.1", "json_typegen_wasm": "^0.7.0", - "jsonc-parser": "^3.2.0", + "jsonc-parser": "^3.2.1", "jsonwebtoken": "^9.0.2", "jxon": "^2.0.0-beta.5", + "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", @@ -59,7 +61,7 @@ "styled-components": "^6.1.8", "toml": "^3.0.0", "use-long-press": "^3.2.0", - "zustand": "^4.5.0" + "zustand": "^4.4.7" }, "devDependencies": { "@next/bundle-analyzer": "^14.1.0", @@ -74,14 +76,14 @@ "@types/lodash.update": "^4.10.9", "@types/node": "^20.11.16", "@types/pako": "^2.0.3", - "@types/react": "18.2.51", + "@types/react": "18.2.52", "@types/react-dom": "^18.2.18", "eslint": "8.56.0", "eslint-config-next": "14.1.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-unused-imports": "^3.0.0", - "prettier": "^3.2.4", + "prettier": "^3.2.2", "ts-node": "^10.9.2", "typescript": "5.3.3" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ade8ea01cc4..bfa9dfe2532 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ dependencies: version: 7.5.1(@mantine/core@7.5.1)(@mantine/hooks@7.5.1)(react-dom@18.2.0)(react@18.2.0) '@mantine/core': specifier: ^7.5.1 - version: 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.51)(react-dom@18.2.0)(react@18.2.0) + version: 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.52)(react-dom@18.2.0)(react@18.2.0) '@mantine/dropzone': specifier: ^7.5.1 version: 7.5.1(@mantine/core@7.5.1)(@mantine/hooks@7.5.1)(react-dom@18.2.0)(react@18.2.0) @@ -50,6 +50,9 @@ dependencies: html-to-image: specifier: ^1.11.11 version: 1.11.11 + impl: + specifier: ^1.3.0 + version: 1.3.0 jq-in-the-browser: specifier: ^0.7.2 version: 0.7.2 @@ -66,14 +69,17 @@ dependencies: specifier: ^0.7.0 version: 0.7.0 jsonc-parser: - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^3.2.1 + version: 3.2.1 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 jxon: specifier: ^2.0.0-beta.5 version: 2.0.0-beta.5 + lodash: + specifier: ^4.17.21 + version: 4.17.21 lodash.debounce: specifier: ^4.0.8 version: 4.0.8 @@ -118,7 +124,7 @@ dependencies: version: 5.0.1(react@18.2.0) react-json-tree: specifier: ^0.18.0 - version: 0.18.0(@types/react@18.2.51)(react@18.2.0) + version: 0.18.0(@types/react@18.2.52)(react@18.2.0) react-linkify-it: specifier: ^1.0.8 version: 1.0.8(react@18.2.0) @@ -141,8 +147,8 @@ dependencies: specifier: ^3.2.0 version: 3.2.0(react@18.2.0) zustand: - specifier: ^4.5.0 - version: 4.5.0(@types/react@18.2.51)(react@18.2.0) + specifier: ^4.4.7 + version: 4.5.0(@types/react@18.2.52)(react@18.2.0) devDependencies: '@next/bundle-analyzer': @@ -182,8 +188,8 @@ devDependencies: specifier: ^2.0.3 version: 2.0.3 '@types/react': - specifier: 18.2.51 - version: 18.2.51 + specifier: 18.2.52 + version: 18.2.52 '@types/react-dom': specifier: ^18.2.18 version: 18.2.18 @@ -203,7 +209,7 @@ devDependencies: specifier: ^3.0.0 version: 3.0.0(eslint@8.56.0) prettier: - specifier: ^3.2.4 + specifier: ^3.2.2 version: 3.2.4 ts-node: specifier: ^10.9.2 @@ -275,9 +281,9 @@ packages: resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.6 + '@babel/types': 7.23.9 '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.22 jsesc: 2.5.2 /@babel/helper-compilation-targets@7.23.6: @@ -396,19 +402,11 @@ packages: regenerator-runtime: 0.14.1 dev: false - /@babel/runtime@7.23.8: - resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - /@babel/runtime@7.23.9: resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - dev: false /@babel/template@7.22.15: resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} @@ -485,7 +483,6 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: false /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} @@ -648,7 +645,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.22 /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} @@ -661,18 +658,11 @@ packages: /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - /@jridgewell/trace-mapping@0.3.20: - resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - /@jridgewell/trace-mapping@0.3.22: resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: false /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -707,7 +697,7 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 dependencies: - '@mantine/core': 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.51)(react-dom@18.2.0)(react@18.2.0) + '@mantine/core': 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.52)(react-dom@18.2.0)(react@18.2.0) '@mantine/hooks': 7.5.1(react@18.2.0) clsx: 2.0.0 highlight.js: 11.9.0 @@ -715,7 +705,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@mantine/core@7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.51)(react-dom@18.2.0)(react@18.2.0): + /@mantine/core@7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.52)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-V7apuQuRubqxTRXb1uxOM43K7tkLRzpbb1ONJ/sj8QRp/26bShkdYp7EVuSKyrQ8DQ5EGYyBBGyzBOQARh41gA==} peerDependencies: '@mantine/hooks': 7.5.1 @@ -728,8 +718,8 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-number-format: 5.3.1(react-dom@18.2.0)(react@18.2.0) - react-remove-scroll: 2.5.7(@types/react@18.2.51)(react@18.2.0) - react-textarea-autosize: 8.5.3(@types/react@18.2.51)(react@18.2.0) + react-remove-scroll: 2.5.7(@types/react@18.2.52)(react@18.2.0) + react-textarea-autosize: 8.5.3(@types/react@18.2.52)(react@18.2.0) type-fest: 3.13.1 transitivePeerDependencies: - '@types/react' @@ -743,7 +733,7 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 dependencies: - '@mantine/core': 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.51)(react-dom@18.2.0)(react@18.2.0) + '@mantine/core': 7.5.1(@mantine/hooks@7.5.1)(@types/react@18.2.52)(react-dom@18.2.0)(react@18.2.0) '@mantine/hooks': 7.5.1(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -957,8 +947,8 @@ packages: rollup: 2.78.0 dev: false - /@rushstack/eslint-patch@1.7.0: - resolution: {integrity: sha512-Jh4t/593gxs0lJZ/z3NnasKlplXT2f+4y/LZYuaKZW5KAaiVFL/fThhs+17EbUd53jUVJ0QudYCBGbN/psvaqg==} + /@rushstack/eslint-patch@1.7.2: + resolution: {integrity: sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==} dev: true /@sentry-internal/feedback@7.99.0: @@ -1361,11 +1351,11 @@ packages: /@types/react-dom@18.2.18: resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 dev: true - /@types/react@18.2.51: - resolution: {integrity: sha512-XeoMaU4CzyjdRr3c4IQQtiH7Rpo18V07rYZUucEZQwOUEtGgTXv7e6igQiQ+xnV6MbMe1qjEmKdgMNnfppnXfg==} + /@types/react@18.2.52: + resolution: {integrity: sha512-E/YjWh3tH+qsLKaUzgpZb5AY0ChVa+ZJzF7ogehVILrFpdQk6nC/WXOv0bfFEABbXbgNxLBGU7IIZByPKb6eBw==} dependencies: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 @@ -1384,8 +1374,8 @@ packages: '@types/node': 20.11.16 dev: false - /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} + /@typescript-eslint/parser@6.20.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1394,10 +1384,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.19.0 - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/scope-manager': 6.20.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/typescript-estree': 6.20.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.20.0 debug: 4.3.4 eslint: 8.56.0 typescript: 5.3.3 @@ -1405,21 +1395,21 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.19.0: - resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} + /@typescript-eslint/scope-manager@6.20.0: + resolution: {integrity: sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/visitor-keys': 6.20.0 dev: true - /@typescript-eslint/types@6.19.0: - resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} + /@typescript-eslint/types@6.20.0: + resolution: {integrity: sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3): - resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} + /@typescript-eslint/typescript-estree@6.20.0(typescript@5.3.3): + resolution: {integrity: sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1427,8 +1417,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/visitor-keys': 6.20.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1440,11 +1430,11 @@ packages: - supports-color dev: true - /@typescript-eslint/visitor-keys@6.19.0: - resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} + /@typescript-eslint/visitor-keys@6.20.0: + resolution: {integrity: sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/types': 6.20.0 eslint-visitor-keys: 3.4.3 dev: true @@ -1668,6 +1658,11 @@ packages: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} + /available-typed-arrays@1.0.6: + resolution: {integrity: sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==} + engines: {node: '>= 0.4'} + dev: true + /axe-core@4.7.0: resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} engines: {node: '>=4'} @@ -1788,10 +1783,6 @@ packages: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false - /caniuse-lite@1.0.30001579: - resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} - dev: false - /caniuse-lite@1.0.30001583: resolution: {integrity: sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==} dev: false @@ -2285,12 +2276,12 @@ packages: optional: true dependencies: '@next/eslint-plugin-next': 14.1.0 - '@rushstack/eslint-patch': 1.7.0 - '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@rushstack/eslint-patch': 1.7.2 + '@typescript-eslint/parser': 6.20.0(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0) eslint-plugin-react: 7.33.2(eslint@8.56.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0) @@ -2319,7 +2310,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2329,8 +2320,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.56.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -2342,7 +2333,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -2363,16 +2354,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.20.0(eslint@8.56.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -2382,7 +2373,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.20.0(eslint@8.56.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -2391,7 +2382,7 @@ packages: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.20.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -2413,7 +2404,7 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.23.9 aria-query: 5.3.0 array-includes: 3.1.7 array.prototype.flatmap: 1.3.2 @@ -2902,7 +2893,7 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.0 + ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 dev: true @@ -2973,6 +2964,13 @@ packages: dependencies: has-symbols: 1.0.3 + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + /has@1.0.4: resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} @@ -3032,10 +3030,19 @@ packages: engines: {node: '>= 4'} dev: true + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + /immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} dev: false + /impl@1.3.0: + resolution: {integrity: sha512-kVha3pLxcXXNg60DBwNt63sj5CmkYHMyIj7RypOQDYQvMX90lBFKTAGtFCjJy4jBcm79LNyUVIRPl4UHXJL+OA==} + dev: false + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -3104,7 +3111,7 @@ packages: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 dev: true /is-bigint@1.0.4: @@ -3179,7 +3186,7 @@ packages: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 dev: true /is-glob@4.0.3: @@ -3393,8 +3400,8 @@ packages: resolution: {integrity: sha512-xTDD7jlMpXB8S/6lD00aqOmHPuVszG4vtrJTaED8Mb6ziryGtXmtkREWpuvJbWWj45aVFGO3O/WjwxRBLw8dUQ==} dev: false - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} dev: false /jsonwebtoken@9.0.2: @@ -3601,7 +3608,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} @@ -3609,8 +3615,8 @@ packages: dependencies: js-tokens: 4.0.0 - /lru-cache@10.1.0: - resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} + /lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} engines: {node: 14 || >=16.14} dev: true @@ -3791,7 +3797,7 @@ packages: '@next/env': 14.1.0 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001579 + caniuse-lite: 1.0.30001583 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.2.0 @@ -4059,7 +4065,7 @@ packages: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} dependencies: - lru-cache: 10.1.0 + lru-cache: 10.2.0 minipass: 7.0.4 dev: true @@ -4249,7 +4255,7 @@ packages: /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - /react-json-tree@0.18.0(@types/react@18.2.51)(react@18.2.0): + /react-json-tree@0.18.0(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-Qe6HKSXrr++n9Y31nkRJ3XvQMATISpqigH1vEKhLwB56+nk5thTP0ITThpjxY6ZG/ubpVq/aEHIcyLP/OPHxeA==} peerDependencies: '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -4257,7 +4263,7 @@ packages: dependencies: '@babel/runtime': 7.23.6 '@types/lodash': 4.14.202 - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 react-base16-styling: 0.9.1 dev: false @@ -4281,7 +4287,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /react-remove-scroll-bar@2.3.4(@types/react@18.2.51)(react@18.2.0): + /react-remove-scroll-bar@2.3.4(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} engines: {node: '>=10'} peerDependencies: @@ -4291,13 +4297,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.51)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.52)(react@18.2.0) tslib: 2.6.2 dev: false - /react-remove-scroll@2.5.7(@types/react@18.2.51)(react@18.2.0): + /react-remove-scroll@2.5.7(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==} engines: {node: '>=10'} peerDependencies: @@ -4307,13 +4313,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 - react-remove-scroll-bar: 2.3.4(@types/react@18.2.51)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.51)(react@18.2.0) + react-remove-scroll-bar: 2.3.4(@types/react@18.2.52)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.52)(react@18.2.0) tslib: 2.6.2 - use-callback-ref: 1.3.1(@types/react@18.2.51)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.51)(react@18.2.0) + use-callback-ref: 1.3.1(@types/react@18.2.52)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.52)(react@18.2.0) dev: false /react-simple-typewriter@5.0.1(react-dom@18.2.0)(react@18.2.0): @@ -4327,7 +4333,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /react-style-singleton@2.2.1(@types/react@18.2.51)(react@18.2.0): + /react-style-singleton@2.2.1(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} peerDependencies: @@ -4337,14 +4343,14 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 tslib: 2.6.2 dev: false - /react-textarea-autosize@8.5.3(@types/react@18.2.51)(react@18.2.0): + /react-textarea-autosize@8.5.3(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==} engines: {node: '>=10'} peerDependencies: @@ -4353,7 +4359,7 @@ packages: '@babel/runtime': 7.23.9 react: 18.2.0 use-composed-ref: 1.3.0(react@18.2.0) - use-latest: 1.2.1(@types/react@18.2.51)(react@18.2.0) + use-latest: 1.2.1(@types/react@18.2.52)(react@18.2.0) transitivePeerDependencies: - '@types/react' dev: false @@ -5134,7 +5140,7 @@ packages: punycode: 2.3.1 dev: true - /use-callback-ref@1.3.1(@types/react@18.2.51)(react@18.2.0): + /use-callback-ref@1.3.1(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==} engines: {node: '>=10'} peerDependencies: @@ -5144,7 +5150,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 tslib: 2.6.2 dev: false @@ -5157,7 +5163,7 @@ packages: react: 18.2.0 dev: false - /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.51)(react@18.2.0): + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: '@types/react': '*' @@ -5166,11 +5172,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 dev: false - /use-latest@1.2.1(@types/react@18.2.51)(react@18.2.0): + /use-latest@1.2.1(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==} peerDependencies: '@types/react': '*' @@ -5179,9 +5185,9 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 - use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.51)(react@18.2.0) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.52)(react@18.2.0) dev: false /use-long-press@3.2.0(react@18.2.0): @@ -5203,7 +5209,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /use-sidecar@1.1.2(@types/react@18.2.51)(react@18.2.0): + /use-sidecar@1.1.2(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} engines: {node: '>=10'} peerDependencies: @@ -5213,7 +5219,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 detect-node-es: 1.1.0 react: 18.2.0 tslib: 2.6.2 @@ -5295,7 +5301,7 @@ packages: engines: {node: '>= 0.4'} dependencies: function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-async-function: 2.0.0 is-date-object: 1.0.5 is-finalizationregistry: 1.0.2 @@ -5305,7 +5311,7 @@ packages: isarray: 2.0.5 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.13 + which-typed-array: 1.1.14 dev: true /which-collection@1.0.1: @@ -5331,6 +5337,17 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 + /which-typed-array@1.1.14: + resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.6 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -5444,7 +5461,7 @@ packages: engines: {node: '>=10'} dev: true - /zustand@4.5.0(@types/react@18.2.51)(react@18.2.0): + /zustand@4.5.0(@types/react@18.2.52)(react@18.2.0): resolution: {integrity: sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==} engines: {node: '>=12.7.0'} peerDependencies: @@ -5459,7 +5476,7 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.51 + '@types/react': 18.2.52 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) dev: false diff --git a/src/pages/_app.tsx b/src/app/CustomAppInit.tsx similarity index 74% rename from src/pages/_app.tsx rename to src/app/CustomAppInit.tsx index 708397cbae7..246b1bf5c46 100644 --- a/src/pages/_app.tsx +++ b/src/app/CustomAppInit.tsx @@ -1,38 +1,34 @@ +"use client"; + import React from "react"; -import type { AppProps } from "next/app"; import dynamic from "next/dynamic"; -import { useRouter } from "next/router"; +import { usePathname } from "next/navigation"; import { MantineProvider, createTheme } from "@mantine/core"; import "@mantine/core/styles.css"; import "@mantine/code-highlight/styles.css"; import { ThemeProvider } from "styled-components"; -import { SessionContextProvider, Session } from "@supabase/auth-helpers-react"; +import { SessionContextProvider } from "@supabase/auth-helpers-react"; import ReactGA from "react-ga4"; import GlobalStyle from "src/constants/globalStyle"; import { lightTheme } from "src/constants/theme"; import { supabase } from "src/lib/api/supabase"; import useUser from "src/store/useUser"; -const mantineTheme = createTheme({ - primaryShade: 8, -}); - const isDevelopment = process.env.NODE_ENV === "development"; const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_ID; ReactGA.initialize(GA_TRACKING_ID, { testMode: isDevelopment }); +const mantineTheme = createTheme({ + primaryShade: 8, +}); + const Toaster = dynamic(() => import("react-hot-toast").then(c => c.Toaster)); const ExternalMode = dynamic(() => import("src/layout/ExternalMode")); const ModalController = dynamic(() => import("src/layout/ModalController")); -function JsonCrack({ - Component, - pageProps, -}: AppProps<{ - initialSession: Session; -}>) { - const router = useRouter(); +export default function CustomAppInit({ children }: { children: React.ReactNode }): JSX.Element { + const pathname = usePathname(); const setSession = useUser(state => state.setSession); React.useEffect(() => { @@ -41,24 +37,20 @@ function JsonCrack({ }); }, [setSession]); - React.useEffect(() => { - const handleRouteChange = (page: string) => { - ReactGA.send({ hitType: "pageview", page }); - }; - - router.events.on("routeChangeComplete", handleRouteChange); + const handleRouteChange = (page: string) => { + ReactGA.send({ hitType: "pageview", page }); + }; - return () => { - router.events.off("routeChangeComplete", handleRouteChange); - }; - }, [router.events]); + React.useEffect(() => { + handleRouteChange(pathname || ""); + }, [pathname]); return ( - + {children} ); } - -export default JsonCrack; diff --git a/src/pages/docs.tsx b/src/app/docs/page.tsx similarity index 98% rename from src/pages/docs.tsx rename to src/app/docs/page.tsx index 1b7741fe8fe..526f0d12027 100644 --- a/src/pages/docs.tsx +++ b/src/app/docs/page.tsx @@ -1,3 +1,5 @@ +"use client"; + import React from "react"; import Head from "next/head"; import { Group, Paper, Stack, Text, Title } from "@mantine/core"; @@ -34,14 +36,14 @@ const StyledHighlight = styled.span<{ $link?: boolean; $alert?: boolean }>` margin: ${({ $alert }) => ($alert ? "8px 0" : "1px")}; `; -const Docs = () => { +export default function Page() { return ( Documentation - JSON Crack - + Documentation @@ -164,6 +166,4 @@ const Docs = () => { </Stack> </Layout> ); -}; - -export default Docs; +} diff --git a/src/pages/editor.tsx b/src/app/editor/page.tsx similarity index 79% rename from src/pages/editor.tsx rename to src/app/editor/page.tsx index ae4d357fb4d..d5db40feaeb 100644 --- a/src/pages/editor.tsx +++ b/src/app/editor/page.tsx @@ -1,7 +1,9 @@ +"use client"; + import React from "react"; import dynamic from "next/dynamic"; import Head from "next/head"; -import { useRouter } from "next/router"; +import { useSearchParams } from "next/navigation"; import styled from "styled-components"; import { BottomBar } from "src/containers/Editor/BottomBar"; import { Toolbar } from "src/containers/Toolbar"; @@ -12,7 +14,7 @@ import useJson from "src/store/useJson"; const Panes = dynamic(() => import("src/containers/Editor/Panes")); -export const StyledPageWrapper = styled.div` +const StyledPageWrapper = styled.div` height: calc(100vh - 27px); width: 100%; @@ -21,21 +23,21 @@ export const StyledPageWrapper = styled.div` } `; -export const StyledEditorWrapper = styled.div` +const StyledEditorWrapper = styled.div` width: 100%; height: 100%; overflow: hidden; `; -const EditorPage: React.FC = () => { - const { query, isReady } = useRouter(); +export default function Page() { + const query = useSearchParams(); const loading = useJson(state => state.loading); - const hasQuery = React.useMemo(() => Object.keys(query).length > 0, [query]); + const hasQuery = React.useMemo(() => query !== null && Object.keys(query).length > 0, [query]); const checkEditorSession = useFile(state => state.checkEditorSession); React.useEffect(() => { - if (isReady) checkEditorSession(query?.json); - }, [checkEditorSession, isReady, query]); + if (query) checkEditorSession(query.get("json") || ""); + }, [checkEditorSession, query]); if (loading) { return ( @@ -66,6 +68,4 @@ const EditorPage: React.FC = () => { </StyledEditorWrapper> </EditorWrapper> ); -}; - -export default EditorPage; +} diff --git a/src/app/forgot-password/ResetPassword.tsx b/src/app/forgot-password/ResetPassword.tsx new file mode 100644 index 00000000000..709ec3a3a10 --- /dev/null +++ b/src/app/forgot-password/ResetPassword.tsx @@ -0,0 +1,66 @@ +import React from "react"; +import { Paper, Stack, PasswordInput, Group, Button, Text } from "@mantine/core"; +import toast from "react-hot-toast"; +import { supabase } from "src/lib/api/supabase"; + +export function ResetPassword() { + const [loading, setLoading] = React.useState(false); + const [password, setPassword] = React.useState(""); + const [password2, setPassword2] = React.useState(""); + + const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => { + try { + e.preventDefault(); + setLoading(true); + + if (password !== password2) throw new Error("Passwords do not match"); + + const { error } = await supabase.auth.updateUser({ password }); + if (error) throw new Error(error.message); + + toast.success("Successfully updated password!"); + setTimeout(() => window.location.assign("/sign-in"), 2000); + } catch (error) { + if (error instanceof Error) toast.error(error.message); + } finally { + setLoading(false); + } + }; + + return ( + <Paper mx="auto" mt={70} maw={400} p="lg" withBorder> + <Text size="lg" w={500} mb="lg"> + Create New Password + </Text> + + <form onSubmit={onSubmit}> + <Stack> + <PasswordInput + value={password} + onChange={e => setPassword(e.target.value)} + required + label="New Password" + radius="sm" + placeholder="∗∗∗∗∗∗∗∗∗∗∗" + style={{ color: "black" }} + /> + <PasswordInput + value={password2} + onChange={e => setPassword2(e.target.value)} + required + label="Validate Password" + radius="sm" + placeholder="∗∗∗∗∗∗∗∗∗∗∗" + style={{ color: "black" }} + /> + </Stack> + + <Group justify="apart" mt="xl"> + <Button color="dark" type="submit" radius="sm" loading={loading} fullWidth> + Reset Password + </Button> + </Group> + </form> + </Paper> + ); +} diff --git a/src/pages/forgot-password.tsx b/src/app/forgot-password/page.tsx similarity index 52% rename from src/pages/forgot-password.tsx rename to src/app/forgot-password/page.tsx index 013aaa467d1..9b65d59e18c 100644 --- a/src/pages/forgot-password.tsx +++ b/src/app/forgot-password/page.tsx @@ -1,80 +1,23 @@ +"use client"; + import React from "react"; import Head from "next/head"; import Link from "next/link"; -import { useRouter } from "next/router"; -import { Button, Group, Paper, Stack, TextInput, Text, Anchor, PasswordInput } from "@mantine/core"; +import { useSearchParams } from "next/navigation"; +import { Button, Group, Paper, Stack, TextInput, Text, Anchor } from "@mantine/core"; import { toast } from "react-hot-toast"; import Layout from "src/layout/Layout"; import { supabase } from "src/lib/api/supabase"; +import { ResetPassword } from "./ResetPassword"; -function ResetPassword() { - const [loading, setLoading] = React.useState(false); - const [password, setPassword] = React.useState(""); - const [password2, setPassword2] = React.useState(""); - - const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => { - try { - e.preventDefault(); - setLoading(true); - - if (password !== password2) throw new Error("Passwords do not match"); - - const { error } = await supabase.auth.updateUser({ password }); - if (error) throw new Error(error.message); - - toast.success("Successfully updated password!"); - setTimeout(() => window.location.assign("/sign-in"), 2000); - } catch (error) { - if (error instanceof Error) toast.error(error.message); - } finally { - setLoading(false); - } - }; - - return ( - <Paper mx="auto" mt={70} maw={400} p="lg" withBorder> - <Text size="lg" w={500} mb="lg"> - Create New Password - </Text> - - <form onSubmit={onSubmit}> - <Stack> - <PasswordInput - value={password} - onChange={e => setPassword(e.target.value)} - required - label="New Password" - radius="sm" - placeholder="∗∗∗∗∗∗∗∗∗∗∗" - style={{ color: "black" }} - /> - <PasswordInput - value={password2} - onChange={e => setPassword2(e.target.value)} - required - label="Validate Password" - radius="sm" - placeholder="∗∗∗∗∗∗∗∗∗∗∗" - style={{ color: "black" }} - /> - </Stack> - - <Group justify="apart" mt="xl"> - <Button color="dark" type="submit" radius="sm" loading={loading} fullWidth> - Reset Password - </Button> - </Group> - </form> - </Paper> - ); -} - -const ForgotPassword = () => { - const { query } = useRouter(); +export default function Page() { + const query = useSearchParams(); + const typeParam = query?.get("type"); + const errorParam = query?.get("error"); const [loading, setLoading] = React.useState(false); const [email, setEmail] = React.useState(""); const [success, setSuccess] = React.useState(false); - const isPasswordReset = query?.type === "recovery" && !query?.error; + const isPasswordReset = typeParam === "recovery" && !errorParam; const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => { try { @@ -141,6 +84,4 @@ const ForgotPassword = () => { )} </Layout> ); -}; - -export default ForgotPassword; +} diff --git a/src/pages/_error.tsx b/src/app/global-error.tsx similarity index 83% rename from src/pages/_error.tsx rename to src/app/global-error.tsx index cf4487eaa5a..94ff39d33c8 100644 --- a/src/pages/_error.tsx +++ b/src/app/global-error.tsx @@ -1,12 +1,17 @@ +"use client"; + import React from "react"; import Head from "next/head"; -import { useRouter } from "next/router"; import { Button, Stack, Text, Title } from "@mantine/core"; import Layout from "src/layout/Layout"; -const Custom500 = () => { - const router = useRouter(); - +const GlobalError = ({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) => { return ( <Layout> <Head> @@ -21,7 +26,7 @@ const Custom500 = () => { Our servers could not handle your request. Don't worry, our development team was already notified. Try refreshing the page. </Text> - <Button size="lg" color="gray" type="button" onClick={() => router.reload()}> + <Button size="lg" color="gray" type="button" onClick={() => reset()}> Refresh the page </Button> </Stack> @@ -29,4 +34,4 @@ const Custom500 = () => { ); }; -export default Custom500; +export default GlobalError; diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 00000000000..a943eef266a --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { Metadata } from "next"; +import { ColorSchemeScript } from "@mantine/core"; +import "@mantine/core/styles.css"; +import StyledComponentsRegistry from "src/lib/registry"; +import CustomAppInit from "./CustomAppInit"; + +export const metadata: Metadata = { + manifest: "/manifest.json", + metadataBase: new URL("https://jsoncrack.com/"), + icons: { + icon: "/favicon.ico", + }, + description: + "Innovative and open-source visualization application that produces interactive graphs from various data formats, such as JSON, YAML, XML, CSV and more.", + openGraph: { + title: "JSON Crack - Visualize Data as Graphs", + images: [ + { + url: "https://jsoncrack.com/assets/jsoncrack.png", + }, + ], + type: "website", + url: "https://jsoncrack.com", + }, + twitter: { + card: "summary_large_image", + title: "JSON Crack - Visualize Data as Graphs", + description: + "Innovative and open-source visualization application that produces interactive graphs from various data formats, such as JSON, YAML, XML, CSV and more.", + images: [{ url: "https://jsoncrack.com/assets/jsoncrack.png" }], + }, +}; + +export const viewport = { + themeColor: "#36393E", +}; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + <html lang="en"> + <head> + <ColorSchemeScript /> + </head> + <body> + <StyledComponentsRegistry> + <CustomAppInit>{children}</CustomAppInit> + </StyledComponentsRegistry> + </body> + </html> + ); +} diff --git a/src/pages/legal/privacy.tsx b/src/app/legal/privacy/page.tsx similarity index 98% rename from src/pages/legal/privacy.tsx rename to src/app/legal/privacy/page.tsx index d42157951b7..172dd6bbbe0 100644 --- a/src/pages/legal/privacy.tsx +++ b/src/app/legal/privacy/page.tsx @@ -3,7 +3,7 @@ import Head from "next/head"; import { Anchor, Container, Paper, Stack, Text, Title } from "@mantine/core"; import Layout from "src/layout/Layout"; -const Privacy = () => { +export default function Page() { return ( <Layout> <Head> @@ -60,6 +60,4 @@ const Privacy = () => { </Container> </Layout> ); -}; - -export default Privacy; +} diff --git a/src/pages/legal/subscription-refund.tsx b/src/app/legal/subscription-refund/page.tsx similarity index 89% rename from src/pages/legal/subscription-refund.tsx rename to src/app/legal/subscription-refund/page.tsx index 24802677bff..5ba835f9e55 100644 --- a/src/pages/legal/subscription-refund.tsx +++ b/src/app/legal/subscription-refund/page.tsx @@ -1,9 +1,9 @@ import React from "react"; import Head from "next/head"; -import { Anchor, Container, List, Paper, Stack, Text, Title } from "@mantine/core"; +import { Anchor, Container, List, Paper, Stack, Text, Title, ListItem } from "@mantine/core"; import Layout from "src/layout/Layout"; -const SubscriptionRefund = () => { +export default function Page() { return ( <Layout> <Head> @@ -34,11 +34,11 @@ const SubscriptionRefund = () => { <Text c="dark"> To cancel your subscription, follow these steps: <List type="ordered" my="lg"> - <List.Item>Log in to your account.</List.Item> - <List.Item> + <ListItem>Log in to your account.</ListItem> + <ListItem> Click on your account name located at the bottom left of the editor. - </List.Item> - <List.Item>Select the "Unsubscribe" option.</List.Item> + </ListItem> + <ListItem>Select the "Unsubscribe" option.</ListItem> </List> Please note that subscription cancellations made after the initial 3-day period are not eligible for a refund. However, you will still have access to the service until @@ -70,6 +70,4 @@ const SubscriptionRefund = () => { </Container> </Layout> ); -}; - -export default SubscriptionRefund; +} diff --git a/src/pages/legal/terms.tsx b/src/app/legal/terms/page.tsx similarity index 99% rename from src/pages/legal/terms.tsx rename to src/app/legal/terms/page.tsx index 3a5709069a6..bd8058a150e 100644 --- a/src/pages/legal/terms.tsx +++ b/src/app/legal/terms/page.tsx @@ -3,7 +3,7 @@ import Head from "next/head"; import { Anchor, Container, Paper, Stack, Text, Title } from "@mantine/core"; import Layout from "src/layout/Layout"; -const Terms = () => { +export default function Page() { return ( <Layout> <Head> @@ -118,6 +118,4 @@ const Terms = () => { </Container> </Layout> ); -}; - -export default Terms; +} diff --git a/src/pages/404.tsx b/src/app/not-found.tsx similarity index 93% rename from src/pages/404.tsx rename to src/app/not-found.tsx index 6a560641985..5e7269a3a96 100644 --- a/src/pages/404.tsx +++ b/src/app/not-found.tsx @@ -1,10 +1,12 @@ +"use client"; + import React from "react"; import Head from "next/head"; import Link from "next/link"; import { Button, Stack, Text, Title } from "@mantine/core"; import Layout from "src/layout/Layout"; -const NotFound: React.FC = () => { +export default function NotFound() { return ( <Layout> <Head> @@ -27,6 +29,4 @@ const NotFound: React.FC = () => { </Stack> </Layout> ); -}; - -export default NotFound; +} diff --git a/src/pages/index.tsx b/src/app/page.tsx similarity index 57% rename from src/pages/index.tsx rename to src/app/page.tsx index 33edf0195ee..f5465338da6 100644 --- a/src/pages/index.tsx +++ b/src/app/page.tsx @@ -1,3 +1,5 @@ +"use client"; + import React from "react"; import Head from "next/head"; import Link from "next/link"; @@ -82,69 +84,63 @@ const StyledHeroTitle = styled.h1` } `; -const HeroSection = () => ( - <StyledHeroSection id="hero-section"> - <StyledHeroSectionBody> - <Stack w="100%" mx="auto" align="center"> - <StyledHeroTitle> - Understand your{" "} - <StyledHighlightedText> - <Typewriter - words={["JSON", "YAML", "XML", "TOML", "CSV"]} - typeSpeed={100} - deleteSpeed={60} - delaySpeed={2000} - loop - /> - </StyledHighlightedText> - <br /> - better by visualizing - </StyledHeroTitle> - - <StyledHeroText> - Visualize, analyze, and manipulate data with ease, a versatile and powerful tool for data - representation and exploration. - </StyledHeroText> - <Group gap="xl"> - <Button - color="gray.2" - c="indigo" - component={Link} - href="/editor" - fw="bold" - rightSection={<FaChevronRight />} - size="xl" - visibleFrom="md" - > - GO TO EDITOR - </Button> - <Button - color="gray.2" - c="indigo" - component={Link} - href="/editor" - fw="bold" - rightSection={<FaChevronRight />} - size="md" - hiddenFrom="md" - > - GO TO EDITOR - </Button> - </Group> - </Stack> - </StyledHeroSectionBody> - </StyledHeroSection> -); - -export const HomePage = () => { +export default function Page() { return ( <Layout> <Head> <title>JSON Crack | Visualize Instantly Into Graphs - + + + + + Understand your{" "} + + + +
+ better by visualizing +
+ + + Visualize, analyze, and manipulate data with ease, a versatile and powerful tool for + data representation and exploration. + + + + + +
+
+
); -}; - -export default HomePage; +} diff --git a/src/pages/pricing.tsx b/src/app/pricing/page.tsx similarity index 99% rename from src/pages/pricing.tsx rename to src/app/pricing/page.tsx index 0ad10a57cde..a26c2f28e3f 100644 --- a/src/pages/pricing.tsx +++ b/src/app/pricing/page.tsx @@ -1,3 +1,5 @@ +"use client"; + import React from "react"; import Head from "next/head"; import { @@ -27,7 +29,7 @@ const purchaseLinks = { "https://herowand.lemonsqueezy.com/checkout/buy/577928ea-fb09-4076-9307-3e5931b35ad0?media=0&enabled=67805%2C82417", }; -const Pricing = () => { +export default function Page() { const email = useUser(state => state.user?.email); const [isMonthly, setIsMonthly] = React.useState(true); @@ -294,6 +296,4 @@ const Pricing = () => { ); -}; - -export default Pricing; +} diff --git a/src/pages/sign-in.tsx b/src/app/sign-in/AuthenticationForm.tsx similarity index 75% rename from src/pages/sign-in.tsx rename to src/app/sign-in/AuthenticationForm.tsx index bc27dd61b4c..78be01cc74b 100644 --- a/src/pages/sign-in.tsx +++ b/src/app/sign-in/AuthenticationForm.tsx @@ -1,24 +1,18 @@ import React from "react"; -import Head from "next/head"; import Link from "next/link"; -import { useRouter } from "next/router"; import { - TextInput, - PasswordInput, - Paper, - PaperProps, + Anchor, Button, Divider, - Anchor, + Paper, + PaperProps, + PasswordInput, Stack, - Center, + TextInput, } from "@mantine/core"; -import { useSession } from "@supabase/auth-helpers-react"; import { toast } from "react-hot-toast"; import { AiOutlineGithub, AiOutlineGoogle } from "react-icons/ai"; -import Layout from "src/layout/Layout"; import { supabase } from "src/lib/api/supabase"; -import { isIframe } from "src/lib/utils/widget"; import useUser from "src/store/useUser"; export function AuthenticationForm(props: PaperProps) { @@ -116,32 +110,3 @@ export function AuthenticationForm(props: PaperProps) { ); } - -const SignIn = () => { - const { isReady, push, query } = useRouter(); - const session = useSession(); - const isPasswordReset = query?.type === "recovery" && !query?.error; - - React.useEffect(() => { - if (isIframe()) push("/"); - if (isReady && session && !isPasswordReset) push("/editor"); - }, [isReady, session, push, isPasswordReset]); - - return ( - - - Sign In - JSON Crack - - - - -
- - Don't have an account? - -
-
- ); -}; - -export default SignIn; diff --git a/src/app/sign-in/page.tsx b/src/app/sign-in/page.tsx new file mode 100644 index 00000000000..5223c584eff --- /dev/null +++ b/src/app/sign-in/page.tsx @@ -0,0 +1,41 @@ +"use client"; + +import React from "react"; +import Head from "next/head"; +import Link from "next/link"; +import { useRouter, useSearchParams } from "next/navigation"; +import { Paper, Anchor, Center } from "@mantine/core"; +import { useSession } from "@supabase/auth-helpers-react"; +import Layout from "src/layout/Layout"; +import { isIframe } from "src/lib/utils/widget"; +import { AuthenticationForm } from "./AuthenticationForm"; + +export default function Page() { + const { push } = useRouter(); + const queryParams = useSearchParams(); + const typeParam = queryParams?.get("type"); + const errorParam = queryParams?.get("error"); + const session = useSession(); + const isPasswordReset = typeParam === "recovery" && !errorParam; + + React.useEffect(() => { + if (isIframe()) push("/"); + if (session && !isPasswordReset) push("/editor"); + }, [session, push, isPasswordReset]); + + return ( + + + Sign In - JSON Crack + + + + +
+ + Don't have an account? + +
+
+ ); +} diff --git a/src/pages/sign-up.tsx b/src/app/sign-up/page.tsx similarity index 99% rename from src/pages/sign-up.tsx rename to src/app/sign-up/page.tsx index 9c475f977fd..1a5a3c5a81d 100644 --- a/src/pages/sign-up.tsx +++ b/src/app/sign-up/page.tsx @@ -1,3 +1,5 @@ +"use client"; + import React from "react"; import Head from "next/head"; import Link from "next/link"; @@ -18,7 +20,7 @@ import { AiOutlineGithub, AiOutlineGoogle } from "react-icons/ai"; import Layout from "src/layout/Layout"; import { supabase } from "src/lib/api/supabase"; -const SignUp = () => { +export default function Page() { const [loading, setLoading] = React.useState(false); const [done, setDone] = React.useState(false); const [userData, setUserData] = React.useState({ @@ -171,6 +173,4 @@ const SignUp = () => { )} ); -}; - -export default SignUp; +} diff --git a/src/pages/widget.tsx b/src/app/widget/page.tsx similarity index 78% rename from src/pages/widget.tsx rename to src/app/widget/page.tsx index 42e6f6000b1..ca0fcdc9577 100644 --- a/src/pages/widget.tsx +++ b/src/app/widget/page.tsx @@ -1,7 +1,9 @@ +"use client"; + import React from "react"; import dynamic from "next/dynamic"; import Head from "next/head"; -import { useRouter } from "next/router"; +import { useRouter, useSearchParams } from "next/navigation"; import { MantineProvider } from "@mantine/core"; import { ThemeProvider } from "styled-components"; import toast from "react-hot-toast"; @@ -21,8 +23,11 @@ const Graph = dynamic(() => import("src/containers/Views/GraphView").then(c => c ssr: false, }); -const WidgetPage = () => { - const { query, push, isReady } = useRouter(); +export default function Page() { + const { push } = useRouter(); + const queryParams = useSearchParams(); + const jsonParam = queryParams?.get("json"); + const partnerParam = queryParams?.get("partner"); const [theme, setTheme] = React.useState<"dark" | "light">("dark"); const checkEditorSession = useFile(state => state.checkEditorSession); const setContents = useFile(state => state.setContents); @@ -30,12 +35,10 @@ const WidgetPage = () => { const clearGraph = useGraph(state => state.clearGraph); React.useEffect(() => { - if (isReady) { - if (typeof query?.json === "string") checkEditorSession(query.json, true); - else clearGraph(); - window.parent.postMessage(window.frameElement?.getAttribute("id"), "*"); - } - }, [clearGraph, checkEditorSession, isReady, push, query.json, query.partner]); + if (typeof jsonParam === "string") checkEditorSession(jsonParam, true); + else clearGraph(); + window.parent.postMessage(window.frameElement?.getAttribute("id"), "*"); + }, [clearGraph, checkEditorSession, push, jsonParam, partnerParam]); React.useEffect(() => { const handler = (event: EmbedMessage) => { @@ -68,6 +71,4 @@ const WidgetPage = () => {
); -}; - -export default WidgetPage; +} diff --git a/src/components/PromptInput/index.tsx b/src/components/PromptInput/index.tsx index 821835f9023..ecdf58d6d64 100644 --- a/src/components/PromptInput/index.tsx +++ b/src/components/PromptInput/index.tsx @@ -2,12 +2,12 @@ import React from "react"; import { ActionIcon, TextInput, - Text, Loader, Tooltip, HoverCard, Flex, Badge, + Text, } from "@mantine/core"; import { getHotkeyHandler } from "@mantine/hooks"; import styled from "styled-components"; diff --git a/src/containers/Editor/BottomBar.tsx b/src/containers/Editor/BottomBar.tsx index 15dc3cd09e9..85a641f2936 100644 --- a/src/containers/Editor/BottomBar.tsx +++ b/src/containers/Editor/BottomBar.tsx @@ -1,6 +1,6 @@ import React from "react"; import Head from "next/head"; -import { useRouter } from "next/router"; +import { usePathname, useSearchParams, useRouter } from "next/navigation"; import { Flex, Popover, Text } from "@mantine/core"; import styled from "styled-components"; import toast from "react-hot-toast"; @@ -86,7 +86,10 @@ const StyledBottomBarItem = styled.button<{ $bg?: string }>` `; export const BottomBar = () => { - const { query, replace } = useRouter(); + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const queryJSON = searchParams?.get("json") || undefined; const data = useFile(state => state.fileData); const user = useUser(state => state.user); const toggleLiveTransform = useConfig(state => state.toggleLiveTransform); @@ -118,20 +121,20 @@ export const BottomBar = () => { if ( hasChanges && !error && - (typeof query.json === "string" || typeof query.json === "undefined") + (typeof queryJSON === "string" || typeof queryJSON === "undefined") ) { try { setIsUpdating(true); toast.loading("Saving document...", { id: "fileSave" }); const { data, error } = await documentSvc.upsert({ - id: query?.json, + id: queryJSON, contents: getContents(), format: getFormat(), }); if (error) throw error; - if (data) replace({ query: { json: data } }); + if (data) router.push(`${pathname}?json=${data}`); toast.success("Document saved to cloud", { id: "fileSave" }); setHasChanges(false); @@ -146,19 +149,20 @@ export const BottomBar = () => { getContents, getFormat, hasChanges, - query.json, - replace, + queryJSON, + router, setHasChanges, setVisible, user, + pathname, ]); const setPrivate = async () => { try { - if (!query.json) return handleSaveJson(); + if (!queryJSON) return handleSaveJson(); setIsUpdating(true); - const { data: updatedJsonData, error } = await documentSvc.update(query.json as string, { + const { data: updatedJsonData, error } = await documentSvc.update(queryJSON as string, { private: !isPrivate, }); @@ -222,7 +226,7 @@ export const BottomBar = () => { {(data?.owner_email === user?.email || (!data && user)) && ( {hasChanges || !user ? : } - {hasChanges || !user ? (query?.json ? "Unsaved Changes" : "Save to Cloud") : "Saved"} + {hasChanges || !user ? (queryJSON ? "Unsaved Changes" : "Save to Cloud") : "Saved"} )} {data?.owner_email === user?.email && ( diff --git a/src/containers/Modals/ClearModal/index.tsx b/src/containers/Modals/ClearModal/index.tsx index 0dcea300330..02f9238ca42 100644 --- a/src/containers/Modals/ClearModal/index.tsx +++ b/src/containers/Modals/ClearModal/index.tsx @@ -1,20 +1,21 @@ import React from "react"; -import { useRouter } from "next/router"; +import { useSearchParams, redirect } from "next/navigation"; import { Modal, Group, Button, Text, Divider, ModalProps } from "@mantine/core"; import { documentSvc } from "src/services/document.service"; import useJson from "src/store/useJson"; export const ClearModal: React.FC = ({ opened, onClose }) => { const setJson = useJson(state => state.setJson); - const { query, replace } = useRouter(); + const searchParams = useSearchParams(); + const queryJson = searchParams?.get("json"); const handleClear = () => { setJson("{}"); onClose(); - if (typeof query.json === "string") { - documentSvc.delete(query.json); - replace("/editor"); + if (typeof queryJson === "string") { + documentSvc.delete(queryJson); + redirect("/editor"); } }; diff --git a/src/containers/Modals/CloudModal/index.tsx b/src/containers/Modals/CloudModal/index.tsx index 69e10d73a5e..e5dadffa582 100644 --- a/src/containers/Modals/CloudModal/index.tsx +++ b/src/containers/Modals/CloudModal/index.tsx @@ -1,6 +1,6 @@ import React from "react"; import Link from "next/link"; -import { useRouter } from "next/router"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { Modal, Text, @@ -93,11 +93,12 @@ export const CloudModal: React.FC = ({ opened, onClose }) => { const setHasChanges = useFile(state => state.setHasChanges); const getFormat = useFile(state => state.getFormat); const [currentFile, setCurrentFile] = React.useState(null); - const { isReady, query, replace } = useRouter(); - - const { data, isLoading, refetch } = useQuery(["allJson", query], () => documentSvc.getAll(), { - enabled: isReady && opened, - }); + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const { data, isLoading, refetch } = useQuery(["allJson", searchParams], () => + documentSvc.getAll() + ); const isCreateDisabled = React.useMemo(() => { if (!data?.length) return false; @@ -116,7 +117,7 @@ export const CloudModal: React.FC = ({ opened, onClose }) => { toast.success("Document saved to cloud", { id: "fileSave" }); setHasChanges(false); - replace({ query: { json: data } }); + router.push(`${pathname}?json=${data}`); onClose(); } catch (error: any) { toast.error("Failed to save document!", { id: "fileSave" }); diff --git a/src/containers/Modals/ShareModal/index.tsx b/src/containers/Modals/ShareModal/index.tsx index 865b621f892..8393f2a4c37 100644 --- a/src/containers/Modals/ShareModal/index.tsx +++ b/src/containers/Modals/ShareModal/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useRouter } from "next/router"; +import { useSearchParams } from "next/navigation"; import { TextInput, Stack, @@ -15,8 +15,10 @@ import { FiExternalLink } from "react-icons/fi"; import { MdCheck, MdCopyAll } from "react-icons/md"; export const ShareModal: React.FC = ({ opened, onClose }) => { - const { query } = useRouter(); - const shareURL = `https://jsoncrack.com/editor?json=${query.json}`; + // const { query } = useRouter(); + const searchParams = useSearchParams(); + const queryJSON = searchParams?.get("json"); + const shareURL = `https://jsoncrack.com/editor?json=${queryJSON}`; return ( diff --git a/src/containers/Toolbar/OptionsMenu.tsx b/src/containers/Toolbar/OptionsMenu.tsx index 0a828e96e24..d1edaf8da3b 100644 --- a/src/containers/Toolbar/OptionsMenu.tsx +++ b/src/containers/Toolbar/OptionsMenu.tsx @@ -3,9 +3,11 @@ import { Menu, Text, Flex, Badge } from "@mantine/core"; import { BsCheck2 } from "react-icons/bs"; import { MdSettings } from "react-icons/md"; import useConfig from "src/store/useConfig"; +import useUser from "src/store/useUser"; import * as Styles from "./styles"; export const OptionsMenu = () => { + const premium = useUser(state => state.premium); const toggleGestures = useConfig(state => state.toggleGestures); const toggleChildrenCount = useConfig(state => state.toggleChildrenCount); const toggleDarkMode = useConfig(state => state.toggleDarkMode); diff --git a/src/layout/Layout/index.tsx b/src/layout/Layout/index.tsx index 7f186cec171..030aae17121 100644 --- a/src/layout/Layout/index.tsx +++ b/src/layout/Layout/index.tsx @@ -1,3 +1,5 @@ +"use client"; + import React from "react"; import { MantineProvider } from "@mantine/core"; import styled, { ThemeProvider } from "styled-components"; diff --git a/src/lib/registry.tsx b/src/lib/registry.tsx new file mode 100644 index 00000000000..f2fce283b5c --- /dev/null +++ b/src/lib/registry.tsx @@ -0,0 +1,21 @@ +"use client"; + +import React, { useState } from "react"; +import { useServerInsertedHTML } from "next/navigation"; +import { ServerStyleSheet, StyleSheetManager } from "styled-components"; + +export default function StyledComponentsRegistry({ children }: { children: React.ReactNode }) { + const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet()); + + useServerInsertedHTML(() => { + const styles = styledComponentsStyleSheet.getStyleElement(); + styledComponentsStyleSheet.instance.clearTag(); + return <>{styles}; + }); + + if (typeof window !== "undefined") return <>{children}; + + return ( + {children} + ); +} diff --git a/src/lib/utils/json/jsonAdapter.ts b/src/lib/utils/json/jsonAdapter.ts index 2b928ac042f..fc1443aa4d1 100644 --- a/src/lib/utils/json/jsonAdapter.ts +++ b/src/lib/utils/json/jsonAdapter.ts @@ -1,8 +1,3 @@ -import { load, dump } from "js-yaml"; -import { csv2json, json2csv } from "json-2-csv"; -import { parse } from "jsonc-parser"; -import jxon from "jxon"; -import toml from "toml"; import { FileFormat } from "src/enums/file.enum"; const keyExists = (obj: object, key: string) => { @@ -33,6 +28,12 @@ const keyExists = (obj: object, key: string) => { const contentToJson = async (value: string, format = FileFormat.JSON): Promise => { try { + const jxon = await import("jxon"); + const { parse } = await import("jsonc-parser"); + const { load } = await import("js-yaml"); + const { csv2json } = await import("json-2-csv"); + const toml = await import("toml"); + let json: object = {}; if (format === FileFormat.JSON) json = parse(value); @@ -52,6 +53,10 @@ const contentToJson = async (value: string, format = FileFormat.JSON): Promise => { try { + const { dump } = await import("js-yaml"); + const { parse } = await import("jsonc-parser"); + const { json2csv } = await import("json-2-csv"); + let contents = json; if (!json) return json; diff --git a/src/lib/utils/widget.ts b/src/lib/utils/widget.ts index 3e336b63a42..005e47508d2 100644 --- a/src/lib/utils/widget.ts +++ b/src/lib/utils/widget.ts @@ -1,5 +1,6 @@ export function isIframe() { try { + if (typeof window === "undefined") return false; return window.self !== window.top; } catch (e) { return true; diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx deleted file mode 100644 index a1c0ce1ebf3..00000000000 --- a/src/pages/_document.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import Document, { - Html, - Head, - Main, - NextScript, - DocumentContext, - DocumentInitialProps, -} from "next/document"; -import { ServerStyleSheet } from "styled-components"; -import { SeoTags } from "src/components/SeoTags"; - -class MyDocument extends Document { - static async getInitialProps(ctx: DocumentContext): Promise { - const sheet = new ServerStyleSheet(); - const originalRenderPage = ctx.renderPage; - - try { - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: App => props => sheet.collectStyles(), - }); - - const initialProps = await Document.getInitialProps(ctx); - - return { - ...initialProps, - styles: ( - <> - {initialProps.styles} - {sheet.getStyleElement()} - - ), - }; - } finally { - sheet.seal(); - } - } - - render() { - return ( - - - - - - - - -
- - - - ); - } -} - -export default MyDocument; diff --git a/tsconfig.json b/tsconfig.json index f0c1a62667c..f38539d1a5a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,11 @@ "compilerOptions": { "baseUrl": ".", "target": "ES6", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -16,8 +20,21 @@ "jsx": "preserve", "incremental": true, "noImplicitAny": false, - "typeRoots": ["types"] + "typeRoots": [ + "types" + ], + "plugins": [ + { + "name": "next" + } + ] }, - "include": ["src", "next-env.d.ts",], - "exclude": ["node_modules"] + "include": [ + "src", + "next-env.d.ts", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }