@searchspring/snap-controller 0.64.0 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts +15 -2
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/cjs/Autocomplete/AutocompleteController.js +133 -7
- package/dist/cjs/Finder/FinderController.d.ts.map +1 -1
- package/dist/cjs/Finder/FinderController.js +1 -3
- package/dist/cjs/Recommendation/RecommendationController.d.ts +12 -16
- package/dist/cjs/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/cjs/Recommendation/RecommendationController.js +83 -320
- package/dist/cjs/Search/SearchController.d.ts +10 -3
- package/dist/cjs/Search/SearchController.d.ts.map +1 -1
- package/dist/cjs/Search/SearchController.js +191 -20
- package/dist/esm/Autocomplete/AutocompleteController.d.ts +15 -2
- package/dist/esm/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/esm/Autocomplete/AutocompleteController.js +127 -7
- package/dist/esm/Finder/FinderController.d.ts.map +1 -1
- package/dist/esm/Finder/FinderController.js +1 -3
- package/dist/esm/Recommendation/RecommendationController.d.ts +12 -16
- package/dist/esm/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/esm/Recommendation/RecommendationController.js +79 -302
- package/dist/esm/Search/SearchController.d.ts +10 -3
- package/dist/esm/Search/SearchController.d.ts.map +1 -1
- package/dist/esm/Search/SearchController.js +172 -18
- package/package.json +10 -10
|
@@ -81,6 +81,8 @@ var AbstractController_1 = require("../Abstract/AbstractController");
|
|
|
81
81
|
var snap_store_mobx_1 = require("@searchspring/snap-store-mobx");
|
|
82
82
|
var getParams_1 = require("../utils/getParams");
|
|
83
83
|
var types_1 = require("../types");
|
|
84
|
+
var BACKGROUND_FILTER_FIELD_MATCHES = ['collection', 'category', 'categories', 'hierarchy'];
|
|
85
|
+
var BACKGROUND_FILTERS_VALUE_FLAGS = [1, 0, '1', '0', 'true', 'false', true, false];
|
|
84
86
|
var defaultConfig = {
|
|
85
87
|
id: 'search',
|
|
86
88
|
globals: {},
|
|
@@ -105,19 +107,24 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
105
107
|
var _this = _super.call(this, config, { client: client, store: store, urlManager: urlManager, eventManager: eventManager, profiler: profiler, logger: logger, tracker: tracker }, context) || this;
|
|
106
108
|
_this.type = types_1.ControllerTypes.search;
|
|
107
109
|
_this.previousResults = [];
|
|
110
|
+
_this.pageType = 'search';
|
|
111
|
+
_this.events = { product: {} };
|
|
108
112
|
_this.track = {
|
|
109
113
|
product: {
|
|
110
|
-
|
|
111
|
-
var _a, _b, _c, _d;
|
|
114
|
+
clickThrough: function (e, result) {
|
|
115
|
+
var _a, _b, _c, _d, _e, _f;
|
|
116
|
+
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.clickThrough) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
112
119
|
var target = e.target;
|
|
113
|
-
var resultHref = ((
|
|
120
|
+
var resultHref = ((_c = (_b = result.display) === null || _b === void 0 ? void 0 : _b.mappings.core) === null || _c === void 0 ? void 0 : _c.url) || ((_d = result.mappings.core) === null || _d === void 0 ? void 0 : _d.url) || '';
|
|
114
121
|
var elemHref = target === null || target === void 0 ? void 0 : target.getAttribute('href');
|
|
115
122
|
// the href that should be used for restoration - if the elemHref contains the resultHref - use resultHref
|
|
116
123
|
var storedHref = (elemHref === null || elemHref === void 0 ? void 0 : elemHref.indexOf(resultHref)) != -1 ? resultHref : elemHref || resultHref;
|
|
117
124
|
var scrollMap = {};
|
|
118
125
|
// generate the selector using element class and parent classes
|
|
119
126
|
var selector = generateHrefSelector(target, storedHref);
|
|
120
|
-
var domRect = selector ? (
|
|
127
|
+
var domRect = selector ? (_e = document === null || document === void 0 ? void 0 : document.querySelector(selector)) === null || _e === void 0 ? void 0 : _e.getBoundingClientRect() : undefined;
|
|
121
128
|
// store element position data to scrollMap
|
|
122
129
|
if (selector || storedHref || domRect) {
|
|
123
130
|
try {
|
|
@@ -135,17 +142,64 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
135
142
|
}
|
|
136
143
|
// store position data or empty object
|
|
137
144
|
_this.storage.set('scrollMap', scrollMap);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
var data = getSearchSchemaData({ params: _this.params, store: _this.store, results: [result] });
|
|
146
|
+
_this.tracker.events[_this.pageType].clickThrough({ data: data, siteId: (_f = _this.config.globals) === null || _f === void 0 ? void 0 : _f.siteId });
|
|
147
|
+
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
148
|
+
_this.events.product[result.id].clickThrough = true;
|
|
149
|
+
_this.eventManager.fire('track.product.clickThrough', { controller: _this, event: e, products: [result], trackEvent: data });
|
|
150
|
+
},
|
|
151
|
+
click: function (e, result) {
|
|
152
|
+
var _a, _b, _c;
|
|
153
|
+
if (result.type === 'banner') {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// TODO: closest might be going too far - write own function to only go n levels up - additionally check that href includes result.url
|
|
157
|
+
var href = ((_a = e.target) === null || _a === void 0 ? void 0 : _a.getAttribute('href')) || ((_c = (_b = e.target) === null || _b === void 0 ? void 0 : _b.closest('a')) === null || _c === void 0 ? void 0 : _c.getAttribute('href'));
|
|
158
|
+
if (href) {
|
|
159
|
+
_this.track.product.clickThrough(e, result);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// TODO: in future, send as an interaction event
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
render: function (result) {
|
|
166
|
+
var _a, _b;
|
|
167
|
+
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.render) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
var data = getSearchSchemaData({ params: _this.params, store: _this.store, results: [result] });
|
|
171
|
+
_this.tracker.events[_this.pageType].render({ data: data, siteId: (_b = _this.config.globals) === null || _b === void 0 ? void 0 : _b.siteId });
|
|
172
|
+
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
173
|
+
_this.events.product[result.id].render = true;
|
|
174
|
+
_this.eventManager.fire('track.product.render', { controller: _this, products: [result], trackEvent: data });
|
|
175
|
+
},
|
|
176
|
+
impression: function (result) {
|
|
177
|
+
var _a, _b;
|
|
178
|
+
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.impression) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
var data = getSearchSchemaData({ params: _this.params, store: _this.store, results: [result] });
|
|
182
|
+
_this.tracker.events[_this.pageType].impression({ data: data, siteId: (_b = _this.config.globals) === null || _b === void 0 ? void 0 : _b.siteId });
|
|
183
|
+
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
184
|
+
_this.events.product[result.id].impression = true;
|
|
185
|
+
_this.eventManager.fire('track.product.impression', { controller: _this, products: [result], trackEvent: data });
|
|
186
|
+
},
|
|
187
|
+
addToCart: function (result) {
|
|
188
|
+
var _a;
|
|
189
|
+
var data = getSearchSchemaData({ params: _this.params, store: _this.store, results: [result] });
|
|
190
|
+
_this.tracker.events[_this.pageType].addToCart({
|
|
191
|
+
data: data,
|
|
192
|
+
siteId: (_a = _this.config.globals) === null || _a === void 0 ? void 0 : _a.siteId,
|
|
144
193
|
});
|
|
145
|
-
_this.eventManager.fire('track.product.
|
|
146
|
-
return event;
|
|
194
|
+
_this.eventManager.fire('track.product.addToCart', { controller: _this, products: [result], trackEvent: data });
|
|
147
195
|
},
|
|
148
196
|
},
|
|
197
|
+
redirect: function (redirectURL) {
|
|
198
|
+
var _a;
|
|
199
|
+
var data = getSearchRedirectSchemaData({ redirectURL: redirectURL });
|
|
200
|
+
_this.tracker.events.search.redirect({ data: data, siteId: (_a = _this.config.globals) === null || _a === void 0 ? void 0 : _a.siteId });
|
|
201
|
+
_this.eventManager.fire('track.product.redirect', { controller: _this, redirectURL: redirectURL, trackEvent: data });
|
|
202
|
+
},
|
|
149
203
|
};
|
|
150
204
|
_this.search = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
151
205
|
var params_1, err_1, stringyParams, prevStringyParams, searchProfile, meta, response, preventBackfill, dontBackfill, backfillRequests, backfillResponses, backfillResults, afterSearchProfile, err_2, afterStoreProfile, err_3, err_4;
|
|
@@ -163,9 +217,11 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
163
217
|
_o.label = 2;
|
|
164
218
|
case 2:
|
|
165
219
|
params_1 = this.params;
|
|
166
|
-
|
|
220
|
+
// reset events for new search
|
|
221
|
+
this.events = { product: {} };
|
|
222
|
+
if (((_d = (_c = params_1.search) === null || _c === void 0 ? void 0 : _c.query) === null || _d === void 0 ? void 0 : _d.string) && ((_f = (_e = params_1.search) === null || _e === void 0 ? void 0 : _e.query) === null || _f === void 0 ? void 0 : _f.string.length)) {
|
|
167
223
|
// save it to the history store
|
|
168
|
-
this.store.history.save(
|
|
224
|
+
this.store.history.save(params_1.search.query.string);
|
|
169
225
|
}
|
|
170
226
|
this.store.loading = true;
|
|
171
227
|
_o.label = 3;
|
|
@@ -373,6 +429,13 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
373
429
|
}
|
|
374
430
|
});
|
|
375
431
|
}); };
|
|
432
|
+
_this.addToCart = function (product) { return __awaiter(_this, void 0, void 0, function () {
|
|
433
|
+
return __generator(this, function (_a) {
|
|
434
|
+
this.track.product.addToCart(product);
|
|
435
|
+
this.eventManager.fire('addToCart', { controller: this, products: [product] });
|
|
436
|
+
return [2 /*return*/];
|
|
437
|
+
});
|
|
438
|
+
}); };
|
|
376
439
|
// deep merge config with defaults
|
|
377
440
|
_this.config = (0, deepmerge_1.default)(defaultConfig, _this.config);
|
|
378
441
|
// set restorePosition to be enabled by default when using infinite (if not provided)
|
|
@@ -386,6 +449,53 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
386
449
|
});
|
|
387
450
|
// set last params to undefined for compare in search
|
|
388
451
|
_this.storage.set('lastStringyParams', undefined);
|
|
452
|
+
_this.eventManager.on('beforeSearch', function (_a, next) {
|
|
453
|
+
var request = _a.request;
|
|
454
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
455
|
+
var req, query, hasCategoryBackgroundFilters;
|
|
456
|
+
var _b, _c, _d;
|
|
457
|
+
return __generator(this, function (_e) {
|
|
458
|
+
switch (_e.label) {
|
|
459
|
+
case 0:
|
|
460
|
+
// wait for other middleware to resolve
|
|
461
|
+
return [4 /*yield*/, next()];
|
|
462
|
+
case 1:
|
|
463
|
+
// wait for other middleware to resolve
|
|
464
|
+
_e.sent();
|
|
465
|
+
if (((_b = this.context) === null || _b === void 0 ? void 0 : _b.pageType) === 'category') {
|
|
466
|
+
this.pageType = 'category';
|
|
467
|
+
return [2 /*return*/];
|
|
468
|
+
}
|
|
469
|
+
req = request;
|
|
470
|
+
query = (_c = req.search) === null || _c === void 0 ? void 0 : _c.query;
|
|
471
|
+
if (!query) {
|
|
472
|
+
hasCategoryBackgroundFilters = (_d = req.filters) === null || _d === void 0 ? void 0 : _d.filter(function (filter) { return filter.background; }).filter(function (filter) {
|
|
473
|
+
return BACKGROUND_FILTER_FIELD_MATCHES.find(function (bgFilter) {
|
|
474
|
+
var _a;
|
|
475
|
+
return (_a = filter.field) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(bgFilter);
|
|
476
|
+
});
|
|
477
|
+
}).filter(function (filter) {
|
|
478
|
+
return BACKGROUND_FILTERS_VALUE_FLAGS.every(function (flag) {
|
|
479
|
+
switch (filter.type) {
|
|
480
|
+
case 'range':
|
|
481
|
+
var rangeFilter = filter;
|
|
482
|
+
return rangeFilter.value !== flag;
|
|
483
|
+
case 'value':
|
|
484
|
+
default:
|
|
485
|
+
var valueFilter = filter;
|
|
486
|
+
return valueFilter.value !== flag;
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
});
|
|
490
|
+
if (hasCategoryBackgroundFilters === null || hasCategoryBackgroundFilters === void 0 ? void 0 : hasCategoryBackgroundFilters.length) {
|
|
491
|
+
this.pageType = 'category';
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return [2 /*return*/];
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
});
|
|
389
499
|
// add 'afterSearch' middleware
|
|
390
500
|
_this.eventManager.on('afterSearch', function (search, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
391
501
|
var config, redirectURL, searchStore, nonBackgroundFilters;
|
|
@@ -399,6 +509,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
399
509
|
if (redirectURL && ((_d = (_c = config === null || config === void 0 ? void 0 : config.settings) === null || _c === void 0 ? void 0 : _c.redirects) === null || _d === void 0 ? void 0 : _d.merchandising) && !((_f = (_e = search === null || search === void 0 ? void 0 : search.response) === null || _e === void 0 ? void 0 : _e.filters) === null || _f === void 0 ? void 0 : _f.length) && !searchStore.loaded) {
|
|
400
510
|
//set loaded to true to prevent infinite search/reloading from happening
|
|
401
511
|
searchStore.loaded = true;
|
|
512
|
+
this.track.redirect(redirectURL);
|
|
402
513
|
window.location.replace(redirectURL);
|
|
403
514
|
return [2 /*return*/, false];
|
|
404
515
|
}
|
|
@@ -558,17 +669,15 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
558
669
|
}
|
|
559
670
|
params.tracking = params.tracking || {};
|
|
560
671
|
params.tracking.domain = window.location.href;
|
|
561
|
-
var
|
|
672
|
+
var _e = this.tracker.getContext(), userId = _e.userId, sessionId = _e.sessionId, pageLoadId = _e.pageLoadId, shopperId = _e.shopperId;
|
|
562
673
|
if (userId) {
|
|
563
674
|
params.tracking.userId = userId;
|
|
564
675
|
}
|
|
565
|
-
var sessionId = this.tracker.getContext().sessionId;
|
|
566
676
|
if (sessionId) {
|
|
567
677
|
params.tracking.sessionId = sessionId;
|
|
568
678
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
params.tracking.pageLoadId = pageId;
|
|
679
|
+
if (pageLoadId) {
|
|
680
|
+
params.tracking.pageLoadId = pageLoadId;
|
|
572
681
|
}
|
|
573
682
|
if (!((_d = (_c = this.config.globals) === null || _c === void 0 ? void 0 : _c.personalization) === null || _d === void 0 ? void 0 : _d.disabled)) {
|
|
574
683
|
var cartItems = this.tracker.cookies.cart.get();
|
|
@@ -581,7 +690,6 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
581
690
|
params.personalization = params.personalization || {};
|
|
582
691
|
params.personalization.lastViewed = lastViewedItems.join(',');
|
|
583
692
|
}
|
|
584
|
-
var shopperId = this.tracker.getShopperId();
|
|
585
693
|
if (shopperId) {
|
|
586
694
|
params.personalization = params.personalization || {};
|
|
587
695
|
params.personalization.shopper = shopperId;
|
|
@@ -641,3 +749,66 @@ function generateHrefSelector(element, href, levels) {
|
|
|
641
749
|
return;
|
|
642
750
|
}
|
|
643
751
|
exports.generateHrefSelector = generateHrefSelector;
|
|
752
|
+
function getSearchRedirectSchemaData(_a) {
|
|
753
|
+
var redirectURL = _a.redirectURL;
|
|
754
|
+
return {
|
|
755
|
+
redirect: redirectURL,
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
function getSearchSchemaData(_a) {
|
|
759
|
+
var _b, _c, _d, _e, _f, _g, _h, _j;
|
|
760
|
+
var params = _a.params, store = _a.store, results = _a.results;
|
|
761
|
+
var filters = (_b = params.filters) === null || _b === void 0 ? void 0 : _b.reduce(function (acc, filter) {
|
|
762
|
+
var _a;
|
|
763
|
+
var _b, _c, _d, _e;
|
|
764
|
+
var key = filter.background ? 'bgfilter' : 'filter';
|
|
765
|
+
acc[key] = acc[key] || [];
|
|
766
|
+
var value = filter.type === 'range' &&
|
|
767
|
+
!isNaN((_b = filter.value) === null || _b === void 0 ? void 0 : _b.low) &&
|
|
768
|
+
!isNaN((_c = filter.value) === null || _c === void 0 ? void 0 : _c.low)
|
|
769
|
+
? ["low=".concat((_d = filter.value) === null || _d === void 0 ? void 0 : _d.low), "high=".concat((_e = filter.value) === null || _e === void 0 ? void 0 : _e.high)]
|
|
770
|
+
: ["".concat(filter.value)];
|
|
771
|
+
var existing = acc[key].find(function (item) { return item.field === filter.field; });
|
|
772
|
+
if (existing && !existing.value.includes(value[0])) {
|
|
773
|
+
(_a = existing.value).push.apply(_a, value);
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
acc[key].push({
|
|
777
|
+
field: filter.field,
|
|
778
|
+
value: value,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
return acc;
|
|
782
|
+
}, {});
|
|
783
|
+
return __assign(__assign({ q: ((_d = (_c = params.search) === null || _c === void 0 ? void 0 : _c.query) === null || _d === void 0 ? void 0 : _d.string) || '', correctedQuery: (_e = params.search) === null || _e === void 0 ? void 0 : _e.originalQuery }, filters), { sort: [
|
|
784
|
+
{
|
|
785
|
+
field: (_f = store.sorting.current) === null || _f === void 0 ? void 0 : _f.field,
|
|
786
|
+
dir: (_g = store.sorting.current) === null || _g === void 0 ? void 0 : _g.direction,
|
|
787
|
+
},
|
|
788
|
+
], pagination: {
|
|
789
|
+
totalResults: store.pagination.totalResults,
|
|
790
|
+
page: store.pagination.page,
|
|
791
|
+
resultsPerPage: store.pagination.pageSize,
|
|
792
|
+
}, merchandising: {
|
|
793
|
+
personalized: store.merchandising.personalized,
|
|
794
|
+
redirect: store.merchandising.redirect,
|
|
795
|
+
triggeredCampaigns: (((_h = store.merchandising.campaigns) === null || _h === void 0 ? void 0 : _h.length) &&
|
|
796
|
+
((_j = store.merchandising.campaigns) === null || _j === void 0 ? void 0 : _j.map(function (campaign) {
|
|
797
|
+
var experiement = store.merchandising.experiments.find(function (experiment) { return experiment.campaignId === campaign.id; });
|
|
798
|
+
return {
|
|
799
|
+
id: campaign.id,
|
|
800
|
+
experimentId: experiement === null || experiement === void 0 ? void 0 : experiement.experimentId,
|
|
801
|
+
variationId: experiement === null || experiement === void 0 ? void 0 : experiement.variationId,
|
|
802
|
+
};
|
|
803
|
+
}))) ||
|
|
804
|
+
undefined,
|
|
805
|
+
}, results: (results === null || results === void 0 ? void 0 : results.map(function (result) {
|
|
806
|
+
var core = result.mappings.core;
|
|
807
|
+
return {
|
|
808
|
+
uid: core.uid || '',
|
|
809
|
+
// childUid: core.uid,
|
|
810
|
+
sku: core.sku,
|
|
811
|
+
// childSku: core.sku,
|
|
812
|
+
};
|
|
813
|
+
})) || [] });
|
|
814
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { StorageStore } from '@searchspring/snap-store-mobx';
|
|
2
|
+
import { StorageStore, Product, Banner } from '@searchspring/snap-store-mobx';
|
|
3
3
|
import { AbstractController } from '../Abstract/AbstractController';
|
|
4
4
|
import { ControllerTypes } from '../types';
|
|
5
5
|
import { AutocompleteStore } from '@searchspring/snap-store-mobx';
|
|
@@ -8,14 +8,26 @@ import type { AutocompleteRequestModel } from '@searchspring/snapi-types';
|
|
|
8
8
|
export declare const INPUT_DELAY = 200;
|
|
9
9
|
type AutocompleteTrackMethods = {
|
|
10
10
|
product: {
|
|
11
|
-
|
|
11
|
+
clickThrough: (e: MouseEvent, result: Product) => void;
|
|
12
|
+
click: (e: MouseEvent, result: Product | Banner) => void;
|
|
13
|
+
render: (result: Product) => void;
|
|
14
|
+
impression: (result: Product) => void;
|
|
15
|
+
addToCart: (results: Product) => void;
|
|
12
16
|
};
|
|
17
|
+
redirect: (redirectURL: string) => void;
|
|
13
18
|
};
|
|
14
19
|
export declare class AutocompleteController extends AbstractController {
|
|
15
20
|
type: ControllerTypes;
|
|
16
21
|
store: AutocompleteStore;
|
|
17
22
|
config: AutocompleteControllerConfig;
|
|
18
23
|
storage: StorageStore;
|
|
24
|
+
events: {
|
|
25
|
+
product: Record<string, {
|
|
26
|
+
clickThrough?: boolean;
|
|
27
|
+
impression?: boolean;
|
|
28
|
+
render?: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
19
31
|
constructor(config: AutocompleteControllerConfig, { client, store, urlManager, eventManager, profiler, logger, tracker }: ControllerServices, context?: ContextVariables);
|
|
20
32
|
track: AutocompleteTrackMethods;
|
|
21
33
|
get params(): AutocompleteRequestModel;
|
|
@@ -39,6 +51,7 @@ export declare class AutocompleteController extends AbstractController {
|
|
|
39
51
|
bind(): Promise<void>;
|
|
40
52
|
searchTrending: () => Promise<void>;
|
|
41
53
|
search: () => Promise<void>;
|
|
54
|
+
addToCart: (product: Product) => Promise<void>;
|
|
42
55
|
}
|
|
43
56
|
export {};
|
|
44
57
|
//# sourceMappingURL=AutocompleteController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAa,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAa,OAAO,EAAqB,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,4BAA4B,EAAiC,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElI,OAAO,KAAK,EAAE,wBAAwB,EAAgE,MAAM,2BAA2B,CAAC;AAWxI,eAAO,MAAM,WAAW,MAAM,CAAC;AA+B/B,KAAK,wBAAwB,GAAG;IAC/B,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACvD,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QACzD,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACtC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;KACtC,CAAC;IACF,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,qBAAa,sBAAuB,SAAQ,kBAAkB;IACtD,IAAI,kBAAgC;IACnC,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;IACtC,OAAO,EAAE,YAAY,CAAC;IAE7B,MAAM,EAAE;QACP,OAAO,EAAE,MAAM,CACd,MAAM,EACN;YACC,YAAY,CAAC,EAAE,OAAO,CAAC;YACvB,UAAU,CAAC,EAAE,OAAO,CAAC;YACrB,MAAM,CAAC,EAAE,OAAO,CAAC;SACjB,CACD,CAAC;KACF,CAEC;gBAGD,MAAM,EAAE,4BAA4B,EACpC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA0D3B,KAAK,EAAE,wBAAwB,CAqD7B;IAEF,IAAI,MAAM,IAAI,wBAAwB,CAwCrC;IAEK,UAAU,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhE,KAAK,IAAI,IAAI;IASb,QAAQ;;0BAEc,aAAa,KAAG,QAAQ,OAAO,GAAG,SAAS,CAAC;wBAkDpD,aAAa,KAAG,IAAI;uBAMrB,UAAU,KAAG,IAAI;4BAQN,MAAM,SAAS,CAAC,gBAAgB,CAAC,KAAG,QAAQ,IAAI,CAAC;mCAgDhD,MAAM,WAAW,CAAC,gBAAgB,CAAC,KAAG,IAAI;uBAqBtD,KAAK;;;;uBAyDL,UAAU,KAAG,IAAI;;MAS5B;IAEF,MAAM,IAAI,IAAI;IAgBR,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgF3B,cAAc,QAAa,QAAQ,IAAI,CAAC,CAwBtC;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CA6I9B;IAEF,SAAS,YAAmB,OAAO,KAAG,QAAQ,IAAI,CAAC,CAGjD;CACF"}
|
|
@@ -37,12 +37,62 @@ export class AutocompleteController extends AbstractController {
|
|
|
37
37
|
constructor(config, { client, store, urlManager, eventManager, profiler, logger, tracker }, context) {
|
|
38
38
|
super(config, { client, store, urlManager, eventManager, profiler, logger, tracker }, context);
|
|
39
39
|
this.type = ControllerTypes.autocomplete;
|
|
40
|
+
this.events = {
|
|
41
|
+
product: {},
|
|
42
|
+
};
|
|
40
43
|
this.track = {
|
|
41
|
-
// TODO: add in future when autocomplete supports result click tracking
|
|
42
44
|
product: {
|
|
43
|
-
|
|
44
|
-
this.
|
|
45
|
+
clickThrough: (e, result) => {
|
|
46
|
+
if (this.events.product[result.id]?.clickThrough) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
50
|
+
this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
51
|
+
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
52
|
+
this.events.product[result.id].clickThrough = true;
|
|
53
|
+
this.eventManager.fire('track.product.clickThrough', { controller: this, event: e, products: [result], trackEvent: data });
|
|
54
|
+
},
|
|
55
|
+
click: (e, result) => {
|
|
56
|
+
if (result.type === 'banner') {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// TODO: closest might be going too far - write own function to only go n levels up - additionally check that href includes result.url
|
|
60
|
+
const href = e.target?.getAttribute('href') || e.target?.closest('a')?.getAttribute('href');
|
|
61
|
+
if (href) {
|
|
62
|
+
this.track.product.clickThrough(e, result);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// TODO: in future, send as an interaction event
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
render: (result) => {
|
|
69
|
+
if (this.events.product[result.id]?.render)
|
|
70
|
+
return;
|
|
71
|
+
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
72
|
+
this.tracker.events.autocomplete.render({ data, siteId: this.config.globals?.siteId });
|
|
73
|
+
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
74
|
+
this.events.product[result.id].render = true;
|
|
75
|
+
this.eventManager.fire('track.product.render', { controller: this, products: [result], trackEvent: data });
|
|
76
|
+
},
|
|
77
|
+
impression: (result) => {
|
|
78
|
+
if (this.events.product[result.id]?.impression)
|
|
79
|
+
return;
|
|
80
|
+
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
81
|
+
this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
82
|
+
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
83
|
+
this.events.product[result.id].impression = true;
|
|
84
|
+
this.eventManager.fire('track.product.impression', { controller: this, products: [result], trackEvent: data });
|
|
45
85
|
},
|
|
86
|
+
addToCart: (result) => {
|
|
87
|
+
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
88
|
+
this.tracker.events.autocomplete.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
89
|
+
this.eventManager.fire('track.product.addToCart', { controller: this, products: [result], trackEvent: data });
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
redirect: (redirectURL) => {
|
|
93
|
+
const data = getAutocompleteRedirectSchemaData({ redirectURL });
|
|
94
|
+
this.tracker.events.autocomplete.redirect({ data, siteId: this.config.globals?.siteId });
|
|
95
|
+
this.eventManager.fire('track.product.redirect', { controller: this, redirectURL, trackEvent: data });
|
|
46
96
|
},
|
|
47
97
|
};
|
|
48
98
|
this.handlers = {
|
|
@@ -257,6 +307,8 @@ export class AutocompleteController extends AbstractController {
|
|
|
257
307
|
if (!this.initialized) {
|
|
258
308
|
await this.init();
|
|
259
309
|
}
|
|
310
|
+
// reset events for new search
|
|
311
|
+
this.events = { product: {} };
|
|
260
312
|
// if urlManager has no query, there will be no need to get params and no query
|
|
261
313
|
if (!this.urlManager.state.query) {
|
|
262
314
|
return;
|
|
@@ -382,6 +434,10 @@ export class AutocompleteController extends AbstractController {
|
|
|
382
434
|
this.store.loading = false;
|
|
383
435
|
}
|
|
384
436
|
};
|
|
437
|
+
this.addToCart = async (product) => {
|
|
438
|
+
this.track.product.addToCart(product);
|
|
439
|
+
this.eventManager.fire('addToCart', { controller: this, products: [product] });
|
|
440
|
+
};
|
|
385
441
|
// deep merge config with defaults
|
|
386
442
|
this.config = deepmerge(defaultConfig, this.config);
|
|
387
443
|
this.store.setConfig(this.config);
|
|
@@ -409,6 +465,7 @@ export class AutocompleteController extends AbstractController {
|
|
|
409
465
|
await next();
|
|
410
466
|
const redirectURL = ac.controller.store.merchandising?.redirect;
|
|
411
467
|
if (redirectURL && this.config?.settings?.redirects?.merchandising) {
|
|
468
|
+
this.track.redirect(redirectURL);
|
|
412
469
|
window.location.href = redirectURL;
|
|
413
470
|
return false;
|
|
414
471
|
}
|
|
@@ -429,9 +486,7 @@ export class AutocompleteController extends AbstractController {
|
|
|
429
486
|
get params() {
|
|
430
487
|
const urlState = this.urlManager.state;
|
|
431
488
|
const params = deepmerge({ ...getSearchParams(urlState) }, this.config.globals);
|
|
432
|
-
const userId = this.tracker.
|
|
433
|
-
const sessionId = this.tracker.getContext().sessionId;
|
|
434
|
-
const pageLoadId = this.tracker.getContext().pageLoadId;
|
|
489
|
+
const { userId, sessionId, pageLoadId, shopperId } = this.tracker.getContext();
|
|
435
490
|
params.tracking = params.tracking || {};
|
|
436
491
|
params.tracking.domain = window.location.href;
|
|
437
492
|
if (userId) {
|
|
@@ -454,7 +509,6 @@ export class AutocompleteController extends AbstractController {
|
|
|
454
509
|
params.personalization = params.personalization || {};
|
|
455
510
|
params.personalization.lastViewed = lastViewedItems.join(',');
|
|
456
511
|
}
|
|
457
|
-
const shopperId = this.tracker.getShopperId();
|
|
458
512
|
if (shopperId) {
|
|
459
513
|
params.personalization = params.personalization || {};
|
|
460
514
|
params.personalization.shopper = shopperId;
|
|
@@ -633,3 +687,69 @@ function unbindFormParameters(form, fn) {
|
|
|
633
687
|
}
|
|
634
688
|
}
|
|
635
689
|
}
|
|
690
|
+
function getAutocompleteRedirectSchemaData({ redirectURL }) {
|
|
691
|
+
return {
|
|
692
|
+
redirect: redirectURL,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function getAutocompleteSchemaData({ params, store, results, }) {
|
|
696
|
+
const filters = params.filters?.reduce((acc, filter) => {
|
|
697
|
+
const key = filter.background ? 'bgfilter' : 'filter';
|
|
698
|
+
acc[key] = acc[key] || [];
|
|
699
|
+
const value = filter.type === 'range' &&
|
|
700
|
+
!isNaN(filter.value?.low) &&
|
|
701
|
+
!isNaN(filter.value?.low)
|
|
702
|
+
? [`low=${filter.value?.low}`, `high=${filter.value?.high}`]
|
|
703
|
+
: [`${filter.value}`];
|
|
704
|
+
const existing = acc[key].find((item) => item.field === filter.field);
|
|
705
|
+
if (existing && !existing.value.includes(value[0])) {
|
|
706
|
+
existing.value.push(...value);
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
acc[key].push({
|
|
710
|
+
field: filter.field,
|
|
711
|
+
value,
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
return acc;
|
|
715
|
+
}, {});
|
|
716
|
+
return {
|
|
717
|
+
q: params.search?.query?.string || '',
|
|
718
|
+
correctedQuery: params.search?.originalQuery || '',
|
|
719
|
+
...filters,
|
|
720
|
+
sort: [
|
|
721
|
+
{
|
|
722
|
+
field: store.sorting.current?.field,
|
|
723
|
+
dir: store.sorting.current?.direction,
|
|
724
|
+
},
|
|
725
|
+
],
|
|
726
|
+
pagination: {
|
|
727
|
+
totalResults: store.pagination.totalResults,
|
|
728
|
+
page: store.pagination.page,
|
|
729
|
+
resultsPerPage: store.pagination.pageSize,
|
|
730
|
+
},
|
|
731
|
+
merchandising: {
|
|
732
|
+
personalized: store.merchandising.personalized,
|
|
733
|
+
redirect: store.merchandising.redirect,
|
|
734
|
+
triggeredCampaigns: (store.merchandising.campaigns?.length &&
|
|
735
|
+
store.merchandising.campaigns?.map((campaign) => {
|
|
736
|
+
const experiement = store.merchandising.experiments.find((experiment) => experiment.campaignId === campaign.id);
|
|
737
|
+
return {
|
|
738
|
+
id: campaign.id,
|
|
739
|
+
experimentId: experiement?.experimentId,
|
|
740
|
+
variationId: experiement?.variationId,
|
|
741
|
+
};
|
|
742
|
+
})) ||
|
|
743
|
+
undefined,
|
|
744
|
+
},
|
|
745
|
+
results: results?.map((result) => {
|
|
746
|
+
const core = result.mappings.core;
|
|
747
|
+
return {
|
|
748
|
+
uid: core.uid || '',
|
|
749
|
+
// childUid: core.uid,
|
|
750
|
+
sku: core.sku,
|
|
751
|
+
// childSku: core.sku,
|
|
752
|
+
};
|
|
753
|
+
}) || [],
|
|
754
|
+
};
|
|
755
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FinderController.d.ts","sourceRoot":"","sources":["../../../src/Finder/FinderController.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAkB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAiB7G,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;gBAGtC,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA+B3B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"FinderController.d.ts","sourceRoot":"","sources":["../../../src/Finder/FinderController.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAkB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAiB7G,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;gBAGtC,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA+B3B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA6BhC;IAED,IAAI,QAAa,QAAQ,IAAI,CAAC,CAkB5B;IAEF,KAAK,QAAO,IAAI,CAId;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CAoI9B;CACF"}
|
|
@@ -194,9 +194,7 @@ export class FinderController extends AbstractController {
|
|
|
194
194
|
}
|
|
195
195
|
get params() {
|
|
196
196
|
const urlState = this.urlManager.state;
|
|
197
|
-
const userId = this.tracker.
|
|
198
|
-
const sessionId = this.tracker.getContext().sessionId;
|
|
199
|
-
const pageLoadId = this.tracker.getContext().pageLoadId;
|
|
197
|
+
const { userId, sessionId, pageLoadId } = this.tracker.getContext();
|
|
200
198
|
const tracking = {};
|
|
201
199
|
if (userId) {
|
|
202
200
|
tracking.userId = userId;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Product } from '@searchspring/snap-store-mobx';
|
|
2
|
-
import { BeaconEvent } from '@searchspring/snap-tracker';
|
|
3
2
|
import { AbstractController } from '../Abstract/AbstractController';
|
|
4
3
|
import { ControllerTypes } from '../types';
|
|
5
4
|
import type { RecommendationStore } from '@searchspring/snap-store-mobx';
|
|
@@ -7,28 +6,25 @@ import type { RecommendRequestModel } from '@searchspring/snap-client';
|
|
|
7
6
|
import type { RecommendationControllerConfig, ControllerServices, ContextVariables } from '../types';
|
|
8
7
|
type RecommendationTrackMethods = {
|
|
9
8
|
product: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
clickThrough: (e: MouseEvent, result: Product) => void;
|
|
10
|
+
click: (e: MouseEvent, result: Product) => void;
|
|
11
|
+
render: (result: Product) => void;
|
|
12
|
+
impression: (result: Product) => void;
|
|
13
|
+
addToCart: (result: Product) => void;
|
|
14
|
+
};
|
|
15
|
+
bundle: {
|
|
16
|
+
addToCart: (results: Product[]) => void;
|
|
15
17
|
};
|
|
16
|
-
click: (e: MouseEvent) => BeaconEvent | undefined;
|
|
17
|
-
addBundle: (e: MouseEvent, results: Product[]) => BeaconEvent | undefined;
|
|
18
|
-
impression: () => BeaconEvent | undefined;
|
|
19
|
-
render: (results?: Product[]) => BeaconEvent | undefined;
|
|
20
18
|
};
|
|
21
19
|
export declare class RecommendationController extends AbstractController {
|
|
22
20
|
type: ControllerTypes;
|
|
23
21
|
store: RecommendationStore;
|
|
24
22
|
config: RecommendationControllerConfig;
|
|
25
23
|
events: {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
impression?: BeaconEvent;
|
|
31
|
-
render?: BeaconEvent;
|
|
24
|
+
product: Record<string, {
|
|
25
|
+
clickThrough?: boolean;
|
|
26
|
+
impression?: boolean;
|
|
27
|
+
render?: boolean;
|
|
32
28
|
}>;
|
|
33
29
|
};
|
|
34
30
|
constructor(config: RecommendationControllerConfig, { client, store, urlManager, eventManager, profiler, logger, tracker }: ControllerServices, context?: ContextVariables);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecommendationController.d.ts","sourceRoot":"","sources":["../../../src/Recommendation/RecommendationController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RecommendationController.d.ts","sourceRoot":"","sources":["../../../src/Recommendation/RecommendationController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIrG,KAAK,0BAA0B,GAAG;IACjC,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACvD,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QAChD,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACtC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;KACrC,CAAC;IACF,MAAM,EAAE;QACP,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;KACxC,CAAC;CACF,CAAC;AAUF,qBAAa,wBAAyB,SAAQ,kBAAkB;IACxD,IAAI,kBAAkC;IACrC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,8BAA8B,CAAC;IAE/C,MAAM,EAAE;QACP,OAAO,EAAE,MAAM,CACd,MAAM,EACN;YACC,YAAY,CAAC,EAAE,OAAO,CAAC;YACvB,UAAU,CAAC,EAAE,OAAO,CAAC;YACrB,MAAM,CAAC,EAAE,OAAO,CAAC;SACjB,CACD,CAAC;KACF,CAEC;gBAGD,MAAM,EAAE,8BAA8B,EACtC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IAwC3B,KAAK,EAAE,0BAA0B,CAyD/B;IAEF,IAAI,MAAM,IAAI,qBAAqB,CA4BlC;IAED,MAAM,QAAa,QAAQ,IAAI,CAAC,CA6H9B;CACF"}
|