@depict-ai/ui 1.1.4 → 1.2.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.
@@ -43,7 +43,7 @@ $parcel$export(module.exports, "defaultGridSpacing", () => $a3280f0aad997933$exp
43
43
  $parcel$export(module.exports, "defaultColsAtSize", () => $a3280f0aad997933$export$c3834fa86c616831);
44
44
  $parcel$export(module.exports, "defaultCategoryTitlePlugin", () => $a3280f0aad997933$export$7bf543b9d9be2c22);
45
45
  $parcel$export(module.exports, "version", () => $b757f75811f3261f$export$83d89fbfd8236492);
46
- /*! Depict.ai search and product listing SDK */ const $b757f75811f3261f$export$83d89fbfd8236492 = "1.1.4";
46
+ /*! Depict.ai search and product listing SDK */ const $b757f75811f3261f$export$83d89fbfd8236492 = "1.2.0";
47
47
 
48
48
 
49
49
 
@@ -244,26 +244,77 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
244
244
  #get_metadata;
245
245
  #get_user_id;
246
246
  #get_session_id;
247
- constructor({ get_metadata: get_metadata , get_user_id: get_user_id , get_session_id: get_session_id } = {}){
248
- this.#get_metadata = get_metadata;
249
- this.#get_user_id = get_user_id;
250
- this.#get_session_id = get_session_id;
247
+ #guard_url_creator_length(expected, received) {
248
+ if (expected.length !== received.length) {
249
+ const e = new Error("Page URL creator returned wrong number of page URLs, got " + received.length + ", expected " + expected.length);
250
+ queueMicrotask(()=>{
251
+ throw e;
252
+ });
253
+ throw e;
254
+ }
251
255
  }
252
- async suggest(input_req) {
253
- const request = this.#add_ids_to_request(input_req);
254
- const url = (0, $57o7A$depictaiutilishared.make_url_with_query_params)($e1d6c0f3d89d531c$var$search_base_url + "suggestions", request);
255
- const results = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(url));
256
- attempt_to_return_api_response: {
257
- if (!results) break attempt_to_return_api_response;
258
- const decoded_json = await results.json();
259
- if (!Array.isArray(decoded_json?.suggestions)) break attempt_to_return_api_response;
260
- return decoded_json;
256
+ async #run_url_creator_for_suggest(merchant, market, response) {
257
+ if (!this.page_url_creator) return response;
258
+ // find category suggestions, run thing with them, and then replace them
259
+ const category_suggestions = response.suggestions.filter((suggestion)=>suggestion.type === "category");
260
+ const page_urls = await this.page_url_creator({
261
+ type: "categories",
262
+ market: market,
263
+ merchant: merchant,
264
+ data: [
265
+ ...category_suggestions
266
+ ]
267
+ });
268
+ this.#guard_url_creator_length(category_suggestions, page_urls);
269
+ while(page_urls.length)Object.assign(category_suggestions.pop(), page_urls.pop());
270
+ return response;
271
+ }
272
+ async #run_url_creator_for_rest(merchant1, market1, input_data) {
273
+ if (!this.page_url_creator) return input_data;
274
+ const displays = input_data.displays;
275
+ const breadcrumb = input_data.breadcrumb;
276
+ const quick_links = input_data.quick_links;
277
+ if (displays) {
278
+ const page_urls = await this.page_url_creator({
279
+ type: "products",
280
+ merchant: merchant1,
281
+ market: market1,
282
+ displays: [
283
+ ...input_data.displays
284
+ ]
285
+ });
286
+ this.#guard_url_creator_length(displays, page_urls);
287
+ for(let i = 0; i < displays.length; i++){
288
+ const new_display_or_page_url = page_urls[i];
289
+ const old_display = displays[i];
290
+ if ("page_url" in new_display_or_page_url && Object.keys(new_display_or_page_url).length === 1) {
291
+ // they only returned page_url, let's put it into the display
292
+ const old_display_was_modern = "variant_index" in old_display;
293
+ if (old_display_was_modern) {
294
+ const variant_displays = old_display.variant_displays;
295
+ for(let i = 0; i < variant_displays.length; i++)variant_displays[i].page_url = new_display_or_page_url.page_url;
296
+ } else old_display.page_url = new_display_or_page_url.page_url;
297
+ } else // We got a whole new display, let's replace it
298
+ displays[i] = new_display_or_page_url;
299
+ }
261
300
  }
262
- return {
263
- "suggestions_request_id": "error",
264
- "suggestions": [],
265
- failed: true
266
- };
301
+ for (const category_display_array of [
302
+ breadcrumb,
303
+ quick_links
304
+ ]){
305
+ if (!category_display_array) continue;
306
+ const page_urls = await this.page_url_creator({
307
+ type: "categories",
308
+ merchant: merchant1,
309
+ market: market1,
310
+ data: [
311
+ ...category_display_array
312
+ ]
313
+ });
314
+ this.#guard_url_creator_length(category_display_array, page_urls);
315
+ for(let i = 0; i < category_display_array.length; i++)Object.assign(category_display_array[i], page_urls[i]);
316
+ }
317
+ return input_data;
267
318
  }
268
319
  async #cached_post_request(endpoint1, input_req, fallback_response) {
269
320
  const cache_obj = this.#get_cache_obj_for_endpoint(endpoint1);
@@ -280,66 +331,101 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
280
331
  let resolve_in_progress;
281
332
  cache_obj.in_progress_[body] = new Promise((r)=>resolve_in_progress = r);
282
333
  try {
283
- let search_results = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(endpoint1), {
334
+ let api_response = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(endpoint1), {
284
335
  method: "POST",
285
336
  body: body
286
337
  });
287
338
  if ("query_id" in request && request.type === "collection") // FIXME: Remove. Backwards compatibility layer
288
339
  // This will retry the request without the collection type if the first request fails
289
340
  {
290
- if (!search_results || search_results?.status === 404) {
341
+ if (!api_response || api_response?.status === 404) {
291
342
  (0, $57o7A$depictaiutilishared.dlog)("Fallback request for collections due to failure");
292
343
  const fallback_body = JSON.parse(body);
293
344
  delete fallback_body.type;
294
- search_results = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(endpoint1), {
345
+ api_response = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(endpoint1), {
295
346
  method: "POST",
296
347
  body: JSON.stringify(fallback_body)
297
348
  });
298
349
  }
299
350
  }
300
- if (!search_results || search_results.status !== 200) {
301
- const retval = fallback_response(input_req);
302
- resolve_in_progress(retval);
303
- return retval;
351
+ return_successfully: {
352
+ if (!api_response || api_response.status !== 200) break return_successfully;
353
+ let result;
354
+ try {
355
+ const unmodified_result = await api_response.json();
356
+ result = await this.#run_url_creator_for_rest(input_req.tenant, input_req.market, unmodified_result);
357
+ } catch (e) {
358
+ (0, $57o7A$depictaiutilishared.dwarn)("URL creator or json decoding failed", e);
359
+ break return_successfully;
360
+ }
361
+ cache_obj.cache_[body] = new WeakRef(result);
362
+ resolve_in_progress(result);
363
+ setTimeout((0, $57o7A$depictaiutilishared.catchify)(()=>{
364
+ if (this.#supports_finalization_registry) cache_obj.finalization_registry_.register(result, body); // delete key from cache when value (WeakRefs) are collected
365
+ else // delete things from cache after 5 minutes, so it doesn't get too heavy
366
+ setTimeout((0, $57o7A$depictaiutilishared.catchify)(()=>delete cache_obj.cache_[body]), 300000);
367
+ }), 60000 // cache values for at least 60 seconds
368
+ );
369
+ return result;
304
370
  }
305
- const result = await search_results.json();
306
- cache_obj.cache_[body] = new WeakRef(result);
307
- resolve_in_progress(result);
308
- setTimeout((0, $57o7A$depictaiutilishared.catchify)(()=>{
309
- if (this.#supports_finalization_registry) cache_obj.finalization_registry_.register(result, body); // delete key from cache when value (WeakRefs) are collected
310
- else // delete things from cache after 5 minutes, so it doesn't get too heavy
311
- setTimeout((0, $57o7A$depictaiutilishared.catchify)(()=>delete cache_obj.cache_[body]), 300000);
312
- }), 30000 // cache values for at least 30 seconds
313
- );
314
- return result;
371
+ // If we get here, the request failed
372
+ const retval = fallback_response(input_req);
373
+ resolve_in_progress(retval);
374
+ return retval;
315
375
  } finally{
316
376
  delete cache_obj.in_progress_[body];
317
377
  }
318
378
  }
379
+ constructor(options){
380
+ const { get_metadata: get_metadata , get_user_id: get_user_id , get_session_id: get_session_id , page_url_creator: page_url_creator } = options ?? {};
381
+ this.#get_metadata = get_metadata;
382
+ this.#get_user_id = get_user_id;
383
+ this.#get_session_id = get_session_id;
384
+ this.page_url_creator = page_url_creator;
385
+ }
386
+ async suggest(input_req) {
387
+ const request = this.#add_ids_to_request(input_req);
388
+ const url = (0, $57o7A$depictaiutilishared.make_url_with_query_params)($e1d6c0f3d89d531c$var$search_base_url + "suggestions", request);
389
+ const results = await (0, $57o7A$depictaiutilishared.fetch_retry)((0, $57o7A$depictaiutilishared.add_version_query_params)(url));
390
+ attempt_to_return_api_response: {
391
+ if (!results) break attempt_to_return_api_response;
392
+ const decoded_json = await results.json();
393
+ if (!Array.isArray(decoded_json?.suggestions)) break attempt_to_return_api_response;
394
+ try {
395
+ return await this.#run_url_creator_for_suggest(input_req.tenant, input_req.market, decoded_json);
396
+ } catch (e) {
397
+ (0, $57o7A$depictaiutilishared.dwarn)("URL creator failed", e);
398
+ }
399
+ }
400
+ return {
401
+ "suggestions_request_id": "error",
402
+ "suggestions": [],
403
+ failed: true
404
+ };
405
+ }
319
406
  async query(input_req) {
320
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "results", input_req, (request)=>({
407
+ return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "results", input_req, ()=>({
321
408
  "n_hits": 0,
322
- "page": request.page ?? 1,
323
409
  "displays": [],
324
- "facets": [],
325
- "suggestions": [],
410
+ "sorts": [],
411
+ "filters": [],
326
412
  "search_request_id": "error",
327
413
  failed: true
328
414
  }));
329
415
  }
330
416
  async list(input_req) {
331
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$v2_base_url + "product-listing", input_req, (request)=>({
417
+ return await this.#cached_post_request($e1d6c0f3d89d531c$var$v2_base_url + "product-listing", input_req, ()=>({
332
418
  "n_hits": 0,
333
- "page": request.page ?? 1,
334
419
  "displays": [],
335
- "facets": [],
336
- "suggestions": [],
420
+ "sorts": [],
421
+ "filters": [],
422
+ "breadcrumb": [],
423
+ "quick_links": [],
337
424
  "product_listing_request_id": "error",
338
425
  failed: true
339
426
  }));
340
427
  }
341
428
  async get_recommended(input_req) {
342
- // @ts-ignore ModernDisplay doesn't have arbitrary string access, and we'd like it to stay that way
343
429
  return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "related", input_req, ()=>({
344
430
  displays: []
345
431
  }));
@@ -1189,6 +1275,7 @@ function $ac167f6af6a48fc3$export$a1fd619a4743ca08({ plp_results_: plp_results_
1189
1275
  const record = records[i];
1190
1276
  const { target: target , intersectionRatio: intersectionRatio } = record;
1191
1277
  const index_of_target = target_to_index_map.get(target);
1278
+ if (index_of_target == undefined) return; // It seems like it can happen that we get IntersectionObserverEntries after the onCleanup function for a recommendation card has run, in Firefox. Probably a bug in Firefox? If I understood the bug correctly, this is a workaround.
1192
1279
  const is_in_set = currently_intersecting.has(index_of_target);
1193
1280
  if (intersectionRatio > 0) {
1194
1281
  if (!is_in_set) currently_intersecting.add(index_of_target);
@@ -5108,23 +5195,30 @@ function $276380e4607fb9fb$export$6e49da55e449af7c({ scroll_restoration_data_: [
5108
5195
  ]); // get rid of old data the browser saves the old state and will restore it later on
5109
5196
  };
5110
5197
  (0, $57o7A$solidjs.createComputed)((0, $57o7A$depictaiutilishared.catchify)(()=>{
5111
- const r = get_last_result_in_viewport_();
5112
- if (r == undefined || r <= 0 || r == Infinity) return;
5198
+ const last_result = get_last_result_in_viewport_();
5199
+ if (last_result == undefined || last_result <= 0 || last_result == Infinity) return;
5200
+ if (isNaN(last_result)) {
5201
+ // if last_result is NaN there's an issue somewhere, but if we store something here that's not a number the for loop further down will break, and we won't be able to load results at all, so let's just continue
5202
+ (0, $57o7A$depictaiutilishared.report)(new Error("last_result is NaN, this should not happen"), "error", {
5203
+ last_result: last_result
5204
+ });
5205
+ return;
5206
+ }
5113
5207
  // We can push to history.state max 100 times per 30 seconds (Safari) so we have to debounce/cap this at 300ms for aggressive scrolling.
5114
5208
  // Pushing to history.state right before we leave the page (onunload etc.) is unreliable, as it has to occur *before* the next page is pushed to history.
5115
- // Instead we delay our push with a timeout set to the next acceptable interval to the previous one, when necessary
5209
+ // Instead, we delay our push with a timeout set to the next acceptable interval to the previous one, when necessary
5116
5210
  const now = +new Date();
5117
5211
  const time_since_last_ran = now - last_time_history_changed;
5118
5212
  if (time_since_last_ran > $276380e4607fb9fb$var$max_history_change_frequency) {
5119
5213
  // If the interval to the previous push is already long enough, it's fine to push the next value directly.
5120
- set_min_results_loaded(r);
5214
+ set_min_results_loaded(last_result);
5121
5215
  last_time_history_changed = now;
5122
5216
  // Even though the interval has passed, there could still be a delayed push timeout in flight (browser can delay timeouts at will).
5123
5217
  // We've already written the guaranteed-to-be-freshest value so we can just cancel it.
5124
5218
  clearTimeout(timeout);
5125
5219
  return;
5126
5220
  }
5127
- set_to_later = r;
5221
+ set_to_later = last_result;
5128
5222
  // If a delayed push timeout is already running, just changing the value that will be pushed is sufficient
5129
5223
  if (timeout) return;
5130
5224
  timeout = setTimeout((0, $57o7A$depictaiutilishared.catchify)(()=>{
@@ -6001,7 +6095,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6001
6095
  set on_navigation(new_function) {
6002
6096
  this.#router.on_navigation_ = new_function;
6003
6097
  }
6004
- constructor({ api: api , on_navigation: on_navigation , ...props_on_class }){
6098
+ constructor({ api: api , on_navigation: on_navigation , page_url_creator: page_url_creator , ...props_on_class }){
6005
6099
  const owner = (0, $57o7A$solidjs.getOwner)() || (0, $57o7A$solidjs.createRoot)(()=>(0, $57o7A$solidjs.getOwner)()); // we might have an owner, if so, pass it on. Otherwise, create one so solid doesn't print warnings to the console
6006
6100
  (0, $57o7A$solidjs.runWithOwner)(owner, ()=>{
6007
6101
  if ($48567ac5b39bac56$export$f34314aa9505732e.#has_been_constructed && !(0, $57o7A$solidjsweb.isServer)) // on the server we can't write stuff to history.state anyway so can have multiple
@@ -6029,7 +6123,9 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6029
6123
  quicklinks_signal_: (0, $57o7A$solidjs.createSignal)(),
6030
6124
  i18n_: i18n_,
6031
6125
  reset_history_state_: reset_history_state_,
6032
- depict_api_: api ?? new (0, $e1d6c0f3d89d531c$export$e015ed2f2950f2e3)(),
6126
+ depict_api_: api ?? new (0, $e1d6c0f3d89d531c$export$e015ed2f2950f2e3)({
6127
+ page_url_creator: page_url_creator
6128
+ }),
6033
6129
  router_: this.#router,
6034
6130
  selected_filters_: selected_filters_,
6035
6131
  current_sorting_: current_sorting_,
@@ -8430,7 +8526,7 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
8430
8526
  #modal_open_signal = (0, $57o7A$solidjs.createSignal)(false);
8431
8527
  static #has_been_constructed = false;
8432
8528
  #router = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation");
8433
- constructor({ search_query_url_param_name: search_query_url_param_name_ = "query" , url_transformer: url_transformer , on_navigation: on_navigation , enable_category_suggestions: enable_category_suggestions = true , disable_scrolling_during_modal: // Stuff needed for non-standard customer deployments that we shouldn't actually expose
8529
+ constructor({ search_query_url_param_name: search_query_url_param_name_ = "query" , url_transformer: url_transformer , on_navigation: on_navigation , enable_category_suggestions: enable_category_suggestions = true , page_url_creator: page_url_creator , disable_scrolling_during_modal: // Stuff needed for non-standard customer deployments that we shouldn't actually expose
8434
8530
  disable_scrolling_during_modal = true , api: api , bottom_distance_under_modal: bottom_distance_under_modal , render_instant_card: render_instant_card , ...props_on_class }){
8435
8531
  const owner = (0, $57o7A$solidjs.getOwner)() || (0, $57o7A$solidjs.createRoot)(()=>(0, $57o7A$solidjs.getOwner)()); // we might have an owner, if so, pass it on. Otherwise, create one so solid doesn't print warnings to the console
8436
8532
  (0, $57o7A$solidjs.runWithOwner)(owner, ()=>{
@@ -8459,7 +8555,9 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
8459
8555
  if (get_search_query_updating_blocked()) return previous_value;
8460
8556
  else return raw_search_query_accessor();
8461
8557
  });
8462
- const depict_api_ = api ?? new (0, $e1d6c0f3d89d531c$export$e015ed2f2950f2e3)();
8558
+ const depict_api_ = api ?? new (0, $e1d6c0f3d89d531c$export$e015ed2f2950f2e3)({
8559
+ page_url_creator: page_url_creator
8560
+ });
8463
8561
  const previous_searches = (0, $2b7a005a65221045$export$84bba84a7b837187)(get_search_query_);
8464
8562
  const [, set_search_showing_recommendation_rows] = state_.search_showing_recommendation_rows;
8465
8563
  const after_submit_ = ()=>set_search_showing_recommendation_rows((0, $fb29c6201c369e39$export$1c8c715550dc689d)); // do this every time after we have submitted a new query - otherwise there might already be a saved number of rows in the state