@empathyco/x-components 8.10.0 → 8.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/docs/API-reference/api/x-components.hierarchicalfilter.md +8 -0
- package/docs/API-reference/api/x-components.md +37 -0
- package/docs/API-reference/api/x-components.querypreviewlist.md +2 -0
- package/docs/API-reference/api/x-components.setquerypreviewvendorbanners.md +16 -0
- package/docs/API-reference/api/x-components.setquerypreviewvendorresults.md +16 -0
- package/docs/API-reference/api/x-components.simplefilter.md +8 -0
- package/docs/API-reference/api/x-components.snippetcallbacks.md +8 -0
- package/docs/API-reference/api/x-components.vendorbannerslist.md +11 -0
- package/docs/API-reference/api/x-components.vendormutations.md +57 -0
- package/docs/API-reference/api/x-components.vendormutations.removequerypreviewvendordata.md +13 -0
- package/docs/API-reference/api/x-components.vendormutations.setquerypreviewvendorbanners.md +16 -0
- package/docs/API-reference/api/x-components.vendormutations.setquerypreviewvendorresults.md +16 -0
- package/docs/API-reference/api/x-components.vendorquerypreview.banners.md +13 -0
- package/docs/API-reference/api/x-components.vendorquerypreview.md +77 -0
- package/docs/API-reference/api/x-components.vendorquerypreview.results.md +13 -0
- package/docs/API-reference/api/x-components.vendorresultslist.md +11 -0
- package/docs/API-reference/api/x-components.vendorstate.md +19 -0
- package/docs/API-reference/api/x-components.vendorstate.querypreviews.md +13 -0
- package/docs/API-reference/api/x-components.vendorxevents.md +38 -0
- package/docs/API-reference/api/x-components.vendorxevents.querypreviewvendorbannerschanged.md +16 -0
- package/docs/API-reference/api/x-components.vendorxevents.querypreviewvendorresultschanged.md +16 -0
- package/docs/API-reference/api/x-components.vendorxevents.vendorquerychanged.md +5 -0
- package/docs/API-reference/components/queries-preview/x-components.query-preview-list.md +46 -0
- package/docs/API-reference/components/vendor/x-components.vendor-banners-list.md +7 -3
- package/docs/API-reference/components/vendor/x-components.vendor-results-list.md +7 -3
- package/js/components/icons/ai-spinner-icon.vue.js +1 -1
- package/js/components/icons/ai-spinner-icon.vue.js.map +1 -1
- package/js/index.js +1 -1
- package/js/x-modules/queries-preview/components/query-preview-list.vue.js +30 -34
- package/js/x-modules/queries-preview/components/query-preview-list.vue.js.map +1 -1
- package/js/x-modules/queries-preview/components/query-preview-list.vue2.js +2 -0
- package/js/x-modules/queries-preview/components/query-preview-list.vue2.js.map +1 -1
- package/js/x-modules/queries-preview/components/query-preview.vue.js.map +1 -1
- package/js/x-modules/queries-preview/components/query-preview.vue2.js +1 -0
- package/js/x-modules/queries-preview/components/query-preview.vue2.js.map +1 -1
- package/js/x-modules/vendor/components/vendor-banners-list.vue.js +34 -5
- package/js/x-modules/vendor/components/vendor-banners-list.vue.js.map +1 -1
- package/js/x-modules/vendor/components/vendor-results-list.vue.js +34 -5
- package/js/x-modules/vendor/components/vendor-results-list.vue.js.map +1 -1
- package/js/x-modules/vendor/store/emitters.js +11 -1
- package/js/x-modules/vendor/store/emitters.js.map +1 -1
- package/js/x-modules/vendor/store/module.js +22 -0
- package/js/x-modules/vendor/store/module.js.map +1 -1
- package/js/x-modules/vendor/wiring.js +32 -1
- package/js/x-modules/vendor/wiring.js.map +1 -1
- package/package.json +2 -2
- package/report/x-components.api.json +647 -19
- package/report/x-components.api.md +103 -1
- package/types/src/components/snippet-callbacks.vue.d.ts +8 -0
- package/types/src/components/snippet-callbacks.vue.d.ts.map +1 -1
- package/types/src/x-modules/facets/components/filters/hierarchical-filter.vue.d.ts +8 -0
- package/types/src/x-modules/facets/components/filters/hierarchical-filter.vue.d.ts.map +1 -1
- package/types/src/x-modules/facets/components/filters/simple-filter.vue.d.ts +8 -0
- package/types/src/x-modules/facets/components/filters/simple-filter.vue.d.ts.map +1 -1
- package/types/src/x-modules/queries-preview/components/query-preview-list.vue.d.ts +2 -0
- package/types/src/x-modules/queries-preview/components/query-preview-list.vue.d.ts.map +1 -1
- package/types/src/x-modules/queries-preview/components/query-preview.vue.d.ts.map +1 -1
- package/types/src/x-modules/vendor/components/vendor-banners-list.vue.d.ts +20 -0
- package/types/src/x-modules/vendor/components/vendor-banners-list.vue.d.ts.map +1 -1
- package/types/src/x-modules/vendor/components/vendor-results-list.vue.d.ts +20 -0
- package/types/src/x-modules/vendor/components/vendor-results-list.vue.d.ts.map +1 -1
- package/types/src/x-modules/vendor/events.types.d.ts +24 -0
- package/types/src/x-modules/vendor/events.types.d.ts.map +1 -1
- package/types/src/x-modules/vendor/store/emitters.d.ts +11 -1
- package/types/src/x-modules/vendor/store/emitters.d.ts.map +1 -1
- package/types/src/x-modules/vendor/store/module.d.ts +1 -0
- package/types/src/x-modules/vendor/store/module.d.ts.map +1 -1
- package/types/src/x-modules/vendor/store/types.d.ts +42 -0
- package/types/src/x-modules/vendor/store/types.d.ts.map +1 -1
- package/types/src/x-modules/vendor/wiring.d.ts +36 -0
- package/types/src/x-modules/vendor/wiring.d.ts.map +1 -1
- package/vendor/index.js +1 -1
|
@@ -12,10 +12,14 @@ The component provides a default slot which wraps the whole component with the `
|
|
|
12
12
|
plus the `injectedListItems` which also contains the injected list items from
|
|
13
13
|
the ancestor.
|
|
14
14
|
|
|
15
|
+
If the `queryPreviewHash` prop is provided, the vendor banners are retrieved from
|
|
16
|
+
VendorState.queryPreviews, scoped to the query preview.
|
|
17
|
+
|
|
15
18
|
It also provides the parent slots to customize the items.
|
|
16
19
|
|
|
17
20
|
## Props
|
|
18
21
|
|
|
19
|
-
| Name
|
|
20
|
-
|
|
|
21
|
-
| <code>animation</code>
|
|
22
|
+
| Name | Description | Type | Default |
|
|
23
|
+
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------------------- |
|
|
24
|
+
| <code>animation</code> | Animation component that will be used to animate the vendor banners. | <code>AnimationProp</code> | <code>'ul'</code> |
|
|
25
|
+
| <code>queryPreviewHash</code> | The hash of the query preview to render its vendor banners. If not provided,<br />the vendor banners from the root state are rendered. | <code>string</code> | <code>undefined</code> |
|
|
@@ -12,10 +12,14 @@ The component provides a default slot which wraps the whole component with the `
|
|
|
12
12
|
plus the `injectedListItems` which also contains the injected list items from
|
|
13
13
|
the ancestor.
|
|
14
14
|
|
|
15
|
+
If the `queryPreviewHash` prop is provided, the vendor results are retrieved from
|
|
16
|
+
VendorState.queryPreviews, scoped to the query preview.
|
|
17
|
+
|
|
15
18
|
It also provides the parent slots to customize the items.
|
|
16
19
|
|
|
17
20
|
## Props
|
|
18
21
|
|
|
19
|
-
| Name
|
|
20
|
-
|
|
|
21
|
-
| <code>animation</code>
|
|
22
|
+
| Name | Description | Type | Default |
|
|
23
|
+
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------------------- |
|
|
24
|
+
| <code>animation</code> | Animation component that will be used to animate the vendor results. | <code>AnimationProp</code> | <code>'ul'</code> |
|
|
25
|
+
| <code>queryPreviewHash</code> | The hash of the query preview to render its vendor results. If not provided,<br />the vendor results from the root state are rendered. | <code>string</code> | <code>undefined</code> |
|
|
@@ -14,7 +14,7 @@ const _hoisted_1 = {
|
|
|
14
14
|
|
|
15
15
|
function _sfc_render(_ctx, _cache) {
|
|
16
16
|
return (openBlock(), createElementBlock("svg", _hoisted_1, [...(_cache[0] || (_cache[0] = [
|
|
17
|
-
createStaticVNode("<g transform=\"translate(150, 150)\"><polygon points=\"0,-100 21.213,-21.213 100,0 21.213,21.213 0,100 -21.213,21.213 -100,0 -21.213,-21.213\" fill=\"
|
|
17
|
+
createStaticVNode("<g transform=\"translate(150, 150)\"><polygon points=\"0,-100 21.213,-21.213 100,0 21.213,21.213 0,100 -21.213,21.213 -100,0 -21.213,-21.213\" fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\"10\" stroke-linejoin=\"round\"><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"scale\" values=\"0;1;1;0\" keyTimes=\"0;0.2;0.8;1\" calcMode=\"linear\" dur=\"2.5s\" repeatCount=\"indefinite\" additive=\"sum\"></animateTransform><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"rotate\" values=\"0;180;180;360\" keyTimes=\"0;0.2;0.8;1\" calcMode=\"linear\" dur=\"2.5s\" repeatCount=\"indefinite\" additive=\"sum\"></animateTransform></polygon><ellipse id=\"e4kx3Cn5VZF3\" cx=\"70\" cy=\"-70\" rx=\"27.5\" ry=\"27.5\" fill=\"currentColor\" stroke-width=\"0\"><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"scale\" values=\"0;1;1;0\" keyTimes=\"0;0.2;0.80;1\" dur=\"2.5s\" begin=\"0.1s\" repeatCount=\"indefinite\" additive=\"sum\"></animateTransform><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"translate\" values=\"-60,00;0,0;0,0;-60,-70\" keyTimes=\"0;0.2;0.80;1\" calcMode=\"linear\" dur=\"2.5s\" begin=\"0.1s\" repeatCount=\"indefinite\" additive=\"sum\"></animateTransform></ellipse></g>", 1)
|
|
18
18
|
]))]))
|
|
19
19
|
}
|
|
20
20
|
var aiSpinnerIcon = /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render]]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-spinner-icon.vue.js","sources":["../../../../src/components/icons/ai-spinner-icon.vue"],"sourcesContent":["<template>\n <svg\n id=\"e4kx3Cn5VZF1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n viewBox=\"0 0 300 300\"\n shape-rendering=\"geometricPrecision\"\n text-rendering=\"geometricPrecision\"\n >\n <g transform=\"translate(150, 150)\">\n <polygon\n points=\"0,-100 21.213,-21.213 100,0 21.213,21.213 0,100 -21.213,21.213 -100,0 -21.213,-21.213\"\n fill=\"
|
|
1
|
+
{"version":3,"file":"ai-spinner-icon.vue.js","sources":["../../../../src/components/icons/ai-spinner-icon.vue"],"sourcesContent":["<template>\n <svg\n id=\"e4kx3Cn5VZF1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n viewBox=\"0 0 300 300\"\n shape-rendering=\"geometricPrecision\"\n text-rendering=\"geometricPrecision\"\n >\n <g transform=\"translate(150, 150)\">\n <polygon\n points=\"0,-100 21.213,-21.213 100,0 21.213,21.213 0,100 -21.213,21.213 -100,0 -21.213,-21.213\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"10\"\n stroke-linejoin=\"round\"\n >\n <animateTransform\n attributeName=\"transform\"\n attributeType=\"XML\"\n type=\"scale\"\n values=\"0;1;1;0\"\n keyTimes=\"0;0.2;0.8;1\"\n calcMode=\"linear\"\n dur=\"2.5s\"\n repeatCount=\"indefinite\"\n additive=\"sum\"\n />\n <animateTransform\n attributeName=\"transform\"\n attributeType=\"XML\"\n type=\"rotate\"\n values=\"0;180;180;360\"\n keyTimes=\"0;0.2;0.8;1\"\n calcMode=\"linear\"\n dur=\"2.5s\"\n repeatCount=\"indefinite\"\n additive=\"sum\"\n />\n </polygon>\n <ellipse\n id=\"e4kx3Cn5VZF3\"\n cx=\"70\"\n cy=\"-70\"\n rx=\"27.5\"\n ry=\"27.5\"\n fill=\"currentColor\"\n stroke-width=\"0\"\n >\n <animateTransform\n attributeName=\"transform\"\n attributeType=\"XML\"\n type=\"scale\"\n values=\"0;1;1;0\"\n keyTimes=\"0;0.2;0.80;1\"\n dur=\"2.5s\"\n begin=\"0.1s\"\n repeatCount=\"indefinite\"\n additive=\"sum\"\n />\n <animateTransform\n attributeName=\"transform\"\n attributeType=\"XML\"\n type=\"translate\"\n values=\"-60,00;0,0;0,0;-60,-70\"\n keyTimes=\"0;0.2;0.80;1\"\n calcMode=\"linear\"\n dur=\"2.5s\"\n begin=\"0.1s\"\n repeatCount=\"indefinite\"\n additive=\"sum\"\n />\n </ellipse>\n </g>\n </svg>\n</template>\n"],"names":["_openBlock","_createElementBlock"],"mappings":";;;;;;AAEI,EAAA,EAAE,EAAC,cAAc;AACjB,EAAA,KAAK,EAAC,4BAA4B;AAClC,EAAA,aAAW,EAAC,8BAA8B;AAC1C,EAAA,OAAO,EAAC,aAAa;AACrB,EAAA,iBAAe,EAAC,oBAAoB;AACpC,EAAA,gBAAc,EAAC;;;;AANjB,EAAA,QAAAA,SAAA,EAAA,EAAAC,kBAAA,CAyEM,OAzEN,UAyEM,EAAA,CAAA,IAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA;;;;;;;;"}
|
package/js/index.js
CHANGED
|
@@ -462,6 +462,6 @@ export { default as VendorBannersList } from './x-modules/vendor/components/vend
|
|
|
462
462
|
export { default as VendorResultsList } from './x-modules/vendor/components/vendor-results-list.vue.js';
|
|
463
463
|
export { vendorEmitters } from './x-modules/vendor/store/emitters.js';
|
|
464
464
|
export { resettableVendorState, vendorXStoreModule } from './x-modules/vendor/store/module.js';
|
|
465
|
-
export { setBanners, setResults, vendorWiring } from './x-modules/vendor/wiring.js';
|
|
465
|
+
export { setBanners, setQueryPreviewVendorBanners, setQueryPreviewVendorResults, setResults, vendorWiring } from './x-modules/vendor/wiring.js';
|
|
466
466
|
export { vendorXModule } from './x-modules/vendor/x-module.js';
|
|
467
467
|
//# sourceMappingURL=index.js.map
|
|
@@ -3,6 +3,7 @@ import { resolveComponent, openBlock, createBlock, resolveDynamicComponent, with
|
|
|
3
3
|
import './query-preview-list.vue3.js';
|
|
4
4
|
import _export_sfc from '../../../_virtual/_plugin-vue_export-helper.js';
|
|
5
5
|
|
|
6
|
+
const _hoisted_1 = ["data-query-preview-hash"];
|
|
6
7
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7
8
|
const _component_QueryPreview = resolveComponent("QueryPreview");
|
|
8
9
|
return openBlock(), createBlock(resolveDynamicComponent(_ctx.animation), {
|
|
@@ -14,40 +15,35 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
14
15
|
Fragment,
|
|
15
16
|
null,
|
|
16
17
|
renderList(_ctx.renderedQueryPreviews, (queryPreview, index) => {
|
|
17
|
-
return openBlock(), createElementBlock(
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
]), 1032, ["debounce-time-ms", "load-when-visible", "max-items-to-render", "persist-in-cache", "query-feature", "query-preview-info", "onLoad", "onError"])
|
|
47
|
-
],
|
|
48
|
-
2
|
|
49
|
-
/* CLASS */
|
|
50
|
-
);
|
|
18
|
+
return openBlock(), createElementBlock("li", {
|
|
19
|
+
key: index,
|
|
20
|
+
class: normalizeClass({ "padding-block-1": _ctx.loadWhenVisible }),
|
|
21
|
+
"data-query-preview-hash": _ctx.getHashFromQueryPreviewInfo(queryPreview, { ..._ctx.params, ...queryPreview.extraParams }),
|
|
22
|
+
"data-test": "query-preview-item"
|
|
23
|
+
}, [
|
|
24
|
+
createVNode(_component_QueryPreview, {
|
|
25
|
+
"debounce-time-ms": _ctx.debounceTimeMs,
|
|
26
|
+
"load-when-visible": _ctx.loadWhenVisible,
|
|
27
|
+
"max-items-to-render": _ctx.maxItemsToRender,
|
|
28
|
+
"persist-in-cache": _ctx.persistInCache,
|
|
29
|
+
"query-feature": _ctx.queryFeature,
|
|
30
|
+
"query-preview-info": queryPreview,
|
|
31
|
+
onLoad: _ctx.flagAsLoaded,
|
|
32
|
+
onError: _ctx.flagAsFailed
|
|
33
|
+
}, createSlots({
|
|
34
|
+
_: 2
|
|
35
|
+
/* DYNAMIC */
|
|
36
|
+
}, [
|
|
37
|
+
renderList(_ctx.$slots, (_, slotName) => {
|
|
38
|
+
return {
|
|
39
|
+
name: slotName,
|
|
40
|
+
fn: withCtx((scope) => [
|
|
41
|
+
renderSlot(_ctx.$slots, slotName, mergeProps({ ref_for: true }, scope), void 0, true)
|
|
42
|
+
])
|
|
43
|
+
};
|
|
44
|
+
})
|
|
45
|
+
]), 1032, ["debounce-time-ms", "load-when-visible", "max-items-to-render", "persist-in-cache", "query-feature", "query-preview-info", "onLoad", "onError"])
|
|
46
|
+
], 10, _hoisted_1);
|
|
51
47
|
}),
|
|
52
48
|
128
|
|
53
49
|
/* KEYED_FRAGMENT */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-preview-list.vue.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview-list.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" class=\"x-query-preview-list\" tag=\"ul\">\n <li\n v-for=\"(queryPreview, index) in renderedQueryPreviews\"\n :key=\"index\"\n :class=\"{ 'padding-block-1': loadWhenVisible }\"\n data-test=\"query-preview-item\"\n >\n <QueryPreview\n :debounce-time-ms=\"debounceTimeMs\"\n :load-when-visible=\"loadWhenVisible\"\n :max-items-to-render=\"maxItemsToRender\"\n :persist-in-cache=\"persistInCache\"\n :query-feature=\"queryFeature\"\n :query-preview-info=\"queryPreview\"\n @load=\"flagAsLoaded\"\n @error=\"flagAsFailed\"\n >\n <template v-for=\"(_, slotName) in $slots\" #[slotName]=\"scope\">\n <slot :name=\"slotName\" v-bind=\"scope\" />\n </template>\n </QueryPreview>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { RequestStatus } from '../../../store'\nimport type { QueryFeature } from '../../../types'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { useState } from '../../../composables/index'\nimport { AnimationProp } from '../../../types'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\nimport QueryPreview from './query-preview.vue'\n\ninterface QueryPreviewStatusRecord {\n [query: string]: RequestStatus\n}\n\n/**\n * Renders the results previews of a list of objects with the information about the query preview,\n * and exposes the {@link QueryPreview} slots to modify the content.\n * The requests are made in sequential order.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreviewList',\n xModule: queriesPreviewXModule.name,\n components: { QueryPreview },\n props: {\n /**\n * The list of queries preview to render.\n *\n * @public\n */\n queriesPreviewInfo: {\n type: Array as PropType<QueryPreviewInfo[]>,\n required: true,\n },\n /**\n * The origin property for the request on each query preview.\n *\n * @public\n */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /**\n * Number of query preview results to be rendered on each query preview.\n *\n * @public\n */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n *\n * @public\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests\n * on each query preview.\n *\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether all the QueryPreview should be removed from the state\n * when the component is destroyed.\n *\n * @public\n */\n persistInCache: Boolean,\n /**\n * Animation component that will be used to animate the elements.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul',\n },\n },\n setup(props) {\n const { params } = useState('queriesPreview')\n\n /**\n * Contains the status of the preview requests, indexed by query.\n */\n const queriesStatus = ref<QueryPreviewStatusRecord>({})\n\n /**\n * The list of queries to preview.\n *\n * @returns The list of queries in the queriesPreviewInfo list.\n * @internal\n */\n const queries = computed((): string[] =>\n props.queriesPreviewInfo.map(item =>\n getHashFromQueryPreviewInfo(item, { ...params.value, ...item.extraParams }),\n ),\n )\n\n /**\n * Gets all the queries to render, that are those that don't have an `error` status.\n *\n * @returns A list of queries.\n * @internal\n */\n const renderedQueryPreviews = computed((): QueryPreviewInfo[] => {\n return props.queriesPreviewInfo.filter(item => {\n const queryPreviewHash = getHashFromQueryPreviewInfo(item, {\n ...params.value,\n ...item.extraParams,\n })\n return (\n queriesStatus.value[queryPreviewHash] === 'success' ||\n queriesStatus.value[queryPreviewHash] === 'loading'\n )\n })\n })\n\n /**\n * Tries to load the next query.\n *\n * @internal\n */\n const loadNext = (): void => {\n const queryToLoad = queries.value.find(query => !(query in queriesStatus.value))\n if (queryToLoad) {\n queriesStatus.value[queryToLoad] = 'loading'\n }\n }\n\n /**\n * Resets the status of all queries if they change.\n *\n * @param newQueries - The new queries.\n * @param oldQueries - The old queries.\n * @internal\n */\n watch(\n queries,\n (newQueries: string[], oldQueries: string[] | undefined) => {\n if (newQueries.toString() !== oldQueries?.toString()) {\n for (const key of Object.keys(queriesStatus.value)) {\n if (!newQueries.includes(key)) {\n delete queriesStatus.value[key]\n }\n }\n loadNext()\n }\n },\n { immediate: true, deep: true },\n )\n\n /**\n * Sets the status of a given query to `success`.\n *\n * @param loadedQuery - The query to flag as loaded.\n * @internal\n */\n const flagAsLoaded = (loadedQuery: string): void => {\n queriesStatus.value[loadedQuery] = 'success'\n loadNext()\n }\n\n /**\n * Sets the status of a given query to `error`.\n *\n * @param failedQuery - The query to flag as failed.\n * @internal\n */\n const flagAsFailed = (failedQuery: string): void => {\n queriesStatus.value[failedQuery] = 'error'\n loadNext()\n }\n\n return {\n renderedQueryPreviews,\n flagAsFailed,\n flagAsLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.padding-block-1 {\n padding-block: 1px;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\nHere you have a basic example of how the QueryPreviewList is rendered. Keep in mind that this\ncomponent is intended to be used overriding its default slot. By default it will only render the\nnames of the results.\n\n```vue live\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreviewList\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #default=\"{ queryPreviewInfo, totalResults, results }\"\n >\n <div class=\"x-flex x-flex-col x-gap-8 x-mb-16\">\n <h1 class=\"x-title2\">{{ queryPreviewInfo.query }} ({{ totalResults }})</h1>\n <SlidingPanel :resetOnContentChange=\"false\">\n <div class=\"x-flex x-gap-8\">\n <Result\n v-for=\"result in results\"\n :key=\"result.id\"\n :result=\"result\"\n style=\"max-width: 180px\"\n />\n </div>\n </SlidingPanel>\n </div>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport SlidingPanel from '@empathyco/x-components/sliding-panel.vue'\nimport Result from '@empathyco/x-components/result.vue'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreviewList\n class=\"x-flex x-gap-8\"\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #result=\"{ result }\"\n >\n <span class=\"x-font-bold\">{{ result.id }}:</span>\n <span>{{ result.name }}</span>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createBlock","_resolveDynamicComponent","_createElementBlock","_Fragment","_renderList","_normalizeClass","_createVNode","_createSlots","_withCtx","_renderSlot","_mergeProps"],"mappings":";;;;;;;AACE,EAAA,OAAAA,SAAA,EAAA,EAAAC,WAAA,CAsBYC,wBAtBI,IAAA,CAAA,SAAS,CAAA,EAAA;AAAA,IAAE,KAAA,EAAM,sBAAA;AAAA,IAAuB,GAAA,EAAI;AAAA,GAAA,EAAA;qBAExD,MAAsD;AAAA,OAAAF,SAAA,CAAA,IAAA,CAAA,EADxDG,kBAAA;AAAA,QAoBKC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAnB6B,IAAA,CAAA,qBAAA,EAAqB,CAA7C,YAAA,EAAc,KAAA,KAAK;AAD7B,UAAA,OAAAL,SAAA,EAAA,EAAAG,kBAAA;AAAA,YAoBK,IAAA;AAAA,YAAA;AAAA,cAlBF,GAAA,EAAK,KAAA;AAAA,cACL,KAAA,EAAKG,oCAAuB,IAAA,CAAA,eAAA,EAAe,CAAA;AAAA,cAC5C,WAAA,EAAU;AAAA,aAAA;;cAEVC,WAAA,CAae,uBAAA,EAAA;AAAA,gBAZZ,kBAAA,EAAkB,IAAA,CAAA,cAAA;AAAA,gBAClB,mBAAA,EAAmB,IAAA,CAAA,eAAA;AAAA,gBACnB,qBAAA,EAAqB,IAAA,CAAA,gBAAA;AAAA,gBACrB,kBAAA,EAAkB,IAAA,CAAA,cAAA;AAAA,gBAClB,eAAA,EAAe,IAAA,CAAA,YAAA;AAAA,gBACf,oBAAA,EAAoB,YAAA;AAAA,gBACpB,MAAA,EAAM,IAAA,CAAA,YAAA;AAAA,gBACN,OAAA,EAAO,IAAA,CAAA;AAAA,eAAA,EAAAC,WAAA,CAAA;;;;2BAE0B,IAAA,CAAA,MAAA,EAAM,CAAtB,GAAG,QAAA,KAAQ;;AAAc,oBAAA,IAAA,EAAA,QAAA;AAAA,oBAAA,EAAA,EAAAC,OAAA,CACzC,CAAwC,KAAA,KADkB;AAAA,sBAC1DC,UAAA,CAAwC,IAAA,CAAA,MAAA,EAA3B,QAAA,EAAbC,UAAA,CAAwC,mBAAT,KAAK,CAAA,EAAA,MAAA,EAAA,IAAA;AAAA,qBAAA;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"query-preview-list.vue.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview-list.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" class=\"x-query-preview-list\" tag=\"ul\">\n <li\n v-for=\"(queryPreview, index) in renderedQueryPreviews\"\n :key=\"index\"\n :class=\"{ 'padding-block-1': loadWhenVisible }\"\n :data-query-preview-hash=\"\n getHashFromQueryPreviewInfo(queryPreview, { ...params, ...queryPreview.extraParams })\n \"\n data-test=\"query-preview-item\"\n >\n <QueryPreview\n :debounce-time-ms=\"debounceTimeMs\"\n :load-when-visible=\"loadWhenVisible\"\n :max-items-to-render=\"maxItemsToRender\"\n :persist-in-cache=\"persistInCache\"\n :query-feature=\"queryFeature\"\n :query-preview-info=\"queryPreview\"\n @load=\"flagAsLoaded\"\n @error=\"flagAsFailed\"\n >\n <template v-for=\"(_, slotName) in $slots\" #[slotName]=\"scope\">\n <slot :name=\"slotName\" v-bind=\"scope\" />\n </template>\n </QueryPreview>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { RequestStatus } from '../../../store'\nimport type { QueryFeature } from '../../../types'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { useState } from '../../../composables/index'\nimport { AnimationProp } from '../../../types'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\nimport QueryPreview from './query-preview.vue'\n\ninterface QueryPreviewStatusRecord {\n [query: string]: RequestStatus\n}\n\n/**\n * Renders the results previews of a list of objects with the information about the query preview,\n * and exposes the {@link QueryPreview} slots to modify the content.\n * The requests are made in sequential order.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreviewList',\n xModule: queriesPreviewXModule.name,\n components: { QueryPreview },\n props: {\n /**\n * The list of queries preview to render.\n *\n * @public\n */\n queriesPreviewInfo: {\n type: Array as PropType<QueryPreviewInfo[]>,\n required: true,\n },\n /**\n * The origin property for the request on each query preview.\n *\n * @public\n */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /**\n * Number of query preview results to be rendered on each query preview.\n *\n * @public\n */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n *\n * @public\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests\n * on each query preview.\n *\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether all the QueryPreview should be removed from the state\n * when the component is destroyed.\n *\n * @public\n */\n persistInCache: Boolean,\n /**\n * Animation component that will be used to animate the elements.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul',\n },\n },\n setup(props) {\n const { params } = useState('queriesPreview')\n\n /**\n * Contains the status of the preview requests, indexed by query.\n */\n const queriesStatus = ref<QueryPreviewStatusRecord>({})\n\n /**\n * The list of queries to preview.\n *\n * @returns The list of queries in the queriesPreviewInfo list.\n * @internal\n */\n const queries = computed((): string[] =>\n props.queriesPreviewInfo.map(item =>\n getHashFromQueryPreviewInfo(item, { ...params.value, ...item.extraParams }),\n ),\n )\n\n /**\n * Gets all the queries to render, that are those that don't have an `error` status.\n *\n * @returns A list of queries.\n * @internal\n */\n const renderedQueryPreviews = computed((): QueryPreviewInfo[] => {\n return props.queriesPreviewInfo.filter(item => {\n const queryPreviewHash = getHashFromQueryPreviewInfo(item, {\n ...params.value,\n ...item.extraParams,\n })\n return (\n queriesStatus.value[queryPreviewHash] === 'success' ||\n queriesStatus.value[queryPreviewHash] === 'loading'\n )\n })\n })\n\n /**\n * Tries to load the next query.\n *\n * @internal\n */\n const loadNext = (): void => {\n const queryToLoad = queries.value.find(query => !(query in queriesStatus.value))\n if (queryToLoad) {\n queriesStatus.value[queryToLoad] = 'loading'\n }\n }\n\n /**\n * Resets the status of all queries if they change.\n *\n * @param newQueries - The new queries.\n * @param oldQueries - The old queries.\n * @internal\n */\n watch(\n queries,\n (newQueries: string[], oldQueries: string[] | undefined) => {\n if (newQueries.toString() !== oldQueries?.toString()) {\n for (const key of Object.keys(queriesStatus.value)) {\n if (!newQueries.includes(key)) {\n delete queriesStatus.value[key]\n }\n }\n loadNext()\n }\n },\n { immediate: true, deep: true },\n )\n\n /**\n * Sets the status of a given query to `success`.\n *\n * @param loadedQuery - The query to flag as loaded.\n * @internal\n */\n const flagAsLoaded = (loadedQuery: string): void => {\n queriesStatus.value[loadedQuery] = 'success'\n loadNext()\n }\n\n /**\n * Sets the status of a given query to `error`.\n *\n * @param failedQuery - The query to flag as failed.\n * @internal\n */\n const flagAsFailed = (failedQuery: string): void => {\n queriesStatus.value[failedQuery] = 'error'\n loadNext()\n }\n\n return {\n params,\n renderedQueryPreviews,\n flagAsFailed,\n flagAsLoaded,\n getHashFromQueryPreviewInfo,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.padding-block-1 {\n padding-block: 1px;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\nHere you have a basic example of how the QueryPreviewList is rendered. Keep in mind that this\ncomponent is intended to be used overriding its default slot. By default it will only render the\nnames of the results.\n\n```vue live\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreviewList\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #default=\"{ queryPreviewInfo, totalResults, results }\"\n >\n <div class=\"x-flex x-flex-col x-gap-8 x-mb-16\">\n <h1 class=\"x-title2\">{{ queryPreviewInfo.query }} ({{ totalResults }})</h1>\n <SlidingPanel :resetOnContentChange=\"false\">\n <div class=\"x-flex x-gap-8\">\n <Result\n v-for=\"result in results\"\n :key=\"result.id\"\n :result=\"result\"\n style=\"max-width: 180px\"\n />\n </div>\n </SlidingPanel>\n </div>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport SlidingPanel from '@empathyco/x-components/sliding-panel.vue'\nimport Result from '@empathyco/x-components/result.vue'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreviewList\n class=\"x-flex x-gap-8\"\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #result=\"{ result }\"\n >\n <span class=\"x-font-bold\">{{ result.id }}:</span>\n <span>{{ result.name }}</span>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with vendor results and vendor banners\n\nThe `VendorResultsList` and `VendorBannersList` components can be used inside the default slot of\nthe `QueryPreviewList`, so the vendor results and vendor banners provided for each query are\ninserted within its results. The order of the nested components defines the merge strategy.\n\n```vue\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" #default=\"{ queryPreviewHash }\">\n <VendorResultsList :queryPreviewHash=\"queryPreviewHash\">\n <VendorBannersList :queryPreviewHash=\"queryPreviewHash\">\n <BaseGrid>\n <template #result=\"{ item }\">\n <span>Result: {{ item.id }}</span>\n </template>\n <template #vendor-result=\"{ item }\">\n <span>Vendor result: {{ item.id }}</span>\n </template>\n <template #vendor-banner=\"{ item }\">\n <span>Vendor banner: {{ item.id }}</span>\n </template>\n </BaseGrid>\n </VendorBannersList>\n </VendorResultsList>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { BaseGrid } from '@empathyco/x-components'\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { VendorBannersList, VendorResultsList } from '@empathyco/x-components/vendor'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createBlock","_resolveDynamicComponent","_createElementBlock","_Fragment","_renderList","_normalizeClass","_createVNode","_createSlots","_withCtx","_renderSlot","_mergeProps"],"mappings":";;;;;;;;AACE,EAAA,OAAAA,SAAA,EAAA,EAAAC,WAAA,CAyBYC,wBAzBI,IAAA,CAAA,SAAS,CAAA,EAAA;AAAA,IAAE,KAAA,EAAM,sBAAA;AAAA,IAAuB,GAAA,EAAI;AAAA,GAAA,EAAA;qBAExD,MAAsD;AAAA,OAAAF,SAAA,CAAA,IAAA,CAAA,EADxDG,kBAAA;AAAA,QAuBKC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAtB6B,IAAA,CAAA,qBAAA,EAAqB,CAA7C,YAAA,EAAc,KAAA,KAAK;8BAD7BF,kBAAA,CAuBK,IAAA,EAAA;AAAA,YArBF,GAAA,EAAK,KAAA;AAAA,YACL,KAAA,EAAKG,oCAAuB,IAAA,CAAA,eAAA,EAAe,CAAA;AAAA,YAC3C,2BAAkC,IAAA,CAAA,2BAAA,CAA4B,YAAA,EAAY,KAAO,IAAA,CAAA,MAAA,EAAM,GAAK,aAAa,WAAA,EAAW,CAAA;AAAA,YAGrH,WAAA,EAAU;AAAA,WAAA,EAAA;YAEVC,WAAA,CAae,uBAAA,EAAA;AAAA,cAZZ,kBAAA,EAAkB,IAAA,CAAA,cAAA;AAAA,cAClB,mBAAA,EAAmB,IAAA,CAAA,eAAA;AAAA,cACnB,qBAAA,EAAqB,IAAA,CAAA,gBAAA;AAAA,cACrB,kBAAA,EAAkB,IAAA,CAAA,cAAA;AAAA,cAClB,eAAA,EAAe,IAAA,CAAA,YAAA;AAAA,cACf,oBAAA,EAAoB,YAAA;AAAA,cACpB,MAAA,EAAM,IAAA,CAAA,YAAA;AAAA,cACN,OAAA,EAAO,IAAA,CAAA;AAAA,aAAA,EAAAC,WAAA,CAAA;;;;yBAE0B,IAAA,CAAA,MAAA,EAAM,CAAtB,GAAG,QAAA,KAAQ;;AAAc,kBAAA,IAAA,EAAA,QAAA;AAAA,kBAAA,EAAA,EAAAC,OAAA,CACzC,CAAwC,KAAA,KADkB;AAAA,oBAC1DC,UAAA,CAAwC,IAAA,CAAA,MAAA,EAA3B,QAAA,EAAbC,UAAA,CAAwC,mBAAT,KAAK,CAAA,EAAA,MAAA,EAAA,IAAA;AAAA,mBAAA;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-preview-list.vue2.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview-list.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" class=\"x-query-preview-list\" tag=\"ul\">\n <li\n v-for=\"(queryPreview, index) in renderedQueryPreviews\"\n :key=\"index\"\n :class=\"{ 'padding-block-1': loadWhenVisible }\"\n data-test=\"query-preview-item\"\n >\n <QueryPreview\n :debounce-time-ms=\"debounceTimeMs\"\n :load-when-visible=\"loadWhenVisible\"\n :max-items-to-render=\"maxItemsToRender\"\n :persist-in-cache=\"persistInCache\"\n :query-feature=\"queryFeature\"\n :query-preview-info=\"queryPreview\"\n @load=\"flagAsLoaded\"\n @error=\"flagAsFailed\"\n >\n <template v-for=\"(_, slotName) in $slots\" #[slotName]=\"scope\">\n <slot :name=\"slotName\" v-bind=\"scope\" />\n </template>\n </QueryPreview>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { RequestStatus } from '../../../store'\nimport type { QueryFeature } from '../../../types'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { useState } from '../../../composables/index'\nimport { AnimationProp } from '../../../types'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\nimport QueryPreview from './query-preview.vue'\n\ninterface QueryPreviewStatusRecord {\n [query: string]: RequestStatus\n}\n\n/**\n * Renders the results previews of a list of objects with the information about the query preview,\n * and exposes the {@link QueryPreview} slots to modify the content.\n * The requests are made in sequential order.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreviewList',\n xModule: queriesPreviewXModule.name,\n components: { QueryPreview },\n props: {\n /**\n * The list of queries preview to render.\n *\n * @public\n */\n queriesPreviewInfo: {\n type: Array as PropType<QueryPreviewInfo[]>,\n required: true,\n },\n /**\n * The origin property for the request on each query preview.\n *\n * @public\n */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /**\n * Number of query preview results to be rendered on each query preview.\n *\n * @public\n */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n *\n * @public\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests\n * on each query preview.\n *\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether all the QueryPreview should be removed from the state\n * when the component is destroyed.\n *\n * @public\n */\n persistInCache: Boolean,\n /**\n * Animation component that will be used to animate the elements.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul',\n },\n },\n setup(props) {\n const { params } = useState('queriesPreview')\n\n /**\n * Contains the status of the preview requests, indexed by query.\n */\n const queriesStatus = ref<QueryPreviewStatusRecord>({})\n\n /**\n * The list of queries to preview.\n *\n * @returns The list of queries in the queriesPreviewInfo list.\n * @internal\n */\n const queries = computed((): string[] =>\n props.queriesPreviewInfo.map(item =>\n getHashFromQueryPreviewInfo(item, { ...params.value, ...item.extraParams }),\n ),\n )\n\n /**\n * Gets all the queries to render, that are those that don't have an `error` status.\n *\n * @returns A list of queries.\n * @internal\n */\n const renderedQueryPreviews = computed((): QueryPreviewInfo[] => {\n return props.queriesPreviewInfo.filter(item => {\n const queryPreviewHash = getHashFromQueryPreviewInfo(item, {\n ...params.value,\n ...item.extraParams,\n })\n return (\n queriesStatus.value[queryPreviewHash] === 'success' ||\n queriesStatus.value[queryPreviewHash] === 'loading'\n )\n })\n })\n\n /**\n * Tries to load the next query.\n *\n * @internal\n */\n const loadNext = (): void => {\n const queryToLoad = queries.value.find(query => !(query in queriesStatus.value))\n if (queryToLoad) {\n queriesStatus.value[queryToLoad] = 'loading'\n }\n }\n\n /**\n * Resets the status of all queries if they change.\n *\n * @param newQueries - The new queries.\n * @param oldQueries - The old queries.\n * @internal\n */\n watch(\n queries,\n (newQueries: string[], oldQueries: string[] | undefined) => {\n if (newQueries.toString() !== oldQueries?.toString()) {\n for (const key of Object.keys(queriesStatus.value)) {\n if (!newQueries.includes(key)) {\n delete queriesStatus.value[key]\n }\n }\n loadNext()\n }\n },\n { immediate: true, deep: true },\n )\n\n /**\n * Sets the status of a given query to `success`.\n *\n * @param loadedQuery - The query to flag as loaded.\n * @internal\n */\n const flagAsLoaded = (loadedQuery: string): void => {\n queriesStatus.value[loadedQuery] = 'success'\n loadNext()\n }\n\n /**\n * Sets the status of a given query to `error`.\n *\n * @param failedQuery - The query to flag as failed.\n * @internal\n */\n const flagAsFailed = (failedQuery: string): void => {\n queriesStatus.value[failedQuery] = 'error'\n loadNext()\n }\n\n return {\n renderedQueryPreviews,\n flagAsFailed,\n flagAsLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.padding-block-1 {\n padding-block: 1px;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\nHere you have a basic example of how the QueryPreviewList is rendered. Keep in mind that this\ncomponent is intended to be used overriding its default slot. By default it will only render the\nnames of the results.\n\n```vue live\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreviewList\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #default=\"{ queryPreviewInfo, totalResults, results }\"\n >\n <div class=\"x-flex x-flex-col x-gap-8 x-mb-16\">\n <h1 class=\"x-title2\">{{ queryPreviewInfo.query }} ({{ totalResults }})</h1>\n <SlidingPanel :resetOnContentChange=\"false\">\n <div class=\"x-flex x-gap-8\">\n <Result\n v-for=\"result in results\"\n :key=\"result.id\"\n :result=\"result\"\n style=\"max-width: 180px\"\n />\n </div>\n </SlidingPanel>\n </div>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport SlidingPanel from '@empathyco/x-components/sliding-panel.vue'\nimport Result from '@empathyco/x-components/result.vue'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreviewList\n class=\"x-flex x-gap-8\"\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #result=\"{ result }\"\n >\n <span class=\"x-font-bold\">{{ result.id }}:</span>\n <span>{{ result.name }}</span>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n</docs>\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-preview-list.vue2.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview-list.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" class=\"x-query-preview-list\" tag=\"ul\">\n <li\n v-for=\"(queryPreview, index) in renderedQueryPreviews\"\n :key=\"index\"\n :class=\"{ 'padding-block-1': loadWhenVisible }\"\n :data-query-preview-hash=\"\n getHashFromQueryPreviewInfo(queryPreview, { ...params, ...queryPreview.extraParams })\n \"\n data-test=\"query-preview-item\"\n >\n <QueryPreview\n :debounce-time-ms=\"debounceTimeMs\"\n :load-when-visible=\"loadWhenVisible\"\n :max-items-to-render=\"maxItemsToRender\"\n :persist-in-cache=\"persistInCache\"\n :query-feature=\"queryFeature\"\n :query-preview-info=\"queryPreview\"\n @load=\"flagAsLoaded\"\n @error=\"flagAsFailed\"\n >\n <template v-for=\"(_, slotName) in $slots\" #[slotName]=\"scope\">\n <slot :name=\"slotName\" v-bind=\"scope\" />\n </template>\n </QueryPreview>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { RequestStatus } from '../../../store'\nimport type { QueryFeature } from '../../../types'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { useState } from '../../../composables/index'\nimport { AnimationProp } from '../../../types'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\nimport QueryPreview from './query-preview.vue'\n\ninterface QueryPreviewStatusRecord {\n [query: string]: RequestStatus\n}\n\n/**\n * Renders the results previews of a list of objects with the information about the query preview,\n * and exposes the {@link QueryPreview} slots to modify the content.\n * The requests are made in sequential order.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreviewList',\n xModule: queriesPreviewXModule.name,\n components: { QueryPreview },\n props: {\n /**\n * The list of queries preview to render.\n *\n * @public\n */\n queriesPreviewInfo: {\n type: Array as PropType<QueryPreviewInfo[]>,\n required: true,\n },\n /**\n * The origin property for the request on each query preview.\n *\n * @public\n */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /**\n * Number of query preview results to be rendered on each query preview.\n *\n * @public\n */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n *\n * @public\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests\n * on each query preview.\n *\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether all the QueryPreview should be removed from the state\n * when the component is destroyed.\n *\n * @public\n */\n persistInCache: Boolean,\n /**\n * Animation component that will be used to animate the elements.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul',\n },\n },\n setup(props) {\n const { params } = useState('queriesPreview')\n\n /**\n * Contains the status of the preview requests, indexed by query.\n */\n const queriesStatus = ref<QueryPreviewStatusRecord>({})\n\n /**\n * The list of queries to preview.\n *\n * @returns The list of queries in the queriesPreviewInfo list.\n * @internal\n */\n const queries = computed((): string[] =>\n props.queriesPreviewInfo.map(item =>\n getHashFromQueryPreviewInfo(item, { ...params.value, ...item.extraParams }),\n ),\n )\n\n /**\n * Gets all the queries to render, that are those that don't have an `error` status.\n *\n * @returns A list of queries.\n * @internal\n */\n const renderedQueryPreviews = computed((): QueryPreviewInfo[] => {\n return props.queriesPreviewInfo.filter(item => {\n const queryPreviewHash = getHashFromQueryPreviewInfo(item, {\n ...params.value,\n ...item.extraParams,\n })\n return (\n queriesStatus.value[queryPreviewHash] === 'success' ||\n queriesStatus.value[queryPreviewHash] === 'loading'\n )\n })\n })\n\n /**\n * Tries to load the next query.\n *\n * @internal\n */\n const loadNext = (): void => {\n const queryToLoad = queries.value.find(query => !(query in queriesStatus.value))\n if (queryToLoad) {\n queriesStatus.value[queryToLoad] = 'loading'\n }\n }\n\n /**\n * Resets the status of all queries if they change.\n *\n * @param newQueries - The new queries.\n * @param oldQueries - The old queries.\n * @internal\n */\n watch(\n queries,\n (newQueries: string[], oldQueries: string[] | undefined) => {\n if (newQueries.toString() !== oldQueries?.toString()) {\n for (const key of Object.keys(queriesStatus.value)) {\n if (!newQueries.includes(key)) {\n delete queriesStatus.value[key]\n }\n }\n loadNext()\n }\n },\n { immediate: true, deep: true },\n )\n\n /**\n * Sets the status of a given query to `success`.\n *\n * @param loadedQuery - The query to flag as loaded.\n * @internal\n */\n const flagAsLoaded = (loadedQuery: string): void => {\n queriesStatus.value[loadedQuery] = 'success'\n loadNext()\n }\n\n /**\n * Sets the status of a given query to `error`.\n *\n * @param failedQuery - The query to flag as failed.\n * @internal\n */\n const flagAsFailed = (failedQuery: string): void => {\n queriesStatus.value[failedQuery] = 'error'\n loadNext()\n }\n\n return {\n params,\n renderedQueryPreviews,\n flagAsFailed,\n flagAsLoaded,\n getHashFromQueryPreviewInfo,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.padding-block-1 {\n padding-block: 1px;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\nHere you have a basic example of how the QueryPreviewList is rendered. Keep in mind that this\ncomponent is intended to be used overriding its default slot. By default it will only render the\nnames of the results.\n\n```vue live\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreviewList\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #default=\"{ queryPreviewInfo, totalResults, results }\"\n >\n <div class=\"x-flex x-flex-col x-gap-8 x-mb-16\">\n <h1 class=\"x-title2\">{{ queryPreviewInfo.query }} ({{ totalResults }})</h1>\n <SlidingPanel :resetOnContentChange=\"false\">\n <div class=\"x-flex x-gap-8\">\n <Result\n v-for=\"result in results\"\n :key=\"result.id\"\n :result=\"result\"\n style=\"max-width: 180px\"\n />\n </div>\n </SlidingPanel>\n </div>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport SlidingPanel from '@empathyco/x-components/sliding-panel.vue'\nimport Result from '@empathyco/x-components/result.vue'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreviewList\n class=\"x-flex x-gap-8\"\n :queriesPreviewInfo=\"queriesPreviewInfo\"\n #result=\"{ result }\"\n >\n <span class=\"x-font-bold\">{{ result.id }}:</span>\n <span>{{ result.name }}</span>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n\n### Play with vendor results and vendor banners\n\nThe `VendorResultsList` and `VendorBannersList` components can be used inside the default slot of\nthe `QueryPreviewList`, so the vendor results and vendor banners provided for each query are\ninserted within its results. The order of the nested components defines the merge strategy.\n\n```vue\n<template>\n <QueryPreviewList :queriesPreviewInfo=\"queriesPreviewInfo\" #default=\"{ queryPreviewHash }\">\n <VendorResultsList :queryPreviewHash=\"queryPreviewHash\">\n <VendorBannersList :queryPreviewHash=\"queryPreviewHash\">\n <BaseGrid>\n <template #result=\"{ item }\">\n <span>Result: {{ item.id }}</span>\n </template>\n <template #vendor-result=\"{ item }\">\n <span>Vendor result: {{ item.id }}</span>\n </template>\n <template #vendor-banner=\"{ item }\">\n <span>Vendor banner: {{ item.id }}</span>\n </template>\n </BaseGrid>\n </VendorBannersList>\n </VendorResultsList>\n </QueryPreviewList>\n</template>\n\n<script setup>\nimport { BaseGrid } from '@empathyco/x-components'\nimport { QueryPreviewList } from '@empathyco/x-components/queries-preview'\nimport { VendorBannersList, VendorResultsList } from '@empathyco/x-components/vendor'\nimport { reactive } from 'vue'\nconst queriesPreviewInfo = reactive([\n { query: 'sandals' },\n { query: 'tshirt' },\n { query: 'jacket' },\n])\n</script>\n```\n</docs>\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-preview.vue.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview.vue"],"sourcesContent":["<template>\n <!-- eslint-disable-next-line vue/no-unused-refs -->\n <section ref=\"queryPreviewElement\" class=\"x-query-preview-wrapper__default-content\">\n <ul v-if=\"hasResults\" data-test=\"query-preview\" class=\"x-query-preview\">\n <li\n v-for=\"result in queryPreviewResults?.results\"\n :key=\"result.id\"\n class=\"x-query-preview__item\"\n data-test=\"query-preview-item\"\n >\n <!--\n @slot Query Preview result slot.\n @binding {Result} result - A Query Preview result\n -->\n <slot name=\"result\" :result=\"result\">\n <span data-test=\"result-name\">{{ result.name }}</span>\n </slot>\n </li>\n </ul>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport type { Filter, SearchRequest } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport type { FeatureLocation, QueryFeature } from '../../../types'\nimport type { DebouncedFunction } from '../../../utils'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { deepEqual } from '@empathyco/x-utils'\nimport { computed, defineComponent, h, inject, onBeforeUnmount, provide, ref, watch } from 'vue'\nimport { LIST_ITEMS_KEY } from '../../../components'\nimport { useOnDisplay, useState, useXBus } from '../../../composables'\nimport { createOrigin, createRawFilters, debounceFunction } from '../../../utils'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\n\n/**\n * Retrieves a preview of the results of a query and exposes them in the default slot,\n * along with the query preview and the totalResults of the search request.\n * By default, it renders the names of the results.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreview',\n xModule: queriesPreviewXModule.name,\n props: {\n /** The information about the request of the query preview. */\n queryPreviewInfo: {\n type: Object as PropType<QueryPreviewInfo>,\n required: true,\n },\n /** The origin property for the request. */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /** Number of query preview results to be rendered. */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests.\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether the QueryPreview should be removed from the state\n * when the component is destroyed.\n */\n persistInCache: {\n type: Boolean,\n default: false,\n },\n },\n emits: ['load', 'error'],\n setup(props, { emit, slots }) {\n const xBus = useXBus()\n\n /**\n * previewResults: The results preview of the queries preview cacheable mounted.\n * It is a dictionary, indexed by the query preview query.\n *\n * params: As the request is handled in this component, we need\n * the extra params that will be used in the request.\n *\n * config: As the request is handled in this component, we need\n * the config that will be used in the request.\n */\n const { queriesPreview: previewResults, params, config } = useState('queriesPreview')\n\n /**\n * Template ref for the root element to track visibility.\n */\n const queryPreviewElement = ref<HTMLElement | null>(null)\n\n /**\n * Query Preview key converted into a unique id.\n *\n * @returns The query hash.\n */\n const queryPreviewHash = computed(() =>\n getHashFromQueryPreviewInfo(props.queryPreviewInfo, {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n }),\n )\n\n provide('queryPreviewHash', queryPreviewHash)\n\n /**\n * Gets from the state the results preview of the query preview.\n *\n * @returns The results preview of the actual query preview.\n */\n const queryPreviewResults = computed(() => {\n const resultsPreview = previewResults.value[queryPreviewHash.value]\n return resultsPreview?.results\n ? {\n ...resultsPreview,\n results: resultsPreview.results.slice(0, props.maxItemsToRender),\n }\n : undefined\n })\n\n /**\n * The results to render from the state.\n *\n * @remarks The results list are provided with `items` key. It can be\n * concatenated with list items from components such as `BannersList`, `PromotedsList`,\n * `BaseGrid` or any component that injects the list.\n *\n * @returns A list of results.\n */\n const results = computed(() => queryPreviewResults.value?.results)\n provide(LIST_ITEMS_KEY as string, results)\n\n /**\n * It injects the provided {@link FeatureLocation} of the selected query in the search request.\n *\n * @internal\n */\n const injectedLocation = inject<Ref<FeatureLocation> | FeatureLocation>('location', 'none')\n const location =\n typeof injectedLocation === 'object' && 'value' in injectedLocation\n ? injectedLocation.value\n : injectedLocation\n\n /**\n * The computed request object to be used to retrieve the query preview results.\n *\n * @returns The search request object.\n */\n const queryPreviewRequest = computed<SearchRequest>(() => {\n const origin = createOrigin({\n feature: props.queryFeature,\n location,\n })\n const filters = props.queryPreviewInfo.filters?.reduce(\n (filtersList, filterId) => {\n const facetId = filterId.split(':')[0]\n const rawFilter = createRawFilters([filterId])[0]\n filtersList[facetId] = filtersList[facetId]\n ? filtersList[facetId].concat(rawFilter)\n : [rawFilter]\n\n return filtersList\n },\n {} as Record<string, Filter[]>,\n )\n\n return {\n query: props.queryPreviewInfo.query,\n rows: config.value.maxItemsToRequest,\n extraParams: {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n },\n filters,\n ...(origin && { origin }),\n }\n })\n\n /**\n * The debounce method to trigger the request after the debounceTimeMs defined\n * for cacheable queries.\n *\n * @returns The search request object.\n */\n const emitQueryPreviewRequestUpdated = computed<DebouncedFunction<[SearchRequest]>>(() =>\n debounceFunction(request => {\n xBus.emit('QueryPreviewRequestUpdated', request, { priority: 0, replaceable: false })\n }, props.debounceTimeMs),\n )\n\n /**\n * Initialises watcher to emit debounced requests, and first value for the requests.\n *\n * @internal\n */\n watch(queryPreviewRequest, (newRequest, oldRequest) => {\n if (!deepEqual(newRequest, oldRequest) && !props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(newRequest)\n }\n })\n\n const cachedQueryPreview = previewResults.value[queryPreviewHash.value]\n\n // If the query has been saved it will emit load instead of the emitting the updated request.\n if (cachedQueryPreview?.status === 'success') {\n emit('load', queryPreviewHash.value)\n xBus.emit('QueryPreviewMounted', queryPreviewHash.value, {\n priority: 0,\n replaceable: false,\n })\n } else if (!props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n\n /**\n * Watch element visibility and emit request when it becomes visible for the first time\n * (only when loadWhenVisible is true).\n */\n const { unwatchDisplay } = useOnDisplay({\n element: queryPreviewElement,\n callback: () => {\n if (props.loadWhenVisible && cachedQueryPreview?.status !== 'success') {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n },\n })\n\n /**\n * Cancels the (remaining) requests when the component is destroyed\n * via the `debounce.cancel()` method.\n * If the prop 'persistInCache' is set to false, it also removes the QueryPreview\n * from the state when the component is destroyed.\n */\n onBeforeUnmount(() => {\n unwatchDisplay?.()\n emitQueryPreviewRequestUpdated.value.cancel()\n xBus.emit(\n 'QueryPreviewUnmounted',\n { queryPreviewHash: queryPreviewHash.value, cache: props.persistInCache },\n {\n priority: 0,\n replaceable: false,\n },\n )\n })\n\n /**\n * Cancels the previous request when the debounced function changes (e.g: the debounceTimeMs\n * prop changes or there is a request in progress that cancels it).\n *\n * @param _new - The new debounced function.\n * @param old - The previous debounced function.\n * @internal\n */\n watch(\n emitQueryPreviewRequestUpdated,\n (_new: DebouncedFunction<[SearchRequest]>, old: DebouncedFunction<[SearchRequest]>) => {\n old.cancel()\n },\n )\n\n const queryPreviewResultsStatus = computed(() => queryPreviewResults.value?.status)\n\n /**\n * Emits an event when the query results are loaded or fail to load.\n *\n * @param status - The status of the query preview request.\n */\n watch(queryPreviewResultsStatus, () => {\n if (queryPreviewResultsStatus.value === 'success') {\n emit(results.value?.length ? 'load' : 'error', queryPreviewHash.value)\n } else if (queryPreviewResultsStatus.value === 'error') {\n emit('error', queryPreviewHash.value)\n }\n })\n\n const hasResults = computed(() => (queryPreviewResults.value?.totalResults ?? 0) > 0)\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are no results. Always wrapped in a section\n * element with the `x-query-preview-wrapper__slot-content` class.\n */\n function renderDefaultSlot() {\n const slotProps = {\n queryPreviewInfo: props.queryPreviewInfo,\n results: queryPreviewResults.value?.results,\n totalResults: queryPreviewResults.value?.totalResults,\n displayTagging: queryPreviewResults.value?.displayTagging,\n queryTagging: queryPreviewResults.value?.queryTagging,\n }\n\n const slotContent = hasResults.value ? slots.default?.(slotProps)[0] : ''\n\n return h(\n 'section',\n { ref: queryPreviewElement, class: 'x-query-preview-wrapper__slot-content' },\n [slotContent],\n )\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { hasResults, queryPreviewResults, queryPreviewElement }\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`QueryPreviewRequestUpdated`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted when the component is mounted and when the properties of the request object\n changes. The event payload is the `queryPreviewRequest` object.\n\n## Vue Events\n\nA list of vue events that the component will emit:\n\n- `load`: the event is emitted when the query results have been loaded.\n- `error`: the event is emitted if there is some error when retrieving the query results.\n\n## See it in action\n\nHere you have a basic example of how the QueryPreview is rendered. Keep in mind that this component\nis intended to be used overriding its default slot. By default it will only render the names of the\nresults.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'sandals' })\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #default=\"{ totalResults, results }\">\n <section>\n <p>Total results: {{ totalResults }}</p>\n <SlidingPanel :resetOnContentChange=\"false\">\n <article\n v-for=\"result in results\"\n :key=\"result.id\"\n class=\"x-result\"\n style=\"max-width: 300px; overflow: hidden\"\n >\n <BaseResultLink :result=\"result\">\n <BaseResultImage :result=\"result\" class=\"x-result__picture\" />\n </BaseResultLink>\n <div class=\"x-result__description\">\n <BaseResultLink :result=\"result\">\n <h1 class=\"x-title3\">{{ result.name }}</h1>\n </BaseResultLink>\n </div>\n </article>\n </SlidingPanel>\n </section>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { BaseResultImage, BaseResultLink, SlidingPanel } from '@empathyco/x-components'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #result=\"{ result }\">\n <span>{{ result.id }}</span>\n <span>{{ result.name }}</span>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with props\n\nIn this example, the query preview has been limited to render a maximum of 4 results.\n\n```vue\n<template>\n <QueryPreview\n :maxItemsToRender=\"maxItemsToRender\"\n :queryPreviewInfo=\"queryPreviewInfo\"\n #default=\"{ results }\"\n >\n <BaseGrid #default=\"{ item }\" :items=\"results\">\n <BaseResultLink :result=\"item\">\n <BaseResultImage :result=\"item\" />\n </BaseResultLink>\n </BaseGrid>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { BaseGrid, BaseResultImage, BaseResultLink } from '@empathyco/x-components'\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst maxItemsToRender = 4\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_renderSlot","_createElementVNode","_toDisplayString"],"mappings":";;;;;EAEW,GAAA,EAAI,qBAAA;AAAA,EAAsB,KAAA,EAAM;;;;EACjB,WAAA,EAAU,eAAA;AAAA,EAAgB,KAAA,EAAM;;AAY1C,MAAA,UAAA,GAAA,EAAA,WAAA,EAAU,aAAA,EAAa;;AAbrC,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAiBU,SAAA;AAAA,IAjBV,UAAA;AAAA,IAiBU;AAAA,MAhBE,IAAA,CAAA,UAAA,IAAAD,SAAA,EAAA,EAAVC,kBAAA,CAeK,IAAA,EAfL,UAAA,EAeK;AAAA,SAAAD,SAAA,CAAA,IAAA,CAAA,EAdHC,kBAAA;AAAA,UAaKC,QAAA;AAAA,UAAA,IAAA;AAAA,UAAAC,UAAA,CAZc,IAAA,CAAA,mBAAA,EAAqB,OAAA,EAAO,CAAtC,MAAA,KAAM;gCADfF,kBAAA,CAaK,IAAA,EAAA;AAAA,cAXF,KAAK,MAAA,CAAO,EAAA;AAAA,cACb,KAAA,EAAM,uBAAA;AAAA,cACN,WAAA,EAAU;AAAA,aAAA,EAAA;cAMVG,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,QAAA,EAAA,EAFc,MAAA,EAAc,EAAnC,MAEO;AAAA,gBADLC,kBAAA;AAAA,kBAAsD,MAAA;AAAA,kBAAtD,UAAA;AAAA,kBAAsDC,eAAA,CAArB,OAAO,IAAI,CAAA;AAAA,kBAAA;AAAA;AAAA;AAAA,eAAA;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"query-preview.vue.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview.vue"],"sourcesContent":["<template>\n <!-- eslint-disable vue/no-unused-refs -->\n <section ref=\"queryPreviewElement\" class=\"x-query-preview-wrapper__default-content\">\n <ul v-if=\"hasResults\" data-test=\"query-preview\" class=\"x-query-preview\">\n <li\n v-for=\"result in queryPreviewResults?.results\"\n :key=\"result.id\"\n class=\"x-query-preview__item\"\n data-test=\"query-preview-item\"\n >\n <!--\n @slot Query Preview result slot.\n @binding {Result} result - A Query Preview result\n -->\n <slot name=\"result\" :result=\"result\">\n <span data-test=\"result-name\">{{ result.name }}</span>\n </slot>\n </li>\n </ul>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport type { Filter, SearchRequest } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport type { FeatureLocation, QueryFeature } from '../../../types'\nimport type { DebouncedFunction } from '../../../utils'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { deepEqual } from '@empathyco/x-utils'\nimport { computed, defineComponent, h, inject, onBeforeUnmount, provide, ref, watch } from 'vue'\nimport { LIST_ITEMS_KEY } from '../../../components'\nimport { useOnDisplay, useState, useXBus } from '../../../composables'\nimport { createOrigin, createRawFilters, debounceFunction } from '../../../utils'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\n\n/**\n * Retrieves a preview of the results of a query and exposes them in the default slot,\n * along with the query preview and the totalResults of the search request.\n * By default, it renders the names of the results.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreview',\n xModule: queriesPreviewXModule.name,\n props: {\n /** The information about the request of the query preview. */\n queryPreviewInfo: {\n type: Object as PropType<QueryPreviewInfo>,\n required: true,\n },\n /** The origin property for the request. */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /** Number of query preview results to be rendered. */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests.\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether the QueryPreview should be removed from the state\n * when the component is destroyed.\n */\n persistInCache: {\n type: Boolean,\n default: false,\n },\n },\n emits: ['load', 'error'],\n setup(props, { emit, slots }) {\n const xBus = useXBus()\n\n /**\n * previewResults: The results preview of the queries preview cacheable mounted.\n * It is a dictionary, indexed by the query preview query.\n *\n * params: As the request is handled in this component, we need\n * the extra params that will be used in the request.\n *\n * config: As the request is handled in this component, we need\n * the config that will be used in the request.\n */\n const { queriesPreview: previewResults, params, config } = useState('queriesPreview')\n\n /**\n * Template ref for the root element to track visibility.\n */\n const queryPreviewElement = ref<HTMLElement | null>(null)\n\n /**\n * Query Preview key converted into a unique id.\n *\n * @returns The query hash.\n */\n const queryPreviewHash = computed(() =>\n getHashFromQueryPreviewInfo(props.queryPreviewInfo, {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n }),\n )\n\n provide('queryPreviewHash', queryPreviewHash)\n\n /**\n * Gets from the state the results preview of the query preview.\n *\n * @returns The results preview of the actual query preview.\n */\n const queryPreviewResults = computed(() => {\n const resultsPreview = previewResults.value[queryPreviewHash.value]\n return resultsPreview?.results\n ? {\n ...resultsPreview,\n results: resultsPreview.results.slice(0, props.maxItemsToRender),\n }\n : undefined\n })\n\n /**\n * The results to render from the state.\n *\n * @remarks The results list are provided with `items` key. It can be\n * concatenated with list items from components such as `BannersList`, `PromotedsList`,\n * `BaseGrid` or any component that injects the list.\n *\n * @returns A list of results.\n */\n const results = computed(() => queryPreviewResults.value?.results)\n provide(LIST_ITEMS_KEY as string, results)\n\n /**\n * It injects the provided {@link FeatureLocation} of the selected query in the search request.\n *\n * @internal\n */\n const injectedLocation = inject<Ref<FeatureLocation> | FeatureLocation>('location', 'none')\n const location =\n typeof injectedLocation === 'object' && 'value' in injectedLocation\n ? injectedLocation.value\n : injectedLocation\n\n /**\n * The computed request object to be used to retrieve the query preview results.\n *\n * @returns The search request object.\n */\n const queryPreviewRequest = computed<SearchRequest>(() => {\n const origin = createOrigin({\n feature: props.queryFeature,\n location,\n })\n const filters = props.queryPreviewInfo.filters?.reduce(\n (filtersList, filterId) => {\n const facetId = filterId.split(':')[0]\n const rawFilter = createRawFilters([filterId])[0]\n filtersList[facetId] = filtersList[facetId]\n ? filtersList[facetId].concat(rawFilter)\n : [rawFilter]\n\n return filtersList\n },\n {} as Record<string, Filter[]>,\n )\n\n return {\n query: props.queryPreviewInfo.query,\n rows: config.value.maxItemsToRequest,\n extraParams: {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n },\n filters,\n ...(origin && { origin }),\n }\n })\n\n /**\n * The debounce method to trigger the request after the debounceTimeMs defined\n * for cacheable queries.\n *\n * @returns The search request object.\n */\n const emitQueryPreviewRequestUpdated = computed<DebouncedFunction<[SearchRequest]>>(() =>\n debounceFunction(request => {\n xBus.emit('QueryPreviewRequestUpdated', request, { priority: 0, replaceable: false })\n }, props.debounceTimeMs),\n )\n\n /**\n * Initialises watcher to emit debounced requests, and first value for the requests.\n *\n * @internal\n */\n watch(queryPreviewRequest, (newRequest, oldRequest) => {\n if (!deepEqual(newRequest, oldRequest) && !props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(newRequest)\n }\n })\n\n const cachedQueryPreview = previewResults.value[queryPreviewHash.value]\n\n // If the query has been saved it will emit load instead of the emitting the updated request.\n if (cachedQueryPreview?.status === 'success') {\n emit('load', queryPreviewHash.value)\n xBus.emit('QueryPreviewMounted', queryPreviewHash.value, {\n priority: 0,\n replaceable: false,\n })\n } else if (!props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n\n /**\n * Watch element visibility and emit request when it becomes visible for the first time\n * (only when loadWhenVisible is true).\n */\n const { unwatchDisplay } = useOnDisplay({\n element: queryPreviewElement,\n callback: () => {\n if (props.loadWhenVisible && cachedQueryPreview?.status !== 'success') {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n },\n })\n\n /**\n * Cancels the (remaining) requests when the component is destroyed\n * via the `debounce.cancel()` method.\n * If the prop 'persistInCache' is set to false, it also removes the QueryPreview\n * from the state when the component is destroyed.\n */\n onBeforeUnmount(() => {\n unwatchDisplay?.()\n emitQueryPreviewRequestUpdated.value.cancel()\n xBus.emit(\n 'QueryPreviewUnmounted',\n { queryPreviewHash: queryPreviewHash.value, cache: props.persistInCache },\n {\n priority: 0,\n replaceable: false,\n },\n )\n })\n\n /**\n * Cancels the previous request when the debounced function changes (e.g: the debounceTimeMs\n * prop changes or there is a request in progress that cancels it).\n *\n * @param _new - The new debounced function.\n * @param old - The previous debounced function.\n * @internal\n */\n watch(\n emitQueryPreviewRequestUpdated,\n (_new: DebouncedFunction<[SearchRequest]>, old: DebouncedFunction<[SearchRequest]>) => {\n old.cancel()\n },\n )\n\n const queryPreviewResultsStatus = computed(() => queryPreviewResults.value?.status)\n\n /**\n * Emits an event when the query results are loaded or fail to load.\n *\n * @param status - The status of the query preview request.\n */\n watch(queryPreviewResultsStatus, () => {\n if (queryPreviewResultsStatus.value === 'success') {\n emit(results.value?.length ? 'load' : 'error', queryPreviewHash.value)\n } else if (queryPreviewResultsStatus.value === 'error') {\n emit('error', queryPreviewHash.value)\n }\n })\n\n const hasResults = computed(() => (queryPreviewResults.value?.totalResults ?? 0) > 0)\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are no results. Always wrapped in a section\n * element with the `x-query-preview-wrapper__slot-content` class.\n */\n function renderDefaultSlot() {\n const slotProps = {\n queryPreviewInfo: props.queryPreviewInfo,\n queryPreviewHash: queryPreviewHash.value,\n results: queryPreviewResults.value?.results,\n totalResults: queryPreviewResults.value?.totalResults,\n displayTagging: queryPreviewResults.value?.displayTagging,\n queryTagging: queryPreviewResults.value?.queryTagging,\n }\n\n const slotContent = hasResults.value ? slots.default?.(slotProps)[0] : ''\n\n return h(\n 'section',\n { ref: queryPreviewElement, class: 'x-query-preview-wrapper__slot-content' },\n [slotContent],\n )\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { hasResults, queryPreviewResults, queryPreviewElement }\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`QueryPreviewRequestUpdated`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted when the component is mounted and when the properties of the request object\n changes. The event payload is the `queryPreviewRequest` object.\n\n## Vue Events\n\nA list of vue events that the component will emit:\n\n- `load`: the event is emitted when the query results have been loaded.\n- `error`: the event is emitted if there is some error when retrieving the query results.\n\n## See it in action\n\nHere you have a basic example of how the QueryPreview is rendered. Keep in mind that this component\nis intended to be used overriding its default slot. By default it will only render the names of the\nresults.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'sandals' })\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #default=\"{ totalResults, results }\">\n <section>\n <p>Total results: {{ totalResults }}</p>\n <SlidingPanel :resetOnContentChange=\"false\">\n <article\n v-for=\"result in results\"\n :key=\"result.id\"\n class=\"x-result\"\n style=\"max-width: 300px; overflow: hidden\"\n >\n <BaseResultLink :result=\"result\">\n <BaseResultImage :result=\"result\" class=\"x-result__picture\" />\n </BaseResultLink>\n <div class=\"x-result__description\">\n <BaseResultLink :result=\"result\">\n <h1 class=\"x-title3\">{{ result.name }}</h1>\n </BaseResultLink>\n </div>\n </article>\n </SlidingPanel>\n </section>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { BaseResultImage, BaseResultLink, SlidingPanel } from '@empathyco/x-components'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #result=\"{ result }\">\n <span>{{ result.id }}</span>\n <span>{{ result.name }}</span>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with props\n\nIn this example, the query preview has been limited to render a maximum of 4 results.\n\n```vue\n<template>\n <QueryPreview\n :maxItemsToRender=\"maxItemsToRender\"\n :queryPreviewInfo=\"queryPreviewInfo\"\n #default=\"{ results }\"\n >\n <BaseGrid #default=\"{ item }\" :items=\"results\">\n <BaseResultLink :result=\"item\">\n <BaseResultImage :result=\"item\" />\n </BaseResultLink>\n </BaseGrid>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { BaseGrid, BaseResultImage, BaseResultLink } from '@empathyco/x-components'\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst maxItemsToRender = 4\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_renderSlot","_createElementVNode","_toDisplayString"],"mappings":";;;;;EAEW,GAAA,EAAI,qBAAA;AAAA,EAAsB,KAAA,EAAM;;;;EACjB,WAAA,EAAU,eAAA;AAAA,EAAgB,KAAA,EAAM;;AAY1C,MAAA,UAAA,GAAA,EAAA,WAAA,EAAU,aAAA,EAAa;;AAbrC,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAiBU,SAAA;AAAA,IAjBV,UAAA;AAAA,IAiBU;AAAA,MAhBE,IAAA,CAAA,UAAA,IAAAD,SAAA,EAAA,EAAVC,kBAAA,CAeK,IAAA,EAfL,UAAA,EAeK;AAAA,SAAAD,SAAA,CAAA,IAAA,CAAA,EAdHC,kBAAA;AAAA,UAaKC,QAAA;AAAA,UAAA,IAAA;AAAA,UAAAC,UAAA,CAZc,IAAA,CAAA,mBAAA,EAAqB,OAAA,EAAO,CAAtC,MAAA,KAAM;gCADfF,kBAAA,CAaK,IAAA,EAAA;AAAA,cAXF,KAAK,MAAA,CAAO,EAAA;AAAA,cACb,KAAA,EAAM,uBAAA;AAAA,cACN,WAAA,EAAU;AAAA,aAAA,EAAA;cAMVG,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,QAAA,EAAA,EAFc,MAAA,EAAc,EAAnC,MAEO;AAAA,gBADLC,kBAAA;AAAA,kBAAsD,MAAA;AAAA,kBAAtD,UAAA;AAAA,kBAAsDC,eAAA,CAArB,OAAO,IAAI,CAAA;AAAA,kBAAA;AAAA;AAAA;AAAA,eAAA;;;;;;;;;;;;;;;;"}
|
|
@@ -343,6 +343,7 @@ var _sfc_main = defineComponent({
|
|
|
343
343
|
function renderDefaultSlot() {
|
|
344
344
|
const slotProps = {
|
|
345
345
|
queryPreviewInfo: props.queryPreviewInfo,
|
|
346
|
+
queryPreviewHash: queryPreviewHash.value,
|
|
346
347
|
results: queryPreviewResults.value?.results,
|
|
347
348
|
totalResults: queryPreviewResults.value?.totalResults,
|
|
348
349
|
displayTagging: queryPreviewResults.value?.displayTagging,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-preview.vue2.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview.vue"],"sourcesContent":["<template>\n <!-- eslint-disable-next-line vue/no-unused-refs -->\n <section ref=\"queryPreviewElement\" class=\"x-query-preview-wrapper__default-content\">\n <ul v-if=\"hasResults\" data-test=\"query-preview\" class=\"x-query-preview\">\n <li\n v-for=\"result in queryPreviewResults?.results\"\n :key=\"result.id\"\n class=\"x-query-preview__item\"\n data-test=\"query-preview-item\"\n >\n <!--\n @slot Query Preview result slot.\n @binding {Result} result - A Query Preview result\n -->\n <slot name=\"result\" :result=\"result\">\n <span data-test=\"result-name\">{{ result.name }}</span>\n </slot>\n </li>\n </ul>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport type { Filter, SearchRequest } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport type { FeatureLocation, QueryFeature } from '../../../types'\nimport type { DebouncedFunction } from '../../../utils'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { deepEqual } from '@empathyco/x-utils'\nimport { computed, defineComponent, h, inject, onBeforeUnmount, provide, ref, watch } from 'vue'\nimport { LIST_ITEMS_KEY } from '../../../components'\nimport { useOnDisplay, useState, useXBus } from '../../../composables'\nimport { createOrigin, createRawFilters, debounceFunction } from '../../../utils'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\n\n/**\n * Retrieves a preview of the results of a query and exposes them in the default slot,\n * along with the query preview and the totalResults of the search request.\n * By default, it renders the names of the results.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreview',\n xModule: queriesPreviewXModule.name,\n props: {\n /** The information about the request of the query preview. */\n queryPreviewInfo: {\n type: Object as PropType<QueryPreviewInfo>,\n required: true,\n },\n /** The origin property for the request. */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /** Number of query preview results to be rendered. */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests.\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether the QueryPreview should be removed from the state\n * when the component is destroyed.\n */\n persistInCache: {\n type: Boolean,\n default: false,\n },\n },\n emits: ['load', 'error'],\n setup(props, { emit, slots }) {\n const xBus = useXBus()\n\n /**\n * previewResults: The results preview of the queries preview cacheable mounted.\n * It is a dictionary, indexed by the query preview query.\n *\n * params: As the request is handled in this component, we need\n * the extra params that will be used in the request.\n *\n * config: As the request is handled in this component, we need\n * the config that will be used in the request.\n */\n const { queriesPreview: previewResults, params, config } = useState('queriesPreview')\n\n /**\n * Template ref for the root element to track visibility.\n */\n const queryPreviewElement = ref<HTMLElement | null>(null)\n\n /**\n * Query Preview key converted into a unique id.\n *\n * @returns The query hash.\n */\n const queryPreviewHash = computed(() =>\n getHashFromQueryPreviewInfo(props.queryPreviewInfo, {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n }),\n )\n\n provide('queryPreviewHash', queryPreviewHash)\n\n /**\n * Gets from the state the results preview of the query preview.\n *\n * @returns The results preview of the actual query preview.\n */\n const queryPreviewResults = computed(() => {\n const resultsPreview = previewResults.value[queryPreviewHash.value]\n return resultsPreview?.results\n ? {\n ...resultsPreview,\n results: resultsPreview.results.slice(0, props.maxItemsToRender),\n }\n : undefined\n })\n\n /**\n * The results to render from the state.\n *\n * @remarks The results list are provided with `items` key. It can be\n * concatenated with list items from components such as `BannersList`, `PromotedsList`,\n * `BaseGrid` or any component that injects the list.\n *\n * @returns A list of results.\n */\n const results = computed(() => queryPreviewResults.value?.results)\n provide(LIST_ITEMS_KEY as string, results)\n\n /**\n * It injects the provided {@link FeatureLocation} of the selected query in the search request.\n *\n * @internal\n */\n const injectedLocation = inject<Ref<FeatureLocation> | FeatureLocation>('location', 'none')\n const location =\n typeof injectedLocation === 'object' && 'value' in injectedLocation\n ? injectedLocation.value\n : injectedLocation\n\n /**\n * The computed request object to be used to retrieve the query preview results.\n *\n * @returns The search request object.\n */\n const queryPreviewRequest = computed<SearchRequest>(() => {\n const origin = createOrigin({\n feature: props.queryFeature,\n location,\n })\n const filters = props.queryPreviewInfo.filters?.reduce(\n (filtersList, filterId) => {\n const facetId = filterId.split(':')[0]\n const rawFilter = createRawFilters([filterId])[0]\n filtersList[facetId] = filtersList[facetId]\n ? filtersList[facetId].concat(rawFilter)\n : [rawFilter]\n\n return filtersList\n },\n {} as Record<string, Filter[]>,\n )\n\n return {\n query: props.queryPreviewInfo.query,\n rows: config.value.maxItemsToRequest,\n extraParams: {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n },\n filters,\n ...(origin && { origin }),\n }\n })\n\n /**\n * The debounce method to trigger the request after the debounceTimeMs defined\n * for cacheable queries.\n *\n * @returns The search request object.\n */\n const emitQueryPreviewRequestUpdated = computed<DebouncedFunction<[SearchRequest]>>(() =>\n debounceFunction(request => {\n xBus.emit('QueryPreviewRequestUpdated', request, { priority: 0, replaceable: false })\n }, props.debounceTimeMs),\n )\n\n /**\n * Initialises watcher to emit debounced requests, and first value for the requests.\n *\n * @internal\n */\n watch(queryPreviewRequest, (newRequest, oldRequest) => {\n if (!deepEqual(newRequest, oldRequest) && !props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(newRequest)\n }\n })\n\n const cachedQueryPreview = previewResults.value[queryPreviewHash.value]\n\n // If the query has been saved it will emit load instead of the emitting the updated request.\n if (cachedQueryPreview?.status === 'success') {\n emit('load', queryPreviewHash.value)\n xBus.emit('QueryPreviewMounted', queryPreviewHash.value, {\n priority: 0,\n replaceable: false,\n })\n } else if (!props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n\n /**\n * Watch element visibility and emit request when it becomes visible for the first time\n * (only when loadWhenVisible is true).\n */\n const { unwatchDisplay } = useOnDisplay({\n element: queryPreviewElement,\n callback: () => {\n if (props.loadWhenVisible && cachedQueryPreview?.status !== 'success') {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n },\n })\n\n /**\n * Cancels the (remaining) requests when the component is destroyed\n * via the `debounce.cancel()` method.\n * If the prop 'persistInCache' is set to false, it also removes the QueryPreview\n * from the state when the component is destroyed.\n */\n onBeforeUnmount(() => {\n unwatchDisplay?.()\n emitQueryPreviewRequestUpdated.value.cancel()\n xBus.emit(\n 'QueryPreviewUnmounted',\n { queryPreviewHash: queryPreviewHash.value, cache: props.persistInCache },\n {\n priority: 0,\n replaceable: false,\n },\n )\n })\n\n /**\n * Cancels the previous request when the debounced function changes (e.g: the debounceTimeMs\n * prop changes or there is a request in progress that cancels it).\n *\n * @param _new - The new debounced function.\n * @param old - The previous debounced function.\n * @internal\n */\n watch(\n emitQueryPreviewRequestUpdated,\n (_new: DebouncedFunction<[SearchRequest]>, old: DebouncedFunction<[SearchRequest]>) => {\n old.cancel()\n },\n )\n\n const queryPreviewResultsStatus = computed(() => queryPreviewResults.value?.status)\n\n /**\n * Emits an event when the query results are loaded or fail to load.\n *\n * @param status - The status of the query preview request.\n */\n watch(queryPreviewResultsStatus, () => {\n if (queryPreviewResultsStatus.value === 'success') {\n emit(results.value?.length ? 'load' : 'error', queryPreviewHash.value)\n } else if (queryPreviewResultsStatus.value === 'error') {\n emit('error', queryPreviewHash.value)\n }\n })\n\n const hasResults = computed(() => (queryPreviewResults.value?.totalResults ?? 0) > 0)\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are no results. Always wrapped in a section\n * element with the `x-query-preview-wrapper__slot-content` class.\n */\n function renderDefaultSlot() {\n const slotProps = {\n queryPreviewInfo: props.queryPreviewInfo,\n results: queryPreviewResults.value?.results,\n totalResults: queryPreviewResults.value?.totalResults,\n displayTagging: queryPreviewResults.value?.displayTagging,\n queryTagging: queryPreviewResults.value?.queryTagging,\n }\n\n const slotContent = hasResults.value ? slots.default?.(slotProps)[0] : ''\n\n return h(\n 'section',\n { ref: queryPreviewElement, class: 'x-query-preview-wrapper__slot-content' },\n [slotContent],\n )\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { hasResults, queryPreviewResults, queryPreviewElement }\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`QueryPreviewRequestUpdated`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted when the component is mounted and when the properties of the request object\n changes. The event payload is the `queryPreviewRequest` object.\n\n## Vue Events\n\nA list of vue events that the component will emit:\n\n- `load`: the event is emitted when the query results have been loaded.\n- `error`: the event is emitted if there is some error when retrieving the query results.\n\n## See it in action\n\nHere you have a basic example of how the QueryPreview is rendered. Keep in mind that this component\nis intended to be used overriding its default slot. By default it will only render the names of the\nresults.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'sandals' })\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #default=\"{ totalResults, results }\">\n <section>\n <p>Total results: {{ totalResults }}</p>\n <SlidingPanel :resetOnContentChange=\"false\">\n <article\n v-for=\"result in results\"\n :key=\"result.id\"\n class=\"x-result\"\n style=\"max-width: 300px; overflow: hidden\"\n >\n <BaseResultLink :result=\"result\">\n <BaseResultImage :result=\"result\" class=\"x-result__picture\" />\n </BaseResultLink>\n <div class=\"x-result__description\">\n <BaseResultLink :result=\"result\">\n <h1 class=\"x-title3\">{{ result.name }}</h1>\n </BaseResultLink>\n </div>\n </article>\n </SlidingPanel>\n </section>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { BaseResultImage, BaseResultLink, SlidingPanel } from '@empathyco/x-components'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #result=\"{ result }\">\n <span>{{ result.id }}</span>\n <span>{{ result.name }}</span>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with props\n\nIn this example, the query preview has been limited to render a maximum of 4 results.\n\n```vue\n<template>\n <QueryPreview\n :maxItemsToRender=\"maxItemsToRender\"\n :queryPreviewInfo=\"queryPreviewInfo\"\n #default=\"{ results }\"\n >\n <BaseGrid #default=\"{ item }\" :items=\"results\">\n <BaseResultLink :result=\"item\">\n <BaseResultImage :result=\"item\" />\n </BaseResultLink>\n </BaseGrid>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { BaseGrid, BaseResultImage, BaseResultLink } from '@empathyco/x-components'\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst maxItemsToRender = 4\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n</docs>\n"],"names":["debounceFunction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-preview.vue2.js","sources":["../../../../../src/x-modules/queries-preview/components/query-preview.vue"],"sourcesContent":["<template>\n <!-- eslint-disable vue/no-unused-refs -->\n <section ref=\"queryPreviewElement\" class=\"x-query-preview-wrapper__default-content\">\n <ul v-if=\"hasResults\" data-test=\"query-preview\" class=\"x-query-preview\">\n <li\n v-for=\"result in queryPreviewResults?.results\"\n :key=\"result.id\"\n class=\"x-query-preview__item\"\n data-test=\"query-preview-item\"\n >\n <!--\n @slot Query Preview result slot.\n @binding {Result} result - A Query Preview result\n -->\n <slot name=\"result\" :result=\"result\">\n <span data-test=\"result-name\">{{ result.name }}</span>\n </slot>\n </li>\n </ul>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport type { Filter, SearchRequest } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport type { FeatureLocation, QueryFeature } from '../../../types'\nimport type { DebouncedFunction } from '../../../utils'\nimport type { QueryPreviewInfo } from '../store/types'\nimport { deepEqual } from '@empathyco/x-utils'\nimport { computed, defineComponent, h, inject, onBeforeUnmount, provide, ref, watch } from 'vue'\nimport { LIST_ITEMS_KEY } from '../../../components'\nimport { useOnDisplay, useState, useXBus } from '../../../composables'\nimport { createOrigin, createRawFilters, debounceFunction } from '../../../utils'\nimport { getHashFromQueryPreviewInfo } from '../utils/get-hash-from-query-preview'\nimport { queriesPreviewXModule } from '../x-module'\n\n/**\n * Retrieves a preview of the results of a query and exposes them in the default slot,\n * along with the query preview and the totalResults of the search request.\n * By default, it renders the names of the results.\n *\n * @public\n */\nexport default defineComponent({\n name: 'QueryPreview',\n xModule: queriesPreviewXModule.name,\n props: {\n /** The information about the request of the query preview. */\n queryPreviewInfo: {\n type: Object as PropType<QueryPreviewInfo>,\n required: true,\n },\n /** The origin property for the request. */\n queryFeature: {\n type: String as PropType<QueryFeature>,\n },\n /** Number of query preview results to be rendered. */\n maxItemsToRender: {\n type: Number,\n },\n /**\n * Controls whether the query preview requests should be triggered when the component is visible in the viewport.\n */\n loadWhenVisible: {\n type: Boolean,\n default: false,\n },\n /**\n * Debounce time in milliseconds for triggering the search requests.\n * It will default to 0 to fit the most common use case (pre-search),\n * and it would work properly with a 250 value inside empathize.\n */\n debounceTimeMs: {\n type: Number,\n default: 0,\n },\n /**\n * Controls whether the QueryPreview should be removed from the state\n * when the component is destroyed.\n */\n persistInCache: {\n type: Boolean,\n default: false,\n },\n },\n emits: ['load', 'error'],\n setup(props, { emit, slots }) {\n const xBus = useXBus()\n\n /**\n * previewResults: The results preview of the queries preview cacheable mounted.\n * It is a dictionary, indexed by the query preview query.\n *\n * params: As the request is handled in this component, we need\n * the extra params that will be used in the request.\n *\n * config: As the request is handled in this component, we need\n * the config that will be used in the request.\n */\n const { queriesPreview: previewResults, params, config } = useState('queriesPreview')\n\n /**\n * Template ref for the root element to track visibility.\n */\n const queryPreviewElement = ref<HTMLElement | null>(null)\n\n /**\n * Query Preview key converted into a unique id.\n *\n * @returns The query hash.\n */\n const queryPreviewHash = computed(() =>\n getHashFromQueryPreviewInfo(props.queryPreviewInfo, {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n }),\n )\n\n provide('queryPreviewHash', queryPreviewHash)\n\n /**\n * Gets from the state the results preview of the query preview.\n *\n * @returns The results preview of the actual query preview.\n */\n const queryPreviewResults = computed(() => {\n const resultsPreview = previewResults.value[queryPreviewHash.value]\n return resultsPreview?.results\n ? {\n ...resultsPreview,\n results: resultsPreview.results.slice(0, props.maxItemsToRender),\n }\n : undefined\n })\n\n /**\n * The results to render from the state.\n *\n * @remarks The results list are provided with `items` key. It can be\n * concatenated with list items from components such as `BannersList`, `PromotedsList`,\n * `BaseGrid` or any component that injects the list.\n *\n * @returns A list of results.\n */\n const results = computed(() => queryPreviewResults.value?.results)\n provide(LIST_ITEMS_KEY as string, results)\n\n /**\n * It injects the provided {@link FeatureLocation} of the selected query in the search request.\n *\n * @internal\n */\n const injectedLocation = inject<Ref<FeatureLocation> | FeatureLocation>('location', 'none')\n const location =\n typeof injectedLocation === 'object' && 'value' in injectedLocation\n ? injectedLocation.value\n : injectedLocation\n\n /**\n * The computed request object to be used to retrieve the query preview results.\n *\n * @returns The search request object.\n */\n const queryPreviewRequest = computed<SearchRequest>(() => {\n const origin = createOrigin({\n feature: props.queryFeature,\n location,\n })\n const filters = props.queryPreviewInfo.filters?.reduce(\n (filtersList, filterId) => {\n const facetId = filterId.split(':')[0]\n const rawFilter = createRawFilters([filterId])[0]\n filtersList[facetId] = filtersList[facetId]\n ? filtersList[facetId].concat(rawFilter)\n : [rawFilter]\n\n return filtersList\n },\n {} as Record<string, Filter[]>,\n )\n\n return {\n query: props.queryPreviewInfo.query,\n rows: config.value.maxItemsToRequest,\n extraParams: {\n ...params.value,\n ...props.queryPreviewInfo.extraParams,\n },\n filters,\n ...(origin && { origin }),\n }\n })\n\n /**\n * The debounce method to trigger the request after the debounceTimeMs defined\n * for cacheable queries.\n *\n * @returns The search request object.\n */\n const emitQueryPreviewRequestUpdated = computed<DebouncedFunction<[SearchRequest]>>(() =>\n debounceFunction(request => {\n xBus.emit('QueryPreviewRequestUpdated', request, { priority: 0, replaceable: false })\n }, props.debounceTimeMs),\n )\n\n /**\n * Initialises watcher to emit debounced requests, and first value for the requests.\n *\n * @internal\n */\n watch(queryPreviewRequest, (newRequest, oldRequest) => {\n if (!deepEqual(newRequest, oldRequest) && !props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(newRequest)\n }\n })\n\n const cachedQueryPreview = previewResults.value[queryPreviewHash.value]\n\n // If the query has been saved it will emit load instead of the emitting the updated request.\n if (cachedQueryPreview?.status === 'success') {\n emit('load', queryPreviewHash.value)\n xBus.emit('QueryPreviewMounted', queryPreviewHash.value, {\n priority: 0,\n replaceable: false,\n })\n } else if (!props.loadWhenVisible) {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n\n /**\n * Watch element visibility and emit request when it becomes visible for the first time\n * (only when loadWhenVisible is true).\n */\n const { unwatchDisplay } = useOnDisplay({\n element: queryPreviewElement,\n callback: () => {\n if (props.loadWhenVisible && cachedQueryPreview?.status !== 'success') {\n emitQueryPreviewRequestUpdated.value(queryPreviewRequest.value)\n }\n },\n })\n\n /**\n * Cancels the (remaining) requests when the component is destroyed\n * via the `debounce.cancel()` method.\n * If the prop 'persistInCache' is set to false, it also removes the QueryPreview\n * from the state when the component is destroyed.\n */\n onBeforeUnmount(() => {\n unwatchDisplay?.()\n emitQueryPreviewRequestUpdated.value.cancel()\n xBus.emit(\n 'QueryPreviewUnmounted',\n { queryPreviewHash: queryPreviewHash.value, cache: props.persistInCache },\n {\n priority: 0,\n replaceable: false,\n },\n )\n })\n\n /**\n * Cancels the previous request when the debounced function changes (e.g: the debounceTimeMs\n * prop changes or there is a request in progress that cancels it).\n *\n * @param _new - The new debounced function.\n * @param old - The previous debounced function.\n * @internal\n */\n watch(\n emitQueryPreviewRequestUpdated,\n (_new: DebouncedFunction<[SearchRequest]>, old: DebouncedFunction<[SearchRequest]>) => {\n old.cancel()\n },\n )\n\n const queryPreviewResultsStatus = computed(() => queryPreviewResults.value?.status)\n\n /**\n * Emits an event when the query results are loaded or fail to load.\n *\n * @param status - The status of the query preview request.\n */\n watch(queryPreviewResultsStatus, () => {\n if (queryPreviewResultsStatus.value === 'success') {\n emit(results.value?.length ? 'load' : 'error', queryPreviewHash.value)\n } else if (queryPreviewResultsStatus.value === 'error') {\n emit('error', queryPreviewHash.value)\n }\n })\n\n const hasResults = computed(() => (queryPreviewResults.value?.totalResults ?? 0) > 0)\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are no results. Always wrapped in a section\n * element with the `x-query-preview-wrapper__slot-content` class.\n */\n function renderDefaultSlot() {\n const slotProps = {\n queryPreviewInfo: props.queryPreviewInfo,\n queryPreviewHash: queryPreviewHash.value,\n results: queryPreviewResults.value?.results,\n totalResults: queryPreviewResults.value?.totalResults,\n displayTagging: queryPreviewResults.value?.displayTagging,\n queryTagging: queryPreviewResults.value?.queryTagging,\n }\n\n const slotContent = hasResults.value ? slots.default?.(slotProps)[0] : ''\n\n return h(\n 'section',\n { ref: queryPreviewElement, class: 'x-query-preview-wrapper__slot-content' },\n [slotContent],\n )\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { hasResults, queryPreviewResults, queryPreviewElement }\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`QueryPreviewRequestUpdated`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted when the component is mounted and when the properties of the request object\n changes. The event payload is the `queryPreviewRequest` object.\n\n## Vue Events\n\nA list of vue events that the component will emit:\n\n- `load`: the event is emitted when the query results have been loaded.\n- `error`: the event is emitted if there is some error when retrieving the query results.\n\n## See it in action\n\nHere you have a basic example of how the QueryPreview is rendered. Keep in mind that this component\nis intended to be used overriding its default slot. By default it will only render the names of the\nresults.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" />\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'sandals' })\n</script>\n```\n\n### Play with the default slot\n\nIn this example, the results will be rendered inside a sliding panel.\n\n```vue live\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #default=\"{ totalResults, results }\">\n <section>\n <p>Total results: {{ totalResults }}</p>\n <SlidingPanel :resetOnContentChange=\"false\">\n <article\n v-for=\"result in results\"\n :key=\"result.id\"\n class=\"x-result\"\n style=\"max-width: 300px; overflow: hidden\"\n >\n <BaseResultLink :result=\"result\">\n <BaseResultImage :result=\"result\" class=\"x-result__picture\" />\n </BaseResultLink>\n <div class=\"x-result__description\">\n <BaseResultLink :result=\"result\">\n <h1 class=\"x-title3\">{{ result.name }}</h1>\n </BaseResultLink>\n </div>\n </article>\n </SlidingPanel>\n </section>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { BaseResultImage, BaseResultLink, SlidingPanel } from '@empathyco/x-components'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with the result slot\n\nThe component exposes a slot to override the result content, without modifying the list.\n\nIn this example, the ID of the results will be rendered along with the name.\n\n```vue\n<template>\n <QueryPreview :queryPreviewInfo=\"queryPreviewInfo\" #result=\"{ result }\">\n <span>{{ result.id }}</span>\n <span>{{ result.name }}</span>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n\n### Play with props\n\nIn this example, the query preview has been limited to render a maximum of 4 results.\n\n```vue\n<template>\n <QueryPreview\n :maxItemsToRender=\"maxItemsToRender\"\n :queryPreviewInfo=\"queryPreviewInfo\"\n #default=\"{ results }\"\n >\n <BaseGrid #default=\"{ item }\" :items=\"results\">\n <BaseResultLink :result=\"item\">\n <BaseResultImage :result=\"item\" />\n </BaseResultLink>\n </BaseGrid>\n </QueryPreview>\n</template>\n\n<script setup>\nimport { BaseGrid, BaseResultImage, BaseResultLink } from '@empathyco/x-components'\nimport { QueryPreview } from '@empathyco/x-components/queries-preview'\nimport { reactive } from 'vue'\nconst maxItemsToRender = 4\nconst queryPreviewInfo = reactive({ query: 'flip-flops' })\n</script>\n```\n</docs>\n"],"names":["debounceFunction"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent,
|
|
1
|
+
import { defineComponent, computed, inject, provide, h } from 'vue';
|
|
2
2
|
import { LIST_ITEMS_KEY } from '../../../components/decorators/injection.consts.js';
|
|
3
3
|
import ItemsList from '../../../components/items-list.vue.js';
|
|
4
4
|
import { use$x } from '../../../composables/use-_x.js';
|
|
@@ -13,6 +13,9 @@ import { vendorXModule } from '../x-module.js';
|
|
|
13
13
|
* plus the `injectedListItems` which also contains the injected list items from
|
|
14
14
|
* the ancestor.
|
|
15
15
|
*
|
|
16
|
+
* If the `queryPreviewHash` prop is provided, the vendor banners are retrieved from
|
|
17
|
+
* {@link VendorState.queryPreviews}, scoped to the query preview.
|
|
18
|
+
*
|
|
16
19
|
* It also provides the parent slots to customize the items.
|
|
17
20
|
*
|
|
18
21
|
* @public
|
|
@@ -26,13 +29,40 @@ var _sfc_main = defineComponent({
|
|
|
26
29
|
type: AnimationProp,
|
|
27
30
|
default: 'ul',
|
|
28
31
|
},
|
|
32
|
+
/**
|
|
33
|
+
* The hash of the query preview to render its vendor banners. If not provided,
|
|
34
|
+
* the vendor banners from the root state are rendered.
|
|
35
|
+
*/
|
|
36
|
+
queryPreviewHash: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: undefined,
|
|
39
|
+
},
|
|
29
40
|
},
|
|
30
41
|
setup(props, { slots }) {
|
|
31
42
|
const $x = use$x();
|
|
32
|
-
/** The vendor banners to render from the state. */
|
|
33
|
-
const
|
|
43
|
+
/** The vendor banners to render from the vendor state. */
|
|
44
|
+
const vendorBanners = useState('vendor').banners;
|
|
45
|
+
/** The vendor banners of the query previews, indexed by their query preview hash. */
|
|
46
|
+
const vendorQueryPreviews = useState('vendor').queryPreviews;
|
|
47
|
+
/**
|
|
48
|
+
* The vendor banners to render. They are read from the query preview state when the
|
|
49
|
+
* `queryPreviewHash` prop is provided, or from the root vendor state otherwise.
|
|
50
|
+
*/
|
|
51
|
+
const stateItems = computed(() => props.queryPreviewHash
|
|
52
|
+
? (vendorQueryPreviews.value?.[props.queryPreviewHash]?.banners ?? [])
|
|
53
|
+
: vendorBanners.value);
|
|
34
54
|
/** It injects {@link ListItem} provided by an ancestor as injectedListItems. */
|
|
35
55
|
const injectedListItems = inject(LIST_ITEMS_KEY);
|
|
56
|
+
/**
|
|
57
|
+
* Indicates if all the results of the current context have been loaded, to know if the
|
|
58
|
+
* vendor banners can be inserted in positions of not yet loaded pages.
|
|
59
|
+
*
|
|
60
|
+
* @remarks The query preview results are always considered as fully loaded, since they are
|
|
61
|
+
* retrieved as a fixed batch.
|
|
62
|
+
*
|
|
63
|
+
* @returns Whether all the results are loaded.
|
|
64
|
+
*/
|
|
65
|
+
const areAllPagesLoaded = computed(() => props.queryPreviewHash ? true : $x.results.length === $x.totalResults);
|
|
36
66
|
/**
|
|
37
67
|
* The `stateItems` concatenated with the `injectedListItems` if there are.
|
|
38
68
|
*
|
|
@@ -54,8 +84,7 @@ var _sfc_main = defineComponent({
|
|
|
54
84
|
index++;
|
|
55
85
|
}
|
|
56
86
|
const isIndexInLoadedPages = index <= items.length;
|
|
57
|
-
|
|
58
|
-
if (!isIndexInLoadedPages && !areAllPagesLoaded) {
|
|
87
|
+
if (!isIndexInLoadedPages && !areAllPagesLoaded.value) {
|
|
59
88
|
break;
|
|
60
89
|
}
|
|
61
90
|
items.splice(index, 0, item);
|