diff --git a/.env b/.env index b6a491ecd3f..6a89b747e4d 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -NEXT_PUBLIC_NODE_LIMIT=600 +NEXT_PUBLIC_NODE_LIMIT=800 NEXT_TELEMETRY_DISABLED=1 \ No newline at end of file diff --git a/.env.development b/.env.development index a13af9210c2..7d391f7b11b 100644 --- a/.env.development +++ b/.env.development @@ -1 +1 @@ -NEXT_PUBLIC_NODE_LIMIT=1000 +NEXT_PUBLIC_DISABLE_EXTERNAL_MODE=false \ No newline at end of file diff --git a/README.md b/README.md index 721e4345b12..e1a7f01e260 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,10 @@ docker compose up # Go to http://localhost:8888 ``` +## Configuration + +The supported node limit can be changed by editing the `NEXT_PUBLIC_NODE_LIMIT` value in the `.env` file at the project root. + ## License diff --git a/public/assets/editor.webp b/public/assets/editor.webp index d5f3153c0f7..7f1fd948e2e 100644 Binary files a/public/assets/editor.webp and b/public/assets/editor.webp differ diff --git a/src/data/example.json b/src/data/example.json new file mode 100644 index 00000000000..f9ae49e946f --- /dev/null +++ b/src/data/example.json @@ -0,0 +1,43 @@ +{ + "fruits": [ + { + "name": "Apple", + "color": "#FF0000", + "details": { + "type": "Pome", + "season": "Fall" + }, + "nutrients": { + "calories": 52, + "fiber": "2.4g", + "vitaminC": "4.6mg" + } + }, + { + "name": "Banana", + "color": "#FFFF00", + "details": { + "type": "Berry", + "season": "Year-round" + }, + "nutrients": { + "calories": 89, + "fiber": "2.6g", + "potassium": "358mg" + } + }, + { + "name": "Orange", + "color": "#FFA500", + "details": { + "type": "Citrus", + "season": "Winter" + }, + "nutrients": { + "calories": 47, + "fiber": "2.4g", + "vitaminC": "53.2mg" + } + } + ] +} diff --git a/src/features/editor/BottomBar.tsx b/src/features/editor/BottomBar.tsx index 171720bb473..a97d92af5b8 100644 --- a/src/features/editor/BottomBar.tsx +++ b/src/features/editor/BottomBar.tsx @@ -1,17 +1,13 @@ import React from "react"; -import Link from "next/link"; -import { Flex, Popover, Text } from "@mantine/core"; +import { Flex, Menu, Popover, Text } from "@mantine/core"; import styled from "styled-components"; import { event as gaEvent } from "nextjs-google-analytics"; import { BiSolidDockLeft } from "react-icons/bi"; -import { - VscCheck, - VscError, - VscFeedback, - VscRunAll, - VscSync, - VscSyncIgnored, -} from "react-icons/vsc"; +import { FaCrown } from "react-icons/fa6"; +import { IoMdCheckmark } from "react-icons/io"; +import { MdArrowUpward } from "react-icons/md"; +import { VscCheck, VscError, VscRunAll, VscSync, VscSyncIgnored } from "react-icons/vsc"; +import { formats } from "../../enums/file.enum"; import useConfig from "../../store/useConfig"; import useFile from "../../store/useFile"; import useGraph from "./views/GraphView/stores/useGraph"; @@ -85,9 +81,10 @@ export const BottomBar = () => { const liveTransformEnabled = useConfig(state => state.liveTransformEnabled); const error = useFile(state => state.error); const setContents = useFile(state => state.setContents); - const nodeCount = useGraph(state => state.nodes.length); const toggleFullscreen = useGraph(state => state.toggleFullscreen); const fullscreen = useGraph(state => state.fullscreen); + const setFormat = useFile(state => state.setFormat); + const currentFormat = useFile(state => state.format); const toggleEditor = () => { toggleFullscreen(!fullscreen); @@ -144,17 +141,40 @@ export const BottomBar = () => { - Nodes: {nodeCount} - - - - Feedback - - + + + + + + {currentFormat?.toUpperCase()} + + + + + {formats.map(format => ( + setFormat(format.value)} + rightSection={currentFormat === format.value && } + > + {format.label} + + ))} + + window.open( + "https://todiagram.com/blog/how-to-create-custom-diagrams-in-todiagram?utm_source=jsoncrack&utm_medium=bottom-bar&utm_campaign=custom-diagram", + "_blank" + ) + } + rightSection={} + > + Custom + + + ); diff --git a/src/features/editor/ExternalMode.tsx b/src/features/editor/ExternalMode.tsx index c4620b63da5..ddcbe94be38 100644 --- a/src/features/editor/ExternalMode.tsx +++ b/src/features/editor/ExternalMode.tsx @@ -1,97 +1,154 @@ import React from "react"; -import { Anchor, Button, Group, Modal, Text } from "@mantine/core"; -import styled from "styled-components"; -import { VscCode } from "react-icons/vsc"; -import { VscArrowRight } from "react-icons/vsc"; - -const StyledAlert = styled.div` - position: fixed; - bottom: 36px; - right: 10px; - background: rgba(255, 255, 255, 0.2); - border-radius: 16px; - box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); - backdrop-filter: blur(5px); - -webkit-backdrop-filter: blur(5px); - border: 1px solid rgba(255, 255, 255, 0.3); - font-weight: 500; - overflow: hidden; -`; - -const StyledTitle = styled.div` - display: flex; - align-items: center; - color: ${({ theme }) => theme.TEXT_POSITIVE}; - flex: 1; - font-weight: 700; - - &::after { - background: ${({ theme }) => theme.TEXT_POSITIVE}; - height: 1px; - - content: ""; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - margin-left: 4px; - opacity: 0.6; - } -`; +import { Accordion, Anchor, Code, Flex, FocusTrap, Group, Modal, Text } from "@mantine/core"; const ExternalMode = () => { const [isExternal, setExternal] = React.useState(false); - const [isOpen, setOpen] = React.useState(false); React.useEffect(() => { - if (typeof window !== "undefined") { - if (window.location.pathname.includes("widget")) return setExternal(false); - if (window.location.host !== "jsoncrack.com") return setExternal(true); - return setExternal(false); + if (process.env.NEXT_PUBLIC_DISABLE_EXTERNAL_MODE === "false") { + if (typeof window !== "undefined") { + if (window.location.pathname.includes("widget")) return setExternal(false); + if (window.location.host !== "jsoncrack.com") return setExternal(true); + return setExternal(false); + } } }, []); - const closeModal = () => setOpen(false); - if (!isExternal) return null; return ( - - - - - Dear valued user, - - We would like to inform you that you are presently utilizing the external release of the{" "} - JSON Crack. Your continued support is - crucial in sustaining and improving our services. -
-
- We kindly encourage you to consider upgrading to the premium version, which not only - enhances your experience but also contributes to the ongoing development of JSON Crack. -
-
- - - -
-
+ setExternal(false)} + centered + size="lg" + > + + + + + How can I change the file size limit? + + The main reason for the file size limit is to prevent performance issues, not to push + you to upgrade. You can increase the limit by setting{" "} + NEXT_PUBLIC_NODE_LIMIT in your .env file. +
+
+ If you'd like to work with even larger files and unlock additional features, you + can upgrade to the{" "} + + Pro + {" "} + version. +
+
+ + How can I stop this dialog from appearing? + + You can disable this dialog by setting NEXT_PUBLIC_DISABLE_EXTERNAL_MODE{" "} + to true in your .env.development file. +
+
+ If you want to re-enable it, simply remove or set the value to false. +
+
+ + What are the license terms? + + Read the full license terms on{" "} + + GitHub + + . + + + + How do I report a bug or request a feature? + + You can report bugs or request features by opening an issue on our{" "} + + GitHub Issues page + + . +
+
+ Please provide as much detail as possible to help us address your feedback quickly. +
+
+ + How do I contribute to the project? + + We welcome contributions! Visit our{" "} + + GitHub repository + {" "} + and read the{" "} + + contributing guide + {" "} + to get started. + + + + + What is the difference between JSON Crack and ToDiagram? + + + JSON Crack is a free and open-source tool for visualizing JSON data. ToDiagram is the + professional version that offers advanced features, higher limits, and the ability to + edit data directly from diagrams. You can learn more or upgrade at{" "} + + todiagram.com + + . + + +
+
+ + + GitHub + + + + ToDiagram + + + + Aykut Saraç (@aykutsarach) + + +
); }; diff --git a/src/features/editor/Toolbar/SearchInput.tsx b/src/features/editor/Toolbar/SearchInput.tsx index 054fb8ebc6d..cbda77fc153 100644 --- a/src/features/editor/Toolbar/SearchInput.tsx +++ b/src/features/editor/Toolbar/SearchInput.tsx @@ -1,11 +1,15 @@ import React from "react"; import { Flex, Text, TextInput } from "@mantine/core"; import { getHotkeyHandler } from "@mantine/hooks"; +import { useOs } from "@mantine/hooks"; import { AiOutlineSearch } from "react-icons/ai"; import { useFocusNode } from "../../../hooks/useFocusNode"; export const SearchInput = () => { const [searchValue, setValue, skip, nodeCount, currentNode] = useFocusNode(); + const os = useOs(); + + const coreKey = os === "macos" ? "⌘" : "Ctrl"; return ( { w={180} value={searchValue} onChange={e => setValue(e.currentTarget.value)} - placeholder="Search Node" + placeholder={`Search Node (${coreKey} + F)`} autoComplete="off" autoCorrect="off" onKeyDown={getHotkeyHandler([["Enter", skip]])} diff --git a/src/features/editor/Toolbar/index.tsx b/src/features/editor/Toolbar/index.tsx index 09dfee37e4f..9f617964716 100644 --- a/src/features/editor/Toolbar/index.tsx +++ b/src/features/editor/Toolbar/index.tsx @@ -1,13 +1,13 @@ import React from "react"; import Link from "next/link"; -import { Flex, Group, Select, Button } from "@mantine/core"; +import { Flex, Group, Button } from "@mantine/core"; import styled from "styled-components"; import toast from "react-hot-toast"; import { AiOutlineFullscreen } from "react-icons/ai"; -import { FaFireFlameCurved, FaGithub } from "react-icons/fa6"; -import { type FileFormat, formats } from "../../../enums/file.enum"; +import { FaCrown, FaGithub } from "react-icons/fa6"; +import { LuLink } from "react-icons/lu"; import { JSONCrackLogo } from "../../../layout/JsonCrackLogo"; -import useFile from "../../../store/useFile"; +import { useModal } from "../../../store/useModal"; import { FileMenu } from "./FileMenu"; import { ToolsMenu } from "./ToolsMenu"; import { ViewMenu } from "./ViewMenu"; @@ -43,8 +43,7 @@ function fullscreenBrowser() { } export const Toolbar = () => { - const setFormat = useFile(state => state.setFormat); - const format = useFile(state => state.format); + const setVisible = useModal(state => state.setVisible); return ( @@ -54,37 +53,35 @@ export const Toolbar = () => { -