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
-
-
+
);
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.
-
-
-
- }
- >
- 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 = () => {
-