import * as React from 'react' ; import { ChangeEvent , createContext , isValidElement , ReactElement , useContext , useState , } from 'react' ; import { Identifier , OptionText , useTranslate } from 'ra-core' ; import set from 'lodash/set' ; param options param { ReactElement } options . create param { String } options . createLabel param { String } options . createItemLabel param { any } options . createValue param { String } options . filter param { OnCreateHandler } options . onCreate param handleChange returns { UseSupportCreateValue } export const useSupportCreateSuggestion = ( options ) : UseSupportCreateValue => { const { create , createLabel = 'ra.action.create' , createItemLabel = 'ra.action.create_item' , createValue = '@@ra-create' , optionText = 'name' , filter , handleChange , onCreate , } = options ; const translate = useTranslate ( ) ; const [ renderOnCreate , setRenderOnCreate ] = useState ( false ) ; const context = { filter , onCancel : ( ) => setRenderOnCreate ( false ) , onCreate : item => { setRenderOnCreate ( false ) ; handleChange ( undefined , item ) ; } , } ; return { getCreateItem : ( ) => { if ( typeof optionText !== 'string' ) { return { id : createValue , name : filter && createItemLabel ? translate ( createItemLabel , { item : filter , _ : createItemLabel , } ) : translate ( createLabel , { _ : createLabel } ) , } ; } return set ( { id : createValue , } , optionText , filter && createItemLabel ? translate ( createItemLabel , { item : filter , _ : createItemLabel , } ) : translate ( createLabel , { _ : createLabel } ) ) ; } , handleChange : async ( eventOrValue ) => { const value = eventOrValue . target ?. value || eventOrValue ; const finalValue = Array . isArray ( value ) ? [ ... value ] . pop ( ) : value ; if ( eventOrValue ?. preventDefault ) { eventOrValue . preventDefault ( ) ; eventOrValue . stopPropagation ( ) ; } if ( finalValue ?. id === createValue || finalValue === createValue ) { if ( ! isValidElement ( create ) ) { const newSuggestion = await onCreate ( filter ) ; if ( newSuggestion ) { handleChange ( eventOrValue , newSuggestion ) ; return ; } } else { setRenderOnCreate ( true ) ; return ; } } handleChange ( eventOrValue , undefined ) ; } , createElement : renderOnCreate && isValidElement ( create ) ? ( < CreateSuggestionContext . Provider value = { context } > { create } < /CreateSuggestionContext.Provider>) : null, } ; } ; export interface SupportCreateSuggestionOptions { create ? : ReactElement ; createValue ? : string ; createLabel ? : string ; createItemLabel ? : string ; filter ? : string ; handleChange : ( value : any , newChoice : any ) => void ; onCreate ? : OnCreateHandler ; optionText ? : OptionText ; } export interface UseSupportCreateValue { getCreateItem : ( ) => { id : Identifier ; [ key ] : any ; } ; handleChange : ( eventOrValue : ChangeEvent | any ) => Promise < void > ; createElement : ReactElement | null ; } const CreateSuggestionContext = createContext < CreateSuggestionContextValue > ( undefined ) ; interface CreateSuggestionContextValue { filter ? : string ; onCreate : ( choice : any ) => void ; onCancel : ( ) => void ; } export const useCreateSuggestionContext = ( ) => useContext ( CreateSuggestionContext ) ; export type OnCreateHandler = ( filter ? : string ) => any | Promise < any > ;