npm package: @searchspring/snap-plugins-dynamic-variants
Description: Handle dynamic variants
Author: Searchspring
Latest version: 1.1.1

# Dynamic Variants
This plugin dynamically selects and re-orders swatches based on the current search query and filters selected in order to display the most relevant color to the current search.

## Installation
```
npm i @searchspring/snap-plugins-dynamic-variants
```

## Usage
1. Import the plugin in your index.js.
```
import { dynamicVariants } from '@searchspring/snap-plugins-dynamicVariants';
```
2. Add the plugin with it's configuration object to each of the controllers that require it. You can find more information on the configuration object below.
```
plugins: [[shared], [dynamicVariants, dynamicVariantsConfig]],
```
3. Add a component for your swatches display to be used in your results. The configuration object for they dynamic variants can be accessed using `controller.store.custom.variantsConfig`. An example component can be found in this document in the Example Component section.

## Configuration Object Options

* **field** `String` *(default: 'ss_swatches')* - The field in the `result.attributes` object which contains the JSON array of objects for the current result. The plugin will automatically parse this array for you prior to processing.
* **simple** `String` *(default: 'color')* - The field name for the simple color (ex. Emerald Green, Crimson) in your swatch objects.
* **group** `String | Array<string>` *(default: 'group')* - A string or array of strings that are the field name(s) for the grouped colors in your swatch objects. For example, if the exact simple color is "Crimson" the grouped color might be "Red".
* **limit** `Integer` *(default: 6)* - The number of swatches to display. 
* **filterEnable** `Boolean` *(default: true)* - Set to `false` to disable matching filters for swatch selection.
* **filterFields** `Array<string>` *(default: 'color')* - The list of filter fields to use when matching filters for swatch selection.
* **searchEnable** `Boolean` *(default: true)* - Set to `false` to disable matching the search query for swatch selection.
* **swap** `Function` *(default: see below)* - The function that should be called to update the data in the result with the data for the selected variant. This function should take three arugments for the result, the selected variant, and optionally the event triggering the swap.
* **modifyVariant** `Function | Boolean` *(default: false)* - This function is called after the swatch JSON is parsed to modify the swatches based on other data. This function should take three arguments for the current variant to modify, the full result object, and the current controller.

### Default `swap` Function
```
function(result, variant, event) {
    const core = result.mappings.core;
    const { attributes, custom } = result;

    // update product details
    if (variant.image) {
        core.thumbnailImageUrl = variant.image;
    }

    // set variantSelected
    custom.variantSelected = variant;
}
```

## Example Component
```
/* external imports */
import { h, Fragment, Component } from 'preact';
import { observer } from 'mobx-react';
import classnames from 'classnames';

/* searchspring imports */
import { filters as tools } from '@searchspring/snap-toolbox';

@observer
export class DynamicVariants extends Component {
	render() {
		const { controller, result } = this.props;
		const store = controller.store;
		const variantsConfig = store.custom.variantsConfig;
		const core = result.mappings.core;
		const { attributes, custom } = result;
		const remaining = attributes[variantsConfig.field] ? attributes[variantsConfig.field].length - variantsConfig.limit : 0;
		const intellisuggest = (e) => controller.track.product.click(e, result);

		return variantsConfig.swap && attributes[variantsConfig.field] && attributes[variantsConfig.field].length !== 0 ? (
			<div className="ss__variants">
				<div className="ss__palette ss__flex__wrap--center">
					{attributes[variantsConfig.field].slice(0, variantsConfig.limit).map((variant) => {
						let variantActive = custom.variantSelected && custom.variantSelected[variantsConfig.simple] == variant[variantsConfig.simple];

						return (
							<div className={classnames('ss__palette__option', { ss__active: variantActive })}>
								<a
									className="ss__palette__link ss__pointer"
									onClick={(e) => {
										variantsConfig.swap(result, variant, e);
									}}
								>
									<div className="ss__palette__block">
										<div
											className={`ss__palette__color ss__palette__color--${tools.handleize(variant[variantsConfig.simple])}`}
											style={`background-color: ${variant.swatchColor}`}
										></div>
									</div>
								</a>
							</div>
						);
					})}
					{remaining > 0 && (
						<div className="ss__palette__option ss__palette__option--more">
							<a className="ss__palette__link" href={core.url} onClick={intellisuggest}>
								+ More
							</a>
						</div>
					)}
				</div>
			</div>
		) : null;
	}
}