@gravityforms/components
Version:
UI components for use in Gravity Forms development. Both React and vanilla js flavors.
47 lines (35 loc) • 1.61 kB
JavaScript
import { React } from '@gravityforms/libraries';
import { sprintf } from '@gravityforms/utils';
const { useState, useCallback } = React;
const deepClone = ( obj ) => JSON.parse( JSON.stringify( obj ) );
const resolvePath = ( path, base = window ) => {
return path.split( '.' ).reduce( ( acc, part ) => acc && acc[ part ], base );
};
const useRepeaterState = ( initialStateOrPath, syncWithWindow = false, titleKey = '', repeaterType = 'inline', titlePrefix = '' ) => {
const isPath = typeof initialStateOrPath === 'string';
const initialState = isPath ? deepClone( resolvePath( initialStateOrPath ) || [] ) : deepClone( initialStateOrPath );
const [ items, setItems ] = useState( initialState );
const updateExternalState = ( updatedItems ) => {
if ( isPath && syncWithWindow ) {
const target = resolvePath( initialStateOrPath );
if ( target ) {
target.length = 0;
target.push( ...updatedItems );
}
}
};
const handleChange = useCallback( ( updatedItems ) => {
setItems( updatedItems );
updateExternalState( updatedItems );
}, [ isPath, initialStateOrPath, syncWithWindow ] );
const onChange = useCallback( ( key, index ) => ( value ) => {
const updatedItems = [ ...items ];
updatedItems[ index ][ key ] = value;
if ( titleKey && repeaterType === 'block' && key === titleKey ) {
updatedItems[ index ].repeater_item_block_content_title = titlePrefix ? sprintf( titlePrefix, value ) : value;
}
handleChange( updatedItems );
}, [ items, handleChange, repeaterType, titleKey ] );
return { items, handleChange, onChange };
};
export default useRepeaterState;