@empathyco/x-components 3.0.0-alpha.230 → 3.0.0-alpha.232

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 (22) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/docs/API-reference/api/x-components.baseresultimage.hoveranimation.md +13 -0
  3. package/docs/API-reference/api/{x-components.baseresultimage.animation.md → x-components.baseresultimage.loadanimation.md} +3 -3
  4. package/docs/API-reference/api/x-components.baseresultimage.md +3 -1
  5. package/docs/API-reference/api/x-components.baseresultimage.shownextimageonhover.md +13 -0
  6. package/docs/API-reference/api/x-components.infinitescroll.md +2 -2
  7. package/docs/API-reference/api/x-components.md +1 -1
  8. package/docs/API-reference/components/common/result/x-components.base-result-image.md +58 -4
  9. package/docs/API-reference/components/common/x-components.highlight.md +100 -0
  10. package/js/components/result/base-result-image.vue.js +24 -9
  11. package/js/components/result/base-result-image.vue.js.map +1 -1
  12. package/js/components/result/base-result-image.vue_rollup-plugin-vue_script.vue.js +56 -12
  13. package/js/components/result/base-result-image.vue_rollup-plugin-vue_script.vue.js.map +1 -1
  14. package/js/components/result/base-result-image.vue_rollup-plugin-vue_styles.0.vue.js +1 -1
  15. package/js/directives/infinite-scroll/infinite-scroll.js +11 -10
  16. package/js/directives/infinite-scroll/infinite-scroll.js.map +1 -1
  17. package/package.json +3 -3
  18. package/report/x-components.api.json +67 -4
  19. package/report/x-components.api.md +14 -4
  20. package/types/components/result/base-result-image.vue.d.ts +49 -6
  21. package/types/components/result/base-result-image.vue.d.ts.map +1 -1
  22. package/types/directives/infinite-scroll/infinite-scroll.d.ts +4 -4
package/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to this project will be documented in this file. See
4
4
  [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.0.0-alpha.232](https://github.com/empathyco/x/compare/@empathyco/x-components@3.0.0-alpha.231...@empathyco/x-components@3.0.0-alpha.232) (2022-11-28)
7
+
8
+ ### Features
9
+
10
+ - add `Highlight` component (#872)
11
+ ([1b5aa57](https://github.com/empathyco/x/commit/1b5aa5793b7916ec0433b4110b7ef355f882f4f6)),
12
+ closes [EX-7468](https://searchbroker.atlassian.net/browse/EX-7468)
13
+
14
+ # Change Log
15
+
16
+ All notable changes to this project will be documented in this file. See
17
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
18
+
19
+ ## [3.0.0-alpha.231](https://github.com/empathyco/x/compare/@empathyco/x-components@3.0.0-alpha.230...@empathyco/x-components@3.0.0-alpha.231) (2022-11-28)
20
+
21
+ ### Features
22
+
23
+ - show next result image on hover (#863)
24
+ ([8fd02cc](https://github.com/empathyco/x/commit/8fd02cc8f9913dfa0e06af83251db4577656099e)),
25
+ closes [EX-5970](https://searchbroker.atlassian.net/browse/EX-5970)
26
+
27
+ ### Bug Fixes
28
+
29
+ - **components:** Fix InfiniteScroll get root element inside Shadow DOM. (#874)
30
+ ([340293f](https://github.com/empathyco/x/commit/340293ffc1946c69018fcfa67a069f443110763d))
31
+
32
+ # Change Log
33
+
34
+ All notable changes to this project will be documented in this file. See
35
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
36
+
6
37
  ## [3.0.0-alpha.230](https://github.com/empathyco/x/compare/@empathyco/x-components@3.0.0-alpha.229...@empathyco/x-components@3.0.0-alpha.230) (2022-11-24)
7
38
 
8
39
  ### Features
@@ -0,0 +1,13 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@empathyco/x-components](./x-components.md) &gt; [BaseResultImage](./x-components.baseresultimage.md) &gt; [hoverAnimation](./x-components.baseresultimage.hoveranimation.md)
4
+
5
+ ## BaseResultImage.hoverAnimation property
6
+
7
+ Animation to use when switching between the loaded image and the hover image.
8
+
9
+ <b>Signature:</b>
10
+
11
+ ```typescript
12
+ hoverAnimation: string | typeof Vue | undefined;
13
+ ```
@@ -1,13 +1,13 @@
1
1
  <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
2
 
3
- [Home](./index.md) &gt; [@empathyco/x-components](./x-components.md) &gt; [BaseResultImage](./x-components.baseresultimage.md) &gt; [animation](./x-components.baseresultimage.animation.md)
3
+ [Home](./index.md) &gt; [@empathyco/x-components](./x-components.md) &gt; [BaseResultImage](./x-components.baseresultimage.md) &gt; [loadAnimation](./x-components.baseresultimage.loadanimation.md)
4
4
 
5
- ## BaseResultImage.animation property
5
+ ## BaseResultImage.loadAnimation property
6
6
 
7
7
  Animation to use when switching between the placeholder, the loaded image, or the failed image fallback.
8
8
 
9
9
  <b>Signature:</b>
10
10
 
11
11
  ```typescript
12
- animation: string | typeof Vue;
12
+ loadAnimation: string | typeof Vue;
13
13
  ```
@@ -17,6 +17,8 @@ export default class BaseResultImage extends Vue
17
17
 
18
18
  | Property | Modifiers | Type | Description |
19
19
  | --- | --- | --- | --- |
20
- | [animation](./x-components.baseresultimage.animation.md) | | string \| typeof Vue | Animation to use when switching between the placeholder, the loaded image, or the failed image fallback. |
20
+ | [hoverAnimation](./x-components.baseresultimage.hoveranimation.md) | | string \| typeof Vue \| undefined | Animation to use when switching between the loaded image and the hover image. |
21
+ | [loadAnimation](./x-components.baseresultimage.loadanimation.md) | | string \| typeof Vue | Animation to use when switching between the placeholder, the loaded image, or the failed image fallback. |
21
22
  | [result](./x-components.baseresultimage.result.md) | | Result | (Required) The [result](./x-types.result.md) information. |
23
+ | [showNextImageOnHover](./x-components.baseresultimage.shownextimageonhover.md) | | boolean | Indicates if the next valid image should be displayed on hover. |
22
24
 
@@ -0,0 +1,13 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@empathyco/x-components](./x-components.md) &gt; [BaseResultImage](./x-components.baseresultimage.md) &gt; [showNextImageOnHover](./x-components.baseresultimage.shownextimageonhover.md)
4
+
5
+ ## BaseResultImage.showNextImageOnHover property
6
+
7
+ Indicates if the next valid image should be displayed on hover.
8
+
9
+ <b>Signature:</b>
10
+
11
+ ```typescript
12
+ showNextImageOnHover: boolean;
13
+ ```
@@ -6,7 +6,7 @@
6
6
 
7
7
  Custom Vue directive for infinite scroll.
8
8
 
9
- This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end the IntersectionObserver triggers that both elements are intersecting.
9
+ This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end, the IntersectionObserver triggers that both elements are intersecting.
10
10
 
11
11
  How it works.
12
12
 
@@ -14,7 +14,7 @@ As a summary, if the scroll reaches the end, the `vNode.context.onInfiniteScroll
14
14
 
15
15
  Usage.
16
16
 
17
- The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: \* html: will set the <html> as the scrollable container. \* body: will set the <body> as the scrollable container. \* id: will set the DOM element with the provided id as the scrollable container.
17
+ The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: `html`<!-- -->: will set the <html> as the scrollable container. `body`<!-- -->: will set the <body> as the scrollable container. ID: will set the DOM element with the provided id as the scrollable container.
18
18
 
19
19
  If no argument is provided the scrollable container fallbacks to the viewport.
20
20
 
@@ -471,7 +471,7 @@ X-Components is a library usable everywhere not only for search experiences.
471
471
  | [identifierResultsXModule](./x-components.identifierresultsxmodule.md) | IdentifierResults [XModule](./x-components.xmodule.md) implementation. This module is auto-registered as soon as you import any component from the <code>identifier-results</code> entry point. |
472
472
  | [increasePageAppendingResults](./x-components.increasepageappendingresults.md) | Default implementation for the [SearchActions.increasePageAppendingResults()](./x-components.searchactions.increasepageappendingresults.md)<!-- -->. |
473
473
  | [increasePageAppendingResultsWire](./x-components.increasepageappendingresultswire.md) | Increases the current search state <code>page</code> by one. |
474
- | [infiniteScroll](./x-components.infinitescroll.md) | Custom Vue directive for infinite scroll.<!-- -->This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end the IntersectionObserver triggers that both elements are intersecting.<!-- -->How it works.<!-- -->As a summary, if the scroll reaches the end, the <code>vNode.context.onInfiniteScrollEnd</code> function implemented by the component which imports the directive, is executed. If you provide a margin in the directive options, this function is triggered when the scroll reaches the end minus that amount of pixels. A default margin of 200px is set.<!-- -->Usage.<!-- -->The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: \* html: will set the <html> as the scrollable container. \* body: will set the <body> as the scrollable container. \* id: will set the DOM element with the provided id as the scrollable container.<!-- -->If no argument is provided the scrollable container fallbacks to the viewport. |
474
+ | [infiniteScroll](./x-components.infinitescroll.md) | Custom Vue directive for infinite scroll.<!-- -->This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end, the IntersectionObserver triggers that both elements are intersecting.<!-- -->How it works.<!-- -->As a summary, if the scroll reaches the end, the <code>vNode.context.onInfiniteScrollEnd</code> function implemented by the component which imports the directive, is executed. If you provide a margin in the directive options, this function is triggered when the scroll reaches the end minus that amount of pixels. A default margin of 200px is set.<!-- -->Usage.<!-- -->The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: <code>html</code>: will set the <html> as the scrollable container. <code>body</code>: will set the <body> as the scrollable container. ID: will set the DOM element with the provided id as the scrollable container.<!-- -->If no argument is provided the scrollable container fallbacks to the viewport. |
475
475
  | [LightBulbOff](./x-components.lightbulboff.md) | |
476
476
  | [LightBulbOn](./x-components.lightbulbon.md) | |
477
477
  | [loadHistoryQueriesFromBrowserStorage](./x-components.loadhistoryqueriesfrombrowserstorage.md) | Default implementation for the [HistoryQueriesActions.loadHistoryQueriesFromBrowserStorage()](./x-components.historyqueriesactions.loadhistoryqueriesfrombrowserstorage.md) action. |
@@ -10,10 +10,12 @@ Component to be reused that renders an `<img>`.
10
10
 
11
11
  ## Props
12
12
 
13
- | Name | Description | Type | Default |
14
- | ---------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------- |
15
- | <code>result</code> | (Required) The {@link @empathyco/x-types#Result \| result} information. | <code>Result</code> | <code></code> |
16
- | <code>animation</code> | Animation to use when switching between the placeholder, the loaded image, or the failed<br />image fallback. | <code>union</code> | <code>() => NoElement</code> |
13
+ | Name | Description | Type | Default |
14
+ | --------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------- | ---------------------------- |
15
+ | <code>result</code> | (Required) The {@link @empathyco/x-types#Result \| result} information. | <code>Result</code> | <code></code> |
16
+ | <code>loadAnimation</code> | Animation to use when switching between the placeholder, the loaded image, or the failed<br />image fallback. | <code>union</code> | <code>() => NoElement</code> |
17
+ | <code>hoverAnimation</code> | Animation to use when switching between the loaded image and the hover image. | <code>union</code> | <code></code> |
18
+ | <code>showNextImageOnHover</code> | Indicates if the next valid image should be displayed on hover. | <code>boolean</code> | <code>false</code> |
17
19
 
18
20
  ## Slots
19
21
 
@@ -35,6 +37,14 @@ The result prop is required. It will render a `<img/>` with the result image:
35
37
  <BaseResultImage :result="result" />
36
38
  ```
37
39
 
40
+ ### Showing the next image on hover
41
+
42
+ If a result has multiple images, it can show the next one on hover.
43
+
44
+ ```vue
45
+ <BaseResultImage :result="result" showNextImageOnHover />
46
+ ```
47
+
38
48
  ### Customizing slots content
39
49
 
40
50
  Fallback and placeholder contents can be customized.
@@ -54,3 +64,47 @@ displayed while the real one is loaded.
54
64
  </template>
55
65
  </BaseResultImage>
56
66
  ```
67
+
68
+ ### Customizing the animations
69
+
70
+ Two animations can be used this component.
71
+
72
+ The `loadAnimation` is used to transition between the placeholder, the fallback and the image.
73
+
74
+ The `hoverAnimation` is used to transition between the image and the hover image, if the
75
+ `showNextImageOnHover` prop is `true`.
76
+
77
+ `hoverAnimation` will default to `loadAnimation` if it is not provided.
78
+
79
+ ```vue
80
+ <template>
81
+ <BaseResultImage
82
+ :result="result"
83
+ :loadAnimation="loadAnimation"
84
+ :hoverAnimation="hoverAnimation"
85
+ showNextImageOnHover
86
+ />
87
+ </template>
88
+
89
+ <script>
90
+ import { BaseResultImage } from "@empathyco/x-components";
91
+ import { CrossFade, CollapseHeight } from "@empathyco/x-components/animations";
92
+
93
+ export default {
94
+ name: "BaseResultImageAnimations",
95
+ components: {
96
+ BaseResultImage
97
+ },
98
+ data() {
99
+ return {
100
+ loadAnimation: CrossFade,
101
+ hoverAnimation: CollapseHeight,
102
+ result: {
103
+ name: "jacket",
104
+ images: ["https://some-image", "https://some-image-2"]
105
+ }
106
+ };
107
+ }
108
+ };
109
+ </script>
110
+ ```
@@ -0,0 +1,100 @@
1
+ ---
2
+
3
+ title: Highlight
4
+
5
+ ---
6
+
7
+ # Highlight
8
+
9
+ Highlights the given part of the text. The component is smart enough to do matches
10
+ between special characters like tilde, cedilla, eñe, capital letters...
11
+
12
+ ## Props
13
+
14
+ | Name | Description | Type | Default |
15
+ | ----------------------- | ------------------------------------------------------------------------ | ------------------- | --------------- |
16
+ | <code>text</code> | The text to highlight some part of it. | <code>string</code> | <code>''</code> |
17
+ | <code>highlight</code> | The part of the text to be highlighted. | <code>string</code> | <code>''</code> |
18
+ | <code>matchClass</code> | CSS Class to add when the `text` string contains the `highlight` string. | <code>string</code> | <code>''</code> |
19
+
20
+ ## Slots
21
+
22
+ | Name | Description | Bindings<br />(name - type - description) |
23
+ | -------------------- | ----------- | ----------------------------------------- |
24
+ | <code>default</code> | | <br /><br /> |
25
+
26
+ ## Events
27
+
28
+ This component emits no events.
29
+
30
+ ## See it in action
31
+
32
+ Here you have a basic example of how the highlight component is rendered.
33
+
34
+ _Type any term in the input field to try it out!_
35
+
36
+ ```vue live
37
+ <template>
38
+ <div>
39
+ <input v-model="highlight" />
40
+ <Highlight :highlight="highlight" text="milanesa" />
41
+ </div>
42
+ </template>
43
+
44
+ <script>
45
+ import { Highlight } from "@empathyco/x-components";
46
+
47
+ export default {
48
+ name: "HighlightDemo",
49
+ components: {
50
+ Highlight
51
+ },
52
+ data() {
53
+ return {
54
+ highlight: ""
55
+ };
56
+ }
57
+ };
58
+ </script>
59
+ ```
60
+
61
+ ### Customise the layout
62
+
63
+ This component allows to customise the whole layout. Be careful as due to Vue 2 limitations you can
64
+ only render a single root element.
65
+
66
+ ```vue live
67
+ <template>
68
+ <div>
69
+ <input v-model="highlight" />
70
+ <Highlight
71
+ :highlight="highlight"
72
+ text="Entraña"
73
+ #default="{ hasMatch, start, match, end, text }"
74
+ >
75
+ <span class="custom-layout" v-if="hasMatch">
76
+ <strong>{{ start }}</strong>
77
+ {{ match }}
78
+ <strong>{{ end }}</strong>
79
+ </span>
80
+ <span v-else>{{ text }}</span>
81
+ </Highlight>
82
+ </div>
83
+ </template>
84
+
85
+ <script>
86
+ import { Highlight } from "@empathyco/x-components";
87
+
88
+ export default {
89
+ name: "HighlightDemo",
90
+ components: {
91
+ Highlight
92
+ },
93
+ data() {
94
+ return {
95
+ highlight: "entran"
96
+ };
97
+ }
98
+ };
99
+ </script>
100
+ ```
@@ -10,36 +10,51 @@ var __vue_render__ = function () {
10
10
  var _h = _vm.$createElement;
11
11
  var _c = _vm._self._c || _h;
12
12
  return _c(
13
- "picture",
13
+ "div",
14
14
  {
15
- ref: "image",
16
15
  staticClass: "x-picture x-result-picture",
17
16
  attrs: { "data-test": "result-picture" },
17
+ on: {
18
+ "~mouseenter": function ($event) {
19
+ _vm.userHasHoveredImage = true;
20
+ },
21
+ mouseenter: function ($event) {
22
+ _vm.isHovering = true;
23
+ },
24
+ mouseleave: function ($event) {
25
+ _vm.isHovering = false;
26
+ },
27
+ },
18
28
  },
19
29
  [
20
- !_vm.hasImageLoaded && _vm.imageSrc
30
+ _vm.shouldLoadNextImage
21
31
  ? _c("img", {
22
32
  style: _vm.loaderStyles,
23
33
  attrs: {
24
34
  loading: "lazy",
25
- src: _vm.imageSrc,
35
+ src: _vm.pendingImages[0],
26
36
  "data-test": "result-picture-loader",
27
37
  alt: "",
28
38
  role: "presentation",
29
39
  },
30
- on: { error: _vm.flagImageAsFailed, load: _vm.flagImageLoaded },
40
+ on: { load: _vm.flagImageLoaded, error: _vm.flagImageAsFailed },
31
41
  })
32
42
  : _vm._e(),
33
43
  _vm._v(" "),
34
44
  _c(
35
45
  _vm.animation,
36
- { tag: "component", staticClass: "x-picture__image" },
46
+ {
47
+ tag: "component",
48
+ staticClass: "x-picture__image",
49
+ attrs: { appear: false },
50
+ },
37
51
  [
38
- !_vm.imageSrc
52
+ !_vm.loadedImages.length && !_vm.pendingImages.length
39
53
  ? _vm._t("fallback")
40
- : !_vm.hasImageLoaded
54
+ : !_vm.loadedImages.length
41
55
  ? _vm._t("placeholder")
42
56
  : _c("img", {
57
+ key: _vm.imageSrc,
43
58
  staticClass: "x-picture__image x-result-picture__image",
44
59
  attrs: {
45
60
  alt: _vm.result.name,
@@ -60,7 +75,7 @@ __vue_render__._withStripped = true;
60
75
  /* style */
61
76
  const __vue_inject_styles__ = undefined;
62
77
  /* scoped */
63
- const __vue_scope_id__ = "data-v-236590f6";
78
+ const __vue_scope_id__ = "data-v-66a674d2";
64
79
  /* module identifier */
65
80
  const __vue_module_identifier__ = undefined;
66
81
  /* functional template */
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-image.vue.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <picture ref=\"image\" class=\"x-picture x-result-picture\" data-test=\"result-picture\">\n <img\n v-if=\"!hasImageLoaded && imageSrc\"\n @error=\"flagImageAsFailed\"\n @load=\"flagImageLoaded\"\n loading=\"lazy\"\n :src=\"imageSrc\"\n :style=\"loaderStyles\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n />\n <component :is=\"animation\" class=\"x-picture__image\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!imageSrc\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!hasImageLoaded\" name=\"placeholder\" />\n\n <img\n v-else\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-picture__image x-result-picture__image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </picture>\n</template>\n\n<script lang=\"ts\">\n import { Result } from '@empathyco/x-types';\n import Vue from 'vue';\n import { Component, Prop } from 'vue-property-decorator';\n import { NoElement } from '../no-element';\n\n /**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\n @Component({\n components: {\n NoElement\n }\n })\n export default class BaseResultImage extends Vue {\n /**\n * (Required) The {@link @empathyco/x-types#Result | result} information.\n *\n * @public\n */\n @Prop({ required: true })\n protected result!: Result;\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n *\n * @public\n */\n @Prop({ default: () => NoElement })\n public animation!: string | typeof Vue;\n /**\n * An array of images that failed to load.\n *\n * @internal\n */\n protected failedImages: string[] = [];\n\n /**\n * Indicates if the result image is loaded.\n *\n * @internal\n */\n protected hasImageLoaded = false;\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n protected loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important'\n };\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n protected get imageSrc(): string {\n const image = this.result.images?.find(image => !this.failedImages.includes(image));\n return image ?? '';\n }\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n protected flagImageAsFailed(): void {\n if (this.imageSrc !== '') {\n this.failedImages.push(this.imageSrc);\n }\n }\n\n /**\n * Marks an image as loaded.\n *\n * @internal\n */\n protected flagImageLoaded(): void {\n this.hasImageLoaded = true;\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .x-result-picture {\n min-width: 1px;\n min-height: 1px;\n position: relative;\n\n &__image {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n }\n }\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<BaseResultImage :result=\"result\" />\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<BaseResultImage :result=\"result\">\n <template #placeholder>\n <img class=\"x-result-picture-placeholder\" src=\"./placeholder-image.svg\"/>\n </template>\n <template #fallback>\n <img class=\"x-result-picture-fallback\" src=\"./fallback-image.svg\"/>\n </template>\n</BaseResultImage>\n```\n</docs>\n"],"names":[],"mappings":";;;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"base-result-image.vue.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <!-- This is a div because using a picture causes the onload event of the image to fire twice. -->\n <!-- eslint-disable-next-line vuejs-accessibility/mouse-events-have-key-events -->\n <div\n @mouseenter.once=\"userHasHoveredImage = true\"\n @mouseenter=\"isHovering = true\"\n @mouseleave=\"isHovering = false\"\n class=\"x-picture x-result-picture\"\n data-test=\"result-picture\"\n >\n <img\n v-if=\"shouldLoadNextImage\"\n @load=\"flagImageLoaded\"\n @error=\"flagImageAsFailed\"\n loading=\"lazy\"\n :src=\"pendingImages[0]\"\n :style=\"loaderStyles\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n />\n <component :is=\"animation\" class=\"x-picture__image\" :appear=\"false\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!loadedImages.length && !pendingImages.length\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!loadedImages.length\" name=\"placeholder\" />\n\n <img\n v-else\n :key=\"imageSrc\"\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-picture__image x-result-picture__image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { Result } from '@empathyco/x-types';\n import Vue from 'vue';\n import { Component, Prop } from 'vue-property-decorator';\n import { NoElement } from '../no-element';\n\n /**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\n @Component({\n components: {\n NoElement\n }\n })\n export default class BaseResultImage extends Vue {\n /**\n * (Required) The {@link @empathyco/x-types#Result | result} information.\n *\n * @public\n */\n @Prop({ required: true })\n protected result!: Result;\n\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n *\n * @public\n */\n @Prop({ default: () => NoElement })\n public loadAnimation!: string | typeof Vue;\n\n /**\n * Animation to use when switching between the loaded image and the hover image.\n *\n * @public\n */\n @Prop()\n public hoverAnimation!: string | typeof Vue | undefined;\n\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n @Prop({ type: Boolean, default: false })\n public showNextImageOnHover!: boolean;\n\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n protected pendingImages: string[] = [...(this.result.images ?? [])];\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n protected loadedImages: string[] = [];\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n protected isHovering = false;\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n protected userHasHoveredImage = false;\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n protected loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important'\n };\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n protected get animation(): string | typeof Vue {\n return this.userHasHoveredImage\n ? this.hoverAnimation ?? this.loadAnimation\n : this.loadAnimation;\n }\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n protected get imageSrc(): string {\n return this.loadedImages[\n !this.showNextImageOnHover || !this.isHovering ? 0 : this.loadedImages.length - 1\n ];\n }\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n protected get shouldLoadNextImage(): boolean {\n const numImagesToLoad = this.showNextImageOnHover && this.userHasHoveredImage ? 2 : 1;\n return !!this.pendingImages.length && this.loadedImages.length < numImagesToLoad;\n }\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n protected flagImageAsFailed(): void {\n this.pendingImages.shift();\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n protected flagImageLoaded(): void {\n const image = this.pendingImages.shift();\n if (image) {\n this.loadedImages.push(image);\n }\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .x-result-picture {\n min-width: 1px;\n min-height: 1px;\n position: relative;\n\n &__image {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n }\n }\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<BaseResultImage :result=\"result\" />\n```\n\n### Showing the next image on hover\n\nIf a result has multiple images, it can show the next one on hover.\n\n```vue\n<BaseResultImage :result=\"result\" showNextImageOnHover />\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<BaseResultImage :result=\"result\">\n <template #placeholder>\n <img class=\"x-result-picture-placeholder\" src=\"./placeholder-image.svg\"/>\n </template>\n <template #fallback>\n <img class=\"x-result-picture-fallback\" src=\"./fallback-image.svg\"/>\n </template>\n</BaseResultImage>\n```\n\n### Customizing the animations\n\nTwo animations can be used this component.\n\nThe `loadAnimation` is used to transition between the placeholder, the fallback and the image.\n\nThe `hoverAnimation` is used to transition between the image and the hover image, if the\n`showNextImageOnHover` prop is `true`.\n\n`hoverAnimation` will default to `loadAnimation` if it is not provided.\n\n```vue\n<template>\n <BaseResultImage\n :result=\"result\"\n :loadAnimation=\"loadAnimation\"\n :hoverAnimation=\"hoverAnimation\"\n showNextImageOnHover\n />\n</template>\n\n<script>\n import { BaseResultImage } from '@empathyco/x-components';\n import { CrossFade, CollapseHeight } from '@empathyco/x-components/animations';\n\n export default {\n name: 'BaseResultImageAnimations',\n components: {\n BaseResultImage\n },\n data() {\n return {\n loadAnimation: CrossFade,\n hoverAnimation: CollapseHeight,\n result: {\n name: 'jacket',\n images: ['https://some-image', 'https://some-image-2']\n }\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -12,17 +12,32 @@ let BaseResultImage = class BaseResultImage extends Vue {
12
12
  constructor() {
13
13
  super(...arguments);
14
14
  /**
15
- * An array of images that failed to load.
15
+ * Copy of the images of the result.
16
+ *
17
+ * It is used as a queue of images to load, once an image loads/fails to load, it is removed
18
+ * from this array.
16
19
  *
17
20
  * @internal
18
21
  */
19
- this.failedImages = [];
22
+ this.pendingImages = [...(this.result.images ?? [])];
20
23
  /**
21
- * Indicates if the result image is loaded.
24
+ * Contains the images that have been loaded successfully.
22
25
  *
23
26
  * @internal
24
27
  */
25
- this.hasImageLoaded = false;
28
+ this.loadedImages = [];
29
+ /**
30
+ * Indicates if the user is hovering the image.
31
+ *
32
+ * @internal
33
+ */
34
+ this.isHovering = false;
35
+ /**
36
+ * Indicates if the user has hovered the image.
37
+ *
38
+ * @internal
39
+ */
40
+ this.userHasHoveredImage = false;
26
41
  /**.
27
42
  * Styles to use inline in the image loader, to prevent override from CSS
28
43
  *
@@ -38,6 +53,18 @@ let BaseResultImage = class BaseResultImage extends Vue {
38
53
  visibility: 'hidden !important'
39
54
  };
40
55
  }
56
+ /**
57
+ * Animation to be used.
58
+ *
59
+ * @returns The animation to be used, taking into account if the user has hovered the image.
60
+ *
61
+ * @internal
62
+ */
63
+ get animation() {
64
+ return this.userHasHoveredImage
65
+ ? this.hoverAnimation ?? this.loadAnimation
66
+ : this.loadAnimation;
67
+ }
41
68
  /**
42
69
  * Gets the src from the result image.
43
70
  *
@@ -46,8 +73,18 @@ let BaseResultImage = class BaseResultImage extends Vue {
46
73
  * @internal
47
74
  */
48
75
  get imageSrc() {
49
- const image = this.result.images?.find(image => !this.failedImages.includes(image));
50
- return image ?? '';
76
+ return this.loadedImages[!this.showNextImageOnHover || !this.isHovering ? 0 : this.loadedImages.length - 1];
77
+ }
78
+ /**
79
+ * Indicates if the loader should try to load the next image.
80
+ *
81
+ * @returns True if it should try to load the next image.
82
+ *
83
+ * @internal
84
+ */
85
+ get shouldLoadNextImage() {
86
+ const numImagesToLoad = this.showNextImageOnHover && this.userHasHoveredImage ? 2 : 1;
87
+ return !!this.pendingImages.length && this.loadedImages.length < numImagesToLoad;
51
88
  }
52
89
  /**
53
90
  * Sets an image as failed.
@@ -55,17 +92,18 @@ let BaseResultImage = class BaseResultImage extends Vue {
55
92
  * @internal
56
93
  */
57
94
  flagImageAsFailed() {
58
- if (this.imageSrc !== '') {
59
- this.failedImages.push(this.imageSrc);
60
- }
95
+ this.pendingImages.shift();
61
96
  }
62
97
  /**
63
- * Marks an image as loaded.
98
+ * Sets an image as loaded.
64
99
  *
65
100
  * @internal
66
101
  */
67
102
  flagImageLoaded() {
68
- this.hasImageLoaded = true;
103
+ const image = this.pendingImages.shift();
104
+ if (image) {
105
+ this.loadedImages.push(image);
106
+ }
69
107
  }
70
108
  };
71
109
  __decorate([
@@ -73,7 +111,13 @@ __decorate([
73
111
  ], BaseResultImage.prototype, "result", void 0);
74
112
  __decorate([
75
113
  Prop({ default: () => NoElement })
76
- ], BaseResultImage.prototype, "animation", void 0);
114
+ ], BaseResultImage.prototype, "loadAnimation", void 0);
115
+ __decorate([
116
+ Prop()
117
+ ], BaseResultImage.prototype, "hoverAnimation", void 0);
118
+ __decorate([
119
+ Prop({ type: Boolean, default: false })
120
+ ], BaseResultImage.prototype, "showNextImageOnHover", void 0);
77
121
  BaseResultImage = __decorate([
78
122
  Component({
79
123
  components: {
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-image.vue_rollup-plugin-vue_script.vue.js","sources":["../../../../src/components/result/base-result-image.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Result } from '@empathyco/x-types';\nimport Vue from 'vue';\nimport { Component, Prop } from 'vue-property-decorator';\nimport { NoElement } from '../no-element';\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\n@Component({\n components: {\n NoElement\n }\n})\nexport default class BaseResultImage extends Vue {\n /**\n * (Required) The {@link @empathyco/x-types#Result | result} information.\n *\n * @public\n */\n @Prop({ required: true })\n protected result!: Result;\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n *\n * @public\n */\n @Prop({ default: () => NoElement })\n public animation!: string | typeof Vue;\n /**\n * An array of images that failed to load.\n *\n * @internal\n */\n protected failedImages: string[] = [];\n\n /**\n * Indicates if the result image is loaded.\n *\n * @internal\n */\n protected hasImageLoaded = false;\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n protected loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important'\n };\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n protected get imageSrc(): string {\n const image = this.result.images?.find(image => !this.failedImages.includes(image));\n return image ?? '';\n }\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n protected flagImageAsFailed(): void {\n if (this.imageSrc !== '') {\n this.failedImages.push(this.imageSrc);\n }\n }\n\n /**\n * Marks an image as loaded.\n *\n * @internal\n */\n protected flagImageLoaded(): void {\n this.hasImageLoaded = true;\n }\n}\n"],"names":[],"mappings":";;;;;AAqCA;;;;;AAUA,IAAqB,eAAe,GAApC,MAAqB,eAAgB,SAAQ,GAAG;IAAhD;;;;;;;QAqBY,iBAAY,GAAa,EAAE,CAAC;;;;;;QAO5B,mBAAc,GAAG,KAAK,CAAC;;;;;;QAOvB,iBAAY,GAAiC;YACrD,QAAQ,EAAE,qBAAqB;YAC/B,GAAG,EAAE,cAAc;YACnB,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,iBAAiB;YACxB,MAAM,EAAE,iBAAiB;YACzB,aAAa,EAAE,iBAAiB;YAChC,UAAU,EAAE,mBAAmB;SAChC,CAAC;KAiCH;;;;;;;;IAxBC,IAAc,QAAQ;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACpF,OAAO,KAAK,IAAI,EAAE,CAAC;KACpB;;;;;;IAOS,iBAAiB;QACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,EAAE,EAAE;YACxB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;SACvC;KACF;;;;;;IAOS,eAAe;QACvB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;KAC5B;CACF,CAAA;AArEC;IADC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;+CACC;AAQ1B;IADC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,CAAC;kDACI;AAfpB,eAAe;IALnC,SAAS,CAAC;QACT,UAAU,EAAE;YACV,SAAS;SACV;KACF,CAAC;GACmB,eAAe,CA4EnC;aA5EoB,eAAe;;;;"}
1
+ {"version":3,"file":"base-result-image.vue_rollup-plugin-vue_script.vue.js","sources":["../../../../src/components/result/base-result-image.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Result } from '@empathyco/x-types';\nimport Vue from 'vue';\nimport { Component, Prop } from 'vue-property-decorator';\nimport { NoElement } from '../no-element';\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\n@Component({\n components: {\n NoElement\n }\n})\nexport default class BaseResultImage extends Vue {\n /**\n * (Required) The {@link @empathyco/x-types#Result | result} information.\n *\n * @public\n */\n @Prop({ required: true })\n protected result!: Result;\n\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n *\n * @public\n */\n @Prop({ default: () => NoElement })\n public loadAnimation!: string | typeof Vue;\n\n /**\n * Animation to use when switching between the loaded image and the hover image.\n *\n * @public\n */\n @Prop()\n public hoverAnimation!: string | typeof Vue | undefined;\n\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n @Prop({ type: Boolean, default: false })\n public showNextImageOnHover!: boolean;\n\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n protected pendingImages: string[] = [...(this.result.images ?? [])];\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n protected loadedImages: string[] = [];\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n protected isHovering = false;\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n protected userHasHoveredImage = false;\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n protected loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important'\n };\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n protected get animation(): string | typeof Vue {\n return this.userHasHoveredImage\n ? this.hoverAnimation ?? this.loadAnimation\n : this.loadAnimation;\n }\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n protected get imageSrc(): string {\n return this.loadedImages[\n !this.showNextImageOnHover || !this.isHovering ? 0 : this.loadedImages.length - 1\n ];\n }\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n protected get shouldLoadNextImage(): boolean {\n const numImagesToLoad = this.showNextImageOnHover && this.userHasHoveredImage ? 2 : 1;\n return !!this.pendingImages.length && this.loadedImages.length < numImagesToLoad;\n }\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n protected flagImageAsFailed(): void {\n this.pendingImages.shift();\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n protected flagImageLoaded(): void {\n const image = this.pendingImages.shift();\n if (image) {\n this.loadedImages.push(image);\n }\n }\n}\n"],"names":[],"mappings":";;;;;AA8CA;;;;;AAUA,IAAqB,eAAe,GAApC,MAAqB,eAAgB,SAAQ,GAAG;IAAhD;;;;;;;;;;QA0CY,kBAAa,GAAa,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC;;;;;;QAO1D,iBAAY,GAAa,EAAE,CAAC;;;;;;QAO5B,eAAU,GAAG,KAAK,CAAC;;;;;;QAOnB,wBAAmB,GAAG,KAAK,CAAC;;;;;;QAO5B,iBAAY,GAAiC;YACrD,QAAQ,EAAE,qBAAqB;YAC/B,GAAG,EAAE,cAAc;YACnB,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,iBAAiB;YACxB,MAAM,EAAE,iBAAiB;YACzB,aAAa,EAAE,iBAAiB;YAChC,UAAU,EAAE,mBAAmB;SAChC,CAAC;KA4DH;;;;;;;;IAnDC,IAAc,SAAS;QACrB,OAAO,IAAI,CAAC,mBAAmB;cAC3B,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,aAAa;cACzC,IAAI,CAAC,aAAa,CAAC;KACxB;;;;;;;;IASD,IAAc,QAAQ;QACpB,OAAO,IAAI,CAAC,YAAY,CACtB,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAClF,CAAC;KACH;;;;;;;;IASD,IAAc,mBAAmB;QAC/B,MAAM,eAAe,GAAG,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,mBAAmB,GAAG,CAAC,GAAG,CAAC,CAAC;QACtF,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,eAAe,CAAC;KAClF;;;;;;IAOS,iBAAiB;QACzB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;KAC5B;;;;;;IAOS,eAAe;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SAC/B;KACF;CACF,CAAA;AAnIC;IADC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;+CACC;AAS1B;IADC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,CAAC;sDACQ;AAQ3C;IADC,IAAI,EAAE;uDACiD;AAQxD;IADC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;6DACF;AAhCnB,eAAe;IALnC,SAAS,CAAC;QACT,UAAU,EAAE;YACV,SAAS;SACV;KACF,CAAC;GACmB,eAAe,CA0InC;aA1IoB,eAAe;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { createInjector, createInjectorSSR } from 'vue-runtime-helpers';
2
2
 
3
- var css = ".x-result-picture[data-v-236590f6] {\n min-width: 1px;\n min-height: 1px;\n position: relative;\n}\n.x-result-picture__image[data-v-236590f6] {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}";
3
+ var css = ".x-result-picture[data-v-66a674d2] {\n min-width: 1px;\n min-height: 1px;\n position: relative;\n}\n.x-result-picture__image[data-v-66a674d2] {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}";
4
4
  const isBrowser = /*#__PURE__*/ (function () {
5
5
  return (
6
6
  Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) !==
@@ -9,7 +9,7 @@ const state = {};
9
9
  *
10
10
  * This directive uses the IntersectionObserver API to handle the intersection between the
11
11
  * children and the scrollable container. The content of the children moves up on scroll and when it
12
- * reaches the end the IntersectionObserver triggers that both elements are intersecting.
12
+ * reaches the end, the IntersectionObserver triggers that both elements are intersecting.
13
13
  *
14
14
  * How it works.
15
15
  *
@@ -22,9 +22,9 @@ const state = {};
22
22
  *
23
23
  * The directive has to be set in the target element. It can receive an argument which will be used
24
24
  * to determine the scrollable container. Possible values:
25
- * * html: will set the <html> as the scrollable container.
26
- * * body: will set the <body> as the scrollable container.
27
- * * id: will set the DOM element with the provided id as the scrollable container.
25
+ * `html`: will set the <html> as the scrollable container.
26
+ * `body`: will set the <body> as the scrollable container.
27
+ * ID: will set the DOM element with the provided id as the scrollable container.
28
28
  *
29
29
  * If no argument is provided the scrollable container fallbacks to the viewport.
30
30
  *
@@ -52,7 +52,7 @@ const state = {};
52
52
  */
53
53
  const infiniteScroll = {
54
54
  inserted(element, { arg: id = VIEWPORT_ID, value: { margin = 200 } = {} }, vNode) {
55
- const root = getRoot(id);
55
+ const root = getRoot(element, id);
56
56
  state[id] = createIntersectionObserver({
57
57
  root,
58
58
  margin,
@@ -70,10 +70,11 @@ const infiniteScroll = {
70
70
  /**
71
71
  * Retrieves the root element for the provided id.
72
72
  *
73
- * @param id - String.
73
+ * @param element - Target element where directive is set.
74
+ * @param id - String identifier.
74
75
  * @returns HTMLElement or null.
75
- * */
76
- function getRoot(id) {
76
+ */
77
+ function getRoot(element, id) {
77
78
  switch (id) {
78
79
  case 'html':
79
80
  return null;
@@ -82,7 +83,7 @@ function getRoot(id) {
82
83
  case VIEWPORT_ID:
83
84
  return null;
84
85
  default:
85
- return document.getElementById(id);
86
+ return element.closest(`#${id}`);
86
87
  }
87
88
  }
88
89
  /**
@@ -96,7 +97,7 @@ function getRoot(id) {
96
97
  */
97
98
  function createIntersectionObserver({ root, margin, vNode }) {
98
99
  // This hack allows the root element to always contain the observed element.
99
- // not overpass the top margin more than 1700000 because it doesn't work in Android chrome
100
+ // Not overpass the top margin more than 1700000 because it doesn't work in Android chrome
100
101
  const rootMargin = `1000000% 0px ${margin}px 0px`;
101
102
  return new IntersectionObserver(([entry]) => {
102
103
  if (entry.isIntersecting) {
@@ -1 +1 @@
1
- {"version":3,"file":"infinite-scroll.js","sources":["../../../../src/directives/infinite-scroll/infinite-scroll.ts"],"sourcesContent":["import { DirectiveOptions } from 'vue';\nimport { Vue } from 'vue/types/vue';\nimport { InfiniteScroll, ObserverOptions } from './infinite-scroll.types';\n\nconst VIEWPORT_ID = 'viewport';\n\n/**\n * A record which contains {@link IntersectionObserver} objects indexed by the id of the scrollable\n * container.\n */\nconst state: Record<string, IntersectionObserver> = {};\n\n/**\n * Custom Vue directive for infinite scroll.\n *\n * This directive uses the IntersectionObserver API to handle the intersection between the\n * children and the scrollable container. The content of the children moves up on scroll and when it\n * reaches the end the IntersectionObserver triggers that both elements are intersecting.\n *\n * How it works.\n *\n * As a summary, if the scroll reaches the end, the `vNode.context.onInfiniteScrollEnd` function\n * implemented by the component which imports the directive, is executed. If you provide a margin in\n * the directive options, this function is triggered when the scroll reaches the end minus that\n * amount of pixels. A default margin of 200px is set.\n *\n * Usage.\n *\n * The directive has to be set in the target element. It can receive an argument which will be used\n * to determine the scrollable container. Possible values:\n * * html: will set the <html> as the scrollable container.\n * * body: will set the <body> as the scrollable container.\n * * id: will set the DOM element with the provided id as the scrollable container.\n *\n * If no argument is provided the scrollable container fallbacks to the viewport.\n *\n * @example How to use it.\n *\n * ```html\n * <ResultsList v-infinite-scroll:html>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll:body>\n * ```\n *\n * ```html\n * <BaseScroll id='scroll-test'>\n * <ResultsList v-infinite-scroll:scroll-test>\n * </BaseScroll>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll=\"{ margin: 40 }\">\n * ```\n *\n * @public\n */\nexport const infiniteScroll: DirectiveOptions = {\n inserted(element, { arg: id = VIEWPORT_ID, value: { margin = 200 } = {} }, vNode) {\n const root = getRoot(id);\n\n state[id] = createIntersectionObserver({\n root,\n margin,\n vNode\n });\n\n state[id].observe(element);\n },\n\n unbind(_element, { arg: id = VIEWPORT_ID }) {\n if (state[id]) {\n state[id].disconnect();\n delete state[id];\n }\n }\n};\n\n/**\n * Retrieves the root element for the provided id.\n *\n * @param id - String.\n * @returns HTMLElement or null.\n * */\nfunction getRoot(id: string): HTMLElement | null {\n switch (id) {\n case 'html':\n return null;\n case 'body':\n return document.body;\n case VIEWPORT_ID:\n return null;\n default:\n return document.getElementById(id)!;\n }\n}\n\n/**\n * Creates an IntersectionObserver.\n *\n * When the observer is fired, it will execute the {@link InfiniteScroll.onInfiniteScrollEnd}\n * function implemented in the provided vNode component instance.\n *\n * @param options - ObserverOptions.\n * @returns IntersectionObserver.\n */\nfunction createIntersectionObserver({\n root,\n margin,\n vNode\n}: ObserverOptions): IntersectionObserver {\n // This hack allows the root element to always contain the observed element.\n // not overpass the top margin more than 1700000 because it doesn't work in Android chrome\n const rootMargin = `1000000% 0px ${margin}px 0px`;\n\n return new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n (vNode.componentInstance as Vue & InfiniteScroll)?.onInfiniteScrollEnd();\n }\n },\n {\n threshold: 0.99,\n rootMargin,\n root\n }\n );\n}\n"],"names":[],"mappings":"AAIA,MAAM,WAAW,GAAG,UAAU,CAAC;AAE/B;;;;AAIA,MAAM,KAAK,GAAyC,EAAE,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA8Ca,cAAc,GAAqB;IAC9C,QAAQ,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK;QAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QAEzB,KAAK,CAAC,EAAE,CAAC,GAAG,0BAA0B,CAAC;YACrC,IAAI;YACJ,MAAM;YACN,KAAK;SACN,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KAC5B;IAED,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,WAAW,EAAE;QACxC,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE;YACb,KAAK,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC;SAClB;KACF;EACD;AAEF;;;;;;AAMA,SAAS,OAAO,CAAC,EAAU;IACzB,QAAQ,EAAE;QACR,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,KAAK,WAAW;YACd,OAAO,IAAI,CAAC;QACd;YACE,OAAO,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAE,CAAC;KACvC;AACH,CAAC;AAED;;;;;;;;;AASA,SAAS,0BAA0B,CAAC,EAClC,IAAI,EACJ,MAAM,EACN,KAAK,EACW;;;IAGhB,MAAM,UAAU,GAAG,gBAAgB,MAAM,QAAQ,CAAC;IAElD,OAAO,IAAI,oBAAoB,CAC7B,CAAC,CAAC,KAAK,CAAC;QACN,IAAI,KAAK,CAAC,cAAc,EAAE;YACvB,KAAK,CAAC,iBAA0C,EAAE,mBAAmB,EAAE,CAAC;SAC1E;KACF,EACD;QACE,SAAS,EAAE,IAAI;QACf,UAAU;QACV,IAAI;KACL,CACF,CAAC;AACJ;;;;"}
1
+ {"version":3,"file":"infinite-scroll.js","sources":["../../../../src/directives/infinite-scroll/infinite-scroll.ts"],"sourcesContent":["import { DirectiveOptions } from 'vue';\nimport { Vue } from 'vue/types/vue';\nimport { InfiniteScroll, ObserverOptions } from './infinite-scroll.types';\n\nconst VIEWPORT_ID = 'viewport';\n\n/**\n * A record which contains {@link IntersectionObserver} objects indexed by the id of the scrollable\n * container.\n */\nconst state: Record<string, IntersectionObserver> = {};\n\n/**\n * Custom Vue directive for infinite scroll.\n *\n * This directive uses the IntersectionObserver API to handle the intersection between the\n * children and the scrollable container. The content of the children moves up on scroll and when it\n * reaches the end, the IntersectionObserver triggers that both elements are intersecting.\n *\n * How it works.\n *\n * As a summary, if the scroll reaches the end, the `vNode.context.onInfiniteScrollEnd` function\n * implemented by the component which imports the directive, is executed. If you provide a margin in\n * the directive options, this function is triggered when the scroll reaches the end minus that\n * amount of pixels. A default margin of 200px is set.\n *\n * Usage.\n *\n * The directive has to be set in the target element. It can receive an argument which will be used\n * to determine the scrollable container. Possible values:\n * `html`: will set the <html> as the scrollable container.\n * `body`: will set the <body> as the scrollable container.\n * ID: will set the DOM element with the provided id as the scrollable container.\n *\n * If no argument is provided the scrollable container fallbacks to the viewport.\n *\n * @example How to use it.\n *\n * ```html\n * <ResultsList v-infinite-scroll:html>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll:body>\n * ```\n *\n * ```html\n * <BaseScroll id='scroll-test'>\n * <ResultsList v-infinite-scroll:scroll-test>\n * </BaseScroll>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll=\"{ margin: 40 }\">\n * ```\n *\n * @public\n */\nexport const infiniteScroll: DirectiveOptions = {\n inserted(element, { arg: id = VIEWPORT_ID, value: { margin = 200 } = {} }, vNode) {\n const root = getRoot(element, id);\n\n state[id] = createIntersectionObserver({\n root,\n margin,\n vNode\n });\n\n state[id].observe(element);\n },\n\n unbind(_element, { arg: id = VIEWPORT_ID }) {\n if (state[id]) {\n state[id].disconnect();\n delete state[id];\n }\n }\n};\n\n/**\n * Retrieves the root element for the provided id.\n *\n * @param element - Target element where directive is set.\n * @param id - String identifier.\n * @returns HTMLElement or null.\n */\nfunction getRoot(element: HTMLElement, id: string): HTMLElement | null {\n switch (id) {\n case 'html':\n return null;\n case 'body':\n return document.body;\n case VIEWPORT_ID:\n return null;\n default:\n return element.closest(`#${id}`)!;\n }\n}\n\n/**\n * Creates an IntersectionObserver.\n *\n * When the observer is fired, it will execute the {@link InfiniteScroll.onInfiniteScrollEnd}\n * function implemented in the provided vNode component instance.\n *\n * @param options - ObserverOptions.\n * @returns IntersectionObserver.\n */\nfunction createIntersectionObserver({\n root,\n margin,\n vNode\n}: ObserverOptions): IntersectionObserver {\n // This hack allows the root element to always contain the observed element.\n // Not overpass the top margin more than 1700000 because it doesn't work in Android chrome\n const rootMargin = `1000000% 0px ${margin}px 0px`;\n\n return new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n (vNode.componentInstance as Vue & InfiniteScroll)?.onInfiniteScrollEnd();\n }\n },\n {\n threshold: 0.99,\n rootMargin,\n root\n }\n );\n}\n"],"names":[],"mappings":"AAIA,MAAM,WAAW,GAAG,UAAU,CAAC;AAE/B;;;;AAIA,MAAM,KAAK,GAAyC,EAAE,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA8Ca,cAAc,GAAqB;IAC9C,QAAQ,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK;QAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAElC,KAAK,CAAC,EAAE,CAAC,GAAG,0BAA0B,CAAC;YACrC,IAAI;YACJ,MAAM;YACN,KAAK;SACN,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KAC5B;IAED,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,WAAW,EAAE;QACxC,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE;YACb,KAAK,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC;SAClB;KACF;EACD;AAEF;;;;;;;AAOA,SAAS,OAAO,CAAC,OAAoB,EAAE,EAAU;IAC/C,QAAQ,EAAE;QACR,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,KAAK,WAAW;YACd,OAAO,IAAI,CAAC;QACd;YACE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAE,CAAC;KACrC;AACH,CAAC;AAED;;;;;;;;;AASA,SAAS,0BAA0B,CAAC,EAClC,IAAI,EACJ,MAAM,EACN,KAAK,EACW;;;IAGhB,MAAM,UAAU,GAAG,gBAAgB,MAAM,QAAQ,CAAC;IAElD,OAAO,IAAI,oBAAoB,CAC7B,CAAC,CAAC,KAAK,CAAC;QACN,IAAI,KAAK,CAAC,cAAc,EAAE;YACvB,KAAK,CAAC,iBAA0C,EAAE,mBAAmB,EAAE,CAAC;SAC1E;KACF,EACD;QACE,SAAS,EAAE,IAAI;QACf,UAAU;QACV,IAAI;KACL,CACF,CAAC;AACJ;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empathyco/x-components",
3
- "version": "3.0.0-alpha.230",
3
+ "version": "3.0.0-alpha.232",
4
4
  "description": "Empathy X Components",
5
5
  "author": "Empathy Systems Corporation S.L.",
6
6
  "license": "Apache-2.0",
@@ -85,7 +85,7 @@
85
85
  "@cypress/vue": "~2.2.4",
86
86
  "@cypress/webpack-dev-server": "~1.8.4",
87
87
  "@empathyco/x-adapter-platform": "^1.0.0-alpha.44",
88
- "@empathyco/x-tailwindcss": "^0.2.0-alpha.29",
88
+ "@empathyco/x-tailwindcss": "^0.2.0-alpha.30",
89
89
  "@microsoft/api-documenter": "~7.15.3",
90
90
  "@microsoft/api-extractor": "~7.19.4",
91
91
  "@rollup/plugin-commonjs": "~21.0.1",
@@ -135,5 +135,5 @@
135
135
  "access": "public",
136
136
  "directory": "dist"
137
137
  },
138
- "gitHead": "add1c39bff84e5aadd005bfbeb34f3572485e504"
138
+ "gitHead": "1f8d1974224849377a90117703484ee644b6e2de"
139
139
  }
@@ -5516,12 +5516,48 @@
5516
5516
  "members": [
5517
5517
  {
5518
5518
  "kind": "Property",
5519
- "canonicalReference": "@empathyco/x-components!BaseResultImage#animation:member",
5519
+ "canonicalReference": "@empathyco/x-components!BaseResultImage#hoverAnimation:member",
5520
+ "docComment": "/**\n * Animation to use when switching between the loaded image and the hover image.\n *\n * @public\n */\n",
5521
+ "excerptTokens": [
5522
+ {
5523
+ "kind": "Content",
5524
+ "text": "hoverAnimation: "
5525
+ },
5526
+ {
5527
+ "kind": "Content",
5528
+ "text": "string | typeof "
5529
+ },
5530
+ {
5531
+ "kind": "Reference",
5532
+ "text": "Vue",
5533
+ "canonicalReference": "vue!Vue:var"
5534
+ },
5535
+ {
5536
+ "kind": "Content",
5537
+ "text": " | undefined"
5538
+ },
5539
+ {
5540
+ "kind": "Content",
5541
+ "text": ";"
5542
+ }
5543
+ ],
5544
+ "isOptional": false,
5545
+ "releaseTag": "Public",
5546
+ "name": "hoverAnimation",
5547
+ "propertyTypeTokenRange": {
5548
+ "startIndex": 1,
5549
+ "endIndex": 4
5550
+ },
5551
+ "isStatic": false
5552
+ },
5553
+ {
5554
+ "kind": "Property",
5555
+ "canonicalReference": "@empathyco/x-components!BaseResultImage#loadAnimation:member",
5520
5556
  "docComment": "/**\n * Animation to use when switching between the placeholder, the loaded image, or the failed image fallback.\n *\n * @public\n */\n",
5521
5557
  "excerptTokens": [
5522
5558
  {
5523
5559
  "kind": "Content",
5524
- "text": "animation: "
5560
+ "text": "loadAnimation: "
5525
5561
  },
5526
5562
  {
5527
5563
  "kind": "Content",
@@ -5539,7 +5575,7 @@
5539
5575
  ],
5540
5576
  "isOptional": false,
5541
5577
  "releaseTag": "Public",
5542
- "name": "animation",
5578
+ "name": "loadAnimation",
5543
5579
  "propertyTypeTokenRange": {
5544
5580
  "startIndex": 1,
5545
5581
  "endIndex": 3
@@ -5573,6 +5609,33 @@
5573
5609
  "endIndex": 2
5574
5610
  },
5575
5611
  "isStatic": false
5612
+ },
5613
+ {
5614
+ "kind": "Property",
5615
+ "canonicalReference": "@empathyco/x-components!BaseResultImage#showNextImageOnHover:member",
5616
+ "docComment": "/**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n",
5617
+ "excerptTokens": [
5618
+ {
5619
+ "kind": "Content",
5620
+ "text": "showNextImageOnHover: "
5621
+ },
5622
+ {
5623
+ "kind": "Content",
5624
+ "text": "boolean"
5625
+ },
5626
+ {
5627
+ "kind": "Content",
5628
+ "text": ";"
5629
+ }
5630
+ ],
5631
+ "isOptional": false,
5632
+ "releaseTag": "Public",
5633
+ "name": "showNextImageOnHover",
5634
+ "propertyTypeTokenRange": {
5635
+ "startIndex": 1,
5636
+ "endIndex": 2
5637
+ },
5638
+ "isStatic": false
5576
5639
  }
5577
5640
  ],
5578
5641
  "extendsTokenRange": {
@@ -22919,7 +22982,7 @@
22919
22982
  {
22920
22983
  "kind": "Variable",
22921
22984
  "canonicalReference": "@empathyco/x-components!infiniteScroll:var",
22922
- "docComment": "/**\n * Custom Vue directive for infinite scroll.\n *\n * This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end the IntersectionObserver triggers that both elements are intersecting.\n *\n * How it works.\n *\n * As a summary, if the scroll reaches the end, the `vNode.context.onInfiniteScrollEnd` function implemented by the component which imports the directive, is executed. If you provide a margin in the directive options, this function is triggered when the scroll reaches the end minus that amount of pixels. A default margin of 200px is set.\n *\n * Usage.\n *\n * The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: * html: will set the <html> as the scrollable container. * body: will set the <body> as the scrollable container. * id: will set the DOM element with the provided id as the scrollable container.\n *\n * If no argument is provided the scrollable container fallbacks to the viewport.\n *\n * @example\n *\n * How to use it.\n * ```html\n * <ResultsList v-infinite-scroll:html>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll:body>\n * ```\n *\n * ```html\n * <BaseScroll id='scroll-test'>\n * <ResultsList v-infinite-scroll:scroll-test>\n * </BaseScroll>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll=\"{ margin: 40 }\">\n * ```\n *\n * @public\n */\n",
22985
+ "docComment": "/**\n * Custom Vue directive for infinite scroll.\n *\n * This directive uses the IntersectionObserver API to handle the intersection between the children and the scrollable container. The content of the children moves up on scroll and when it reaches the end, the IntersectionObserver triggers that both elements are intersecting.\n *\n * How it works.\n *\n * As a summary, if the scroll reaches the end, the `vNode.context.onInfiniteScrollEnd` function implemented by the component which imports the directive, is executed. If you provide a margin in the directive options, this function is triggered when the scroll reaches the end minus that amount of pixels. A default margin of 200px is set.\n *\n * Usage.\n *\n * The directive has to be set in the target element. It can receive an argument which will be used to determine the scrollable container. Possible values: `html`: will set the <html> as the scrollable container. `body`: will set the <body> as the scrollable container. ID: will set the DOM element with the provided id as the scrollable container.\n *\n * If no argument is provided the scrollable container fallbacks to the viewport.\n *\n * @example\n *\n * How to use it.\n * ```html\n * <ResultsList v-infinite-scroll:html>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll:body>\n * ```\n *\n * ```html\n * <BaseScroll id='scroll-test'>\n * <ResultsList v-infinite-scroll:scroll-test>\n * </BaseScroll>\n * ```\n *\n * ```html\n * <ResultsList v-infinite-scroll=\"{ margin: 40 }\">\n * ```\n *\n * @public\n */\n",
22923
22986
  "excerptTokens": [
22924
22987
  {
22925
22988
  "kind": "Content",
@@ -530,20 +530,30 @@ export class BaseResultCurrentPrice extends Vue_2 {
530
530
 
531
531
  // @public
532
532
  export class BaseResultImage extends Vue_2 {
533
- animation: string | typeof Vue_2;
534
533
  // @internal
535
- protected failedImages: string[];
534
+ protected get animation(): string | typeof Vue_2;
536
535
  // @internal
537
536
  protected flagImageAsFailed(): void;
538
537
  // @internal
539
538
  protected flagImageLoaded(): void;
540
- // @internal
541
- protected hasImageLoaded: boolean;
539
+ hoverAnimation: string | typeof Vue_2 | undefined;
542
540
  // @internal
543
541
  protected get imageSrc(): string;
544
542
  // @internal
543
+ protected isHovering: boolean;
544
+ loadAnimation: string | typeof Vue_2;
545
+ // @internal
546
+ protected loadedImages: string[];
547
+ // @internal
545
548
  protected loaderStyles: Partial<CSSStyleDeclaration>;
549
+ // @internal
550
+ protected pendingImages: string[];
546
551
  protected result: Result;
552
+ // @internal
553
+ protected get shouldLoadNextImage(): boolean;
554
+ showNextImageOnHover: boolean;
555
+ // @internal
556
+ protected userHasHoveredImage: boolean;
547
557
  }
548
558
 
549
559
  // @public
@@ -18,25 +18,60 @@ export default class BaseResultImage extends Vue {
18
18
  *
19
19
  * @public
20
20
  */
21
- animation: string | typeof Vue;
21
+ loadAnimation: string | typeof Vue;
22
22
  /**
23
- * An array of images that failed to load.
23
+ * Animation to use when switching between the loaded image and the hover image.
24
+ *
25
+ * @public
26
+ */
27
+ hoverAnimation: string | typeof Vue | undefined;
28
+ /**
29
+ * Indicates if the next valid image should be displayed on hover.
30
+ *
31
+ * @public
32
+ */
33
+ showNextImageOnHover: boolean;
34
+ /**
35
+ * Copy of the images of the result.
36
+ *
37
+ * It is used as a queue of images to load, once an image loads/fails to load, it is removed
38
+ * from this array.
24
39
  *
25
40
  * @internal
26
41
  */
27
- protected failedImages: string[];
42
+ protected pendingImages: string[];
28
43
  /**
29
- * Indicates if the result image is loaded.
44
+ * Contains the images that have been loaded successfully.
30
45
  *
31
46
  * @internal
32
47
  */
33
- protected hasImageLoaded: boolean;
48
+ protected loadedImages: string[];
49
+ /**
50
+ * Indicates if the user is hovering the image.
51
+ *
52
+ * @internal
53
+ */
54
+ protected isHovering: boolean;
55
+ /**
56
+ * Indicates if the user has hovered the image.
57
+ *
58
+ * @internal
59
+ */
60
+ protected userHasHoveredImage: boolean;
34
61
  /**.
35
62
  * Styles to use inline in the image loader, to prevent override from CSS
36
63
  *
37
64
  * @internal
38
65
  */
39
66
  protected loaderStyles: Partial<CSSStyleDeclaration>;
67
+ /**
68
+ * Animation to be used.
69
+ *
70
+ * @returns The animation to be used, taking into account if the user has hovered the image.
71
+ *
72
+ * @internal
73
+ */
74
+ protected get animation(): string | typeof Vue;
40
75
  /**
41
76
  * Gets the src from the result image.
42
77
  *
@@ -45,6 +80,14 @@ export default class BaseResultImage extends Vue {
45
80
  * @internal
46
81
  */
47
82
  protected get imageSrc(): string;
83
+ /**
84
+ * Indicates if the loader should try to load the next image.
85
+ *
86
+ * @returns True if it should try to load the next image.
87
+ *
88
+ * @internal
89
+ */
90
+ protected get shouldLoadNextImage(): boolean;
48
91
  /**
49
92
  * Sets an image as failed.
50
93
  *
@@ -52,7 +95,7 @@ export default class BaseResultImage extends Vue {
52
95
  */
53
96
  protected flagImageAsFailed(): void;
54
97
  /**
55
- * Marks an image as loaded.
98
+ * Sets an image as loaded.
56
99
  *
57
100
  * @internal
58
101
  */
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-image.vue?rollup-plugin-vue=script.d.ts","sourceRoot":"","sources":["../../../../src/components/result/base-result-image.vue?rollup-plugin-vue=script.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB;;;;GAIG;AAMH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,GAAG;IAC9C;;;;OAIG;IAEH,SAAS,CAAC,MAAM,EAAG,MAAM,CAAC;IAC1B;;;;;OAKG;IAEI,SAAS,EAAG,MAAM,GAAG,OAAO,GAAG,CAAC;IACvC;;;;OAIG;IACH,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IAEtC;;;;OAIG;IACH,SAAS,CAAC,cAAc,UAAS;IAEjC;;;;OAIG;IACH,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAQlD;IAEF;;;;;;OAMG;IACH,SAAS,KAAK,QAAQ,IAAI,MAAM,CAG/B;IAED;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,IAAI,IAAI;IAMnC;;;;OAIG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAGlC"}
1
+ {"version":3,"file":"base-result-image.vue?rollup-plugin-vue=script.d.ts","sourceRoot":"","sources":["../../../../src/components/result/base-result-image.vue?rollup-plugin-vue=script.ts"],"names":[],"mappings":"AAyCA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB;;;;GAIG;AAMH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,GAAG;IAC9C;;;;OAIG;IAEH,SAAS,CAAC,MAAM,EAAG,MAAM,CAAC;IAE1B;;;;;OAKG;IAEI,aAAa,EAAG,MAAM,GAAG,OAAO,GAAG,CAAC;IAE3C;;;;OAIG;IAEI,cAAc,EAAG,MAAM,GAAG,OAAO,GAAG,GAAG,SAAS,CAAC;IAExD;;;;OAIG;IAEI,oBAAoB,EAAG,OAAO,CAAC;IAEtC;;;;;;;OAOG;IACH,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,CAAmC;IAEpE;;;;OAIG;IACH,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IAEtC;;;;OAIG;IACH,SAAS,CAAC,UAAU,UAAS;IAE7B;;;;OAIG;IACH,SAAS,CAAC,mBAAmB,UAAS;IAEtC;;;;OAIG;IACH,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAQlD;IAEF;;;;;;OAMG;IACH,SAAS,KAAK,SAAS,IAAI,MAAM,GAAG,OAAO,GAAG,CAI7C;IAED;;;;;;OAMG;IACH,SAAS,KAAK,QAAQ,IAAI,MAAM,CAI/B;IAED;;;;;;OAMG;IACH,SAAS,KAAK,mBAAmB,IAAI,OAAO,CAG3C;IAED;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,IAAI,IAAI;IAInC;;;;OAIG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAMlC"}
@@ -4,7 +4,7 @@ import { DirectiveOptions } from 'vue';
4
4
  *
5
5
  * This directive uses the IntersectionObserver API to handle the intersection between the
6
6
  * children and the scrollable container. The content of the children moves up on scroll and when it
7
- * reaches the end the IntersectionObserver triggers that both elements are intersecting.
7
+ * reaches the end, the IntersectionObserver triggers that both elements are intersecting.
8
8
  *
9
9
  * How it works.
10
10
  *
@@ -17,9 +17,9 @@ import { DirectiveOptions } from 'vue';
17
17
  *
18
18
  * The directive has to be set in the target element. It can receive an argument which will be used
19
19
  * to determine the scrollable container. Possible values:
20
- * * html: will set the <html> as the scrollable container.
21
- * * body: will set the <body> as the scrollable container.
22
- * * id: will set the DOM element with the provided id as the scrollable container.
20
+ * `html`: will set the <html> as the scrollable container.
21
+ * `body`: will set the <body> as the scrollable container.
22
+ * ID: will set the DOM element with the provided id as the scrollable container.
23
23
  *
24
24
  * If no argument is provided the scrollable container fallbacks to the viewport.
25
25
  *