
Компонент реагирования для редактирования или просмотра данных JSON/Object

Важный
Нарушение изменений:
theme . Встроенные темы должны теперь импортироваться отдельно и передаваться, а не просто называть тему как строку. Это лучше для устранения деревьев, поэтому неиспользованные темы не будут связаны с вашей сборкой. Увидеть темы и стилиsetData и не использовать onUpdate для обновления ваших данных извне. См. Управляющее состояние. npm i json-edit-react
или
yarn add json-edit-react
import { JsonEditor } from 'json-edit-react'
// In your React component:
return
< JsonEditor
data = { jsonData }
setData = { setJsonData } // optional
{ ... otherProps } /> (для конечного пользователя)
Это довольно самостоятельно (нажмите кнопку «Редактировать», чтобы редактировать и т. Д.), Но есть несколько не очень очевидных способов взаимодействия с редактором:
Cmd/Ctrl/Shift-Enter , чтобы добавить новую строку ( Enter представляет значение)Enter для новой строки и Cmd/Ctrl/Shift-Enter для отправкиEscape , чтобы отменить редактированиеCmd/Ctrl скопирует путь к выбранному узлу, а не его значениюjsonParse Prop. Единственным необходимым значением являются data (хотя вам необходимо предоставить метод setData для обновления ваших данных).
| проп | тип | по умолчанию | описание |
|---|---|---|---|
data | object|array | Данные, которые будут отображаться / отредактированы | |
setData | object|array => void | Метод обновления объекта data . См. Управление состоянием ниже для дополнительных заметок. | |
rootName | string | "data" | Имя для отображения в редакторе как корень объекта данных. |
onUpdate | UpdateFunction | Функция для запуска всякий раз, когда обновляется значение (редактировать, удалить или добавить) в редакторе. См. Функции обновления. | |
onEdit | UpdateFunction | Функция для запуска всякий раз, когда значение отредактируется . | |
onDelete | UpdateFunction | Функция для запуска всякий раз, когда значение удаляется . | |
onAdd | UpdateFunction | Функция для запуска всякий раз, когда добавляется новое свойство. | |
onChange | OnChangeFunction | Функция для изменения/ограничения пользовательского ввода по мере их ввода - см. Функции OnChange. | |
onError | OnErrorFunction | Функция для запуска всякий раз, когда компонент сообщает об ошибке - см. OnerrorRorfunction. | |
showErrorMessages | boolean | true | Независимо от того, должен ли компонент отображать свои собственные сообщения об ошибках (вы, вероятно, захотите отключить это, только если вы предоставили свою собственную функцию onError ) |
enableClipboard | boolean|CopyFunction | true | Чтобы включить кнопку «Скопировать в буфер обмена» в пользовательском интерфейсе. Если функция предоставлена, предполагается true , и эта функция будет выполнена, когда будет скопирован элемент. |
indent | number | 3 | Укажите количество вдавливания для каждого уровня гнездования в отображаемых данных. |
collapse | boolean|number|FilterFunction | false | Определяет, какие узлы дерева JSON будут отображаться «открытыми» в пользовательском интерфейсе при нагрузке. Если boolean , это будет либо все, либо нет. number указывает глубину гнездования, после которой узлы будут закрыты. Для более тонкого управления может быть предоставлена функция - см. Функции фильтра. |
collapseAnimationTime | number | 300 | Время (в миллисекундах) для переходной анимации при складывании узлов коллекции. |
restrictEdit | boolean|FilterFunction | false | Если true , редактирование не допускается. Функция может быть предоставлена для большей специфики - см. Функции фильтра |
restrictDelete | boolean|FilterFunction | false | Как и в случае restrictEdit но для удаления |
restrictAdd | boolean|FilterFunction | false | Как и в случае restrictEdit но для добавления новых свойств |
restrictTypeSelection | boolean|DataType[]|TypeFilterFunction | true | Для ограничения типов данных пользователь может выбрать. Может быть список типов данных (например, [ 'string', 'number', 'boolean', 'array', 'object', 'null' ] ) или логического. Функция может быть предоставлена - она должна принимать тот же вход, что и вышеупомянутая FilterFunction , но выход должен быть boolean | DataType[] . |
restrictDrag | boolean|FilterFunction | true | Установить на false , чтобы включить функциональность перетаскивания. Смотрите Drag-n-Drop |
searchText | string | undefined | Видимость данных будет отфильтрована путем сопоставления с значением, используя метод, определенный ниже в searchFilter |
searchFilter | "key"|"value"|"all"|SearchFilterFunction | undefined | Определите, как searchText должен быть сопоставлен, чтобы фильтровать видимые элементы. Смотрите поиск/фильтрация |
searchDebounceTime | number | 350 | Дебютировать время при изменении searchText |
keySort | boolean|CompareFunction | false | Если true , ключи объектов будут заказаны (с помощью default js .sort() ). Функция сравнения также может быть предоставлена для определения поведения сортировки. |
showArrayIndices | boolean | true | Чтобы отображать индекс (в качестве ключа свойства) для элементов массива. |
showStringQuotes | boolean | true | Остановка значений строки в «кавычках». |
showCollectionCount | boolean|"when-closed" | true | Чтобы отображать количество элементов в каждой коллекции (объект или массив). |
defaultValue | any|DefaultValueFilterFunction | null | Когда добавляется новое свойство, оно инициализируется этим значением. Функция может быть обеспечена почти тем же входом, что и FilterFunction S, но должна вывести значение. Это позволяет использовать другое значение по умолчанию в зависимости от состояния данных (например, по умолчанию для верхнего уровня является объектом, но строка в другом месте.) |
stringTruncate | number | 250 | Значения строки дольше, чем это много символов будет отображаться усечено (с ... ). Полная строка всегда будет видна при редактировании. |
translations | LocalisedStrings объекты объекта | { } | Строки пользовательского интерфейса (например, сообщения об ошибках) могут быть переведены путем передачи объекта, содержащего локализованные строковые значения (их только). См. Локализацию |
theme | ThemeInput | default | Либо одна из встроенных тем (импортируется отдельно), либо объект, указывающий некоторые или все свойства темы. Увидеть темы. |
className | string | Название класса CSS для применения к компоненту. В большинстве случаев указание свойств theme будет более простым. | |
id | string | Имя для атрибута HTML id в основном контейнере компонента. | |
icons | {[iconName]: JSX.Element, ... } | { } | Замените встроенные значки, указав их здесь. Увидеть темы. |
minWidth | number|string (значение CSS) | 250 | Минимальная ширина для контейнера редактора. |
maxWidth | number|string (значение CSS) | 600 | Максимальная ширина для контейнера редактора. |
rootFontSize | number|string (значение CSS) | 16px | «Базовый» размер шрифта, из которого получаются все остальные Sizings (в em S). Изменив это, вы масштабируете весь компонент. контейнер. |
customNodeDefinitions | CustomNodeDefinition[] | Вы можете предоставить индивидуальные компоненты для переопределения определенных узлов в дереве данных в соответствии с функцией условия. Смотрите пользовательские узлы для более подробной информации. (Простой пользовательский компонент для превращения строк URL -адреса в активные ссылки приведен в основном пакете - см. Здесь) | |
customText | CustomTextDefinitions | В дополнение к локализации текстовых строк компонента, вы также можете динамически изменить их, в зависимости от данных. Смотрите пользовательский текст для более подробной информации. | |
customButtons | CustomButtonDefinition[] | [] | Вы можете добавить свои собственные кнопки на панель «Редактировать кнопки», если вы хотите выполнить пользовательскую работу на данных. Смотрите пользовательские кнопки |
jsonParse | (input: string) => JsonData | JSON.parse | При редактировании блока JSON напрямую вы можете позволить какой -то «более низкий» вход - например, «одиночные цитаты», запятые или имена поля. В этом случае вы можете предоставить сторонний метод анализа JSON. Я рекомендую json5, что используется в демонстрации |
jsonStringify | (data: JsonData) => string | (data) => JSON.stringify(data, null, 2) | Точно так же вы можете переопределить презентацию строки JSON по умолчанию при начале редактирования JSON. Вы можете предоставить различные параметры форматирования для нативного JSON.stringify() или предоставить сторонний вариант, например, вышеупомянутый JSON5. |
errorMessageTimeout | number | 2500 | Время (в миллисекундах) для отображения сообщения об ошибке в пользовательском интерфейсе. |
keyboardControls | KeyboardControls | Как объяснено выше | Переопределите некоторые или все элементы управления клавиатурой. Смотрите настройку клавиатуры для деталей. |
insertAtTop | boolean| "object | "array" | false | Если true , вставляют новые значения вверху, а не снизу. Можно установить поведение только для массивов или объектов, настроив на "object" или "array" соответственно. |
Рекомендуется, чтобы вы управляли состоянием data самостоятельно вне этого компонента - просто передайте методу setData , который называется внутренне для обновления ваших data . Тем не менее, это не обязательно - если вы не предоставите метод setData , данные будут управляться внутри, что будет хорошо, если вы ничего не делаете с данными. Альтернатива состоит в том, чтобы использовать функции обновления для обновления ваших data извне, но это не рекомендуется, за исключением особых обстоятельств, поскольку вы можете столкнуться с проблемами, удерживающими ваши данные в синхронизации с внутренним состоянием (что отображается), а также ненужные повторные рестораны. Функции обновления должны быть в идеале использоваться только для реализации побочных эффектов, проверки ошибок или мутирования данных, прежде чем установить их с setData .
Можно предоставить обратный вызов, который должен быть выполнен всякий раз, когда происходит обновление данных (редактирование, удаление или добавление). Возможно, вы захотите использовать это для обновления какого -то внешнего состояния, сделать вызов API, изменить данные перед его сохранением или проверить структуру данных на схеме JSON. Если вы хотите одну и ту же функцию для всех обновлений, то только что опоры onUpdate достаточно. Однако, если вам потребуется что -то другое для редактирования, удаления и сложения, вы можете предоставить отдельные функции обновления через реквизит onEdit , onDelete и onAdd .
Функция получит следующий объект в качестве параметра:
{
newData , // data state after update
currentData , // data state before update
newValue , // the new value of the property being updated
currentValue , // the current value of the property being updated
name , // name of the property being updated
path // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name")
}Функция не может ничего вернуть (в этом случае данные обновляются нормально) или значение для представления успеха/сбоя, значения ошибки или модифицированных данных. Возвратное значение может быть одним из следующих, и соответственно обрабатывается:
true / void / undefined : данные продолжают обновлять как обычноfalse : рассматривает обновление как ошибку, поэтому данные не обновляются (возвращается к предыдущему значению), а общее сообщение об ошибке отображается в пользовательском интерфейсеstring : также считается ошибкой, поэтому нет обновления данных, но сообщение об ошибке пользовательского интерфейса будет вашей предоставленной строкой[ "value", <value> ] : сообщает компоненту использование возвращаемого <value> вместо входных данных. Вы можете использовать это для автоматического изменения ввода пользователя - например, сортировки массива или вставки поле TimeStamp в объект.[ "error", <value> ] : так же, как string , но в более длинном формате кортежей. Подобно функциям обновления, функция onChange выполняется как изменение ввода пользователя. Вы можете использовать это для ограничения или ограничения пользовательского ввода - например, ограничения чисел положительными значениями или предотвращение разрывов строк в строках. Функция должна вернуть значение, чтобы обновить поле пользователя ввода, поэтому, если никаких изменений не внесено, просто верните его немодифицированным.
Входной объект аналогичен входу функции обновления, но без поля newData (поскольку эта операция происходит до обновления данных).
// in <JsonEditor /> props
onChange = ( { newValue , name } ) => {
if ( name === "age" && newValue < 0 ) return 0 ;
if ( name === "age" && newValue > 100 ) return 100 ;
return newValue
} onChange = ( { newValue , name } ) => {
if ( name === 'name' && typeof newValue === "string" )
return newValue . replace ( / [^a-zA-Zs]|n|r / gm , '' ) ;
return newValue ;
} Обычно компонент отображает простые сообщения об ошибках, когда обнаруживается условие ошибки (например, ввод ввода JSON, дубликаты или пользовательские ошибки, возвращаемые функциями onUpdate )). Тем не менее, вы можете предоставить свой собственный обратный вызов onError , чтобы реализовать свой собственный пользовательский интерфейс или запустить дополнительные побочные эффекты. (В первом случае вы, вероятно, тоже захотите отключить опору showErrorMessages .) Вход в обратный вызов аналогичен другим обратным вызовам:
{
currentData , // data state before update
currentValue , // the current value of the property being updated
errorValue , // the erroneous value that failed to update the property
name , // name of the property being updated
path , // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name"),
error : {
code , // one of 'UPDATE_ERROR' | 'DELETE_ERROR' | 'ADD_ERROR' | 'INVALID_JSON' | 'KEY_EXISTS'
message // the (localised) error message that would be displayed
}
}(Пример пользовательского пользовательского интерфейса ошибки можно увидеть в демонстрации с набором данных «Пользовательские узлы» - когда вы вводите недопустимый ввод JSON ввод «тост», отображается вместо нормального сообщения об ошибке компонента.)
Аналогичный обратный вызов выполняется всякий раз, когда элемент копируется в буфер обмена (если передается в опору enableClipboard ), но с другим входным параметром:
key // name of the property being copied
path // path to the property
value // the value copied to the clipboard
type // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
stringValue // A nicely stringified version of `value`
// (i.e. what the clipboard actually receives)Поскольку при нажатии на «копию» очень мало отзывов пользователей, хорошей идеей будет представление о каком -то уведомлении в этом обратном вызове.
В дополнение к кнопкам «Копировать», «Редактировать» и «Удалить», которые появляются по каждому значению, вы можете добавить свои собственные кнопки, если вам нужно разрешить некоторые пользовательские операции в данных. Предоставьте массив определений кнопок в предложении customButtons , в следующей структуре определения:
{
Element : React . FC ,
onClick : ( nodeData : NodeData , e : React . MouseEvent ) => void
} Где NodeData - это та же структура данных, полученную предыдущими «функциями обновления».
Вы можете контролировать, какие узлы структуры данных можно отредактировать, удалить или добавить или изменить их тип данных путем передачи функций фильтра. Они будут вызваны на каждое свойство в данных, а атрибут будет применен в зависимости от того, возвращает ли функция true или false ( true средства не могут быть отредактированы).
Функция получает следующий объект:
{
key , // name of the property
path , // path to the property (as an array of property keys)
level , // depth of the property (with 0 being the root)
index , // index of the node within its collection (based on display order)
value , // value of the property
size , // if a collection (object, array), the number of items (null for non-collections)
parentData , // parent object containing the current node
fullData // the full (overall) data object
collapsed // whether or not the current node is in a
// "collapsed" state (only for Collection nodes)
} Функция фильтра также доступна и для collapse , так что вы можете появиться с открытыми открытыми коллекциями с глубоко вставленными коллекциями, в то время как обрушив все остальное.
Для ограничения типов данных функция фильтра (типа) немного более сложна. Ввод одинаков, но выход может быть либо boolean , который ограничивает доступные типы для данного узла либо всем , либо нет ), либо массивом типов данных, которые будут ограничены. Доступные значения:
"string""number""boolean""null""object""array" Для редактирования ключевых имен объектов нет конкретной функции ограничения, но они должны вернуть true как для restrictEdit , так и restrictDelete (и restrictAdd для коллекций), поскольку изменение имени ключа эквивалентно удалению свойства и добавлению нового.
Вы также можете установить динамическое значение по умолчанию, передавая функцию фильтра в опору defaultValue - вход такой же, как и выше, но также принимает новое значение key в качестве второго параметра, поэтому новое значение может зависеть от добавленного нового ключа.
Использование всех этих ограниченных фильтров может позволить вам обеспечить соблюдение достаточно сложной схемы данных.
// in <JsonEditor /> props
restrictEdit = { ( { level } ) => level === 0 }id поля: restrictEdit = { ( { key } ) => key === "id" }
// You'd probably want to include this in `restrictDelete` as well restrictDelete = { ( { size } ) => size !== null } restrictAdd = { ( { key } ) => key !== "address" && key !== "users" }
// "Adding" is irrelevant for non-collection nodesstring могут быть изменены только на строки или объекты (для гнездования)null не допускается нигдеboolean ценности должны оставаться логическими restrictTypeSelection = { ( { path , value } ) => {
if ( path . includes ( 'user' ) ) return [ 'string' , 'number' , 'boolean' ]
if ( typeof value === 'boolean' ) return false
if ( typeof value === 'string' ) return [ 'string' , 'object' ]
return [ 'string' , 'number' , 'boolean' , 'array' , 'object' ] // no "null"
} }Помимо динамического управления доступом к различным инструментам редактирования, как описано выше, можно выполнить полную проверку схемы JSON, создав функцию обновления, которая передает данные в библиотеку валидации схемы 3-й части (например, AJV). Затем это отклонит любой недопустимый вход и отобразит ошибку в пользовательском интерфейсе (или через пользовательскую функцию Onerror). Вы можете увидеть пример этого в демонстрации с набором данных «проверка схемы JSON» (и набор данных «пользовательские узлы»).
Примером функции проверки onUpdate (с использованием AJV) может быть что -то вроде этого:
import { JsonEditor } from 'json-edit-react'
import Ajv from 'ajv'
import schema from './my-json-schema.json'
const ajv = new Ajv ( )
const validate = ajv . compile ( schema )
/// Etc....
// In the React component:
return
< JsonEditor
data = { jsonData }
onUpdate = { ( { newData } ) => {
const valid = validate ( newData )
if ( ! valid ) {
console . log ( 'Errors' , validate . errors )
const errorMessage = validate . errors
?. map ( ( error ) => ` ${ error . instancePath } ${ error . instancePath ? ': ' : '' } ${ error . message } ` )
. join ( 'n' )
// Send detailed error message to an external UI element, such as a "Toast" notification
displayError ( {
title : 'Not compliant with JSON Schema' ,
description : errorMessage ,
status : 'error' ,
} )
// This string returned to and displayed in json-edit-react UI
return 'JSON Schema error'
}
} }
{ ... otherProps } />Примечание
Это новая функция и должна считаться «экспериментальной». Пожалуйста, предоставьте обратную связь или предложения, чтобы помочь улучшить его.
Свойство restrictDrag контролирует, какие элементы (если таковые имеются) можно перетащить в новые позиции. По умолчанию это выключено , поэтому вы должны установить restrictDrag = false чтобы включить эту функциональность. Как и приведенные выше ограничения редактирования, это свойство также может выполнять функцию фильтра для мелкозернистого управления. Есть несколько дополнительных соображений, хотя:
jsonb (бинарный json), порядок ключей является бессмысленным, поэтому в следующий раз, когда объект загружен, ключи будут перечислены в алфавитном порядке.restrictDrag применяется к исходному элементу (то есть узел перетаскивается), а не к пункту назначения.restrictDelete ), так как перетаскивание узла в новый пункт назначения, по сути, просто удаление его и добавление обратно в другом месте. Отображаемые данные могут быть отфильтрованы на основе ввода поиска от пользователя. Ввод пользователя должен быть зафиксирован независимо (мы не предоставляем пользовательский интерфейс здесь) и переданы с помощью searchText Prop. Этот ввод дезантируется внутренне (время может быть установлено с помощью searchDebounceTime Prop), поэтому в этом нет необходимости. Значения, с которыми протестированы searchText , указаны с помощью searchFilter Prop. По умолчанию (не определяется searchFilter ), он будет соответствовать значениям данных (с нечувствительным к случаям частичного сопоставления-т.е. вход «ILB», сопоставит значение «bilbo»).
Вы можете указать, что должно быть сопоставлено, установив searchFilter на либо "key" (имена свойств совпадает), "value" (по умолчанию, описанное выше), либо "all" (сопоставьте как свойства, так и значения). Этого должно быть достаточно для большинства вариантов использования, но вы можете указать свою собственную SearchFilterFunction . Функция поиска та же самая подпись, что и вышеуказанная фильтровая функции, но принимает один дополнительный аргумент для searchText , т.е.
( { key , path , level , value , ... etc } : FilterFunctionInput , searchText : string ) => boolean Существуют две вспомогательные функции ( matchNode() и matchNodeKey() ), экспортируемые с пакетом, которые могут упростить создание функции поиска (это функции, используемые внутри, для "key" и "value" описанных выше). Вы можете увидеть, что они делают здесь.
Пример пользовательского функции поиска можно увидеть в демонстрации с набором данных «Список клиентов» - функция поиска совпадает по имени и имени пользователя, и делает весь объект «клиента» видимым при одном из этих совпадений, поэтому его можно использовать для поиска конкретного человека и редактирования их конкретных деталей:
( { path , fullData } , searchText ) => {
// Matches *any* node that shares a path (i.e. a descendent) with a matching name/username
if ( path ?. length >= 2 ) {
const index = path ?. [ 0 ]
return (
matchNode ( { value : fullData [ index ] . name } , searchText ) ||
matchNode ( { value : fullData [ index ] . username } , searchText )
)
} else return false
} Существует небольшой выбор встроенных тем (как видно в демонстрационном приложении). Чтобы использовать один из них, просто импортируйте его из упаковки и пропустите его в качестве предложения темы:
import { JsonEditor , githubDarkTheme } from 'json-edit-react'
// ...other imports
const MyApp = ( ) => {
const [ data , setData ] = useState ( { one : 1 , two : 2 } )
return < JsonEditor
data = { data }
setData = { setData }
theme = { githubDarkTheme }
// other props...
/>
}Следующие темы доступны в пакете (хотя реально, они существуют больше для демонстрации возможностей-я открыт для лучших встроенных тем, поэтому не стесняйтесь создавать проблему с предложениями):
githubDarkThemegithubLightThememonoDarkThememonoLightThemecandyWrapperThemepsychedelicThemeТем не менее, вы можете передать свой собственный объект темы или его часть. Структура темы заключается в следующем (это определение темы «по умолчанию»):
{
displayName : 'Default' ,
fragments : { edit : 'rgb(42, 161, 152)' } ,
styles : {
container : {
backgroundColor : '#f6f6f6' ,
fontFamily : 'monospace' ,
} ,
collection : { } ,
collectionInner : { } ,
collectionElement : { } ,
dropZone : { } ,
property : '#292929' ,
bracket : { color : 'rgb(0, 43, 54)' , fontWeight : 'bold' } ,
itemCount : { color : 'rgba(0, 0, 0, 0.3)' , fontStyle : 'italic' } ,
string : 'rgb(203, 75, 22)' ,
number : 'rgb(38, 139, 210)' ,
boolean : 'green' ,
null : { color : 'rgb(220, 50, 47)' , fontVariant : 'small-caps' , fontWeight : 'bold' } ,
input : [ '#292929' , { fontSize : '90%' } ] ,
inputHighlight : '#b3d8ff' ,
error : { fontSize : '0.8em' , color : 'red' , fontWeight : 'bold' } ,
iconCollection : 'rgb(0, 43, 54)' ,
iconEdit : 'edit' ,
iconDelete : 'rgb(203, 75, 22)' ,
iconAdd : 'edit' ,
iconCopy : 'rgb(38, 139, 210)' ,
iconOk : 'green' ,
iconCancel : 'rgb(203, 75, 22)' ,
} ,
} Свойство styles является основной, на которой можно сосредоточиться. Каждый ключ ( property , bracket , itemCount ) относится к части пользовательского интерфейса. Значение для каждого ключа либо :
string , в этом случае она интерпретируется как цвет (или цвет фона в случае container и inputHighlight )null ). Это позволяет динамически изменять стиль различных элементов на основе контента или структуры.null . (В массиве более поздние элементы имеют более высокий приоритет)Для простого примера, если вы хотите использовать тему «githubdark», но просто измените пару мелочей, вы бы указали что -то вроде этого:
// in <JsonEditor /> props
theme = { [
githubDarkTheme ,
{
iconEdit : 'grey' ,
boolean : { color : 'red' , fontStyle : 'italic' , fontWeight : 'bold' , fontSize : '80%' } ,
} ,
] } Который изменит значок «редактирование» и логические значения с этого: 
в это: 
Или вы можете создать свою собственную тему с нуля и перезаписать весь объект темы.
Итак, подводя итог, предложение theme может занять либо :
"candyWrapperTheme"fragments , styles , displayName и т. Д., Или только часть styles (на корневом уровне)[ "<themeName>, {...overrides } ]Вы можете играть в живое редактирование тем в демонстрационном приложении, выбрав «Редактировать эту тему!» Из селектора «Демо -данных» (хотя вы не сможете создавать функции в JSON).
Еще один способ стилизовать компонент - напрямую нацелиться на классы CSS. У каждого элемента в компоненте есть уникальное имя класса, поэтому вы должны иметь возможность найти их в инспекторе браузера и соответственно переопределить их. Все имена классов начинаются с префикса jer- , Eg jer-collection-header-row , jer-value-string .
Свойство fragments выше - это просто удобство, позволяющее определить повторные «фрагменты» стиля один раз, и ссылаться на использование псевдонима. Например, если вы хотите, чтобы все ваши значки были синими, немного больше и распределены, вы можете определить фрагмент, как так:
fragments: { iconAdjust : { color : "blue" , fontSize : "110%" , marginRight : "0.6em" } }Затем в объекте темы просто используйте:
{
... ,
iconEdit : "iconAdjust" ,
iconDelete : "iconAdjust" ,
iconAdd : "iconAdjust" ,
iconCopy : "iconAdjust" ,
}Затем, когда вы хотите настроить его позже, вам нужно обновить его только в одном месте!
Фрагменты также могут быть смешаны с дополнительными свойствами и даже другими фрагментами, как SO:
iconEdit: [ "iconAdjust" , "anotherFragment" , { marginLeft : "1em" } ] Внутренне все размеры и расстояние проводятся в em S, никогда не px (кроме rootFontSize , который устанавливает «базовый» размер). Это делает масштабирование намного проще - просто измените Prop rootFontSize (или установите fontSize на основном контейнере посредством нацеливания на класс или настраивайте тему), и следуйте по всей компонентной шкале.
Значки по умолчанию могут быть заменены, но вам необходимо предоставить их как элементы React/HTML. Просто определите любое или все из них в опоре icons , представленные следующим образом:
icons = { {
add : < YourIcon />
edit : < YourIcon / >
delete : < YourIcon />
copy : < YourIcon / >
ok : < YourIcon / >
cancel : < YourIcon / >
chevron : < YourIcon / >
} }Компоненты иконы должны будут иметь свои собственные стили, так как стили темы не будут добавлены в пользовательские элементы.
Локализуйте свою реализацию, передавая объект translations , чтобы заменить строки по умолчанию. Ключи и значения по умолчанию (английский) следующие:
{
ITEM_SINGLE : '{{count}} item' ,
ITEMS_MULTIPLE : '{{count}} items' ,
KEY_NEW : 'Enter new key' ,
ERROR_KEY_EXISTS : 'Key already exists' ,
ERROR_INVALID_JSON : 'Invalid JSON' ,
ERROR_UPDATE : 'Update unsuccessful' ,
ERROR_DELETE : 'Delete unsuccessful' ,
ERROR_ADD : 'Adding node unsuccessful' ,
DEFAULT_STRING : 'New data!' ,
DEFAULT_NEW_KEY : 'key' ,
} Вы можете заменить определенные узлы в дереве данных своими собственными пользовательскими компонентами. Примером может быть отображение изображения, или пользовательский редактор даты, или просто для добавления визуального шипа. См. Набор данных «Пользовательские узлы» в интерактивной демонстрации, чтобы увидеть его в действии. (Существует также пользовательский сборщик даты, который появляется при редактировании струн ISO в других наборах данных.)
Пользовательские узлы представлены в предложении customNodeDefinitions , в качестве массива объектов следующей структуры:
{
condition , // a FilterFunction, as above
element , // React Component
customNodeProps , // object (optional)
hideKey , // boolean (optional)
defaultValue , // JSON value for a new instance of your component
showOnEdit // boolean, default false
showOnView // boolean, default true
showEditTools // boolean, default true
name // string (appears in Types selector)
showInTypesSelector , // boolean (optional), default false
// Only affects Collection nodes:
showCollectionWrapper // boolean (optional), default true
wrapperElement // React component (optional) to wrap *outside* the normal collection wrapper
wrapperProps // object (optional) -- props for the above wrapper component
} condition представляет собой просто функцию фильтра, с одинаковыми входными параметрами ( key , path , value и т. Д.), А element - это компонент React. Каждый узел в структуре данных будет проходить через каждую функцию условия, и любое соответствие будет заменено вашим пользовательским компонентом. Обратите внимание, что если узел соответствует более чем одним пользовательским условиям определения (из нескольких компонентов), будет использоваться первый , поэтому поместите их в массив в приоритетном порядке.
Компонент будет получать все те же реквизиты, что и стандартный компонент узла (см. Codebase), но вы можете передать дополнительные реквизиты своему компоненту, если это необходимо, через объект customNodeProps . В демонстрации используется тщательный пример специального выбора даты (наряду с несколькими другими более базовыми презентационными), которые вы можете проверить, чтобы увидеть, как использовать стандартные реквизиты и пару пользовательских реквизитов. Просмотреть исходный код здесь
По умолчанию ваш компонент будет представлен справа от ключа свойства, которым он принадлежит, как и любое другое значение. Тем не менее, вы можете скрыть сам ключ, установив hideKey: true , и пользовательский компонент займет всю строку. (См. «Представлено» в поле «Пользовательские узлы» набор данных для примера.)
Кроме того, по умолчанию ваш компонент будет рассматриваться как элемент «дисплея», то есть он появится в зрителе JSON, но при редактировании он вернется к стандартному интерфейсу редактирования. Однако это можно изменить с помощью showOnEdit , showOnView и showEditTools реквизита. Например, сборщик даты может потребоваться только при редактировании и оставленном как есть для отображения. Пропоказ showEditTools относится к значкам редактирования (копия, добавление, редактирование, удаление), которые появляются справа от каждого значения на пахни. Если вы решите отключить их, но вы все равно хотите, чтобы ваш компонент имел режим «редактирования», вам придется предоставить свой собственный механизм пользовательского интерфейса для переключения редактирования.
Вы можете позволить пользователям создавать новые экземпляры ваших специальных узлов, выбрав их как «тип» в селекторе типов при редактировании/добавлении значений. SET showInTypesSelector: true , чтобы включить это. Однако, если это включено, вам необходимо также предоставить name (которое пользователь увидит в селекторе) и defaultValue , которое является данными, которые вставляются, когда пользователь выбирает этот тип «. ( defaultValue должна вернуть true если его проходят через функцию condition , чтобы она была немедленно отображена с помощью пользовательского компонента.)
Простой пользовательский компонент и определение для превращения строк URL -адреса в кликабельные ссылки предоставляются с основным пакетом, который вы можете использовать из коробки. Просто импортируйте и используйте так:
import { JsonEditor , LinkCustomNodeDefinition } from 'json-edit-react'
// ...Other stuff
return (
< JsonEditor
{ ... otherProps }
customNodeDefinitions = { [ LinkCustomNodeDefinition , ... otherCustomDefinitions ] }
/>
) В большинстве случаев будет предпочтительнее (и проще) создавать пользовательские узлы для сопоставления узлов значений (то есть не array или узлов сбора object ), что показывают все демонстрационные примеры. Однако, если вы хотите нацелиться на целый узел сбора, есть пара других вещей, которые нужно знать:
children , это просто становится ответственностью вашего компонента за его обработку.element , которая будет отображаться внутри скобков (т.е. оно выглядит как содержимое коллекции)wrapperElement , который отображается вне коллекции (реквизит может быть поставлен, как описано выше, с помощью wrapperProps ). Опять же, внутреннее содержание (включая ваш пользовательский element ) может отображаться с использованием children React. В этом примере синяя граница показывает wrapperElement , а красная граница показывает внутренний element : 
showCollectionWrapper (по умолчанию true ), которая, когда устанавливается на false , скрывает окружающие элементы коллекции (а именно «Шид/шоу» и кронштейны). В этом случае вы должны были бы предоставить свой собственный механизм прятки/показа в своем компоненте, если вы этого хотите. Можно изменить различные текстовые строки, отображаемые компонентом. Вы можете локализовать его, но вы также можете указать функции для переопределения отображаемого текста на основе определенных условий. Например, скажем, мы хотим, чтобы текст количества свойств (например, 6 items по умолчанию) дал сводку определенного типа узла, который может выглядеть красиво при обрушении. Например (взято из демонстрации):

Свойство customText принимает объект с любыми локальными клавишами в качестве ключей, с функцией, которая возвращает строку (или null , которая заставляет ее отступать в строку локализованной или по умолчанию). Вход в эти функции такой же, как и для функций фильтров, поэтому в этом примере он будет определяться так:
// The function definition
const itemCountReplacement = ( { key , value , size } ) => {
// This returns "Steve Rogers (Marvel)" for the node summary
if ( value instanceof Object && 'name' in value )
return ` ${ value . name } ( ${ ( value ) ?. publisher ?? '' } )`
// This returns "X names" for the alias lists
if ( key === 'aliases' && Array . isArray ( value ) )
return ` ${ size } ${ size === 1 ? 'name' : 'names' } `
// Everything else as normal
return null
}
// And in component props...
. . . otherProps ,
customText = {
ITEM_SINGLE : itemCountReplacement ,
ITEMS_MULTIPLE : itemCountReplacement ,
} Управление клавиатуры по умолчанию изложено выше, но можно настроить/переопределить их. Просто пройдите в keyboardControls с определенными действиями, которые вы хотите переопределить. Объект конфигурации по умолчанию:
{
confirm : 'Enter' , // default for all Value nodes, and key entry
cancel : 'Escape' ,
objectConfirm : { key : 'Enter' , modifier : [ 'Meta' , 'Shift' , 'Control' ] } ,
objectLineBreak : 'Enter' ,
stringConfirm : 'Enter' ,
stringLineBreak : { key : 'Enter' , modifier : 'Shift' } ,
numberConfirm : 'Enter' ,
numberUp : 'ArrowUp' ,
numberDown : 'ArrowDown' ,
booleanConfirm : 'Enter' ,
clipboardModifier : [ 'Meta' , 'Control' ] ,
collapseModifier : 'Alt' ,
}Если (например), вы просто хотите изменить общее действие «подтверждение» на «Cmd-enter» (на Mac) или «Ctrl-enter», вы просто пройдите в:
keyboardControls = {
confirm : {
key : "Enter" ,
modifier : [ "Meta" , "Control" ]
}
}Соображения :
stringConfirm , numberConfirm и booleanConfirm , если они должны отличаться от вашего значения confirm .clipboardModifier по умолчанию). Несмотря на то, что в большинстве случаев функциональность отмены/повторно, вероятно, желательна, это не встроено для компонента, по двум основным причинам:
Несколько вспомогательных функций, компонентов и типов, которые могут быть полезны в ваших собственных реализациях (от создания функций фильтра или обновления или пользовательских компонентов) экспортируются из пакета:
themes : объект, содержащий все встроенные определения темыLinkCustomComponent : компонент, используемый для отображения гиперссылокLinkCustomNodeDefinition : Пользовательское определение узла для гиперссылокIconAdd , IconEdit , IconDelete , IconCopy , IconOk , IconCancel , IconChevron : Все встроенные компоненты иконыmatchNode , matchNodeKey : Помощники для определения пользовательских функций поискаtruncate : функция усекнуть строку до указанной длины. Смотрите здесьextract : функция для извлечения глубоко вложенного значения объекта из пути строки. Смотрите здесьassign : функция, чтобы установить глубокое значение объекта из пути строки. Смотрите здесьThemeName : Стронный буквальный список встроенных имен тем именTheme : полный объект темыThemeInput : тип ввода для поддержки themeJsonEditorProps : все входные реквизиты для компонента редактора JSONJsonData : основной объект data - любая действительная структура JSONUpdateFunction , OnChangeFunction , OnErrorFunction FilterFunction , CopyFunction , SearchFilterFunction , CompareFunction , TypeFilterFunction , LocalisedString , CustomNodeDefinition , CustomTextDefinitions , CustomTextFunction ,TranslateFunction : функция, которая принимает ключ локализации и возвращает переведенную строкуIconReplacements : тип ввода для опоры iconsCollectionNodeProps : все реквизиты переданы внутренне к узлам "Collection" (т.е. объекты/массивы)ValueNodeProps : все реквизиты переданы внутренне к узлам «значения» (то есть не объекты/массивы)CustomNodeProps : все реквизиты передаются внутри страны к пользовательским узлам; В основном то же самое, что и CollectionNodeProps с дополнительным полем customNodeProps для передачи реквизита, уникальных для вашего компонента 'DataType : "string" | "number" | "boolean" | "null" | "object" | "array"KeyboardControls : структура для настройки клавиатуры Пожалуйста, откройте проблему: https://github.com/carlosnz/json-edit-react/issues
Основные функции, которые я хотел бы представить:
This component is heavily inspired by react-json-view, a great package that I've used in my own projects. However, it seems to have been abandoned now, and requires a few critical fixes, so I decided to create my own from scratch and extend the functionality while I was at it.
defaultValue function takes the new key as second parameteroverflow: clip setting based on animating statetrue to represent successsetData prop to discourage reliance on internal data state managementuseEffect hooksnull #90onError callback available for custom error handlingrootFontSize prop to set the "base" size for the componentonChange prop to allow validation/restriction of user input as they typedata if user hasn't actually changed a value (prevents Undo from being unnecessarily triggered)wrapperElement propid propindex in Filter (and other) function inputdefaultValue prop