1- import { Select , Form , Space } from "antd" ;
2- import { PlusCircleOutlined } from "@ant-design/icons" ;
3- import React , {
4- useCallback ,
5- useEffect ,
6- useMemo ,
7- useRef ,
8- useState ,
9- } from "react" ;
1+ import { Select , Form } from "antd" ;
2+ import React , { useCallback , useEffect , useMemo , useState } from "react" ;
103import {
114 CustomScopeProvider ,
125 evaluate ,
@@ -20,7 +13,7 @@ import type {
2013 EnsembleAction ,
2114 Expression ,
2215} from "@ensembleui/react-framework" ;
23- import { get , isEmpty , isNull , isObject , isString } from "lodash-es" ;
16+ import { get , isArray , isEmpty , isNull , isObject , isString } from "lodash-es" ;
2417import { WidgetRegistry } from "../../registry" ;
2518import type {
2619 EnsembleWidgetProps ,
@@ -33,7 +26,6 @@ import { getComponentStyles } from "../../shared/styles";
3326import type { HasBorder } from "../../shared/hasSchema" ;
3427import type { FormInputProps } from "./types" ;
3528import { EnsembleFormItem } from "./FormItem" ;
36- import { updateFieldValue } from "./Form" ;
3729
3830const widgetName = "Dropdown" ;
3931
@@ -64,7 +56,6 @@ export type DropdownProps = {
6456 autoComplete : Expression < boolean > ;
6557 hintStyle ?: EnsembleWidgetStyles ;
6658 panel ?: { [ key : string ] : unknown } ;
67- allowCreateOptions ?: boolean ;
6859} & EnsembleWidgetProps < DropdownStyles > &
6960 HasItemTemplate & {
7061 "item-template" ?: { value : Expression < string > } ;
@@ -73,49 +64,11 @@ export type DropdownProps = {
7364const DropdownRenderer = (
7465 menu : React . ReactElement ,
7566 panel ?: { [ key : string ] : unknown } ,
76- newOption ?: string ,
77- onAddNewOption ?: ( value : string ) => void ,
7867) : React . ReactElement => {
7968 const panelOption = useMemo ( ( ) => {
8069 return panel ? EnsembleRuntime . render ( [ unwrapWidget ( panel ) ] ) : null ;
8170 } , [ ] ) ;
8271
83- // if we have a new option to add, show custom content along with the menu
84- if ( newOption ) {
85- return (
86- < >
87- < div style = { { padding : "10px 15px" } } >
88- < span > There are no matches</ span >
89- </ div >
90- < Space
91- style = { {
92- padding : "10px 15px" ,
93- display : "flex" ,
94- flexDirection : "column" ,
95- alignItems : "flex-start" ,
96- width : "100%" ,
97- cursor : "pointer" ,
98- } }
99- onClick = { ( ) => onAddNewOption ?.( newOption ) }
100- >
101- < Space >
102- < PlusCircleOutlined />
103- < span > { `Add "${ newOption } "` } </ span >
104- </ Space >
105- </ Space >
106- { /* eslint-disable-next-line jsx-a11y/no-static-element-interactions */ }
107- < div
108- onMouseDown = { ( e ) => {
109- e . preventDefault ( ) ;
110- e . stopPropagation ( ) ;
111- } }
112- >
113- { panelOption }
114- </ div >
115- </ >
116- ) ;
117- }
118-
11972 return (
12073 < >
12174 { menu }
@@ -136,10 +89,8 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
13689 const [ selectedValue , setSelectedValue ] = useState <
13790 string | number | undefined
13891 > ( ) ;
139- const [ newOption , setNewOption ] = useState ( "" ) ;
92+
14093 const [ isOpen , setIsOpen ] = useState < boolean > ( false ) ;
141- const [ items , setItems ] = useState < SelectOption [ ] > ( [ ] ) ;
142- const initializedRef = useRef ( false ) ;
14394 const {
14495 "item-template" : itemTemplate ,
14596 onChange,
@@ -173,21 +124,8 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
173124 ( value ?: number | string ) => {
174125 setSelectedValue ( value ) ;
175126 onChangeAction ?. callback ( { value } ) ;
176-
177- // if the selected value is a new option that doesn't exist in items, add it
178- if ( value && values ?. allowCreateOptions ) {
179- const optionExists = items . find ( ( item ) => item . value === value ) ;
180- if ( ! optionExists ) {
181- const newItem : SelectOption = {
182- label : value . toString ( ) ,
183- value : value ,
184- } ;
185- setItems ( ( prevItems ) => [ ...prevItems , newItem ] ) ;
186- }
187- }
188- setNewOption ( "" ) ;
189127 } ,
190- [ onChangeAction ?. callback , values ?. allowCreateOptions , items ] ,
128+ [ onChangeAction ?. callback ] ,
191129 ) ;
192130
193131 const onItemSelectAction = useEnsembleAction ( onItemSelect ) ;
@@ -199,60 +137,16 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
199137 [ onItemSelectAction ?. callback ] ,
200138 ) ;
201139
202- const handleSearch = ( value : string ) : void => {
203- if ( ! values ?. allowCreateOptions ) {
204- return ;
205- }
206-
207- const isOptionExist = items . find ( ( option ) =>
208- option . label . toString ( ) . toLowerCase ( ) . includes ( value . toLowerCase ( ) ) ,
209- ) ;
210-
211- if ( ! isOptionExist && value . trim ( ) ) {
212- setNewOption ( value ) ;
213- } else {
214- setNewOption ( "" ) ;
215- }
216- } ;
217-
218- const handleAddNewOption = useCallback (
219- ( value : string ) => {
220- const newItem : SelectOption = {
221- label : value ,
222- value : value ,
223- } ;
224- setItems ( ( prevItems ) => [ ...prevItems , newItem ] ) ;
225-
226- setSelectedValue ( value ) ;
227- onChangeAction ?. callback ( { value } ) ;
228-
229- // trigger form's onChange action
230- updateFieldValue ( formInstance , values ?. id ?? values ?. label ?? "" , value ) ;
231-
232- setNewOption ( "" ) ;
233- setIsOpen ( false ) ;
234- } ,
235- [ onChangeAction ?. callback ] ,
236- ) ;
237-
238140 const { namedData } = useTemplateData ( {
239141 data : itemTemplate ?. data ,
240142 name : itemTemplate ?. name ,
241143 } ) ;
242144
243- // initialize items from props only once
244- useEffect ( ( ) => {
245- if ( values ?. items && ! initializedRef . current ) {
246- setItems ( values . items ) ;
247- initializedRef . current = true ;
248- }
249- } , [ values ?. items ] ) ;
250-
251145 const options = useMemo ( ( ) => {
252146 let dropdownOptions : React . ReactNode [ ] | null = null ;
253147
254- if ( items . length > 0 ) {
255- const tempOptions = items . map ( ( item ) => {
148+ if ( values ?. items && isArray ( values . items ) ) {
149+ const tempOptions = values . items . map ( ( item ) => {
256150 if ( item . type === "group" ) {
257151 // Render a group item with sub-items
258152 return (
@@ -312,7 +206,7 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
312206 }
313207
314208 return dropdownOptions ;
315- } , [ items , namedData , itemTemplate ] ) ;
209+ } , [ values ?. items , namedData , itemTemplate ] ) ;
316210
317211 const { backgroundColor : _ , ...formItemStyles } = values ?. styles ?? { } ;
318212
@@ -409,24 +303,17 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
409303 < div ref = { rootRef } style = { { flex : 1 , ...formItemStyles } } >
410304 < EnsembleFormItem values = { values } >
411305 < Select
412- key = { `${ id } -${ items . length } ` }
413306 allowClear = { values ?. allowClear ?? true }
414307 className = { `${ values ?. styles ?. names || "" } ${ id } _input` }
415308 defaultValue = { values ?. value }
416309 disabled = { values ?. enabled === false }
417310 dropdownRender = { ( menu ) : React . ReactElement =>
418- DropdownRenderer (
419- menu ,
420- values ?. panel ,
421- newOption ,
422- handleAddNewOption ,
423- )
311+ DropdownRenderer ( menu , values ?. panel )
424312 }
425313 dropdownStyle = { values ?. styles }
426314 id = { values ?. id }
427315 onChange = { handleChange }
428316 onDropdownVisibleChange = { ( state ) : void => setIsOpen ( state ) }
429- onSearch = { values ?. allowCreateOptions ? handleSearch : undefined }
430317 onSelect = { onItemSelectCallback }
431318 open = { isOpen }
432319 placeholder = {
@@ -437,10 +324,7 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
437324 )
438325 }
439326 optionFilterProp = "children"
440- showSearch = {
441- Boolean ( values ?. autoComplete ) ||
442- Boolean ( values ?. allowCreateOptions )
443- }
327+ showSearch = { Boolean ( values ?. autoComplete ) }
444328 value = { values ?. selectedValue }
445329 >
446330 { options }
0 commit comments