vviinn-widgets 2.7.2 → 2.7.3

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 (51) hide show
  1. package/dist/cjs/{index-df6896e2.js → cropper-handler_30.cjs.entry.js} +2323 -165
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/vviinn-widgets.cjs.js +1 -1
  4. package/dist/collection/components/vviinn-product-card/vviinn-product-card.js +5 -2
  5. package/dist/esm/{app-globals-865bc7a7.js → app-globals-2f864b5d.js} +1 -1
  6. package/dist/esm/{index-2fdd499d.js → cropper-handler_30.entry.js} +2294 -119
  7. package/dist/esm/{index-443468c7.js → index-040cfca9.js} +2 -2
  8. package/dist/esm/{index-51f71d18.js → index-2d36a726.js} +1 -1
  9. package/dist/esm/loader.js +3 -3
  10. package/dist/esm/vviinn-recommendations-sidebar.entry.js +2 -2
  11. package/dist/esm/vviinn-vpr-button.entry.js +2 -2
  12. package/dist/esm/vviinn-widgets.js +3 -3
  13. package/dist/types/components/vviinn-product-card/vviinn-product-card.d.ts +1 -0
  14. package/dist/vviinn-widgets/{p-3469b71a.js → p-334db07e.js} +1 -1
  15. package/dist/vviinn-widgets/{p-40bea5b5.entry.js → p-a98df480.entry.js} +1 -1
  16. package/dist/vviinn-widgets/p-da99b592.entry.js +1 -0
  17. package/dist/vviinn-widgets/{p-a6e0710f.entry.js → p-dc124f62.entry.js} +1 -1
  18. package/dist/vviinn-widgets/{p-465d043d.js → p-e5a7f685.js} +1 -1
  19. package/dist/vviinn-widgets/{p-166970f3.js → p-fe8dc0b9.js} +1 -1
  20. package/dist/vviinn-widgets/vviinn-widgets.esm.js +1 -1
  21. package/package.json +1 -1
  22. package/www/build/{p-3469b71a.js → p-334db07e.js} +1 -1
  23. package/www/build/{p-40bea5b5.entry.js → p-a98df480.entry.js} +1 -1
  24. package/www/build/p-c5ef37e7.js +125 -0
  25. package/www/build/p-da99b592.entry.js +1 -0
  26. package/www/build/{p-a6e0710f.entry.js → p-dc124f62.entry.js} +1 -1
  27. package/www/build/p-e0153ae2.css +6 -0
  28. package/www/build/{p-465d043d.js → p-e5a7f685.js} +1 -1
  29. package/www/build/{p-166970f3.js → p-fe8dc0b9.js} +1 -1
  30. package/www/build/vviinn-widgets.esm.js +1 -1
  31. package/www/index.html +2495 -1
  32. package/dist/cjs/cropper-handler_27.cjs.entry.js +0 -1135
  33. package/dist/cjs/customized-slots-06ca4007.js +0 -53
  34. package/dist/cjs/vviinn-carousel_2.cjs.entry.js +0 -1001
  35. package/dist/cjs/vviinn-vps-button.cjs.entry.js +0 -43
  36. package/dist/esm/cropper-handler_27.entry.js +0 -1105
  37. package/dist/esm/customized-slots-96902edf.js +0 -50
  38. package/dist/esm/vviinn-carousel_2.entry.js +0 -996
  39. package/dist/esm/vviinn-vps-button.entry.js +0 -39
  40. package/dist/vviinn-widgets/p-2dd35f19.entry.js +0 -1
  41. package/dist/vviinn-widgets/p-59bd2a99.js +0 -1
  42. package/dist/vviinn-widgets/p-74ed36af.entry.js +0 -1
  43. package/dist/vviinn-widgets/p-9def6b8b.entry.js +0 -1
  44. package/dist/vviinn-widgets/p-cd995515.js +0 -1
  45. package/www/build/p-2dd35f19.entry.js +0 -1
  46. package/www/build/p-59bd2a99.js +0 -1
  47. package/www/build/p-61933b75.js +0 -1
  48. package/www/build/p-74ed36af.entry.js +0 -1
  49. package/www/build/p-9def6b8b.entry.js +0 -1
  50. package/www/build/p-a67898be.css +0 -1
  51. package/www/build/p-cd995515.js +0 -1
@@ -1,1105 +0,0 @@
1
- import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-51f71d18.js';
2
- import { g as getCursorValue, p as pipe, O as Option, s as sequenceToOption, i as imageSearchState, a as pointDiffSemigroup, _ as _function, t as transform, m as move, f as fromMouseEvent, b as makeRectangularSearchRequest, c as fromAlt, d as foldValueObject, e as scaleWithSized, h as center, j as detectedObjectEq, k as toFile, l as processSelectedFile, E as Either, n as match, o as fromImage, q as dimensionsFromImage, r as scaleByLargestSide, S as Semigroup, u as state, N as NonEmptyArray, v as createProductViewVpsEvent, w as createProductClickVpsEvent, x as createSearchEvent, y as createFilterEvent, z as v4, A as createTrackingApi, B as createWidgetVpsEvent, C as isEmpty } from './index-2fdd499d.js';
3
- import { C as CheckIcon, O as OnboardingCard1Icon, a as OnboardingCard2Icon, b as OnboardingCard3Icon, A as ArrowIcon } from './index-443468c7.js';
4
- import { s as slotChangeListener } from './customized-slots-96902edf.js';
5
-
6
- 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}";
7
-
8
- let CropperHandler = class {
9
- constructor(hostRef) {
10
- registerInstance(this, hostRef);
11
- this.disabled = false;
12
- }
13
- render() {
14
- return (h(Host, { part: `handle ${getCursorValue(this.handler.direction)}`, class: {
15
- disabled: this.disabled,
16
- [getCursorValue(this.handler.direction)]: true,
17
- }, style: {
18
- "--size": "20px",
19
- cursor: getCursorValue(this.handler.direction),
20
- }, draggable: false }));
21
- }
22
- };
23
- CropperHandler.style = cropperHandlerCss;
24
-
25
- const fromRectangle = (shape, target) => {
26
- const top = `${shape.y}px`;
27
- const left = `${shape.x}px`;
28
- const right = `${target.width - (shape.x + shape.width)}px`;
29
- const bottom = `${target.height - (shape.y + shape.height)}px`;
30
- return {
31
- top,
32
- right,
33
- bottom,
34
- left,
35
- };
36
- };
37
- const printClip = (clip) => `inset(${clip.top} ${clip.right} ${clip.bottom} ${clip.left})`;
38
- const getClipValue = (shape, target) => printClip(fromRectangle(shape, target));
39
-
40
- // -------------------------------------------------------------------------------------
41
- // -------------------------------------------------------------------------------------
42
- // instances
43
- // -------------------------------------------------------------------------------------
44
- /**
45
- * @category instances
46
- * @since 2.10.0
47
- */
48
- var Eq = {
49
- equals: function (first, second) { return first === second; }
50
- };
51
- /**
52
- * @category instances
53
- * @since 2.10.0
54
- */
55
- var Ord = {
56
- equals: Eq.equals,
57
- compare: function (first, second) { return (first < second ? -1 : first > second ? 1 : 0); }
58
- };
59
-
60
- 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)}}";
61
-
62
- let HighlightBox = class {
63
- constructor(hostRef) {
64
- registerInstance(this, hostRef);
65
- }
66
- getInsetValue() {
67
- return pipe(sequenceToOption(imageSearchState.searchArea, imageSearchState.imageBounds), Option.map(([selection, image]) => getClipValue(selection, image)), Option.getOrElse(() => ""));
68
- }
69
- renderImage() {
70
- return pipe(sequenceToOption(imageSearchState.imageUrl, imageSearchState.imageBounds), Option.map(([url, bounds]) => (h("img", { src: url, width: bounds.width, height: bounds.height, style: { "clip-path": `${this.getInsetValue()}` } }))), Option.getOrElse(() => ""));
71
- }
72
- render() {
73
- return h(Host, null, this.renderImage());
74
- }
75
- };
76
- HighlightBox.style = highlightBoxCss;
77
-
78
- const findTarget = (ev) => {
79
- return ev.target;
80
- };
81
-
82
- const imageCropperCss = ":host{display:block;height:100%;left:0;position:absolute;top:0;width:100%}:host(.hidden){visibility:hidden}.crop-area{border:1px solid white;box-sizing:border-box;position:absolute;touch-action:none;transition-property:border-color, opacity;transition-duration:.25s;transition-timing-function:ease-in-out;z-index:2;position:relative;will-change:transform}.crop-area.active{border-color:whitesmoke}.crop-area.disabled{opacity:0.25}";
83
-
84
- const MIN_SEARCHAREA_SIZE = 40;
85
- let ImageCropper = class {
86
- constructor(hostRef) {
87
- registerInstance(this, hostRef);
88
- this.cropperChanged = createEvent(this, "cropperChanged", 7);
89
- this.disabled = false;
90
- this.handleMove = false;
91
- this.mouseStartPoint = undefined;
92
- this.bounds = undefined;
93
- }
94
- componentDidLoad() {
95
- this.bounds = this.el.getBoundingClientRect();
96
- }
97
- handleHandlerMove(event) {
98
- event.preventDefault();
99
- event.stopPropagation();
100
- const destination = fromMouseEvent(event);
101
- const distance = pointDiffSemigroup.concat(destination, this.mouseStartPoint);
102
- const transformedHandler = {
103
- position: distance,
104
- direction: this.handlerMoveDirection,
105
- };
106
- _function.pipe(imageSearchState.searchArea, Option.map((area) => {
107
- const newSearchArea = transform(area, transformedHandler);
108
- if (this.outOfBounds(newSearchArea))
109
- return;
110
- imageSearchState.searchArea = Option.some(newSearchArea);
111
- this.mouseStartPoint = destination;
112
- imageSearchState.detectedObject = undefined;
113
- }));
114
- }
115
- outOfBounds(area) {
116
- return (area.width < MIN_SEARCHAREA_SIZE ||
117
- area.height < MIN_SEARCHAREA_SIZE ||
118
- area.x < 0 ||
119
- area.y < 0 ||
120
- this.bounds.height - (area.y + area.height) < 0 ||
121
- this.bounds.width - (area.x + area.width) < 0);
122
- }
123
- handleCropperMove(ev) {
124
- ev.preventDefault();
125
- ev.stopPropagation();
126
- const destination = fromMouseEvent(ev);
127
- const distance = pointDiffSemigroup.concat(destination, this.mouseStartPoint);
128
- _function.pipe(imageSearchState.searchArea, Option.map((searchArea) => {
129
- const newSearchArea = move(searchArea, distance);
130
- if (newSearchArea.x < 0 ||
131
- newSearchArea.y < 0 ||
132
- this.bounds.height - (newSearchArea.y + newSearchArea.height) < 0 ||
133
- this.bounds.width - (newSearchArea.x + newSearchArea.width) < 0)
134
- return;
135
- imageSearchState.detectedObject = undefined;
136
- imageSearchState.searchArea = Option.some(newSearchArea);
137
- this.mouseStartPoint = destination;
138
- }));
139
- }
140
- handlePointerDown(event) {
141
- event.stopPropagation();
142
- this.mouseStartPoint = fromMouseEvent(event);
143
- // should be htmlelement or handler
144
- const target = findTarget(event);
145
- if (target.localName === "cropper-handler") {
146
- this.handlerMoveDirection = target.handler.direction;
147
- this.pointerMoveListener = this.handleHandlerMove.bind(this);
148
- }
149
- else {
150
- this.pointerMoveListener = this.handleCropperMove.bind(this);
151
- }
152
- this.pointerReleaseListener = this.handleSearchAreaRelease.bind(this);
153
- this.el.addEventListener("pointermove", this.pointerMoveListener);
154
- window.addEventListener("pointerup", this.pointerReleaseListener, {
155
- once: true,
156
- });
157
- }
158
- handleSearchAreaRelease() {
159
- this.el.removeEventListener("pointermove", this.pointerMoveListener);
160
- document.removeEventListener("pointerup", this.pointerReleaseListener);
161
- this.mouseStartPoint = undefined;
162
- makeRectangularSearchRequest();
163
- this.cropperChanged.emit();
164
- }
165
- getStyleMap() {
166
- return _function.pipe(imageSearchState.searchArea, Option.map((rectangle) => {
167
- return {
168
- width: `${rectangle.width}px`,
169
- height: `${rectangle.height}px`,
170
- transform: `translate3d(${rectangle.x}px, ${rectangle.y}px, 0)`,
171
- cursor: this.handleMove ? "move" : "default",
172
- };
173
- }), Option.getOrElse(() => {
174
- return {};
175
- }));
176
- }
177
- render() {
178
- return (h(Host, { exportparts: "handle, e-resize, n-resize, ne-resize, nw-resize, s-resize, se-resize, sw-resize, w-resize" }, h("div", { class: {
179
- "crop-area": true,
180
- active: this.handleMove,
181
- disabled: this.disabled,
182
- }, draggable: false, style: this.getStyleMap(), onContextMenu: () => false, onPointerDown: (ev) => this.handlePointerDown(ev) }, imageSearchState.cropperHandlers.map((handler) => (h("cropper-handler", { disabled: this.disabled, handler: handler, onPointerDown: (ev) => this.handlePointerDown(ev) }))))));
183
- }
184
- get el() { return getElement(this); }
185
- };
186
- ImageCropper.style = imageCropperCss;
187
-
188
- const searchFiltersCss = ":host{display:grid;grid-gap:1rem}.filters{display:flex;flex-direction:row;flex-wrap:wrap;gap:0.5rem}.filter{align-items:center;-webkit-animation-duration:0.25s;animation-duration:0.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-name:scalein;animation-name:scalein;border:1px solid lightgray;cursor:pointer;display:flex;flex-direction:row;grid-gap:8px;height:-webkit-max-content;height:-moz-max-content;height:max-content;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;padding:0.1rem;transform:scale(0);transition-property:background;transition-duration:0.25s;transition-timing-function:ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:6px 16px}.filter.active{border:1px solid black;padding:6px 8px}.filter:hover{border:1px solid gray}.show-more{display:flex}.show-more.hidden{display:none}.show-more::after{content:url(\"data:image/svg+xml,%3Csvg width='16' height='16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 12.2l-6-6L3.2 5 8 9.8 12.8 5 14 6.2l-6 6z' fill='%23525252'/%3E%3C/svg%3E\");display:block;height:16px;margin-top:1px;margin-left:8px}.show-more.active::after{transform:rotateX(180deg)}@-webkit-keyframes scalein{from{opacity:0;transform:scale(0.5)}to{opacity:1;transform:scale(1)}}@keyframes scalein{from{opacity:0;transform:scale(0.5)}to{opacity:1;transform:scale(1)}}@media (max-width: 415px){.show-more::after{transform:rotate(-90deg)}.show-more.active::after{transform:rotate(90deg)}}@media (max-width: 800px){.filters{flex-wrap:nowrap;overflow-x:scroll;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;grid-gap:unset}.filter{scroll-snap-align:end;margin-right:0.5rem}}";
189
-
190
- const FILTERS_COUNT = 5;
191
- const ACTIVE_FILTER_CLASSNAME = ".filter.active";
192
- const getFilterId = (filter) => filter.href.split("/").reverse()[0];
193
- let SearchFilters = class {
194
- constructor(hostRef) {
195
- registerInstance(this, hostRef);
196
- this.filterSelected = createEvent(this, "filterSelected", 7);
197
- this.filter = null;
198
- this.selectedCategoryId = null;
199
- this.hideFilters = true;
200
- }
201
- handleFilterSelection(filter) {
202
- return this.isFilterSelected(filter)
203
- ? this.clearSelectedFilter()
204
- : this.selectFilter(filter);
205
- }
206
- selectFilter(filter) {
207
- this.selectedCategoryId = getFilterId(filter);
208
- imageSearchState.activeIonLink = filter;
209
- this.filterSelected.emit("select");
210
- }
211
- clearSelectedFilter() {
212
- this.selectedCategoryId = null;
213
- imageSearchState.activeIonLink = undefined;
214
- this.findSelectedFilter().blur();
215
- this.filterSelected.emit("deselect");
216
- }
217
- findSelectedFilter() {
218
- return this.el.shadowRoot.querySelector(ACTIVE_FILTER_CLASSNAME);
219
- }
220
- toggleFilters() {
221
- this.hideFilters = !this.hideFilters;
222
- }
223
- handleEnter(ev, f) {
224
- if (ev.key !== "Enter")
225
- return;
226
- this.handleFilterSelection(f);
227
- }
228
- isFilterSelected(filterLink) {
229
- return this.selectedCategoryId === getFilterId(filterLink);
230
- }
231
- render() {
232
- return (h(Host, { exportparts: "filter, show-more-filters" }, h("div", { class: "filters" }, this.filter.filters
233
- .filter((_, i) => (this.hideFilters ? i < FILTERS_COUNT : true))
234
- .map((f, n) => (h("div", { role: "button", tabindex: "0", part: this.isFilterSelected(f) ? "filter active" : "filter", class: {
235
- filter: true,
236
- active: this.selectedCategoryId === getFilterId(f),
237
- }, style: { "animation-delay": `${n * 10}ms` }, onPointerUp: (ev) => {
238
- ev.stopPropagation();
239
- this.handleFilterSelection(f);
240
- }, onKeyPress: (ev) => this.handleEnter(ev, f) }, this.isFilterSelected(f) ? h(CheckIcon, null) : null, f.name))), h("div", { class: {
241
- filter: true,
242
- "show-more": true,
243
- hidden: this.filter.filters.length <= FILTERS_COUNT,
244
- active: !this.hideFilters,
245
- }, role: "button", tabindex: "0", "aria-role": "button", onClick: () => this.toggleFilters(), onKeyPress: (ev) => {
246
- if (ev.key === "Enter") {
247
- this.toggleFilters();
248
- }
249
- }, part: "show-more-filters" }, this.hideFilters ? "Zeige mehr" : "Zeige weniger"))));
250
- }
251
- get el() { return getElement(this); }
252
- };
253
- SearchFilters.style = searchFiltersCss;
254
-
255
- const vviinnDetectedObjectCss = ":host{--color-primary-system:#0F62FE;--color-primary-hover-system:#014CDA;--color-icons-system:#2F8EDF;--spacer:8px}:host{--size:32px;--x-position:0;--y-position:0;background:rgba(22, 22, 22, 0.5);border-radius:50%;border:none;cursor:pointer;display:block;height:var(--size);position:absolute;transition:opacity 0.25s;width:var(--size);z-index:2;transform:translate(calc(var(--x-position) - (var(--size) * 0.5)), calc(var(--y-position) - (var(--size) * 0.5)));transition:background 0.1 ease-in-out}:host(:hover){background:rgba(22, 22, 22, 0.75)}:host(.active){background:var(--color-primary, var(--color-primary-system))!important;border:2px solid white}:host::after{--size:32px;border-radius:50%;content:\"\";cursor:pointer;display:block;height:calc(var(--size) * 0.25);transform:translate(calc(-50% + var(--size) * 0.5), calc(-50% + var(--size) * 0.5));width:calc(var(--size) * 0.25);background:white}";
256
-
257
- let VviinnDetectedObject = class {
258
- constructor(hostRef) {
259
- registerInstance(this, hostRef);
260
- this.detectedObjectClicked = createEvent(this, "detectedObjectClicked", 7);
261
- this.position = ["0", "0"];
262
- }
263
- getObjectPosition() {
264
- return _function.pipe(imageSearchState.imageBounds, Option.map((bounds) => {
265
- const objectRectangle = fromAlt(foldValueObject(this.detectedObject).rectangle);
266
- const { x, y } = _function.pipe(objectRectangle, scaleWithSized(bounds), center);
267
- return [`${x}px`, `${y}px`];
268
- }), Option.getOrElse(() => ["0", "0"]));
269
- }
270
- selectDetectedObject() {
271
- _function.pipe(imageSearchState.imageBounds, Option.map((bounds) => {
272
- const rectangle = foldValueObject(this.detectedObject).rectangle;
273
- const transformedRect = fromAlt(rectangle);
274
- const scaledRect = scaleWithSized(bounds)(transformedRect);
275
- imageSearchState.detectedObject = this.detectedObject;
276
- imageSearchState.searchArea = Option.some(scaledRect);
277
- }));
278
- makeRectangularSearchRequest();
279
- this.detectedObjectClicked.emit();
280
- }
281
- isActive() {
282
- if (!this.detectedObject)
283
- return false;
284
- if (!imageSearchState.detectedObject)
285
- return false;
286
- const thisObject = foldValueObject(this.detectedObject);
287
- const savedObject = foldValueObject(imageSearchState.detectedObject);
288
- return detectedObjectEq.equals(thisObject, savedObject);
289
- }
290
- render() {
291
- return (h(Host, { class: {
292
- active: this.isActive(),
293
- }, onClick: () => this.selectDetectedObject(), style: {
294
- "--x-position": this.getObjectPosition()[0],
295
- "--y-position": this.getObjectPosition()[1],
296
- } }));
297
- }
298
- };
299
- VviinnDetectedObject.style = vviinnDetectedObjectCss;
300
-
301
- const vviinnEmptyResultsCss = ":host{display:grid}vviinn-error{justify-items:center}";
302
-
303
- let VviinnEmptyResults = class {
304
- constructor(hostRef) {
305
- registerInstance(this, hostRef);
306
- this.actionClick = createEvent(this, "actionClick", 7);
307
- }
308
- render() {
309
- return (h(Host, null, h("vviinn-error", null, h("svg", { slot: "icon", class: "icon", width: "32", height: "32", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { d: "M16 2a14 14 0 1 0 0 28 14 14 0 0 0 0-28Zm0 26a12 12 0 1 1 0-24 12 12 0 0 1 0 24Z", fill: "#525252" }), h("path", { d: "M17 8h-2v11h2V8Zm-1 14a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z", fill: "#525252" })), h("h4", { slot: "title" }, "Leider nichts gefunden"), h("span", { slot: "text" }, "Leider konnten wir keine passenden Produkte finden. Bitte versuche es mit einem anderen Bildausschnitt noch einmal."))));
310
- }
311
- };
312
- VviinnEmptyResults.style = vviinnEmptyResultsCss;
313
-
314
- 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}";
315
-
316
- let VviinnError = class {
317
- constructor(hostRef) {
318
- registerInstance(this, hostRef);
319
- }
320
- render() {
321
- return (h(Host, null, h("slot", { name: "icon" }), h("slot", { name: "title" }), h("slot", { name: "text" }), h("slot", { name: "action" })));
322
- }
323
- };
324
- VviinnError.style = vviinnErrorCss;
325
-
326
- 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}}";
327
-
328
- let VviinnExampleImage = class {
329
- constructor(hostRef) {
330
- registerInstance(this, hostRef);
331
- this.exampleImageSelected = createEvent(this, "exampleImageSelected", 7);
332
- this.exampleImageError = createEvent(this, "exampleImageError", 7);
333
- this.src = "";
334
- this.width = 0;
335
- this.height = 0;
336
- this.selected = false;
337
- }
338
- async selectImage(_event) {
339
- this.selected = true;
340
- const file = await toFile(this.src);
341
- const processResult = await processSelectedFile(file);
342
- _function.pipe(processResult, Either.match(() => this.exampleImageError.emit(), () => this.exampleImageSelected.emit()));
343
- this.selected = false;
344
- }
345
- showPreloader() {
346
- return ((imageSearchState.objectDetectionInProgress ||
347
- imageSearchState.loading) &&
348
- this.selected);
349
- }
350
- render() {
351
- return (h(Host, null, this.showPreloader() ? (h("div", { class: "image-preloader" }, h("vviinn-preloader", null))) : null, h("img", { onClick: (ev) => this.selectImage(ev), src: this.src, width: this.width, height: this.height })));
352
- }
353
- };
354
- VviinnExampleImage.style = vviinnExampleImageCss;
355
-
356
- const vviinnExampleImagesCss = "h3{font-size:22px;font-weight:600;line-height:32px;margin:0;margin-bottom:16px;text-align:center}.images{display:block;-moz-column-count:2;column-count:2;-moz-column-gap:16px;column-gap:16px}";
357
-
358
- let VviinnExampleImages = class {
359
- constructor(hostRef) {
360
- registerInstance(this, hostRef);
361
- this.imageSelected = createEvent(this, "imageSelected", 7);
362
- this.imageSelectedError = createEvent(this, "imageSelectedError", 7);
363
- }
364
- handleImageSelection() {
365
- this.imageSelected.emit();
366
- }
367
- handleImageSelectionError() {
368
- this.imageSelectedError.emit();
369
- }
370
- componentWillLoad() {
371
- slotChangeListener(this, this.el);
372
- }
373
- render() {
374
- return (h(Host, null, h("slot", { name: "vviinn-example-images-title" }, h("h3", null, "Mit den Beispielbildern die Suche direkt ausprobieren")), h("div", { class: "images" }, h("slot", { name: "vviinn-example-images-1" }, h("vviinn-example-image", { width: 480, height: 640, src: "https://cdn.vviinn.com/0/fit/480/0/ce/0/Z3M6Ly9haWFhcy1pbWdwcm94eS9leGFtcGxlcy9pbWctaW5zcGlyYXRpb24tMDEtTC5qcGc=" })), h("slot", { name: "vviinn-example-images-2" }, h("vviinn-example-image", { width: 280, height: 480, src: "https://cdn.vviinn.com/0/fit/480/0/ce/0/Z3M6Ly9haWFhcy1pbWdwcm94eS9leGFtcGxlcy9pbWctaW5zcGlyYXRpb24tMDItTS5qcGc=" })), h("slot", { name: "vviinn-example-images-3" }, h("vviinn-example-image", { width: 280, height: 480, src: "https://cdn.vviinn.com/0/fit/480/0/ce/0/Z3M6Ly9haWFhcy1pbWdwcm94eS9leGFtcGxlcy9pbWctaW5zcGlyYXRpb24tMDMtTS5qcGc=" })), h("slot", { name: "vviinn-example-images-4" }, h("vviinn-example-image", { width: 480, height: 640, src: "https://cdn.vviinn.com/0/fit/480/0/ce/0/Z3M6Ly9haWFhcy1pbWdwcm94eS9leGFtcGxlcy9pbWctaW5zcGlyYXRpb24tMDQtTC5qcGc=" })))));
375
- }
376
- get el() { return getElement(this); }
377
- };
378
- VviinnExampleImages.style = vviinnExampleImagesCss;
379
-
380
- const vviinnImageSelectorCss = ":host{display:block}:host(::hover){background:whitesmoke}.visually-hidden{clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}label{cursor:pointer;display:grid;padding:0.5rem;transition:background 0.1s ease-in-out}";
381
-
382
- let VviinnImageSelector = class {
383
- constructor(hostRef) {
384
- registerInstance(this, hostRef);
385
- this.imageSelected = createEvent(this, "imageSelected", 7);
386
- this.imageSelectedError = createEvent(this, "imageSelectedError", 7);
387
- }
388
- async handleInputChange(event) {
389
- const input = event.target;
390
- const processingResult = await processSelectedFile(input.files[0]);
391
- _function.pipe(processingResult, match(() => this.imageSelectedError.emit(), () => this.imageSelected.emit()));
392
- input.value = null;
393
- }
394
- isLoading() {
395
- return (imageSearchState.loading || imageSearchState.objectDetectionInProgress);
396
- }
397
- render() {
398
- return (h(Host, { exportparts: "button" }, this.isLoading() ? h("vviinn-preloader", null) : null, this.isLoading() ? null : (h("label", { htmlFor: "fileInput", part: "button" }, h("slot", { name: "upload-button-text" }, "Upload image"))), h("input", { id: "fileInput", class: "visually-hidden", type: "file", accept: "image/*", onChange: (event) => this.handleInputChange(event) })));
399
- }
400
- };
401
- VviinnImageSelector.style = vviinnImageSelectorCss;
402
-
403
- 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}";
404
-
405
- const getImageSizes = (i) => {
406
- const dimensions = dimensionsFromImage(i);
407
- const resize = scaleByLargestSide(288);
408
- const newDimensions = resize(dimensions);
409
- const sizes = newDimensions.map(d => d.size);
410
- return [sizes[0], sizes[1]];
411
- };
412
- let VviinnImageView = class {
413
- constructor(hostRef) {
414
- registerInstance(this, hostRef);
415
- }
416
- handleInitialImageLoad(ev) {
417
- const target = ev.target;
418
- const imageBounds = fromImage(target);
419
- const padding = 12;
420
- const { x, y } = move(imageBounds, { x: padding, y: padding });
421
- const searchArea = {
422
- x,
423
- y,
424
- width: imageBounds.width - padding * 2,
425
- height: imageBounds.height - padding * 2,
426
- };
427
- imageSearchState.imageBounds = Option.some(imageBounds);
428
- imageSearchState.searchArea = Option.some(searchArea);
429
- }
430
- renderDetectedObject(object) {
431
- return h("vviinn-detected-object", { detectedObject: object });
432
- }
433
- renderImage() {
434
- return _function.pipe(sequenceToOption(imageSearchState.imageUrl, imageSearchState.image), Option.map(([url, refImage]) => {
435
- const [width, height] = getImageSizes(refImage);
436
- const image = (h("img", { decoding: "async", width: width, height: height, src: url, onLoad: (el) => this.handleInitialImageLoad(el), draggable: false }));
437
- return image;
438
- }), Option.getOrElse(() => null));
439
- }
440
- renderCropper() {
441
- return _function.pipe(imageSearchState.imageUrl, Option.map(() => h("image-cropper", null)), Option.getOrElse(() => null));
442
- }
443
- render() {
444
- return (h(Host, null, imageSearchState.loading ||
445
- imageSearchState.objectDetectionInProgress ? (h("div", { class: "image-preloader" }, h("vviinn-preloader", null))) : null, h("highlight-box", null), this.renderImage(), this.renderCropper(), imageSearchState.detectedObjects.map((o) => this.renderDetectedObject(o))));
446
- }
447
- };
448
- VviinnImageView.style = vviinnImageViewCss;
449
-
450
- const vviinnModalCss = ":host{background:white;border-radius:4px;box-sizing:border-box;display:grid;grid-template-rows:-webkit-min-content auto;grid-template-rows:min-content auto;max-width:960px}@media (max-width: 415px){:host{-webkit-animation-name:fade-in;animation-name:fade-in;-webkit-animation-duration:0.5s;animation-duration:0.5s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}:host(.closed){-webkit-animation-name:fade-out;animation-name:fade-out;-webkit-animation-fill-mode:none;animation-fill-mode:none}.body{overflow-y:auto}}@media (max-width: 640px) and (min-width: 415px){:host{max-width:80%}}.head{align-items:center;border-bottom:1px solid #F4F4F4;display:grid;grid-gap:16px;grid-template-columns:-webkit-min-content auto -webkit-min-content;grid-template-columns:min-content auto min-content;justify-items:center;padding:16px}.title{font-weight:600;font-size:18px;line-height:24px}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:grid;padding:unset}@-webkit-keyframes fade-in{from{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes fade-in{from{transform:translateY(100%)}to{transform:translateY(0)}}@-webkit-keyframes fade-out{from{transform:translateY(0)}to{transform:translateY(100%)}}@keyframes fade-out{from{transform:translateY(0)}to{transform:translateY(100%)}}";
451
-
452
- let VviinnModal = class {
453
- constructor(hostRef) {
454
- registerInstance(this, hostRef);
455
- this.modalClosed = createEvent(this, "modalClosed", 7);
456
- this.secondaryActionClicked = createEvent(this, "secondaryActionClicked", 7);
457
- this.active = false;
458
- this.slider = false;
459
- }
460
- close() {
461
- this.active = false;
462
- setTimeout(() => {
463
- this.modalClosed.emit();
464
- }, this.slider ? 500 : 0);
465
- }
466
- handleAnimationEnd(ev) {
467
- if (ev.animationName !== "fade-in")
468
- return;
469
- this.slider = true;
470
- }
471
- render() {
472
- return (h(Host, { exportparts: "secondary-action, title, close-button", class: { closed: !this.active }, onAnimationEnd: (ev) => this.handleAnimationEnd(ev) }, h("div", { class: "head" }, h("button", { part: "secondary-action", onClick: () => this.secondaryActionClicked.emit() }, h("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { d: "M20.25 12H3.75", stroke: "#161616", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { d: "M10.5 5.25L3.75 12L10.5 18.75", stroke: "#161616", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("div", { class: "title", part: "title" }, "Bildsuche"), h("button", { onClick: () => this.close(), class: "close-button", part: "close-button" }, h("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { d: "M16 1.4L14.6 0L8 6.6L1.4 0L0 1.4L6.6 8L0 14.6L1.4 16L8 9.4L14.6 16L16 14.6L9.4 8L16 1.4Z", fill: "#333333" })))), h("div", { class: "body" }, h("slot", null))));
473
- }
474
- };
475
- VviinnModal.style = vviinnModalCss;
476
-
477
- const vviinnOnboardingCss = ":host{--color-primary-system:#0F62FE;--color-primary-hover-system:#014CDA;--color-icons-system:#2F8EDF;--spacer:8px}::host{display:block}h3{font-size:22px;font-weight:600;line-height:32px;margin:0;margin-bottom:16px;text-align:center}vviinn-slide{background:#f4f4f4;padding:24px}svg{padding:16px 0}.text{display:grid;grid-gap:8px}.text>h4{color:#161616;font-size:18px;font-weight:600;line-height:24px;margin:unset;text-align:center}.text>p{color:#525252;font-size:14px;font-style:normal;font-weight:normal;line-height:20px;margin:unset;text-align:center}.colored{fill:var(--color-icons, var(--color-icons-system))}";
478
-
479
- let VviinnOnboarding = class {
480
- constructor(hostRef) {
481
- registerInstance(this, hostRef);
482
- }
483
- componentWillLoad() {
484
- slotChangeListener(this, this.el);
485
- }
486
- render() {
487
- return (h(Host, null, h("slot", { name: "vviinn-onboarding-title" }, h("h3", null, "So funktioniert es")), h("vviinn-slider", { showArrows: true }, h("vviinn-slide", null, h("vviinn-onboarding-card-1", null)), h("vviinn-slide", null, h("vviinn-onboarding-card-2", null)), h("vviinn-slide", null, h("vviinn-onboarding-card-3", null)))));
488
- }
489
- get el() { return getElement(this); }
490
- };
491
- VviinnOnboarding.style = vviinnOnboardingCss;
492
-
493
- const onboardingCardCss$2 = ":host{align-items:center;background:#f4f4f4;display:grid;grid-template-rows:repeat(2, 1fr);justify-items:center;padding:24px;width:100%}h4{color:#161616;font-size:18px;font-weight:600;line-height:24px;margin:unset;text-align:center}svg{padding:16px 0}p{color:#525252;font-size:14px;font-style:normal;font-weight:normal;line-height:20px;margin:unset;text-align:center}.colored{fill:var(--color-icons, var(--color-icons-system))}.text{display:grid;grid-gap:8px}";
494
-
495
- let VviinnOnboardingCard1 = class {
496
- constructor(hostRef) {
497
- registerInstance(this, hostRef);
498
- }
499
- componentWillLoad() {
500
- slotChangeListener(this, this.el);
501
- }
502
- render() {
503
- return (h(Host, null, h("slot", { name: "onboarding-card-1-icon" }, h(OnboardingCard1Icon, null)), h("slot", { name: "onboarding-card-1-text" }, h("div", { class: "text" }, h("h4", null, "Starte die Bildsuche"), h("p", null, "Lade ein Bild aus Deiner Galerie hoch oder fotografiere ein Produkt mit Deiner Kamera.")))));
504
- }
505
- get el() { return getElement(this); }
506
- };
507
- VviinnOnboardingCard1.style = onboardingCardCss$2;
508
-
509
- const onboardingCardCss$1 = ":host{align-items:center;background:#f4f4f4;display:grid;grid-template-rows:repeat(2, 1fr);justify-items:center;padding:24px;width:100%}h4{color:#161616;font-size:18px;font-weight:600;line-height:24px;margin:unset;text-align:center}svg{padding:16px 0}p{color:#525252;font-size:14px;font-style:normal;font-weight:normal;line-height:20px;margin:unset;text-align:center}.colored{fill:var(--color-icons, var(--color-icons-system))}.text{display:grid;grid-gap:8px}";
510
-
511
- let VviinnOnboardingCard2 = class {
512
- constructor(hostRef) {
513
- registerInstance(this, hostRef);
514
- }
515
- componentWillLoad() {
516
- slotChangeListener(this, this.el);
517
- }
518
- render() {
519
- return (h(Host, null, h("slot", { name: "onboarding-card-2-icon" }, h(OnboardingCard2Icon, null)), h("slot", { name: "onboarding-card-2-text" }, h("div", { class: "text" }, h("h4", null, "Verfeiner deine Suche"), h("p", null, "Du kannst den Bildrahmen selber festlegen und so die Produkte genau ausw\u00E4hlen.")))));
520
- }
521
- get el() { return getElement(this); }
522
- };
523
- VviinnOnboardingCard2.style = onboardingCardCss$1;
524
-
525
- const onboardingCardCss = ":host{align-items:center;background:#f4f4f4;display:grid;grid-template-rows:repeat(2, 1fr);justify-items:center;padding:24px;width:100%}h4{color:#161616;font-size:18px;font-weight:600;line-height:24px;margin:unset;text-align:center}svg{padding:16px 0}p{color:#525252;font-size:14px;font-style:normal;font-weight:normal;line-height:20px;margin:unset;text-align:center}.colored{fill:var(--color-icons, var(--color-icons-system))}.text{display:grid;grid-gap:8px}";
526
-
527
- let VviinnOnboardingCard3 = class {
528
- constructor(hostRef) {
529
- registerInstance(this, hostRef);
530
- }
531
- componentWillLoad() {
532
- slotChangeListener(this, this.el);
533
- }
534
- render() {
535
- return (h(Host, null, h("slot", { name: "onboarding-card-3-icon" }, h(OnboardingCard3Icon, null)), h("slot", { name: "onboarding-card-3-text" }, h("div", { class: "text" }, h("h4", null, "Ohne Hintergrund"), h("p", null, "Die besten Ergebnisse erh\u00E4ltst Du, wenn das gesuchte Objekt mit einfarbigem und hellem Hintergrund zu sehen ist.")))));
536
- }
537
- get el() { return getElement(this); }
538
- };
539
- VviinnOnboardingCard3.style = onboardingCardCss;
540
-
541
- const vviinnOverlayCss = ":host{-webkit-animation:fade-in 0.5s ease-in-out;animation:fade-in 0.5s ease-in-out;background:rgba(0, 0, 0, 0.5);display:block;height:100vh;left:0;overflow:hidden;position:fixed;top:0;width:100vw;z-index:9999}@-webkit-keyframes fade-in{from{opacity:0.1}to{opacity:1}}@keyframes fade-in{from{opacity:0.1}to{opacity:1}}";
542
-
543
- let VviinnOverlay = class {
544
- constructor(hostRef) {
545
- registerInstance(this, hostRef);
546
- }
547
- render() {
548
- return (h(Host, null, h("slot", null)));
549
- }
550
- };
551
- VviinnOverlay.style = vviinnOverlayCss;
552
-
553
- const vviinnOverlayedModalCss = ":host{display:none}:host(.active){display:block}vviinn-overlay{align-items:center;display:grid;justify-items:center}@media (max-width: 415px){vviinn-modal{border-radius:4px 4px 0 0;height:100vh;margin-top:32px;transform:translateY(100%);width:100vw}vviinn-overlay{align-items:end;display:grid;justify-items:center}}";
554
-
555
- let VviinnOverlayedModal = class {
556
- constructor(hostRef) {
557
- registerInstance(this, hostRef);
558
- this.secondaryActionClicked = createEvent(this, "secondaryActionClicked", 7);
559
- this.modalClosed = createEvent(this, "modalClosed", 7);
560
- this.active = false;
561
- }
562
- render() {
563
- return (h(Host, { class: { active: this.active } }, h("vviinn-overlay", null, h("vviinn-modal", { onSecondaryActionClicked: () => this.secondaryActionClicked.emit(), active: this.active }, h("slot", null, "CONTENT")))));
564
- }
565
- };
566
- VviinnOverlayedModal.style = vviinnOverlayedModalCss;
567
-
568
- 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)}}";
569
-
570
- let VviinnPreloader = class {
571
- constructor(hostRef) {
572
- registerInstance(this, hostRef);
573
- }
574
- isActive() {
575
- return (imageSearchState.loading || imageSearchState.objectDetectionInProgress);
576
- }
577
- render() {
578
- return (h(Host, { class: {
579
- active: this.isActive(),
580
- } }));
581
- }
582
- };
583
- VviinnPreloader.style = vviinnPreloaderCss;
584
-
585
- 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}";
586
-
587
- let VviinnPrivacyBadge = class {
588
- constructor(hostRef) {
589
- registerInstance(this, hostRef);
590
- }
591
- componentWillLoad() {
592
- slotChangeListener(this, this.el);
593
- }
594
- render() {
595
- return (h(Host, null, h("slot", null, h("div", { class: "content" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none" }, h("defs", null), h("path", { fill: "#525252", d: "M8.5 11V7h-2v1h1v3H6v1h4v-1H8.5zM8 4a.75.75 0 100 1.5A.75.75 0 008 4z" }), h("path", { fill: "#525252", d: "M8 15A7 7 0 118 1a7 7 0 010 14zM8 2a6 6 0 100 12A6 6 0 008 2z" })), h("slot", { name: "vviinn-privacy-badge-text" }, h("p", null, "Wir gehen sorgf\u00E4ltig mit Deinen Daten um. Deine Bilder werden nur zum Zweck der Bildsuche gespeichert."))))));
596
- }
597
- get el() { return getElement(this); }
598
- };
599
- VviinnPrivacyBadge.style = vviinnPrivacyBadgeCss;
600
-
601
- class GtagAnalytics {
602
- sendImpression(product) {
603
- var _a, _b, _c;
604
- gtag('event', 'view_item_list', {
605
- items: [
606
- {
607
- id: product.productId,
608
- name: product.title,
609
- brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
610
- category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
611
- list_name: 'VI VPR View',
612
- price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
613
- }
614
- ]
615
- });
616
- return undefined;
617
- }
618
- sendClick(product) {
619
- var _a, _b, _c;
620
- gtag('event', 'select_content', {
621
- content_type: 'product',
622
- items: [
623
- {
624
- id: product.productId,
625
- name: product.title,
626
- brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
627
- category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
628
- list_name: 'VI VPR View',
629
- price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
630
- }
631
- ]
632
- });
633
- return undefined;
634
- }
635
- }
636
-
637
- class GAnalytics {
638
- constructor() {
639
- ga('require', 'ec');
640
- }
641
- convertProduct(product) {
642
- var _a, _b, _c;
643
- return {
644
- id: product.productId,
645
- name: product.title,
646
- brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
647
- category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
648
- list: 'VI VPR View',
649
- price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
650
- };
651
- }
652
- sendImpression(product) {
653
- ga('ec:addImpression', this.convertProduct(product));
654
- return undefined;
655
- }
656
- sendClick(product) {
657
- var _a, _b, _c;
658
- ga('ec:addProduct', {
659
- id: product.productId,
660
- name: product.title,
661
- brand: (_a = product.brand) !== null && _a !== void 0 ? _a : '',
662
- category: (_b = product.productType) !== null && _b !== void 0 ? _b : '',
663
- price: Math.min(...[product.price.actual, (_c = product.price.sale) !== null && _c !== void 0 ? _c : Infinity])
664
- });
665
- ga('ec:setAction', 'click', { list: 'VI VPR View' });
666
- return undefined;
667
- }
668
- }
669
-
670
- const getGtagAnalytics = () => _function.pipe(Option.fromNullable(window.gtag), Option.map(() => new GtagAnalytics()));
671
- const getCommonAnalytics = () => _function.pipe(Option.fromNullable(window.ga), Option.map(() => new GAnalytics()));
672
- const analyticsMonoid = Option.getMonoid(Semigroup.first());
673
- const getAnalyticsModule = analyticsMonoid.concat(getGtagAnalytics(), getCommonAnalytics());
674
-
675
- const FIT_EXPR = /fit\/\d+\//;
676
- const containsFit = (url) => {
677
- return _function.pipe(url.match(FIT_EXPR), Either.fromNullable(url), Either.map(() => url));
678
- };
679
- const processWidth = (url, size) => {
680
- return _function.pipe(containsFit(url), Either.map((url) => url.replace(FIT_EXPR, `fit/${size}/`)), Either.getOrElse(() => url));
681
- };
682
- const Linked = (props, child) => props.deeplink ? (h("a", { class: props.part, part: props.part, href: props.deeplink }, child)) : (child);
683
- const FormattedPrice = (props) => {
684
- var _a;
685
- const locale = props.locale;
686
- const formattedPrice = new Intl.NumberFormat(locale, {
687
- minimumFractionDigits: 2,
688
- }).format(props.price);
689
- const fullPrice = `${(_a = props.prefix) !== null && _a !== void 0 ? _a : ""} ${formattedPrice} ${props.currency}`;
690
- return (h("span", { class: "price-amount", part: "price-amount" }, fullPrice));
691
- };
692
- const Price = (props) => {
693
- const priceEl = (h(FormattedPrice, { prefix: props.prefix, currency: props.currency, price: props.price, locale: props.locale }));
694
- return (h("span", { class: "price-container", part: "price-container" }, props.salePrice ? ([
695
- h("span", { class: "price-sale", part: "price-sale" },
696
- h(FormattedPrice, { prefix: props.prefix, currency: props.currency, price: props.salePrice, locale: props.locale })),
697
- h("span", { class: "price-outdated", part: "price-outdated" }, priceEl),
698
- ]) : (h("span", { class: "price-regular", part: "price-regular" }, priceEl))));
699
- };
700
- const Image = (props, onLoadEnd = () => undefined) => (h("picture", null,
701
- 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 })));
702
- const ResponsiveImage = (props, onLoadEnd = () => undefined) => (h("picture", null,
703
- h("img", { loading: props.lazy ? "lazy" : "eager", part: "image", class: "image responsive", src: processWidth(props.src, props.width), alt: props.title, onLoad: onLoadEnd })));
704
-
705
- 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}";
706
-
707
- let VviinnProductCard = class {
708
- constructor(hostRef) {
709
- registerInstance(this, hostRef);
710
- this.recommendationLoad = createEvent(this, "recommendationLoad", 7);
711
- this.recommendationView = createEvent(this, "recommendationView", 7);
712
- this.recommendationClick = createEvent(this, "recommendationClick", 7);
713
- this.productImageLoaded = createEvent(this, "productImageLoaded", 7);
714
- this.currency = undefined;
715
- this.imageRatio = 1;
716
- this.imageWidth = 200;
717
- this.locale = undefined;
718
- this.pricePrefix = undefined;
719
- this.responsive = false;
720
- this.dimmedBackground = false;
721
- /** @internal */
722
- this.index = 0;
723
- this.imageLoaded = false;
724
- this.productData = null;
725
- this.intersectionObserver = new IntersectionObserver(this.intersectionCallback.bind(this), { threshold: 1.0 });
726
- }
727
- connectedCallback() {
728
- this.productData = {
729
- product: this.productId,
730
- rank: this.index,
731
- };
732
- }
733
- intersectionCallback(data) {
734
- if (data.some((entry) => entry.isIntersecting)) {
735
- _function.pipe(getAnalyticsModule, Option.map((analytics) => analytics.sendImpression(this.getProduct())));
736
- this.recommendationView.emit(this.productData);
737
- this.intersectionObserver.disconnect();
738
- }
739
- }
740
- componentDidLoad() {
741
- this.recommendationLoad.emit(this.productData);
742
- this.intersectionObserver.observe(this.el);
743
- const links = this.el.shadowRoot.querySelectorAll("a");
744
- links.forEach((link) => link.addEventListener("click", (event) => {
745
- event.preventDefault();
746
- event.stopImmediatePropagation();
747
- this.recommendationClick.emit(this.productData);
748
- _function.pipe(getAnalyticsModule, Option.match(() => null, (analytics) => analytics.sendClick(this.getProduct())));
749
- }));
750
- }
751
- getProduct() {
752
- return imageSearchState.results.find((r) => r.productId === this.productId);
753
- }
754
- renderImage() {
755
- const props = {
756
- width: this.imageWidth,
757
- height: this.imageWidth * this.imageRatio,
758
- src: this.image,
759
- title: this.productTitle,
760
- lazy: false,
761
- };
762
- return this.responsive
763
- ? ResponsiveImage(props, () => this.kek())
764
- : Image(props, () => this.kek());
765
- }
766
- kek() {
767
- this.productImageLoaded.emit(this.productId);
768
- }
769
- render() {
770
- var _a, _b, _c;
771
- return (h(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" }, h(Linked, { deeplink: this.deeplink, part: "image-link" }, this.renderImage()), h(Linked, { deeplink: this.deeplink, part: "deeplink" }, h("span", { class: "title", part: "title" }, this.productTitle)), h("span", { class: "brand", part: "brand" }, this.brand), h("span", { class: "type", part: "type" }, this.productType), h(Price, { prefix: (_a = this.pricePrefix) !== null && _a !== void 0 ? _a : state.pricePrefix, currency: (_b = this.currency) !== null && _b !== void 0 ? _b : state.currencySign, price: this.price, salePrice: this.salePrice, locale: (_c = this.locale) !== null && _c !== void 0 ? _c : state.locale })));
772
- }
773
- get el() { return getElement(this); }
774
- };
775
- VviinnProductCard.style = vviinnProductCardCss;
776
-
777
- const vviinnServerErrorCss = ":host{display:block}";
778
-
779
- let VviinnServerError = class {
780
- constructor(hostRef) {
781
- registerInstance(this, hostRef);
782
- this.actionClick = createEvent(this, "actionClick", 7);
783
- }
784
- render() {
785
- return (h(Host, null, h("vviinn-error", null, h("h4", { slot: "title" }, "Keine Verbindung"), h("span", { slot: "text" }, "Etwas hat leider nicht funktioniert. Bitte pr\u00FCfen Sie Ihre Internetverbindung und laden Sie das Bild noch einmal hoch."), h("button", { slot: "action", onClick: () => this.actionClick.emit() }, "Erneut versuchen"))));
786
- }
787
- };
788
- VviinnServerError.style = vviinnServerErrorCss;
789
-
790
- const vviinnSlideCss = ":host{display:grid;justify-items:center}";
791
-
792
- let VviinnSlide = class {
793
- constructor(hostRef) {
794
- registerInstance(this, hostRef);
795
- }
796
- render() {
797
- return (h(Host, null, h("slot", null)));
798
- }
799
- };
800
- VviinnSlide.style = vviinnSlideCss;
801
-
802
- const getStyleMap = (data) => {
803
- return {
804
- "arrow-wrapper": true,
805
- [data.kind]: true,
806
- disabled: data.disabled,
807
- };
808
- };
809
- const Arrow = ({ kind, tabindex, disabled, onClick, onKeyDown, }) => (h("div", { class: getStyleMap({ kind, disabled }), onClick: onClick, tabindex: tabindex, onKeyDown: onKeyDown },
810
- h(ArrowIcon, null)));
811
-
812
- 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}";
813
-
814
- let VviinnSlider = class {
815
- constructor(hostRef) {
816
- registerInstance(this, hostRef);
817
- this.elementsCount = 0;
818
- this.internalPosition = 0;
819
- this.swipeStartPosition = Option.none;
820
- this.showBullets = true;
821
- this.position = 0;
822
- this.showArrows = false;
823
- }
824
- positionWatchHandler(newValue) {
825
- this.internalPosition = newValue;
826
- this.el.style.setProperty("--position", `${newValue}`);
827
- this.setActiveCssClassToSlide(newValue);
828
- }
829
- connectedCallback() {
830
- this.handleDomContentChanges();
831
- }
832
- handleDomContentChanges() {
833
- const items = this.el.querySelectorAll("vviinn-slide");
834
- this.elementsCount = items.length;
835
- this.el.style.setProperty("--num-items", `${this.elementsCount}`);
836
- this.setActiveCssClassToSlide(0);
837
- }
838
- setActiveCssClassToSlide(index) {
839
- const items = this.el.querySelectorAll("vviinn-slide");
840
- items.forEach((i) => i.classList.remove("active"));
841
- items[index].classList.add("active");
842
- }
843
- goToSlide(index) {
844
- this.internalPosition = index;
845
- this.el.style.setProperty("--position", `${index}`);
846
- this.setActiveCssClassToSlide(index);
847
- }
848
- renderBullets() {
849
- return this.showBullets ? (h("div", { class: "controls" }, NonEmptyArray.range(0, this.elementsCount - 1).map((i) => (h("div", { class: {
850
- bullet: true,
851
- active: i == this.internalPosition % this.elementsCount,
852
- }, onClick: () => this.goToSlide(i) }))))) : null;
853
- }
854
- nextSlide() {
855
- this.internalPosition++;
856
- this.renderSlidePosition();
857
- }
858
- prevSlide() {
859
- const nextPostion = this.internalPosition - 1;
860
- this.internalPosition =
861
- nextPostion > -1 ? nextPostion : this.elementsCount - 1;
862
- this.renderSlidePosition();
863
- }
864
- renderSlidePosition() {
865
- requestAnimationFrame(() => {
866
- this.el.style.setProperty("--position", `${this.internalPosition % this.elementsCount}`);
867
- });
868
- }
869
- handleKeyDown(event) {
870
- if (event.key !== "Space" && event.key !== "Enter")
871
- return;
872
- const target = event.target;
873
- const direction = target.className.includes("prev") ? "prev" : "next";
874
- switch (direction) {
875
- case "prev":
876
- this.prevSlide();
877
- break;
878
- case "next":
879
- this.nextSlide();
880
- break;
881
- }
882
- }
883
- handleTouchStart(event) {
884
- if (!this.showBullets)
885
- return;
886
- this.swipeStartPosition = _function.pipe(event.touches[0], Option.fromNullable, Option.map((t) => t.clientX));
887
- }
888
- handleTouchEnd(event) {
889
- if (!this.showBullets)
890
- return;
891
- const swipeEndPosition = _function.pipe(event.changedTouches[0], Option.fromNullable, Option.map((t) => t.clientX));
892
- _function.pipe(sequenceToOption(this.swipeStartPosition, swipeEndPosition), Option.map(([start, end]) => Ord.compare(start, end)), Option.map((swipeDirection) => {
893
- switch (swipeDirection) {
894
- case 1:
895
- return this.nextSlide();
896
- case -1:
897
- return this.prevSlide();
898
- }
899
- }));
900
- }
901
- render() {
902
- return (h(Host, null, h("div", { class: "items-wrapper" }, h("div", { class: "items", onTouchStart: (e) => this.handleTouchStart(e), onTouchEnd: (e) => this.handleTouchEnd(e) }, h("slot", null))), this.showArrows
903
- ? [
904
- h(Arrow, { kind: "prev", onClick: () => this.prevSlide(), onKeyDown: (ev) => this.handleKeyDown(ev), tabindex: 1, disabled: false }),
905
- h(Arrow, { kind: "next", onClick: () => this.nextSlide(), onKeyDown: (ev) => this.handleKeyDown(ev), tabindex: 0, disabled: false }),
906
- ]
907
- : null, this.renderBullets()));
908
- }
909
- get el() { return getElement(this); }
910
- static get watchers() { return {
911
- "position": ["positionWatchHandler"]
912
- }; }
913
- };
914
- VviinnSlider.style = vviinnSliderCss;
915
-
916
- const vviinnTeaserCss = ":host{align-items:center;display:grid;justify-items:center;grid-gap:16px}.vviinn-teaser-text{font-size:28px;font-weight:600;line-height:40px;size:28px;text-align:center}";
917
-
918
- let VviinnTeaser = class {
919
- constructor(hostRef) {
920
- registerInstance(this, hostRef);
921
- }
922
- componentWillLoad() {
923
- slotChangeListener(this, this.el);
924
- }
925
- render() {
926
- return (h(Host, null, h("slot", null, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "64", height: "64", fill: "none" }, h("defs", null), h("path", { fill: "#C6C6C6", d: "M48 28a11.98 11.98 0 00-9.77 18.942L28 57.172 30.828 60l10.23-10.23A11.994 11.994 0 1048 28zm0 20a8 8 0 118-8 8.009 8.009 0 01-8 8zM34 24a6 6 0 10-6-6 6.006 6.006 0 006 6zm0-8a2 2 0 110 4 2 2 0 010-4z" }), h("path", { fill: "#C6C6C6", d: "M24 48H8V35.993L18 26l11.172 11.172L32 34.336 20.828 23.165a4 4 0 00-5.656 0L8 30.336V8h40v12h4V8a4.004 4.004 0 00-4-4H8a4.004 4.004 0 00-4 4v40a4.005 4.005 0 004 4h16v-4z" })), h("span", { class: "vviinn-teaser-text" }, h("slot", { name: "vviinn-teaser-text" }, "Finde Produkte auf ", h("br", null), " einem Foto")))));
927
- }
928
- get el() { return getElement(this); }
929
- };
930
- VviinnTeaser.style = vviinnTeaserCss;
931
-
932
- 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}";
933
-
934
- const filterInt = (value) => /^[-+]?(\d+|Infinity)$/.test(value) ? Number(value) : NaN;
935
- const notEmptyString = (s) => !isEmpty(s);
936
- const notNan = (n) => !isNaN(n);
937
- let VviinnVpsWidget = class {
938
- constructor(hostRef) {
939
- registerInstance(this, hostRef);
940
- /** @internal */
941
- this.apiPath = "https://api.vviinn.com";
942
- /** When true modal window with widget will be shown */
943
- this.active = false;
944
- /** Currency sign will shown after price */
945
- this.currencySign = "€";
946
- /** Locale for currency formatting */
947
- this.locale = "de-DE";
948
- this.slidePosition = 0;
949
- this.width = 0;
950
- this.wrongImageFormat = false;
951
- this.imageSource = null;
952
- }
953
- activeWatcher(value) {
954
- if (value) {
955
- this.overflow = document.body.style.overflow;
956
- document.body.style.overflow = "hidden";
957
- this.trackOpenEvent();
958
- }
959
- else {
960
- document.body.style.overflow = this.overflow;
961
- }
962
- }
963
- trackRecommendationView({ detail }) {
964
- const recommendationViewEvent = createProductViewVpsEvent(Object.assign({ session_id: this.uiSessionId }, detail));
965
- this.trackingApi.trackEvent(recommendationViewEvent);
966
- }
967
- trackRecommendationClick({ detail }) {
968
- const recommendationClickEvent = createProductClickVpsEvent(Object.assign({ session_id: this.uiSessionId }, detail));
969
- this.trackingApi.trackEvent(recommendationClickEvent).finally(() => {
970
- const product = imageSearchState.results.find((r) => r.productId === detail.product);
971
- if (!product || !product.deeplink)
972
- return;
973
- window.location.href = product.deeplink;
974
- });
975
- }
976
- trachSearchAreaChanges() {
977
- const searchEvent = createSearchEvent({
978
- session_id: this.uiSessionId,
979
- source: this.imageSource,
980
- search_area: "manual-selection",
981
- });
982
- this.trackingApi.trackEvent(searchEvent);
983
- }
984
- trackDetectedObject() {
985
- const searchEvent = createSearchEvent({
986
- session_id: this.uiSessionId,
987
- source: this.imageSource,
988
- search_area: "attention-point",
989
- });
990
- this.trackingApi.trackEvent(searchEvent);
991
- }
992
- trackFilter({ detail }) {
993
- const searchEvent = createFilterEvent({
994
- session_id: this.uiSessionId,
995
- source: this.imageSource,
996
- kind: "category",
997
- action: detail,
998
- });
999
- this.trackingApi.trackEvent(searchEvent);
1000
- }
1001
- componentWillLoad() {
1002
- slotChangeListener(this, this.el);
1003
- }
1004
- connectedCallback() {
1005
- state.apiPath = this.apiPath;
1006
- state.currencySign = this.currencySign;
1007
- state.locale = this.locale;
1008
- imageSearchState.token = this.token;
1009
- imageSearchState.campaignId = _function.pipe(this.campaignId, Option.fromNullable, Option.chain(Option.fromPredicate(notEmptyString)), Option.map(filterInt), Option.chain(Option.fromPredicate(notNan)), Option.map((s) => `${s}`));
1010
- this.uiSessionId = v4();
1011
- this.trackingApi = createTrackingApi(this.apiPath, this.token);
1012
- }
1013
- trackOpenEvent() {
1014
- const widgetOpenEvent = createWidgetVpsEvent({
1015
- action: "open",
1016
- session_id: this.uiSessionId,
1017
- });
1018
- this.trackingApi.trackEvent(widgetOpenEvent);
1019
- }
1020
- handleImageSelection(source) {
1021
- this.imageSource = source;
1022
- this.slidePosition = 1;
1023
- const root = this.el.shadowRoot.querySelector("vviinn-overlayed-modal");
1024
- const overlay = root.shadowRoot.querySelector("vviinn-overlay");
1025
- const modal = overlay.querySelector("vviinn-modal");
1026
- const modalBody = modal.shadowRoot.querySelector(".body");
1027
- modalBody.scrollTop = 0;
1028
- this.trackInitialSearch();
1029
- }
1030
- trackInitialSearch() {
1031
- const searchEvent = createSearchEvent({
1032
- session_id: this.uiSessionId,
1033
- source: this.imageSource,
1034
- search_area: "full",
1035
- });
1036
- this.trackingApi.trackEvent(searchEvent);
1037
- }
1038
- resetState() {
1039
- this.resetScroll("onboarding-block");
1040
- this.slidePosition = 0;
1041
- imageSearchState.image = Option.none;
1042
- imageSearchState.imageUrl = Option.none;
1043
- imageSearchState.imageBounds = Option.none;
1044
- imageSearchState.searchArea = Option.none;
1045
- imageSearchState.results = [];
1046
- imageSearchState.filters = [];
1047
- imageSearchState.detectedObjects = [];
1048
- imageSearchState.activeIonLink = undefined;
1049
- imageSearchState.rectangleSearchForm = undefined;
1050
- this.resetScroll("results-block");
1051
- }
1052
- haveErrors() {
1053
- return this.wrongImageFormat || imageSearchState.serverError;
1054
- }
1055
- resetScroll(elementId, behavior = "auto") {
1056
- const element = this.el.shadowRoot.getElementById(elementId);
1057
- element.scroll({ top: 0, left: 0, behavior });
1058
- }
1059
- handleModalClose() {
1060
- this.active = false;
1061
- this.resetState();
1062
- const elementsToReset = ["onboarding-block", "results-block"];
1063
- elementsToReset.forEach((name) => this.resetScroll(name));
1064
- const widgetOpenEvent = createWidgetVpsEvent({
1065
- action: "close",
1066
- session_id: this.uiSessionId,
1067
- });
1068
- this.trackingApi.trackEvent(widgetOpenEvent);
1069
- }
1070
- render() {
1071
- return (h(Host, null, 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" }, h("vviinn-slider", { showBullets: false, position: this.slidePosition }, h("vviinn-slide", { class: { "start-page": true } }, h("div", { class: {
1072
- error: this.haveErrors(),
1073
- "start-page_block": true,
1074
- } }, h("vviinn-wrong-format", { class: { hidden: !this.wrongImageFormat }, onActionClick: () => (this.wrongImageFormat = false) }), h("vviinn-server-error", { class: { hidden: !imageSearchState.serverError }, onActionClick: () => (imageSearchState.serverError = false) }), h("vviinn-teaser", { class: { hidden: this.haveErrors() } }), h("vviinn-image-selector", { class: { hidden: this.haveErrors() }, onImageSelected: () => this.handleImageSelection("upload"), onImageSelectedError: () => (this.wrongImageFormat = true), part: "select-image_button" }, h("span", { slot: "upload-button-text", class: "upload-button-content" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "29", height: "28", fill: "none" }, h("defs", null), 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" }), 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" })), h("slot", { name: "vviinn-image-upload-button-text" }, h("span", null, "Kamera oder Bild ausw\u00E4hlen")))), h("vviinn-privacy-badge", { class: { hidden: this.haveErrors() } })), h("div", { id: "onboarding-block", class: "start-page_block" }, h("div", { class: "onboarding-wrapper" }, h("vviinn-onboarding", null), h("vviinn-example-images", { part: "example-images", onImageSelected: () => this.handleImageSelection("example"), onImageSelectedError: () => this.resetScroll("onboarding-block", "smooth") })))), h("vviinn-slide", { class: { "results-page": true, active: this.slidePosition == 1 } }, h("div", { class: "image-wrapper" }, h("vviinn-image-view", null), h("div", { class: "filters-wrapper" }, h("div", { class: "filters" }, imageSearchState.filters.map((filter) => (h("search-filters", { filter: filter })))))), h("div", { id: "results-block", class: "products-wrapper" }, h("div", { class: {
1075
- "nothing-found": true,
1076
- hidden: imageSearchState.results.length > 0,
1077
- } }, h("vviinn-empty-results", null), h("vviinn-onboarding", null)), h("div", { class: {
1078
- hidden: imageSearchState.results.length <= 0,
1079
- products: true,
1080
- } }, imageSearchState.results.map((p, i) => {
1081
- var _a;
1082
- return (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 }));
1083
- }))))))));
1084
- }
1085
- get el() { return getElement(this); }
1086
- static get watchers() { return {
1087
- "active": ["activeWatcher"]
1088
- }; }
1089
- };
1090
- VviinnVpsWidget.style = vviinnVpsWidgetCss;
1091
-
1092
- const vviinnWrongFormatCss = ":host{display:block}";
1093
-
1094
- let VviinnWrongFormat = class {
1095
- constructor(hostRef) {
1096
- registerInstance(this, hostRef);
1097
- this.actionClick = createEvent(this, "actionClick", 7);
1098
- }
1099
- render() {
1100
- return (h(Host, null, h("vviinn-error", null, h("h4", { slot: "title" }, "Dateityp wird nicht unterst\u00FCtzt"), h("span", { slot: "text" }, "Leider unterst\u00FCtzen wir dieses Format nicht. Bitte laden Sie eine .jpg, .png oder .webp Bilddatei hoch."), h("button", { slot: "action", onClick: () => this.actionClick.emit() }, "Neues Bild hochladen"))));
1101
- }
1102
- };
1103
- VviinnWrongFormat.style = vviinnWrongFormatCss;
1104
-
1105
- export { CropperHandler as cropper_handler, HighlightBox as highlight_box, ImageCropper as image_cropper, SearchFilters as search_filters, VviinnDetectedObject as vviinn_detected_object, VviinnEmptyResults as vviinn_empty_results, VviinnError as vviinn_error, VviinnExampleImage as vviinn_example_image, VviinnExampleImages as vviinn_example_images, VviinnImageSelector as vviinn_image_selector, VviinnImageView as vviinn_image_view, VviinnModal as vviinn_modal, VviinnOnboarding as vviinn_onboarding, VviinnOnboardingCard1 as vviinn_onboarding_card_1, VviinnOnboardingCard2 as vviinn_onboarding_card_2, VviinnOnboardingCard3 as vviinn_onboarding_card_3, VviinnOverlay as vviinn_overlay, VviinnOverlayedModal as vviinn_overlayed_modal, VviinnPreloader as vviinn_preloader, VviinnPrivacyBadge as vviinn_privacy_badge, VviinnProductCard as vviinn_product_card, VviinnServerError as vviinn_server_error, VviinnSlide as vviinn_slide, VviinnSlider as vviinn_slider, VviinnTeaser as vviinn_teaser, VviinnVpsWidget as vviinn_vps_widget, VviinnWrongFormat as vviinn_wrong_format };