diff --git a/README.md b/README.md
index ebcabad4..272df668 100644
--- a/README.md
+++ b/README.md
@@ -232,7 +232,7 @@ Pass the JSON contents to be rendered in the JSONEditor. `Content` is an object
selection: JSONEditorSelection | undefined
```
-The current selected contents. You can use two-way binding using `bind:selection`. The `tree` mode supports `MultiSelection`, `KeySelection`, `ValueSelection`, `InsideSelection`, or `AfterSelection`. The `table` mode supports `ValueSelection`, and `text` mode supports `TextSelection.`.
+The current selected contents. You can use two-way binding using `bind:selection`. The `tree` mode supports `MultiSelection`, `KeySelection`, `EditKeySelection`, `ValueSelection`, `EditValueSelection`, `InsideSelection`, or `AfterSelection`. The `table` mode supports `ValueSelection`, and `text` mode supports `TextSelection.`.
#### mode
@@ -586,7 +586,7 @@ A menu item `ContextMenuItem` can be one of the following types:
onSelect: (selection: JSONEditorSelection | undefined) => void
```
-Callback invoked when the selection is changed. When the selection is removed, the callback is invoked with `undefined` as argument. In `text` mode, a `TextSelection` will be fired. In `tree` and `table` mode, a `JSONSelection` will be fired (which can be `MultiSelection`, `KeySelection`, `ValueSelection`, `InsideSelection`, or `AfterSelection`). Use typeguards like `isTextSelection` and `isValueSelection` to check what type the selection has.
+Callback invoked when the selection is changed. When the selection is removed, the callback is invoked with `undefined` as argument. In `text` mode, a `TextSelection` will be fired. In `tree` and `table` mode, a `JSONSelection` will be fired (which can be `MultiSelection`, `KeySelection`, `EditKeySelection`, `ValueSelection`, `EditValueSelection`, `InsideSelection`, or `AfterSelection`). Use typeguards like `isTextSelection` and `isValueSelection` to check what type the selection has.
#### queryLanguages
@@ -856,7 +856,9 @@ The library exports a set of utility functions. The exact definitions of those f
- `isMultiSelection`,
- `isEditingSelection`
- `createValueSelection`
+ - `createEditValueSelection`
- `createKeySelection`
+ - `createEditKeySelection`
- `createInsideSelection`,
- `createAfterSelection`
- `createMultiSelection`
diff --git a/src/lib/components/controls/EditableDiv.svelte b/src/lib/components/controls/EditableDiv.svelte
index 88ac4ca1..791a616f 100644
--- a/src/lib/components/controls/EditableDiv.svelte
+++ b/src/lib/components/controls/EditableDiv.svelte
@@ -13,6 +13,7 @@
const debug = createDebug('jsoneditor:EditableDiv')
export let value: string
+ export let initialValue: string | undefined
export let shortText = false
export let label: string
export let onChange: (newValue: string, updateSelection: UpdateSelectionAfterChange) => void
@@ -27,17 +28,12 @@
let closed = false
onMount(() => {
- debug('onMount', { value })
- setDomValue(value)
+ debug('onMount', { value, initialValue })
+ setDomValue(initialValue !== undefined ? initialValue : value)
// focus
if (domValue) {
setCursorToEnd(domValue)
-
- // The refresh method can be used to update the classnames for example
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- domValue.refresh = handleValueInput
}
})
diff --git a/src/lib/components/modes/tablemode/TableMode.svelte b/src/lib/components/modes/tablemode/TableMode.svelte
index ae7aae26..3037e6d4 100644
--- a/src/lib/components/modes/tablemode/TableMode.svelte
+++ b/src/lib/components/modes/tablemode/TableMode.svelte
@@ -673,9 +673,7 @@
const index = parseInt(path[0], 10)
const nextPath = [String(index + 1), ...path.slice(1)]
- return existsIn(json, nextPath)
- ? createValueSelection(nextPath, false)
- : createValueSelection(path, false)
+ return existsIn(json, nextPath) ? createValueSelection(nextPath) : createValueSelection(path)
}
export function focus() {
@@ -736,7 +734,7 @@
return
}
- updateSelection(createValueSelection(path, false))
+ updateSelection(createValueSelection(path))
event.preventDefault()
}
@@ -752,7 +750,7 @@
// Select the first row, first column
const path = ['0', ...columns[0]]
- return createValueSelection(path, false)
+ return createValueSelection(path)
} else {
return undefined
}
@@ -1047,7 +1045,7 @@
if (isObjectOrArray(value)) {
openJSONEditorModal(path)
} else {
- updateSelection(createValueSelection(path, true))
+ updateSelection(createValueSelection(path))
}
}
@@ -1173,7 +1171,6 @@
await onInsertCharacter({
char,
selectInside: false,
- refJsonEditor,
json,
selection: selection,
readOnly,
@@ -1453,7 +1450,7 @@
function handleSelectValidationError(error: ValidationError) {
debug('select validation error', error)
- updateSelection(createValueSelection(error.path, false))
+ updateSelection(createValueSelection(error.path))
scrollTo(error.path)
}
diff --git a/src/lib/components/modes/treemode/JSONKey.svelte b/src/lib/components/modes/treemode/JSONKey.svelte
index 2996be94..db393d43 100644
--- a/src/lib/components/modes/treemode/JSONKey.svelte
+++ b/src/lib/components/modes/treemode/JSONKey.svelte
@@ -3,6 +3,7 @@
@@ -70,6 +71,7 @@
{#if !context.readOnly && isEditingKey}
({
// expand the newly replaced array and select it
state: expandSmart(patchedJson, patchedState, rootPath),
- selection: createValueSelection(rootPath, false)
+ selection: createValueSelection(rootPath)
}))
},
onClose: () => {
@@ -1108,7 +1108,7 @@
handlePatch(operations, (patchedJson, patchedState) => ({
// expand the newly replaced array and select it
state: expandSmart(patchedJson, patchedState, rootPath),
- selection: createValueSelection(rootPath, false)
+ selection: createValueSelection(rootPath)
}))
}
},
@@ -1514,7 +1514,7 @@
const parent = getIn(json, initial(path))
if (Array.isArray(parent)) {
// change into selection of the value
- updateSelection(createValueSelection(path, false))
+ updateSelection(createValueSelection(path))
}
}
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 2b145d2a..e9bfab0d 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -50,7 +50,9 @@ export {
isMultiSelection,
isEditingSelection,
createValueSelection,
+ createEditValueSelection,
createKeySelection,
+ createEditKeySelection,
createInsideSelection,
createAfterSelection,
createMultiSelection,
diff --git a/src/lib/logic/actions.ts b/src/lib/logic/actions.ts
index 8217a017..a5f6962a 100644
--- a/src/lib/logic/actions.ts
+++ b/src/lib/logic/actions.ts
@@ -1,11 +1,11 @@
import {
+ createEditKeySelection,
+ createEditValueSelection,
createInsideSelection,
- createKeySelection,
createMultiSelection,
createValueSelection,
getFocusPath,
hasSelectionContents,
- isEditingSelection,
isKeySelection,
isValueSelection,
selectionToPartialJson
@@ -40,9 +40,8 @@ import {
parsePath
} from 'immutable-json-patch'
import { isObject, isObjectOrArray } from '$lib/utils/typeUtils.js'
-import { expandAll, expandSmart, expandPath, expandNone } from '$lib/logic/documentState.js'
+import { expandAll, expandNone, expandPath, expandSmart } from '$lib/logic/documentState.js'
import { initial, isEmpty, last } from 'lodash-es'
-import { insertActiveElementContents } from '$lib/utils/domUtils.js'
import { fromTableCellPosition, toTableCellPosition } from '$lib/logic/table.js'
const debug = createDebug('jsoneditor:actions')
@@ -135,7 +134,7 @@ export function onPaste({
function doPaste(pastedText: string) {
if (json !== undefined) {
- const ensureSelection = selection || createValueSelection([], false)
+ const ensureSelection = selection || createValueSelection([])
const operations = insert(json, ensureSelection, pastedText, parser)
@@ -281,7 +280,7 @@ export function onDuplicateRow({
onPatch(operations, (_, patchedState) => {
const newRowIndex = rowIndex < (json as Array).length ? rowIndex + 1 : rowIndex
const newPath = fromTableCellPosition({ rowIndex: newRowIndex, columnIndex }, columns)
- const newSelection = createValueSelection(newPath, false)
+ const newSelection = createValueSelection(newPath)
return {
state: patchedState,
@@ -366,7 +365,7 @@ export function onInsertAfterRow({
onPatch(operations, (_, patchedState) => {
const nextPath = fromTableCellPosition({ rowIndex: nextRowIndex, columnIndex }, columns)
- const newSelection = createValueSelection(nextPath, false)
+ const newSelection = createValueSelection(nextPath)
return {
state: patchedState,
@@ -411,8 +410,7 @@ export function onRemoveRow({ json, selection, columns, readOnly, onPatch }: OnR
const newSelection =
newRowIndex !== undefined
? createValueSelection(
- fromTableCellPosition({ rowIndex: newRowIndex, columnIndex }, columns),
- false
+ fromTableCellPosition({ rowIndex: newRowIndex, columnIndex }, columns)
)
: undefined
@@ -428,9 +426,9 @@ export function onRemoveRow({ json, selection, columns, readOnly, onPatch }: OnR
export interface OnInsert {
insertType: InsertType
selectInside: boolean
- refJsonEditor: HTMLElement
json: unknown | undefined
selection: JSONSelection | undefined
+ initialValue: string | undefined
readOnly: boolean
parser: JSONParser
onPatch: OnPatch
@@ -441,7 +439,7 @@ export interface OnInsert {
export function onInsert({
insertType,
selectInside,
- refJsonEditor,
+ initialValue,
json,
selection,
readOnly,
@@ -483,8 +481,8 @@ export function onInsert({
return {
state: expandPath(patchedJson, patchedState, path, expandNone),
selection: isObject(parent)
- ? createKeySelection(path, true)
- : createValueSelection(path, true)
+ ? createEditKeySelection(path, initialValue)
+ : createEditValueSelection(path, initialValue)
}
}
}
@@ -493,13 +491,6 @@ export function onInsert({
})
debug('after patch')
-
- if (operation) {
- if (newValue === '') {
- // open the newly inserted value in edit mode (can be cancelled via ESC this way)
- tick2(() => insertActiveElementContents(refJsonEditor, '', true, refreshEditableDiv))
- }
- }
} else {
// document is empty or invalid (in that case it has text but no json)
debug('onInsert', { insertType, newValue })
@@ -509,7 +500,7 @@ export function onInsert({
state: expandSmart(patchedJson, patchedState, path),
selection: isObjectOrArray(newValue)
? createInsideSelection(path)
- : createValueSelection(path, true)
+ : createEditValueSelection(path)
}))
}
}
@@ -517,7 +508,6 @@ export function onInsert({
export interface OnInsertCharacter {
char: string
selectInside: boolean
- refJsonEditor: HTMLElement
json: unknown | undefined
selection: JSONSelection | undefined
readOnly: boolean
@@ -531,7 +521,6 @@ export interface OnInsertCharacter {
export async function onInsertCharacter({
char,
selectInside,
- refJsonEditor,
json,
selection,
readOnly,
@@ -547,15 +536,7 @@ export async function onInsertCharacter({
}
if (isKeySelection(selection)) {
- // only replace contents when not yet in edit mode (can happen when entering
- // multiple characters very quickly after each other due to the async handling)
- const replaceContents = !selection.edit
-
- onSelect({ ...selection, edit: true })
- tick2(() =>
- // We use this way via insertActiveElementContents, so we can cancel via ESC
- insertActiveElementContents(refJsonEditor, char, replaceContents, refreshEditableDiv)
- )
+ onSelect({ ...selection, edit: true, initialValue: char })
return
}
@@ -563,7 +544,7 @@ export async function onInsertCharacter({
onInsert({
insertType: 'object',
selectInside,
- refJsonEditor,
+ initialValue: undefined, // not relevant
json,
selection,
readOnly,
@@ -575,7 +556,7 @@ export async function onInsertCharacter({
onInsert({
insertType: 'array',
selectInside,
- refJsonEditor,
+ initialValue: undefined, // not relevant
json,
selection,
readOnly,
@@ -586,15 +567,7 @@ export async function onInsertCharacter({
} else {
if (isValueSelection(selection) && json !== undefined) {
if (!isObjectOrArray(getIn(json, selection.path))) {
- // only replace contents when not yet in edit mode (can happen when entering
- // multiple characters very quickly after each other due to the async handling)
- const replaceContents = !selection.edit
-
- onSelect({ ...selection, edit: true })
- tick2(() =>
- // We use this way via insertActiveElementContents, so we can cancel via ESC
- insertActiveElementContents(refJsonEditor, char, replaceContents, refreshEditableDiv)
- )
+ onSelect({ ...selection, edit: true, initialValue: char })
} else {
// TODO: replace the object/array with editing a text in edit mode?
// (Ideally this this should not create an entry in history though,
@@ -605,7 +578,6 @@ export async function onInsertCharacter({
debug('onInsertValueWithCharacter', { char })
await onInsertValueWithCharacter({
char,
- refJsonEditor,
json,
selection,
readOnly,
@@ -619,7 +591,6 @@ export async function onInsertCharacter({
interface OnInsertValueWithCharacter {
char: string
- refJsonEditor: HTMLElement
json: unknown | undefined
selection: JSONSelection | undefined
readOnly: boolean
@@ -630,7 +601,6 @@ interface OnInsertValueWithCharacter {
async function onInsertValueWithCharacter({
char,
- refJsonEditor,
json,
selection,
readOnly,
@@ -646,7 +616,7 @@ async function onInsertValueWithCharacter({
onInsert({
insertType: 'value',
selectInside: false, // not relevant, we insert a value, not an object or array
- refJsonEditor,
+ initialValue: char,
json,
selection,
readOnly,
@@ -654,29 +624,4 @@ async function onInsertValueWithCharacter({
onPatch,
onReplaceJson
})
-
- // only replace contents when not yet in edit mode (can happen when entering
- // multiple characters very quickly after each other due to the async handling)
- const replaceContents = !isEditingSelection(selection)
-
- tick2(() => insertActiveElementContents(refJsonEditor, char, replaceContents, refreshEditableDiv))
-}
-
-/**
- * set two timeouts, two ticks of delay.
- * This allows to perform some action in the DOM *after* Svelte has re-rendered the app for example
- * WARNING: try to avoid using this function, it is tricky to rely on it.
- */
-function tick2(callback: () => void) {
- setTimeout(() => setTimeout(callback))
-}
-
-function refreshEditableDiv(element: HTMLElement) {
- // We force a refresh because when changing the text of the editable div programmatically,
- // the DIV doesn't get a trigger to update it's class
- // TODO: come up with a better solution
-
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- element?.refresh()
}
diff --git a/src/lib/logic/operations.ts b/src/lib/logic/operations.ts
index 678b88f8..7e450585 100644
--- a/src/lib/logic/operations.ts
+++ b/src/lib/logic/operations.ts
@@ -678,7 +678,7 @@ export function createRemoveOperations(
// there is no parent, this is the root document
const operations: JSONPatchDocument = [{ op: 'replace', path: '', value: '' }]
- const newSelection = createValueSelection([], false)
+ const newSelection = createValueSelection([])
return { operations, newSelection }
}
diff --git a/src/lib/logic/search.test.ts b/src/lib/logic/search.test.ts
index 8b588c9b..b0362b55 100644
--- a/src/lib/logic/search.test.ts
+++ b/src/lib/logic/search.test.ts
@@ -331,7 +331,7 @@ describe('search', () => {
}
])
- assert.deepStrictEqual(newSelection, createValueSelection(['hello world'], false))
+ assert.deepStrictEqual(newSelection, createValueSelection(['hello world']))
const updatedJson = immutableJSONPatch(json, operations)
assert.deepStrictEqual(updatedJson, {
@@ -364,7 +364,7 @@ describe('search', () => {
{ op: 'move', from: '/after', path: '/after' }
])
- assert.deepStrictEqual(newSelection, createKeySelection(['hello *'], false))
+ assert.deepStrictEqual(newSelection, createKeySelection(['hello *']))
const updatedJson = immutableJSONPatch(json, operations)
assert.deepStrictEqual(updatedJson, {
@@ -527,7 +527,7 @@ describe('search', () => {
{ op: 'move', from: '/after', path: '/after' }
])
- assert.deepStrictEqual(newSelection, createKeySelection(['hello *'], false))
+ assert.deepStrictEqual(newSelection, createKeySelection(['hello *']))
const updatedJson = immutableJSONPatch(json, operations)
assert.deepStrictEqual(updatedJson, {
diff --git a/src/lib/logic/selection.test.ts b/src/lib/logic/selection.test.ts
index 2b38e5ad..3ff84c54 100644
--- a/src/lib/logic/selection.test.ts
+++ b/src/lib/logic/selection.test.ts
@@ -80,14 +80,14 @@ describe('selection', () => {
test('should expand a key selection', () => {
const path = ['obj', 'arr']
- const actual = getSelectionPaths(json, createKeySelection(path, false))
+ const actual = getSelectionPaths(json, createKeySelection(path))
assert.deepStrictEqual(actual, [['obj', 'arr']])
})
test('should expand a value selection', () => {
const path = ['obj', 'arr']
- const actual = getSelectionPaths(json, createValueSelection(path, false))
+ const actual = getSelectionPaths(json, createValueSelection(path))
assert.deepStrictEqual(actual, [['obj', 'arr']])
})
@@ -142,10 +142,10 @@ describe('selection', () => {
const path2 = ['a']
assert.deepStrictEqual(findRootPath(json, createAfterSelection(path1)), path2)
assert.deepStrictEqual(findRootPath(json, createInsideSelection(path1)), path2)
- assert.deepStrictEqual(findRootPath(json, createKeySelection(path1, false)), path2)
- assert.deepStrictEqual(findRootPath(json, createValueSelection(path1, false)), path2)
- assert.deepStrictEqual(findRootPath(json, createValueSelection(path2, false)), path2)
- assert.deepStrictEqual(findRootPath(json, createKeySelection(path2, false)), path2)
+ assert.deepStrictEqual(findRootPath(json, createKeySelection(path1)), path2)
+ assert.deepStrictEqual(findRootPath(json, createValueSelection(path1)), path2)
+ assert.deepStrictEqual(findRootPath(json, createValueSelection(path2)), path2)
+ assert.deepStrictEqual(findRootPath(json, createKeySelection(path2)), path2)
assert.deepStrictEqual(findRootPath(json, createMultiSelection(['a'], ['a'])), path2)
})
@@ -162,28 +162,28 @@ describe('selection', () => {
test('getSelectionLeft', () => {
assert.deepStrictEqual(
- getSelectionLeft(json2, documentState2, createValueSelection(['path'], false)),
- createKeySelection(['path'], false)
+ getSelectionLeft(json2, documentState2, createValueSelection(['path'])),
+ createKeySelection(['path'])
)
assert.deepStrictEqual(
- getSelectionLeft(json2, documentState2, createKeySelection(['path1'], false)),
+ getSelectionLeft(json2, documentState2, createKeySelection(['path1'])),
createAfterSelection(['path'])
)
assert.deepStrictEqual(
getSelectionLeft(json2, documentState2, createAfterSelection(['path'])),
- createValueSelection(['path'], false)
+ createValueSelection(['path'])
)
assert.deepStrictEqual(
getSelectionLeft(json2, documentState2, createInsideSelection([])),
- createValueSelection([], false)
+ createValueSelection([])
)
assert.deepStrictEqual(
getSelectionLeft(json2, documentState2, createMultiSelection(['path1'], ['path2'])),
- createKeySelection(['path2'], false)
+ createKeySelection(['path2'])
)
})
@@ -193,7 +193,7 @@ describe('selection', () => {
json: json2,
expand: () => false
})
- const selection = createValueSelection(['1'], false)
+ const selection = createValueSelection(['1'])
assert.deepStrictEqual(
getSelectionLeft(json2, documentState2, selection),
@@ -204,12 +204,7 @@ describe('selection', () => {
test('getSelectionLeft: keep anchor path', () => {
const keepAnchorPath = true
assert.deepStrictEqual(
- getSelectionLeft(
- json2,
- documentState2,
- createValueSelection(['path'], false),
- keepAnchorPath
- ),
+ getSelectionLeft(json2, documentState2, createValueSelection(['path']), keepAnchorPath),
{
type: SelectionType.multi,
anchorPath: ['path'],
@@ -220,23 +215,23 @@ describe('selection', () => {
test('getSelectionRight', () => {
assert.deepStrictEqual(
- getSelectionRight(json2, documentState2, createKeySelection(['path'], false)),
- createValueSelection(['path'], false)
+ getSelectionRight(json2, documentState2, createKeySelection(['path'])),
+ createValueSelection(['path'])
)
assert.deepStrictEqual(
- getSelectionRight(json2, documentState2, createValueSelection([], false)),
+ getSelectionRight(json2, documentState2, createValueSelection([])),
createInsideSelection([])
)
assert.deepStrictEqual(
- getSelectionRight(json2, documentState2, createValueSelection(['path'], false)),
+ getSelectionRight(json2, documentState2, createValueSelection(['path'])),
createAfterSelection(['path'])
)
assert.deepStrictEqual(
getSelectionRight(json2, documentState2, createAfterSelection(['path'])),
- createKeySelection(['path1'], false)
+ createKeySelection(['path1'])
)
assert.deepStrictEqual(
@@ -246,19 +241,14 @@ describe('selection', () => {
assert.deepStrictEqual(
getSelectionRight(json2, documentState2, createMultiSelection(['path1'], ['path2'])),
- createValueSelection(['path2'], false)
+ createValueSelection(['path2'])
)
})
test('getSelectionRight: keep anchor path', () => {
const keepAnchorPath = true
assert.deepStrictEqual(
- getSelectionRight(
- json2,
- documentState2,
- createKeySelection(['path'], false),
- keepAnchorPath
- ),
+ getSelectionRight(json2, documentState2, createKeySelection(['path']), keepAnchorPath),
{
type: SelectionType.multi,
anchorPath: ['path'],
@@ -280,78 +270,78 @@ describe('selection', () => {
test('should get selection up from KEY selection', () => {
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createKeySelection(['obj'], false)),
- createKeySelection(['a'], false)
+ getSelectionUp(json2, documentState2, createKeySelection(['obj'])),
+ createKeySelection(['a'])
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createKeySelection(['obj', 'c'], false)),
- createKeySelection(['obj'], false)
+ getSelectionUp(json2, documentState2, createKeySelection(['obj', 'c'])),
+ createKeySelection(['obj'])
)
// jump from key to array value
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createKeySelection(['d'], false)),
- createValueSelection(['arr', '1'], false)
+ getSelectionUp(json2, documentState2, createKeySelection(['d'])),
+ createValueSelection(['arr', '1'])
)
})
test('should get selection up from VALUE selection', () => {
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createValueSelection(['obj'], false)),
- createValueSelection(['a'], false)
+ getSelectionUp(json2, documentState2, createValueSelection(['obj'])),
+ createValueSelection(['a'])
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createValueSelection(['obj', 'c'], false)),
- createValueSelection(['obj'], false)
+ getSelectionUp(json2, documentState2, createValueSelection(['obj', 'c'])),
+ createValueSelection(['obj'])
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createValueSelection(['d'], false)),
- createValueSelection(['arr', '1'], false)
+ getSelectionUp(json2, documentState2, createValueSelection(['d'])),
+ createValueSelection(['arr', '1'])
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createValueSelection(['arr', '1'], false)),
- createValueSelection(['arr', '0'], false)
+ getSelectionUp(json2, documentState2, createValueSelection(['arr', '1'])),
+ createValueSelection(['arr', '0'])
)
})
test('should get selection up from AFTER selection', () => {
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createAfterSelection(['arr', '1'])),
- createValueSelection(['arr', '1'], false)
+ createValueSelection(['arr', '1'])
)
// FIXME: this should return a value selection of /obj/c instead of /obj
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createAfterSelection(['obj'])),
- createValueSelection(['obj'], false)
+ createValueSelection(['obj'])
)
})
test('should get selection up from INSIDE selection', () => {
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createInsideSelection(['arr'])),
- createValueSelection(['arr'], false)
+ createValueSelection(['arr'])
)
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createInsideSelection(['obj'])),
- createValueSelection(['obj'], false)
+ createValueSelection(['obj'])
)
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createInsideSelection([])),
- createValueSelection([], false)
+ createValueSelection([])
)
})
test('should get selection up from MULTI selection', () => {
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createMultiSelection(['d'], ['obj'])),
- createValueSelection(['a'], false)
+ createValueSelection(['a'])
)
assert.deepStrictEqual(
@@ -361,12 +351,12 @@ describe('selection', () => {
assert.deepStrictEqual(
getSelectionUp(json2, documentState2, createMultiSelection(['obj'], ['d'])),
- createValueSelection(['a'], false)
+ createValueSelection(['a'])
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createMultiSelection(['obj'], ['d']), false),
- createValueSelection(['a'], false)
+ getSelectionUp(json2, documentState2, createMultiSelection(['obj'], ['d'])),
+ createValueSelection(['a'])
)
assert.deepStrictEqual(
@@ -375,8 +365,8 @@ describe('selection', () => {
)
assert.deepStrictEqual(
- getSelectionUp(json2, documentState2, createMultiSelection(['a'], ['a']), false),
- createValueSelection([], false)
+ getSelectionUp(json2, documentState2, createMultiSelection(['a'], ['a'])),
+ createValueSelection([])
)
})
})
@@ -394,70 +384,70 @@ describe('selection', () => {
test('should get selection down from KEY selection', () => {
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createKeySelection(['obj'], false)),
- createKeySelection(['obj', 'c'], false)
+ getSelectionDown(json2, documentState2, createKeySelection(['obj'])),
+ createKeySelection(['obj', 'c'])
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createKeySelection(['obj', 'c'], false)),
- createKeySelection(['arr'], false)
+ getSelectionDown(json2, documentState2, createKeySelection(['obj', 'c'])),
+ createKeySelection(['arr'])
)
// jump from key to array value
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createKeySelection(['arr'], false)),
- createValueSelection(['arr', '0'], false)
+ getSelectionDown(json2, documentState2, createKeySelection(['arr'])),
+ createValueSelection(['arr', '0'])
)
})
test('should get selection down from VALUE selection', () => {
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createValueSelection(['obj'], false)),
- createValueSelection(['obj', 'c'], false)
+ getSelectionDown(json2, documentState2, createValueSelection(['obj'])),
+ createValueSelection(['obj', 'c'])
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createValueSelection(['obj', 'c'], false)),
- createValueSelection(['arr'], false)
+ getSelectionDown(json2, documentState2, createValueSelection(['obj', 'c'])),
+ createValueSelection(['arr'])
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createValueSelection(['arr', '1'], false)),
- createValueSelection(['d'], false)
+ getSelectionDown(json2, documentState2, createValueSelection(['arr', '1'])),
+ createValueSelection(['d'])
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createValueSelection(['arr', '0'], false)),
- createValueSelection(['arr', '1'], false)
+ getSelectionDown(json2, documentState2, createValueSelection(['arr', '0'])),
+ createValueSelection(['arr', '1'])
)
})
test('should get selection down from AFTER selection', () => {
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createAfterSelection(['arr', '0'])),
- createValueSelection(['arr', '1'], false)
+ createValueSelection(['arr', '1'])
)
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createAfterSelection(['arr', '1'])),
- createValueSelection(['d'], false)
+ createValueSelection(['d'])
)
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createAfterSelection(['obj'])),
- createValueSelection(['arr'], false)
+ createValueSelection(['arr'])
)
})
test('should get selection down from INSIDE selection', () => {
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createInsideSelection(['arr'])),
- createValueSelection(['arr', '0'], false)
+ createValueSelection(['arr', '0'])
)
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createInsideSelection(['obj'])),
- createValueSelection(['obj', 'c'], false)
+ createValueSelection(['obj', 'c'])
)
assert.deepStrictEqual(
@@ -469,12 +459,12 @@ describe('selection', () => {
test('should get selection down from MULTI selection', () => {
assert.deepStrictEqual(
getSelectionDown(json2, documentState2, createMultiSelection(['arr'], ['a'])),
- createValueSelection(['d'], false)
+ createValueSelection(['d'])
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createMultiSelection(['arr'], ['a']), false),
- createValueSelection(['d'], false)
+ getSelectionDown(json2, documentState2, createMultiSelection(['arr'], ['a'])),
+ createValueSelection(['d'])
)
assert.deepStrictEqual(
@@ -483,8 +473,8 @@ describe('selection', () => {
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createMultiSelection(['a'], ['arr']), false),
- createValueSelection(['d'], false)
+ getSelectionDown(json2, documentState2, createMultiSelection(['a'], ['arr'])),
+ createValueSelection(['d'])
)
assert.deepStrictEqual(
@@ -493,8 +483,8 @@ describe('selection', () => {
)
assert.deepStrictEqual(
- getSelectionDown(json2, documentState2, createMultiSelection(['arr'], ['arr']), false),
- createValueSelection(['d'], false)
+ getSelectionDown(json2, documentState2, createMultiSelection(['arr'], ['arr'])),
+ createValueSelection(['d'])
)
})
@@ -509,7 +499,7 @@ describe('selection', () => {
const documentState3 = createDocumentState({ json: json3, expand: () => true })
assert.deepStrictEqual(
- getSelectionDown(json3, documentState3, createAfterSelection(['arr']), false),
+ getSelectionDown(json3, documentState3, createAfterSelection(['arr'])),
undefined
)
})
@@ -524,48 +514,42 @@ describe('selection', () => {
assert.deepStrictEqual(getInitialSelectionWithState({}), {
type: SelectionType.value,
- path: [],
- edit: false
+ path: []
})
assert.deepStrictEqual(getInitialSelectionWithState([]), {
type: SelectionType.value,
- path: [],
- edit: false
+ path: []
})
assert.deepStrictEqual(getInitialSelectionWithState('test'), {
type: SelectionType.value,
- path: [],
- edit: false
+ path: []
})
assert.deepStrictEqual(getInitialSelectionWithState({ a: 2, b: 3 }), {
type: SelectionType.key,
- path: ['a'],
- edit: false
+ path: ['a']
})
assert.deepStrictEqual(getInitialSelectionWithState({ a: {} }), {
type: SelectionType.key,
- path: ['a'],
- edit: false
+ path: ['a']
})
assert.deepStrictEqual(getInitialSelectionWithState([2, 3, 4]), {
type: SelectionType.value,
- path: ['0'],
- edit: false
+ path: ['0']
})
})
test('should turn selection into text', () => {
assert.deepStrictEqual(
- selectionToPartialJson(json, createKeySelection(['str'], false), 2, JSON),
+ selectionToPartialJson(json, createKeySelection(['str']), 2, JSON),
'str'
)
assert.deepStrictEqual(
- selectionToPartialJson(json, createValueSelection(['str'], false), 2, JSON),
+ selectionToPartialJson(json, createValueSelection(['str']), 2, JSON),
'hello world'
)
assert.deepStrictEqual(
- selectionToPartialJson(json, createValueSelection(['obj', 'arr', '1'], false), 2, JSON),
+ selectionToPartialJson(json, createValueSelection(['obj', 'arr', '1']), 2, JSON),
'2'
)
assert.deepStrictEqual(
@@ -602,7 +586,7 @@ describe('selection', () => {
)
assert.deepStrictEqual(
- selectionToPartialJson(json, createValueSelection(['obj'], false), 2, JSON),
+ selectionToPartialJson(json, createValueSelection(['obj']), 2, JSON),
JSON.stringify(json.obj, null, 2)
)
@@ -626,12 +610,7 @@ describe('selection', () => {
const objArr2 = '{\n' + ' "first": 3,\n' + ' "last": 4\n' + '}'
assert.deepStrictEqual(
- selectionToPartialJson(
- json,
- createValueSelection(['obj', 'arr', '2'], false),
- indentation,
- JSON
- ),
+ selectionToPartialJson(json, createValueSelection(['obj', 'arr', '2']), indentation, JSON),
objArr2
)
assert.deepStrictEqual(
@@ -698,7 +677,7 @@ describe('selection', () => {
createSelectionFromOperations(json, [
{ op: 'replace', path: '/str', value: 'hello world (updated)' }
]),
- createValueSelection(['str'], false)
+ createValueSelection(['str'])
)
})
@@ -709,14 +688,14 @@ describe('selection', () => {
{ op: 'move', from: '/foo', path: '/foo' },
{ op: 'move', from: '/bar', path: '/bar' }
]),
- createKeySelection(['strRenamed'], false)
+ createKeySelection(['strRenamed'])
)
})
test('should get selection from renaming the last key of an object', () => {
assert.deepStrictEqual(
createSelectionFromOperations(json, [{ op: 'move', from: '/arr', path: '/arrRenamed' }]),
- createKeySelection(['arrRenamed'], false)
+ createKeySelection(['arrRenamed'])
)
})
@@ -730,7 +709,7 @@ describe('selection', () => {
test('should get selection from inserting a new root document', () => {
assert.deepStrictEqual(
createSelectionFromOperations(json, [{ op: 'replace', path: '', value: 'test' }]),
- createValueSelection([], false)
+ createValueSelection([])
)
})
})
@@ -763,7 +742,7 @@ describe('selection', () => {
describe('selectionIfOverlapping', () => {
test('should determine whether a KeySelection is relevant for given pointer', () => {
- const selection = createKeySelection(['obj', 'arr'], false)
+ const selection = createKeySelection(['obj', 'arr'])
assert.deepStrictEqual(selectionIfOverlapping(json, selection, []), selection)
assert.deepStrictEqual(selectionIfOverlapping(json, selection, ['obj']), selection)
@@ -775,7 +754,7 @@ describe('selection', () => {
})
test('should determine whether a ValueSelection is relevant for given pointer', () => {
- const selection = createValueSelection(['obj', 'arr'], false)
+ const selection = createValueSelection(['obj', 'arr'])
assert.deepStrictEqual(selectionIfOverlapping(json, selection, []), selection)
assert.deepStrictEqual(selectionIfOverlapping(json, selection, ['obj']), selection)
@@ -844,14 +823,14 @@ describe('selection', () => {
describe('pathInSelection', () => {
test('should determine path in selection for a KeySelection', () => {
- const selection = createKeySelection(['obj'], false)
+ const selection = createKeySelection(['obj'])
assert.strictEqual(pathInSelection(json, selection, ['obj']), true)
assert.strictEqual(pathInSelection(json, selection, ['str']), false)
assert.strictEqual(pathInSelection(json, selection, ['obj', 'arr', '1']), false)
})
test('should determine path in selection for a ValueSelection', () => {
- const selection = createValueSelection(['obj'], false)
+ const selection = createValueSelection(['obj'])
assert.strictEqual(pathInSelection(json, selection, ['obj']), true)
assert.strictEqual(pathInSelection(json, selection, ['str']), false)
assert.strictEqual(pathInSelection(json, selection, ['obj', 'arr', '1']), true)
diff --git a/src/lib/logic/selection.ts b/src/lib/logic/selection.ts
index 04407ffa..90aa533b 100644
--- a/src/lib/logic/selection.ts
+++ b/src/lib/logic/selection.ts
@@ -22,6 +22,8 @@ import type {
AfterSelection,
CaretPosition,
DocumentState,
+ EditKeySelection,
+ EditValueSelection,
InsideSelection,
JSONEditorSelection,
JSONParser,
@@ -246,12 +248,12 @@ export function getSelectionUp(
if (isAfterSelection(selection)) {
// select the node itself, not the previous node,
// FIXME: when after an expanded object/array, should go to the last item inside the object/array
- return createValueSelection(focusPath, false)
+ return createValueSelection(focusPath)
}
if (isInsideSelection(selection)) {
// select the node itself, not the previous node,
- return createValueSelection(focusPath, false)
+ return createValueSelection(focusPath)
}
if (isKeySelection(selection)) {
@@ -263,18 +265,18 @@ export function getSelectionUp(
const parent = getIn(json, parentPath)
if (Array.isArray(parent) || isEmpty(previousPath)) {
// switch to value selection: array has no keys, and root object also not
- return createValueSelection(previousPath, false)
+ return createValueSelection(previousPath)
} else {
- return createKeySelection(previousPath, false)
+ return createKeySelection(previousPath)
}
}
if (isValueSelection(selection)) {
- return previousPath !== undefined ? createValueSelection(previousPath, false) : undefined
+ return previousPath !== undefined ? createValueSelection(previousPath) : undefined
}
if (previousPath !== undefined) {
- return createValueSelection(previousPath, false)
+ return createValueSelection(previousPath)
}
return undefined
@@ -318,15 +320,15 @@ export function getSelectionDown(
}
if (isAfterSelection(selection)) {
- return nextPathAfter !== undefined ? createValueSelection(nextPathAfter, false) : undefined
+ return nextPathAfter !== undefined ? createValueSelection(nextPathAfter) : undefined
}
if (isInsideSelection(selection)) {
- return nextPath !== undefined ? createValueSelection(nextPath, false) : undefined
+ return nextPath !== undefined ? createValueSelection(nextPath) : undefined
}
if (isValueSelection(selection)) {
- return nextPath !== undefined ? createValueSelection(nextPath, false) : undefined
+ return nextPath !== undefined ? createValueSelection(nextPath) : undefined
}
if (isKeySelection(selection)) {
@@ -338,17 +340,17 @@ export function getSelectionDown(
const parent = getIn(json, parentPath)
if (Array.isArray(parent)) {
// switch to value selection: array has no keys
- return createValueSelection(nextPath, false)
+ return createValueSelection(nextPath)
} else {
- return createKeySelection(nextPath, false)
+ return createKeySelection(nextPath)
}
}
if (isMultiSelection(selection)) {
return nextPathAfter !== undefined
- ? createValueSelection(nextPathAfter, false)
+ ? createValueSelection(nextPathAfter)
: nextPath !== undefined
- ? createValueSelection(nextPath, false)
+ ? createValueSelection(nextPath)
: undefined
}
@@ -373,7 +375,7 @@ export function getSelectionNextInside(
const nextPathInside = parent ? getNextVisiblePath(parent, documentState, childPath) : undefined
if (nextPathInside) {
- return createValueSelection(parentPath.concat(nextPathInside), false)
+ return createValueSelection(parentPath.concat(nextPathInside))
} else {
return createAfterSelection(path)
}
@@ -449,7 +451,7 @@ export function getSelectionLeft(
}
if (isMultiSelection(selection) && !Array.isArray(parent)) {
- return createKeySelection(selection.focusPath, false)
+ return createKeySelection(selection.focusPath)
}
return undefined
@@ -481,7 +483,7 @@ export function getSelectionRight(
}
if (isMultiSelection(selection)) {
- return createValueSelection(selection.focusPath, false)
+ return createValueSelection(selection.focusPath)
}
return undefined
@@ -507,8 +509,8 @@ export function getInitialSelection(
const path = visiblePaths[index]
return path === undefined || path.length === 0 || Array.isArray(getIn(json, initial(path)))
- ? createValueSelection(path, false) // Array items and root object/array do not have a key, so select value in that case
- : createKeySelection(path, false)
+ ? createValueSelection(path) // Array items and root object/array do not have a key, so select value in that case
+ : createKeySelection(path)
}
export function createSelectionFromOperations(
@@ -521,7 +523,7 @@ export function createSelectionFromOperations(
// a replaced value
const path = parsePath(json, operation.path)
- return createValueSelection(path, false)
+ return createValueSelection(path)
}
}
@@ -537,7 +539,7 @@ export function createSelectionFromOperations(
// a renamed key
const path = parsePath(json, firstOp.path)
- return createKeySelection(path, false)
+ return createKeySelection(path)
}
}
@@ -611,27 +613,31 @@ export function pathStartsWith(path: JSONPath, parentPath: JSONPath): boolean {
export function removeEditModeFromSelection(
selection: JSONSelection | undefined
): JSONSelection | undefined {
- if ((isKeySelection(selection) || isValueSelection(selection)) && selection.edit) {
- return { ...selection, edit: false }
+ if (isEditingSelection(selection)) {
+ const { type, path } = selection
+ return { type, path } as KeySelection | ValueSelection
}
return selection
}
-export function createKeySelection(path: JSONPath, edit: boolean): KeySelection {
- return {
- type: SelectionType.key,
- path,
- edit
- }
+export function createKeySelection(path: JSONPath): KeySelection {
+ return { type: SelectionType.key, path }
}
-export function createValueSelection(path: JSONPath, edit: boolean): ValueSelection {
- return {
- type: SelectionType.value,
- path,
- edit
- }
+export function createEditKeySelection(path: JSONPath, initialValue?: string): EditKeySelection {
+ return { type: SelectionType.key, path, edit: true, initialValue }
+}
+
+export function createValueSelection(path: JSONPath): ValueSelection {
+ return { type: SelectionType.value, path }
+}
+
+export function createEditValueSelection(
+ path: JSONPath,
+ initialValue?: string
+): EditValueSelection {
+ return { type: SelectionType.value, path, edit: true, initialValue }
}
export function createInsideSelection(path: JSONPath): InsideSelection {
@@ -715,8 +721,13 @@ export function selectionToPartialJson(
return undefined
}
-export function isEditingSelection(selection: JSONSelection | undefined): boolean {
- return (isKeySelection(selection) || isValueSelection(selection)) && selection.edit === true
+export function isEditingSelection(
+ selection: JSONSelection | undefined
+): selection is EditKeySelection | EditValueSelection {
+ return (
+ (isKeySelection(selection) || isValueSelection(selection)) &&
+ (selection as Record).edit === true
+ )
}
/**
@@ -724,7 +735,7 @@ export function isEditingSelection(selection: JSONSelection | undefined): boolea
*/
// TODO: write unit tests
export function selectAll(): JSONSelection {
- return createValueSelection([], false)
+ return createValueSelection([])
}
// TODO: write unit tests
@@ -749,9 +760,9 @@ export function canConvert(selection: JSONSelection | undefined): boolean {
export function fromCaretPosition(caretPosition: CaretPosition): JSONSelection {
switch (caretPosition.type) {
case CaretType.key:
- return createKeySelection(caretPosition.path, false)
+ return createKeySelection(caretPosition.path)
case CaretType.value:
- return createValueSelection(caretPosition.path, false)
+ return createValueSelection(caretPosition.path)
case CaretType.after:
return createAfterSelection(caretPosition.path)
case CaretType.inside:
@@ -764,9 +775,9 @@ export function fromCaretPosition(caretPosition: CaretPosition): JSONSelection {
export function fromSelectionType(selectionType: SelectionType, path: JSONPath): JSONSelection {
switch (selectionType) {
case SelectionType.key:
- return createKeySelection(path, false)
+ return createKeySelection(path)
case SelectionType.value:
- return createValueSelection(path, false)
+ return createValueSelection(path)
case SelectionType.after:
return createAfterSelection(path)
case SelectionType.inside:
diff --git a/src/lib/logic/table.test.ts b/src/lib/logic/table.test.ts
index fa64812e..6cc83ca5 100644
--- a/src/lib/logic/table.test.ts
+++ b/src/lib/logic/table.test.ts
@@ -172,49 +172,49 @@ describe('table', () => {
test('selectPreviousRow', () => {
deepStrictEqual(
- selectPreviousRow(columns, createValueSelection(['2', 'id'], false)),
- createValueSelection(['1', 'id'], false)
+ selectPreviousRow(columns, createValueSelection(['2', 'id'])),
+ createValueSelection(['1', 'id'])
)
deepStrictEqual(
- selectPreviousRow(columns, createValueSelection(['0', 'id'], false)),
- createValueSelection(['0', 'id'], false)
+ selectPreviousRow(columns, createValueSelection(['0', 'id'])),
+ createValueSelection(['0', 'id'])
)
})
test('selectNextRow', () => {
deepStrictEqual(
- selectNextRow(json, columns, createValueSelection(['0', 'id'], false)),
- createValueSelection(['1', 'id'], false)
+ selectNextRow(json, columns, createValueSelection(['0', 'id'])),
+ createValueSelection(['1', 'id'])
)
deepStrictEqual(
- selectNextRow(json, columns, createValueSelection(['1', 'id'], false)),
- createValueSelection(['1', 'id'], false)
+ selectNextRow(json, columns, createValueSelection(['1', 'id'])),
+ createValueSelection(['1', 'id'])
)
})
test('selectPreviousColumn', () => {
deepStrictEqual(
- selectPreviousColumn(columns, createValueSelection(['2', 'name'], false)),
- createValueSelection(['2', 'id'], false)
+ selectPreviousColumn(columns, createValueSelection(['2', 'name'])),
+ createValueSelection(['2', 'id'])
)
deepStrictEqual(
- selectPreviousColumn(columns, createValueSelection(['2', 'id'], false)),
- createValueSelection(['2', 'id'], false)
+ selectPreviousColumn(columns, createValueSelection(['2', 'id'])),
+ createValueSelection(['2', 'id'])
)
})
test('selectNextColumn', () => {
deepStrictEqual(
- selectNextColumn(columns, createValueSelection(['2', 'id'], false)),
- createValueSelection(['2', 'name'], false)
+ selectNextColumn(columns, createValueSelection(['2', 'id'])),
+ createValueSelection(['2', 'name'])
)
deepStrictEqual(
- selectNextColumn(columns, createValueSelection(['2', 'other'], false)),
- createValueSelection(['2', 'other'], false)
+ selectNextColumn(columns, createValueSelection(['2', 'other'])),
+ createValueSelection(['2', 'other'])
)
})
diff --git a/src/lib/logic/table.ts b/src/lib/logic/table.ts
index b9c6aac8..0766ce93 100644
--- a/src/lib/logic/table.ts
+++ b/src/lib/logic/table.ts
@@ -269,7 +269,7 @@ export function selectPreviousRow(columns: JSONPath[], selection: JSONSelection)
if (rowIndex > 0) {
const previousPosition = { rowIndex: rowIndex - 1, columnIndex }
const previousPath = fromTableCellPosition(previousPosition, columns)
- return createValueSelection(previousPath, false)
+ return createValueSelection(previousPath)
}
return selection
@@ -285,7 +285,7 @@ export function selectNextRow(
if (rowIndex < (json as Array).length - 1) {
const nextPosition = { rowIndex: rowIndex + 1, columnIndex }
const nextPath = fromTableCellPosition(nextPosition, columns)
- return createValueSelection(nextPath, false)
+ return createValueSelection(nextPath)
}
return selection
@@ -297,7 +297,7 @@ export function selectPreviousColumn(columns: JSONPath[], selection: JSONSelecti
if (columnIndex > 0) {
const previousPosition = { rowIndex, columnIndex: columnIndex - 1 }
const previousPath = fromTableCellPosition(previousPosition, columns)
- return createValueSelection(previousPath, false)
+ return createValueSelection(previousPath)
}
return selection
@@ -309,7 +309,7 @@ export function selectNextColumn(columns: JSONPath[], selection: JSONSelection):
if (columnIndex < columns.length - 1) {
const nextPosition = { rowIndex, columnIndex: columnIndex + 1 }
const nextPath = fromTableCellPosition(nextPosition, columns)
- return createValueSelection(nextPath, false)
+ return createValueSelection(nextPath)
}
return selection
diff --git a/src/lib/plugins/value/components/EditableValue.svelte b/src/lib/plugins/value/components/EditableValue.svelte
index 4ff13c14..4375b5b0 100644
--- a/src/lib/plugins/value/components/EditableValue.svelte
+++ b/src/lib/plugins/value/components/EditableValue.svelte
@@ -4,12 +4,13 @@
import type { JSONPatchDocument, JSONPath } from 'immutable-json-patch'
import { compileJSONPointer } from 'immutable-json-patch'
import { isObjectOrArray, stringConvert } from '$lib/utils/typeUtils.js'
- import { createValueSelection, getFocusPath } from '$lib/logic/selection.js'
+ import { createValueSelection, getFocusPath, isEditingSelection } from '$lib/logic/selection.js'
import { getValueClass } from '$lib/plugins/value/components/utils/getValueClass.js'
import EditableDiv from '../../../components/controls/EditableDiv.svelte'
import type {
FindNextInside,
JSONParser,
+ JSONSelection,
OnFind,
OnJSONSelect,
OnPasteJson,
@@ -22,6 +23,7 @@
export let path: JSONPath
export let value: unknown
+ export let selection: JSONSelection | undefined
export let parser: JSONParser
export let normalization: ValueNormalization
export let enforceString: boolean
@@ -56,7 +58,7 @@
const selection =
updateSelection === UpdateSelectionAfterChange.nextInside
? findNextInside(path)
- : createValueSelection(path, false)
+ : createValueSelection(path)
return {
state: patchedState,
@@ -69,7 +71,7 @@
}
function handleCancelChange() {
- onSelect(createValueSelection(path, false))
+ onSelect(createValueSelection(path))
focus()
}
@@ -112,6 +114,7 @@
import { isUrl } from '$lib/utils/typeUtils.js'
- import { createValueSelection } from '$lib/logic/selection.js'
+ import { createEditValueSelection } from '$lib/logic/selection.js'
import SearchResultHighlighter from '../../../components/modes/treemode/highlight/SearchResultHighlighter.svelte'
import { getValueClass } from './utils/getValueClass.js'
import { addNewLineSuffix } from '$lib/utils/domUtils.js'
@@ -38,7 +38,7 @@
function handleValueDoubleClick(event: MouseEvent) {
if (!readOnly) {
event.preventDefault()
- onSelect(createValueSelection(path, true))
+ onSelect(createEditValueSelection(path))
}
}
diff --git a/src/lib/plugins/value/renderValue.ts b/src/lib/plugins/value/renderValue.ts
index 7ee124c1..75441f3c 100644
--- a/src/lib/plugins/value/renderValue.ts
+++ b/src/lib/plugins/value/renderValue.ts
@@ -1,15 +1,16 @@
-import { isBoolean, isColor, isTimestamp } from '../../utils/typeUtils.js'
+import { isBoolean, isColor, isTimestamp } from '$lib/utils/typeUtils.js'
+import type { RenderValueComponentDescription, RenderValueProps } from '$lib/types'
import BooleanToggle from './components/BooleanToggle.svelte'
import ColorPicker from './components/ColorPicker.svelte'
import EditableValue from './components/EditableValue.svelte'
import ReadonlyValue from './components/ReadonlyValue.svelte'
import TimestampTag from './components/TimestampTag.svelte'
-import type { RenderValueComponentDescription, RenderValueProps } from '../../types'
export function renderValue({
path,
value,
readOnly,
+ selection,
enforceString,
searchResultItems,
isEditing,
@@ -44,6 +45,7 @@ export function renderValue({
props: {
path,
value,
+ selection,
enforceString,
parser,
normalization,
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 876d4723..9ddc9be0 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -201,13 +201,25 @@ export interface InsideSelection {
export interface KeySelection {
type: SelectionType.key
path: JSONPath
- edit?: boolean
}
-export interface ValueSelection {
+export interface EditKeySelection extends KeySelection {
+ type: SelectionType.key
+ path: JSONPath
+ edit: true
+ initialValue?: string
+}
+
+export type ValueSelection = {
+ type: SelectionType.value
+ path: JSONPath
+}
+
+export interface EditValueSelection extends ValueSelection {
type: SelectionType.value
path: JSONPath
- edit?: boolean
+ edit: true
+ initialValue?: string
}
export type JSONSelection =
@@ -215,7 +227,9 @@ export type JSONSelection =
| AfterSelection
| InsideSelection
| KeySelection
+ | EditKeySelection
| ValueSelection
+ | EditValueSelection
// TextSelection is the result of EditorSelection.toJSON() from CodeMirror,
// with an additional `type` property
diff --git a/src/lib/utils/domUtils.ts b/src/lib/utils/domUtils.ts
index feeabdbf..5dd1d837 100644
--- a/src/lib/utils/domUtils.ts
+++ b/src/lib/utils/domUtils.ts
@@ -223,33 +223,6 @@ export function setCursorToEnd(element: HTMLElement) {
selection?.addRange(range)
}
-/**
- * Insert (append or replace) the text contents of the current active element
- */
-export function insertActiveElementContents(
- container: HTMLElement,
- text: string,
- replaceContents: boolean,
- onActiveElement?: (activeElement: HTMLElement) => void
-) {
- const window = getWindow(container)
- if (!window) {
- return
- }
-
- const activeElement: HTMLElement | undefined = window.document.activeElement
- ? (window.document.activeElement as HTMLElement)
- : undefined
-
- if (activeElement && activeElement.isContentEditable) {
- activeElement.textContent = replaceContents ? text : activeElement.textContent + text
- setCursorToEnd(activeElement)
- if (onActiveElement) {
- onActiveElement(activeElement)
- }
- }
-}
-
/**
* Gets a DOM element's Window. This is normally just the global `window`
* variable, but if we opened a child window, it may be different.
diff --git a/src/routes/components/EditableValueInput.svelte b/src/routes/components/EditableValueInput.svelte
index c0aa8fd6..e0b7d495 100644
--- a/src/routes/components/EditableValueInput.svelte
+++ b/src/routes/components/EditableValueInput.svelte
@@ -64,7 +64,7 @@
}
function cancel() {
- onSelect(createValueSelection(path, false))
+ onSelect(createValueSelection(path))
focus()
}
diff --git a/src/routes/components/EvaluatorAction.ts b/src/routes/components/EvaluatorAction.ts
index 2fcc9d44..5fb226e2 100644
--- a/src/routes/components/EvaluatorAction.ts
+++ b/src/routes/components/EvaluatorAction.ts
@@ -1,6 +1,7 @@
-import { createValueSelection, type OnJSONSelect } from 'svelte-jsoneditor'
+import { type OnJSONSelect } from 'svelte-jsoneditor'
import type { Action } from 'svelte/action'
import { type JSONPath } from 'immutable-json-patch'
+import { createEditValueSelection } from '$lib/logic/selection'
export interface EvaluatorActionProps {
value: unknown
@@ -25,7 +26,7 @@ export const EvaluatorAction: Action> =
event.stopPropagation()
// open in edit mode
- props.onSelect(createValueSelection(props.path, true))
+ props.onSelect(createEditValueSelection(props.path))
}
}
diff --git a/src/routes/development/+page.svelte b/src/routes/development/+page.svelte
index bd0161bf..11df2a21 100644
--- a/src/routes/development/+page.svelte
+++ b/src/routes/development/+page.svelte
@@ -663,7 +663,7 @@