From 6dd69cdd5e2d7e4b6591d8cd032f50cf89e83693 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Fri, 21 Feb 2025 14:14:56 +0100 Subject: [PATCH] feat: change most methods like `set`, `update`, `expand`, and `collapse` to synchrounous, fixing #499 (#524) --- README.md | 20 ++++---- src/lib/components/JSONEditor.svelte | 46 ++++++++++--------- src/lib/components/controls/SearchBox.svelte | 8 ++-- .../components/modals/JSONEditorModal.svelte | 15 +++--- .../modes/tablemode/TableMode.svelte | 16 +++---- .../components/modes/textmode/TextMode.svelte | 12 +++-- .../components/modes/treemode/TreeMode.svelte | 21 +++++---- src/lib/index-vanilla.ts | 8 ++-- src/routes/development/+page.svelte | 5 +- 9 files changed, 82 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 0a575e4a..6b28ef04 100644 --- a/README.md +++ b/README.md @@ -688,7 +688,7 @@ Get the current JSON document. #### set ```ts -JSONEditor.prototype.set(content: Content): Promise +JSONEditor.prototype.set(content: Content): void ``` Replace the current content. Will reset the state of the editor. See also method `update(content)`. @@ -696,7 +696,7 @@ Replace the current content. Will reset the state of the editor. See also method #### update ```ts -JSONEditor.prototype.update(content: Content): Promise +JSONEditor.prototype.update(content: Content): void ``` Update the loaded content, keeping the state of the editor (like expanded objects). You can also call `editor.updateProps({ content })`. See also method `set(content)`. @@ -706,7 +706,7 @@ Update the loaded content, keeping the state of the editor (like expanded object #### patch ```ts -JSONEditor.prototype.patch(operations: JSONPatchDocument) : Promise +JSONEditor.prototype.patch(operations: JSONPatchDocument) : JSONPatchResult ``` Apply a JSON patch document to update the contents of the JSON document. A JSON patch document is a list with JSON Patch operations. @@ -716,7 +716,7 @@ Apply a JSON patch document to update the contents of the JSON document. A JSON #### updateProps ```ts -JSONEditor.prototype.updateProps(props: Object): Promise +JSONEditor.prototype.updateProps(props: Object): void ``` Tpdate some or all of the properties. Updated `content` can be passed too; this is equivalent to calling `update(content)`. Example: @@ -730,7 +730,7 @@ editor.updateProps({ #### expand ```ts -JSONEditor.prototype.expand(path: JSONPath, callback?: (relativePath: JSONPath) => boolean = expandSelf): Promise +JSONEditor.prototype.expand(path: JSONPath, callback?: (relativePath: JSONPath) => boolean = expandSelf): void ``` Expand paths in the editor. All nodes along the provided `path` will be expanded and become visible (rendered). So for example collapsed sections of an array will be expanded. Using the optional `callback`, the node itself and some or all of its nested child nodes can be expanded too. The `callback` function only iterates over the visible sections of an array and not over any of the collapsed sections. By default, the first 100 items of an array are visible and rendered. @@ -755,7 +755,7 @@ The library exports a couple of utility functions for commonly used `callback` f ### collapse ```ts -JSONEditor.prototype.collapse(path: JSONPath, recursive?: boolean = false): Promise +JSONEditor.prototype.collapse(path: JSONPath, recursive?: boolean = false): void ``` Collapse a path in the editor. When `recursive` is `true`, all nested objects and arrays will be collapsed too. The default value of `recursive` is `false`. @@ -763,7 +763,7 @@ Collapse a path in the editor. When `recursive` is `true`, all nested objects an #### transform ```ts -JSONEditor.prototype.transform({ id?: string, rootPath?: [], onTransform: ({ operations: JSONPatchDocument, json: unknown, transformedJson: unknown }) => void, onClose: () => void }) +JSONEditor.prototype.transform(options?: { id?: string, rootPath?: [], onTransform: ({ operations: JSONPatchDocument, json: unknown, transformedJson: unknown }) => void, onClose: () => void }) ``` Programmatically trigger clicking of the transform button in the main menu, opening the transform model. If a callback `onTransform` is provided, it will replace the build-in logic to apply a transform, allowing you to process the transform operations in an alternative way. If provided, `onClose` callback will trigger when the transform modal closes, both after the user clicked apply or cancel. If an `id` is provided, the transform modal will load the previous status of this `id` instead of the status of the editors transform modal. @@ -774,7 +774,7 @@ Programmatically trigger clicking of the transform button in the main menu, open JSONEditor.prototype.scrollTo(path: JSONPath): Promise ``` -Scroll the editor vertically such that the specified path comes into view. Only applicable to modes `tree` and `table`. The path will be expanded when needed. The returned Promise is resolved after scrolling is finished. +Scroll the editor vertically such that the specified path comes into view. Only applicable to modes `tree` and `table`. The path will be expanded when needed. The returned promise is resolved after scrolling is finished. #### findElement @@ -787,7 +787,7 @@ Find the DOM element of a given path. Returns `undefined` when not found. #### acceptAutoRepair ```ts -JSONEditor.prototype.acceptAutoRepair(): Promise +JSONEditor.prototype.acceptAutoRepair(): Content ``` In tree mode, invalid JSON is automatically repaired when loaded. When the repair was successful, the repaired contents are rendered but not yet applied to the document itself until the user clicks "Ok" or starts editing the data. Instead of accepting the repair, the user can also click "Repair manually instead". Invoking `.acceptAutoRepair()` will programmatically accept the repair. This will trigger an update, and the method itself also returns the updated contents. In case of `text` mode or when the editor is not in an "accept auto repair" status, nothing will happen, and the contents will be returned as is. @@ -819,7 +819,7 @@ Change the current selection. See also option `selection`. #### focus ```ts -JSONEditor.prototype.focus(): Promise +JSONEditor.prototype.focus(): void ``` Give the editor focus. diff --git a/src/lib/components/JSONEditor.svelte b/src/lib/components/JSONEditor.svelte index 3fb4d5a1..d1238c46 100644 --- a/src/lib/components/JSONEditor.svelte +++ b/src/lib/components/JSONEditor.svelte @@ -7,7 +7,7 @@ import AbsolutePopup from './modals/popup/AbsolutePopup.svelte' import { jsonQueryLanguage } from '$lib/plugins/query/jsonQueryLanguage.js' import { renderValue } from '$lib/plugins/value/renderValue.js' - import { tick } from 'svelte' + import { flushSync } from 'svelte' import TransformModal from './modals/TransformModal.svelte' import type { Content, @@ -171,7 +171,7 @@ return content } - export async function set(newContent: Content): Promise { + export function set(newContent: Content): void { debug('set') const contentError = validateContentType(newContent) @@ -184,9 +184,11 @@ // update content *after* re-render, so that the new editor will trigger an onChange event content = newContent + + flushSync() } - export async function update(updatedContent: Content): Promise { + export function update(updatedContent: Content): void { debug('update') const contentError = validateContentType(updatedContent) @@ -196,42 +198,44 @@ content = updatedContent - await tick() // await rerender + flushSync() } - export async function patch(operations: JSONPatchDocument): Promise { + export function patch(operations: JSONPatchDocument): JSONPatchResult { // Note that patch has an optional afterPatch callback. // right now we don's support this in the public API. const result = refJSONEditorRoot.patch(operations) - await tick() // await rerender + flushSync() return result } - export async function select(newSelection: JSONEditorSelection | undefined) { + export function select(newSelection: JSONEditorSelection | undefined): void { selection = newSelection - await tick() // await rerender + flushSync() } - export async function expand(path: JSONPath, callback?: OnExpand): Promise { + export function expand(path: JSONPath, callback?: OnExpand): void { refJSONEditorRoot.expand(path, callback) - await tick() // await rerender + flushSync() } - export async function collapse(path: JSONPath, recursive = false): Promise { + export function collapse(path: JSONPath, recursive = false): void { refJSONEditorRoot.collapse(path, recursive) - await tick() // await rerender + flushSync() } /** * Open the transform modal */ - export function transform(options: TransformModalOptions): void { + export function transform(options: TransformModalOptions = {}): void { refJSONEditorRoot.transform(options) + + flushSync() } /** @@ -253,10 +257,10 @@ * mode or when the editor is not in an "accept auto repair" status, nothing * will happen, and the contents will be returned as is. */ - export async function acceptAutoRepair(): Promise { + export function acceptAutoRepair(): Content { const content = refJSONEditorRoot.acceptAutoRepair() - await tick() // await rerender + flushSync() return content } @@ -269,17 +273,17 @@ return refJSONEditorRoot.findElement(path) } - export async function focus(): Promise { + export function focus(): void { refJSONEditorRoot.focus() - await tick() // await rerender + flushSync() } export async function refresh(): Promise { await refJSONEditorRoot.refresh() } - export async function updateProps(props: JSONEditorPropsOptional): Promise { + export function updateProps(props: JSONEditorPropsOptional): void { const names = Object.keys(props) as (keyof JSONEditorPropsOptional)[] for (const name of names) { @@ -389,7 +393,7 @@ debug(`Unknown property "${name}"`) } - await tick() // await rerender + flushSync() } export async function destroy() { @@ -436,8 +440,8 @@ mode = newMode - await tick() - await focus() + flushSync() + focus() onChangeMode(newMode) } diff --git a/src/lib/components/controls/SearchBox.svelte b/src/lib/components/controls/SearchBox.svelte index 4acb4699..30f47c38 100644 --- a/src/lib/components/controls/SearchBox.svelte +++ b/src/lib/components/controls/SearchBox.svelte @@ -25,7 +25,7 @@ updateSearchResult } from '$lib/logic/search.js' import type { JSONPath } from 'immutable-json-patch' - import { tick } from 'svelte' + import { flushSync } from 'svelte' const debug = createDebug('jsoneditor:SearchBox') @@ -125,8 +125,8 @@ } async function handlePaste() { - await tick() - setTimeout(() => applyChangedSearchTextDebounced.flush()) + flushSync() + await applyChangedSearchTextDebounced.flush() } async function handleReplace() { @@ -161,7 +161,7 @@ })) // immediately trigger updating the search results - await tick() + flushSync() await applyChangedJsonDebounced.flush() // focus to the next search result diff --git a/src/lib/components/modals/JSONEditorModal.svelte b/src/lib/components/modals/JSONEditorModal.svelte index b9ec7a70..969e27b5 100644 --- a/src/lib/components/modals/JSONEditorModal.svelte +++ b/src/lib/components/modals/JSONEditorModal.svelte @@ -1,7 +1,7 @@