Skip to content

Commit

Permalink
feat: custom rendering with onRenderValue, performance improvements, …
Browse files Browse the repository at this point in the history
…and fixes

* chore: reduce JSONValue to rendering a list with value render components based on conditions

* chore: move ajv plugin into plugins/validator

* feat: implement `renderValue` callback and use it in `JSONValue` (WIP)

* fix: component JSONKey was broken during refactoring

* feat: implement `onRenderValue` callback

* chore: fix broken import after merge

* chore: fix a svelte console warning

* docs: create example demonstrating onRenderValue

* fix: improve performance by passing a recursive selection object

* feat: implement EnumValue and renderJSONSchemaEnum (WIP)

* fix: create a `svelte-jsoneditor` alias in the vite config and use that in the examples

* fix: handle focus of EnumValue, colorize text

* chore: update all dependencies

* fix: multiple context menu buttons visible in case of multi select

* fix: make custom validation example more robust

* chore: improve custom validation example a bit

* fix: move selection to value after editing a key
  • Loading branch information
josdejong authored Dec 4, 2021
1 parent b9727fa commit 635f542
Show file tree
Hide file tree
Showing 48 changed files with 1,714 additions and 347 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,23 @@ const editor = new JSONEditor({
- `onChangeMode(mode: string)`. Invoked when the mode is changed.
- `onClassName(path: Path, value: any): string | undefined`.
Add a custom class name to specific nodes, based on their path and/or value.
- `onRenderValue(props: RenderValueProps) : RenderValueConstructor[]`

_EXPERIMENTAL! This API will most likely change in future versions._

Customize rendering of the values. By default, `renderValue` is used, which renders a value as an editable div and depending on the value can also render a boolean toggle, a color picker, and a timestamp tag. Multiple components can be rendered alongside each other, like the boolean toggle and color picker being rendered left from the editable div. Built in value renderer components: `EditableValue`, `ReadonlyValue`, `BooleanToggle`, `ColorPicker`, `TimestampTag`, `EnumValue`.

For JSON Schema enums, there is a value renderer `renderJSONSchemaEnum` which renders enums using the `EnumValue` component. This can be used like:

```js
import { renderJSONSchemaEnum, renderValue } from 'svelte-jsoneditor'

function onRenderValue(props) {
// use the enum renderer, and fallback on the default renderer
return renderJSONSchemaEnum(props, schema, schemaRefs) || renderValue(props)
}
```

- `onRenderMenu(mode: string, items: Array) : Array | undefined`.
Callback which can be used to make changes to the menu items. New items can
be added, or existing items can be removed or reorganized. When the function
Expand Down Expand Up @@ -341,6 +358,24 @@ type QueryLanguageOptions = {
paths?: string[][]
}
}
type RenderValueProps = {
path: Path
value: JSON
readOnly: boolean
selection?: Selection
isSelected: boolean
isEditing: boolean
searchResult?: SearchResultItem
onPatch: (patch: JSONPatchDocument, newSelection: Selection | null) => void
onPasteJson: (pastedJson: { path: Path; contents: JSON }) => void
onSelect: (selection: Selection) => void
}
type RenderValueConstructor = {
component: SvelteComponentConstructor
props: Object
}
```

## Develop
Expand Down
240 changes: 126 additions & 114 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@
"ace-builds": "^1.4.13",
"ajv": "^8.8.2",
"classnames": "^2.3.1",
"diff-sequences": "^27.0.6",
"diff-sequences": "^27.4.0",
"immutable-json-patch": "^1.1.2",
"jmespath": "^0.15.0",
"json-source-map": "^0.6.1",
"jsonrepair": "^2.2.1",
"lodash-es": "^4.17.21",
"natural-compare-lite": "^1.4.0",
"sass": "^1.43.4",
"sass": "^1.44.0",
"svelte-awesome": "^2.4.2",
"svelte-select": "^4.4.5",
"svelte-select": "^4.4.6",
"svelte-simple-modal": "^1.1.1",
"vanilla-picker": "^2.12.1"
},
Expand All @@ -52,20 +52,20 @@
"@rollup/plugin-json": "4.1.0",
"@rollup/plugin-node-resolve": "13.0.6",
"@rollup/plugin-typescript": "8.3.0",
"@sveltejs/kit": "1.0.0-next.199",
"@sveltejs/kit": "1.0.0-next.201",
"@types/cookie": "0.4.1",
"@types/lodash-es": "4.17.5",
"@types/mocha": "9.0.0",
"@typescript-eslint/eslint-plugin": "5.4.0",
"@typescript-eslint/parser": "5.4.0",
"@typescript-eslint/eslint-plugin": "5.5.0",
"@typescript-eslint/parser": "5.5.0",
"eslint": "8.3.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-svelte3": "3.2.1",
"husky": "7.0.4",
"mocha": "9.1.3",
"prettier": "2.4.1",
"prettier": "2.5.0",
"prettier-plugin-svelte": "2.5.0",
"rollup": "2.59.0",
"rollup": "2.60.2",
"rollup-plugin-svelte": "7.1.0",
"rollup-plugin-terser": "7.0.2",
"standard-version": "9.3.2",
Expand Down
6 changes: 5 additions & 1 deletion src/lib/components/JSONEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import CodeMode from './modes/codemode/CodeMode.svelte'
import TreeMode from './modes/treemode/TreeMode.svelte'
import { javascriptQueryLanguage } from '../plugins/query/javascriptQueryLanguage.js'
import { renderValue } from '$lib/plugins/value/renderValue'
// TODO: document how to enable debugging in the readme: localStorage.debug="jsoneditor:*", then reload
const debug = createDebug('jsoneditor:Main')
Expand Down Expand Up @@ -46,6 +47,9 @@
/** @type {((content: Content, previousContent: Content, patchResult: JSONPatchResult | null) => void) | null} */
export let onChange = null
/** @type {(props: RenderValueProps) => RenderValueConstructor[]} */
export let onRenderValue = renderValue
export let onClassName = () => {
// no op by default
}
Expand Down Expand Up @@ -297,7 +301,6 @@
{readOnly}
{indentation}
{mainMenuBar}
{navigationBar}
{validator}
{queryLanguages}
{queryLanguageId}
Expand Down Expand Up @@ -325,6 +328,7 @@
{onError}
onChange={handleChange}
onRequestRepair={handleRequestRepair}
{onRenderValue}
{onClassName}
onFocus={handleFocus}
onBlur={handleBlur}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import '../../../../styles';
@import '../shared.scss';
@import '../../styles';
@import './EditableDivShared';

// for key and value
div.jse-editable-div {
Expand All @@ -11,6 +11,7 @@ div.jse-editable-div {
outline: none;
border-radius: 1px;
vertical-align: top;
overflow-wrap: anywhere;

&[contenteditable='true'] {
outline: 2px solid $edit-border-color;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import { onDestroy, onMount } from 'svelte'
import { getPlainText, setCursorToEnd, setPlainText } from '$lib/utils/domUtils'
import { keyComboFromEvent } from '$lib/utils/keyBindings'
import { createDebug } from '../../../../utils/debug'
import { createDebug } from '$lib/utils/debug'
import { noop } from 'lodash-es'
const debug = createDebug('jsoneditor:ValueEditor')
const debug = createDebug('jsoneditor:EditableDiv')
export let value
export let onChange
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import '../../../styles';
@import '../../styles';

.value {
&.string {
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/modals/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
vertical-align: middle;
}

button.config,
button.close {
button {
border: none;
background: transparent;
min-width: 32px;
Expand Down
1 change: 0 additions & 1 deletion src/lib/components/modes/treemode/JSONKey.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@import '../../../styles';
@import 'shared';

.key {
display: inline-block;
Expand Down
12 changes: 6 additions & 6 deletions src/lib/components/modes/treemode/JSONKey.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

<script>
import classnames from 'classnames'
import { isEqual } from 'lodash-es'
import { initial } from 'lodash-es'
import { SELECTION_TYPE } from '$lib/logic/selection'
import SearchResultHighlighter from './highlight/SearchResultHighlighter.svelte'
import EditableDiv from './value/EditableDiv.svelte'
import EditableDiv from '../../controls/EditableDiv.svelte'
export let path
export let key
Expand All @@ -15,8 +15,7 @@
export let onSelect
export let searchResult
$: selectedKey =
selection && selection.type === SELECTION_TYPE.KEY ? isEqual(selection.focusPath, path) : false
$: selectedKey = selection && selection.type === SELECTION_TYPE.KEY
$: editKey = !readOnly && selectedKey && selection && selection.edit === true
function handleKeyDoubleClick(event) {
Expand All @@ -33,9 +32,10 @@
}
function handleChangeValue(newKey) {
onUpdateKey(key, newKey)
const updatedKey = onUpdateKey(key, newKey)
const updatedPath = initial(path).concat(updatedKey)
onSelect({ type: SELECTION_TYPE.KEY, path, next: true })
onSelect({ type: SELECTION_TYPE.KEY, path: updatedPath, next: true })
}
function handleCancelChange() {
Expand Down
Loading

0 comments on commit 635f542

Please sign in to comment.