33 * SPDX-License-Identifier: MIT
44 */
55
6- import { useEffect , useMemo , useRef , useState } from 'react' ;
6+ import { useEffect , useState } from 'react' ;
77
8- import { omit } from 'lodash' ;
9- import { IJsonSchema } from '@flowgram.ai/json-schema' ;
8+ import { difference , omit } from 'lodash' ;
9+ import { produce } from 'immer' ;
10+ import { IJsonSchema , type JsonSchemaTypeManager , useTypeManager } from '@flowgram.ai/json-schema' ;
1011
1112import { PropertyValueType } from './types' ;
1213
@@ -15,92 +16,46 @@ function genId() {
1516 return _id ++ ;
1617}
1718
18- function getDrilldownSchema (
19- value ?: PropertyValueType ,
20- path ?: ( keyof PropertyValueType ) [ ]
21- ) : { schema ?: PropertyValueType | null ; path ?: ( keyof PropertyValueType ) [ ] } {
22- if ( ! value ) {
23- return { } ;
24- }
25-
26- if ( value . type === 'array' && value . items ) {
27- return getDrilldownSchema ( value . items , [ ...( path || [ ] ) , 'items' ] ) ;
28- }
29-
30- return { schema : value , path } ;
31- }
32-
3319export function usePropertiesEdit (
3420 value ?: PropertyValueType ,
3521 onChange ?: ( value : PropertyValueType ) => void
3622) {
37- // Get drilldown (array.items.items...)
38- const drilldown = useMemo ( ( ) => getDrilldownSchema ( value ) , [ value , value ?. type , value ?. items ] ) ;
39-
40- const isDrilldownObject = drilldown . schema ?. type === 'object' ;
41-
42- // Generate Init Property List
43- const initPropertyList = useMemo (
44- ( ) =>
45- isDrilldownObject
46- ? Object . entries ( drilldown . schema ?. properties || { } )
47- . sort ( ( [ , a ] , [ , b ] ) => ( a . extra ?. index ?? 0 ) - ( b . extra ?. index ?? 0 ) )
48- . map (
49- ( [ name , _value ] , index ) =>
50- ( {
51- key : genId ( ) ,
52- name,
53- isPropertyRequired : drilldown . schema ?. required ?. includes ( name ) || false ,
54- ..._value ,
55- extra : {
56- ...( _value . extra || { } ) ,
57- index,
58- } ,
59- } as PropertyValueType )
60- )
61- : [ ] ,
62- [ isDrilldownObject ]
63- ) ;
64-
65- const [ propertyList , setPropertyList ] = useState < PropertyValueType [ ] > ( initPropertyList ) ;
66-
67- const mountRef = useRef ( false ) ;
23+ const typeManager = useTypeManager ( ) as JsonSchemaTypeManager ;
24+
25+ // Get drilldown properties (array.items.items.properties...)
26+ const drilldownSchema = typeManager . getPropertiesParent ( value || { } ) ;
27+ const canAddField = typeManager . canAddField ( value || { } ) ;
28+
29+ const [ propertyList , setPropertyList ] = useState < PropertyValueType [ ] > ( [ ] ) ;
6830
6931 useEffect ( ( ) => {
70- // If initRef is true, it means the component has been mounted
71- if ( mountRef . current ) {
72- // If the value is changed, update the property list
73- setPropertyList ( ( _list ) => {
74- const nameMap = new Map < string , PropertyValueType > ( ) ;
75-
76- for ( const _property of _list ) {
77- if ( _property . name ) {
78- nameMap . set ( _property . name , _property ) ;
79- }
80- }
81- return Object . entries ( drilldown . schema ?. properties || { } )
82- . sort ( ( [ , a ] , [ , b ] ) => ( a . extra ?. index ?? 0 ) - ( b . extra ?. index ?? 0 ) )
83- . map ( ( [ name , _value ] ) => {
84- const _property = nameMap . get ( name ) ;
85- if ( _property ) {
86- return {
87- key : _property . key ,
88- name,
89- isPropertyRequired : drilldown . schema ?. required ?. includes ( name ) || false ,
90- ..._value ,
91- } ;
92- }
93- return {
94- key : genId ( ) ,
95- name,
96- isPropertyRequired : drilldown . schema ?. required ?. includes ( name ) || false ,
97- ..._value ,
98- } ;
99- } ) ;
100- } ) ;
101- }
102- mountRef . current = true ;
103- } , [ drilldown . schema ] ) ;
32+ // If the value is changed, update the property list
33+ setPropertyList ( ( _list ) => {
34+ const newNames = Object . entries ( drilldownSchema ?. properties || { } )
35+ . sort ( ( [ , a ] , [ , b ] ) => ( a . extra ?. index ?? 0 ) - ( b . extra ?. index ?? 0 ) )
36+ . map ( ( [ key ] ) => key ) ;
37+
38+ const oldNames = _list . map ( ( item ) => item . name ) . filter ( Boolean ) as string [ ] ;
39+ const addNames = difference ( newNames , oldNames ) ;
40+
41+ return _list
42+ . filter ( ( item ) => ! item . name || newNames . includes ( item . name ) )
43+ . map ( ( item ) => ( {
44+ key : item . key ,
45+ name : item . name ,
46+ isPropertyRequired : drilldownSchema ?. required ?. includes ( item . name || '' ) || false ,
47+ ...item ,
48+ } ) )
49+ . concat (
50+ addNames . map ( ( _name ) => ( {
51+ key : genId ( ) ,
52+ name : _name ,
53+ isPropertyRequired : drilldownSchema ?. required ?. includes ( _name ) || false ,
54+ ...( drilldownSchema ?. properties ?. [ _name ] || { } ) ,
55+ } ) )
56+ ) ;
57+ } ) ;
58+ } , [ drilldownSchema ] ) ;
10459
10560 const updatePropertyList = ( updater : ( list : PropertyValueType [ ] ) => PropertyValueType [ ] ) => {
10661 setPropertyList ( ( _list ) => {
@@ -122,21 +77,25 @@ export function usePropertiesEdit(
12277 }
12378 }
12479
125- let drilldownSchema = value || { } ;
126- if ( drilldown . path ) {
127- drilldownSchema = drilldown . path . reduce ( ( acc , key ) => acc [ key ] , value || { } ) ;
128- }
129- drilldownSchema . properties = nextProperties ;
130- drilldownSchema . required = nextRequired ;
80+ onChange ?.(
81+ produce ( value || { } , ( draft ) => {
82+ const propertiesParent = typeManager . getPropertiesParent ( draft ) ;
13183
132- onChange ?.( value || { } ) ;
84+ if ( propertiesParent ) {
85+ propertiesParent . properties = nextProperties ;
86+ propertiesParent . required = nextRequired ;
87+ return ;
88+ }
89+ } )
90+ ) ;
13391
13492 return next ;
13593 } ) ;
13694 } ;
13795
13896 const onAddProperty = ( ) => {
139- updatePropertyList ( ( _list ) => [
97+ // set property list only, not trigger updatePropertyList
98+ setPropertyList ( ( _list ) => [
14099 ..._list ,
141100 { key : genId ( ) , name : '' , type : 'string' , extra : { index : _list . length + 1 } } ,
142101 ] ) ;
@@ -153,14 +112,14 @@ export function usePropertiesEdit(
153112 } ;
154113
155114 useEffect ( ( ) => {
156- if ( ! isDrilldownObject ) {
115+ if ( ! canAddField ) {
157116 setPropertyList ( [ ] ) ;
158117 }
159- } , [ isDrilldownObject ] ) ;
118+ } , [ canAddField ] ) ;
160119
161120 return {
162121 propertyList,
163- isDrilldownObject ,
122+ canAddField ,
164123 onAddProperty,
165124 onRemoveProperty,
166125 onEditProperty,
0 commit comments