Skip to content

Commit

Permalink
chore: refactor KeySelection and ValueSelection (#463)
Browse files Browse the repository at this point in the history
Refactor `KeySelection` and `ValueSelection` to get rid of a couple of internal workarounds

BREAKING CHANGES:
-  The property `edit` is removed from the types `KeySelection` and `ValueSelection`, 
    and two new types `EditKeySelection` and `EditValueSelection` are added.
-  The helper functions  `createKeySelection` and `createValueSelection` are changed,
    argument `edit` is removed, and two new helper functions `createEditKeySelection` 
    and `createEditValueSelection` are added.
-  the API of the component `EditableValue` requires an additional property `selection`.
  • Loading branch information
josdejong authored Jul 15, 2024
1 parent e90390d commit c807600
Show file tree
Hide file tree
Showing 21 changed files with 253 additions and 326 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`
Expand Down
10 changes: 3 additions & 7 deletions src/lib/components/controls/EditableDiv.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
})
Expand Down
13 changes: 5 additions & 8 deletions src/lib/components/modes/tablemode/TableMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -736,7 +734,7 @@
return
}
updateSelection(createValueSelection(path, false))
updateSelection(createValueSelection(path))
event.preventDefault()
}
Expand All @@ -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
}
Expand Down Expand Up @@ -1047,7 +1045,7 @@
if (isObjectOrArray(value)) {
openJSONEditorModal(path)
} else {
updateSelection(createValueSelection(path, true))
updateSelection(createValueSelection(path))
}
}
Expand Down Expand Up @@ -1173,7 +1171,6 @@
await onInsertCharacter({
char,
selectInside: false,
refJsonEditor,
json,
selection: selection,
readOnly,
Expand Down Expand Up @@ -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)
}
Expand Down
14 changes: 8 additions & 6 deletions src/lib/components/modes/treemode/JSONKey.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<script lang="ts">
import { initial, isEqual } from 'lodash-es'
import {
createEditKeySelection,
createKeySelection,
createValueSelection,
isEditingSelection,
Expand All @@ -13,7 +14,7 @@
import { addNewLineSuffix } from '$lib/utils/domUtils.js'
import type { ExtendedSearchResultItem, JSONSelection, TreeModeContext } from '$lib/types.js'
import { UpdateSelectionAfterChange } from '$lib/types.js'
import { parseJSONPointer, type JSONPath, type JSONPointer } from 'immutable-json-patch'
import { type JSONPath, type JSONPointer, parseJSONPointer } from 'immutable-json-patch'
import ContextMenuPointer from '../../../components/controls/contextmenu/ContextMenuPointer.svelte'
import { classnames } from '$lib/utils/cssUtils.js'
Expand All @@ -28,15 +29,15 @@
let path: JSONPath
$: path = parseJSONPointer(pointer)
$: isKeySelected = selection ? isKeySelection(selection) && isEqual(selection.path, path) : false
$: isKeySelected = isKeySelection(selection) && isEqual(selection.path, path)
$: isEditingKey = isKeySelected && isEditingSelection(selection)
function handleKeyDoubleClick(
event: MouseEvent & { currentTarget: EventTarget & HTMLDivElement }
) {
if (!isEditingKey && !context.readOnly) {
event.preventDefault()
context.onSelect(createKeySelection(path, true))
context.onSelect(createEditKeySelection(path))
}
}
Expand All @@ -52,8 +53,8 @@
context.onSelect(
updateSelection === UpdateSelectionAfterChange.nextInside
? createValueSelection(updatedPath, false)
: createKeySelection(updatedPath, false)
? createValueSelection(updatedPath)
: createKeySelection(updatedPath)
)
if (updateSelection !== UpdateSelectionAfterChange.self) {
Expand All @@ -62,14 +63,15 @@
}
function handleCancelChange() {
context.onSelect(createKeySelection(path, false))
context.onSelect(createKeySelection(path))
context.focus()
}
</script>

{#if !context.readOnly && isEditingKey}
<EditableDiv
value={context.normalization.escapeValue(key)}
initialValue={isEditingSelection(selection) ? selection.initialValue : undefined}
label="Edit key"
shortText
onChange={handleChangeValue}
Expand Down
22 changes: 11 additions & 11 deletions src/lib/components/modes/treemode/TreeMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
import {
canConvert,
createAfterSelection,
createEditKeySelection,
createEditValueSelection,
createInsideSelection,
createKeySelection,
createSelectionFromOperations,
createValueSelection,
findRootPath,
Expand Down Expand Up @@ -312,7 +313,7 @@
function handleSelectValidationError(error: ValidationError) {
debug('select validation error', error)
updateSelection(createValueSelection(error.path, false))
updateSelection(createValueSelection(error.path))
scrollTo(error.path)
}
Expand Down Expand Up @@ -578,7 +579,7 @@
function createDefaultSelection() {
debug('createDefaultSelection')
updateSelection(createValueSelection([], false))
updateSelection(createValueSelection([]))
}
export function patch(
Expand Down Expand Up @@ -661,7 +662,7 @@
return
}
updateSelection(createKeySelection(getFocusPath(selection), true))
updateSelection(createEditKeySelection(getFocusPath(selection)))
}
function handleEditValue() {
Expand All @@ -674,7 +675,7 @@
if (isObjectOrArray(value)) {
openJSONEditorModal(path, value)
} else {
updateSelection(createValueSelection(path, true))
updateSelection(createEditValueSelection(path))
}
}
Expand Down Expand Up @@ -834,7 +835,7 @@
onInsert({
insertType,
selectInside: true,
refJsonEditor,
initialValue: undefined,
json,
selection,
readOnly,
Expand All @@ -847,7 +848,7 @@
function handleInsertFromContextMenu(type: InsertType) {
if (isKeySelection(selection)) {
// in this case, we do not want to rename the key, but replace the property
updateSelection(createValueSelection(selection.path, false))
updateSelection(createValueSelection(selection.path))
}
if (!selection) {
Expand Down Expand Up @@ -940,7 +941,6 @@
await onInsertCharacter({
char,
selectInside: true,
refJsonEditor,
json,
selection,
readOnly,
Expand Down Expand Up @@ -1054,7 +1054,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)
}))
},
onClose: () => {
Expand Down Expand Up @@ -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)
}))
}
},
Expand Down Expand Up @@ -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))
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export {
isMultiSelection,
isEditingSelection,
createValueSelection,
createEditValueSelection,
createKeySelection,
createEditKeySelection,
createInsideSelection,
createAfterSelection,
createMultiSelection,
Expand Down
Loading

0 comments on commit c807600

Please sign in to comment.