vviinn-widgets 2.221.0 → 2.223.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.
Files changed (49) hide show
  1. package/dist/cjs/{index-sL3iGA57.js → index-DZw3p4dq.js} +1 -1
  2. package/dist/cjs/{search.store-C-fS-eJR.js → search.store-Bh2_GSpU.js} +2 -1
  3. package/dist/cjs/vviinn-button_6.cjs.entry.js +1 -1
  4. package/dist/cjs/vviinn-camera_12.cjs.entry.js +259 -107
  5. package/dist/cjs/vviinn-carousel_10.cjs.entry.js +2 -53
  6. package/dist/cjs/vviinn-shop-the-look.cjs.entry.js +1 -1
  7. package/dist/cjs/vviinn-text-search.cjs.entry.js +1 -1
  8. package/dist/collection/components/vviinn-cropper/helpers/cropperOcrGate.js +36 -0
  9. package/dist/collection/components/vviinn-cropper/helpers/hasSelectedOcrFilter.js +4 -0
  10. package/dist/collection/components/vviinn-cropper/vviinn-cropper.js +108 -38
  11. package/dist/collection/components/vviinn-filters/vviinn-extended-filters.js +2 -2
  12. package/dist/collection/components/vviinn-results/vviinn-results.js +78 -3
  13. package/dist/collection/components/vviinn-suggestions/helpers.js +27 -10
  14. package/dist/collection/components/vviinn-suggestions/render-helpers.js +42 -15
  15. package/dist/esm/{index-D5yWioO8.js → index-DQQYIioG.js} +1 -1
  16. package/dist/esm/{search.store-C8LIDQfX.js → search.store-lTerE9Yh.js} +2 -2
  17. package/dist/esm/vviinn-button_6.entry.js +1 -1
  18. package/dist/esm/vviinn-camera_12.entry.js +259 -107
  19. package/dist/esm/vviinn-carousel_10.entry.js +2 -53
  20. package/dist/esm/vviinn-shop-the-look.entry.js +1 -1
  21. package/dist/esm/vviinn-text-search.entry.js +1 -1
  22. package/dist/storybook/helpers/industryToken.js +6 -8
  23. package/dist/types/components/vviinn-cropper/helpers/cropperOcrGate.d.ts +19 -0
  24. package/dist/types/components/vviinn-cropper/helpers/hasSelectedOcrFilter.d.ts +2 -0
  25. package/dist/types/components/vviinn-cropper/vviinn-cropper.d.ts +14 -0
  26. package/dist/types/components/vviinn-filters/vviinn-extended-filters.d.ts +51 -0
  27. package/dist/types/components/vviinn-results/vviinn-results.d.ts +1 -1
  28. package/dist/types/components/vviinn-suggestions/helpers.d.ts +1 -0
  29. package/dist/vviinn-widgets/p-08d39cc9.entry.js +1 -0
  30. package/dist/vviinn-widgets/{p-07211a51.entry.js → p-1e2f9b9f.entry.js} +1 -1
  31. package/dist/vviinn-widgets/{p-95423f25.entry.js → p-3daed25b.entry.js} +1 -1
  32. package/dist/vviinn-widgets/{p-DTASrq1W.js → p-CJAxBbhA.js} +1 -1
  33. package/dist/vviinn-widgets/{p-BpHXy3Gg.js → p-DhCqK4d8.js} +1 -1
  34. package/dist/vviinn-widgets/{p-f46ad1fd.entry.js → p-eb579723.entry.js} +1 -1
  35. package/{www/build/p-f48452fd.entry.js → dist/vviinn-widgets/p-f9f4e909.entry.js} +1 -1
  36. package/dist/vviinn-widgets/vviinn-widgets.esm.js +1 -1
  37. package/package.json +1 -1
  38. package/www/build/p-08d39cc9.entry.js +1 -0
  39. package/www/build/{p-07211a51.entry.js → p-1e2f9b9f.entry.js} +1 -1
  40. package/www/build/{p-95423f25.entry.js → p-3daed25b.entry.js} +1 -1
  41. package/www/build/{p-2d5777fa.js → p-4f556dc3.js} +1 -1
  42. package/www/build/{p-DTASrq1W.js → p-CJAxBbhA.js} +1 -1
  43. package/www/build/{p-BpHXy3Gg.js → p-DhCqK4d8.js} +1 -1
  44. package/www/build/{p-f46ad1fd.entry.js → p-eb579723.entry.js} +1 -1
  45. package/{dist/vviinn-widgets/p-f48452fd.entry.js → www/build/p-f9f4e909.entry.js} +1 -1
  46. package/www/build/vviinn-widgets.esm.js +1 -1
  47. package/www/index.html +1 -1
  48. package/dist/vviinn-widgets/p-e7b0a5b9.entry.js +0 -1
  49. package/www/build/p-e7b0a5b9.entry.js +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-BU8FMTXn.js');
4
- var search_store = require('./search.store-C-fS-eJR.js');
4
+ var search_store = require('./search.store-Bh2_GSpU.js');
5
5
  var store = require('./store-jPZ4ROqV.js');
6
6
 
7
7
  const PlusIcon = () => (index.h("svg", { width: "32", height: "32", viewBox: "0 0 32 32", fill: "none", xmlns: "http://www.w3.org/2000/svg", class: "plus-icon", "aria-hidden": "true" },
@@ -8598,7 +8598,7 @@ const encodeToBase64UTF8 = (str) => {
8598
8598
  return btoa(String.fromCharCode.apply(null, utf8Array));
8599
8599
  };
8600
8600
 
8601
- const version = "2.221.0";
8601
+ const version = "2.223.0";
8602
8602
 
8603
8603
  const appStateGlobalDefaults = {
8604
8604
  excluded: null,
@@ -8901,6 +8901,7 @@ exports.campaignTypeNames = campaignTypeNames;
8901
8901
  exports.checkDeviceType = checkDeviceType;
8902
8902
  exports.checkImageType = checkImageType;
8903
8903
  exports.extractFilterValue = extractFilterValue;
8904
+ exports.extractSelectedFilters = extractSelectedFilters;
8904
8905
  exports.fold = fold;
8905
8906
  exports.fromString = fromString;
8906
8907
  exports.getAcceptableFileFormats = getAcceptableFileFormats;
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-BU8FMTXn.js');
4
4
  var store = require('./store-jPZ4ROqV.js');
5
- var search_store = require('./search.store-C-fS-eJR.js');
5
+ var search_store = require('./search.store-Bh2_GSpU.js');
6
6
  var index$1 = require('./index-CP1QUrJT.js');
7
7
  var SecondaryActionIcon = require('./SecondaryActionIcon-CuNEBTWD.js');
8
8
  var index$2 = require('./index-BF9aENF8.js');
@@ -2,9 +2,9 @@
2
2
 
3
3
  var index = require('./index-BU8FMTXn.js');
4
4
  var Rectangle = require('./Rectangle-7dF6_xf3.js');
5
- var search_store = require('./search.store-C-fS-eJR.js');
5
+ var search_store = require('./search.store-Bh2_GSpU.js');
6
6
  var index$2 = require('./index-CP1QUrJT.js');
7
- var index$1 = require('./index-sL3iGA57.js');
7
+ var index$1 = require('./index-DZw3p4dq.js');
8
8
  var store = require('./store-jPZ4ROqV.js');
9
9
  var cropperUtils = require('./cropperUtils-DCDOLeBS.js');
10
10
  var cssUrlHelper = require('./cssUrlHelper-B5A2BBm7.js');
@@ -246,6 +246,46 @@ const ValidateCropBoxData = (cropBoxData) => {
246
246
  return result;
247
247
  };
248
248
 
249
+ const MODALITY_COLUMN = "modality";
250
+ const OCR_VALUE = "OCR";
251
+ const hasSelectedOcrFilter = (dynamicFilters) => search_store.extractSelectedFilters(dynamicFilters !== null && dynamicFilters !== void 0 ? dynamicFilters : []).some((filter) => filter.column === MODALITY_COLUMN && filter.values.includes(OCR_VALUE));
252
+
253
+ /**
254
+ * Decides whether the cropper must be hidden because an OCR filter is active.
255
+ * Once the user adjusts the crop box the cropper stays regardless of OCR.
256
+ * Engagement resets whenever a different image is loaded.
257
+ */
258
+ class CropperOcrGate {
259
+ constructor() {
260
+ this.engaged = false;
261
+ this.lastImage = null;
262
+ this.awaitingFilters = false;
263
+ }
264
+ /** Re-arm OCR gating for a freshly loaded image. */
265
+ onImage(image) {
266
+ if (image === this.lastImage)
267
+ return;
268
+ this.lastImage = image;
269
+ this.engaged = false;
270
+ this.awaitingFilters = true;
271
+ }
272
+ /** Fresh dynamicFilters for the current image have arrived. */
273
+ onFreshFilters() {
274
+ this.awaitingFilters = false;
275
+ }
276
+ /** Mark that the user started working with the cropper. */
277
+ onUserAdjust() {
278
+ this.engaged = true;
279
+ }
280
+ /** True when the cropper should be hidden. */
281
+ isGated(dynamicFilters, isSearchLoading = false) {
282
+ // Defer while the image's search is still resolving, to avoid a flash.
283
+ if (this.awaitingFilters && isSearchLoading)
284
+ return true;
285
+ return !this.engaged && hasSelectedOcrFilter(dynamicFilters);
286
+ }
287
+ }
288
+
249
289
  const VviinnCropper = class {
250
290
  constructor(hostRef) {
251
291
  index.registerInstance(this, hostRef);
@@ -268,6 +308,45 @@ const VviinnCropper = class {
268
308
  this.showInWidget = false;
269
309
  this.cropper = null;
270
310
  this.selectedDetectedObject = null;
311
+ this.imageElement = null;
312
+ this.gate = new CropperOcrGate();
313
+ this.destroyCropper = () => {
314
+ var _a;
315
+ (_a = this.cropper) === null || _a === void 0 ? void 0 : _a.destroy();
316
+ this.cropper = null;
317
+ };
318
+ this.clearCropSelection = () => {
319
+ this.state.searchArea = null;
320
+ this.state.croppedImageUrl = null;
321
+ this.selectedDetectedObject = null;
322
+ };
323
+ /** Tear down the cropper and drop any applied crop. */
324
+ this.discardCrop = () => {
325
+ this.destroyCropper();
326
+ this.clearCropSelection();
327
+ };
328
+ this.resetCropperState = () => {
329
+ this.discardCrop();
330
+ this.state.image = null;
331
+ };
332
+ /** Show or hide the cropper to match the current OCR gate decision. */
333
+ this.reconcileCropper = () => {
334
+ // Trust the fresh filters even before the image DOM is ready.
335
+ this.gate.onFreshFilters();
336
+ if (!this.state.image || !this.imageElement || !this.state.imageBounds)
337
+ return;
338
+ if (this.gate.isGated(this.state.dynamicFilters)) {
339
+ // Drop only the frame, keep the region/object so OCR searches within it.
340
+ this.destroyCropper();
341
+ return;
342
+ }
343
+ // Guard geometry here so initCropper doesn't re-emit the aspect-ratio error on every filter change.
344
+ if (!this.cropper &&
345
+ this.hasSupportedAspectRatio() &&
346
+ this.hasSupportedSize()) {
347
+ this.initCropper(this.imageElement);
348
+ }
349
+ };
271
350
  this.initPreloadedImage = () => {
272
351
  var _a;
273
352
  if (this.showInWidget && this.state.image) {
@@ -291,14 +370,12 @@ const VviinnCropper = class {
291
370
  cleanLocalStorage();
292
371
  };
293
372
  this.resetStateHandler = ({ detail, }) => {
294
- var _a, _b;
373
+ var _a;
295
374
  if (this.skipStateChanges(detail.isTriggeredByVpsWidget))
296
375
  return;
297
- this.selectedDetectedObject = null;
298
376
  (_a = this.state.image) === null || _a === void 0 ? void 0 : _a.setAttribute("src", "");
299
377
  this.state.detectedObjects = [];
300
- this.state.image = null;
301
- (_b = this.cropper) === null || _b === void 0 ? void 0 : _b.destroy();
378
+ this.resetCropperState();
302
379
  cleanLocalStorage();
303
380
  };
304
381
  this.resetCropAreaHandler = ({ detail, }) => {
@@ -306,9 +383,7 @@ const VviinnCropper = class {
306
383
  if (this.skipStateChanges(detail.isTriggeredByVpsWidget))
307
384
  return;
308
385
  (_a = this.cropper) === null || _a === void 0 ? void 0 : _a.reset();
309
- this.state.searchArea = null;
310
- this.state.croppedImageUrl = null;
311
- this.selectedDetectedObject = null;
386
+ this.clearCropSelection();
312
387
  this.vviinnImageCrop.emit({
313
388
  isTriggeredByVpsWidget: this.showInWidget,
314
389
  });
@@ -336,32 +411,62 @@ const VviinnCropper = class {
336
411
  this.cropper.replace(this.state.image.src);
337
412
  };
338
413
  this.loadImage = () => {
339
- const renderedImageElement = this.el.shadowRoot.querySelector("img");
340
- if (this.state.image) {
341
- let data = {};
342
- if (this.cropper) {
343
- data = this.cropper.getData(true);
344
- this.cropper.destroy();
345
- }
346
- const imageBounds = Rectangle.fromImage(renderedImageElement);
347
- const { width, height } = imageBounds;
348
- this.vviinnCropperLoadImage.emit({
349
- imageBounds,
350
- });
351
- this.state.imageBounds = imageBounds;
352
- if (width / height < cropperUtils.SUPPORTED_ASPECT_RATIO ||
353
- height / width < cropperUtils.SUPPORTED_ASPECT_RATIO) {
354
- this.vviinnCropperAspectRatioError.emit(true);
355
- return;
356
- }
357
- if (width < cropperUtils.MIN_IMAGE_SIDE_FOR_CROPPER ||
358
- height < cropperUtils.MIN_IMAGE_SIDE_FOR_CROPPER) {
359
- return;
360
- }
361
- this.cropper = new cropperUtils.Cropper(renderedImageElement, Object.assign(Object.assign({}, cropperUtils.cropperOptions), { cropstart: this.cropStart, cropend: this.cropEnd, ready: () => this.cropper.reset(), data }));
414
+ var _a;
415
+ if (!this.state.image)
416
+ return;
417
+ const renderedImageElement = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector("img");
418
+ if (!renderedImageElement)
419
+ return;
420
+ this.imageElement = renderedImageElement;
421
+ this.gate.onImage(this.state.image);
422
+ let data = {};
423
+ if (this.cropper) {
424
+ data = this.cropper.getData(true);
425
+ this.destroyCropper();
362
426
  }
427
+ const imageBounds = Rectangle.fromImage(renderedImageElement);
428
+ this.vviinnCropperLoadImage.emit({
429
+ imageBounds,
430
+ });
431
+ this.state.imageBounds = imageBounds;
432
+ const isSearchLoading = this.state.searchStatus === "loading";
433
+ if (this.gate.isGated(this.state.dynamicFilters, isSearchLoading)) {
434
+ this.discardCrop();
435
+ // Still surface aspect-ratio errors while hidden — geometry matters regardless.
436
+ this.checkAspectRatio();
437
+ return;
438
+ }
439
+ this.initCropper(renderedImageElement, data);
440
+ };
441
+ this.hasSupportedAspectRatio = () => {
442
+ if (!this.state.imageBounds)
443
+ return false;
444
+ const { width, height } = this.state.imageBounds;
445
+ return (width / height >= cropperUtils.SUPPORTED_ASPECT_RATIO &&
446
+ height / width >= cropperUtils.SUPPORTED_ASPECT_RATIO);
447
+ };
448
+ this.hasSupportedSize = () => {
449
+ if (!this.state.imageBounds)
450
+ return false;
451
+ const { width, height } = this.state.imageBounds;
452
+ return (width >= cropperUtils.MIN_IMAGE_SIDE_FOR_CROPPER &&
453
+ height >= cropperUtils.MIN_IMAGE_SIDE_FOR_CROPPER);
454
+ };
455
+ this.checkAspectRatio = () => {
456
+ if (this.hasSupportedAspectRatio())
457
+ return true;
458
+ this.vviinnCropperAspectRatioError.emit(true);
459
+ return false;
460
+ };
461
+ this.initCropper = (imageElement, data = {}) => {
462
+ if (!imageElement)
463
+ return;
464
+ if (!this.checkAspectRatio() || !this.hasSupportedSize())
465
+ return;
466
+ this.cropper = new cropperUtils.Cropper(imageElement, Object.assign(Object.assign({}, cropperUtils.cropperOptions), { cropstart: this.cropStart, cropend: this.cropEnd, ready: () => { var _a; return (_a = this.cropper) === null || _a === void 0 ? void 0 : _a.reset(); }, data }));
363
467
  };
364
468
  this.cropStart = () => {
469
+ this.gate.onUserAdjust();
365
470
  this.startEndCropBoxData = cropperUtils.getCropBoxData(this.cropper);
366
471
  };
367
472
  this.cropEnd = () => {
@@ -387,9 +492,10 @@ const VviinnCropper = class {
387
492
  !this.showAspectRatioError;
388
493
  }
389
494
  connectedCallback() {
390
- const { state, storeName } = search_store.useSearchStore(this.showInWidget);
495
+ const { state, storeName, onChange } = search_store.useSearchStore(this.showInWidget);
391
496
  this.state = state;
392
497
  this.storeName = storeName;
498
+ this.disposeStoreListener = onChange("dynamicFilters", this.reconcileCropper);
393
499
  this.initPreloadedImage();
394
500
  this.eventAbortController = new AbortController();
395
501
  const { signal } = this.eventAbortController;
@@ -400,10 +506,13 @@ const VviinnCropper = class {
400
506
  ], signal);
401
507
  }
402
508
  disconnectedCallback() {
403
- var _a, _b, _c;
509
+ var _a, _b;
404
510
  (_a = this.eventAbortController) === null || _a === void 0 ? void 0 : _a.abort();
405
- (_c = (_b = this.cropper) === null || _b === void 0 ? void 0 : _b.destroy) === null || _c === void 0 ? void 0 : _c.call(_b);
406
- this.state.image = null;
511
+ (_b = this.disposeStoreListener) === null || _b === void 0 ? void 0 : _b.call(this);
512
+ this.destroyCropper();
513
+ // "never" keeps no image across mounts, so clear it from the shared store.
514
+ if (this.saveImageMode === "never")
515
+ this.state.image = null;
407
516
  }
408
517
  selectDetectedObject({ detail }) {
409
518
  this.selectedDetectedObject = detail.detectedObject;
@@ -436,14 +545,14 @@ const VviinnCropper = class {
436
545
  }
437
546
  render() {
438
547
  var _a;
439
- return (index.h(index.Host, { key: 'ae2656d0782e723ffe5c8ba9ad6074db55e219c0', class: {
548
+ return (index.h(index.Host, { key: 'b50ccb5595b27ef6673ff9d9350fc30359a6f7ce', class: {
440
549
  "show-in-widget": this.showInWidget,
441
550
  active: !!this.state.image,
442
- } }, cssUrlHelper.renderExternalCSS(this.cssUrl), index.h("div", { key: '0c547762649ddc68aa2755681c6637ec1556b315', class: "container" }, this.state.image && (index.h("div", { key: '811e79aaf4ee1144c8c6ce0017300ba9aeda8803', class: "image-container", style: {
551
+ } }, cssUrlHelper.renderExternalCSS(this.cssUrl), index.h("div", { key: 'efd816ed4e19082091567714fee4ef40efe9a6c4', class: "container" }, this.state.image && (index.h("div", { key: '13f35758ba243eb73513e17375daca8431538383', class: "image-container", style: {
443
552
  width: `${this.width.toString()}px`,
444
553
  overflow: "hidden",
445
- } }, index.h("img", { key: '458474fa006a1397daa335fb9ee50477ab0e62ce', decoding: "async", width: this.width, height: this.height, src: this.state.image.src, draggable: false, onLoad: this.loadImage, alt: store.instance.t("a11y.cropperImage") }), (_a = this.state.detectedObjects) === null || _a === void 0 ? void 0 :
446
- _a.map((object) => (index.h("vviinn-detected-object", { detectedObject: object, selectedDetectedObject: this.selectedDetectedObject, basicEventData: this.basicEventData, imageBounds: this.state.imageBounds, showInWidget: this.showInWidget }))))), this.showPreloader() && (index.h("div", { key: 'd002cf170858ae7e5a46ca0f36bc64a425990119', class: "image-preloader" }, index.h("vviinn-preloader", { key: '2867876e7f492364528636d4b77dc4c7f80bee71' }))))));
554
+ } }, index.h("img", { key: '7525aae0654325fb25c88106a9ee1fface11a62e', decoding: "async", width: this.width, height: this.height, src: this.state.image.src, draggable: false, onLoad: this.loadImage, alt: store.instance.t("a11y.cropperImage") }), (_a = this.state.detectedObjects) === null || _a === void 0 ? void 0 :
555
+ _a.map((object) => (index.h("vviinn-detected-object", { detectedObject: object, selectedDetectedObject: this.selectedDetectedObject, basicEventData: this.basicEventData, imageBounds: this.state.imageBounds, showInWidget: this.showInWidget }))))), this.showPreloader() && (index.h("div", { key: 'b89ad46bda5279b77f4fe258f7a6d4af08f81c29', class: "image-preloader" }, index.h("vviinn-preloader", { key: '34f55578c05321480d7e3d8141a4638df8aad08b' }))))));
447
556
  }
448
557
  get el() { return index.getElement(this); }
449
558
  };
@@ -1040,13 +1149,13 @@ const VviinnResults = class {
1040
1149
  render() {
1041
1150
  var _a;
1042
1151
  const resultsLength = this.getResults().length;
1043
- return (index.h(index.Host, { key: '0767d0c21dee72b9a0f09a80dfe2ca7c375e4d50', id: "results-block", class: {
1152
+ return (index.h(index.Host, { key: 'd62957bb1294f3a62e14fa9a3eb97c7ef6007eae', id: "results-block", class: {
1044
1153
  "show-in-widget": this.showInWidget,
1045
1154
  "matching-discovery": this.oneClickDiscoveryMode === "append-slider",
1046
- }, exportparts: `${index$3.productCardParts}, ${index$3.listCardParts}, ${index$3.contentCardParts}, ${index$3.productCardsGridPart}` }, cssUrlHelper.renderExternalCSS(this.cssUrl), index.h("div", { key: 'bfd01f2bf39be84501ce0cf42f5672acda3e500b', class: "nothing-found" }, this.getCurrentErrorType() && (index.h("vviinn-error", { key: 'ce077ad92253c7727a509567571d821ebda6dbd4', errorType: this.getCurrentErrorType(), handler: this.resetWidgetState, hasBackground: this.showInWidget, searchType: this.state.searchType }))), index.h("div", { key: 'dc63984664328f04abe6011aa0db856cb862f37c', class: {
1155
+ }, exportparts: `${index$3.productCardParts}, ${index$3.listCardParts}, ${index$3.contentCardParts}, ${index$3.productCardsGridPart}` }, cssUrlHelper.renderExternalCSS(this.cssUrl), index.h("div", { key: '69f7a38dc02f42c357dbae8cf154ecb78380f270', class: "nothing-found" }, this.getCurrentErrorType() && (index.h("vviinn-error", { key: 'd78ed9f6d777d7ec1686b10b709deee018c4391e', errorType: this.getCurrentErrorType(), handler: this.resetWidgetState, hasBackground: this.showInWidget, searchType: this.state.searchType }))), index.h("div", { key: 'be3db62dcfd508b6f60036454d3c825d6c27f5ae', class: {
1047
1156
  hidden: this.showAspectRatioError || resultsLength === 0,
1048
1157
  products: true,
1049
- }, part: index$3.productCardsGridPart, id: "vviinn-results-products" }, resultsLength > 0 && this.renderResults(), index.h("div", { key: '2e39c5d65c5c7981c0b9a93dfe97ad62165a25b4', id: "one-click-discovery-append", style: {
1158
+ }, part: index$3.productCardsGridPart, id: "vviinn-results-products" }, resultsLength > 0 && this.renderResults(), index.h("div", { key: '88d3d2d5880806b9e24799694cc540de676d17f8', id: "one-click-discovery-append", style: {
1050
1159
  order: ((_a = this.oneClickDiscoveryAppendIndex) !== null && _a !== void 0 ? _a : resultsLength).toString(),
1051
1160
  } }))));
1052
1161
  }
@@ -1444,6 +1553,72 @@ ${e}</tr>
1444
1553
  `}strong({tokens:e}){return `<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return `<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return `<code>${O(e,true)}</code>`}br(e){return "<br>"}del({tokens:e}){return `<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let r=this.parser.parseInline(n),i=J(e);if(i===null)return r;e=i;let s='<a href="'+e+'"';return t&&(s+=' title="'+O(t)+'"'),s+=">"+r+"</a>",s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=J(e);if(i===null)return O(n);e=i;let s=`<img src="${e}" alt="${O(n)}"`;return t&&(s+=` title="${O(t)}"`),s+=">",s}text(e){return "tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:O(e.text)}};var $=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return ""+e}image({text:e}){return ""+e}br(){return ""}checkbox({raw:e}){return e}};var b=class u{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new y,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new $;}static parse(e,t){return new u(t).parse(e)}static parseInline(e,t){return new u(t).parseInline(e)}parse(e){this.renderer.parser=this;let t="";for(let n=0;n<e.length;n++){let r=e[n];if(this.options.extensions?.renderers?.[r.type]){let s=r,a=this.options.extensions.renderers[s.type].call({parser:this},s);if(a!==false||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(s.type)){t+=a||"";continue}}let i=r;switch(i.type){case "space":{t+=this.renderer.space(i);break}case "hr":{t+=this.renderer.hr(i);break}case "heading":{t+=this.renderer.heading(i);break}case "code":{t+=this.renderer.code(i);break}case "table":{t+=this.renderer.table(i);break}case "blockquote":{t+=this.renderer.blockquote(i);break}case "list":{t+=this.renderer.list(i);break}case "checkbox":{t+=this.renderer.checkbox(i);break}case "html":{t+=this.renderer.html(i);break}case "def":{t+=this.renderer.def(i);break}case "paragraph":{t+=this.renderer.paragraph(i);break}case "text":{t+=this.renderer.text(i);break}default:{let s='Token with "'+i.type+'" type was not found.';if(this.options.silent)return console.error(s),"";throw new Error(s)}}}return t}parseInline(e,t=this.renderer){this.renderer.parser=this;let n="";for(let r=0;r<e.length;r++){let i=e[r];if(this.options.extensions?.renderers?.[i.type]){let a=this.options.extensions.renderers[i.type].call({parser:this},i);if(a!==false||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(i.type)){n+=a||"";continue}}let s=i;switch(s.type){case "escape":{n+=t.text(s);break}case "html":{n+=t.html(s);break}case "link":{n+=t.link(s);break}case "image":{n+=t.image(s);break}case "checkbox":{n+=t.checkbox(s);break}case "strong":{n+=t.strong(s);break}case "em":{n+=t.em(s);break}case "codespan":{n+=t.codespan(s);break}case "br":{n+=t.br(s);break}case "del":{n+=t.del(s);break}case "text":{n+=t.text(s);break}default:{let a='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return n}};var P=class{options;block;constructor(e){this.options=e||T;}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?x.lex:x.lexInline}provideParser(){return this.block?b.parse:b.parseInline}};var D=class{defaults=M();options=this.setOptions;parse=this.parseMarkdown(true);parseInline=this.parseMarkdown(false);Parser=b;Renderer=y;TextRenderer=$;Lexer=x;Tokenizer=w;Hooks=P;constructor(...e){this.use(...e);}walkTokens(e,t){let n=[];for(let r of e)switch(n=n.concat(t.call(this,r)),r.type){case "table":{let i=r;for(let s of i.header)n=n.concat(this.walkTokens(s.tokens,t));for(let s of i.rows)for(let a of s)n=n.concat(this.walkTokens(a.tokens,t));break}case "list":{let i=r;n=n.concat(this.walkTokens(i.items,t));break}default:{let i=r;this.defaults.extensions?.childTokens?.[i.type]?this.defaults.extensions.childTokens[i.type].forEach(s=>{let a=i[s].flat(1/0);n=n.concat(this.walkTokens(a,t));}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)));}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||false,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let s=t.renderers[i.name];s?t.renderers[i.name]=function(...a){let o=i.renderer.apply(this,a);return o===false&&(o=s.apply(this,a)),o}:t.renderers[i.name]=i.renderer;}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]));}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens);}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new y(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if(["options","parser"].includes(s))continue;let a=s,o=n.renderer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===false&&(c=l.apply(i,p)),c||""};}r.renderer=i;}if(n.tokenizer){let i=this.defaults.tokenizer||new w(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if(["options","rules","lexer"].includes(s))continue;let a=s,o=n.tokenizer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===false&&(c=l.apply(i,p)),c};}r.tokenizer=i;}if(n.hooks){let i=this.defaults.hooks||new P;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if(["options","block"].includes(s))continue;let a=s,o=n.hooks[a],l=i[a];P.passThroughHooks.has(s)?i[a]=p=>{if(this.defaults.async&&P.passThroughHooksRespectAsync.has(s))return (async()=>{let d=await o.call(i,p);return l.call(i,d)})();let c=o.call(i,p);return l.call(i,c)}:i[a]=(...p)=>{if(this.defaults.async)return (async()=>{let d=await o.apply(i,p);return d===false&&(d=await l.apply(i,p)),d})();let c=o.apply(i,p);return c===false&&(c=l.apply(i,p)),c};}r.hooks=i;}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(a){let o=[];return o.push(s.call(this,a)),i&&(o=o.concat(i.call(this,a))),o};}this.defaults={...this.defaults,...r};}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return (n,r)=>{let i={...r},s={...this.defaults,...i},a=this.onError(!!s.silent,!!s.async);if(this.defaults.async===true&&i.async===false)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return a(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return (async()=>{let o=s.hooks?await s.hooks.preprocess(n):n,p=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(o,s),c=s.hooks?await s.hooks.processAllTokens(p):p;s.walkTokens&&await Promise.all(this.walkTokens(c,s.walkTokens));let h=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(c,s);return s.hooks?await s.hooks.postprocess(h):h})().catch(a);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let c=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(c=s.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=`
1445
1554
  Please report this to https://github.com/markedjs/marked.`,e){let r="<p>An error occurred:</p><pre>"+O(n.message+"",true)+"</pre>";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}};var L=new D;function g(u,e){return L.parse(u,e)}g.options=g.setOptions=function(u){return L.setOptions(u),g.defaults=L.defaults,G(g.defaults),g};g.getDefaults=M;g.defaults=T;g.use=function(...u){return L.use(...u),g.defaults=L.defaults,G(g.defaults),g};g.walkTokens=function(u,e){return L.walkTokens(u,e)};g.parseInline=L.parseInline;g.Parser=b;g.parser=b.parse;g.Renderer=y;g.TextRenderer=$;g.Lexer=x;g.lexer=x.lex;g.Tokenizer=w;g.Hooks=P;g.parse=g;
1446
1555
 
1556
+ const toggleFilterInSet = (appliedFilters, suggestionText) => {
1557
+ const newAppliedFilters = new Set(appliedFilters);
1558
+ if (newAppliedFilters.has(suggestionText)) {
1559
+ newAppliedFilters.delete(suggestionText);
1560
+ }
1561
+ else {
1562
+ newAppliedFilters.add(suggestionText);
1563
+ }
1564
+ return newAppliedFilters;
1565
+ };
1566
+ const formatIntervalKey = (column, start, end) => `${column}:${start}-${end}`;
1567
+ const extractActiveFilterValues = (activeFilters) => {
1568
+ const activeValues = new Set();
1569
+ activeFilters.forEach((filter) => {
1570
+ if (!Array.isArray(filter.values))
1571
+ return;
1572
+ filter.values.forEach((v) => {
1573
+ // Interval values are `{start, end}` objects; categorical values are strings.
1574
+ if (v !== null && typeof v === "object" && "start" in v) {
1575
+ activeValues.add(formatIntervalKey(filter.column, v.start, v.end));
1576
+ }
1577
+ else {
1578
+ activeValues.add(`${filter.column}:${String(v)}`);
1579
+ }
1580
+ });
1581
+ });
1582
+ return activeValues;
1583
+ };
1584
+ const syncSuggestionFilters = (activeFilters, stream) => {
1585
+ var _a, _b, _c;
1586
+ const activeValues = extractActiveFilterValues(activeFilters);
1587
+ const updatedAppliedFilters = new Set();
1588
+ if (!(stream === null || stream === void 0 ? void 0 : stream.items))
1589
+ return updatedAppliedFilters;
1590
+ for (const item of stream.items) {
1591
+ if (item.role !== "assistant" || !item.parts)
1592
+ continue;
1593
+ for (const part of item.parts) {
1594
+ if (!((_a = part.text) === null || _a === void 0 ? void 0 : _a.annotations))
1595
+ continue;
1596
+ for (const annotation of part.text.annotations) {
1597
+ if (!((_c = (_b = annotation.interactions) === null || _b === void 0 ? void 0 : _b.dynamicFilters) === null || _c === void 0 ? void 0 : _c.length))
1598
+ continue;
1599
+ for (const filter of annotation.interactions.dynamicFilters) {
1600
+ if (filter.type === "categorical" && "values" in filter) {
1601
+ filter.values.forEach((value) => {
1602
+ if (activeValues.has(`${filter.column}:${String(value.value)}`)) {
1603
+ updatedAppliedFilters.add(`${filter.column}:${value.value}`);
1604
+ }
1605
+ });
1606
+ }
1607
+ else if (filter.type === "interval" && "selectedValues" in filter) {
1608
+ filter.selectedValues.forEach((interval) => {
1609
+ const key = formatIntervalKey(filter.column, interval.start, interval.end);
1610
+ if (activeValues.has(key)) {
1611
+ updatedAppliedFilters.add(key);
1612
+ }
1613
+ });
1614
+ }
1615
+ }
1616
+ }
1617
+ }
1618
+ }
1619
+ return updatedAppliedFilters;
1620
+ };
1621
+
1447
1622
  const extractDataItems = (annotation) => annotation.data.items;
1448
1623
  const findMatchingFilterValue = (item, filter) => {
1449
1624
  if (filter.type !== "categorical" ||
@@ -1464,18 +1639,38 @@ const applyFiltersForItems = (dataItems, interactions, currentRequestFilters, ha
1464
1639
  let updatedFilters = currentRequestFilters;
1465
1640
  if (dataItems.length === 0) {
1466
1641
  for (const filter of filters) {
1467
- if (filter.type !== "categorical" || !("values" in filter))
1468
- continue;
1469
- for (const filterValue of filter.values) {
1470
- updatedFilters = index$1.triggerFilter({
1471
- filterValue: filterValue,
1472
- selectedFilter: filter,
1473
- requestFilters: updatedFilters,
1474
- vviinnFilterTriggered: handlers.vviinnFilterTriggered,
1475
- vviinnFiltersChanged: handlers.vviinnFiltersChanged,
1476
- el: handlers.el,
1477
- isTriggeredByVpsWidget: handlers.isTriggeredByVpsWidget,
1478
- });
1642
+ if (filter.type === "categorical" && "values" in filter) {
1643
+ for (const filterValue of filter.values) {
1644
+ updatedFilters = index$1.triggerFilter({
1645
+ filterValue: filterValue,
1646
+ selectedFilter: filter,
1647
+ requestFilters: updatedFilters,
1648
+ vviinnFilterTriggered: handlers.vviinnFilterTriggered,
1649
+ vviinnFiltersChanged: handlers.vviinnFiltersChanged,
1650
+ el: handlers.el,
1651
+ isTriggeredByVpsWidget: handlers.isTriggeredByVpsWidget,
1652
+ });
1653
+ }
1654
+ }
1655
+ else if (filter.type === "interval" && "selectedValues" in filter) {
1656
+ // A suggestion chip represents one specific range to toggle, not a slider.
1657
+ // The backend emits `full === selectedValues[0]`, which would make
1658
+ // `isFullRangeInterval` read every click as "cleared to the full range"
1659
+ // (deselect-only). Neutralize `full` so the shared toggle logic selects /
1660
+ // deselects this exact interval by value match. Only the object passed to
1661
+ // `triggerFilter` is affected; `value` still carries the real interval.
1662
+ const chipFilter = Object.assign(Object.assign({}, filter), { full: { start: undefined, end: undefined } });
1663
+ for (const interval of filter.selectedValues) {
1664
+ updatedFilters = index$1.triggerFilter({
1665
+ filterValue: { interval },
1666
+ selectedFilter: chipFilter,
1667
+ requestFilters: updatedFilters,
1668
+ vviinnFilterTriggered: handlers.vviinnFilterTriggered,
1669
+ vviinnFiltersChanged: handlers.vviinnFiltersChanged,
1670
+ el: handlers.el,
1671
+ isTriggeredByVpsWidget: handlers.isTriggeredByVpsWidget,
1672
+ });
1673
+ }
1479
1674
  }
1480
1675
  }
1481
1676
  return updatedFilters;
@@ -1524,9 +1719,15 @@ const splitContentByLocators = (content, annotations) => {
1524
1719
  };
1525
1720
  const getAnnotationFilterKeys = (annotation) => {
1526
1721
  var _a, _b, _c;
1527
- return (_c = (_b = (_a = annotation.interactions) === null || _a === void 0 ? void 0 : _a.dynamicFilters) === null || _b === void 0 ? void 0 : _b.flatMap((filter) => "values" in filter
1528
- ? filter.values.map((v) => `${filter.column}:${v.value}`)
1529
- : [])) !== null && _c !== void 0 ? _c : [];
1722
+ return (_c = (_b = (_a = annotation.interactions) === null || _a === void 0 ? void 0 : _a.dynamicFilters) === null || _b === void 0 ? void 0 : _b.flatMap((filter) => {
1723
+ if (filter.type === "categorical" && "values" in filter) {
1724
+ return filter.values.map((v) => `${filter.column}:${v.value}`);
1725
+ }
1726
+ if (filter.type === "interval" && "selectedValues" in filter) {
1727
+ return filter.selectedValues.map((interval) => formatIntervalKey(filter.column, interval.start, interval.end));
1728
+ }
1729
+ return [];
1730
+ })) !== null && _c !== void 0 ? _c : [];
1530
1731
  };
1531
1732
  const getAnnotationDeeplink = (annotation) => {
1532
1733
  for (const item of annotation.data.items) {
@@ -1553,55 +1754,6 @@ const renderAnnotatedContent = (content, annotations, onAnnotationClick, applied
1553
1754
  };
1554
1755
  const renderInfoText = (content, key) => (index.h("div", { class: "suggestion-info-text", part: "suggestion-info-text", key: key, innerHTML: g.parse(content) }));
1555
1756
 
1556
- const toggleFilterInSet = (appliedFilters, suggestionText) => {
1557
- const newAppliedFilters = new Set(appliedFilters);
1558
- if (newAppliedFilters.has(suggestionText)) {
1559
- newAppliedFilters.delete(suggestionText);
1560
- }
1561
- else {
1562
- newAppliedFilters.add(suggestionText);
1563
- }
1564
- return newAppliedFilters;
1565
- };
1566
- const extractActiveFilterValues = (activeFilters) => {
1567
- const activeValues = new Set();
1568
- activeFilters.forEach((filter) => {
1569
- if (Array.isArray(filter.values)) {
1570
- filter.values.forEach((v) => activeValues.add(`${filter.column}:${String(v)}`));
1571
- }
1572
- });
1573
- return activeValues;
1574
- };
1575
- const syncSuggestionFilters = (activeFilters, stream) => {
1576
- var _a, _b, _c;
1577
- const activeValues = extractActiveFilterValues(activeFilters);
1578
- const updatedAppliedFilters = new Set();
1579
- if (!(stream === null || stream === void 0 ? void 0 : stream.items))
1580
- return updatedAppliedFilters;
1581
- for (const item of stream.items) {
1582
- if (item.role !== "assistant" || !item.parts)
1583
- continue;
1584
- for (const part of item.parts) {
1585
- if (!((_a = part.text) === null || _a === void 0 ? void 0 : _a.annotations))
1586
- continue;
1587
- for (const annotation of part.text.annotations) {
1588
- if (!((_c = (_b = annotation.interactions) === null || _b === void 0 ? void 0 : _b.dynamicFilters) === null || _c === void 0 ? void 0 : _c.length))
1589
- continue;
1590
- for (const filter of annotation.interactions.dynamicFilters) {
1591
- if (filter.type !== "categorical" || !("values" in filter))
1592
- continue;
1593
- filter.values.forEach((value) => {
1594
- if (activeValues.has(`${filter.column}:${String(value.value)}`)) {
1595
- updatedAppliedFilters.add(`${filter.column}:${value.value}`);
1596
- }
1597
- });
1598
- }
1599
- }
1600
- }
1601
- }
1602
- return updatedAppliedFilters;
1603
- };
1604
-
1605
1757
  const vviinnSuggestionsCss = ":host{--font-family-base:Inter, system-ui, sans-serif;--font-family-mono:monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--font-size-display:32px;--font-size-title:24px;--font-size-headline:18px;--font-size-label-large:16px;--font-size-label:14px;--font-size-body-large:16px;--font-size-body:14px;--font-size-caption:12px;--line-height-display:40px;--line-height-title:32px;--line-height-headline:24px;--line-height-label-large:24px;--line-height-label:20px;--line-height-body-large:24px;--line-height-body:20px;--line-height-caption:16px;--letter-spacing-title:0px;--letter-spacing-headline:0px;--letter-spacing-label-large:0px;--letter-spacing-label:0px;--letter-spacing-body-large:0px;--letter-spacing-body:0px;--letter-spacing-caption:0px;--font-weight-400:400;--font-weight-500:500;--font-weight-600:600;--font-weight-700:700;--spacing-none:0px;--spacing-25:2px;--spacing-50:4px;--spacing-75:6px;--spacing-100:8px;--spacing-125:10px;--spacing-150:12px;--spacing-200:16px;--spacing-250:20px;--spacing-300:24px;--spacing-400:32px;--spacing-500:40px;--spacing-600:48px;--border-radius-none:0px;--border-radius-25:2px;--border-radius-50:4px;--border-radius-100:8px;--border-radius-150:12px;--border-radius-200:16px;--border-radius-300:24px;--border-radius-400:32px;--border-radius-full:9999px;--stroke-width-none:0px;--stroke-width-25:1px;--stroke-width-50:2px;--stroke-width-75:3px;--stroke-width-100:4px;--stroke-width-150:6px;--stroke-width-200:8px;--stroke-width-300:12px;--product-card-widget-min-width:135px;--product-card-results-min-width:250px;--image-set-mode-min-width:155px;--source-card-set-mode-max-width:500px;--filter-blur-none:0px;--filter-blur-100:8px;--filter-blur-150:12px;--filter-blur-200:16px;--color-bg-base:#ffffff;--color-bg-inverse:#161616;--color-border-00:#ffffff;--color-border-01:#f4f4f4;--color-border-02:#e0e0e0;--color-border-03:#c6c6c6;--color-border-inverse-00:#161616;--color-border-inverse-01:#393939;--color-field-01:#ffffff;--color-field-02:#f4f4f4;--color-icon-primary:#161616;--color-icon-secondary:#525252;--color-icon-helper:#8d8d8d;--color-icon-on-color:#ffffff;--color-icon-inverse:#ffffff;--color-icon-disabled:#16161640;--color-text-primary:#161616;--color-text-secondary:#707070;--color-text-helper:#8d8d8d;--color-text-placeholder:#a8a8a8;--color-text-on-color:#ffffff;--color-text-inverse:#ffffff;--color-text-disabled:#16161640;--button-bg-color-primary:#000000;--button-bg-color-primary-hover:#161616;--button-bg-color-primary-active:#1e1e1e;--button-bg-color-secondary:#f4f4f4;--button-bg-color-secondary-hover:#e0e0e0;--button-bg-color-secondary-active:#c6c6c6;--button-bg-color-ghost-hover:#f4f4f4;--button-bg-color-ghost-active:#eaeaea;--button-bg-color-frosted:#6f6f6f66;--button-bg-color-frosted-hover:#6f6f6f80;--button-bg-color-frosted-active:#6f6f6f99;--button-bg-color-disabled:#e0e0e0;--button-bg-color-positive:#dcfce7;--surface-bg-color-01:#f4f4f4;--surface-bg-color-01-hover:#eaeaea;--surface-bg-color-01-active:#e0e0e0;--surface-bg-color-02:#ffffff;--surface-bg-color-inverse:#262626;--surface-bg-color-inverse-hover:#303030;--surface-bg-color-inverse-active:#393939;--surface-bg-color-disabled:#e0e0e0;--surface-bg-color-shadow-01:#dddddd;--surface-bg-color-shadow-02:#c6c6c6;--chip-bg-color-primary:#161616;--chip-bg-color-primary-hover:#1e1e1e;--chip-bg-color-primary-active:#262626;--chip-bg-color-subtle:#f4f4f4;--chip-bg-color-subtle-hover:#eaeaea;--chip-bg-color-subtle-active:#e0e0e0;--chip-bg-color-outline-hover:#f4f4f4;--chip-bg-color-outline-active:#eaeaea;--label-bg-color-accent:#ff3944;--sidebar-animation-duration-default:0.5s;--search-modal-animation-duration-default:0.25s;--search-modal-animation-duration-mobile-default:0.35s;}:host{display:contents}.container{display:flex;flex-direction:column;gap:var(--spacing-150);font-family:var(--font-family, var(--font-family-base));padding-right:var(--spacing-100);line-height:normal}.header{display:flex;align-items:center;gap:var(--spacing-100)}.icon{font-size:20px}.title{margin:0;font-size:var(--font-size-headline);line-height:var(--line-height-headline);font-weight:600;color:var(--color-text-primary)}.suggestions-wrapper{display:flex;flex-direction:column;gap:var(--spacing-100);width:100%}.suggestions-list{list-style:none;margin:0;padding:0;padding-right:var(--spacing-100);display:flex;align-items:center;gap:var(--spacing-100);flex-wrap:wrap;font-size:var(--font-size-label)}.suggestion-item{display:contents}.suggestion-link{background:none;border:none;color:var(--color-primary-500);text-decoration:underline;cursor:pointer;font-size:inherit;line-height:inherit;padding:0;margin:0}.suggestion-link:hover{color:var(--color-primary-600)}.suggestion-link:focus{outline:2px solid var(--color-primary-500);outline-offset:2px;border-radius:2px}.suggestion-filter-button{background:none;border:none;cursor:pointer;display:flex;align-items:center;height:36px;padding:var(--spacing-75);gap:var(--spacing-50);white-space:nowrap;border-radius:var(--border-radius-100);background-color:var(--surface-bg-color-01);transition:background-color 0.1s;font-family:var(--font-family, var(--font-family-base));font-size:var(--font-size-label);color:var(--color-text-primary)}.suggestion-filter-button:hover{background-color:var(--surface-bg-color-01-hover)}.suggestion-filter-button.active{background:var(--surface-bg-color-inverse);color:var(--color-text-inverse)}.suggestion-info-text{font-size:var(--font-size-label);color:var(--color-text-primary)}.suggestion-info-text *{font-size:var(--font-size-label);margin:0}";
1606
1758
 
1607
1759
  const VviinnSuggestions = class {