Skip to content

Commit

Permalink
feat: keep history when switching mode (#504)
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong authored Nov 26, 2024
1 parent bdacef3 commit b5f11ca
Show file tree
Hide file tree
Showing 12 changed files with 423 additions and 142 deletions.
5 changes: 4 additions & 1 deletion src/lib/components/JSONEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@
case 'content':
content = props[name] ?? contentDefault
break
case 'selection':
selection = props[name] ?? selectionDefault
break
case 'readOnly':
readOnly = props[name] ?? readOnlyDefault
break
Expand Down Expand Up @@ -527,7 +530,7 @@
{#key instanceId}
<JSONEditorRoot
bind:this={refJSONEditorRoot}
{mode}
externalMode={mode}
{content}
{selection}
{readOnly}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/modals/JSONEditorModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@
<div class="jse-modal-inline-editor">
<JSONEditorRoot
bind:this={refEditor}
mode={currentState.mode}
externalMode={currentState.mode}
content={currentState.content}
selection={currentState.selection}
{readOnly}
Expand Down
15 changes: 15 additions & 0 deletions src/lib/components/modals/TransformModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import TreeMode from '../modes/treemode/TreeMode.svelte'
import type {
Content,
HistoryItem,
History,
JSONParser,
JSONPathParser,
OnChangeQueryLanguage,
Expand All @@ -31,6 +33,7 @@
import { readonlyProxy } from '$lib/utils/readonlyProxy.js'
import Modal from './Modal.svelte'
import { onMount } from 'svelte'
import { createHistoryInstance } from '$lib/logic/history'
const debug = createDebug('jsoneditor:TransformModal')
Expand Down Expand Up @@ -60,6 +63,12 @@
let refQueryInput: HTMLTextAreaElement
const historyInstance = createHistoryInstance<HistoryItem>({
onChange: (updatedHistory) => (history = updatedHistory)
})
let history: History<HistoryItem> = historyInstance.get()
let selectedJson: unknown | undefined
$: selectedJson = readonlyProxy(getIn(json, rootPath))
let selectedContent: Content
Expand Down Expand Up @@ -316,6 +325,7 @@
<TreeMode
externalContent={selectedContent}
externalSelection={undefined}
{history}
readOnly={true}
mainMenuBar={false}
navigationBar={false}
Expand All @@ -331,6 +341,8 @@
onChange={noop}
onChangeMode={noop}
onSelect={noop}
onUndo={noop}
onRedo={noop}
onFocus={noop}
onBlur={noop}
onSortModal={noop}
Expand All @@ -351,6 +363,7 @@
<TreeMode
externalContent={previewContent}
externalSelection={undefined}
{history}
readOnly={true}
mainMenuBar={false}
navigationBar={false}
Expand All @@ -366,6 +379,8 @@
onChange={noop}
onChangeMode={noop}
onSelect={noop}
onUndo={noop}
onRedo={noop}
onFocus={noop}
onBlur={noop}
onSortModal={noop}
Expand Down
91 changes: 87 additions & 4 deletions src/lib/components/modes/JSONEditorRoot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Content,
ContentErrors,
ContextMenuItem,
HistoryItem,
History,
JSONEditorSelection,
JSONParser,
JSONPatchResult,
Expand All @@ -26,23 +28,26 @@
OnSortModal,
OnTransformModal,
TransformModalOptions,
Validator
Validator,
ModeHistoryItem
} from '$lib/types'
import { Mode } from '$lib/types.js'
import TextMode from './textmode/TextMode.svelte'
import TableMode from './tablemode/TableMode.svelte'
import TreeMode from './treemode/TreeMode.svelte'
import type { JSONPatchDocument, JSONPath } from 'immutable-json-patch'
import { isMenuSpace } from '$lib/typeguards.js'
import { isMenuSpace, isModeHistoryItem } from '$lib/typeguards.js'
import { cloneDeep } from 'lodash-es'
import { createHistoryInstance } from '$lib/logic/history'
import { createDebug } from '$lib/utils/debug'
export let content: Content
export let selection: JSONEditorSelection | undefined
export let readOnly: boolean
export let indentation: number | string
export let tabSize: number
export let mode: Mode
export let externalMode: Mode
export let mainMenuBar: boolean
export let navigationBar: boolean
export let statusBar: boolean
Expand Down Expand Up @@ -75,6 +80,75 @@
let refTableMode: TableMode | undefined
let refTextMode: TextMode | undefined
const debug = createDebug('jsoneditor:JSONEditorRoot')
const historyInstance = createHistoryInstance<HistoryItem>({
onChange: (updatedHistory) => (history = updatedHistory)
})
let history: History<HistoryItem> = historyInstance.get()
let mode = externalMode
function applyExternalMode(externalMode: Mode) {
if (externalMode === mode) {
return
}
const item: ModeHistoryItem = {
type: 'mode',
undo: { mode, selection: undefined },
redo: { mode: externalMode, selection: undefined }
}
if (mode === 'text' && refTextMode) {
// flush pending changes before adding a new history item
refTextMode.flush()
}
debug('add history item', item)
history.add(item)
mode = externalMode
}
$: applyExternalMode(externalMode)
function handleUndo(item: HistoryItem | undefined) {
if (isModeHistoryItem(item)) {
mode = item.undo.mode // important to prevent a new history item from being created
// find the selection of the previous history item (if any), and use that as initial selection
const items = history.items()
const index = items.findIndex((i) => i === item)
const prevItem = index !== -1 ? items[index - 1] : undefined
debug('handleUndo', { index, item, items, prevItem })
if (prevItem) {
selection = prevItem.redo.selection
}
onChangeMode(mode)
}
}
function handleRedo(item: HistoryItem | undefined) {
if (isModeHistoryItem(item)) {
// prevent a new history item from being created
mode = item.redo.mode
// find the selection of the next history item (if any), and use that as initial selection
const items = history.items()
const index = items.findIndex((i) => i === item)
const nextItem = index !== -1 ? items[index + 1] : undefined
debug('handleRedo', { index, item, items, nextItem })
if (nextItem) {
selection = nextItem.undo.selection
}
onChangeMode(mode)
}
}
let modeMenuItems: MenuItem[]
$: modeMenuItems = [
{
Expand Down Expand Up @@ -268,6 +342,7 @@
bind:this={refTextMode}
externalContent={content}
externalSelection={selection}
{history}
{readOnly}
{indentation}
{tabSize}
Expand All @@ -279,8 +354,10 @@
{validator}
{validationParser}
{onChange}
{onSelect}
{onChangeMode}
{onSelect}
onUndo={handleUndo}
onRedo={handleRedo}
{onError}
{onFocus}
{onBlur}
Expand All @@ -293,6 +370,7 @@
bind:this={refTableMode}
externalContent={content}
externalSelection={selection}
{history}
{readOnly}
{mainMenuBar}
{escapeControlCharacters}
Expand All @@ -306,6 +384,8 @@
{onChange}
{onChangeMode}
{onSelect}
onUndo={handleUndo}
onRedo={handleRedo}
{onRenderValue}
{onFocus}
{onBlur}
Expand All @@ -321,6 +401,7 @@
bind:this={refTreeMode}
externalContent={content}
externalSelection={selection}
{history}
{readOnly}
{indentation}
{mainMenuBar}
Expand All @@ -336,6 +417,8 @@
{onChange}
{onChangeMode}
{onSelect}
onUndo={handleUndo}
onRedo={handleRedo}
{onRenderValue}
{onClassName}
{onFocus}
Expand Down
Loading

0 comments on commit b5f11ca

Please sign in to comment.