New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@searchspring/snap-store-mobx

Package Overview
Dependencies
Maintainers
2
Versions
116
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@searchspring/snap-store-mobx - npm Package Compare versions

Comparing version 0.55.0 to 0.56.0

4

dist/cjs/Autocomplete/AutocompleteStore.js

@@ -109,3 +109,2 @@ "use strict";

this.error = undefined;
this.loaded = !!data.pagination;
this.meta = new MetaStore_1.MetaStore(data.meta);

@@ -131,3 +130,3 @@ // set the query to match the actual queried term and not the input query

this.filters = new Stores_1.SearchFilterStore(this.services, data.filters, this.meta.data);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, data.results || [], data.pagination, data.merchandising);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, data.results || [], data.pagination, data.merchandising, this.loaded);
if ((this.results.length === 0 && !this.trending.filter(function (term) { return term.active; }).length) || ((_a = this.terms) === null || _a === void 0 ? void 0 : _a.filter(function (term) { return term.active; }).length)) {

@@ -140,2 +139,3 @@ // if a trending term was selected and then a subsequent search yields no results, reset trending terms to remove active state

this.sorting = new Stores_1.SearchSortingStore(this.services, data.sorting || [], data.search || {}, this.meta.data);
this.loaded = !!data.pagination;
};

@@ -142,0 +142,0 @@ return AutocompleteStore;

@@ -50,3 +50,3 @@ "use strict";

var _a;
price += (((_a = item.display.mappings.core) === null || _a === void 0 ? void 0 : _a.price) || 0) * item.quantity;
price += +(((_a = item.display.mappings.core) === null || _a === void 0 ? void 0 : _a.price) || 0) * item.quantity;
});

@@ -63,3 +63,3 @@ return price;

var _a, _b;
price += (((_a = item.display.mappings.core) === null || _a === void 0 ? void 0 : _a.msrp) || ((_b = item.display.mappings.core) === null || _b === void 0 ? void 0 : _b.price) || 0) * item.quantity;
price += (+(((_a = item.display.mappings.core) === null || _a === void 0 ? void 0 : _a.msrp) || 0) || +(((_b = item.display.mappings.core) === null || _b === void 0 ? void 0 : _b.price) || 0) || 0) * item.quantity;
});

@@ -66,0 +66,0 @@ return price;

@@ -47,6 +47,5 @@ "use strict";

this.error = undefined;
this.loaded = !!(data === null || data === void 0 ? void 0 : data.profile);
this.meta = new MetaStore_1.MetaStore(data === null || data === void 0 ? void 0 : data.meta);
this.profile = new Stores_2.RecommendationProfileStore(this.services, data);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, data === null || data === void 0 ? void 0 : data.results);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, data === null || data === void 0 ? void 0 : data.results, undefined, undefined, this.loaded);
// only create a cart store when type is bundle

@@ -56,2 +55,3 @@ if (this.profile.type == 'bundle') {

}
this.loaded = !!(data === null || data === void 0 ? void 0 : data.profile);
};

@@ -58,0 +58,0 @@ return RecommendationStore;

@@ -73,3 +73,2 @@ "use strict";

this.error = undefined;
this.loaded = !!data.pagination;
this.meta = new MetaStore_1.MetaStore(data.meta);

@@ -80,5 +79,6 @@ this.merchandising = new Stores_1.SearchMerchandisingStore(this.services, (data === null || data === void 0 ? void 0 : data.merchandising) || {});

this.filters = new Stores_1.SearchFilterStore(this.services, data.filters, this.meta.data);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, (data === null || data === void 0 ? void 0 : data.results) || [], data.pagination, data.merchandising);
this.results = new Stores_1.SearchResultStore(this.config, this.services, this.meta.data, (data === null || data === void 0 ? void 0 : data.results) || [], data.pagination, data.merchandising, this.loaded);
this.pagination = new Stores_1.SearchPaginationStore(this.config, this.services, data.pagination, this.meta.data);
this.sorting = new Stores_1.SearchSortingStore(this.services, (data === null || data === void 0 ? void 0 : data.sorting) || [], (data === null || data === void 0 ? void 0 : data.search) || {}, this.meta.data);
this.loaded = !!data.pagination;
};

@@ -85,0 +85,0 @@ return SearchStore;

@@ -5,3 +5,3 @@ export { SearchMerchandisingStore, BannerContent, ContentType } from './SearchMerchandisingStore';

export { SearchPaginationStore } from './SearchPaginationStore';
export { SearchResultStore, Product, Banner } from './SearchResultStore';
export { SearchResultStore, Product, Banner, VariantSelection, VariantSelectionValue } from './SearchResultStore';
export { SearchSortingStore } from './SearchSortingStore';

@@ -8,0 +8,0 @@ export { SearchQueryStore } from './SearchQueryStore';

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SearchHistoryStore = exports.SearchQueryStore = exports.SearchSortingStore = exports.Banner = exports.Product = exports.SearchResultStore = exports.SearchPaginationStore = exports.Filter = exports.SearchFilterStore = exports.FacetRangeValue = exports.FacetHierarchyValue = exports.FacetValue = exports.RangeFacet = exports.ValueFacet = exports.SearchFacetStore = exports.ContentType = exports.SearchMerchandisingStore = void 0;
exports.SearchHistoryStore = exports.SearchQueryStore = exports.SearchSortingStore = exports.VariantSelection = exports.Banner = exports.Product = exports.SearchResultStore = exports.SearchPaginationStore = exports.Filter = exports.SearchFilterStore = exports.FacetRangeValue = exports.FacetHierarchyValue = exports.FacetValue = exports.RangeFacet = exports.ValueFacet = exports.SearchFacetStore = exports.ContentType = exports.SearchMerchandisingStore = void 0;
var SearchMerchandisingStore_1 = require("./SearchMerchandisingStore");

@@ -23,2 +23,3 @@ Object.defineProperty(exports, "SearchMerchandisingStore", { enumerable: true, get: function () { return SearchMerchandisingStore_1.SearchMerchandisingStore; } });

Object.defineProperty(exports, "Banner", { enumerable: true, get: function () { return SearchResultStore_1.Banner; } });
Object.defineProperty(exports, "VariantSelection", { enumerable: true, get: function () { return SearchResultStore_1.VariantSelection; } });
var SearchSortingStore_1 = require("./SearchSortingStore");

@@ -25,0 +26,0 @@ Object.defineProperty(exports, "SearchSortingStore", { enumerable: true, get: function () { return SearchSortingStore_1.SearchSortingStore; } });

@@ -1,6 +0,6 @@

import type { StoreServices, StoreConfigs, VariantSelectionOptions, ResultBadge, VariantConfig } from '../../types';
import type { StoreServices, StoreConfigs, ResultBadge, VariantOptionConfig, VariantConfig } from '../../types';
import type { SearchResponseModelResult, SearchResponseModelPagination, SearchResponseModelMerchandising, SearchResponseModelResultMappings, SearchResponseModelMerchandisingContentInline, SearchResponseModelMerchandisingContentConfig, MetaResponseModel } from '@searchspring/snapi-types';
export declare class SearchResultStore extends Array<Product | Banner> {
static get [Symbol.species](): ArrayConstructor;
constructor(config: StoreConfigs, services: StoreServices, metaData: MetaResponseModel, resultData?: SearchResponseModelResult[], paginationData?: SearchResponseModelPagination, merchData?: SearchResponseModelMerchandising);
constructor(config: StoreConfigs, services: StoreServices, metaData: MetaResponseModel, resultData?: SearchResponseModelResult[], paginationData?: SearchResponseModelPagination, merchData?: SearchResponseModelMerchandising, loaded?: boolean);
}

@@ -70,6 +70,7 @@ export declare class Banner {

}
type SelectionValue = {
export type VariantSelectionValue = {
value: string;
label?: string;
thumbnailImageUrl?: string;
backgroundImageUrl?: string;
background?: string;

@@ -81,7 +82,8 @@ available?: boolean;

label: string;
selected?: string;
previouslySelected?: string;
values: SelectionValue[];
selected?: VariantSelectionValue;
previouslySelected?: VariantSelectionValue;
values: VariantSelectionValue[];
private config;
private variantsUpdate;
constructor(variants: Variants, selectorConfig: VariantSelectionOptions);
constructor(variants: Variants, selectorField: string, variantConfig?: VariantOptionConfig);
refineValues(variants: Variants): void;

@@ -88,0 +90,0 @@ reset(): void;

@@ -45,10 +45,42 @@ "use strict";

var is_plain_object_1 = require("is-plain-object");
var VARIANT_ATTRIBUTE = 'ss-variant-option';
var VARIANT_ATTRIBUTE_SELECTED = 'ss-variant-option-selected';
var SearchResultStore = /** @class */ (function (_super) {
__extends(SearchResultStore, _super);
function SearchResultStore(config, services, metaData, resultData, paginationData, merchData) {
var _a;
function SearchResultStore(config, services, metaData, resultData, paginationData, merchData, loaded) {
var _a, _b, _c, _d;
var results = (resultData || []).map(function (result) {
return new Product(services, result, metaData, config);
});
if ((_a = merchData === null || merchData === void 0 ? void 0 : merchData.content) === null || _a === void 0 ? void 0 : _a.inline) {
var variantConfig = (_a = config === null || config === void 0 ? void 0 : config.settings) === null || _a === void 0 ? void 0 : _a.variants;
// preselected variant options
if ((_b = variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.realtime) === null || _b === void 0 ? void 0 : _b.enabled) {
// attach click events - ONLY happens once (known limitation)
if (!loaded && results.length) {
document.querySelectorAll("[".concat(VARIANT_ATTRIBUTE, "]")).forEach(function (elem) {
var _a;
if ((variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.field) && !((_a = variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.realtime) === null || _a === void 0 ? void 0 : _a.enabled) === false) {
elem.addEventListener('click', function () { return variantOptionClick(elem, variantConfig, results); });
}
});
}
// check for attributes for preselection
if (results.length) {
if ((variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.field) && !((_c = variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.realtime) === null || _c === void 0 ? void 0 : _c.enabled) === false) {
var options_1 = {};
// grab values from elements on the page to form preselected elements
document.querySelectorAll("[".concat(VARIANT_ATTRIBUTE_SELECTED, "]")).forEach(function (elem) {
var attr = elem.getAttribute(VARIANT_ATTRIBUTE);
if (attr) {
var _a = attr.split(':'), option = _a[0], value = _a[1];
if (option && value) {
options_1[option.toLowerCase()] = [value.toLowerCase()];
}
}
});
makeVariantSelections(variantConfig, options_1, results);
}
}
}
if ((_d = merchData === null || merchData === void 0 ? void 0 : merchData.content) === null || _d === void 0 ? void 0 : _d.inline) {
var banners = merchData.content.inline

@@ -118,3 +150,3 @@ .sort(function (a, b) {

var parsedVariants = JSON.parse(this.attributes[variantsField]);
this.variants = new Variants(parsedVariants, this.mask, (_c = config.settings) === null || _c === void 0 ? void 0 : _c.variants);
this.variants = new Variants(parsedVariants, this.mask, (_c = config === null || config === void 0 ? void 0 : config.settings) === null || _c === void 0 ? void 0 : _c.variants);
}

@@ -251,3 +283,5 @@ catch (err) {

};
this.config = config;
if (config) {
this.config = config;
}
this.update(variantData, config);

@@ -259,8 +293,8 @@ }

try {
var options_1 = [];
var options_2 = [];
// create variants objects
this.data = variantData.map(function (variant) {
Object.keys(variant.options).forEach(function (variantOption) {
if (!options_1.includes(variantOption)) {
options_1.push(variantOption);
if (!options_2.includes(variantOption)) {
options_2.push(variantOption);
}

@@ -272,9 +306,6 @@ });

this.selections = [];
options_1.map(function (option) {
// TODO - merge with variant config before constructing selection (for label overrides and swatch mappings)
var optionConfig = {
field: option,
label: option,
};
_this.selections.push(new VariantSelection(_this, optionConfig));
options_2.map(function (option) {
var _a;
var variantOptionConfig = ((_a = _this.config) === null || _a === void 0 ? void 0 : _a.options) && _this.config.options[option];
_this.selections.push(new VariantSelection(_this, option, variantOptionConfig));
});

@@ -299,3 +330,3 @@ var preselectedOptions_1 = {};

// options = {color: 'Blue', size: 'L'};
if (!options) {
if (!options || !Object.keys(options).length) {
// select first available for each selection

@@ -315,3 +346,3 @@ this.selections.forEach(function (selection) {

var preferedOptions = options[selection.field];
var preferencedOption = availableOptions[0];
var preferencedOption = selection.selected || availableOptions[0];
// if theres a preference for that field

@@ -321,3 +352,3 @@ if (preferedOptions) {

//see if that option is in the available options
var availablePreferedOptions = availableOptions.find(function (value) { return value.value.toLowerCase() == preference.toLowerCase(); });
var availablePreferedOptions = availableOptions.find(function (value) { return value.value.toString().toLowerCase() == (preference === null || preference === void 0 ? void 0 : preference.toString().toLowerCase()); });
//use it

@@ -339,3 +370,3 @@ if (availablePreferedOptions) {

if (preferencedOption) {
selection.select(preferencedOption.value);
selection.select(preferencedOption.value, true);
}

@@ -358,7 +389,7 @@ });

// check to see if we have enough selections made to update the display
var selectedSelections = this.selections.filter(function (selection) { return selection.selected; });
var selectedSelections = this.selections.filter(function (selection) { var _a, _b; return (_b = (_a = selection.selected) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.length; });
if (selectedSelections.length) {
var availableVariants = this.data;
var _loop_1 = function (selectedSelection) {
availableVariants = availableVariants.filter(function (variant) { return selectedSelection.selected == variant.options[selectedSelection.field].value && variant.available; });
availableVariants = availableVariants.filter(function (variant) { var _a; return ((_a = selectedSelection.selected) === null || _a === void 0 ? void 0 : _a.value) == variant.options[selectedSelection.field].value && variant.available; });
};

@@ -380,9 +411,10 @@ // loop through selectedSelections and only include available products that match current selections

var VariantSelection = /** @class */ (function () {
function VariantSelection(variants, selectorConfig) {
function VariantSelection(variants, selectorField, variantConfig) {
var _this = this;
this.selected = ''; //ex: blue
this.previouslySelected = '';
this.selected = undefined;
this.previouslySelected = undefined;
this.values = [];
this.field = selectorConfig.field;
this.label = selectorConfig.label;
this.field = selectorField;
this.label = (variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.label) || selectorField;
this.config = variantConfig || {};
// needed to prevent attaching variants as class property

@@ -403,3 +435,3 @@ this.variantsUpdate = function () { return variants.refineSelections(_this); };

var _loop_2 = function (selectedSelection) {
availableVariants = availableVariants.filter(function (variant) { return selectedSelection.selected == variant.options[selectedSelection.field].value && variant.available; });
availableVariants = availableVariants.filter(function (variant) { var _a; return ((_a = selectedSelection.selected) === null || _a === void 0 ? void 0 : _a.value) == variant.options[selectedSelection.field].value && variant.available; });
};

@@ -416,6 +448,26 @@ // loop through selectedSelections and remove products that do not match

if (!values.some(function (val) { return variant.options[_this.field].value == val.value; })) {
values.push(__assign({ label: variant.options[_this.field].value,
// TODO: use configurable mappings from config
// TODO: set background for swatches (via configurable mappings) from config
thumbnailImageUrl: (_a = variant.mappings.core) === null || _a === void 0 ? void 0 : _a.thumbnailImageUrl, available: Boolean(availableVariants.some(function (availableVariant) { return availableVariant.options[_this.field].value == variant.options[_this.field].value; })) }, variant.options[_this.field]));
var value = variant.options[_this.field].value;
var thumbnailImageUrl = (_a = variant.mappings.core) === null || _a === void 0 ? void 0 : _a.thumbnailImageUrl;
var mappedValue = {
value: value,
label: value,
thumbnailImageUrl: thumbnailImageUrl,
available: Boolean(availableVariants.some(function (availableVariant) { return availableVariant.options[_this.field].value == variant.options[_this.field].value; })),
};
if (_this.config.thumbnailBackgroundImages) {
mappedValue.backgroundImageUrl = thumbnailImageUrl;
}
if (_this.config.mappings && _this.config.mappings && _this.config.mappings[value.toString().toLowerCase()]) {
var mapping = _this.config.mappings[value.toString().toLowerCase()];
if (mapping.label) {
mappedValue.label = mapping.label;
}
if (mapping.background) {
mappedValue.background = mapping.background;
}
if (mapping.backgroundImageUrl) {
mappedValue.backgroundImageUrl = mapping.backgroundImageUrl;
}
}
values.push(mappedValue);
}

@@ -428,8 +480,8 @@ // TODO: use sorting function from config

// check if the selection is stil available
if (!newValues.some(function (val) { return val.value == _this.selected && val.available; })) {
if (!newValues.some(function (val) { var _a; return val.value == ((_a = _this.selected) === null || _a === void 0 ? void 0 : _a.value) && val.available; })) {
// the selection is no longer available, attempt to select previous selection
if (this.selected !== this.previouslySelected &&
this.previouslySelected &&
newValues.some(function (val) { return val.value == _this.previouslySelected && val.available; })) {
this.select(this.previouslySelected, true);
newValues.some(function (val) { var _a; return val.value == ((_a = _this.previouslySelected) === null || _a === void 0 ? void 0 : _a.value) && val.available; })) {
this.select(this.previouslySelected.value, true);
}

@@ -441,3 +493,3 @@ else {

var nextAvailableValue = availableValues[0].value;
if (this.selected !== nextAvailableValue) {
if (this.selected.value !== nextAvailableValue) {
this.select(nextAvailableValue, true);

@@ -452,3 +504,3 @@ }

VariantSelection.prototype.reset = function () {
this.selected = '';
this.selected = undefined;
this.values.forEach(function (val) { return (val.available = false); });

@@ -463,3 +515,3 @@ };

}
this.selected = value;
this.selected = valueExist;
this.variantsUpdate();

@@ -530,1 +582,30 @@ }

}
function variantOptionClick(elem, variantConfig, results) {
var options = {};
var attr = elem.getAttribute(VARIANT_ATTRIBUTE);
if (attr) {
var _a = attr.split(':'), option = _a[0], value = _a[1];
options[option.toLowerCase()] = [value.toLowerCase()];
makeVariantSelections(variantConfig, options, results);
}
}
function makeVariantSelections(variantConfig, options, results) {
var _a, _b;
var filteredResults = results;
// filter based on config
(_b = (_a = variantConfig.realtime) === null || _a === void 0 ? void 0 : _a.filters) === null || _b === void 0 ? void 0 : _b.forEach(function (filter) {
if (filter == 'first') {
filteredResults = [filteredResults[0]];
}
if (filter == 'unaltered') {
filteredResults = filteredResults.filter(function (result) { var _a; return !((_a = result.variants) === null || _a === void 0 ? void 0 : _a.selections.some(function (selection) { return selection.previouslySelected; })); });
}
});
filteredResults.forEach(function (result) {
var _a;
// no banner types
if (result.type == 'product') {
(_a = result.variants) === null || _a === void 0 ? void 0 : _a.makeSelections(options);
}
});
}

@@ -7,14 +7,26 @@ import type { UrlManager } from '@searchspring/snap-url-manager';

};
export type VariantConfigFilterTypes = 'first' | 'unaltered';
export type VariantConfig = {
field: string;
realtime?: {
enabled: boolean;
filters?: VariantConfigFilterTypes[];
};
options?: {
[field: string]: {
preSelected?: string[];
};
[optionField: string]: VariantOptionConfig;
};
};
export type VariantSelectionOptions = {
field: string;
label: string;
export type VariantOptionConfig = {
label?: string;
preSelected?: string[];
thumbnailBackgroundImages?: boolean;
mappings?: VariantOptionConfigMappings;
};
export type VariantOptionConfigMappings = {
[optionValue: string]: {
label?: string;
background?: string;
backgroundImageUrl?: string;
};
};
export type SearchStoreConfig = StoreConfig & {

@@ -110,3 +122,5 @@ globals?: Partial<SearchRequestModel>;

order?: number;
variants?: VariantConfig;
settings?: {
variants?: VariantConfig;
};
};

@@ -113,0 +127,0 @@ export type StoreConfigs = SearchStoreConfig | AutocompleteStoreConfig | FinderStoreConfig | RecommendationStoreConfig;

@@ -79,3 +79,2 @@ import { makeObservable, observable } from 'mobx';

this.error = undefined;
this.loaded = !!data.pagination;
this.meta = new MetaStore(data.meta);

@@ -101,3 +100,3 @@ // set the query to match the actual queried term and not the input query

this.filters = new SearchFilterStore(this.services, data.filters, this.meta.data);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data.results || [], data.pagination, data.merchandising);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data.results || [], data.pagination, data.merchandising, this.loaded);
if ((this.results.length === 0 && !this.trending.filter((term) => term.active).length) || this.terms?.filter((term) => term.active).length) {

@@ -110,3 +109,4 @@ // if a trending term was selected and then a subsequent search yields no results, reset trending terms to remove active state

this.sorting = new SearchSortingStore(this.services, data.sorting || [], data.search || {}, this.meta.data);
this.loaded = !!data.pagination;
}
}

@@ -27,3 +27,3 @@ import { observable, computed, makeObservable } from 'mobx';

this.items.forEach((item) => {
price += (item.display.mappings.core?.price || 0) * item.quantity;
price += +(item.display.mappings.core?.price || 0) * item.quantity;
});

@@ -35,3 +35,3 @@ return price;

this.items.forEach((item) => {
price += (item.display.mappings.core?.msrp || item.display.mappings.core?.price || 0) * item.quantity;
price += (+(item.display.mappings.core?.msrp || 0) || +(item.display.mappings.core?.price || 0) || 0) * item.quantity;
});

@@ -38,0 +38,0 @@ return price;

@@ -26,6 +26,5 @@ import { makeObservable, observable } from 'mobx';

this.error = undefined;
this.loaded = !!data?.profile;
this.meta = new MetaStore(data?.meta);
this.profile = new RecommendationProfileStore(this.services, data);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data?.results);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data?.results, undefined, undefined, this.loaded);
// only create a cart store when type is bundle

@@ -35,3 +34,4 @@ if (this.profile.type == 'bundle') {

}
this.loaded = !!data?.profile;
}
}

@@ -51,3 +51,2 @@ import { makeObservable, observable } from 'mobx';

this.error = undefined;
this.loaded = !!data.pagination;
this.meta = new MetaStore(data.meta);

@@ -58,6 +57,7 @@ this.merchandising = new SearchMerchandisingStore(this.services, data?.merchandising || {});

this.filters = new SearchFilterStore(this.services, data.filters, this.meta.data);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data?.results || [], data.pagination, data.merchandising);
this.results = new SearchResultStore(this.config, this.services, this.meta.data, data?.results || [], data.pagination, data.merchandising, this.loaded);
this.pagination = new SearchPaginationStore(this.config, this.services, data.pagination, this.meta.data);
this.sorting = new SearchSortingStore(this.services, data?.sorting || [], data?.search || {}, this.meta.data);
this.loaded = !!data.pagination;
}
}

@@ -5,3 +5,3 @@ export { SearchMerchandisingStore, BannerContent, ContentType } from './SearchMerchandisingStore';

export { SearchPaginationStore } from './SearchPaginationStore';
export { SearchResultStore, Product, Banner } from './SearchResultStore';
export { SearchResultStore, Product, Banner, VariantSelection, VariantSelectionValue } from './SearchResultStore';
export { SearchSortingStore } from './SearchSortingStore';

@@ -8,0 +8,0 @@ export { SearchQueryStore } from './SearchQueryStore';

@@ -5,5 +5,5 @@ export { SearchMerchandisingStore, ContentType } from './SearchMerchandisingStore';

export { SearchPaginationStore } from './SearchPaginationStore';
export { SearchResultStore, Product, Banner } from './SearchResultStore';
export { SearchResultStore, Product, Banner, VariantSelection } from './SearchResultStore';
export { SearchSortingStore } from './SearchSortingStore';
export { SearchQueryStore } from './SearchQueryStore';
export { SearchHistoryStore } from './SearchHistoryStore';

@@ -1,6 +0,6 @@

import type { StoreServices, StoreConfigs, VariantSelectionOptions, ResultBadge, VariantConfig } from '../../types';
import type { StoreServices, StoreConfigs, ResultBadge, VariantOptionConfig, VariantConfig } from '../../types';
import type { SearchResponseModelResult, SearchResponseModelPagination, SearchResponseModelMerchandising, SearchResponseModelResultMappings, SearchResponseModelMerchandisingContentInline, SearchResponseModelMerchandisingContentConfig, MetaResponseModel } from '@searchspring/snapi-types';
export declare class SearchResultStore extends Array<Product | Banner> {
static get [Symbol.species](): ArrayConstructor;
constructor(config: StoreConfigs, services: StoreServices, metaData: MetaResponseModel, resultData?: SearchResponseModelResult[], paginationData?: SearchResponseModelPagination, merchData?: SearchResponseModelMerchandising);
constructor(config: StoreConfigs, services: StoreServices, metaData: MetaResponseModel, resultData?: SearchResponseModelResult[], paginationData?: SearchResponseModelPagination, merchData?: SearchResponseModelMerchandising, loaded?: boolean);
}

@@ -70,6 +70,7 @@ export declare class Banner {

}
type SelectionValue = {
export type VariantSelectionValue = {
value: string;
label?: string;
thumbnailImageUrl?: string;
backgroundImageUrl?: string;
background?: string;

@@ -81,7 +82,8 @@ available?: boolean;

label: string;
selected?: string;
previouslySelected?: string;
values: SelectionValue[];
selected?: VariantSelectionValue;
previouslySelected?: VariantSelectionValue;
values: VariantSelectionValue[];
private config;
private variantsUpdate;
constructor(variants: Variants, selectorConfig: VariantSelectionOptions);
constructor(variants: Variants, selectorField: string, variantConfig?: VariantOptionConfig);
refineValues(variants: Variants): void;

@@ -88,0 +90,0 @@ reset(): void;

import { computed, makeObservable, observable } from 'mobx';
import deepmerge from 'deepmerge';
import { isPlainObject } from 'is-plain-object';
const VARIANT_ATTRIBUTE = 'ss-variant-option';
const VARIANT_ATTRIBUTE_SELECTED = 'ss-variant-option-selected';
export class SearchResultStore extends Array {

@@ -8,6 +10,35 @@ static get [Symbol.species]() {

}
constructor(config, services, metaData, resultData, paginationData, merchData) {
constructor(config, services, metaData, resultData, paginationData, merchData, loaded) {
let results = (resultData || []).map((result) => {
return new Product(services, result, metaData, config);
});
const variantConfig = config?.settings?.variants;
// preselected variant options
if (variantConfig?.realtime?.enabled) {
// attach click events - ONLY happens once (known limitation)
if (!loaded && results.length) {
document.querySelectorAll(`[${VARIANT_ATTRIBUTE}]`).forEach((elem) => {
if (variantConfig?.field && !variantConfig?.realtime?.enabled === false) {
elem.addEventListener('click', () => variantOptionClick(elem, variantConfig, results));
}
});
}
// check for attributes for preselection
if (results.length) {
if (variantConfig?.field && !variantConfig?.realtime?.enabled === false) {
const options = {};
// grab values from elements on the page to form preselected elements
document.querySelectorAll(`[${VARIANT_ATTRIBUTE_SELECTED}]`).forEach((elem) => {
const attr = elem.getAttribute(VARIANT_ATTRIBUTE);
if (attr) {
const [option, value] = attr.split(':');
if (option && value) {
options[option.toLowerCase()] = [value.toLowerCase()];
}
}
});
makeVariantSelections(variantConfig, options, results);
}
}
}
if (merchData?.content?.inline) {

@@ -66,3 +97,3 @@ const banners = merchData.content.inline

const parsedVariants = JSON.parse(this.attributes[variantsField]);
this.variants = new Variants(parsedVariants, this.mask, config.settings?.variants);
this.variants = new Variants(parsedVariants, this.mask, config?.settings?.variants);
}

@@ -186,3 +217,5 @@ catch (err) {

};
this.config = config;
if (config) {
this.config = config;
}
this.update(variantData, config);

@@ -205,8 +238,4 @@ }

options.map((option) => {
// TODO - merge with variant config before constructing selection (for label overrides and swatch mappings)
const optionConfig = {
field: option,
label: option,
};
this.selections.push(new VariantSelection(this, optionConfig));
const variantOptionConfig = this.config?.options && this.config.options[option];
this.selections.push(new VariantSelection(this, option, variantOptionConfig));
});

@@ -231,3 +260,3 @@ const preselectedOptions = {};

// options = {color: 'Blue', size: 'L'};
if (!options) {
if (!options || !Object.keys(options).length) {
// select first available for each selection

@@ -247,3 +276,3 @@ this.selections.forEach((selection) => {

const preferedOptions = options[selection.field];
let preferencedOption = availableOptions[0];
let preferencedOption = selection.selected || availableOptions[0];
// if theres a preference for that field

@@ -253,3 +282,3 @@ if (preferedOptions) {

//see if that option is in the available options
const availablePreferedOptions = availableOptions.find((value) => value.value.toLowerCase() == preference.toLowerCase());
const availablePreferedOptions = availableOptions.find((value) => value.value.toString().toLowerCase() == preference?.toString().toLowerCase());
//use it

@@ -271,3 +300,3 @@ if (availablePreferedOptions) {

if (preferencedOption) {
selection.select(preferencedOption.value);
selection.select(preferencedOption.value, true);
}

@@ -289,3 +318,3 @@ });

// check to see if we have enough selections made to update the display
const selectedSelections = this.selections.filter((selection) => selection.selected);
const selectedSelections = this.selections.filter((selection) => selection.selected?.value?.length);
if (selectedSelections.length) {

@@ -295,3 +324,3 @@ let availableVariants = this.data;

for (const selectedSelection of selectedSelections) {
availableVariants = availableVariants.filter((variant) => selectedSelection.selected == variant.options[selectedSelection.field].value && variant.available);
availableVariants = availableVariants.filter((variant) => selectedSelection.selected?.value == variant.options[selectedSelection.field].value && variant.available);
}

@@ -306,8 +335,9 @@ // set active variant

export class VariantSelection {
constructor(variants, selectorConfig) {
this.selected = ''; //ex: blue
this.previouslySelected = '';
constructor(variants, selectorField, variantConfig) {
this.selected = undefined;
this.previouslySelected = undefined;
this.values = [];
this.field = selectorConfig.field;
this.label = selectorConfig.label;
this.field = selectorField;
this.label = variantConfig?.label || selectorField;
this.config = variantConfig || {};
// needed to prevent attaching variants as class property

@@ -328,3 +358,3 @@ this.variantsUpdate = () => variants.refineSelections(this);

for (const selectedSelection of selectedSelections) {
availableVariants = availableVariants.filter((variant) => selectedSelection.selected == variant.options[selectedSelection.field].value && variant.available);
availableVariants = availableVariants.filter((variant) => selectedSelection.selected?.value == variant.options[selectedSelection.field].value && variant.available);
}

@@ -335,10 +365,26 @@ const newValues = variants.data

if (!values.some((val) => variant.options[this.field].value == val.value)) {
values.push({
label: variant.options[this.field].value,
// TODO: use configurable mappings from config
// TODO: set background for swatches (via configurable mappings) from config
thumbnailImageUrl: variant.mappings.core?.thumbnailImageUrl,
const value = variant.options[this.field].value;
const thumbnailImageUrl = variant.mappings.core?.thumbnailImageUrl;
const mappedValue = {
value: value,
label: value,
thumbnailImageUrl: thumbnailImageUrl,
available: Boolean(availableVariants.some((availableVariant) => availableVariant.options[this.field].value == variant.options[this.field].value)),
...variant.options[this.field],
});
};
if (this.config.thumbnailBackgroundImages) {
mappedValue.backgroundImageUrl = thumbnailImageUrl;
}
if (this.config.mappings && this.config.mappings && this.config.mappings[value.toString().toLowerCase()]) {
const mapping = this.config.mappings[value.toString().toLowerCase()];
if (mapping.label) {
mappedValue.label = mapping.label;
}
if (mapping.background) {
mappedValue.background = mapping.background;
}
if (mapping.backgroundImageUrl) {
mappedValue.backgroundImageUrl = mapping.backgroundImageUrl;
}
}
values.push(mappedValue);
}

@@ -351,8 +397,8 @@ // TODO: use sorting function from config

// check if the selection is stil available
if (!newValues.some((val) => val.value == this.selected && val.available)) {
if (!newValues.some((val) => val.value == this.selected?.value && val.available)) {
// the selection is no longer available, attempt to select previous selection
if (this.selected !== this.previouslySelected &&
this.previouslySelected &&
newValues.some((val) => val.value == this.previouslySelected && val.available)) {
this.select(this.previouslySelected, true);
newValues.some((val) => val.value == this.previouslySelected?.value && val.available)) {
this.select(this.previouslySelected.value, true);
}

@@ -364,3 +410,3 @@ else {

const nextAvailableValue = availableValues[0].value;
if (this.selected !== nextAvailableValue) {
if (this.selected.value !== nextAvailableValue) {
this.select(nextAvailableValue, true);

@@ -375,3 +421,3 @@ }

reset() {
this.selected = '';
this.selected = undefined;
this.values.forEach((val) => (val.available = false));

@@ -385,3 +431,3 @@ }

}
this.selected = value;
this.selected = valueExist;
this.variantsUpdate();

@@ -446,1 +492,28 @@ }

}
function variantOptionClick(elem, variantConfig, results) {
const options = {};
const attr = elem.getAttribute(VARIANT_ATTRIBUTE);
if (attr) {
const [option, value] = attr.split(':');
options[option.toLowerCase()] = [value.toLowerCase()];
makeVariantSelections(variantConfig, options, results);
}
}
function makeVariantSelections(variantConfig, options, results) {
let filteredResults = results;
// filter based on config
variantConfig.realtime?.filters?.forEach((filter) => {
if (filter == 'first') {
filteredResults = [filteredResults[0]];
}
if (filter == 'unaltered') {
filteredResults = filteredResults.filter((result) => !result.variants?.selections.some((selection) => selection.previouslySelected));
}
});
filteredResults.forEach((result) => {
// no banner types
if (result.type == 'product') {
result.variants?.makeSelections(options);
}
});
}

@@ -7,14 +7,26 @@ import type { UrlManager } from '@searchspring/snap-url-manager';

};
export type VariantConfigFilterTypes = 'first' | 'unaltered';
export type VariantConfig = {
field: string;
realtime?: {
enabled: boolean;
filters?: VariantConfigFilterTypes[];
};
options?: {
[field: string]: {
preSelected?: string[];
};
[optionField: string]: VariantOptionConfig;
};
};
export type VariantSelectionOptions = {
field: string;
label: string;
export type VariantOptionConfig = {
label?: string;
preSelected?: string[];
thumbnailBackgroundImages?: boolean;
mappings?: VariantOptionConfigMappings;
};
export type VariantOptionConfigMappings = {
[optionValue: string]: {
label?: string;
background?: string;
backgroundImageUrl?: string;
};
};
export type SearchStoreConfig = StoreConfig & {

@@ -110,3 +122,5 @@ globals?: Partial<SearchRequestModel>;

order?: number;
variants?: VariantConfig;
settings?: {
variants?: VariantConfig;
};
};

@@ -113,0 +127,0 @@ export type StoreConfigs = SearchStoreConfig | AutocompleteStoreConfig | FinderStoreConfig | RecommendationStoreConfig;

{
"name": "@searchspring/snap-store-mobx",
"version": "0.55.0",
"version": "0.56.0",
"description": "Snap MobX Store",

@@ -23,8 +23,8 @@ "main": "dist/cjs/index.js",

"dependencies": {
"@searchspring/snap-toolbox": "^0.55.0",
"@searchspring/snap-toolbox": "^0.56.0",
"mobx": "6.9.0"
},
"devDependencies": {
"@searchspring/snap-client": "^0.55.0",
"@searchspring/snap-url-manager": "^0.55.0"
"@searchspring/snap-client": "^0.56.0",
"@searchspring/snap-url-manager": "^0.56.0"
},

@@ -35,3 +35,3 @@ "sideEffects": false,

],
"gitHead": "ad413e17c9756a28e1972173b3b25f0a4dcb127c"
"gitHead": "3326303c739fd3bbb23e6477b275b89f7df3bb74"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc