Skip to content

Commit 085a9d3

Browse files
committedAug 30, 2023
fix: restore the selection when going back when having multiple JSONEditor modals
1 parent c7705f6 commit 085a9d3

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed
 

‎src/lib/components/modals/JSONEditorModal.svelte

+42-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<svelte:options immutable={true} />
22

33
<script lang="ts">
4-
import { getContext } from 'svelte'
4+
import { getContext, tick } from 'svelte'
55
import Header from './Header.svelte'
66
import type { JSONPatchDocument, JSONPath } from 'immutable-json-patch'
77
import { compileJSONPointer, immutableJSONPatch, isJSONArray } from 'immutable-json-patch'
@@ -30,6 +30,7 @@
3030
import { faCaretLeft } from '@fortawesome/free-solid-svg-icons'
3131
import memoizeOne from 'memoize-one'
3232
import { onEscape } from '$lib/actions/onEscape.js'
33+
import { getFocusPath } from '$lib/logic/selection.js'
3334
3435
const debug = createDebug('jsoneditor:JSONEditorModal')
3536
@@ -64,17 +65,21 @@
6465
interface ModalState {
6566
mode: Mode
6667
content: Content
68+
selection: JSONEditorSelection | null
6769
relativePath: JSONPath
6870
}
6971
72+
let refEditor: JSONEditorRoot
73+
7074
const rootState: ModalState = {
7175
mode: determineMode(content),
7276
content,
77+
selection: null,
7378
relativePath: path
7479
}
7580
let stack: ModalState[] = [rootState]
76-
let selection: JSONEditorSelection | null = null
7781
82+
$: currentState = last(stack) || rootState
7883
$: absolutePath = stack.flatMap((state) => state.relativePath)
7984
$: pathDescription = !isEmpty(absolutePath) ? stringifyJSONPath(absolutePath) : '(whole document)'
8085
@@ -87,6 +92,13 @@
8792
return isJSONContent(content) && isJSONArray(content.json) ? Mode.table : Mode.tree
8893
}
8994
95+
function scrollToSelection() {
96+
const selection: JSONPath | null = last(stack)?.selection || null
97+
if (selection) {
98+
refEditor.scrollTo(getFocusPath(selection))
99+
}
100+
}
101+
90102
function handleApply() {
91103
debug('handleApply')
92104
@@ -97,8 +109,8 @@
97109
try {
98110
error = undefined
99111
100-
const path = last(stack).relativePath
101-
const content = last(stack).content
112+
const path = currentState.relativePath
113+
const content = currentState.content
102114
const operations: JSONPatchDocument = [
103115
{
104116
op: 'replace',
@@ -114,17 +126,18 @@
114126
json: immutableJSONPatch(parentJson, operations)
115127
}
116128
117-
// after successfully updated, remove from the stack and apply the change
118-
stack = initial(stack)
119-
selection = null // TODO: restore the selection, like selection = createValueSelection(path, false)
120-
handleChange(updatedParentContent)
129+
// after successfully updated, remove from the stack and apply the change to the parent
130+
const parentState = stack[stack.length - 2] || rootState
131+
const updatedParentState: ModalState = { ...parentState, content: updatedParentContent }
132+
stack = [...stack.slice(0, stack.length - 2), updatedParentState]
133+
tick().then(scrollToSelection)
121134
} else {
122135
onPatch(operations)
123136
124137
close()
125138
}
126139
} catch (err) {
127-
error = err.toString()
140+
error = String(err)
128141
}
129142
}
130143
@@ -134,6 +147,7 @@
134147
if (stack.length > 1) {
135148
// remove the last item from the stack
136149
stack = initial(stack)
150+
tick().then(scrollToSelection)
137151
138152
// clear any error from the just closed state
139153
error = undefined
@@ -147,18 +161,29 @@
147161
debug('handleChange', updatedContent)
148162
149163
const updatedState = {
150-
...last(stack),
164+
...currentState,
151165
content: updatedContent
152166
}
153167
154168
stack = [...initial(stack), updatedState]
155169
}
156170
171+
function handleChangeSelection(newSelection: JSONEditorSelection | null) {
172+
debug('handleChangeSelection', newSelection)
173+
174+
const updatedState = {
175+
...currentState,
176+
selection: newSelection
177+
}
178+
179+
stack = [...initial(stack), updatedState]
180+
}
181+
157182
function handleChangeMode(newMode: Mode) {
158183
debug('handleChangeMode', newMode)
159184
160185
const updatedState = {
161-
...last(stack),
186+
...currentState,
162187
mode: newMode
163188
}
164189
@@ -176,6 +201,7 @@
176201
const nestedModalState = {
177202
mode: determineMode(content),
178203
content,
204+
selection: null,
179205
relativePath: path
180206
}
181207
stack = [...stack, nestedModalState]
@@ -204,9 +230,10 @@
204230

205231
<div class="jse-modal-inline-editor">
206232
<JSONEditorRoot
207-
mode={last(stack).mode}
208-
content={last(stack).content}
209-
{selection}
233+
bind:this={refEditor}
234+
mode={currentState.mode}
235+
content={currentState.content}
236+
selection={currentState.selection}
210237
{readOnly}
211238
{indentation}
212239
{tabSize}
@@ -226,9 +253,7 @@
226253
onError={handleError}
227254
onChange={handleChange}
228255
onChangeMode={handleChangeMode}
229-
onSelect={(newSelection) => {
230-
selection = newSelection
231-
}}
256+
onSelect={handleChangeSelection}
232257
{onRenderValue}
233258
{onClassName}
234259
onFocus={noop}

0 commit comments

Comments
 (0)
Please sign in to comment.