# json-edit-react screenshot A highly-configurable [React](https://github.com/facebook/react) component for editing or viewing JSON/object data ## ๐Ÿš€๏ธ [Explore the Demo](https://carlosnz.github.io/json-edit-react/) ![NPM Version](https://img.shields.io/npm/v/json-edit-react) ![GitHub License](https://img.shields.io/github/license/carlosnz/json-edit-react) ![NPM Downloads](https://img.shields.io/npm/dm/json-edit-react) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/CarlosNZ/json-edit-react) [![Discuss on GitHub](https://img.shields.io/badge/Discussions-Join%20the%20conversation-blue?logo=github)](https://github.com/CarlosNZ/json-edit-react/discussions) [![Sponsor](https://img.shields.io/badge/Sponsor-โ™ฅ-pink.svg)](https://github.com/sponsors/CarlosNZ) ### Features include: - โœ… **Easy inline editing** of individual values or whole blocks of JSON text - ๐Ÿ”’ **Granular control** โ€“ restrict edits, deletions, or additions per element - ๐Ÿ“ **[JSON Schema](https://json-schema.org/) validation** (using 3rd-party validation library) - ๐ŸŽจ **Customisable UI** โ€” built-in or custom [themes](#appearance--theming), CSS overrides or targeted classes - ๐Ÿ“ฆ **Self-contained** โ€” plain HTML/CSS, no external UI library dependencies, and *zero runtime dependencies* - ๐Ÿ” **Search & filter** โ€” find data by key, value or custom function - ๐Ÿšง **[Custom components](#custom-nodes--components)** โ€” replace keys and/or values with specialised components (e.g. date picker, links, images, `undefined`, `BigInt`, `Symbol`) - ๐ŸŒ **[Localisation](#localisation)** โ€” easily translate UI labels and messages - ๐Ÿ”„ **[Drag-n-drop](#drag-and-drop-reordering)** re-ordering within objects/arrays - ๐ŸŽน **[Keyboard customisation](#keyboard-control)** โ€” define your own key bindings - ๐ŸŽฎ **[External control](#programmatic-control)** via callbacks and imperative methods ๐Ÿ’ก Try the **[Live Demo](https://carlosnz.github.io/json-edit-react/)** to see these features in action! screenshot > [!IMPORTANT] > This documentation is for V2 of **json-edit-react**. Looking for V1? See the [V1 docs](https://github.com/CarlosNZ/json-edit-react/tree/v1.x#readme) and [V1 demo](https://carlosnz.github.io/json-edit-react-v1/). > > If you're upgrading from V1, be sure to read the [migration guide](https://github.com/CarlosNZ/json-edit-react/blob/main/migration-guide.md). > > ๐ŸŽค๏ธ Got feedback? [Open an issue](https://github.com/CarlosNZ/json-edit-react/issues), or join the conversation in [Discussions](https://github.com/CarlosNZ/json-edit-react/discussions/categories/announcements). ## Optional Companion Packages - **THEMES**: [@json-edit-react/themes](https://www.npmjs.com/package/@json-edit-react/themes) โ€” curated, ready-made [themes](#using-a-prebuilt-theme-json-edit-reactthemes) - **COMPONENTS**: [@json-edit-react/components](https://www.npmjs.com/package/@json-edit-react/components) - custom node components (links, date picker, etc.) - **UTILITIES**: [@json-edit-react/utils](https://www.npmjs.com/package/@json-edit-react/utils) โ€”ย a collection of helpers and tools for extending and streamlining your **json-edit-react** experience ---- ## Contents - [Using the editor (for end users)](#using-the-editor-for-end-users) - [Installation](#installation) - [Implementation](#implementation) - [Props Reference](#props-reference) - [Managing state](#managing-state) - [Filter Functions](#filter-functions) - [Controlling editing](#controlling-editing) - [Reacting to changes](#reacting-to-changes) - [Appearance \& theming](#appearance--theming) - [Initial expansion โ€” `collapse`](#initial-expansion--collapse) - [Search \& filtering](#search--filtering) - [Localisation](#localisation) - [Keyboard control](#keyboard-control) - [Custom Nodes \& Components](#custom-nodes--components) - [Overriding and extending the UI](#overriding-and-extending-the-ui) - [Programmatic control](#programmatic-control) - [Performance considerations](#performance-considerations) - [Undo functionality](#undo-functionality) - [Exported helpers \& types](#exported-helpers--types) - [Issues \& support](#issues--support) - [Inspiration](#inspiration) - [Changelog](#changelog) ## Using the editor (for end users) It's pretty self explanatory (click the "edit" icon to edit, etc.), but there are a few not-so-obvious ways of interacting with the editor: - **Double-click** a value (or a key) to edit it - When editing a string, use Cmd/Ctrl-Enter or Shift-Enter to add a new line (Enter submits the value) - It's the opposite when editing a full object/array node (which you do by **clicking "edit"** on an object or array value) โ€” Enter for new line, and Cmd/Ctrl/Shift-Enter for submit - Escape to **cancel** editing - Use Tab/Shift-Tab to quickly move from one value to another when editing - When clicking the "**clipboard**" icon, holding down Cmd/Ctrl will copy the *path* to the selected node rather than its value - When opening/closing a node, hold down Alt/Option to open/close *all* child nodes at once - For Number inputs, the โ†‘ / โ†“ arrow keys will increment/decrement the value - For Boolean inputs, the Space bar will toggle the value - Easily navigate to the next or previous node for editing using the Tab/Shift-Tab keys. - **Drag and drop** items to change the structure or modify display order - When editing is not permitted, double-clicking a string value will expand the text to the full value if it is truncated due to length (there is also a clickable "..." for long strings) - **JSON text input** can accept "looser" input, if an additional JSON parsing method is provided (e.g. [JSON5](https://json5.org/)). See `jsonParse` prop. [Have a play with the Demo app](https://carlosnz.github.io/json-edit-react/) to get a feel for it! ## Installation ```sh # Depending on your package manager: npm i json-edit-react # OR yarn add json-edit-react # OR pnpm add json-edit-react ``` ## Implementation ```jsx import { JsonEditor } from 'json-edit-react' // In your React component: return ( ); // For a read-only viewer, use the `JsonViewer` component instead: import { JsonViewer } from 'json-edit-react' return ``` ## Props Reference `data` and `setData` are the only *required* props. For a read-only component, use [`JsonViewer`](#read-only-display--jsonviewer) instead โ€” its only required prop is `data`. This is a reference list of *all* possible props, divided into related sections. Most of them provide a link to a section below in which the concepts are explored in more detail.
### Data Management | Prop | Type | Default | Description | | --------------------- | ----------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `object\|array` | - | The data to be displayed / edited | | `setData` | `object\|array => void` | - | Method to update your `data` object. **Required.** See [Managing state](#managing-state) below for additional notes. | | `onUpdate` | `UpdateFunction` | - | A function to run whenever a value is changed in the editor โ€” edit, add, delete, rename *or* move. See [Update functions](#onupdate--accept-reject-transform). | | `onChange` | `OnChangeFunction` | - | A function to modify/constrain user input as they type โ€” see [OnChange functions](#onchange--validating-each-keystroke). | | `onError` | `OnErrorFunction` | - | A function to run whenever the component reports an error โ€” see [OnErrorFunction](#onerror). | | `showClipboardButton` | `boolean` | `true` | Show or hide the "Copy to clipboard" button in the UI. | | `onCopy` | `OnCopyFunction` | - | A function to run whenever an item is **copied** to the clipboard โ€” see [Copy Function](#oncopy). |
### Restricting Editing | Prop | Type | Default | Description | | -------------------- | ------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `allowEdit` | `boolean\|FilterFunction` | `true` | If `false`, no editing at all is permitted. A callback function can be provided (return `true` to permit a given node) โ€” see [Advanced Editing Control](#filter-functions) | | `allowDelete` | `boolean\|FilterFunction` | `true` | As with `allowEdit` but for deletion | | `allowAdd` | `boolean\|FilterFunction` | `true` | As with `allowEdit` but for adding new properties | | `allowTypeSelection` | `boolean\|TypeOptions\|TypeFilterFunction` | `true` | Controls which data types the user can select, including [Custom Node](#custom-nodes--components) types, and **Enums** โ€” see [Data Type Restrictions](#restricting-data-types--allowtypeselection) | | `newKeyOptions` | `string[] \| NewKeyOptionsFunction` | - | New keys can be restricted to certain values โ€” see [New Key Restrictions & Default Values](#new-key-restrictions--default-values) | | `defaultValue` | `any\|DefaultValueFunction` | `null` | Value that new properties are initialised with โ€” see [New Key Restrictions & Default Values](#new-key-restrictions--default-values) | | `allowDrag` | `boolean\|FilterFunction` | `false` | Set to `true` to enable drag and drop functionality โ€” see [Drag-n-drop](#drag-and-drop-reordering) |
### Look and Feel / UI | Prop | Type | Default | Description | | ----------------------- | --------------------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `theme` | `ThemeInput` | `defaultTheme` | Either one of the built-in themes (imported separately), or an object specifying some or all theme properties โ€” see [Themes](#appearance--theming). | | `showIconTooltips` | `boolean` | false | Display tooltips on the icon controls and the other labelled controls when hovering. | | `indent` | `number` | `3` | Specify the amount of indentation for each level of nesting in the displayed data. | | `collapse` | `boolean\|number\|FilterFunction` | `3` | Defines which depth level of the data tree will be displayed "expanded" in the UI on initial load โ€” see [Collapse](#initial-expansion--collapse). | | `collapseAnimationTime` | `number` | `300` | Time (in ms) for the transition animation when collapsing collection nodes. | | `collapseClickZones` | `Array<"left" \| "header" \| "property">` | `["left", "header"]` | Aside from the `โŒ„` icon, you can specify other regions of the UI to be clickable for collapsing/opening a collection. | | `rootName` | `string` | `"data"` | A name to display in the editor as the root of the data object. | | `showArrayIndexes` | `boolean` | `true` | Whether or not to display the index (as a property key) for array elements. | | `arrayIndexStart` | `0 \| 1` | `0` | The number the *first* array element's index label starts from. | | `showStringQuotes` | `boolean` | `true` | Whether or not to display string values in "quotes". | | `showCollectionCount` | `boolean\|"when-collapsed"\|"when-collapsed-or-filtered"` | `"when-collapsed-or-filtered"` | Whether or not to display the number of items in each collection (object or array). | | `stringTruncateLength` | `number` | `250` | String values longer than this many characters will be displayed truncated (with `...`). The full string will always be visible when editing. | | `sortKeys` | `boolean\|CompareFunction` | `false` | If `true`, object keys will be ordered (using default JS `.sort()`). A [compare function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) can also be provided to define sorting behaviour, except the input type should be a tuple of the key and the value of a node i.e. `(a: [string \| number, ValueData], b: [string \| number, ValueData]) => number` | | `minWidth` | `number\|string` (CSS value) | `250` | Minimum width for the editor container. | | `maxWidth` | `number\|string` (CSS value) | `600` | Maximum width for the editor container. | | `baseFontSize` | `number\|string` (CSS value) | `16px` | The "base" font size from which all other sizings are derived (in `em`s). By changing this you will scale the entire component. | | `insertAtTop` | `boolean\|"object"\|"array"` | `false` | If `true`, inserts new values at the *top* rather than bottom. Can set the behaviour just for arrays or objects by setting to `"object"` or `"array"` respectively. | | `errorDisplayTime` | `number` | `2500` | Time (in ms) to display the error message in the UI. | | | `showErrorMessages` | `boolean ` | `true` | Whether or not the component should display its own error messages (you'd probably only want to disable this if you provided your own [`onError` function](#onerror)) |
### Search and Filtering | Prop | Type | Default | Description | | -------------------- | --------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------ | | `searchText` | `string` | `undefined` | Data visibility will be filtered by matching against value, using the method defined below in `searchFilter` | | `searchFilter` | `"key"\|"value"\|"all"\|SearchFilterFunction` | `undefined` | Define how `searchText` should be matched to filter the visible items โ€” see [Search/Filtering](#search--filtering) | | `searchDebounceTime` | `number` | `350` | Debounce time when `searchText` changes |
### Custom components & overrides (incl. Localisation) | Prop | Type | Default | Description | | ----------------------- | --------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `customNodeDefinitions` | `CustomNodeDefinition[]` | | You can provide custom React components to override specific nodes in the data tree, according to a condition function โ€” see [Custom nodes](#custom-nodes--components) or browse the [@json-edit-react/components](https://www.npmjs.com/package/@json-edit-react/components) | | `customButtons` | `CustomButtonDefinition[]` | `[]` | You can add your own buttons to the Edit Buttons panel if you'd like to be able to perform a custom operation on the data โ€” see [Custom Buttons](#custom-buttons) | | `translations` | `LocalisedStrings` | `{ }` | UI strings (such as error messages) can be translated by passing an object containing localised string values (there are only a few) โ€” see [Localisation](#localisation) | | `customText` | `CustomTextDefinitions` | | In addition to [localising the component](#localisation) text strings, you can also *dynamically* alter them, depending on the data โ€” see [Custom Text](#dynamic-text--customtext) | | `TextEditor` | `ReactComponent`
  `` | | Pass a component to offer a custom text/code editor when editing full JSON object as text. [See details](#replacing-the-textcode-editor--texteditor-codeeditor) | | `Select` | `ReactComponent`
  `` | `` | Pass a component to replace the built-in native `` element Similarly, the drop-downs used in component are stock HTML [`select`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/select) elements. Drop-downs can appear in 3 places: - [type selection](#restricting-data-types--allowtypeselection) - [enum options](#enums) - [new key options](#new-key-restrictions--default-values) You can provide any component you like that conforms to the following API: ```ts export interface SelectProps { options: string[] /** Controlled value. Mutually exclusive with `defaultValue`. */ value?: string /** Initial value when used uncontrolled โ€” typically `''` so the * placeholder shows first. Mutually exclusive with `value`. */ defaultValue?: string /** Fired with the selected option's value. */ onChange: (value: string) => void /** Forwarded to the underlying input. Lets the call site keep * ownership of keyboard semantics via `handleKeyboard(...)`. */ onKeyDown?: (e: React.KeyboardEvent) => void /** Grab focus on mount. */ autoFocus?: boolean /** Disabled first option shown when nothing is selected. */ placeholder?: string /** Form name / id hint. */ name?: string /** Class applied to the inner control. */ className?: string } ``` If your drop-down component of choice has a different interface, you can create a thin wrapper component around it to translate the props accordingly. I have provided an example of this using [**react-select**](https://react-select.com/home) in the `@json-edit-react/components` repo, called [ReactSelect](https://github.com/CarlosNZ/json-edit-react/blob/main/packages/components/README.md#editor-slot-widgets), so you can copy that pattern or just use that one directly (this is the component used in the [example](https://carlosnz.github.io/json-edit-react/examples/swap-the-built-ins) above). #### But what about the text input element? I haven't made the main string input component swappable, for two main reasons: 1. It's actually a special `textarea` that grows in width and height as the contents changes, not just a single-line ``. I'm using a [bit of a hack](https://github.com/CarlosNZ/json-edit-react/blob/main/src/AutogrowTextArea.tsx) to achieve this, so it wouldn't be straightforward to just swap it out with a single component that could directly replace it. 2. Unlike `