@@ -8,11 +8,13 @@ import {
88 CustomTextDefinitions ,
99 LinkCustomNodeDefinition ,
1010 assign ,
11+ matchNode ,
1112} from '../JsonEditImport'
1213import {
1314 CollectionKey ,
1415 DataType ,
1516 DefaultValueFunction ,
17+ SearchFilterFunction ,
1618 ThemeStyles ,
1719 UpdateFunction ,
1820} from '../json-edit-react/src/types'
@@ -28,6 +30,8 @@ interface DemoData {
2830 restrictDelete ?: FilterFunction
2931 restrictAdd ?: FilterFunction
3032 restrictTypeSelection ?: boolean | DataType [ ]
33+ searchFilter ?: 'key' | 'value' | 'all' | SearchFilterFunction
34+ searchPlaceholder ?: string
3135 onUpdate ?: UpdateFunction
3236 onAdd ?: ( props : {
3337 newData : object
@@ -141,16 +145,36 @@ export const demoData: Record<string, DemoData> = {
141145 to the main "Person" objects.
142146 </ Text >
143147 < Text >
144- Also, notice that when a new item is added at the top level, a correctly structured{ ' ' }
148+ Also, notice that when you add a new item in the top level array , a correctly structured{ ' ' }
145149 "Person" object is added, but adding new items elsewhere adds simple string values. This
146150 is done by specifying a function for the < span className = "code" > defaultValue</ span > prop.
147151 </ Text >
152+ < Text >
153+ We've also changed the behaviour of the "Search" input, so that it matches specific people
154+ (on < span className = "code" > name</ span > and < span className = "code" > username</ span > ) and
155+ displays all fields associated with the matching people. This is achieved by specifying a
156+ custom{ ' ' }
157+ < Link href = "https://github.com/CarlosNZ/json-edit-react#searchfiltering" isExternal >
158+ Search filter function
159+ </ Link >
160+ .
161+ </ Text >
148162 </ Flex >
149163 ) ,
150164 restrictEdit : ( { key, level } ) => key === 'id' || level === 0 || level === 1 ,
151165 restrictAdd : ( { level } ) => level === 1 ,
152166 restrictDelete : ( { key } ) => key === 'id' ,
153167 collapse : 2 ,
168+ searchFilter : ( { path, fullData } , searchText ) => {
169+ if ( path ?. length >= 2 ) {
170+ const index = path ?. [ 0 ]
171+ return (
172+ matchNode ( { value : fullData [ index ] . name } , searchText ) ||
173+ matchNode ( { value : fullData [ index ] . username } , searchText )
174+ )
175+ } else return false
176+ } ,
177+ searchPlaceholder : 'Search by name or username' ,
154178 defaultValue : ( { level } ) => {
155179 if ( level === 0 )
156180 return {
@@ -183,51 +207,70 @@ export const demoData: Record<string, DemoData> = {
183207 vsCode : {
184208 name : '⚙️ VSCode settings file' ,
185209 description : (
186- < >
210+ < Flex flexDir = "column" gap = { 2 } >
187211 < Text >
188212 A typical{ ' ' }
189213 < Link href = "https://code.visualstudio.com/" isExternal >
190214 VSCode
191215 </ Link > { ' ' }
192216 config file.
193217 </ Text >
194- < Text mt = { 3 } >
218+ < Text >
195219 The only restriction here is that you can't set any boolean values to{ ' ' }
196220 < span className = "code" > false</ span > . It uses a custom{ ' ' }
197221 < span className = "code" > onUpdate</ span > function to return an error string when you attempt
198222 to do so, and the value is reset to < span className = "code" > true</ span > .
199223 </ Text >
200- </ >
224+ < Text >
225+ Note the "Search" input is configured to filter for object < em > properties</ em > rather than{ ' ' }
226+ < em > values</ em > (by setting < span className = "code" > searchFilter: "key"</ span > ).
227+ </ Text >
228+ </ Flex >
201229 ) ,
202230 collapse : 2 ,
203231 data : data . vsCode ,
204232 onUpdate : ( { newValue } ) => {
205233 if ( newValue === false ) return "Don't use FALSE, just delete the value"
206234 } ,
235+ searchFilter : 'key' ,
236+ searchPlaceholder : 'Search properties' ,
207237 } ,
208238 liveData : {
209239 name : '📖 Live Data (from database)' ,
210240 description : (
211- < >
241+ < Flex flexDir = "column" gap = { 2 } >
212242 < Text >
213243 Here's a live "guestbook" — your changes can be saved permanently to the cloud. However,
214244 there are restrictions:
215- < UnorderedList >
216- < ListItem > You can only add new messages, or fields within your message</ ListItem >
217- < ListItem > Only the most recent message is editable, and only for five minutes</ ListItem >
218- </ UnorderedList >
219245 </ Text >
220- < Text mt = { 3 } >
246+ < UnorderedList >
247+ < ListItem >
248+ < Text > You can only add new messages, or fields within your message</ Text >
249+ </ ListItem >
250+ < ListItem >
251+ < Text > Only the most recent message is editable, and only for five minutes</ Text >
252+ </ ListItem >
253+ </ UnorderedList >
254+ < Text >
221255 Notice also (these are achieved by customising the < span className = "code" > onEdit</ span > { ' ' }
222256 and < span className = "code" > onAdd</ span > props):
223- < UnorderedList >
224- < ListItem >
257+ </ Text >
258+ < UnorderedList >
259+ < ListItem >
260+ < Text >
225261 The messages list gets sorted so the most recent is at the < em > top</ em >
226- </ ListItem >
227- < ListItem > The timestamps get updated automatically after each edit</ ListItem >
228- </ UnorderedList >
262+ </ Text >
263+ </ ListItem >
264+ < ListItem >
265+ < Text > The timestamps get updated automatically after each edit</ Text >
266+ </ ListItem >
267+ </ UnorderedList >
268+ < Text >
269+ You can also filter full "Message" objects by searching any text value (
270+ < span className = "code" > message</ span > , < span className = "code" > name</ span > ,{ ' ' }
271+ < span className = "code" > from</ span > ).
229272 </ Text >
230- </ >
273+ </ Flex >
231274 ) ,
232275 rootName : 'liveData' ,
233276 collapse : 3 ,
@@ -290,6 +333,18 @@ export const demoData: Record<string, DemoData> = {
290333 }
291334 return 'New value'
292335 } ,
336+ searchFilter : ( { path, fullData } , searchText ) => {
337+ if ( path ?. length >= 2 && path [ 0 ] === 'messages' ) {
338+ const index = path ?. [ 1 ]
339+ const messages = ( fullData as { messages : unknown [ ] } ) ?. messages
340+ return (
341+ matchNode ( { value : messages [ index ] . message } , searchText ) ||
342+ matchNode ( { value : messages [ index ] . name } , searchText ) ||
343+ matchNode ( { value : messages [ index ] . from } , searchText )
344+ )
345+ } else return true
346+ } ,
347+ searchPlaceholder : 'Search guestbook' ,
293348 data : { } ,
294349 customNodeDefinitions : [
295350 {
@@ -337,6 +392,8 @@ export const demoData: Record<string, DemoData> = {
337392 restrictAdd : ( { level } ) => level === 0 ,
338393 restrictTypeSelection : [ 'string' , 'object' , 'array' ] ,
339394 collapse : 2 ,
395+ searchFilter : 'key' ,
396+ searchPlaceholder : 'Search Theme keys' ,
340397 data : { } ,
341398 } ,
342399 customNodes : {
@@ -373,6 +430,13 @@ export const demoData: Record<string, DemoData> = {
373430 ) ,
374431 rootName : 'Superheroes' ,
375432 collapse : 2 ,
433+ searchFilter : ( { path, fullData } , searchText = '' ) => {
434+ if ( path ?. length >= 2 ) {
435+ const index = path ?. [ 0 ]
436+ return matchNode ( { value : fullData [ index ] . name } , searchText )
437+ } else return false
438+ } ,
439+ searchPlaceholder : 'Search by character name' ,
376440 data : data . customNodes ,
377441 customNodeDefinitions : [
378442 {
0 commit comments