From deeb39b4c47d06a18f836460cdd11197c1ad5e5f Mon Sep 17 00:00:00 2001 From: Carl Smith <5456533+CarlosNZ@users.noreply.github.com> Date: Tue, 30 Sep 2025 12:40:25 +1300 Subject: [PATCH 1/4] Implement property --- demo/src/App.tsx | 26 ++++++++++++++++++++------ src/CollectionNode.tsx | 4 +++- src/JsonEditor.tsx | 2 ++ src/KeyDisplay.tsx | 18 +++++++++++------- src/ValueNodeWrapper.tsx | 4 +++- src/types.ts | 2 ++ 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 48c460f..21267b0 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -67,6 +67,7 @@ interface AppState { allowCopy: boolean sortKeys: boolean showIndices: boolean + arraysFromOne: boolean showStringQuotes: boolean defaultNewValue: string searchText: string @@ -111,6 +112,7 @@ function App() { allowCopy: true, sortKeys: false, showIndices: true, + arraysFromOne: false, showStringQuotes: true, defaultNewValue: 'New data!', searchText: '', @@ -176,6 +178,7 @@ function App() { collapseTime, showCount, showIndices, + arraysFromOne, sortKeys, showStringQuotes, allowCopy, @@ -508,6 +511,7 @@ function App() { defaultValue={dataDefinition?.defaultValue ?? defaultNewValue} newKeyOptions={dataDefinition?.newKeyOptions} showArrayIndices={showIndices} + arrayCountFromOne={arraysFromOne} showStringQuotes={showStringQuotes} minWidth={'min(500px, 95vw)'} maxWidth="min(670px, 90vw)" @@ -825,6 +829,16 @@ function App() { > Show String quotes + toggleState('sortKeys')} + w="50%" + > + Sort Object keys + + + Show Array indices - - toggleState('sortKeys')} + id="arraysFromOneCheckbox" + isChecked={arraysFromOne} + onChange={() => toggleState('arraysFromOne')} w="50%" > - Sort Object keys + Arrays start from 1 + + = (props) => { indent, sort, showArrayIndices, + arrayCountFromOne, defaultValue, newKeyOptions, translate, @@ -444,7 +445,8 @@ export const CollectionNode: React.FC = (props) => { isEditingKey, pathString, path, - name: name as string, + name, + arrayCountFromOne, handleKeyboard, handleEditKey, handleCancel, diff --git a/src/JsonEditor.tsx b/src/JsonEditor.tsx index 68bd73e..0173824 100644 --- a/src/JsonEditor.tsx +++ b/src/JsonEditor.tsx @@ -63,6 +63,7 @@ const Editor: React.FC = ({ searchDebounceTime = 350, keySort = false, showArrayIndices = true, + arrayCountFromOne = false, showStringQuotes = true, showIconTooltips = false, defaultValue = null, @@ -368,6 +369,7 @@ const Editor: React.FC = ({ keySort, sort, showArrayIndices, + arrayCountFromOne, showStringQuotes, showIconTooltips, indent, diff --git a/src/KeyDisplay.tsx b/src/KeyDisplay.tsx index 72547f3..f28029b 100644 --- a/src/KeyDisplay.tsx +++ b/src/KeyDisplay.tsx @@ -11,7 +11,8 @@ interface KeyDisplayProps { isEditingKey: boolean pathString: string path: CollectionKey[] - name: string + name: string | number + arrayCountFromOne: boolean handleKeyboard: ( e: React.KeyboardEvent, eventMap: Partial void>> @@ -31,6 +32,7 @@ export const KeyDisplay: React.FC = ({ pathString, path, name, + arrayCountFromOne, handleKeyboard, handleEditKey, handleCancel, @@ -42,20 +44,22 @@ export const KeyDisplay: React.FC = ({ }) => { const { setCurrentlyEditingElement } = useTreeState() + const displayKey = typeof name === 'number' ? String(name + (arrayCountFromOne ? 1 : 0)) : name + if (!isEditingKey) return ( 10 ? 1 : 0, + minWidth: `${Math.min(displayKey.length + 1, 5)}ch`, + flexShrink: displayKey.length > 10 ? 1 : 0, }} onDoubleClick={() => canEditKey && setCurrentlyEditingElement(path, 'key')} onClick={handleClick} > - {emptyStringKey ? {emptyStringKey} : name} - {name !== '' || emptyStringKey ? : : null} + {emptyStringKey ? {emptyStringKey} : displayKey} + {displayKey !== '' || emptyStringKey ? : : null} ) @@ -64,7 +68,7 @@ export const KeyDisplay: React.FC = ({ className="jer-input-text jer-key-edit" type="text" name={pathString} - defaultValue={name} + defaultValue={displayKey} autoFocus onFocus={(e) => e.target.select()} onKeyDown={(e: React.KeyboardEvent) => @@ -86,7 +90,7 @@ export const KeyDisplay: React.FC = ({ }, }) } - style={{ width: `${String(name).length / 1.5 + 0.5}em` }} + style={{ width: `${displayKey.length / 1.5 + 0.5}em` }} /> ) } diff --git a/src/ValueNodeWrapper.tsx b/src/ValueNodeWrapper.tsx index fc74c6d..99925b2 100644 --- a/src/ValueNodeWrapper.tsx +++ b/src/ValueNodeWrapper.tsx @@ -40,6 +40,7 @@ export const ValueNodeWrapper: React.FC = (props) => { showLabel, stringTruncate, showStringQuotes, + arrayCountFromOne, indent, translate, customNodeDefinitions, @@ -305,7 +306,8 @@ export const ValueNodeWrapper: React.FC = (props) => { isEditingKey, pathString, path, - name: name as string, + name, + arrayCountFromOne, handleKeyboard, handleEditKey, handleCancel, diff --git a/src/types.ts b/src/types.ts index 5ed8fdf..903045b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -37,6 +37,7 @@ export interface JsonEditorProps { searchDebounceTime?: number keySort?: boolean | CompareFunction showArrayIndices?: boolean + arrayCountFromOne?: boolean showStringQuotes?: boolean showIconTooltips?: boolean defaultValue?: string | number | boolean | null | object | DefaultValueFunction @@ -272,6 +273,7 @@ interface BaseNodeProps { restrictTypeSelection: boolean | TypeOptions | TypeFilterFunction stringTruncate: number indent: number + arrayCountFromOne: boolean sort: SortFunction translate: TranslateFunction customNodeDefinitions: CustomNodeDefinition[] From c0dd586dbe04ebf9b831b6280d41bc12016cd31b Mon Sep 17 00:00:00 2001 From: Carl Smith <5456533+CarlosNZ@users.noreply.github.com> Date: Tue, 30 Sep 2025 12:55:03 +1300 Subject: [PATCH 2/4] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7cc38d8..5b1e091 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,7 @@ This is a reference list of *all* possible props, divided into related sections. | `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. | | `showArrayIndices` | `boolean` | `true` | Whether or not to display the index (as a property key) for array elements. | +| `arrayCountFromOne` | `boolean` | `false` | When showing array indices, first item will be labelled "1" (as opposed to "0"). | | `showStringQuotes` | `boolean` | `true` | Whether or not to display string values in "quotes". | | `showCollectionCount` | `boolean\|"when-closed"` | `true` | Whether or not to display the number of items in each collection (object or array). | | `stringTruncate` | `number` | `250` | String values longer than this many characters will be displayed truncated (with `...`). The full string will always be visible when editing. | @@ -1241,6 +1242,7 @@ This component is heavily inspired by [react-json-view](https://github.com/mac-s ## Changelog +- **1.28.3**: Option to display array indexes starting at "1" ([#62](https://github.com/CarlosNZ/json-edit-react/issues/62)) - **1.28.2**: When switching data type, only keep editing if new type is primitive ([#216](https://github.com/CarlosNZ/json-edit-react/issues/216)) - **1.28.1**: Fix left padding of root node when value is primitive ([#214](https://github.com/CarlosNZ/json-edit-react/issues/214)) - **1.28.0**: From 1fdf6f32367b04120c5ce77a826a4eb50aa338b5 Mon Sep 17 00:00:00 2001 From: Carl Smith <5456533+CarlosNZ@users.noreply.github.com> Date: Wed, 1 Oct 2025 23:35:32 +1300 Subject: [PATCH 3/4] Rename variable --- README.md | 2 +- demo/src/App.tsx | 4 ++-- src/CollectionNode.tsx | 4 ++-- src/JsonEditor.tsx | 4 ++-- src/KeyDisplay.tsx | 6 +++--- src/ValueNodeWrapper.tsx | 4 ++-- src/types.ts | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 5b1e091..2001ecb 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ This is a reference list of *all* possible props, divided into related sections. | `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. | | `showArrayIndices` | `boolean` | `true` | Whether or not to display the index (as a property key) for array elements. | -| `arrayCountFromOne` | `boolean` | `false` | When showing array indices, first item will be labelled "1" (as opposed to "0"). | +| `arrayIndexFromOne` | `boolean` | `false` | When showing array indices, first item will be labelled "1" (as opposed to "0"). | | `showStringQuotes` | `boolean` | `true` | Whether or not to display string values in "quotes". | | `showCollectionCount` | `boolean\|"when-closed"` | `true` | Whether or not to display the number of items in each collection (object or array). | | `stringTruncate` | `number` | `250` | String values longer than this many characters will be displayed truncated (with `...`). The full string will always be visible when editing. | diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 21267b0..a7cd78b 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -511,7 +511,7 @@ function App() { defaultValue={dataDefinition?.defaultValue ?? defaultNewValue} newKeyOptions={dataDefinition?.newKeyOptions} showArrayIndices={showIndices} - arrayCountFromOne={arraysFromOne} + arrayIndexFromOne={arraysFromOne} showStringQuotes={showStringQuotes} minWidth={'min(500px, 95vw)'} maxWidth="min(670px, 90vw)" @@ -853,7 +853,7 @@ function App() { onChange={() => toggleState('arraysFromOne')} w="50%" > - Arrays start from 1 + Arrays index from 1 diff --git a/src/CollectionNode.tsx b/src/CollectionNode.tsx index bb6a8f9..098fc7e 100644 --- a/src/CollectionNode.tsx +++ b/src/CollectionNode.tsx @@ -54,7 +54,7 @@ export const CollectionNode: React.FC = (props) => { indent, sort, showArrayIndices, - arrayCountFromOne, + arrayIndexFromOne, defaultValue, newKeyOptions, translate, @@ -446,7 +446,7 @@ export const CollectionNode: React.FC = (props) => { pathString, path, name, - arrayCountFromOne, + arrayIndexFromOne, handleKeyboard, handleEditKey, handleCancel, diff --git a/src/JsonEditor.tsx b/src/JsonEditor.tsx index 0173824..7b4af14 100644 --- a/src/JsonEditor.tsx +++ b/src/JsonEditor.tsx @@ -63,7 +63,7 @@ const Editor: React.FC = ({ searchDebounceTime = 350, keySort = false, showArrayIndices = true, - arrayCountFromOne = false, + arrayIndexFromOne = false, showStringQuotes = true, showIconTooltips = false, defaultValue = null, @@ -369,7 +369,7 @@ const Editor: React.FC = ({ keySort, sort, showArrayIndices, - arrayCountFromOne, + arrayIndexFromOne, showStringQuotes, showIconTooltips, indent, diff --git a/src/KeyDisplay.tsx b/src/KeyDisplay.tsx index f28029b..fd36f92 100644 --- a/src/KeyDisplay.tsx +++ b/src/KeyDisplay.tsx @@ -12,7 +12,7 @@ interface KeyDisplayProps { pathString: string path: CollectionKey[] name: string | number - arrayCountFromOne: boolean + arrayIndexFromOne: boolean handleKeyboard: ( e: React.KeyboardEvent, eventMap: Partial void>> @@ -32,7 +32,7 @@ export const KeyDisplay: React.FC = ({ pathString, path, name, - arrayCountFromOne, + arrayIndexFromOne, handleKeyboard, handleEditKey, handleCancel, @@ -44,7 +44,7 @@ export const KeyDisplay: React.FC = ({ }) => { const { setCurrentlyEditingElement } = useTreeState() - const displayKey = typeof name === 'number' ? String(name + (arrayCountFromOne ? 1 : 0)) : name + const displayKey = typeof name === 'number' ? String(name + (arrayIndexFromOne ? 1 : 0)) : name if (!isEditingKey) return ( diff --git a/src/ValueNodeWrapper.tsx b/src/ValueNodeWrapper.tsx index 99925b2..e4a9d27 100644 --- a/src/ValueNodeWrapper.tsx +++ b/src/ValueNodeWrapper.tsx @@ -40,7 +40,7 @@ export const ValueNodeWrapper: React.FC = (props) => { showLabel, stringTruncate, showStringQuotes, - arrayCountFromOne, + arrayIndexFromOne, indent, translate, customNodeDefinitions, @@ -307,7 +307,7 @@ export const ValueNodeWrapper: React.FC = (props) => { pathString, path, name, - arrayCountFromOne, + arrayIndexFromOne, handleKeyboard, handleEditKey, handleCancel, diff --git a/src/types.ts b/src/types.ts index 903045b..5196307 100644 --- a/src/types.ts +++ b/src/types.ts @@ -37,7 +37,7 @@ export interface JsonEditorProps { searchDebounceTime?: number keySort?: boolean | CompareFunction showArrayIndices?: boolean - arrayCountFromOne?: boolean + arrayIndexFromOne?: boolean showStringQuotes?: boolean showIconTooltips?: boolean defaultValue?: string | number | boolean | null | object | DefaultValueFunction @@ -273,7 +273,7 @@ interface BaseNodeProps { restrictTypeSelection: boolean | TypeOptions | TypeFilterFunction stringTruncate: number indent: number - arrayCountFromOne: boolean + arrayIndexFromOne: boolean sort: SortFunction translate: TranslateFunction customNodeDefinitions: CustomNodeDefinition[] From e075060cdf6a0c8fdb0bbc0e49712a8b88c90371 Mon Sep 17 00:00:00 2001 From: Carl Smith <5456533+CarlosNZ@users.noreply.github.com> Date: Wed, 1 Oct 2025 23:40:39 +1300 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2001ecb..294fa8a 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ This is a reference list of *all* possible props, divided into related sections. | `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. | | `showArrayIndices` | `boolean` | `true` | Whether or not to display the index (as a property key) for array elements. | -| `arrayIndexFromOne` | `boolean` | `false` | When showing array indices, first item will be labelled "1" (as opposed to "0"). | +| `arrayIndexFromOne` | `boolean` | `false` | When displaying array indices, first item will be labelled "1" (as opposed to "0"). | | `showStringQuotes` | `boolean` | `true` | Whether or not to display string values in "quotes". | | `showCollectionCount` | `boolean\|"when-closed"` | `true` | Whether or not to display the number of items in each collection (object or array). | | `stringTruncate` | `number` | `250` | String values longer than this many characters will be displayed truncated (with `...`). The full string will always be visible when editing. |