@empathyco/x-components 6.1.4 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/ai/index.js +0 -1
  3. package/core/index.js.map +1 -1
  4. package/docs/API-reference/api/x-components.aicarousel.md +24 -28
  5. package/docs/API-reference/api/x-components.aimutations.md +1 -58
  6. package/docs/API-reference/api/x-components.aimutations.setexcludedresultids.md +1 -1
  7. package/docs/API-reference/api/x-components.aistate.md +0 -55
  8. package/docs/API-reference/api/x-components.aixevents.md +3 -3
  9. package/docs/API-reference/api/{x-components.aixevents.userclickedaioverviewexpandbutton.md → x-components.aixevents.userclickedanaicarouseladd2cart.md} +3 -3
  10. package/docs/API-reference/api/{x-components.aixevents.userclickedanaioverviewresult.md → x-components.aixevents.userclickedanaicarouselresult.md} +3 -3
  11. package/docs/API-reference/api/x-components.hierarchicalfilter.md +2 -2
  12. package/docs/API-reference/api/x-components.md +0 -9
  13. package/docs/API-reference/api/x-components.simplefilter.md +2 -2
  14. package/docs/API-reference/api/x-components.snippetcallbacks.md +2 -2
  15. package/docs/API-reference/components/ai/x-components.ai-carousel.md +9 -7
  16. package/docs/API-reference/components/ai/x-components.ai-grouped-carousel.md +25 -0
  17. package/docs/API-reference/components/common/x-components.display-click-provider.md +1 -1
  18. package/js/components/display-click-provider.vue.js +3 -3
  19. package/js/components/display-click-provider.vue.js.map +1 -1
  20. package/js/components/icons/spinner.vue.js +2 -2
  21. package/js/index.js +0 -1
  22. package/js/index.js.map +1 -1
  23. package/js/x-modules/ai/components/ai-carousel.vue.js +121 -66
  24. package/js/x-modules/ai/components/ai-carousel.vue.js.map +1 -1
  25. package/js/x-modules/ai/components/ai-carousel.vue2.js +18 -17
  26. package/js/x-modules/ai/components/ai-carousel.vue2.js.map +1 -1
  27. package/js/x-modules/ai/components/ai-carousel.vue3.js +1 -1
  28. package/js/x-modules/ai/components/ai-grouped-carousel.vue.js +68 -0
  29. package/js/x-modules/ai/components/ai-grouped-carousel.vue.js.map +1 -0
  30. package/js/x-modules/ai/components/{ai-overview.vue2.js → ai-grouped-carousel.vue2.js} +24 -86
  31. package/js/x-modules/ai/components/ai-grouped-carousel.vue2.js.map +1 -0
  32. package/js/x-modules/ai/store/actions/fetch-and-save-ai-suggestions.action.js +2 -10
  33. package/js/x-modules/ai/store/actions/fetch-and-save-ai-suggestions.action.js.map +1 -1
  34. package/js/x-modules/ai/store/module.js +6 -18
  35. package/js/x-modules/ai/store/module.js.map +1 -1
  36. package/js/x-modules/tagging/wiring.js +2 -2
  37. package/js/x-modules/tagging/wiring.js.map +1 -1
  38. package/package.json +2 -3
  39. package/report/x-components.api.json +102 -709
  40. package/report/x-components.api.md +37 -128
  41. package/types/src/components/snippet-callbacks.vue.d.ts +2 -2
  42. package/types/src/x-modules/ai/components/ai-carousel.vue.d.ts +24 -28
  43. package/types/src/x-modules/ai/components/ai-carousel.vue.d.ts.map +1 -1
  44. package/types/src/x-modules/ai/components/ai-grouped-carousel.vue.d.ts +19 -0
  45. package/types/src/x-modules/ai/components/ai-grouped-carousel.vue.d.ts.map +1 -0
  46. package/types/src/x-modules/ai/components/index.d.ts +0 -1
  47. package/types/src/x-modules/ai/components/index.d.ts.map +1 -1
  48. package/types/src/x-modules/ai/events.types.d.ts +2 -2
  49. package/types/src/x-modules/ai/events.types.d.ts.map +1 -1
  50. package/types/src/x-modules/ai/store/actions/fetch-and-save-ai-suggestions.action.d.ts.map +1 -1
  51. package/types/src/x-modules/ai/store/module.d.ts.map +1 -1
  52. package/types/src/x-modules/ai/store/types.d.ts +6 -29
  53. package/types/src/x-modules/ai/store/types.d.ts.map +1 -1
  54. package/types/src/x-modules/facets/components/filters/hierarchical-filter.vue.d.ts +2 -2
  55. package/types/src/x-modules/facets/components/filters/simple-filter.vue.d.ts +2 -2
  56. package/types/src/x-modules/tagging/wiring.d.ts +2 -2
  57. package/docs/API-reference/api/x-components.aimutations.setisnoresults.md +0 -13
  58. package/docs/API-reference/api/x-components.aimutations.setresponsetext.md +0 -13
  59. package/docs/API-reference/api/x-components.aimutations.setsuggestiontext.md +0 -13
  60. package/docs/API-reference/api/x-components.aioverview.md +0 -88
  61. package/docs/API-reference/api/x-components.aistate.isnoresults.md +0 -13
  62. package/docs/API-reference/api/x-components.aistate.responsetext.md +0 -13
  63. package/docs/API-reference/api/x-components.aistate.suggestiontext.md +0 -11
  64. package/docs/API-reference/components/ai/x-components.ai-overview.md +0 -96
  65. package/js/x-modules/ai/components/ai-overview.vue.js +0 -267
  66. package/js/x-modules/ai/components/ai-overview.vue.js.map +0 -1
  67. package/js/x-modules/ai/components/ai-overview.vue2.js.map +0 -1
  68. package/js/x-modules/ai/components/ai-overview.vue3.js +0 -7
  69. package/js/x-modules/ai/components/ai-overview.vue3.js.map +0 -1
  70. package/types/src/x-modules/ai/components/ai-overview.vue.d.ts +0 -81
  71. package/types/src/x-modules/ai/components/ai-overview.vue.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import _sfc_main from './ai-carousel.vue2.js';
2
- import { resolveComponent, openBlock, createBlock, withCtx, createElementBlock, createVNode, createElementVNode, normalizeClass, toDisplayString, createCommentVNode, renderSlot, Fragment, renderList } from 'vue';
2
+ import { resolveComponent, openBlock, createBlock, withCtx, createElementBlock, createVNode, createElementVNode, normalizeClass, toDisplayString, createCommentVNode, renderSlot, Fragment, renderList, createTextVNode } from 'vue';
3
3
  import './ai-carousel.vue3.js';
4
4
  import _export_sfc from '../../../_virtual/_plugin-vue_export-helper.js';
5
5
 
@@ -8,15 +8,26 @@ const _hoisted_1 = {
8
8
  class: "x-ai-carousel"
9
9
  };
10
10
  const _hoisted_2 = ["aria-label"];
11
- const _hoisted_3 = { class: "x-ai-carousel-suggestion" };
12
- const _hoisted_4 = { class: "x-ai-carousel-suggestion-results" };
11
+ const _hoisted_3 = {
12
+ key: 1,
13
+ class: "x-ai-carousel-suggestions",
14
+ "data-test": "ai-carousel-suggestions-container"
15
+ };
16
+ const _hoisted_4 = {
17
+ class: "x-ai-carousel-suggestion",
18
+ "data-test": "ai-carousel-suggestion"
19
+ };
20
+ const _hoisted_5 = { class: "x-ai-carousel-suggestion-results" };
13
21
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
14
22
  const _component_AIStarIcon = resolveComponent("AIStarIcon");
15
23
  const _component_ChangeHeight = resolveComponent("ChangeHeight");
16
24
  const _component_ChevronDownIcon = resolveComponent("ChevronDownIcon");
17
25
  const _component_DisplayEmitter = resolveComponent("DisplayEmitter");
18
- const _component_DisplayClickProvider = resolveComponent("DisplayClickProvider");
26
+ const _component_AiGroupedCarousel = resolveComponent("AiGroupedCarousel");
27
+ const _component_ArrowRightIcon = resolveComponent("ArrowRightIcon");
28
+ const _component_BaseEventButton = resolveComponent("BaseEventButton");
19
29
  const _component_SlidingPanel = resolveComponent("SlidingPanel");
30
+ const _component_DisplayClickProvider = resolveComponent("DisplayClickProvider");
20
31
  const _component_CollapseHeight = resolveComponent("CollapseHeight");
21
32
  return openBlock(), createBlock(_component_CollapseHeight, null, {
22
33
  default: withCtx(() => [
@@ -74,68 +85,112 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
74
85
  _: 1
75
86
  /* STABLE */
76
87
  }, 8, ["payload", "event-metadata"]),
77
- renderSlot(_ctx.$slots, "sliding-panel", {
78
- suggestions: _ctx.suggestionsSearch,
79
- tagging: _ctx.tagging
80
- }, () => [
81
- createVNode(_component_SlidingPanel, {
82
- class: normalizeClass(_ctx.slidingPanelClasses),
83
- "scroll-container-class": _ctx.slidingPanelContainerClasses,
84
- "button-class": _ctx.slidingPanelButtonsClasses,
85
- "reset-on-content-change": false
86
- }, {
87
- "sliding-panel-addons": withCtx(({ arrivedState }) => [
88
- renderSlot(_ctx.$slots, "sliding-panels-addons", { arrivedState })
89
- ]),
90
- "sliding-panel-left-button": withCtx(() => [
91
- renderSlot(_ctx.$slots, "sliding-panels-left-button")
92
- ]),
93
- "sliding-panel-right-button": withCtx(() => [
94
- renderSlot(_ctx.$slots, "sliding-panels-right-button")
95
- ]),
96
- default: withCtx(() => [
97
- createElementVNode("div", _hoisted_3, [
98
- createElementVNode("ul", _hoisted_4, [
99
- (openBlock(true), createElementBlock(
100
- Fragment,
101
- null,
102
- renderList(_ctx.suggestionsSearch, (suggestion) => {
103
- return openBlock(), createBlock(_component_DisplayClickProvider, {
104
- key: suggestion.query,
105
- "tooling-display-tagging": _ctx.tagging?.searchQueries[suggestion.query].toolingDisplayClick,
106
- "tooling-add2-cart-tagging": _ctx.tagging?.searchQueries[suggestion.query].toolingDisplayAdd2Cart,
107
- "result-feature": "ai_carousel"
108
- }, {
109
- default: withCtx(() => [
110
- (openBlock(true), createElementBlock(
111
- Fragment,
112
- null,
113
- renderList(suggestion.results, (result) => {
114
- return openBlock(), createElementBlock("li", {
115
- key: result.id,
116
- "data-test": "ai-carousel-suggestion-result"
117
- }, [
118
- renderSlot(_ctx.$slots, "result", { result })
119
- ]);
120
- }),
121
- 128
122
- /* KEYED_FRAGMENT */
123
- ))
124
- ]),
125
- _: 2
126
- /* DYNAMIC */
127
- }, 1032, ["tooling-display-tagging", "tooling-add2-cart-tagging"]);
128
- }),
129
- 128
130
- /* KEYED_FRAGMENT */
131
- ))
132
- ])
133
- ])
134
- ]),
135
- _: 3
136
- /* FORWARDED */
137
- }, 8, ["class", "scroll-container-class", "button-class"])
138
- ]),
88
+ _ctx.group ? (openBlock(), createBlock(_component_AiGroupedCarousel, { key: 0 }, {
89
+ "sliding-panel-addons": withCtx(({ arrivedState }) => [
90
+ renderSlot(_ctx.$slots, "sliding-panels-addons", { arrivedState })
91
+ ]),
92
+ "sliding-panel-left-button": withCtx(() => [
93
+ renderSlot(_ctx.$slots, "sliding-panels-left-button")
94
+ ]),
95
+ "sliding-panel-right-button": withCtx(() => [
96
+ renderSlot(_ctx.$slots, "sliding-panels-right-button")
97
+ ]),
98
+ result: withCtx(({ result }) => [
99
+ renderSlot(_ctx.$slots, "result", { result })
100
+ ]),
101
+ _: 3
102
+ /* FORWARDED */
103
+ })) : (openBlock(), createElementBlock("div", _hoisted_3, [
104
+ (openBlock(true), createElementBlock(
105
+ Fragment,
106
+ null,
107
+ renderList(_ctx.suggestionsSearch, ({ query: suggestionQuery, results: queriesResults }) => {
108
+ return openBlock(), createBlock(_component_DisplayEmitter, {
109
+ key: suggestionQuery,
110
+ payload: _ctx.tagging?.searchQueries[suggestionQuery].toolingDisplay ?? _ctx.emptyTaggingRequest,
111
+ "event-metadata": {
112
+ feature: "ai_carousel",
113
+ displayOriginalQuery: _ctx.query || "ai-carousel-without-query",
114
+ replaceable: false
115
+ },
116
+ "data-test": "ai-carousel-query-display-emitter"
117
+ }, {
118
+ default: withCtx(() => [
119
+ createElementVNode("div", _hoisted_4, [
120
+ createVNode(_component_BaseEventButton, {
121
+ class: "x-ai-carousel-suggestion-query-btn",
122
+ events: { UserAcceptedAQuery: suggestionQuery }
123
+ }, {
124
+ default: withCtx(() => [
125
+ createTextVNode(
126
+ toDisplayString(suggestionQuery) + " ",
127
+ 1
128
+ /* TEXT */
129
+ ),
130
+ createVNode(_component_ArrowRightIcon, { class: "x-ai-carousel-suggestion-query-btn-icon" })
131
+ ]),
132
+ _: 2
133
+ /* DYNAMIC */
134
+ }, 1032, ["events"]),
135
+ createVNode(_component_DisplayClickProvider, {
136
+ "tooling-display-tagging": _ctx.tagging?.searchQueries[suggestionQuery].toolingDisplayClick,
137
+ "tooling-add2-cart-tagging": _ctx.tagging?.searchQueries[suggestionQuery].toolingDisplayAdd2Cart,
138
+ "result-feature": "ai_carousel"
139
+ }, {
140
+ default: withCtx(() => [
141
+ renderSlot(_ctx.$slots, "sliding-panel", { results: queriesResults }, () => [
142
+ createVNode(_component_SlidingPanel, {
143
+ class: normalizeClass(_ctx.slidingPanelClasses),
144
+ "scroll-container-class": _ctx.slidingPanelContainerClasses,
145
+ "button-class": _ctx.slidingPanelButtonsClasses,
146
+ "reset-on-content-change": false
147
+ }, {
148
+ "sliding-panel-addons": withCtx(({ arrivedState }) => [
149
+ renderSlot(_ctx.$slots, "sliding-panels-addons", { arrivedState })
150
+ ]),
151
+ "sliding-panel-left-button": withCtx(() => [
152
+ renderSlot(_ctx.$slots, "sliding-panels-left-button")
153
+ ]),
154
+ "sliding-panel-right-button": withCtx(() => [
155
+ renderSlot(_ctx.$slots, "sliding-panels-right-button")
156
+ ]),
157
+ default: withCtx(() => [
158
+ createElementVNode("ul", _hoisted_5, [
159
+ (openBlock(true), createElementBlock(
160
+ Fragment,
161
+ null,
162
+ renderList(queriesResults, (result) => {
163
+ return openBlock(), createElementBlock("li", {
164
+ key: result.id,
165
+ "data-test": "ai-carousel-suggestion-result"
166
+ }, [
167
+ renderSlot(_ctx.$slots, "result", { result })
168
+ ]);
169
+ }),
170
+ 128
171
+ /* KEYED_FRAGMENT */
172
+ ))
173
+ ])
174
+ ]),
175
+ _: 2
176
+ /* DYNAMIC */
177
+ }, 1032, ["class", "scroll-container-class", "button-class"])
178
+ ])
179
+ ]),
180
+ _: 2
181
+ /* DYNAMIC */
182
+ }, 1032, ["tooling-display-tagging", "tooling-add2-cart-tagging"])
183
+ ])
184
+ ]),
185
+ _: 2
186
+ /* DYNAMIC */
187
+ }, 1032, ["payload", "event-metadata"]);
188
+ }),
189
+ 128
190
+ /* KEYED_FRAGMENT */
191
+ )),
192
+ renderSlot(_ctx.$slots, "suggestions-extra-content")
193
+ ])),
139
194
  renderSlot(_ctx.$slots, "extra-content"),
140
195
  renderSlot(_ctx.$slots, "cta-button")
141
196
  ])) : createCommentVNode("v-if", true)
@@ -1 +1 @@
1
- {"version":3,"file":"ai-carousel.vue.js","sources":["../../../../../src/x-modules/ai/components/ai-carousel.vue"],"sourcesContent":["<template>\n <CollapseHeight>\n <div v-if=\"suggestionsSearch.length\" class=\"x-ai-carousel\">\n <DisplayEmitter\n :payload=\"tagging?.toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-display-emitter\"\n >\n <span\n class=\"x-ai-carousel-title\"\n :class=\"{ 'x-ai-carousel-title--expanded': titleExpanded }\"\n data-test=\"ai-carousel-title\"\n @click=\"toggleTitleExpansion\"\n >\n <AIStarIcon class=\"x-ai-carousel-title-icon\" />\n <ChangeHeight>\n <span\n ref=\"titleRef\"\n class=\"x-ai-carousel-title-text\"\n :class=\"{ 'x-ai-carousel-title-text--expanded': titleExpanded }\"\n >\n {{ title }}\n </span>\n </ChangeHeight>\n <button\n v-if=\"isTitleOverflowing\"\n class=\"x-ai-carousel-title-button\"\n data-test=\"ai-carousel-title-button\"\n :aria-label=\"titleExpanded ? 'Collapse' : 'Expand'\"\n >\n <ChevronDownIcon\n class=\"x-ai-carousel-title-button-icon\"\n :class=\"{ 'x-ai-carousel-title-button-icon--expanded': titleExpanded }\"\n />\n </button>\n </span>\n </DisplayEmitter>\n <slot name=\"sliding-panel\" :suggestions=\"suggestionsSearch\" :tagging=\"tagging\">\n <SlidingPanel\n :class=\"slidingPanelClasses\"\n :scroll-container-class=\"slidingPanelContainerClasses\"\n :button-class=\"slidingPanelButtonsClasses\"\n :reset-on-content-change=\"false\"\n >\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <div class=\"x-ai-carousel-suggestion\">\n <ul class=\"x-ai-carousel-suggestion-results\">\n <DisplayClickProvider\n v-for=\"suggestion in suggestionsSearch\"\n :key=\"suggestion.query\"\n :tooling-display-tagging=\"\n tagging?.searchQueries[suggestion.query].toolingDisplayClick\n \"\n :tooling-add2-cart-tagging=\"\n tagging?.searchQueries[suggestion.query].toolingDisplayAdd2Cart\n \"\n result-feature=\"ai_carousel\"\n >\n <li\n v-for=\"result in suggestion.results\"\n :key=\"result.id\"\n data-test=\"ai-carousel-suggestion-result\"\n >\n <!-- @slot (required) result card -->\n <slot name=\"result\" :result=\"result\" />\n </li>\n </DisplayClickProvider>\n </ul>\n </div>\n </SlidingPanel>\n </slot>\n <slot name=\"extra-content\" />\n <slot name=\"cta-button\" />\n </div>\n </CollapseHeight>\n</template>\n\n<script lang=\"ts\">\nimport type { TaggingRequest } from '@empathyco/x-types'\nimport { useResizeObserver } from '@vueuse/core'\nimport { computed, defineComponent, onMounted, ref, watch } from 'vue'\nimport {\n AIStarIcon,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n SlidingPanel,\n} from '../../../components'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport { use$x, useState } from '../../../composables'\nimport { aiXModule } from '../x-module'\n\nexport default defineComponent({\n xModule: aiXModule.name,\n components: {\n ChangeHeight,\n DisplayClickProvider,\n DisplayEmitter,\n CollapseHeight,\n AIStarIcon,\n ChevronDownIcon,\n SlidingPanel,\n },\n props: {\n /* The title text displayed */\n title: {\n type: String,\n },\n /* The classes added to the sliding panel. */\n slidingPanelClasses: {\n type: String,\n },\n /* The classes added to the sliding panel container. */\n slidingPanelContainerClasses: {\n type: String,\n },\n /* The classes added to the sliding panel buttons. */\n slidingPanelButtonsClasses: {\n type: String,\n },\n },\n setup(props) {\n const $x = use$x()\n const { query, isNoResults, suggestionsSearch, queries, tagging } = useState('ai')\n const emptyTaggingRequest: TaggingRequest = { url: '', params: {} }\n\n const titleRef = ref<HTMLElement | null>(null)\n const titleExpanded = ref(false)\n const isTitleOverflowing = ref(false)\n\n /**\n * Checks if the title is overflowing and updates the state.\n */\n function updateTitleOverflow() {\n if (titleExpanded.value) {\n return\n }\n if (titleRef.value) {\n isTitleOverflowing.value = titleRef.value.scrollWidth > titleRef.value.clientWidth\n }\n }\n\n /**\n * Toggles the title expanded state if it is overflowing.\n */\n function toggleTitleExpansion() {\n if (isTitleOverflowing.value) {\n titleExpanded.value = !titleExpanded.value\n }\n }\n\n const title = computed(() => {\n if (!props.title) {\n const queriesList = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n }).format(queries.value.map(({ query }) => query))\n return `Searching for ${queriesList}`\n }\n return props.title\n })\n\n watch(queries, () => {\n if (queries.value.length > 0) {\n $x.emit('AiSuggestionsSearchRequestUpdated')\n }\n })\n\n onMounted(() => {\n $x.emit('AiComponentMounted', undefined, { feature: 'ai_carousel' })\n })\n\n useResizeObserver(titleRef, updateTitleOverflow)\n\n return {\n emptyTaggingRequest,\n isNoResults,\n isTitleOverflowing,\n queries,\n query,\n suggestionsSearch,\n tagging,\n title,\n titleExpanded,\n titleRef,\n toggleTitleExpansion,\n }\n },\n})\n</script>\n<style lang=\"css\">\n.x-ai-carousel {\n --color: var(--x-ai-carousel-color, #bbc9cf);\n --color-lighter: var(--x-ai-carousel-color-lighter, color-mix(in srgb, var(--color) 25%, white));\n\n padding: 8px 0;\n position: relative;\n border-radius: 1.5rem;\n background-color: var(--color-lighter);\n}\n\n.x-ai-carousel-title {\n display: flex;\n font-size: 12px;\n gap: 8px;\n align-items: flex-start;\n margin: 0 14px 8px;\n cursor: pointer;\n}\n.x-ai-carousel-title-text {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.x-ai-carousel-title-text--expanded {\n white-space: normal;\n}\n.x-ai-carousel-title-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n color: var(--color);\n flex-shrink: 0;\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color);\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n transition: transform 0.3s ease;\n}\n.x-ai-carousel-title-button-icon--expanded {\n transform: rotate(180deg);\n}\n\n.x-ai-carousel-suggestion {\n display: flex;\n gap: 8px;\n}\n\n.x-ai-carousel-suggestion-results {\n display: flex;\n gap: 1rem;\n padding-left: 1rem;\n padding-right: 1rem;\n}\n</style>\n"],"names":["_createBlock","_withCtx","_openBlock","_createElementBlock","_createVNode","_createElementVNode","_normalizeClass","_renderSlot","_Fragment","_renderList","_createCommentVNode"],"mappings":"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"}
1
+ {"version":3,"file":"ai-carousel.vue.js","sources":["../../../../../src/x-modules/ai/components/ai-carousel.vue"],"sourcesContent":["<template>\n <CollapseHeight>\n <div v-if=\"suggestionsSearch.length\" class=\"x-ai-carousel\">\n <DisplayEmitter\n :payload=\"tagging?.toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-display-emitter\"\n >\n <span\n class=\"x-ai-carousel-title\"\n :class=\"{ 'x-ai-carousel-title--expanded': titleExpanded }\"\n data-test=\"ai-carousel-title\"\n @click=\"toggleTitleExpansion\"\n >\n <AIStarIcon class=\"x-ai-carousel-title-icon\" />\n <ChangeHeight>\n <span\n ref=\"titleRef\"\n class=\"x-ai-carousel-title-text\"\n :class=\"{ 'x-ai-carousel-title-text--expanded': titleExpanded }\"\n >\n {{ title }}\n </span>\n </ChangeHeight>\n <button\n v-if=\"isTitleOverflowing\"\n class=\"x-ai-carousel-title-button\"\n data-test=\"ai-carousel-title-button\"\n :aria-label=\"titleExpanded ? 'Collapse' : 'Expand'\"\n >\n <ChevronDownIcon\n class=\"x-ai-carousel-title-button-icon\"\n :class=\"{ 'x-ai-carousel-title-button-icon--expanded': titleExpanded }\"\n />\n </button>\n </span>\n </DisplayEmitter>\n\n <AiGroupedCarousel v-if=\"group\">\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <template #result=\"{ result }\">\n <slot name=\"result\" :result=\"result\" />\n </template>\n </AiGroupedCarousel>\n\n <div v-else class=\"x-ai-carousel-suggestions\" data-test=\"ai-carousel-suggestions-container\">\n <DisplayEmitter\n v-for=\"{ query: suggestionQuery, results: queriesResults } in suggestionsSearch\"\n :key=\"suggestionQuery\"\n :payload=\"tagging?.searchQueries[suggestionQuery].toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-query-display-emitter\"\n >\n <div class=\"x-ai-carousel-suggestion\" data-test=\"ai-carousel-suggestion\">\n <BaseEventButton\n class=\"x-ai-carousel-suggestion-query-btn\"\n :events=\"{ UserAcceptedAQuery: suggestionQuery }\"\n >\n {{ suggestionQuery }}\n <ArrowRightIcon class=\"x-ai-carousel-suggestion-query-btn-icon\" />\n </BaseEventButton>\n\n <DisplayClickProvider\n :tooling-display-tagging=\"tagging?.searchQueries[suggestionQuery].toolingDisplayClick\"\n :tooling-add2-cart-tagging=\"\n tagging?.searchQueries[suggestionQuery].toolingDisplayAdd2Cart\n \"\n result-feature=\"ai_carousel\"\n >\n <slot name=\"sliding-panel\" :results=\"queriesResults\">\n <SlidingPanel\n :class=\"slidingPanelClasses\"\n :scroll-container-class=\"slidingPanelContainerClasses\"\n :button-class=\"slidingPanelButtonsClasses\"\n :reset-on-content-change=\"false\"\n >\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <ul class=\"x-ai-carousel-suggestion-results\">\n <li\n v-for=\"result in queriesResults\"\n :key=\"result.id\"\n data-test=\"ai-carousel-suggestion-result\"\n >\n <!-- @slot (required) result card -->\n <slot name=\"result\" :result=\"result\" />\n </li>\n </ul>\n </SlidingPanel>\n </slot>\n </DisplayClickProvider>\n </div>\n </DisplayEmitter>\n <slot name=\"suggestions-extra-content\" />\n </div>\n\n <slot name=\"extra-content\" />\n <slot name=\"cta-button\" />\n </div>\n </CollapseHeight>\n</template>\n\n<script lang=\"ts\">\nimport type { TaggingRequest } from '@empathyco/x-types'\nimport { useResizeObserver } from '@vueuse/core'\nimport { computed, defineComponent, onMounted, ref, watch } from 'vue'\nimport {\n AIStarIcon,\n ArrowRightIcon,\n BaseEventButton,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n DisplayEmitter,\n SlidingPanel,\n} from '../../../components'\nimport { use$x, useState } from '../../../composables'\nimport { aiXModule } from '../x-module'\nimport AiGroupedCarousel from './ai-grouped-carousel.vue'\n\nexport default defineComponent({\n xModule: aiXModule.name,\n components: {\n AIStarIcon,\n AiGroupedCarousel,\n ArrowRightIcon,\n BaseEventButton,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n DisplayEmitter,\n SlidingPanel,\n },\n props: {\n /* The title text displayed */\n title: String,\n /* The classes added to the sliding panel. */\n slidingPanelClasses: String,\n /* The classes added to the sliding panel container. */\n slidingPanelContainerClasses: String,\n /* The classes added to the sliding panel buttons. */\n slidingPanelButtonsClasses: String,\n /* Controls whether the carousel should group results or display N carousels per N queries. */\n group: {\n type: Boolean,\n default: true,\n },\n },\n setup(props) {\n const $x = use$x()\n const { query, suggestionsSearch, queries, tagging } = useState('ai')\n const emptyTaggingRequest: TaggingRequest = { url: '', params: {} }\n\n const titleRef = ref<HTMLElement | null>(null)\n const titleExpanded = ref(false)\n const isTitleOverflowing = ref(false)\n\n /**\n * Checks if the title is overflowing and updates the state.\n */\n function updateTitleOverflow() {\n if (titleExpanded.value) {\n return\n }\n if (titleRef.value) {\n isTitleOverflowing.value = titleRef.value.scrollWidth > titleRef.value.clientWidth\n }\n }\n\n /**\n * Toggles the title expanded state if it is overflowing.\n */\n function toggleTitleExpansion() {\n if (isTitleOverflowing.value) {\n titleExpanded.value = !titleExpanded.value\n }\n }\n\n const title = computed(() => {\n if (!props.title) {\n const queriesList = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n }).format(queries.value.map(({ query }) => query))\n return `Searching for ${queriesList}`\n }\n return props.title\n })\n\n watch(queries, () => {\n if (queries.value.length > 0) {\n $x.emit('AiSuggestionsSearchRequestUpdated')\n }\n })\n\n onMounted(() => {\n $x.emit('AiComponentMounted', undefined, { feature: 'ai_carousel' })\n })\n\n useResizeObserver(titleRef, updateTitleOverflow)\n\n return {\n emptyTaggingRequest,\n isTitleOverflowing,\n queries,\n query,\n suggestionsSearch,\n tagging,\n title,\n titleExpanded,\n titleRef,\n toggleTitleExpansion,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-ai-carousel {\n --color: var(--x-ai-carousel-color, #bbc9cf);\n --color-lighter: var(--x-ai-carousel-color-lighter, color-mix(in srgb, var(--color) 25%, white));\n\n padding: 8px 0;\n position: relative;\n border-radius: 1.5rem;\n background-color: var(--color-lighter);\n}\n\n.x-ai-carousel-title {\n display: flex;\n font-size: 12px;\n gap: 8px;\n align-items: flex-start;\n margin: 0 14px 8px;\n cursor: pointer;\n}\n.x-ai-carousel-title-text {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.x-ai-carousel-title-text--expanded {\n white-space: normal;\n}\n.x-ai-carousel-title-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n color: var(--color);\n flex-shrink: 0;\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color);\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n transition: transform 0.3s ease;\n}\n.x-ai-carousel-title-button-icon--expanded {\n transform: rotate(180deg);\n}\n\n.x-ai-carousel-suggestions {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding-bottom: 1rem;\n}\n\n.x-ai-carousel-suggestion {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.x-ai-carousel-suggestion-query-btn {\n border-color: transparent;\n background-color: transparent;\n margin-left: 1rem;\n margin-right: 1rem;\n font-weight: 700;\n width: fit-content;\n display: flex;\n align-items: center;\n gap: 1rem;\n cursor: pointer;\n}\n\n.x-ai-carousel-suggestion-query-btn-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n}\n\n.x-ai-carousel-suggestion-results {\n display: flex;\n gap: 1rem;\n padding-left: 1rem;\n padding-right: 1rem;\n}\n</style>\n"],"names":["_createBlock","_withCtx","_openBlock","_createElementBlock","_createVNode","_createElementVNode","_normalizeClass","_renderSlot","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode"],"mappings":"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"}
@@ -22,7 +22,7 @@ import '../../../components/auto-progress-bar.vue2.js';
22
22
  import '../../../components/auto-progress-bar.vue3.js';
23
23
  import '../../../components/base-dropdown.vue2.js';
24
24
  import '../../../components/base-dropdown.vue3.js';
25
- import '../../../components/base-event-button.vue2.js';
25
+ import BaseEventButton from '../../../components/base-event-button.vue.js';
26
26
  import '../../../components/base-grid.vue2.js';
27
27
  import '../../../components/base-grid.vue3.js';
28
28
  import '../../../components/base-keyboard-navigation.vue2.js';
@@ -44,6 +44,7 @@ import '../../../components/filters/labels/base-rating-filter-label.vue2.js';
44
44
  import '../../../components/global-x-bus.vue.js';
45
45
  import '../../../components/highlight.vue2.js';
46
46
  import AIStarIcon from '../../../components/icons/ai-star.vue.js';
47
+ import ArrowRightIcon from '../../../components/icons/arrow-right.vue.js';
47
48
  import ChevronDownIcon from '../../../components/icons/chevron-down.vue.js';
48
49
  import '../../../components/items-list.vue2.js';
49
50
  import '../../../components/location-provider.vue.js';
@@ -96,39 +97,40 @@ import '../../../plugins/x-plugin.js';
96
97
  import 'rxjs';
97
98
  import { useState } from '../../../composables/use-state.js';
98
99
  import { aiXModule } from '../x-module.js';
100
+ import AiGroupedCarousel from './ai-grouped-carousel.vue.js';
99
101
 
100
102
  var _sfc_main = defineComponent({
101
103
  xModule: aiXModule.name,
102
104
  components: {
105
+ AIStarIcon,
106
+ AiGroupedCarousel,
107
+ ArrowRightIcon,
108
+ BaseEventButton,
103
109
  ChangeHeight,
110
+ ChevronDownIcon,
111
+ CollapseHeight,
104
112
  DisplayClickProvider: _sfc_main$2,
105
113
  DisplayEmitter: _sfc_main$1,
106
- CollapseHeight,
107
- AIStarIcon,
108
- ChevronDownIcon,
109
114
  SlidingPanel,
110
115
  },
111
116
  props: {
112
117
  /* The title text displayed */
113
- title: {
114
- type: String,
115
- },
118
+ title: String,
116
119
  /* The classes added to the sliding panel. */
117
- slidingPanelClasses: {
118
- type: String,
119
- },
120
+ slidingPanelClasses: String,
120
121
  /* The classes added to the sliding panel container. */
121
- slidingPanelContainerClasses: {
122
- type: String,
123
- },
122
+ slidingPanelContainerClasses: String,
124
123
  /* The classes added to the sliding panel buttons. */
125
- slidingPanelButtonsClasses: {
126
- type: String,
124
+ slidingPanelButtonsClasses: String,
125
+ /* Controls whether the carousel should group results or display N carousels per N queries. */
126
+ group: {
127
+ type: Boolean,
128
+ default: true,
127
129
  },
128
130
  },
129
131
  setup(props) {
130
132
  const $x = use$x();
131
- const { query, isNoResults, suggestionsSearch, queries, tagging } = useState('ai');
133
+ const { query, suggestionsSearch, queries, tagging } = useState('ai');
132
134
  const emptyTaggingRequest = { url: '', params: {} };
133
135
  const titleRef = ref(null);
134
136
  const titleExpanded = ref(false);
@@ -173,7 +175,6 @@ var _sfc_main = defineComponent({
173
175
  useResizeObserver(titleRef, updateTitleOverflow);
174
176
  return {
175
177
  emptyTaggingRequest,
176
- isNoResults,
177
178
  isTitleOverflowing,
178
179
  queries,
179
180
  query,
@@ -1 +1 @@
1
- {"version":3,"file":"ai-carousel.vue2.js","sources":["../../../../../src/x-modules/ai/components/ai-carousel.vue"],"sourcesContent":["<template>\n <CollapseHeight>\n <div v-if=\"suggestionsSearch.length\" class=\"x-ai-carousel\">\n <DisplayEmitter\n :payload=\"tagging?.toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-display-emitter\"\n >\n <span\n class=\"x-ai-carousel-title\"\n :class=\"{ 'x-ai-carousel-title--expanded': titleExpanded }\"\n data-test=\"ai-carousel-title\"\n @click=\"toggleTitleExpansion\"\n >\n <AIStarIcon class=\"x-ai-carousel-title-icon\" />\n <ChangeHeight>\n <span\n ref=\"titleRef\"\n class=\"x-ai-carousel-title-text\"\n :class=\"{ 'x-ai-carousel-title-text--expanded': titleExpanded }\"\n >\n {{ title }}\n </span>\n </ChangeHeight>\n <button\n v-if=\"isTitleOverflowing\"\n class=\"x-ai-carousel-title-button\"\n data-test=\"ai-carousel-title-button\"\n :aria-label=\"titleExpanded ? 'Collapse' : 'Expand'\"\n >\n <ChevronDownIcon\n class=\"x-ai-carousel-title-button-icon\"\n :class=\"{ 'x-ai-carousel-title-button-icon--expanded': titleExpanded }\"\n />\n </button>\n </span>\n </DisplayEmitter>\n <slot name=\"sliding-panel\" :suggestions=\"suggestionsSearch\" :tagging=\"tagging\">\n <SlidingPanel\n :class=\"slidingPanelClasses\"\n :scroll-container-class=\"slidingPanelContainerClasses\"\n :button-class=\"slidingPanelButtonsClasses\"\n :reset-on-content-change=\"false\"\n >\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <div class=\"x-ai-carousel-suggestion\">\n <ul class=\"x-ai-carousel-suggestion-results\">\n <DisplayClickProvider\n v-for=\"suggestion in suggestionsSearch\"\n :key=\"suggestion.query\"\n :tooling-display-tagging=\"\n tagging?.searchQueries[suggestion.query].toolingDisplayClick\n \"\n :tooling-add2-cart-tagging=\"\n tagging?.searchQueries[suggestion.query].toolingDisplayAdd2Cart\n \"\n result-feature=\"ai_carousel\"\n >\n <li\n v-for=\"result in suggestion.results\"\n :key=\"result.id\"\n data-test=\"ai-carousel-suggestion-result\"\n >\n <!-- @slot (required) result card -->\n <slot name=\"result\" :result=\"result\" />\n </li>\n </DisplayClickProvider>\n </ul>\n </div>\n </SlidingPanel>\n </slot>\n <slot name=\"extra-content\" />\n <slot name=\"cta-button\" />\n </div>\n </CollapseHeight>\n</template>\n\n<script lang=\"ts\">\nimport type { TaggingRequest } from '@empathyco/x-types'\nimport { useResizeObserver } from '@vueuse/core'\nimport { computed, defineComponent, onMounted, ref, watch } from 'vue'\nimport {\n AIStarIcon,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n SlidingPanel,\n} from '../../../components'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport { use$x, useState } from '../../../composables'\nimport { aiXModule } from '../x-module'\n\nexport default defineComponent({\n xModule: aiXModule.name,\n components: {\n ChangeHeight,\n DisplayClickProvider,\n DisplayEmitter,\n CollapseHeight,\n AIStarIcon,\n ChevronDownIcon,\n SlidingPanel,\n },\n props: {\n /* The title text displayed */\n title: {\n type: String,\n },\n /* The classes added to the sliding panel. */\n slidingPanelClasses: {\n type: String,\n },\n /* The classes added to the sliding panel container. */\n slidingPanelContainerClasses: {\n type: String,\n },\n /* The classes added to the sliding panel buttons. */\n slidingPanelButtonsClasses: {\n type: String,\n },\n },\n setup(props) {\n const $x = use$x()\n const { query, isNoResults, suggestionsSearch, queries, tagging } = useState('ai')\n const emptyTaggingRequest: TaggingRequest = { url: '', params: {} }\n\n const titleRef = ref<HTMLElement | null>(null)\n const titleExpanded = ref(false)\n const isTitleOverflowing = ref(false)\n\n /**\n * Checks if the title is overflowing and updates the state.\n */\n function updateTitleOverflow() {\n if (titleExpanded.value) {\n return\n }\n if (titleRef.value) {\n isTitleOverflowing.value = titleRef.value.scrollWidth > titleRef.value.clientWidth\n }\n }\n\n /**\n * Toggles the title expanded state if it is overflowing.\n */\n function toggleTitleExpansion() {\n if (isTitleOverflowing.value) {\n titleExpanded.value = !titleExpanded.value\n }\n }\n\n const title = computed(() => {\n if (!props.title) {\n const queriesList = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n }).format(queries.value.map(({ query }) => query))\n return `Searching for ${queriesList}`\n }\n return props.title\n })\n\n watch(queries, () => {\n if (queries.value.length > 0) {\n $x.emit('AiSuggestionsSearchRequestUpdated')\n }\n })\n\n onMounted(() => {\n $x.emit('AiComponentMounted', undefined, { feature: 'ai_carousel' })\n })\n\n useResizeObserver(titleRef, updateTitleOverflow)\n\n return {\n emptyTaggingRequest,\n isNoResults,\n isTitleOverflowing,\n queries,\n query,\n suggestionsSearch,\n tagging,\n title,\n titleExpanded,\n titleRef,\n toggleTitleExpansion,\n }\n },\n})\n</script>\n<style lang=\"css\">\n.x-ai-carousel {\n --color: var(--x-ai-carousel-color, #bbc9cf);\n --color-lighter: var(--x-ai-carousel-color-lighter, color-mix(in srgb, var(--color) 25%, white));\n\n padding: 8px 0;\n position: relative;\n border-radius: 1.5rem;\n background-color: var(--color-lighter);\n}\n\n.x-ai-carousel-title {\n display: flex;\n font-size: 12px;\n gap: 8px;\n align-items: flex-start;\n margin: 0 14px 8px;\n cursor: pointer;\n}\n.x-ai-carousel-title-text {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.x-ai-carousel-title-text--expanded {\n white-space: normal;\n}\n.x-ai-carousel-title-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n color: var(--color);\n flex-shrink: 0;\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color);\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n transition: transform 0.3s ease;\n}\n.x-ai-carousel-title-button-icon--expanded {\n transform: rotate(180deg);\n}\n\n.x-ai-carousel-suggestion {\n display: flex;\n gap: 8px;\n}\n\n.x-ai-carousel-suggestion-results {\n display: flex;\n gap: 1rem;\n padding-left: 1rem;\n padding-right: 1rem;\n}\n</style>\n"],"names":["DisplayClickProvider","DisplayEmitter"],"mappings":"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"}
1
+ {"version":3,"file":"ai-carousel.vue2.js","sources":["../../../../../src/x-modules/ai/components/ai-carousel.vue"],"sourcesContent":["<template>\n <CollapseHeight>\n <div v-if=\"suggestionsSearch.length\" class=\"x-ai-carousel\">\n <DisplayEmitter\n :payload=\"tagging?.toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-display-emitter\"\n >\n <span\n class=\"x-ai-carousel-title\"\n :class=\"{ 'x-ai-carousel-title--expanded': titleExpanded }\"\n data-test=\"ai-carousel-title\"\n @click=\"toggleTitleExpansion\"\n >\n <AIStarIcon class=\"x-ai-carousel-title-icon\" />\n <ChangeHeight>\n <span\n ref=\"titleRef\"\n class=\"x-ai-carousel-title-text\"\n :class=\"{ 'x-ai-carousel-title-text--expanded': titleExpanded }\"\n >\n {{ title }}\n </span>\n </ChangeHeight>\n <button\n v-if=\"isTitleOverflowing\"\n class=\"x-ai-carousel-title-button\"\n data-test=\"ai-carousel-title-button\"\n :aria-label=\"titleExpanded ? 'Collapse' : 'Expand'\"\n >\n <ChevronDownIcon\n class=\"x-ai-carousel-title-button-icon\"\n :class=\"{ 'x-ai-carousel-title-button-icon--expanded': titleExpanded }\"\n />\n </button>\n </span>\n </DisplayEmitter>\n\n <AiGroupedCarousel v-if=\"group\">\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <template #result=\"{ result }\">\n <slot name=\"result\" :result=\"result\" />\n </template>\n </AiGroupedCarousel>\n\n <div v-else class=\"x-ai-carousel-suggestions\" data-test=\"ai-carousel-suggestions-container\">\n <DisplayEmitter\n v-for=\"{ query: suggestionQuery, results: queriesResults } in suggestionsSearch\"\n :key=\"suggestionQuery\"\n :payload=\"tagging?.searchQueries[suggestionQuery].toolingDisplay ?? emptyTaggingRequest\"\n :event-metadata=\"{\n feature: 'ai_carousel',\n displayOriginalQuery: query || 'ai-carousel-without-query',\n replaceable: false,\n }\"\n data-test=\"ai-carousel-query-display-emitter\"\n >\n <div class=\"x-ai-carousel-suggestion\" data-test=\"ai-carousel-suggestion\">\n <BaseEventButton\n class=\"x-ai-carousel-suggestion-query-btn\"\n :events=\"{ UserAcceptedAQuery: suggestionQuery }\"\n >\n {{ suggestionQuery }}\n <ArrowRightIcon class=\"x-ai-carousel-suggestion-query-btn-icon\" />\n </BaseEventButton>\n\n <DisplayClickProvider\n :tooling-display-tagging=\"tagging?.searchQueries[suggestionQuery].toolingDisplayClick\"\n :tooling-add2-cart-tagging=\"\n tagging?.searchQueries[suggestionQuery].toolingDisplayAdd2Cart\n \"\n result-feature=\"ai_carousel\"\n >\n <slot name=\"sliding-panel\" :results=\"queriesResults\">\n <SlidingPanel\n :class=\"slidingPanelClasses\"\n :scroll-container-class=\"slidingPanelContainerClasses\"\n :button-class=\"slidingPanelButtonsClasses\"\n :reset-on-content-change=\"false\"\n >\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <ul class=\"x-ai-carousel-suggestion-results\">\n <li\n v-for=\"result in queriesResults\"\n :key=\"result.id\"\n data-test=\"ai-carousel-suggestion-result\"\n >\n <!-- @slot (required) result card -->\n <slot name=\"result\" :result=\"result\" />\n </li>\n </ul>\n </SlidingPanel>\n </slot>\n </DisplayClickProvider>\n </div>\n </DisplayEmitter>\n <slot name=\"suggestions-extra-content\" />\n </div>\n\n <slot name=\"extra-content\" />\n <slot name=\"cta-button\" />\n </div>\n </CollapseHeight>\n</template>\n\n<script lang=\"ts\">\nimport type { TaggingRequest } from '@empathyco/x-types'\nimport { useResizeObserver } from '@vueuse/core'\nimport { computed, defineComponent, onMounted, ref, watch } from 'vue'\nimport {\n AIStarIcon,\n ArrowRightIcon,\n BaseEventButton,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n DisplayEmitter,\n SlidingPanel,\n} from '../../../components'\nimport { use$x, useState } from '../../../composables'\nimport { aiXModule } from '../x-module'\nimport AiGroupedCarousel from './ai-grouped-carousel.vue'\n\nexport default defineComponent({\n xModule: aiXModule.name,\n components: {\n AIStarIcon,\n AiGroupedCarousel,\n ArrowRightIcon,\n BaseEventButton,\n ChangeHeight,\n ChevronDownIcon,\n CollapseHeight,\n DisplayClickProvider,\n DisplayEmitter,\n SlidingPanel,\n },\n props: {\n /* The title text displayed */\n title: String,\n /* The classes added to the sliding panel. */\n slidingPanelClasses: String,\n /* The classes added to the sliding panel container. */\n slidingPanelContainerClasses: String,\n /* The classes added to the sliding panel buttons. */\n slidingPanelButtonsClasses: String,\n /* Controls whether the carousel should group results or display N carousels per N queries. */\n group: {\n type: Boolean,\n default: true,\n },\n },\n setup(props) {\n const $x = use$x()\n const { query, suggestionsSearch, queries, tagging } = useState('ai')\n const emptyTaggingRequest: TaggingRequest = { url: '', params: {} }\n\n const titleRef = ref<HTMLElement | null>(null)\n const titleExpanded = ref(false)\n const isTitleOverflowing = ref(false)\n\n /**\n * Checks if the title is overflowing and updates the state.\n */\n function updateTitleOverflow() {\n if (titleExpanded.value) {\n return\n }\n if (titleRef.value) {\n isTitleOverflowing.value = titleRef.value.scrollWidth > titleRef.value.clientWidth\n }\n }\n\n /**\n * Toggles the title expanded state if it is overflowing.\n */\n function toggleTitleExpansion() {\n if (isTitleOverflowing.value) {\n titleExpanded.value = !titleExpanded.value\n }\n }\n\n const title = computed(() => {\n if (!props.title) {\n const queriesList = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n }).format(queries.value.map(({ query }) => query))\n return `Searching for ${queriesList}`\n }\n return props.title\n })\n\n watch(queries, () => {\n if (queries.value.length > 0) {\n $x.emit('AiSuggestionsSearchRequestUpdated')\n }\n })\n\n onMounted(() => {\n $x.emit('AiComponentMounted', undefined, { feature: 'ai_carousel' })\n })\n\n useResizeObserver(titleRef, updateTitleOverflow)\n\n return {\n emptyTaggingRequest,\n isTitleOverflowing,\n queries,\n query,\n suggestionsSearch,\n tagging,\n title,\n titleExpanded,\n titleRef,\n toggleTitleExpansion,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-ai-carousel {\n --color: var(--x-ai-carousel-color, #bbc9cf);\n --color-lighter: var(--x-ai-carousel-color-lighter, color-mix(in srgb, var(--color) 25%, white));\n\n padding: 8px 0;\n position: relative;\n border-radius: 1.5rem;\n background-color: var(--color-lighter);\n}\n\n.x-ai-carousel-title {\n display: flex;\n font-size: 12px;\n gap: 8px;\n align-items: flex-start;\n margin: 0 14px 8px;\n cursor: pointer;\n}\n.x-ai-carousel-title-text {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.x-ai-carousel-title-text--expanded {\n white-space: normal;\n}\n.x-ai-carousel-title-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n color: var(--color);\n flex-shrink: 0;\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color);\n margin-bottom: auto;\n}\n.x-ai-carousel-title-button-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n transition: transform 0.3s ease;\n}\n.x-ai-carousel-title-button-icon--expanded {\n transform: rotate(180deg);\n}\n\n.x-ai-carousel-suggestions {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding-bottom: 1rem;\n}\n\n.x-ai-carousel-suggestion {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.x-ai-carousel-suggestion-query-btn {\n border-color: transparent;\n background-color: transparent;\n margin-left: 1rem;\n margin-right: 1rem;\n font-weight: 700;\n width: fit-content;\n display: flex;\n align-items: center;\n gap: 1rem;\n cursor: pointer;\n}\n\n.x-ai-carousel-suggestion-query-btn-icon {\n height: 1rem;\n aspect-ratio: 1 / 1;\n}\n\n.x-ai-carousel-suggestion-results {\n display: flex;\n gap: 1rem;\n padding-left: 1rem;\n padding-right: 1rem;\n}\n</style>\n"],"names":["DisplayClickProvider","DisplayEmitter"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import injectCss from '../../../../tools/inject-css.js';
2
2
 
3
- var css = ".x-ai-carousel{--color:var(--x-ai-carousel-color,#bbc9cf);--color-lighter:var(--x-ai-carousel-color-lighter,color-mix(in srgb,var(--color) 25%,#fff));background-color:var(--color-lighter);border-radius:1.5rem;padding:8px 0;position:relative}.x-ai-carousel-title{align-items:flex-start;cursor:pointer;display:flex;font-size:12px;gap:8px;margin:0 14px 8px}.x-ai-carousel-title-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.x-ai-carousel-title-text--expanded{white-space:normal}.x-ai-carousel-title-icon{aspect-ratio:1/1;color:var(--color);flex-shrink:0;height:1rem;margin-bottom:auto}.x-ai-carousel-title-button{align-items:center;background:none;border:none;color:var(--color);cursor:pointer;display:flex;justify-content:center;margin-bottom:auto;padding:0}.x-ai-carousel-title-button-icon{aspect-ratio:1/1;height:1rem;transition:transform .3s ease}.x-ai-carousel-title-button-icon--expanded{transform:rotate(180deg)}.x-ai-carousel-suggestion{display:flex;gap:8px}.x-ai-carousel-suggestion-results{display:flex;gap:1rem;padding-left:1rem;padding-right:1rem}";
3
+ var css = ".x-ai-carousel{--color:var(--x-ai-carousel-color,#bbc9cf);--color-lighter:var(--x-ai-carousel-color-lighter,color-mix(in srgb,var(--color) 25%,#fff));background-color:var(--color-lighter);border-radius:1.5rem;padding:8px 0;position:relative}.x-ai-carousel-title{align-items:flex-start;cursor:pointer;display:flex;font-size:12px;gap:8px;margin:0 14px 8px}.x-ai-carousel-title-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.x-ai-carousel-title-text--expanded{white-space:normal}.x-ai-carousel-title-icon{aspect-ratio:1/1;color:var(--color);flex-shrink:0;height:1rem;margin-bottom:auto}.x-ai-carousel-title-button{align-items:center;background:none;border:none;color:var(--color);cursor:pointer;display:flex;justify-content:center;margin-bottom:auto;padding:0}.x-ai-carousel-title-button-icon{aspect-ratio:1/1;height:1rem;transition:transform .3s ease}.x-ai-carousel-title-button-icon--expanded{transform:rotate(180deg)}.x-ai-carousel-suggestions{display:flex;flex-direction:column;gap:.5rem;padding-bottom:1rem}.x-ai-carousel-suggestion{display:flex;flex-direction:column;gap:8px}.x-ai-carousel-suggestion-query-btn{align-items:center;background-color:transparent;border-color:transparent;cursor:pointer;display:flex;font-weight:700;gap:1rem;margin-left:1rem;margin-right:1rem;width:fit-content}.x-ai-carousel-suggestion-query-btn-icon{aspect-ratio:1/1;height:1rem}.x-ai-carousel-suggestion-results{display:flex;gap:1rem;padding-left:1rem;padding-right:1rem}";
4
4
  injectCss(css);
5
5
 
6
6
  export { css };
@@ -0,0 +1,68 @@
1
+ import _sfc_main from './ai-grouped-carousel.vue2.js';
2
+ import { resolveComponent, openBlock, createBlock, normalizeClass, withCtx, createElementVNode, createElementBlock, Fragment, renderList, renderSlot } from 'vue';
3
+ import _export_sfc from '../../../_virtual/_plugin-vue_export-helper.js';
4
+
5
+ const _hoisted_1 = { class: "x-ai-carousel-suggestion-results" };
6
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
7
+ const _component_DisplayClickProvider = resolveComponent("DisplayClickProvider");
8
+ const _component_SlidingPanel = resolveComponent("SlidingPanel");
9
+ return openBlock(), createBlock(_component_SlidingPanel, {
10
+ class: normalizeClass(_ctx.slidingPanelClasses),
11
+ "scroll-container-class": _ctx.slidingPanelContainerClasses,
12
+ "button-class": _ctx.slidingPanelButtonsClasses,
13
+ "reset-on-content-change": false
14
+ }, {
15
+ "sliding-panel-addons": withCtx(({ arrivedState }) => [
16
+ renderSlot(_ctx.$slots, "sliding-panels-addons", { arrivedState })
17
+ ]),
18
+ "sliding-panel-left-button": withCtx(() => [
19
+ renderSlot(_ctx.$slots, "sliding-panels-left-button")
20
+ ]),
21
+ "sliding-panel-right-button": withCtx(() => [
22
+ renderSlot(_ctx.$slots, "sliding-panels-right-button")
23
+ ]),
24
+ default: withCtx(() => [
25
+ createElementVNode("ul", _hoisted_1, [
26
+ (openBlock(true), createElementBlock(
27
+ Fragment,
28
+ null,
29
+ renderList(_ctx.suggestionsSearch, (suggestion) => {
30
+ return openBlock(), createBlock(_component_DisplayClickProvider, {
31
+ key: suggestion.query,
32
+ "tooling-display-tagging": _ctx.tagging?.searchQueries[suggestion.query].toolingDisplayClick,
33
+ "tooling-add2-cart-tagging": _ctx.tagging?.searchQueries[suggestion.query].toolingDisplayAdd2Cart,
34
+ "result-feature": "ai_carousel"
35
+ }, {
36
+ default: withCtx(() => [
37
+ (openBlock(true), createElementBlock(
38
+ Fragment,
39
+ null,
40
+ renderList(suggestion.results, (result) => {
41
+ return openBlock(), createElementBlock("li", {
42
+ key: result.id,
43
+ "data-test": "ai-carousel-suggestion-result"
44
+ }, [
45
+ renderSlot(_ctx.$slots, "result", { result })
46
+ ]);
47
+ }),
48
+ 128
49
+ /* KEYED_FRAGMENT */
50
+ ))
51
+ ]),
52
+ _: 2
53
+ /* DYNAMIC */
54
+ }, 1032, ["tooling-display-tagging", "tooling-add2-cart-tagging"]);
55
+ }),
56
+ 128
57
+ /* KEYED_FRAGMENT */
58
+ ))
59
+ ])
60
+ ]),
61
+ _: 3
62
+ /* FORWARDED */
63
+ }, 8, ["class", "scroll-container-class", "button-class"]);
64
+ }
65
+ var AiGroupedCarousel = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
66
+
67
+ export { AiGroupedCarousel as default };
68
+ //# sourceMappingURL=ai-grouped-carousel.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-grouped-carousel.vue.js","sources":["../../../../../src/x-modules/ai/components/ai-grouped-carousel.vue"],"sourcesContent":["<template>\n <SlidingPanel\n :class=\"slidingPanelClasses\"\n :scroll-container-class=\"slidingPanelContainerClasses\"\n :button-class=\"slidingPanelButtonsClasses\"\n :reset-on-content-change=\"false\"\n >\n <template #sliding-panel-addons=\"{ arrivedState }\">\n <slot name=\"sliding-panels-addons\" :arrived-state=\"arrivedState\" />\n </template>\n <template #sliding-panel-left-button>\n <slot name=\"sliding-panels-left-button\" />\n </template>\n <template #sliding-panel-right-button>\n <slot name=\"sliding-panels-right-button\" />\n </template>\n <ul class=\"x-ai-carousel-suggestion-results\">\n <DisplayClickProvider\n v-for=\"suggestion in suggestionsSearch\"\n :key=\"suggestion.query\"\n :tooling-display-tagging=\"tagging?.searchQueries[suggestion.query].toolingDisplayClick\"\n :tooling-add2-cart-tagging=\"tagging?.searchQueries[suggestion.query].toolingDisplayAdd2Cart\"\n result-feature=\"ai_carousel\"\n >\n <li\n v-for=\"result in suggestion.results\"\n :key=\"result.id\"\n data-test=\"ai-carousel-suggestion-result\"\n >\n <!-- @slot (required) result card -->\n <slot name=\"result\" :result=\"result\" />\n </li>\n </DisplayClickProvider>\n </ul>\n </SlidingPanel>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { DisplayClickProvider, SlidingPanel } from '../../../components'\nimport { useState } from '../../../composables'\n\nexport default defineComponent({\n components: {\n DisplayClickProvider,\n SlidingPanel,\n },\n props: {\n /* The title text displayed */\n title: String,\n /* The classes added to the sliding panel. */\n slidingPanelClasses: String,\n /* The classes added to the sliding panel container. */\n slidingPanelContainerClasses: String,\n /* The classes added to the sliding panel buttons. */\n slidingPanelButtonsClasses: String,\n },\n setup() {\n const { suggestionsSearch, tagging } = useState('ai')\n\n return {\n suggestionsSearch,\n tagging,\n }\n },\n})\n</script>\n"],"names":["_createBlock","_normalizeClass","_withCtx","_renderSlot","_createElementVNode","_openBlock","_createElementBlock","_Fragment","_renderList"],"mappings":";;;;AAgBQ,MAAA,UAAA,GAAA,EAAA,KAAA,EAAM,kCAAA,EAAkC;;;;sBAf9CA,WAAA,CAiCe,uBAAA,EAAA;AAAA,IAhCZ,KAAA,EAAKC,eAAE,IAAA,CAAA,mBAAmB,CAAA;AAAA,IAC1B,wBAAA,EAAwB,IAAA,CAAA,4BAAA;AAAA,IACxB,cAAA,EAAc,IAAA,CAAA,0BAAA;AAAA,IACd,yBAAA,EAAyB;AAAA,GAAA,EAAA;IAEf,sBAAA,EAAoBC,OAAA,CAC7B,CAAmE,EADlC,YAAA,EAAY,KAAA;AAAA,MAC7CC,UAAA,CAAmE,wCAA/B,YAAA,EAA2B;AAAA,KAAA,CAAA;AAEtD,IAAA,2BAAA,EAAyBD,QAClC,MAA0C;AAAA,MAA1CC,UAAA,CAA0C,IAAA,CAAA,MAAA,EAAA,4BAAA;AAAA,KAAA,CAAA;AAEjC,IAAA,4BAAA,EAA0BD,QACnC,MAA2C;AAAA,MAA3CC,UAAA,CAA2C,IAAA,CAAA,MAAA,EAAA,6BAAA;AAAA,KAAA,CAAA;qBAE7C,MAiBK;AAAA,MAjBLC,kBAAA,CAiBK,MAjBL,UAAA,EAiBK;AAAA,SAAAC,SAAA,CAAA,IAAA,CAAA,EAhBHC,kBAAA;AAAA,UAeuBC,QAAA;AAAA,UAAA,IAAA;AAAA,UAAAC,UAAA,CAdA,IAAA,CAAA,iBAAA,EAAiB,CAA/B,UAAA,KAAU;gCADnBR,WAAA,CAeuB,+BAAA,EAAA;AAAA,cAbpB,KAAK,UAAA,CAAW,KAAA;AAAA,cAChB,yBAAA,EAAyB,IAAA,CAAA,OAAA,EAAS,aAAA,CAAc,UAAA,CAAW,KAAK,CAAA,CAAE,mBAAA;AAAA,cAClE,2BAAA,EAA2B,IAAA,CAAA,OAAA,EAAS,aAAA,CAAc,UAAA,CAAW,KAAK,CAAA,CAAE,sBAAA;AAAA,cACrE,gBAAA,EAAe;AAAA,aAAA,EAAA;+BAGb,MAAoC;AAAA,iBAAAK,SAAA,CAAA,IAAA,CAAA,EADtCC,kBAAA;AAAA,kBAOKC,QAAA;AAAA,kBAAA,IAAA;AAAA,kBAAAC,UAAA,CANc,UAAA,CAAW,OAAA,EAAO,CAA5B,MAAA,KAAM;wCADfF,kBAAA,CAOK,IAAA,EAAA;AAAA,sBALF,KAAK,MAAA,CAAO,EAAA;AAAA,sBACb,WAAA,EAAU;AAAA,qBAAA,EAAA;AAGV,sBAAAH,UAAA,CAAuC,yBAAlB,MAAA,EAAc;AAAA,qBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;"}