@gravityforms/components
Version:
UI components for use in Gravity Forms development. Both React and vanilla js flavors.
266 lines (249 loc) • 6.81 kB
JavaScript
import { isObject, slugify } from '@gravityforms/utils';
import Icon from '../../elements/Icon';
import Image from '../../elements/Image';
/**
* @function normalizeText
* @description Normalizes the provided text and trims leading and trailing spaces.
*
* @since 4.5.0
*
* @param {string} text The text to normalize.
*
* @return {string} The normalized text.
*/
export const normalizeText = ( text = '' ) => {
return text
.normalize( 'NFD' )
.replace( /[\u0300-\u036f]/g, '' )
.trim();
};
/**
* @function getId
* @description Get the id from the prefix and key provided.
*
* @since 4.5.0
*
* @param {string} prefix The id prefix.
* @param {string} key The id key.
*
* @return {string} The id.
*/
export const getId = ( prefix, key ) => slugify( `${ prefix }-${ key }` );
/**
* @function getSearchItem
* @description Get the search item.
*
* @since 4.5.0
*
* @param {string} idPrefix The id prefix.
*
* @return {object} The search item.
*/
export const getSearchItem = ( idPrefix ) => ( {
component: 'search',
id: getId( idPrefix, 'search' ),
} );
/**
* @function augmentListItems
* @description Augment list items to add id to the item.
*
* @since 4.5.0
*
* @param {Array} listItems The list items.
* @param {object} args Arguments to augment list items with.
* @param {boolean} args.hasSearch Whether the dropdown has search or not.
* @param {string} args.id The id prefix.
*
* @return {Array} The augmented list items.
*/
export const augmentListItems = ( listItems, { hasSearch = false, id: idPrefix = '' } ) => {
const newListItems = [
...listItems,
...( hasSearch ? [ getSearchItem( idPrefix ) ] : [] ),
];
return newListItems.map( ( item ) => {
if ( item.component === 'search' ) {
return item;
}
return {
...item,
id: getId( idPrefix, item.value ),
};
} );
};
/**
* @function getListItemsState
* @description Gets the state for list items.
*
* @since 4.5.0
*
* @param {Array} listItems The list items.
* @param {object} args Arguments to augment list items with.
* @param {boolean} args.hasSearch Whether the dropdown has search or not.
* @param {string} args.id The id prefix.
*
* @return {object} The list items state.
*/
export const getListItemsState = ( listItems, args = {} ) => {
const items = augmentListItems( listItems, args );
return {
ids: items.map( ( item ) => item.id ),
items,
};
};
/**
* @function filterListItems
* @description Filters list items based on the search value provided.
*
* @since 4.5.0
*
* @param {Array} listItems The list items.
* @param {string} searchValue The search value.
*
* @return {Array} The filtered list items.
*/
export const filterListItems = ( listItems, searchValue ) => {
if ( searchValue === '' ) {
return listItems;
}
return listItems.filter( ( item ) => {
const itemLabel = item.label || '';
if ( ! itemLabel ) {
return false;
}
return normalizeText( itemLabel ).toLowerCase().indexOf( searchValue.toLowerCase() ) !== -1;
} );
};
/**
* @function getComponent
* @description Gets the component from the args provided.
*
* @since 4.5.0
*
* @param {object} args The component args.
*
* @return {JSX.Element} The component.
*/
export const getComponent = ( args = {} ) => {
let component = null;
switch ( args.component ) {
case 'Icon':
component = <Icon { ...args.props } />;
break;
case 'Image':
component = <Image { ...args.props } />;
break;
default:
component = null;
}
return component;
};
/**
* @function convertSingleToMultiItem
* @description Converts a single item to a multi item.
*
* @since 4.5.0
*
* @param {object} singleItem The single item.
*
* @return {Array} The multi item.
*/
export const convertSingleToMultiItem = ( singleItem ) => {
if ( ! isObject( singleItem ) ) {
// Single item is not object, something is wrong here, return single item.
return singleItem;
}
if ( Object.keys( singleItem ).length === 0 ) {
// Single item is empty, return empty array.
return [];
}
// Return single item as multi value.
return [ singleItem ];
};
/**
* @function convertMultiToSingleItem
* @description Converts a multi item to a single item.
*
* @since 4.5.0
*
* @param {Array} multiItem The multi item.
* @param {Array} listItems The current list items.
*
* @return {object} The single item.
*/
export const convertMultiToSingleItem = ( multiItem, listItems ) => {
if ( ! Array.isArray( multiItem ) ) {
// multi item is not array, something is wrong here, return multi item.
return multiItem;
}
if ( multiItem.length === 0 ) {
// Selected item is empty, return first item in list items.
return listItems[ 0 ] || {};
}
// Return first item in multi value.
return multiItem[ 0 ];
};
/**
* @function isListItemShape
* @description Check if the item is in the shape of a list item.
*
* @since 5.4.5
*
* @param {*} item The item to check.
*
* @return {boolean} Whether the item is in the shape of a list item.
*/
export const isListItemShape = ( item ) => {
return isObject( item ) &&
Object.prototype.hasOwnProperty.call( item, 'label' ) &&
Object.prototype.hasOwnProperty.call( item, 'value' );
};
/**
* @function getSelectedItemFromValue
* @description Get the selected item from the value provided.
*
* @since 5.4.5
*
* @param {string|Array|object} value The provided value.
* @param {Array} listItems The list items to get the selected item from.
* @param {boolean} multi Whether the dropdown is multi or not.
*
* @return {object|Array} The selected item.
*/
export const getSelectedItemFromValue = ( value, listItems, multi ) => {
// If the value is a string
if ( typeof value === 'string' ) {
const item = listItems.find( ( listItem ) => listItem.value === value );
if ( multi ) {
return item ? [ item ] : [];
}
return item || {};
}
// If the value is an array
if ( Array.isArray( value ) ) {
if ( multi ) {
return value.reduce( ( acc, val ) => {
// If val is a string, find the list item with the value and add it to the accumulator.
if ( typeof val === 'string' ) {
return [ ...acc, listItems.find( ( listItem ) => listItem.value === val ) ];
}
// If val is an object, add it to the accumulator.
if ( isListItemShape( val ) ) {
return [ ...acc, val ];
}
// If val is not a string or an object, return the accumulator.
return acc;
}, [] );
}
return convertMultiToSingleItem( value, listItems );
}
// If the value is an object
if ( isListItemShape( value ) ) {
if ( multi ) {
return [ value ];
}
return value;
}
// If the value is not a string, an array, or an object, return the default value.
return multi ? [] : {};
};