vviinn-widgets 2.5.2 → 2.7.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 (116) hide show
  1. package/dist/cjs/{app-globals-d15b4c2c.js → app-globals-047a582c.js} +1 -1
  2. package/dist/cjs/{highlight-box_22.cjs.entry.js → cropper-handler_27.cjs.entry.js} +473 -85
  3. package/dist/cjs/{customized-slots-0c0d0665.js → customized-slots-cb722e68.js} +1 -1
  4. package/dist/cjs/{index-0f5516a6.js → index-bd771524.js} +1 -1
  5. package/dist/cjs/{imageSearch.store-865c23f4.js → index-d07466b9.js} +14707 -11093
  6. package/dist/cjs/{index-31b9cb7a.js → index-fcafbfe5.js} +1 -1
  7. package/dist/cjs/loader.cjs.js +3 -3
  8. package/dist/cjs/{vviinn-carousel_3.cjs.entry.js → vviinn-carousel_2.cjs.entry.js} +35 -208
  9. package/dist/cjs/vviinn-recommendations-sidebar.cjs.entry.js +5 -3
  10. package/dist/cjs/vviinn-vpr-button.cjs.entry.js +7 -2
  11. package/dist/cjs/vviinn-vps-button.cjs.entry.js +4 -4
  12. package/dist/cjs/vviinn-widgets.cjs.js +3 -3
  13. package/dist/collection/campaign/VCSCampaignService.js +4 -2
  14. package/dist/collection/campaign/VPRCampaignService.js +4 -2
  15. package/dist/collection/components/vviinn-vpr-button/recommendations-sidebar/recommendations-sidebar.js +21 -1
  16. package/dist/collection/components/vviinn-vpr-button/stories/args.js +6 -0
  17. package/dist/collection/components/vviinn-vpr-button/stories/vviinn-vpr-button.stories.js +2 -0
  18. package/dist/collection/components/vviinn-vpr-button/vviinn-vpr-button.js +23 -0
  19. package/dist/collection/components/vviinn-vpr-widget/stories/args.js +7 -0
  20. package/dist/collection/components/vviinn-vpr-widget/stories/vviinn-vpr-widget.stories.js +12 -13
  21. package/dist/collection/components/vviinn-vpr-widget/vviinn-vpr-vidget.js +28 -1
  22. package/dist/collection/components/vviinn-vps-button/stories/vviinn-vps-button.stories.js +9 -5
  23. package/dist/collection/components/vviinn-vps-button/vviinn-vps-button.js +18 -1
  24. package/dist/collection/components/vviinn-vps-widget/stories/vviinn-vps-widget.stories.js +11 -7
  25. package/dist/collection/components/vviinn-vps-widget/vviinn-vps-widget.js +23 -0
  26. package/dist/collection/searchSession/searchSession.js +6 -1
  27. package/dist/collection/store/imageSearch.store.js +2 -7
  28. package/dist/esm/{app-globals-6f6aa89e.js → app-globals-68b1d848.js} +1 -1
  29. package/dist/esm/{highlight-box_22.entry.js → cropper-handler_27.entry.js} +404 -21
  30. package/dist/esm/{customized-slots-6b427dda.js → customized-slots-95a05ceb.js} +1 -1
  31. package/dist/esm/{imageSearch.store-0ae87235.js → index-33fe5a25.js} +14832 -11234
  32. package/dist/esm/{index-59f44eaa.js → index-75a1f589.js} +1 -1
  33. package/dist/esm/{index-ac05c460.js → index-f9df412f.js} +2 -2
  34. package/dist/esm/loader.js +3 -3
  35. package/dist/esm/{vviinn-carousel_3.entry.js → vviinn-carousel_2.entry.js} +15 -187
  36. package/dist/esm/vviinn-recommendations-sidebar.entry.js +5 -3
  37. package/dist/esm/vviinn-vpr-button.entry.js +7 -2
  38. package/dist/esm/vviinn-vps-button.entry.js +4 -4
  39. package/dist/esm/vviinn-widgets.js +3 -3
  40. package/dist/types/campaign/CampaignService.d.ts +1 -1
  41. package/dist/types/campaign/VCSCampaignService.d.ts +2 -1
  42. package/dist/types/campaign/VPRCampaignService.d.ts +2 -1
  43. package/dist/types/components/vviinn-vpr-button/recommendations-sidebar/recommendations-sidebar.d.ts +2 -0
  44. package/dist/types/components/vviinn-vpr-button/stories/args.d.ts +6 -0
  45. package/dist/types/components/vviinn-vpr-button/stories/vviinn-vpr-button.stories.d.ts +6 -0
  46. package/dist/types/components/vviinn-vpr-button/vviinn-vpr-button.d.ts +2 -0
  47. package/dist/types/components/vviinn-vpr-widget/stories/args.d.ts +6 -0
  48. package/dist/types/components/vviinn-vpr-widget/stories/vviinn-vpr-widget.stories.d.ts +6 -0
  49. package/dist/types/components/vviinn-vpr-widget/vviinn-vpr-vidget.d.ts +3 -0
  50. package/dist/types/components/vviinn-vps-button/vviinn-vps-button.d.ts +2 -0
  51. package/dist/types/components/vviinn-vps-widget/vviinn-vps-widget.d.ts +2 -0
  52. package/dist/types/components.d.ts +40 -0
  53. package/dist/types/searchSession/searchSession.d.ts +2 -1
  54. package/dist/types/store/imageSearch.store.d.ts +7 -6
  55. package/dist/vviinn-widgets/{p-bad1809f.js → p-4e55513e.js} +1 -1
  56. package/dist/vviinn-widgets/p-5358970c.entry.js +1 -0
  57. package/{www/build/p-c36546fa.js → dist/vviinn-widgets/p-66015ad7.js} +1 -1
  58. package/dist/vviinn-widgets/p-669a156c.entry.js +1 -0
  59. package/dist/vviinn-widgets/p-8080679b.entry.js +1 -0
  60. package/dist/vviinn-widgets/p-9de1b0e7.js +1 -0
  61. package/dist/vviinn-widgets/{p-ee46fc83.js → p-b254eee7.js} +1 -1
  62. package/dist/vviinn-widgets/p-c1cd51ef.entry.js +1 -0
  63. package/dist/vviinn-widgets/p-e32c30d4.entry.js +1 -0
  64. package/dist/vviinn-widgets/{p-118ac907.js → p-f6e59cb2.js} +1 -1
  65. package/dist/vviinn-widgets/vviinn-widgets.esm.js +1 -1
  66. package/package.json +3 -3
  67. package/www/build/{p-bad1809f.js → p-4e55513e.js} +1 -1
  68. package/www/build/p-5358970c.entry.js +1 -0
  69. package/{dist/vviinn-widgets/p-c36546fa.js → www/build/p-66015ad7.js} +1 -1
  70. package/www/build/p-669a156c.entry.js +1 -0
  71. package/www/build/p-8080679b.entry.js +1 -0
  72. package/www/build/p-9de1b0e7.js +1 -0
  73. package/www/build/{p-ee46fc83.js → p-b254eee7.js} +1 -1
  74. package/www/build/p-c1cd51ef.entry.js +1 -0
  75. package/www/build/p-e32c30d4.entry.js +1 -0
  76. package/www/build/p-eb8f77e4.js +1 -0
  77. package/www/build/{p-118ac907.js → p-f6e59cb2.js} +1 -1
  78. package/www/build/vviinn-widgets.esm.js +1 -1
  79. package/www/index.html +1 -1
  80. package/dist/cjs/Handler-176539c8.js +0 -331
  81. package/dist/cjs/cropper-handler.cjs.entry.js +0 -27
  82. package/dist/cjs/index-0eb3036a.js +0 -3235
  83. package/dist/cjs/vviinn-error.cjs.entry.js +0 -19
  84. package/dist/cjs/vviinn-preloader.cjs.entry.js +0 -26
  85. package/dist/cjs/vviinn-vps-widget.cjs.entry.js +0 -167
  86. package/dist/esm/Handler-f9b8735c.js +0 -309
  87. package/dist/esm/cropper-handler.entry.js +0 -23
  88. package/dist/esm/index-2e296af4.js +0 -3224
  89. package/dist/esm/vviinn-error.entry.js +0 -15
  90. package/dist/esm/vviinn-preloader.entry.js +0 -22
  91. package/dist/esm/vviinn-vps-widget.entry.js +0 -163
  92. package/dist/vviinn-widgets/p-11f61564.js +0 -1
  93. package/dist/vviinn-widgets/p-39fdc5c9.entry.js +0 -1
  94. package/dist/vviinn-widgets/p-762dc067.entry.js +0 -1
  95. package/dist/vviinn-widgets/p-7e2f542c.js +0 -1
  96. package/dist/vviinn-widgets/p-8d56e795.entry.js +0 -1
  97. package/dist/vviinn-widgets/p-8f955b15.entry.js +0 -1
  98. package/dist/vviinn-widgets/p-9654fe35.entry.js +0 -1
  99. package/dist/vviinn-widgets/p-9e5adc42.js +0 -1
  100. package/dist/vviinn-widgets/p-b3731705.entry.js +0 -1
  101. package/dist/vviinn-widgets/p-d991330b.entry.js +0 -1
  102. package/dist/vviinn-widgets/p-da9c933b.entry.js +0 -1
  103. package/dist/vviinn-widgets/p-f41e25f0.entry.js +0 -1
  104. package/www/build/p-11f61564.js +0 -1
  105. package/www/build/p-39fdc5c9.entry.js +0 -1
  106. package/www/build/p-762dc067.entry.js +0 -1
  107. package/www/build/p-7e2f542c.js +0 -1
  108. package/www/build/p-8d56e795.entry.js +0 -1
  109. package/www/build/p-8f955b15.entry.js +0 -1
  110. package/www/build/p-9654fe35.entry.js +0 -1
  111. package/www/build/p-9e5adc42.js +0 -1
  112. package/www/build/p-b3731705.entry.js +0 -1
  113. package/www/build/p-cfd998c1.js +0 -1
  114. package/www/build/p-d991330b.entry.js +0 -1
  115. package/www/build/p-da9c933b.entry.js +0 -1
  116. package/www/build/p-f41e25f0.entry.js +0 -1
@@ -2,11 +2,44 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const index = require('./index-0f5516a6.js');
6
- const imageSearch_store = require('./imageSearch.store-865c23f4.js');
7
- const Handler = require('./Handler-176539c8.js');
8
- const index$1 = require('./index-31b9cb7a.js');
9
- const customizedSlots = require('./customized-slots-0c0d0665.js');
5
+ const index = require('./index-bd771524.js');
6
+ const index$1 = require('./index-d07466b9.js');
7
+ const index$2 = require('./index-fcafbfe5.js');
8
+ const customizedSlots = require('./customized-slots-cb722e68.js');
9
+
10
+ const cropperHandlerCss = ":host{--size:20px;background:transparent;border:4px solid white;box-sizing:content-box;display:block;height:var(--size);touch-action:none;position:absolute;width:var(--size);z-index:4;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}:host(.disabled){opacity:0.25}:host(.nw-resize){border-bottom:none;border-right:none;top:0;left:0}:host(.ne-resize){border-left:none;border-bottom:none;right:0;top:0}:host(.sw-resize){border-right:none;border-top:none;left:0;bottom:0}:host(.se-resize){border-left:none;border-top:none;bottom:0;right:0}";
11
+
12
+ let CropperHandler = class {
13
+ constructor(hostRef) {
14
+ index.registerInstance(this, hostRef);
15
+ this.disabled = false;
16
+ }
17
+ render() {
18
+ return (index.h(index.Host, { part: `handle ${index$1.getCursorValue(this.handler.direction)}`, class: {
19
+ disabled: this.disabled,
20
+ [index$1.getCursorValue(this.handler.direction)]: true,
21
+ }, style: {
22
+ "--size": "20px",
23
+ cursor: index$1.getCursorValue(this.handler.direction),
24
+ }, draggable: false }));
25
+ }
26
+ };
27
+ CropperHandler.style = cropperHandlerCss;
28
+
29
+ const fromRectangle = (shape, target) => {
30
+ const top = `${shape.y}px`;
31
+ const left = `${shape.x}px`;
32
+ const right = `${target.width - (shape.x + shape.width)}px`;
33
+ const bottom = `${target.height - (shape.y + shape.height)}px`;
34
+ return {
35
+ top,
36
+ right,
37
+ bottom,
38
+ left,
39
+ };
40
+ };
41
+ const printClip = (clip) => `inset(${clip.top} ${clip.right} ${clip.bottom} ${clip.left})`;
42
+ const getClipValue = (shape, target) => printClip(fromRectangle(shape, target));
10
43
 
11
44
  // -------------------------------------------------------------------------------------
12
45
  // -------------------------------------------------------------------------------------
@@ -28,21 +61,6 @@ var Ord = {
28
61
  compare: function (first, second) { return (first < second ? -1 : first > second ? 1 : 0); }
29
62
  };
30
63
 
31
- const fromRectangle = (shape, target) => {
32
- const top = `${shape.y}px`;
33
- const left = `${shape.x}px`;
34
- const right = `${target.width - (shape.x + shape.width)}px`;
35
- const bottom = `${target.height - (shape.y + shape.height)}px`;
36
- return {
37
- top,
38
- right,
39
- bottom,
40
- left,
41
- };
42
- };
43
- const printClip = (clip) => `inset(${clip.top} ${clip.right} ${clip.bottom} ${clip.left})`;
44
- const getClipValue = (shape, target) => printClip(fromRectangle(shape, target));
45
-
46
64
  const highlightBoxCss = ":host{display:grid;position:absolute;box-sizing:border-box;border:none;width:100%;height:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;--size:10px;--x-position:0;--y-position:0}img{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pointer{position:absolute;width:var(--size);height:var(--size);background:black;border-radius:50%;z-index:2;cursor:pointer;transform:translate(var(--x-position), var(--y-position)) scale(0);-webkit-animation:0.25s linear fadein;animation:0.25s linear fadein;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.pointer::after{content:\"\";cursor:pointer;border:5px solid black;border-radius:50%;width:var(--size);height:var(--size);display:block;transform:translate(calc(-50% + var(--size) * 0.5), calc(-50% + var(--size) * 0.5));padding:calc(var(--size) * 0.5);opacity:.75}@-webkit-keyframes fadein{from{transform:translate(var(--x-position), var(--y-position)) scale(0)}to{transform:translate(var(--x-position), var(--y-position)) scale(1)}}@keyframes fadein{from{transform:translate(var(--x-position), var(--y-position)) scale(0)}to{transform:translate(var(--x-position), var(--y-position)) scale(1)}}";
47
65
 
48
66
  let HighlightBox = class {
@@ -50,10 +68,10 @@ let HighlightBox = class {
50
68
  index.registerInstance(this, hostRef);
51
69
  }
52
70
  getInsetValue() {
53
- return Handler.pipe(imageSearch_store.sequenceToOption(imageSearch_store.imageSearchState.searchArea, imageSearch_store.imageSearchState.imageBounds), imageSearch_store.Option.map(([selection, image]) => getClipValue(selection, image)), imageSearch_store.Option.getOrElse(() => ""));
71
+ return index$1.pipe(index$1.sequenceToOption(index$1.imageSearchState.searchArea, index$1.imageSearchState.imageBounds), index$1.Option.map(([selection, image]) => getClipValue(selection, image)), index$1.Option.getOrElse(() => ""));
54
72
  }
55
73
  renderImage() {
56
- return Handler.pipe(imageSearch_store.sequenceToOption(imageSearch_store.imageSearchState.imageUrl, imageSearch_store.imageSearchState.imageBounds), imageSearch_store.Option.map(([url, bounds]) => (index.h("img", { src: url, width: bounds.width, height: bounds.height, style: { "clip-path": `${this.getInsetValue()}` } }))), imageSearch_store.Option.getOrElse(() => ""));
74
+ return index$1.pipe(index$1.sequenceToOption(index$1.imageSearchState.imageUrl, index$1.imageSearchState.imageBounds), index$1.Option.map(([url, bounds]) => (index.h("img", { src: url, width: bounds.width, height: bounds.height, style: { "clip-path": `${this.getInsetValue()}` } }))), index$1.Option.getOrElse(() => ""));
57
75
  }
58
76
  render() {
59
77
  return index.h(index.Host, null, this.renderImage());
@@ -83,19 +101,19 @@ let ImageCropper = class {
83
101
  handleHandlerMove(event) {
84
102
  event.preventDefault();
85
103
  event.stopPropagation();
86
- const destination = Handler.fromMouseEvent(event);
87
- const distance = Handler.pointDiffSemigroup.concat(destination, this.mouseStartPoint);
104
+ const destination = index$1.fromMouseEvent(event);
105
+ const distance = index$1.pointDiffSemigroup.concat(destination, this.mouseStartPoint);
88
106
  const transformedHandler = {
89
107
  position: distance,
90
108
  direction: this.handlerMoveDirection,
91
109
  };
92
- imageSearch_store._function.pipe(imageSearch_store.imageSearchState.searchArea, imageSearch_store.Option.map((area) => {
93
- const newSearchArea = imageSearch_store.transform(area, transformedHandler);
110
+ index$1._function.pipe(index$1.imageSearchState.searchArea, index$1.Option.map((area) => {
111
+ const newSearchArea = index$1.transform(area, transformedHandler);
94
112
  if (this.outOfBounds(newSearchArea))
95
113
  return;
96
- imageSearch_store.imageSearchState.searchArea = imageSearch_store.Option.some(newSearchArea);
114
+ index$1.imageSearchState.searchArea = index$1.Option.some(newSearchArea);
97
115
  this.mouseStartPoint = destination;
98
- imageSearch_store.imageSearchState.detectedObject = undefined;
116
+ index$1.imageSearchState.detectedObject = undefined;
99
117
  }));
100
118
  }
101
119
  outOfBounds(area) {
@@ -109,23 +127,23 @@ let ImageCropper = class {
109
127
  handleCropperMove(ev) {
110
128
  ev.preventDefault();
111
129
  ev.stopPropagation();
112
- const destination = Handler.fromMouseEvent(ev);
113
- const distance = Handler.pointDiffSemigroup.concat(destination, this.mouseStartPoint);
114
- imageSearch_store._function.pipe(imageSearch_store.imageSearchState.searchArea, imageSearch_store.Option.map((searchArea) => {
115
- const newSearchArea = imageSearch_store.move(searchArea, distance);
130
+ const destination = index$1.fromMouseEvent(ev);
131
+ const distance = index$1.pointDiffSemigroup.concat(destination, this.mouseStartPoint);
132
+ index$1._function.pipe(index$1.imageSearchState.searchArea, index$1.Option.map((searchArea) => {
133
+ const newSearchArea = index$1.move(searchArea, distance);
116
134
  if (newSearchArea.x < 0 ||
117
135
  newSearchArea.y < 0 ||
118
136
  this.bounds.height - (newSearchArea.y + newSearchArea.height) < 0 ||
119
137
  this.bounds.width - (newSearchArea.x + newSearchArea.width) < 0)
120
138
  return;
121
- imageSearch_store.imageSearchState.detectedObject = undefined;
122
- imageSearch_store.imageSearchState.searchArea = imageSearch_store.Option.some(newSearchArea);
139
+ index$1.imageSearchState.detectedObject = undefined;
140
+ index$1.imageSearchState.searchArea = index$1.Option.some(newSearchArea);
123
141
  this.mouseStartPoint = destination;
124
142
  }));
125
143
  }
126
144
  handlePointerDown(event) {
127
145
  event.stopPropagation();
128
- this.mouseStartPoint = Handler.fromMouseEvent(event);
146
+ this.mouseStartPoint = index$1.fromMouseEvent(event);
129
147
  // should be htmlelement or handler
130
148
  const target = findTarget(event);
131
149
  if (target.localName === "cropper-handler") {
@@ -145,18 +163,18 @@ let ImageCropper = class {
145
163
  this.el.removeEventListener("pointermove", this.pointerMoveListener);
146
164
  document.removeEventListener("pointerup", this.pointerReleaseListener);
147
165
  this.mouseStartPoint = undefined;
148
- imageSearch_store.makeRectangularSearchRequest();
166
+ index$1.makeRectangularSearchRequest();
149
167
  this.cropperChanged.emit();
150
168
  }
151
169
  getStyleMap() {
152
- return imageSearch_store._function.pipe(imageSearch_store.imageSearchState.searchArea, imageSearch_store.Option.map((rectangle) => {
170
+ return index$1._function.pipe(index$1.imageSearchState.searchArea, index$1.Option.map((rectangle) => {
153
171
  return {
154
172
  width: `${rectangle.width}px`,
155
173
  height: `${rectangle.height}px`,
156
174
  transform: `translate3d(${rectangle.x}px, ${rectangle.y}px, 0)`,
157
175
  cursor: this.handleMove ? "move" : "default",
158
176
  };
159
- }), imageSearch_store.Option.getOrElse(() => {
177
+ }), index$1.Option.getOrElse(() => {
160
178
  return {};
161
179
  }));
162
180
  }
@@ -165,7 +183,7 @@ let ImageCropper = class {
165
183
  "crop-area": true,
166
184
  active: this.handleMove,
167
185
  disabled: this.disabled,
168
- }, draggable: false, style: this.getStyleMap(), onContextMenu: () => false, onPointerDown: (ev) => this.handlePointerDown(ev) }, imageSearch_store.imageSearchState.cropperHandlers.map((handler) => (index.h("cropper-handler", { disabled: this.disabled, handler: handler, onPointerDown: (ev) => this.handlePointerDown(ev) }))))));
186
+ }, draggable: false, style: this.getStyleMap(), onContextMenu: () => false, onPointerDown: (ev) => this.handlePointerDown(ev) }, index$1.imageSearchState.cropperHandlers.map((handler) => (index.h("cropper-handler", { disabled: this.disabled, handler: handler, onPointerDown: (ev) => this.handlePointerDown(ev) }))))));
169
187
  }
170
188
  get el() { return index.getElement(this); }
171
189
  };
@@ -191,12 +209,12 @@ let SearchFilters = class {
191
209
  }
192
210
  selectFilter(filter) {
193
211
  this.selectedCategoryId = getFilterId(filter);
194
- imageSearch_store.imageSearchState.activeIonLink = filter;
212
+ index$1.imageSearchState.activeIonLink = filter;
195
213
  this.filterSelected.emit("select");
196
214
  }
197
215
  clearSelectedFilter() {
198
216
  this.selectedCategoryId = null;
199
- imageSearch_store.imageSearchState.activeIonLink = undefined;
217
+ index$1.imageSearchState.activeIonLink = undefined;
200
218
  this.findSelectedFilter().blur();
201
219
  this.filterSelected.emit("deselect");
202
220
  }
@@ -223,7 +241,7 @@ let SearchFilters = class {
223
241
  }, style: { "animation-delay": `${n * 10}ms` }, onPointerUp: (ev) => {
224
242
  ev.stopPropagation();
225
243
  this.handleFilterSelection(f);
226
- }, onKeyPress: (ev) => this.handleEnter(ev, f) }, this.isFilterSelected(f) ? index.h(index$1.CheckIcon, null) : null, f.name))), index.h("div", { class: {
244
+ }, onKeyPress: (ev) => this.handleEnter(ev, f) }, this.isFilterSelected(f) ? index.h(index$2.CheckIcon, null) : null, f.name))), index.h("div", { class: {
227
245
  filter: true,
228
246
  "show-more": true,
229
247
  hidden: this.filter.filters.length <= FILTERS_COUNT,
@@ -247,31 +265,31 @@ let VviinnDetectedObject = class {
247
265
  this.position = ["0", "0"];
248
266
  }
249
267
  getObjectPosition() {
250
- return imageSearch_store._function.pipe(imageSearch_store.imageSearchState.imageBounds, imageSearch_store.Option.map((bounds) => {
251
- const objectRectangle = imageSearch_store.fromAlt(imageSearch_store.foldValueObject(this.detectedObject).rectangle);
252
- const { x, y } = imageSearch_store._function.pipe(objectRectangle, imageSearch_store.scaleWithSized(bounds), imageSearch_store.center);
268
+ return index$1._function.pipe(index$1.imageSearchState.imageBounds, index$1.Option.map((bounds) => {
269
+ const objectRectangle = index$1.fromAlt(index$1.foldValueObject(this.detectedObject).rectangle);
270
+ const { x, y } = index$1._function.pipe(objectRectangle, index$1.scaleWithSized(bounds), index$1.center);
253
271
  return [`${x}px`, `${y}px`];
254
- }), imageSearch_store.Option.getOrElse(() => ["0", "0"]));
272
+ }), index$1.Option.getOrElse(() => ["0", "0"]));
255
273
  }
256
274
  selectDetectedObject() {
257
- imageSearch_store._function.pipe(imageSearch_store.imageSearchState.imageBounds, imageSearch_store.Option.map((bounds) => {
258
- const rectangle = imageSearch_store.foldValueObject(this.detectedObject).rectangle;
259
- const transformedRect = imageSearch_store.fromAlt(rectangle);
260
- const scaledRect = imageSearch_store.scaleWithSized(bounds)(transformedRect);
261
- imageSearch_store.imageSearchState.detectedObject = this.detectedObject;
262
- imageSearch_store.imageSearchState.searchArea = imageSearch_store.Option.some(scaledRect);
275
+ index$1._function.pipe(index$1.imageSearchState.imageBounds, index$1.Option.map((bounds) => {
276
+ const rectangle = index$1.foldValueObject(this.detectedObject).rectangle;
277
+ const transformedRect = index$1.fromAlt(rectangle);
278
+ const scaledRect = index$1.scaleWithSized(bounds)(transformedRect);
279
+ index$1.imageSearchState.detectedObject = this.detectedObject;
280
+ index$1.imageSearchState.searchArea = index$1.Option.some(scaledRect);
263
281
  }));
264
- imageSearch_store.makeRectangularSearchRequest();
282
+ index$1.makeRectangularSearchRequest();
265
283
  this.detectedObjectClicked.emit();
266
284
  }
267
285
  isActive() {
268
286
  if (!this.detectedObject)
269
287
  return false;
270
- if (!imageSearch_store.imageSearchState.detectedObject)
288
+ if (!index$1.imageSearchState.detectedObject)
271
289
  return false;
272
- const thisObject = imageSearch_store.foldValueObject(this.detectedObject);
273
- const savedObject = imageSearch_store.foldValueObject(imageSearch_store.imageSearchState.detectedObject);
274
- return imageSearch_store.detectedObjectEq.equals(thisObject, savedObject);
290
+ const thisObject = index$1.foldValueObject(this.detectedObject);
291
+ const savedObject = index$1.foldValueObject(index$1.imageSearchState.detectedObject);
292
+ return index$1.detectedObjectEq.equals(thisObject, savedObject);
275
293
  }
276
294
  render() {
277
295
  return (index.h(index.Host, { class: {
@@ -297,6 +315,18 @@ let VviinnEmptyResults = class {
297
315
  };
298
316
  VviinnEmptyResults.style = vviinnEmptyResultsCss;
299
317
 
318
+ const vviinnErrorCss = ":host{background:#F4F4F4;border-radius:8px;display:grid;grid-gap:20px;padding:24px;text-align:center}::slotted(svg){display:grid;align-self:center}::slotted(h4){margin:unset;font-weight:600;font-size:18px;line-height:24px}::slotted(span){font-size:14px;line-height:20px}::slotted(button){-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;background:transparent;color:var(--color-primary, var(--color-primary-system));font-weight:600;font-size:16px;line-height:20px;cursor:pointer}";
319
+
320
+ let VviinnError = class {
321
+ constructor(hostRef) {
322
+ index.registerInstance(this, hostRef);
323
+ }
324
+ render() {
325
+ return (index.h(index.Host, null, index.h("slot", { name: "icon" }), index.h("slot", { name: "title" }), index.h("slot", { name: "text" }), index.h("slot", { name: "action" })));
326
+ }
327
+ };
328
+ VviinnError.style = vviinnErrorCss;
329
+
300
330
  const vviinnExampleImageCss = ":host{display:block;margin-bottom:8px;position:relative}img{width:100%;height:auto;cursor:pointer}.image-preloader{background:rgba(0, 0, 0, 0.25);border-radius:4px;bottom:12px;display:none;padding:4px 6px;pointer-events:none;position:absolute;right:12px;z-index:4}vviinn-preloader{--preloader-size:12px}@media (max-width: 640px){.image-preloader{display:block}}";
301
331
 
302
332
  let VviinnExampleImage = class {
@@ -311,14 +341,14 @@ let VviinnExampleImage = class {
311
341
  }
312
342
  async selectImage(_event) {
313
343
  this.selected = true;
314
- const file = await imageSearch_store.toFile(this.src);
315
- const processResult = await imageSearch_store.processSelectedFile(file);
316
- imageSearch_store._function.pipe(processResult, imageSearch_store.Either.match(() => this.exampleImageError.emit(), () => this.exampleImageSelected.emit()));
344
+ const file = await index$1.toFile(this.src);
345
+ const processResult = await index$1.processSelectedFile(file);
346
+ index$1._function.pipe(processResult, index$1.Either.match(() => this.exampleImageError.emit(), () => this.exampleImageSelected.emit()));
317
347
  this.selected = false;
318
348
  }
319
349
  showPreloader() {
320
- return ((imageSearch_store.imageSearchState.objectDetectionInProgress ||
321
- imageSearch_store.imageSearchState.loading) &&
350
+ return ((index$1.imageSearchState.objectDetectionInProgress ||
351
+ index$1.imageSearchState.loading) &&
322
352
  this.selected);
323
353
  }
324
354
  render() {
@@ -361,12 +391,12 @@ let VviinnImageSelector = class {
361
391
  }
362
392
  async handleInputChange(event) {
363
393
  const input = event.target;
364
- const processingResult = await imageSearch_store.processSelectedFile(input.files[0]);
365
- imageSearch_store._function.pipe(processingResult, imageSearch_store.match(() => this.imageSelectedError.emit(), () => this.imageSelected.emit()));
394
+ const processingResult = await index$1.processSelectedFile(input.files[0]);
395
+ index$1._function.pipe(processingResult, index$1.match(() => this.imageSelectedError.emit(), () => this.imageSelected.emit()));
366
396
  input.value = null;
367
397
  }
368
398
  isLoading() {
369
- return (imageSearch_store.imageSearchState.loading || imageSearch_store.imageSearchState.objectDetectionInProgress);
399
+ return (index$1.imageSearchState.loading || index$1.imageSearchState.objectDetectionInProgress);
370
400
  }
371
401
  render() {
372
402
  return (index.h(index.Host, { exportparts: "button" }, this.isLoading() ? index.h("vviinn-preloader", null) : null, this.isLoading() ? null : (index.h("label", { htmlFor: "fileInput", part: "button" }, index.h("slot", { name: "upload-button-text" }, "Upload image"))), index.h("input", { id: "fileInput", class: "visually-hidden", type: "file", accept: "image/*", onChange: (event) => this.handleInputChange(event) })));
@@ -377,8 +407,8 @@ VviinnImageSelector.style = vviinnImageSelectorCss;
377
407
  const vviinnImageViewCss = ":host{display:grid;position:relative;justify-self:center}img{box-sizing:border-box;filter:brightness(60%);position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:-1}.image-preloader{background:rgba(0, 0, 0, 0.25);border-radius:4px;bottom:18px;padding:4px 6px;pointer-events:none;position:absolute;right:18px;z-index:4}vviinn-preloader{--preloader-size:12px}";
378
408
 
379
409
  const getImageSizes = (i) => {
380
- const dimensions = imageSearch_store.dimensionsFromImage(i);
381
- const resize = imageSearch_store.scaleByLargestSide(288);
410
+ const dimensions = index$1.dimensionsFromImage(i);
411
+ const resize = index$1.scaleByLargestSide(288);
382
412
  const newDimensions = resize(dimensions);
383
413
  const sizes = newDimensions.map(d => d.size);
384
414
  return [sizes[0], sizes[1]];
@@ -389,34 +419,34 @@ let VviinnImageView = class {
389
419
  }
390
420
  handleInitialImageLoad(ev) {
391
421
  const target = ev.target;
392
- const imageBounds = imageSearch_store.fromImage(target);
422
+ const imageBounds = index$1.fromImage(target);
393
423
  const padding = 12;
394
- const { x, y } = imageSearch_store.move(imageBounds, { x: padding, y: padding });
424
+ const { x, y } = index$1.move(imageBounds, { x: padding, y: padding });
395
425
  const searchArea = {
396
426
  x,
397
427
  y,
398
428
  width: imageBounds.width - padding * 2,
399
429
  height: imageBounds.height - padding * 2,
400
430
  };
401
- imageSearch_store.imageSearchState.imageBounds = imageSearch_store.Option.some(imageBounds);
402
- imageSearch_store.imageSearchState.searchArea = imageSearch_store.Option.some(searchArea);
431
+ index$1.imageSearchState.imageBounds = index$1.Option.some(imageBounds);
432
+ index$1.imageSearchState.searchArea = index$1.Option.some(searchArea);
403
433
  }
404
434
  renderDetectedObject(object) {
405
435
  return index.h("vviinn-detected-object", { detectedObject: object });
406
436
  }
407
437
  renderImage() {
408
- return imageSearch_store._function.pipe(imageSearch_store.sequenceToOption(imageSearch_store.imageSearchState.imageUrl, imageSearch_store.imageSearchState.image), imageSearch_store.Option.map(([url, refImage]) => {
438
+ return index$1._function.pipe(index$1.sequenceToOption(index$1.imageSearchState.imageUrl, index$1.imageSearchState.image), index$1.Option.map(([url, refImage]) => {
409
439
  const [width, height] = getImageSizes(refImage);
410
440
  const image = (index.h("img", { decoding: "async", width: width, height: height, src: url, onLoad: (el) => this.handleInitialImageLoad(el), draggable: false }));
411
441
  return image;
412
- }), imageSearch_store.Option.getOrElse(() => null));
442
+ }), index$1.Option.getOrElse(() => null));
413
443
  }
414
444
  renderCropper() {
415
- return imageSearch_store._function.pipe(imageSearch_store.imageSearchState.imageUrl, imageSearch_store.Option.map(() => index.h("image-cropper", null)), imageSearch_store.Option.getOrElse(() => null));
445
+ return index$1._function.pipe(index$1.imageSearchState.imageUrl, index$1.Option.map(() => index.h("image-cropper", null)), index$1.Option.getOrElse(() => null));
416
446
  }
417
447
  render() {
418
- return (index.h(index.Host, null, imageSearch_store.imageSearchState.loading ||
419
- imageSearch_store.imageSearchState.objectDetectionInProgress ? (index.h("div", { class: "image-preloader" }, index.h("vviinn-preloader", null))) : null, index.h("highlight-box", null), this.renderImage(), this.renderCropper(), imageSearch_store.imageSearchState.detectedObjects.map((o) => this.renderDetectedObject(o))));
448
+ return (index.h(index.Host, null, index$1.imageSearchState.loading ||
449
+ index$1.imageSearchState.objectDetectionInProgress ? (index.h("div", { class: "image-preloader" }, index.h("vviinn-preloader", null))) : null, index.h("highlight-box", null), this.renderImage(), this.renderCropper(), index$1.imageSearchState.detectedObjects.map((o) => this.renderDetectedObject(o))));
420
450
  }
421
451
  };
422
452
  VviinnImageView.style = vviinnImageViewCss;
@@ -474,7 +504,7 @@ let VviinnOnboardingCard1 = class {
474
504
  customizedSlots.slotChangeListener(this, this.el);
475
505
  }
476
506
  render() {
477
- return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-1-icon" }, index.h(index$1.OnboardingCard1Icon, null)), index.h("slot", { name: "onboarding-card-1-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Starte die Bildsuche"), index.h("p", null, "Lade ein Bild aus Deiner Galerie hoch oder fotografiere ein Produkt mit Deiner Kamera.")))));
507
+ return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-1-icon" }, index.h(index$2.OnboardingCard1Icon, null)), index.h("slot", { name: "onboarding-card-1-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Starte die Bildsuche"), index.h("p", null, "Lade ein Bild aus Deiner Galerie hoch oder fotografiere ein Produkt mit Deiner Kamera.")))));
478
508
  }
479
509
  get el() { return index.getElement(this); }
480
510
  };
@@ -490,7 +520,7 @@ let VviinnOnboardingCard2 = class {
490
520
  customizedSlots.slotChangeListener(this, this.el);
491
521
  }
492
522
  render() {
493
- return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-2-icon" }, index.h(index$1.OnboardingCard2Icon, null)), index.h("slot", { name: "onboarding-card-2-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Verfeiner deine Suche"), index.h("p", null, "Du kannst den Bildrahmen selber festlegen und so die Produkte genau ausw\u00E4hlen.")))));
523
+ return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-2-icon" }, index.h(index$2.OnboardingCard2Icon, null)), index.h("slot", { name: "onboarding-card-2-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Verfeiner deine Suche"), index.h("p", null, "Du kannst den Bildrahmen selber festlegen und so die Produkte genau ausw\u00E4hlen.")))));
494
524
  }
495
525
  get el() { return index.getElement(this); }
496
526
  };
@@ -506,7 +536,7 @@ let VviinnOnboardingCard3 = class {
506
536
  customizedSlots.slotChangeListener(this, this.el);
507
537
  }
508
538
  render() {
509
- return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-3-icon" }, index.h(index$1.OnboardingCard3Icon, null)), index.h("slot", { name: "onboarding-card-3-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Ohne Hintergrund"), index.h("p", null, "Die besten Ergebnisse erh\u00E4ltst Du, wenn das gesuchte Objekt mit einfarbigem und hellem Hintergrund zu sehen ist.")))));
539
+ return (index.h(index.Host, null, index.h("slot", { name: "onboarding-card-3-icon" }, index.h(index$2.OnboardingCard3Icon, null)), index.h("slot", { name: "onboarding-card-3-text" }, index.h("div", { class: "text" }, index.h("h4", null, "Ohne Hintergrund"), index.h("p", null, "Die besten Ergebnisse erh\u00E4ltst Du, wenn das gesuchte Objekt mit einfarbigem und hellem Hintergrund zu sehen ist.")))));
510
540
  }
511
541
  get el() { return index.getElement(this); }
512
542
  };
@@ -539,6 +569,23 @@ let VviinnOverlayedModal = class {
539
569
  };
540
570
  VviinnOverlayedModal.style = vviinnOverlayedModalCss;
541
571
 
572
+ const vviinnPreloaderCss = ":host{--preloader-size:24px;--preloader-width:calc(var(--preloader-size) / 6);transform-origin:center;-webkit-animation:rotate 3s linear infinite;animation:rotate 3s linear infinite;border:var(--preloader-width) solid white;border-radius:50%;border-top-color:transparent;display:none;outline:0;width:var(--preloader-size);height:var(--preloader-size);box-sizing:border-box}:host(.active){display:flex}@-webkit-keyframes rotate{from{transform:rotate(-360deg)}to{transform:rotate(360deg)}}@keyframes rotate{from{transform:rotate(-360deg)}to{transform:rotate(360deg)}}";
573
+
574
+ let VviinnPreloader = class {
575
+ constructor(hostRef) {
576
+ index.registerInstance(this, hostRef);
577
+ }
578
+ isActive() {
579
+ return (index$1.imageSearchState.loading || index$1.imageSearchState.objectDetectionInProgress);
580
+ }
581
+ render() {
582
+ return (index.h(index.Host, { class: {
583
+ active: this.isActive(),
584
+ } }));
585
+ }
586
+ };
587
+ VviinnPreloader.style = vviinnPreloaderCss;
588
+
542
589
  const vviinnPrivacyBadgeCss = ":host{display:block;background:#F4F4F4;padding:17px}.content{display:grid;grid-template-columns:-webkit-min-content auto;grid-template-columns:min-content auto;grid-gap:9px}.content p{color:#525252;font-size:12px;line-height:16px;margin:unset}";
543
590
 
544
591
  let VviinnPrivacyBadge = class {
@@ -555,6 +602,182 @@ let VviinnPrivacyBadge = class {
555
602
  };
556
603
  VviinnPrivacyBadge.style = vviinnPrivacyBadgeCss;
557
604
 
605
+ class GtagAnalytics {
606
+ sendImpression(product) {
607
+ var _a, _b, _c;
608
+ gtag('event', 'view_item_list', {
609
+ items: [
610
+ {
611
+ id: product.productId,
612
+ name: product.title,
613
+ brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
614
+ category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
615
+ list_name: 'VI VPR View',
616
+ price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
617
+ }
618
+ ]
619
+ });
620
+ return undefined;
621
+ }
622
+ sendClick(product) {
623
+ var _a, _b, _c;
624
+ gtag('event', 'select_content', {
625
+ content_type: 'product',
626
+ items: [
627
+ {
628
+ id: product.productId,
629
+ name: product.title,
630
+ brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
631
+ category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
632
+ list_name: 'VI VPR View',
633
+ price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
634
+ }
635
+ ]
636
+ });
637
+ return undefined;
638
+ }
639
+ }
640
+
641
+ class GAnalytics {
642
+ constructor() {
643
+ ga('require', 'ec');
644
+ }
645
+ convertProduct(product) {
646
+ var _a, _b, _c;
647
+ return {
648
+ id: product.productId,
649
+ name: product.title,
650
+ brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
651
+ category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
652
+ list: 'VI VPR View',
653
+ price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
654
+ };
655
+ }
656
+ sendImpression(product) {
657
+ ga('ec:addImpression', this.convertProduct(product));
658
+ return undefined;
659
+ }
660
+ sendClick(product) {
661
+ var _a, _b, _c;
662
+ ga('ec:addProduct', {
663
+ id: product.productId,
664
+ name: product.title,
665
+ brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
666
+ category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
667
+ price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
668
+ });
669
+ ga('ec:setAction', 'click', { list: 'VI VPR View' });
670
+ return undefined;
671
+ }
672
+ }
673
+
674
+ const getGtagAnalytics = () => index$1._function.pipe(index$1.Option.fromNullable(window.gtag), index$1.Option.map(() => new GtagAnalytics()));
675
+ const getCommonAnalytics = () => index$1._function.pipe(index$1.Option.fromNullable(window.ga), index$1.Option.map(() => new GAnalytics()));
676
+ const analyticsMonoid = index$1.Option.getMonoid(index$1.Semigroup.first());
677
+ const getAnalyticsModule = analyticsMonoid.concat(getGtagAnalytics(), getCommonAnalytics());
678
+
679
+ const FIT_EXPR = /fit\/\d+\//;
680
+ const containsFit = (url) => {
681
+ return index$1._function.pipe(url.match(FIT_EXPR), index$1.Either.fromNullable(url), index$1.Either.map(() => url));
682
+ };
683
+ const processWidth = (url, size) => {
684
+ return index$1._function.pipe(containsFit(url), index$1.Either.map((url) => url.replace(FIT_EXPR, `fit/${size}/`)), index$1.Either.getOrElse(() => url));
685
+ };
686
+ const Linked = (props, child) => props.deeplink ? (index.h("a", { class: props.part, part: props.part, href: props.deeplink }, child)) : (child);
687
+ const FormattedPrice = (props) => {
688
+ var _a;
689
+ const locale = props.locale;
690
+ const formattedPrice = new Intl.NumberFormat(locale, {
691
+ minimumFractionDigits: 2,
692
+ }).format(props.price);
693
+ const fullPrice = `${(_a = props.prefix) !== null && _a !== void 0 ? _a : ""} ${formattedPrice} ${props.currency}`;
694
+ return (index.h("span", { class: "price-amount", part: "price-amount" }, fullPrice));
695
+ };
696
+ const Price = (props) => {
697
+ const priceEl = (index.h(FormattedPrice, { prefix: props.prefix, currency: props.currency, price: props.price, locale: props.locale }));
698
+ return (index.h("span", { class: "price-container", part: "price-container" }, props.salePrice ? ([
699
+ index.h("span", { class: "price-sale", part: "price-sale" },
700
+ index.h(FormattedPrice, { prefix: props.prefix, currency: props.currency, price: props.salePrice, locale: props.locale })),
701
+ index.h("span", { class: "price-outdated", part: "price-outdated" }, priceEl),
702
+ ]) : (index.h("span", { class: "price-regular", part: "price-regular" }, priceEl))));
703
+ };
704
+ const Image = (props, onLoadEnd = () => undefined) => (index.h("picture", null,
705
+ index.h("img", { loading: props.lazy ? "lazy" : "eager", part: "image", class: "image", width: props.width, height: props.height, src: processWidth(props.src, props.width), alt: props.title, onLoad: onLoadEnd })));
706
+ const ResponsiveImage = (props, onLoadEnd = () => undefined) => (index.h("picture", null,
707
+ index.h("img", { loading: props.lazy ? "lazy" : "eager", part: "image", class: "image responsive", src: processWidth(props.src, props.width), alt: props.title, onLoad: onLoadEnd })));
708
+
709
+ const vviinnProductCardCss = ":host{align-items:center;display:flex;flex-direction:column;gap:8px;height:100%}.price-container{display:flex;flex-direction:column}.price-sale,.price-regular{font-style:normal;font-weight:normal;font-size:16px;line-height:24px;color:#161616}.price-outdated{font-style:normal;font-weight:normal;font-size:16px;line-height:24px;color:#757575;text-decoration:line-through}.product-type{word-wrap:anywhere}.image{display:grid;align-content:center;-o-object-position:50% 50%;object-position:50% 50%;-o-object-fit:contain;object-fit:contain;text-align:center;box-sizing:border-box}img.responsive{width:100%;height:auto;aspect-ratio:1}.brand,.type{display:none}.title{-webkit-box-orient:vertical;-webkit-line-clamp:2;color:#161616;display:-webkit-box;font-size:16px;font-style:normal;font-weight:500;line-height:24px;margin-bottom:8px;overflow:hidden}.deeplink{text-decoration:none}.image-link{display:contents}picture{position:relative;width:100%}:host(.dimmed) picture::before{content:\"\";width:100%;height:100%;box-sizing:border-box;background:#f7f7f7;display:block;top:0;left:0;position:absolute;mix-blend-mode:multiply}";
710
+
711
+ let VviinnProductCard = class {
712
+ constructor(hostRef) {
713
+ index.registerInstance(this, hostRef);
714
+ this.recommendationLoad = index.createEvent(this, "recommendationLoad", 7);
715
+ this.recommendationView = index.createEvent(this, "recommendationView", 7);
716
+ this.recommendationClick = index.createEvent(this, "recommendationClick", 7);
717
+ this.productImageLoaded = index.createEvent(this, "productImageLoaded", 7);
718
+ this.currency = undefined;
719
+ this.imageRatio = 1;
720
+ this.imageWidth = 200;
721
+ this.locale = undefined;
722
+ this.pricePrefix = undefined;
723
+ this.responsive = false;
724
+ this.dimmedBackground = false;
725
+ /** @internal */
726
+ this.index = 0;
727
+ this.imageLoaded = false;
728
+ this.productData = null;
729
+ this.intersectionObserver = new IntersectionObserver(this.intersectionCallback.bind(this), { threshold: 1.0 });
730
+ }
731
+ connectedCallback() {
732
+ this.productData = {
733
+ product: this.productId,
734
+ rank: this.index,
735
+ };
736
+ }
737
+ intersectionCallback(data) {
738
+ if (data.some((entry) => entry.isIntersecting)) {
739
+ index$1._function.pipe(getAnalyticsModule, index$1.Option.map((analytics) => analytics.sendImpression(this.getProduct())));
740
+ this.recommendationView.emit(this.productData);
741
+ this.intersectionObserver.disconnect();
742
+ }
743
+ }
744
+ componentDidLoad() {
745
+ this.recommendationLoad.emit(this.productData);
746
+ this.intersectionObserver.observe(this.el);
747
+ const links = this.el.shadowRoot.querySelectorAll("a");
748
+ links.forEach((link) => link.addEventListener("click", (event) => {
749
+ event.preventDefault();
750
+ event.stopImmediatePropagation();
751
+ this.recommendationClick.emit(this.productData);
752
+ index$1._function.pipe(getAnalyticsModule, index$1.Option.match(() => null, (analytics) => analytics.sendClick(this.getProduct())));
753
+ }));
754
+ }
755
+ getProduct() {
756
+ return index$1.imageSearchState.results.find((r) => r.productId === this.productId);
757
+ }
758
+ renderImage() {
759
+ const props = {
760
+ width: this.imageWidth,
761
+ height: this.imageWidth * this.imageRatio,
762
+ src: this.image,
763
+ title: this.productTitle,
764
+ lazy: false,
765
+ };
766
+ return this.responsive
767
+ ? ResponsiveImage(props, () => this.kek())
768
+ : Image(props, () => this.kek());
769
+ }
770
+ kek() {
771
+ this.productImageLoaded.emit(this.productId);
772
+ }
773
+ render() {
774
+ var _a, _b, _c;
775
+ return (index.h(index.Host, { part: "product-card", class: { dimmed: this.dimmedBackground }, exportparts: "brand, currency, deeplink, image, image-link, price-amount, price-container, price-outdated, price-prefix, price-regular, price-sale, title" }, index.h(Linked, { deeplink: this.deeplink, part: "image-link" }, this.renderImage()), index.h(Linked, { deeplink: this.deeplink, part: "deeplink" }, index.h("span", { class: "title", part: "title" }, this.productTitle)), index.h("span", { class: "brand", part: "brand" }, this.brand), index.h("span", { class: "type", part: "type" }, this.productType), index.h(Price, { prefix: (_a = this.pricePrefix) !== null && _a !== void 0 ? _a : index$1.state.pricePrefix, currency: (_b = this.currency) !== null && _b !== void 0 ? _b : index$1.state.currencySign, price: this.price, salePrice: this.salePrice, locale: (_c = this.locale) !== null && _c !== void 0 ? _c : index$1.state.locale })));
776
+ }
777
+ get el() { return index.getElement(this); }
778
+ };
779
+ VviinnProductCard.style = vviinnProductCardCss;
780
+
558
781
  const vviinnServerErrorCss = ":host{display:block}";
559
782
 
560
783
  let VviinnServerError = class {
@@ -588,7 +811,7 @@ const getStyleMap = (data) => {
588
811
  };
589
812
  };
590
813
  const Arrow = ({ kind, tabindex, disabled, onClick, onKeyDown, }) => (index.h("div", { class: getStyleMap({ kind, disabled }), onClick: onClick, tabindex: tabindex, onKeyDown: onKeyDown },
591
- index.h(index$1.ArrowIcon, null)));
814
+ index.h(index$2.ArrowIcon, null)));
592
815
 
593
816
  const vviinnSliderCss = ":host{--color-primary-system:#0F62FE;--color-primary-hover-system:#014CDA;--color-icons-system:#2F8EDF;--spacer:8px}:host{--num-items:0;--position:0;display:grid;grid-gap:20px;justify-items:center;position:relative}.items-wrapper{overflow:hidden;width:100%}.items{box-sizing:border-box;display:grid;grid-auto-flow:column;grid-template-columns:repeat(var(--num-items), 100%);transform:translateX(calc(-100% * var(--position)));transition:transform 0.33s ease-in-out}.controls{display:grid;grid-gap:16px;grid-template-columns:repeat(var(--num-items), -webkit-min-content);grid-template-columns:repeat(var(--num-items), min-content)}.bullet{background:#E0E0E0;border-radius:50%;box-sizing:border-box;cursor:pointer;height:8px;width:8px;transition:background 0.1s ease-in-out}.bullet:hover{background:#C6C6C6}.bullet.active{background:var(--color-primary, var(--color-primary-system))}.bullet:active{background:transparent;border:2px solid var(--color-primary, var(--color-primary-system))}.arrow-wrapper{align-items:center;background:white;border:2px solid white;bottom:0;box-sizing:border-box;display:grid;height:calc(var(--spacer) * 6);justify-items:center;margin:auto;position:absolute;top:0;transform:translate3d(0, -50%, 0);transition:border 0.25ms ease-in-out;width:calc(var(--spacer) * 4)}.arrow-wrapper:active{border-color:var(--color-primary, var(--color-primary-system));opacity:0.75}.arrow-wrapper:focus{border-color:var(--color-primary, var(--color-primary-system));opacity:0.5;outline:none}.prev{left:0}.next{right:0}.next>svg{transform:rotate3d(0, 1, 0, 180deg)}.arrow-wrapper>svg{transition:fill 0.25ms ease-in-out;fill:#A8A8A8}.arrow-wrapper:hover>svg{fill:#8D8D8D}";
594
817
 
@@ -597,7 +820,7 @@ let VviinnSlider = class {
597
820
  index.registerInstance(this, hostRef);
598
821
  this.elementsCount = 0;
599
822
  this.internalPosition = 0;
600
- this.swipeStartPosition = imageSearch_store.Option.none;
823
+ this.swipeStartPosition = index$1.Option.none;
601
824
  this.showBullets = true;
602
825
  this.position = 0;
603
826
  this.showArrows = false;
@@ -627,7 +850,7 @@ let VviinnSlider = class {
627
850
  this.setActiveCssClassToSlide(index);
628
851
  }
629
852
  renderBullets() {
630
- return this.showBullets ? (index.h("div", { class: "controls" }, imageSearch_store.NonEmptyArray.range(0, this.elementsCount - 1).map((i) => (index.h("div", { class: {
853
+ return this.showBullets ? (index.h("div", { class: "controls" }, index$1.NonEmptyArray.range(0, this.elementsCount - 1).map((i) => (index.h("div", { class: {
631
854
  bullet: true,
632
855
  active: i == this.internalPosition % this.elementsCount,
633
856
  }, onClick: () => this.goToSlide(i) }))))) : null;
@@ -664,13 +887,13 @@ let VviinnSlider = class {
664
887
  handleTouchStart(event) {
665
888
  if (!this.showBullets)
666
889
  return;
667
- this.swipeStartPosition = imageSearch_store._function.pipe(event.touches[0], imageSearch_store.Option.fromNullable, imageSearch_store.Option.map((t) => t.clientX));
890
+ this.swipeStartPosition = index$1._function.pipe(event.touches[0], index$1.Option.fromNullable, index$1.Option.map((t) => t.clientX));
668
891
  }
669
892
  handleTouchEnd(event) {
670
893
  if (!this.showBullets)
671
894
  return;
672
- const swipeEndPosition = imageSearch_store._function.pipe(event.changedTouches[0], imageSearch_store.Option.fromNullable, imageSearch_store.Option.map((t) => t.clientX));
673
- imageSearch_store._function.pipe(imageSearch_store.sequenceToOption(this.swipeStartPosition, swipeEndPosition), imageSearch_store.Option.map(([start, end]) => Ord.compare(start, end)), imageSearch_store.Option.map((swipeDirection) => {
895
+ const swipeEndPosition = index$1._function.pipe(event.changedTouches[0], index$1.Option.fromNullable, index$1.Option.map((t) => t.clientX));
896
+ index$1._function.pipe(index$1.sequenceToOption(this.swipeStartPosition, swipeEndPosition), index$1.Option.map(([start, end]) => Ord.compare(start, end)), index$1.Option.map((swipeDirection) => {
674
897
  switch (swipeDirection) {
675
898
  case 1:
676
899
  return this.nextSlide();
@@ -710,6 +933,166 @@ let VviinnTeaser = class {
710
933
  };
711
934
  VviinnTeaser.style = vviinnTeaserCss;
712
935
 
936
+ const vviinnVpsWidgetCss = ":host{--color-primary-system:#0F62FE;--color-primary-hover-system:#014CDA;--color-icons-system:#2F8EDF;--spacer:8px}:host{display:block}.hidden{visibility:hidden;height:1px}vviinn-overlayed-modal.first-screen::part(title),vviinn-overlayed-modal.first-screen::part(secondary-action){visibility:hidden}.start-page{display:grid;grid-template-columns:repeat(2, 1fr);min-height:580px}.start-page_block{align-content:start;border-right:1px solid #F4F4F4;display:grid;padding:48px}.start-page_block.error{align-content:center}#onboarding-block{border-right:unset;box-sizing:border-box;grid-gap:24px;overflow-y:auto;position:relative;width:100%}vviinn-teaser{margin-bottom:32px;margin-top:-24px}vviinn-image-selector{align-items:center;background:var(--color-primary, var(--color-primary-system));border-color:var(--color-primary, var(--color-primary-system));border-radius:2px;color:white;display:grid;font-size:16px;font-weight:600;height:56px;justify-items:center;margin-bottom:16px;transition:background 0.1s ease-in-out}vviinn-image-selector:hover{background:var(--color-primary-hover, var(--color-primary-hover-system));border-color:var(--color-primary-hover, var(--color-primary-hover-system))}vviinn-image-selector:active{border-color:black}.upload-button-content{display:grid;align-items:center;justify-items:start;justify-content:center;grid-template-columns:-webkit-max-content auto;grid-template-columns:max-content auto;grid-gap:16px}.results-page{display:grid;grid-template-columns:336px auto;box-sizing:border-box}.results-page>*{padding:24px;box-sizing:border-box}.products{align-content:center;align-items:start;box-sizing:border-box;display:grid;grid-gap:32px 16px;grid-template-columns:repeat(auto-fill, minmax(152px, 1fr));justify-items:center;padding:24px;padding-right:0;position:absolute;width:calc(100% - 16px)}.products.hidden{display:none}vviinn-empty-results{width:280px;align-self:center;justify-self:center}.products-wrapper{display:grid;overflow-y:auto;overflow-x:hidden;padding:unset;position:relative;width:100%}.image-wrapper{border-right:1px solid #F4F4F4;display:grid;grid-template-rows:-webkit-min-content 170px;grid-template-rows:min-content 170px;grid-gap:24px;min-width:100%}.onboarding-wrapper{position:absolute;width:100%;padding:48px;box-sizing:border-box;display:grid;grid-gap:64px;padding-bottom:24px}vviinn-product-card{gap:0;width:100%}vviinn-product-card::part(image){border:1px solid #eaeaea;margin-bottom:8px}vviinn-product-card::part(price-container),vviinn-product-card::part(deeplink),vviinn-product-card::part(title){align-self:start}search-filters span{display:none}search-filters::part(filter){background:#F4F4F4;border-radius:4px;border:1px solid #F4F4F4;box-sizing:border-box;color:#161616;font-size:14px;font-weight:600;line-height:20px}search-filters::part(show-more-filters){border:1px solid #f4f4f4;border-radius:4px;box-sizing:border-box;color:#161616;font-size:14px;font-weight:600;line-height:20px;padding:6px 16px}search-filters::part(show-more-filters):hover{background:#EAEAEA}search-filters::part(filter):hover{background:#EAEAEA}search-filters::part(filter):focus{outline:none;border:1px solid var(--color-primary, var(--color-primary-system))}search-filters::part(filter active){background:rgba(15, 98, 254, 0.15);color:var(--color-primary, var(--color-primary-system))}.filters-wrapper{overflow:auto}.results-page:not(.active){display:none}.nothing-found{display:grid;grid-gap:64px;justify-self:center;padding-top:64px;padding-bottom:16px;position:absolute;width:60%}@media (max-width: 768px){.start-page_block{padding:24px}.onboarding-wrapper{padding:24px}}@media (max-width: 640px){.start-page{grid-template-rows:-webkit-min-content;grid-template-rows:min-content;grid-template-columns:unset;grid-gap:48px;padding:24px 0 48px 0}}@media (max-width: 640px) and (min-width: 415px){.onboarding-wrapper{position:unset}#onboarding-block{overflow:unset}.start-page.active{height:1px;overflow:auto}}@media (max-width: 415px){.results-page>*{box-sizing:border-box;padding:24px}vviinn-slide{padding-bottom:48px}.start-page_block:last-of-type{border-right:unset;overflow-y:unset;position:static;box-sizing:border-box;width:unset}.start-page_block{padding:0 24px}vviinn-teaser{margin-top:24px}.onboarding-wrapper{position:static;width:unset;padding:unset;box-sizing:border-box}.results-page{grid-template-columns:unset;grid-template-rows:-webkit-min-content auto;grid-template-rows:min-content auto}.image{margin-bottom:8px}.image-wrapper{grid-template-rows:-webkit-min-content auto;grid-template-rows:min-content auto;width:100%}.products-wrapper{align-content:start;position:static;overflow-y:unset;width:100%;padding-top:0}.products{position:static;padding:0;width:unset;grid-gap:32px 16px;justify-content:center}.nothing-found{position:static;grid-gap:64px;padding:unset;align-content:start;width:unset}}@media (max-width: 320px){.products{grid-template-columns:unset}}vviinn-wrong-format,vviinn-server-error{width:280px;align-self:center;justify-self:center}";
937
+
938
+ const filterInt = (value) => /^[-+]?(\d+|Infinity)$/.test(value) ? Number(value) : NaN;
939
+ const notEmptyString = (s) => !index$1.isEmpty(s);
940
+ const notNan = (n) => !isNaN(n);
941
+ let VviinnVpsWidget = class {
942
+ constructor(hostRef) {
943
+ index.registerInstance(this, hostRef);
944
+ /** @internal */
945
+ this.apiPath = "https://api.vviinn.com";
946
+ /** When true modal window with widget will be shown */
947
+ this.active = false;
948
+ /** Currency sign will shown after price */
949
+ this.currencySign = "€";
950
+ /** Locale for currency formatting */
951
+ this.locale = "de-DE";
952
+ this.slidePosition = 0;
953
+ this.width = 0;
954
+ this.wrongImageFormat = false;
955
+ this.imageSource = null;
956
+ }
957
+ activeWatcher(value) {
958
+ if (value) {
959
+ this.overflow = document.body.style.overflow;
960
+ document.body.style.overflow = "hidden";
961
+ this.trackOpenEvent();
962
+ }
963
+ else {
964
+ document.body.style.overflow = this.overflow;
965
+ }
966
+ }
967
+ trackRecommendationView({ detail }) {
968
+ const recommendationViewEvent = index$1.createProductViewVpsEvent(Object.assign({ session_id: this.uiSessionId }, detail));
969
+ this.trackingApi.trackEvent(recommendationViewEvent);
970
+ }
971
+ trackRecommendationClick({ detail }) {
972
+ const recommendationClickEvent = index$1.createProductClickVpsEvent(Object.assign({ sessionId: this.uiSessionId }, detail));
973
+ this.trackingApi.trackEvent(recommendationClickEvent).finally(() => {
974
+ const product = index$1.imageSearchState.results.find((r) => r.productId === detail.product);
975
+ if (!product || !product.deeplink)
976
+ return;
977
+ window.location.href = product.deeplink;
978
+ });
979
+ }
980
+ trachSearchAreaChanges() {
981
+ const searchEvent = index$1.createSearchEvent({
982
+ session_id: this.uiSessionId,
983
+ source: this.imageSource,
984
+ search_area: "manual-selection",
985
+ });
986
+ this.trackingApi.trackEvent(searchEvent);
987
+ }
988
+ trackDetectedObject() {
989
+ const searchEvent = index$1.createSearchEvent({
990
+ session_id: this.uiSessionId,
991
+ source: this.imageSource,
992
+ search_area: "attention-point",
993
+ });
994
+ this.trackingApi.trackEvent(searchEvent);
995
+ }
996
+ trackFilter({ detail }) {
997
+ const searchEvent = index$1.createFilterEvent({
998
+ session_id: this.uiSessionId,
999
+ source: this.imageSource,
1000
+ kind: "category",
1001
+ action: detail,
1002
+ });
1003
+ this.trackingApi.trackEvent(searchEvent);
1004
+ }
1005
+ componentWillLoad() {
1006
+ customizedSlots.slotChangeListener(this, this.el);
1007
+ }
1008
+ connectedCallback() {
1009
+ index$1.state.apiPath = this.apiPath;
1010
+ index$1.state.currencySign = this.currencySign;
1011
+ index$1.state.locale = this.locale;
1012
+ index$1.imageSearchState.token = this.token;
1013
+ index$1.imageSearchState.campaignId = index$1._function.pipe(this.campaignId, index$1.Option.fromNullable, index$1.Option.chain(index$1.Option.fromPredicate(notEmptyString)), index$1.Option.map(filterInt), index$1.Option.chain(index$1.Option.fromPredicate(notNan)), index$1.Option.map((s) => `${s}`));
1014
+ this.uiSessionId = index$1.v4();
1015
+ }
1016
+ trackOpenEvent() {
1017
+ this.trackingApi = index$1.createTrackingApi(this.apiPath, this.token);
1018
+ const widgetOpenEvent = index$1.createWidgetVpsEvent({
1019
+ action: "open",
1020
+ session_id: this.uiSessionId,
1021
+ });
1022
+ this.trackingApi.trackEvent(widgetOpenEvent);
1023
+ }
1024
+ handleImageSelection(source) {
1025
+ this.imageSource = source;
1026
+ this.slidePosition = 1;
1027
+ const root = this.el.shadowRoot.querySelector("vviinn-overlayed-modal");
1028
+ const overlay = root.shadowRoot.querySelector("vviinn-overlay");
1029
+ const modal = overlay.querySelector("vviinn-modal");
1030
+ const modalBody = modal.shadowRoot.querySelector(".body");
1031
+ modalBody.scrollTop = 0;
1032
+ this.trackInitialSearch();
1033
+ }
1034
+ trackInitialSearch() {
1035
+ const searchEvent = index$1.createSearchEvent({
1036
+ session_id: this.uiSessionId,
1037
+ source: this.imageSource,
1038
+ search_area: "full",
1039
+ });
1040
+ this.trackingApi.trackEvent(searchEvent);
1041
+ }
1042
+ resetState() {
1043
+ this.resetScroll("onboarding-block");
1044
+ this.slidePosition = 0;
1045
+ index$1.imageSearchState.image = index$1.Option.none;
1046
+ index$1.imageSearchState.imageUrl = index$1.Option.none;
1047
+ index$1.imageSearchState.imageBounds = index$1.Option.none;
1048
+ index$1.imageSearchState.searchArea = index$1.Option.none;
1049
+ index$1.imageSearchState.results = [];
1050
+ index$1.imageSearchState.filters = [];
1051
+ index$1.imageSearchState.detectedObjects = [];
1052
+ index$1.imageSearchState.activeIonLink = undefined;
1053
+ index$1.imageSearchState.rectangleSearchForm = undefined;
1054
+ this.resetScroll("results-block");
1055
+ }
1056
+ haveErrors() {
1057
+ return this.wrongImageFormat || index$1.imageSearchState.serverError;
1058
+ }
1059
+ resetScroll(elementId, behavior = "auto") {
1060
+ const element = this.el.shadowRoot.getElementById(elementId);
1061
+ element.scroll({ top: 0, left: 0, behavior });
1062
+ }
1063
+ handleModalClose() {
1064
+ this.active = false;
1065
+ this.resetState();
1066
+ const elementsToReset = ["onboarding-block", "results-block"];
1067
+ elementsToReset.forEach((name) => this.resetScroll(name));
1068
+ const widgetOpenEvent = index$1.createWidgetVpsEvent({
1069
+ action: "close",
1070
+ session_id: this.uiSessionId,
1071
+ });
1072
+ this.trackingApi.trackEvent(widgetOpenEvent);
1073
+ }
1074
+ render() {
1075
+ return (index.h(index.Host, null, index.h("vviinn-overlayed-modal", { class: { "first-screen": this.slidePosition === 0 }, active: this.active, onSecondaryActionClicked: () => this.resetState(), onModalClosed: () => this.handleModalClose(), exportparts: "secondary-action, title, close-button, example-images" }, index.h("vviinn-slider", { showBullets: false, position: this.slidePosition }, index.h("vviinn-slide", { class: { "start-page": true } }, index.h("div", { class: {
1076
+ error: this.haveErrors(),
1077
+ "start-page_block": true,
1078
+ } }, index.h("vviinn-wrong-format", { class: { hidden: !this.wrongImageFormat }, onActionClick: () => (this.wrongImageFormat = false) }), index.h("vviinn-server-error", { class: { hidden: !index$1.imageSearchState.serverError }, onActionClick: () => (index$1.imageSearchState.serverError = false) }), index.h("vviinn-teaser", { class: { hidden: this.haveErrors() } }), index.h("vviinn-image-selector", { class: { hidden: this.haveErrors() }, onImageSelected: () => this.handleImageSelection("upload"), onImageSelectedError: () => (this.wrongImageFormat = true), part: "select-image_button" }, index.h("span", { slot: "upload-button-text", class: "upload-button-content" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "29", height: "28", fill: "none" }, index.h("defs", null), index.h("path", { fill: "#fff", "fill-rule": "evenodd", d: "M10.271 3.89A.875.875 0 0111 3.5h7c.293 0 .566.146.728.39l1.49 2.235h3.033a2.625 2.625 0 012.625 2.625V21a2.625 2.625 0 01-2.625 2.625H5.75A2.625 2.625 0 013.125 21V8.75A2.625 2.625 0 015.75 6.125h3.031l1.49-2.235zm1.197 1.36l-1.49 2.235a.875.875 0 01-.729.39H5.75a.875.875 0 00-.875.875V21a.875.875 0 00.875.875h17.5a.875.875 0 00.875-.875V8.75a.875.875 0 00-.875-.875h-3.5a.875.875 0 01-.729-.39l-1.49-2.235h-6.063z", "clip-rule": "evenodd" }), index.h("path", { fill: "#fff", "fill-rule": "evenodd", d: "M14.5 11.375a3.062 3.062 0 100 6.125 3.062 3.062 0 000-6.125zm-4.813 3.063a4.812 4.812 0 119.625 0 4.812 4.812 0 01-9.625 0z", "clip-rule": "evenodd" })), index.h("slot", { name: "vviinn-image-upload-button-text" }, index.h("span", null, "Kamera oder Bild ausw\u00E4hlen")))), index.h("vviinn-privacy-badge", { class: { hidden: this.haveErrors() } })), index.h("div", { id: "onboarding-block", class: "start-page_block" }, index.h("div", { class: "onboarding-wrapper" }, index.h("vviinn-onboarding", null), index.h("vviinn-example-images", { part: "example-images", onImageSelected: () => this.handleImageSelection("example"), onImageSelectedError: () => this.resetScroll("onboarding-block", "smooth") })))), index.h("vviinn-slide", { class: { "results-page": true, active: this.slidePosition == 1 } }, index.h("div", { class: "image-wrapper" }, index.h("vviinn-image-view", null), index.h("div", { class: "filters-wrapper" }, index.h("div", { class: "filters" }, index$1.imageSearchState.filters.map((filter) => (index.h("search-filters", { filter: filter })))))), index.h("div", { id: "results-block", class: "products-wrapper" }, index.h("div", { class: {
1079
+ "nothing-found": true,
1080
+ hidden: index$1.imageSearchState.results.length > 0,
1081
+ } }, index.h("vviinn-empty-results", null), index.h("vviinn-onboarding", null)), index.h("div", { class: {
1082
+ hidden: index$1.imageSearchState.results.length <= 0,
1083
+ products: true,
1084
+ } }, index$1.imageSearchState.results.map((p, i) => {
1085
+ var _a;
1086
+ return (index.h("vviinn-product-card", { hidden: true, productTitle: p.title, productId: p.productId, brand: p.brand, deeplink: p.deeplink, price: p.price.actual, salePrice: p.price.sale, imageWidth: 160, image: (_a = p.image.thumbnail) !== null && _a !== void 0 ? _a : p.image.original, part: "product-card", index: i }));
1087
+ }))))))));
1088
+ }
1089
+ get el() { return index.getElement(this); }
1090
+ static get watchers() { return {
1091
+ "active": ["activeWatcher"]
1092
+ }; }
1093
+ };
1094
+ VviinnVpsWidget.style = vviinnVpsWidgetCss;
1095
+
713
1096
  const vviinnWrongFormatCss = ":host{display:block}";
714
1097
 
715
1098
  let VviinnWrongFormat = class {
@@ -723,11 +1106,13 @@ let VviinnWrongFormat = class {
723
1106
  };
724
1107
  VviinnWrongFormat.style = vviinnWrongFormatCss;
725
1108
 
1109
+ exports.cropper_handler = CropperHandler;
726
1110
  exports.highlight_box = HighlightBox;
727
1111
  exports.image_cropper = ImageCropper;
728
1112
  exports.search_filters = SearchFilters;
729
1113
  exports.vviinn_detected_object = VviinnDetectedObject;
730
1114
  exports.vviinn_empty_results = VviinnEmptyResults;
1115
+ exports.vviinn_error = VviinnError;
731
1116
  exports.vviinn_example_image = VviinnExampleImage;
732
1117
  exports.vviinn_example_images = VviinnExampleImages;
733
1118
  exports.vviinn_image_selector = VviinnImageSelector;
@@ -739,9 +1124,12 @@ exports.vviinn_onboarding_card_2 = VviinnOnboardingCard2;
739
1124
  exports.vviinn_onboarding_card_3 = VviinnOnboardingCard3;
740
1125
  exports.vviinn_overlay = VviinnOverlay;
741
1126
  exports.vviinn_overlayed_modal = VviinnOverlayedModal;
1127
+ exports.vviinn_preloader = VviinnPreloader;
742
1128
  exports.vviinn_privacy_badge = VviinnPrivacyBadge;
1129
+ exports.vviinn_product_card = VviinnProductCard;
743
1130
  exports.vviinn_server_error = VviinnServerError;
744
1131
  exports.vviinn_slide = VviinnSlide;
745
1132
  exports.vviinn_slider = VviinnSlider;
746
1133
  exports.vviinn_teaser = VviinnTeaser;
1134
+ exports.vviinn_vps_widget = VviinnVpsWidget;
747
1135
  exports.vviinn_wrong_format = VviinnWrongFormat;