@empathyco/x-components 6.2.0 → 6.2.2
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 +15 -0
- package/docs/API-reference/api/x-components.slidingpanel.md +9 -0
- package/docs/API-reference/components/common/x-components.sliding-panel.md +1 -0
- package/js/components/sliding-panel.vue.js +1 -1
- package/js/components/sliding-panel.vue.js.map +1 -1
- package/js/components/sliding-panel.vue2.js +7 -0
- package/js/components/sliding-panel.vue2.js.map +1 -1
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue.js +2 -1
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue.js.map +1 -1
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue2.js.map +1 -1
- package/package.json +15 -15
- package/report/x-components.api.json +20 -2
- package/report/x-components.api.md +9 -0
- package/types/src/components/sliding-panel.vue.d.ts +15 -0
- package/types/src/components/sliding-panel.vue.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [6.2.2](https://github.com/empathyco/x/compare/@empathyco/x-components@6.2.1...@empathyco/x-components@6.2.2) (2026-05-18)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @empathyco/x-components
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [6.2.1](https://github.com/empathyco/x/compare/@empathyco/x-components@6.2.0...@empathyco/x-components@6.2.1) (2026-05-12)
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **x-components:** add optional sliding panel fade for related prompts (#2103)
|
|
19
|
+
|
|
20
|
+
|
|
6
21
|
## [6.2.0](https://github.com/empathyco/x/compare/@empathyco/x-components@6.1.4...@empathyco/x-components@6.2.0) (2026-05-11)
|
|
7
22
|
|
|
8
23
|
### Features
|
|
@@ -24,6 +24,10 @@ _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
|
24
24
|
type: BooleanConstructor;
|
|
25
25
|
default: boolean;
|
|
26
26
|
};
|
|
27
|
+
fade: {
|
|
28
|
+
type: BooleanConstructor;
|
|
29
|
+
default: boolean;
|
|
30
|
+
};
|
|
27
31
|
buttonClass: {
|
|
28
32
|
type: PropType<VueCSSClasses>;
|
|
29
33
|
};
|
|
@@ -60,6 +64,10 @@ _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
|
60
64
|
type: BooleanConstructor;
|
|
61
65
|
default: boolean;
|
|
62
66
|
};
|
|
67
|
+
fade: {
|
|
68
|
+
type: BooleanConstructor;
|
|
69
|
+
default: boolean;
|
|
70
|
+
};
|
|
63
71
|
buttonClass: {
|
|
64
72
|
type: PropType<VueCSSClasses>;
|
|
65
73
|
};
|
|
@@ -70,5 +78,6 @@ _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
|
70
78
|
scrollFactor: number;
|
|
71
79
|
showButtons: boolean;
|
|
72
80
|
resetOnContentChange: boolean;
|
|
81
|
+
fade: boolean;
|
|
73
82
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>
|
|
74
83
|
```
|
|
@@ -20,6 +20,7 @@ elements: `buttonClass`.
|
|
|
20
20
|
| <code>scrollFactor</code> | Scroll factor that will dictate how much the scroll moves when pressing a navigation button. | <code>number</code> | <code>0.7</code> |
|
|
21
21
|
| <code>showButtons</code> | Would make the navigation buttons visible when they're needed or always hide them. | <code>boolean</code> | <code>true</code> |
|
|
22
22
|
| <code>resetOnContentChange</code> | When true, whenever the DOM content in the sliding panel slot changes, it will reset<br />the scroll position to 0. | <code>boolean</code> | <code>true</code> |
|
|
23
|
+
| <code>fade</code> | When true, applies the design-system edge fade mask to the scroll container. | <code>boolean</code> | <code>true</code> |
|
|
23
24
|
| <code>buttonClass</code> | | <code>VueCSSClasses</code> | <code></code> |
|
|
24
25
|
| <code>scrollContainerClass</code> | | <code>VueCSSClasses</code> | <code></code> |
|
|
25
26
|
|
|
@@ -16,7 +16,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
16
16
|
"div",
|
|
17
17
|
{
|
|
18
18
|
ref: "scrollContainerRef",
|
|
19
|
-
class: normalizeClass([
|
|
19
|
+
class: normalizeClass(["x-sliding-panel__scroll", [_ctx.scrollContainerClass, { "xds:sliding-panel-fade": _ctx.fade }]]),
|
|
20
20
|
"data-test": "sliding-panel-scroll"
|
|
21
21
|
},
|
|
22
22
|
[
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sliding-panel.vue.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"xds:sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <div\n ref=\"scrollContainerRef\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll xds:sliding-panel-fade\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <slot name=\"sliding-panel-addons\" :arrived-state=\"arrivedState\" :scroll=\"xScroll\" />\n <template v-if=\"showButtons\">\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n @click=\"xScroll -= slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n @click=\"xScroll += slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../utils/types'\nimport {\n useElementBounding,\n useElementVisibility,\n useMutationObserver,\n useScroll,\n whenever,\n} from '@vueuse/core'\nimport { computed, defineComponent, ref } from 'vue'\n\n/**\n * This component allows for any other component or element inside it to be horizontally\n * navigable. It also implements customizable buttons as well as other minor customizations to its\n * general behavior.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'SlidingPanel',\n props: {\n /**\n * Scroll factor that will dictate how much the scroll moves when pressing a navigation button.\n */\n scrollFactor: {\n type: Number,\n default: 0.7,\n },\n /** Would make the navigation buttons visible when they're needed or always hide them. */\n showButtons: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, whenever the DOM content in the sliding panel slot changes, it will reset\n * the scroll position to 0.\n */\n resetOnContentChange: {\n type: Boolean,\n default: true,\n },\n buttonClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n scrollContainerClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n },\n setup(props, { slots }) {\n const scrollContainerRef = ref<HTMLDivElement>()\n\n const { width: slotContainerWidth } = useElementBounding(scrollContainerRef)\n const isVisible = useElementVisibility(scrollContainerRef)\n\n const {\n x: xScroll,\n arrivedState,\n measure,\n } = useScroll(scrollContainerRef, {\n behavior: 'smooth',\n })\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'xds:sliding-panel-at-start': arrivedState.left,\n 'xds:sliding-panel-at-end': arrivedState.right,\n }))\n\n if (props.resetOnContentChange) {\n useMutationObserver(\n scrollContainerRef,\n mutations => {\n if (mutations.length > 0) {\n xScroll.value = 0\n }\n },\n {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false,\n },\n )\n }\n //ensure positions are right calculated as soon as the sliding panel is shown\n whenever(isVisible as any, measure)\n\n return {\n arrivedState,\n cssClasses,\n scrollContainerRef,\n slotContainerWidth,\n xScroll,\n slots,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-sliding-panel__scroll {\n display: flex;\n flex: 100%;\n flex-flow: row nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE */\n}\n\n/* Chrome, Edge & Safari */\n.x-sliding-panel__scroll::-webkit-scrollbar {\n display: none;\n}\n\n.x-sliding-panel__scroll > * {\n flex: 0 0 auto;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## See it in action\n\nSimplest implementation of the component, just a list-based component inside its slot.\n\n```vue\n<template>\n <SlidingPanel>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n### Play with props\n\n#### Modifying scroll buttons travel distance\n\nEdit how much the scroll travels when navigating with the buttons by changing the `scrollFactor`\nprop.\n\n```vue\n<template>\n <SlidingPanel :scrollFactor=\"1.5\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Hiding scroll buttons\n\nHide the navigational buttons completely by setting the `showButtons` prop to `false`. This is\nintended to be used when other scrolling options are available, like in mobile, where you can scroll\njust by swiping.\n\n```vue\n<template>\n <SlidingPanel :showButtons=\"false\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Customizing the content with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\nThe `scrollContainerClass` prop can be used to add classes to the scroll content.\n\n```vue\n<template>\n <SlidingPanel buttonClass=\"x-button--round\" scrollContainerClass=\"x-sliding-panel-fade\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Disabling reset the scroll when content changes\n\nBy default, whenever the content of the sliding panel changes, it auto resets its scroll position.\nYou can disable this behavior setting the `resetOnContentChange` prop to `false`.\n\n```vue\n<template>\n <div>\n <button @click=\"items++\">Add item</button>\n <label>\n <input type=\"checkbox\" v-model=\"resetOnContentChange\" />\n Reset content onchange\n </label>\n <SlidingPanel :resetOnContentChange=\"resetOnContentChange\">\n <div class=\"item\" v-for=\"item in items\" :key=\"item\">Item {{ item }}</div>\n </SlidingPanel>\n </div>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n data() {\n return {\n items: 4,\n resetOnContentChange: false,\n }\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n## Extending the component\n\n### Overriding Button content\n\nBy default the buttons show an arrow depicting the direction the scroll would go to when clicked,\nbut this content can be customized with anything, from characters to SVG and images.\n\n```vue\n<template>\n <SlidingPanel>\n <template #sliding-panel-left-button>Left</template>\n <template #default>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </template>\n <template #sliding-panel-right-button>Right</template>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_renderSlot","_Fragment","_createTextVNode"],"mappings":";;;;;;AACa,EAAA,OAAA,IAAA,CAAA,KAAA,CAAM,OAAA,IAAAA,SAAA,EAAA,EAAjBC,kBAAA;AAAA,IA+BM,KAAA;AAAA,IAAA;AAAA,MAAA,GAAA,EAAA,CAAA;MA/BoB,KAAA,EAAKC,cAAA,CAAA,CAAC,qBAA4B,IAAA,CAAA,UAAU,CAAA,CAAA;AAAA,MAAE,WAAA,EAAU;AAAA,KAAA;;AAChF,MAAAC,kBAAA;AAAA,QAQM,KAAA;AAAA,QAAA;AAAA,UAPJ,GAAA,EAAI,oBAAA;AAAA,UACH,KAAA,EAAKD,cAAA,CAAA,CAAE,IAAA,CAAA,oBAAA,EACF,gDAAgD,CAAA,CAAA;AAAA,UACtD,WAAA,EAAU;AAAA,SAAA;;UAGVE,UAAA,CAAQ,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAA,EAAA,MAAA,EAAA,IAAA;AAAA,SAAA;;;;MAEVA,UAAA,CAAoF,IAAA,CAAA,MAAA,EAAA,sBAAA,EAAA;AAAA,QAAjD,YAAA,EAAe,IAAA,CAAA,YAAA;AAAA,QAAe,MAAA,EAAQ,IAAA,CAAA;AAAA,OAAA,EAAA,MAAA,EAAA,IAAA,CAAA;MACzD,IAAA,CAAA,WAAA,IAAAJ,SAAA,EAAA,EAAhBC,kBAAA;AAAA,QAmBWI,QAAA;AAAA,QAAA,EAAA,GAAA,EAAA,CAAA,EAAA;AAAA,QAAA;AAAA,UAlBTF,kBAAA;AAAA,YAQS,QAAA;AAAA,YAAA;AAAA,cAPP,KAAA,EAAKD,cAAA,CAAA,CAAC,wDAAA,EACE,IAAA,CAAA,WAAW,CAAA,CAAA;AAAA,cACnB,WAAA,EAAU,2BAAA;AAAA,cACT,OAAA,EAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KAAE,IAAA,CAAA,OAAA,IAAW,IAAA,CAAA,kBAAA,GAAqB,IAAA,CAAA,YAAA;AAAA,aAAA;;AAGxC,cAAAE,UAAA,CAA+C,8CAA/C,MAA+C;AAAA,gBAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAE,eAAA;AAAR,kBAAA,GAAA;AAAA,kBAAC;AAAA;AAAA,iBAAA;AAAA,eAAA,EAAA,IAAA;;;;;AAE1C,UAAAH,kBAAA;AAAA,YAQS,QAAA;AAAA,YAAA;AAAA,cAPP,KAAA,EAAKD,cAAA,CAAA,CAAC,yDAAA,EACE,IAAA,CAAA,WAAW,CAAA,CAAA;AAAA,cACnB,WAAA,EAAU,4BAAA;AAAA,cACT,OAAA,EAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KAAE,IAAA,CAAA,OAAA,IAAW,IAAA,CAAA,kBAAA,GAAqB,IAAA,CAAA,YAAA;AAAA,aAAA;;AAGxC,cAAAE,UAAA,CAAgD,+CAAhD,MAAgD;AAAA,gBAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAE,eAAA;AAAR,kBAAA,GAAA;AAAA,kBAAC;AAAA;AAAA,iBAAA;AAAA,eAAA,EAAA,IAAA;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"sliding-panel.vue.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"xds:sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <div\n ref=\"scrollContainerRef\"\n class=\"x-sliding-panel__scroll\"\n :class=\"[scrollContainerClass, { 'xds:sliding-panel-fade': fade }]\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <slot name=\"sliding-panel-addons\" :arrived-state=\"arrivedState\" :scroll=\"xScroll\" />\n <template v-if=\"showButtons\">\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n @click=\"xScroll -= slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n @click=\"xScroll += slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../utils/types'\nimport {\n useElementBounding,\n useElementVisibility,\n useMutationObserver,\n useScroll,\n whenever,\n} from '@vueuse/core'\nimport { computed, defineComponent, ref } from 'vue'\n\n/**\n * This component allows for any other component or element inside it to be horizontally\n * navigable. It also implements customizable buttons as well as other minor customizations to its\n * general behavior.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'SlidingPanel',\n props: {\n /**\n * Scroll factor that will dictate how much the scroll moves when pressing a navigation button.\n */\n scrollFactor: {\n type: Number,\n default: 0.7,\n },\n /** Would make the navigation buttons visible when they're needed or always hide them. */\n showButtons: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, whenever the DOM content in the sliding panel slot changes, it will reset\n * the scroll position to 0.\n */\n resetOnContentChange: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, applies the design-system edge fade mask to the scroll container.\n */\n fade: {\n type: Boolean,\n default: true,\n },\n buttonClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n scrollContainerClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n },\n setup(props, { slots }) {\n const scrollContainerRef = ref<HTMLDivElement>()\n\n const { width: slotContainerWidth } = useElementBounding(scrollContainerRef)\n const isVisible = useElementVisibility(scrollContainerRef)\n\n const {\n x: xScroll,\n arrivedState,\n measure,\n } = useScroll(scrollContainerRef, {\n behavior: 'smooth',\n })\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'xds:sliding-panel-at-start': arrivedState.left,\n 'xds:sliding-panel-at-end': arrivedState.right,\n }))\n\n if (props.resetOnContentChange) {\n useMutationObserver(\n scrollContainerRef,\n mutations => {\n if (mutations.length > 0) {\n xScroll.value = 0\n }\n },\n {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false,\n },\n )\n }\n //ensure positions are right calculated as soon as the sliding panel is shown\n whenever(isVisible as any, measure)\n\n return {\n arrivedState,\n cssClasses,\n scrollContainerRef,\n slotContainerWidth,\n xScroll,\n slots,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-sliding-panel__scroll {\n display: flex;\n flex: 100%;\n flex-flow: row nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE */\n}\n\n/* Chrome, Edge & Safari */\n.x-sliding-panel__scroll::-webkit-scrollbar {\n display: none;\n}\n\n.x-sliding-panel__scroll > * {\n flex: 0 0 auto;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## See it in action\n\nSimplest implementation of the component, just a list-based component inside its slot.\n\n```vue\n<template>\n <SlidingPanel>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n### Play with props\n\n#### Modifying scroll buttons travel distance\n\nEdit how much the scroll travels when navigating with the buttons by changing the `scrollFactor`\nprop.\n\n```vue\n<template>\n <SlidingPanel :scrollFactor=\"1.5\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Hiding scroll buttons\n\nHide the navigational buttons completely by setting the `showButtons` prop to `false`. This is\nintended to be used when other scrolling options are available, like in mobile, where you can scroll\njust by swiping.\n\n```vue\n<template>\n <SlidingPanel :showButtons=\"false\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Customizing the content with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\nThe `scrollContainerClass` prop can be used to add classes to the scroll content.\n\n```vue\n<template>\n <SlidingPanel buttonClass=\"x-button--round\" scrollContainerClass=\"x-sliding-panel-fade\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Disabling reset the scroll when content changes\n\nBy default, whenever the content of the sliding panel changes, it auto resets its scroll position.\nYou can disable this behavior setting the `resetOnContentChange` prop to `false`.\n\n```vue\n<template>\n <div>\n <button @click=\"items++\">Add item</button>\n <label>\n <input type=\"checkbox\" v-model=\"resetOnContentChange\" />\n Reset content onchange\n </label>\n <SlidingPanel :resetOnContentChange=\"resetOnContentChange\">\n <div class=\"item\" v-for=\"item in items\" :key=\"item\">Item {{ item }}</div>\n </SlidingPanel>\n </div>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n data() {\n return {\n items: 4,\n resetOnContentChange: false,\n }\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n## Extending the component\n\n### Overriding Button content\n\nBy default the buttons show an arrow depicting the direction the scroll would go to when clicked,\nbut this content can be customized with anything, from characters to SVG and images.\n\n```vue\n<template>\n <SlidingPanel>\n <template #sliding-panel-left-button>Left</template>\n <template #default>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </template>\n <template #sliding-panel-right-button>Right</template>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_renderSlot","_Fragment","_createTextVNode"],"mappings":";;;;;;AACa,EAAA,OAAA,IAAA,CAAA,KAAA,CAAM,OAAA,IAAAA,SAAA,EAAA,EAAjBC,kBAAA;AAAA,IA+BM,KAAA;AAAA,IAAA;AAAA,MAAA,GAAA,EAAA,CAAA;MA/BoB,KAAA,EAAKC,cAAA,CAAA,CAAC,qBAA4B,IAAA,CAAA,UAAU,CAAA,CAAA;AAAA,MAAE,WAAA,EAAU;AAAA,KAAA;;AAChF,MAAAC,kBAAA;AAAA,QAQM,KAAA;AAAA,QAAA;AAAA,UAPJ,GAAA,EAAI,oBAAA;AAAA,UACJ,OAAKD,cAAA,CAAA,CAAC,yBAAA,EAAyB,CACtB,IAAA,CAAA,oBAAA,EAAoB,4BAA8B,IAAA,CAAA,IAAA,EAAI,CAAA,CAAA,CAAA;AAAA,UAC/D,WAAA,EAAU;AAAA,SAAA;;UAGVE,UAAA,CAAQ,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAA,EAAA,MAAA,EAAA,IAAA;AAAA,SAAA;;;;MAEVA,UAAA,CAAoF,IAAA,CAAA,MAAA,EAAA,sBAAA,EAAA;AAAA,QAAjD,YAAA,EAAe,IAAA,CAAA,YAAA;AAAA,QAAe,MAAA,EAAQ,IAAA,CAAA;AAAA,OAAA,EAAA,MAAA,EAAA,IAAA,CAAA;MACzD,IAAA,CAAA,WAAA,IAAAJ,SAAA,EAAA,EAAhBC,kBAAA;AAAA,QAmBWI,QAAA;AAAA,QAAA,EAAA,GAAA,EAAA,CAAA,EAAA;AAAA,QAAA;AAAA,UAlBTF,kBAAA;AAAA,YAQS,QAAA;AAAA,YAAA;AAAA,cAPP,KAAA,EAAKD,cAAA,CAAA,CAAC,wDAAA,EACE,IAAA,CAAA,WAAW,CAAA,CAAA;AAAA,cACnB,WAAA,EAAU,2BAAA;AAAA,cACT,OAAA,EAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KAAE,IAAA,CAAA,OAAA,IAAW,IAAA,CAAA,kBAAA,GAAqB,IAAA,CAAA,YAAA;AAAA,aAAA;;AAGxC,cAAAE,UAAA,CAA+C,8CAA/C,MAA+C;AAAA,gBAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAE,eAAA;AAAR,kBAAA,GAAA;AAAA,kBAAC;AAAA;AAAA,iBAAA;AAAA,eAAA,EAAA,IAAA;;;;;AAE1C,UAAAH,kBAAA;AAAA,YAQS,QAAA;AAAA,YAAA;AAAA,cAPP,KAAA,EAAKD,cAAA,CAAA,CAAC,yDAAA,EACE,IAAA,CAAA,WAAW,CAAA,CAAA;AAAA,cACnB,WAAA,EAAU,4BAAA;AAAA,cACT,OAAA,EAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KAAE,IAAA,CAAA,OAAA,IAAW,IAAA,CAAA,kBAAA,GAAqB,IAAA,CAAA,YAAA;AAAA,aAAA;;AAGxC,cAAAE,UAAA,CAAgD,+CAAhD,MAAgD;AAAA,gBAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAE,eAAA;AAAR,kBAAA,GAAA;AAAA,kBAAC;AAAA;AAAA,iBAAA;AAAA,eAAA,EAAA,IAAA;;;;;;;;;;;;;;;;;;"}
|
|
@@ -34,6 +34,13 @@ var _sfc_main = defineComponent({
|
|
|
34
34
|
type: Boolean,
|
|
35
35
|
default: true,
|
|
36
36
|
},
|
|
37
|
+
/**
|
|
38
|
+
* When true, applies the design-system edge fade mask to the scroll container.
|
|
39
|
+
*/
|
|
40
|
+
fade: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: true,
|
|
43
|
+
},
|
|
37
44
|
buttonClass: { type: [String, Object, Array] },
|
|
38
45
|
scrollContainerClass: { type: [String, Object, Array] },
|
|
39
46
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sliding-panel.vue2.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"xds:sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <div\n ref=\"scrollContainerRef\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll xds:sliding-panel-fade\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <slot name=\"sliding-panel-addons\" :arrived-state=\"arrivedState\" :scroll=\"xScroll\" />\n <template v-if=\"showButtons\">\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n @click=\"xScroll -= slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n @click=\"xScroll += slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../utils/types'\nimport {\n useElementBounding,\n useElementVisibility,\n useMutationObserver,\n useScroll,\n whenever,\n} from '@vueuse/core'\nimport { computed, defineComponent, ref } from 'vue'\n\n/**\n * This component allows for any other component or element inside it to be horizontally\n * navigable. It also implements customizable buttons as well as other minor customizations to its\n * general behavior.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'SlidingPanel',\n props: {\n /**\n * Scroll factor that will dictate how much the scroll moves when pressing a navigation button.\n */\n scrollFactor: {\n type: Number,\n default: 0.7,\n },\n /** Would make the navigation buttons visible when they're needed or always hide them. */\n showButtons: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, whenever the DOM content in the sliding panel slot changes, it will reset\n * the scroll position to 0.\n */\n resetOnContentChange: {\n type: Boolean,\n default: true,\n },\n buttonClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n scrollContainerClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n },\n setup(props, { slots }) {\n const scrollContainerRef = ref<HTMLDivElement>()\n\n const { width: slotContainerWidth } = useElementBounding(scrollContainerRef)\n const isVisible = useElementVisibility(scrollContainerRef)\n\n const {\n x: xScroll,\n arrivedState,\n measure,\n } = useScroll(scrollContainerRef, {\n behavior: 'smooth',\n })\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'xds:sliding-panel-at-start': arrivedState.left,\n 'xds:sliding-panel-at-end': arrivedState.right,\n }))\n\n if (props.resetOnContentChange) {\n useMutationObserver(\n scrollContainerRef,\n mutations => {\n if (mutations.length > 0) {\n xScroll.value = 0\n }\n },\n {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false,\n },\n )\n }\n //ensure positions are right calculated as soon as the sliding panel is shown\n whenever(isVisible as any, measure)\n\n return {\n arrivedState,\n cssClasses,\n scrollContainerRef,\n slotContainerWidth,\n xScroll,\n slots,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-sliding-panel__scroll {\n display: flex;\n flex: 100%;\n flex-flow: row nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE */\n}\n\n/* Chrome, Edge & Safari */\n.x-sliding-panel__scroll::-webkit-scrollbar {\n display: none;\n}\n\n.x-sliding-panel__scroll > * {\n flex: 0 0 auto;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## See it in action\n\nSimplest implementation of the component, just a list-based component inside its slot.\n\n```vue\n<template>\n <SlidingPanel>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n### Play with props\n\n#### Modifying scroll buttons travel distance\n\nEdit how much the scroll travels when navigating with the buttons by changing the `scrollFactor`\nprop.\n\n```vue\n<template>\n <SlidingPanel :scrollFactor=\"1.5\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Hiding scroll buttons\n\nHide the navigational buttons completely by setting the `showButtons` prop to `false`. This is\nintended to be used when other scrolling options are available, like in mobile, where you can scroll\njust by swiping.\n\n```vue\n<template>\n <SlidingPanel :showButtons=\"false\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Customizing the content with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\nThe `scrollContainerClass` prop can be used to add classes to the scroll content.\n\n```vue\n<template>\n <SlidingPanel buttonClass=\"x-button--round\" scrollContainerClass=\"x-sliding-panel-fade\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Disabling reset the scroll when content changes\n\nBy default, whenever the content of the sliding panel changes, it auto resets its scroll position.\nYou can disable this behavior setting the `resetOnContentChange` prop to `false`.\n\n```vue\n<template>\n <div>\n <button @click=\"items++\">Add item</button>\n <label>\n <input type=\"checkbox\" v-model=\"resetOnContentChange\" />\n Reset content onchange\n </label>\n <SlidingPanel :resetOnContentChange=\"resetOnContentChange\">\n <div class=\"item\" v-for=\"item in items\" :key=\"item\">Item {{ item }}</div>\n </SlidingPanel>\n </div>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n data() {\n return {\n items: 4,\n resetOnContentChange: false,\n }\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n## Extending the component\n\n### Overriding Button content\n\nBy default the buttons show an arrow depicting the direction the scroll would go to when clicked,\nbut this content can be customized with anything, from characters to SVG and images.\n\n```vue\n<template>\n <SlidingPanel>\n <template #sliding-panel-left-button>Left</template>\n <template #default>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </template>\n <template #sliding-panel-right-button>Right</template>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n</docs>\n"],"names":[],"mappings":";;;AA+CA;;;;;;;;;AASE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,KAAK,EAAE;AACL;;AAEE;AACF,QAAA,YAAY,EAAE;AACZ,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,GAAG;AACb,SAAA;;AAED,QAAA,WAAW,EAAE;AACX,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA;AACD;;;AAGE;AACF,QAAA,oBAAoB,EAAE;AACpB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA;QACD,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAA8B;QACzE,oBAAoB,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAA8B;AACnF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,KAAI,EAAG,EAAA;AACpB,QAAA,MAAM,kBAAiB,GAAI,GAAG,EAAiB;QAE/C,MAAM,EAAE,KAAK,EAAE,kBAAiB,EAAE,GAAI,kBAAkB,CAAC,kBAAkB,CAAA;AAC3E,QAAA,MAAM,YAAY,oBAAoB,CAAC,kBAAkB,CAAA;AAEzD,QAAA,MAAM,EACJ,CAAC,EAAE,OAAO,EACV,YAAY,EACZ,OAAO,GACT,GAAI,SAAS,CAAC,kBAAkB,EAAE;AAChC,YAAA,QAAQ,EAAE,QAAQ;AACnB,SAAA,CAAA;;AAGD,QAAA,MAAM,UAAS,GAAI,QAAQ,CAAC,OAAO;YACjC,4BAA4B,EAAE,YAAY,CAAC,IAAI;YAC/C,0BAA0B,EAAE,YAAY,CAAC,KAAK;AAC/C,SAAA,CAAC,CAAA;AAEF,QAAA,IAAI,KAAK,CAAC,oBAAoB,EAAE;AAC9B,YAAA,mBAAmB,CACjB,kBAAkB,EAClB,SAAQ,IAAG;AACT,gBAAA,IAAI,SAAS,CAAC,MAAK,GAAI,CAAC,EAAE;AACxB,oBAAA,OAAO,CAAC,KAAI,GAAI,CAAA;gBAClB;AACF,YAAA,CAAC,EACD;AACE,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,IAAI;AACf,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,aAAa,EAAE,KAAK;AACrB,aAAA,CACH;QACF;;AAEA,QAAA,QAAQ,CAAC,SAAgB,EAAE,OAAO,CAAA;QAElC,OAAO;YACL,YAAY;YACZ,UAAU;YACV,kBAAkB;YAClB,kBAAkB;YAClB,OAAO;YACP,KAAK;SACP;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"sliding-panel.vue2.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"xds:sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <div\n ref=\"scrollContainerRef\"\n class=\"x-sliding-panel__scroll\"\n :class=\"[scrollContainerClass, { 'xds:sliding-panel-fade': fade }]\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <slot name=\"sliding-panel-addons\" :arrived-state=\"arrivedState\" :scroll=\"xScroll\" />\n <template v-if=\"showButtons\">\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n @click=\"xScroll -= slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <button\n class=\"xds:sliding-panel-button xds:sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n @click=\"xScroll += slotContainerWidth * scrollFactor\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../utils/types'\nimport {\n useElementBounding,\n useElementVisibility,\n useMutationObserver,\n useScroll,\n whenever,\n} from '@vueuse/core'\nimport { computed, defineComponent, ref } from 'vue'\n\n/**\n * This component allows for any other component or element inside it to be horizontally\n * navigable. It also implements customizable buttons as well as other minor customizations to its\n * general behavior.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'SlidingPanel',\n props: {\n /**\n * Scroll factor that will dictate how much the scroll moves when pressing a navigation button.\n */\n scrollFactor: {\n type: Number,\n default: 0.7,\n },\n /** Would make the navigation buttons visible when they're needed or always hide them. */\n showButtons: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, whenever the DOM content in the sliding panel slot changes, it will reset\n * the scroll position to 0.\n */\n resetOnContentChange: {\n type: Boolean,\n default: true,\n },\n /**\n * When true, applies the design-system edge fade mask to the scroll container.\n */\n fade: {\n type: Boolean,\n default: true,\n },\n buttonClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n scrollContainerClass: { type: [String, Object, Array] as PropType<VueCSSClasses> },\n },\n setup(props, { slots }) {\n const scrollContainerRef = ref<HTMLDivElement>()\n\n const { width: slotContainerWidth } = useElementBounding(scrollContainerRef)\n const isVisible = useElementVisibility(scrollContainerRef)\n\n const {\n x: xScroll,\n arrivedState,\n measure,\n } = useScroll(scrollContainerRef, {\n behavior: 'smooth',\n })\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'xds:sliding-panel-at-start': arrivedState.left,\n 'xds:sliding-panel-at-end': arrivedState.right,\n }))\n\n if (props.resetOnContentChange) {\n useMutationObserver(\n scrollContainerRef,\n mutations => {\n if (mutations.length > 0) {\n xScroll.value = 0\n }\n },\n {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false,\n },\n )\n }\n //ensure positions are right calculated as soon as the sliding panel is shown\n whenever(isVisible as any, measure)\n\n return {\n arrivedState,\n cssClasses,\n scrollContainerRef,\n slotContainerWidth,\n xScroll,\n slots,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-sliding-panel__scroll {\n display: flex;\n flex: 100%;\n flex-flow: row nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE */\n}\n\n/* Chrome, Edge & Safari */\n.x-sliding-panel__scroll::-webkit-scrollbar {\n display: none;\n}\n\n.x-sliding-panel__scroll > * {\n flex: 0 0 auto;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## See it in action\n\nSimplest implementation of the component, just a list-based component inside its slot.\n\n```vue\n<template>\n <SlidingPanel>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n### Play with props\n\n#### Modifying scroll buttons travel distance\n\nEdit how much the scroll travels when navigating with the buttons by changing the `scrollFactor`\nprop.\n\n```vue\n<template>\n <SlidingPanel :scrollFactor=\"1.5\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Hiding scroll buttons\n\nHide the navigational buttons completely by setting the `showButtons` prop to `false`. This is\nintended to be used when other scrolling options are available, like in mobile, where you can scroll\njust by swiping.\n\n```vue\n<template>\n <SlidingPanel :showButtons=\"false\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Customizing the content with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\nThe `scrollContainerClass` prop can be used to add classes to the scroll content.\n\n```vue\n<template>\n <SlidingPanel buttonClass=\"x-button--round\" scrollContainerClass=\"x-sliding-panel-fade\">\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n#### Disabling reset the scroll when content changes\n\nBy default, whenever the content of the sliding panel changes, it auto resets its scroll position.\nYou can disable this behavior setting the `resetOnContentChange` prop to `false`.\n\n```vue\n<template>\n <div>\n <button @click=\"items++\">Add item</button>\n <label>\n <input type=\"checkbox\" v-model=\"resetOnContentChange\" />\n Reset content onchange\n </label>\n <SlidingPanel :resetOnContentChange=\"resetOnContentChange\">\n <div class=\"item\" v-for=\"item in items\" :key=\"item\">Item {{ item }}</div>\n </SlidingPanel>\n </div>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n data() {\n return {\n items: 4,\n resetOnContentChange: false,\n }\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n\n## Extending the component\n\n### Overriding Button content\n\nBy default the buttons show an arrow depicting the direction the scroll would go to when clicked,\nbut this content can be customized with anything, from characters to SVG and images.\n\n```vue\n<template>\n <SlidingPanel>\n <template #sliding-panel-left-button>Left</template>\n <template #default>\n <div class=\"item\">Item 1</div>\n <div class=\"item\">Item 2</div>\n <div class=\"item\">Item 3</div>\n <div class=\"item\">Item 4</div>\n </template>\n <template #sliding-panel-right-button>Right</template>\n </SlidingPanel>\n</template>\n\n<script>\nimport { SlidingPanel } from '@empathyco/x-components'\n\nexport default {\n name: 'SlidingPanelDemo',\n components: {\n SlidingPanel,\n },\n}\n</script>\n\n<style>\n.x-sliding-panel {\n width: 200px;\n}\n\n.item {\n display: inline-block;\n width: 100px;\n}\n</style>\n```\n</docs>\n"],"names":[],"mappings":";;;AA+CA;;;;;;;;;AASE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,KAAK,EAAE;AACL;;AAEE;AACF,QAAA,YAAY,EAAE;AACZ,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,GAAG;AACb,SAAA;;AAED,QAAA,WAAW,EAAE;AACX,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA;AACD;;;AAGE;AACF,QAAA,oBAAoB,EAAE;AACpB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA;AACD;;AAEE;AACF,QAAA,IAAI,EAAE;AACJ,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA;QACD,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAA8B;QACzE,oBAAoB,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAA8B;AACnF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,KAAI,EAAG,EAAA;AACpB,QAAA,MAAM,kBAAiB,GAAI,GAAG,EAAiB;QAE/C,MAAM,EAAE,KAAK,EAAE,kBAAiB,EAAE,GAAI,kBAAkB,CAAC,kBAAkB,CAAA;AAC3E,QAAA,MAAM,YAAY,oBAAoB,CAAC,kBAAkB,CAAA;AAEzD,QAAA,MAAM,EACJ,CAAC,EAAE,OAAO,EACV,YAAY,EACZ,OAAO,GACT,GAAI,SAAS,CAAC,kBAAkB,EAAE;AAChC,YAAA,QAAQ,EAAE,QAAQ;AACnB,SAAA,CAAA;;AAGD,QAAA,MAAM,UAAS,GAAI,QAAQ,CAAC,OAAO;YACjC,4BAA4B,EAAE,YAAY,CAAC,IAAI;YAC/C,0BAA0B,EAAE,YAAY,CAAC,KAAK;AAC/C,SAAA,CAAC,CAAA;AAEF,QAAA,IAAI,KAAK,CAAC,oBAAoB,EAAE;AAC9B,YAAA,mBAAmB,CACjB,kBAAkB,EAClB,SAAQ,IAAG;AACT,gBAAA,IAAI,SAAS,CAAC,MAAK,GAAI,CAAC,EAAE;AACxB,oBAAA,OAAO,CAAC,KAAI,GAAI,CAAA;gBAClB;AACF,YAAA,CAAC,EACD;AACE,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,IAAI;AACf,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,aAAa,EAAE,KAAK;AACrB,aAAA,CACH;QACF;;AAEA,QAAA,QAAQ,CAAC,SAAgB,EAAE,OAAO,CAAA;QAElC,OAAO;YACL,YAAY;YACZ,UAAU;YACV,kBAAkB;YAClB,kBAAkB;YAClB,OAAO;YACP,KAAK;SACP;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
|
|
@@ -10,6 +10,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
10
10
|
const _component_SlidingPanel = resolveComponent("SlidingPanel");
|
|
11
11
|
return openBlock(), createBlock(_component_SlidingPanel, {
|
|
12
12
|
key: _ctx.x.query.search,
|
|
13
|
+
fade: _ctx.selectedPromptIndex === -1,
|
|
13
14
|
"reset-on-content-change": false,
|
|
14
15
|
"button-class": _ctx.buttonClass,
|
|
15
16
|
"show-buttons": _ctx.showButtons && _ctx.selectedPromptIndex === -1,
|
|
@@ -93,7 +94,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
93
94
|
]),
|
|
94
95
|
_: 3
|
|
95
96
|
/* FORWARDED */
|
|
96
|
-
}, 8, ["button-class", "show-buttons", "scroll-container-class"]);
|
|
97
|
+
}, 8, ["fade", "button-class", "show-buttons", "scroll-container-class"]);
|
|
97
98
|
}
|
|
98
99
|
var relatedPromptsTagList = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
|
|
99
100
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"related-prompts-tag-list.vue.js","sources":["../../../../../src/x-modules/related-prompts/components/related-prompts-tag-list.vue"],"sourcesContent":["<template>\n <SlidingPanel\n :key=\"x.query.search\"\n :reset-on-content-change=\"false\"\n :button-class=\"buttonClass\"\n :show-buttons=\"showButtons && selectedPromptIndex === -1\"\n :scroll-container-class=\"[\n 'x-related-prompts-tag-list-scroll-container',\n scrollContainerClass || '',\n ]\"\n >\n <template #sliding-panel-left-button>\n <!--\n @slot sliding-panel-left-button - The button to be displayed on the left side of the sliding panel.\n -->\n <slot name=\"sliding-panel-left-button\" />\n </template>\n <transition-group\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\n @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n >\n <li\n v-for=\"{ index, ...relatedPrompt } in visibleRelatedPrompts\"\n ref=\"listItems\"\n :key=\"relatedPrompt.suggestionText\"\n class=\"x-related-prompts-tag-list-item\"\n :class=\"[tagClass, tagColors && tagColors[index % tagColors.length]]\"\n :data-index=\"index\"\n :style=\"{\n ...(selectedPromptIndex === index && { width: '100%' }),\n ...(isAnimating && { pointerEvents: 'none' }),\n }\"\n data-test=\"related-prompts-tag-list-item\"\n >\n <!--\n @slot - The slot to render related prompt information.\n @prop {Object} relatedPrompt - The related prompt object.\n @prop {Function} onSelect - The function to select the related prompt.\n @prop {Boolean} isSelected - Indicates if the related prompt is currently selected.\n -->\n <slot\n :related-prompt=\"relatedPrompt\"\n :on-select=\"() => onSelect(index)\"\n :is-selected=\"selectedPromptIndex === index\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.tagging?.toolingDisplayTagging!\"\n :event-metadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false,\n }\"\n >\n <RelatedPrompt\n :related-prompt=\"relatedPrompt\"\n :selected=\"selectedPromptIndex === index\"\n @click=\"onSelect(index)\"\n >\n <template #related-prompt-extra-content>\n <!--\n @slot related-prompt-extra-content - The slot to render related prompt extra information.\n @prop {Object} relatedPrompt - The related prompt object.\n -->\n <slot name=\"related-prompt-extra-content\" :related-prompt=\"relatedPrompt\" />\n </template>\n </RelatedPrompt>\n </DisplayEmitter>\n </slot>\n </li>\n </transition-group>\n <template #sliding-panel-right-button>\n <!--\n @slot sliding-panel-right-button - The button to be displayed on the right side of the sliding panel.\n -->\n <slot name=\"sliding-panel-right-button\" />\n </template>\n </SlidingPanel>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { computed, defineComponent, onBeforeUnmount, ref } from 'vue'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport SlidingPanel from '../../../components/sliding-panel.vue'\nimport { use$x, useState } from '../../../composables'\nimport { relatedPromptsXModule } from '../x-module'\nimport RelatedPrompt from './related-prompt.vue'\n\n/**\n * This component shows the list of `RelatedPrompts` components.\n *\n * If the default slot is reimplemented in the consumer, `onSelect` function will be\n * necessary to handle the selection of the related prompt and to trigger the stagger-fade-slide animation.\n *\n * @public\n */\nexport default defineComponent({\n name: 'RelatedPromptsTagList',\n xModule: relatedPromptsXModule.name,\n components: { DisplayEmitter, RelatedPrompt, SlidingPanel },\n props: {\n /**\n * The CSS class for the left and right button of the sliding panel.\n *\n * @public\n */\n buttonClass: String,\n /**\n * The boolean prop to handle the visiblity of sliding pannel buttons.\n *\n * @public\n */\n showButtons: { type: Boolean, default: true },\n /**\n * The CSS class for the wrapper of all the related prompt wrapper elements.\n *\n * @public\n */\n scrollContainerClass: String,\n /**\n * The CSS class for all the related prompt wrapper elements.\n *\n * @public\n */\n tagClass: String,\n /**\n * Array of colors to apply to the related prompts. It will be applied to tag\n * elements cyclically according to their index in the nex way: `tagColors[index % tagColors.length]`.\n *\n * @public\n */\n tagColors: Array as PropType<string[]>,\n /**\n * The duration of the total animation in milliseconds.\n *\n * @public\n */\n animationDurationInMs: {\n type: Number,\n default: 700,\n },\n },\n setup(props) {\n const x = use$x()\n const { relatedPrompts, selectedPrompt: selectedPromptIndex } = useState('relatedPrompts')\n\n const clickedListItemIndex = ref<number | null>(null)\n const initialOffsetLefts: Record<number, number> = {}\n const isAnimating = ref(false)\n const listItems = ref<HTMLElement[]>([])\n\n const sortedListItems = computed<HTMLElement[]>(() =>\n [...listItems.value].sort(\n (a: HTMLElement, b: HTMLElement) =>\n Number.parseInt(b.getAttribute('data-index')!) -\n Number.parseInt(a.getAttribute('data-index')!),\n ),\n )\n\n // The duration of a single animation (enter or leave) in milliseconds\n // if a related prompt is clicked (clickedListItemIndex.value !== null), the duration is divided by the number of related\n // prompts -1 (the clicked one is synchronized with the last one to leave or the first one to enter)\n const singleAnimationDurationInMs = computed(\n () =>\n props.animationDurationInMs /\n (clickedListItemIndex.value !== null\n ? relatedPrompts.value.length - 1\n : relatedPrompts.value.length),\n )\n\n const indexRelatedPrompts = computed(() =>\n relatedPrompts.value.map((relatedPrompt, index) => ({ ...relatedPrompt, index })),\n )\n\n const visibleRelatedPrompts = computed(() =>\n selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value,\n )\n\n let timeOutId: number\n const resetTransitionStyle = (excludedProperties: Array<string> = ['width']) => {\n if (timeOutId) {\n clearTimeout(timeOutId)\n }\n\n isAnimating.value = true\n timeOutId = +setTimeout(() => {\n isAnimating.value = false\n clickedListItemIndex.value = null\n\n sortedListItems.value.forEach(element => {\n element.style.cssText\n .split(';')\n .map(rule => rule.split(':')[0]?.trim())\n .forEach(property => {\n if (!excludedProperties.includes(property)) {\n element.style.removeProperty(property)\n }\n })\n })\n }, props.animationDurationInMs)\n }\n\n const onSelect = (selectedIndex: number): void => {\n resetTransitionStyle()\n\n clickedListItemIndex.value = selectedIndex\n const selected: HTMLElement = sortedListItems.value.find(\n element => Number.parseInt(element.getAttribute('data-index')!) === selectedIndex,\n )!\n\n // selectedPromptIndex.value === -1 ? 'SELECTING' : 'DESELECTING'\n if (selectedPromptIndex.value === -1) {\n // Prepare all the elements for the leave animation (~ 'beforeLeave' hook). Remember the elements are\n // sorted in descending order by index.\n sortedListItems.value.forEach(element => {\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n initialOffsetLefts[index] = element.offsetLeft\n element.style.left = `${element.offsetLeft}px`\n element.style.position = 'absolute'\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n\n if (index !== selectedIndex) {\n element.style.opacity = '1'\n element.style.transitionDelay = `${\n (index < selectedIndex ? index : index - 1) * singleAnimationDurationInMs.value\n }ms`\n }\n })\n\n // Synchronize the transition delay of the selected element with the last\n // element to leave\n selected.style.transitionDelay = `${\n (relatedPrompts.value.length > 1 ? relatedPrompts.value.length - 2 : 0) *\n singleAnimationDurationInMs.value\n }ms`\n\n // Trigger the animation (selecting) for the selected element\n requestAnimationFrame(() => {\n const maxWidth = getComputedStyle(selected).maxWidth\n\n selected.style.left = '0px'\n selected.style.setProperty(\n 'width',\n `${maxWidth !== 'none' ? maxWidth : '100%'}`,\n 'important',\n )\n })\n } else {\n // Prepare the selected element for the deselecting animation\n selected.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n selected.style.left = '0px'\n selected.style.position = 'absolute'\n\n // Trigger the animation (deselecting) for the selected element\n selected.style.removeProperty('width')\n requestAnimationFrame(() => {\n selected.style.left = `${initialOffsetLefts[selectedIndex]}px`\n })\n }\n\n x.emit('UserSelectedARelatedPrompt', selectedIndex, {\n relatedPrompt: relatedPrompts.value[selectedIndex],\n selectedPrompt: selectedPromptIndex.value,\n })\n }\n\n const onBeforeEnter = (el: Element) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Prepare the element for the enter animation\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n element.style.transitionDelay = `${\n (clickedListItemIndex.value !== null && index > clickedListItemIndex.value\n ? index - 1\n : index) * singleAnimationDurationInMs.value\n }ms`\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n }\n\n const onEnter = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Also part of the preparation for the enter animation, but it needs to be done\n // once the element is inserted in DOM (if not the offsetLeft will be always 0)\n element.style.left = `${initialOffsetLefts[index] ?? element.offsetLeft}px`\n\n // trigger enter animation\n requestAnimationFrame(() => {\n element.style.opacity = '1'\n element.style.position = 'absolute'\n element.style.transform = 'translateY(0)'\n })\n\n done()\n }\n\n const onLeave = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n\n // trigger leave animation\n requestAnimationFrame(() => {\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n })\n\n // Wait for the animation to finish (done() exectution extracts the element from the DOM)\n setTimeout(done, props.animationDurationInMs)\n }\n\n // Changing the request will trigger the appear animation, so we need to reset the\n // style after it finishes\n x.on('SearchRequestChanged', false).subscribe(() => {\n resetTransitionStyle([])\n })\n\n onBeforeUnmount(() => {\n x.emit('RelatedPromptsUnmounted')\n })\n\n return {\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-related-prompts-tag-list-scroll-container {\n height: 100%;\n position: relative;\n}\n.x-related-prompts-tag-list {\n display: flex;\n gap: 16px;\n min-width: 100%;\n width: 100%;\n}\n.x-related-prompts-tag-list-item {\n height: 100%;\n flex-shrink: 0;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\n### Basic usage\n\n```vue live\n<template>\n <RelatedPromptsTagList />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing tag colors and classes\n\n```vue live\n<template>\n <RelatedPromptsTagList :tagColors=\"['x-bg-neutral-50', 'x-bg-lead-50']\" tagClass=\"rounded\" />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Using the default slot to customize prompt rendering\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #default=\"{ relatedPrompt, onSelect, isSelected }\">\n <button :class=\"{ selected: isSelected }\" @click=\"onSelect()\">\n {{ relatedPrompt.suggestionText }}\n </button>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing extra content in RelatedPrompt\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #related-prompt-extra-content=\"{ relatedPrompt }\">\n <span>Extra: {{ relatedPrompt.suggestionText }}</span>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n</docs>\n"],"names":["_createBlock","_withCtx","_renderSlot","_createVNode","_TransitionGroup","_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"related-prompts-tag-list.vue.js","sources":["../../../../../src/x-modules/related-prompts/components/related-prompts-tag-list.vue"],"sourcesContent":["<template>\n <SlidingPanel\n :key=\"x.query.search\"\n :fade=\"selectedPromptIndex === -1\"\n :reset-on-content-change=\"false\"\n :button-class=\"buttonClass\"\n :show-buttons=\"showButtons && selectedPromptIndex === -1\"\n :scroll-container-class=\"[\n 'x-related-prompts-tag-list-scroll-container',\n scrollContainerClass || '',\n ]\"\n >\n <template #sliding-panel-left-button>\n <!--\n @slot sliding-panel-left-button - The button to be displayed on the left side of the sliding panel.\n -->\n <slot name=\"sliding-panel-left-button\" />\n </template>\n <transition-group\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\n @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n >\n <li\n v-for=\"{ index, ...relatedPrompt } in visibleRelatedPrompts\"\n ref=\"listItems\"\n :key=\"relatedPrompt.suggestionText\"\n class=\"x-related-prompts-tag-list-item\"\n :class=\"[tagClass, tagColors && tagColors[index % tagColors.length]]\"\n :data-index=\"index\"\n :style=\"{\n ...(selectedPromptIndex === index && { width: '100%' }),\n ...(isAnimating && { pointerEvents: 'none' }),\n }\"\n data-test=\"related-prompts-tag-list-item\"\n >\n <!--\n @slot - The slot to render related prompt information.\n @prop {Object} relatedPrompt - The related prompt object.\n @prop {Function} onSelect - The function to select the related prompt.\n @prop {Boolean} isSelected - Indicates if the related prompt is currently selected.\n -->\n <slot\n :related-prompt=\"relatedPrompt\"\n :on-select=\"() => onSelect(index)\"\n :is-selected=\"selectedPromptIndex === index\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.tagging?.toolingDisplayTagging!\"\n :event-metadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false,\n }\"\n >\n <RelatedPrompt\n :related-prompt=\"relatedPrompt\"\n :selected=\"selectedPromptIndex === index\"\n @click=\"onSelect(index)\"\n >\n <template #related-prompt-extra-content>\n <!--\n @slot related-prompt-extra-content - The slot to render related prompt extra information.\n @prop {Object} relatedPrompt - The related prompt object.\n -->\n <slot name=\"related-prompt-extra-content\" :related-prompt=\"relatedPrompt\" />\n </template>\n </RelatedPrompt>\n </DisplayEmitter>\n </slot>\n </li>\n </transition-group>\n <template #sliding-panel-right-button>\n <!--\n @slot sliding-panel-right-button - The button to be displayed on the right side of the sliding panel.\n -->\n <slot name=\"sliding-panel-right-button\" />\n </template>\n </SlidingPanel>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { computed, defineComponent, onBeforeUnmount, ref } from 'vue'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport SlidingPanel from '../../../components/sliding-panel.vue'\nimport { use$x, useState } from '../../../composables'\nimport { relatedPromptsXModule } from '../x-module'\nimport RelatedPrompt from './related-prompt.vue'\n\n/**\n * This component shows the list of `RelatedPrompts` components.\n *\n * If the default slot is reimplemented in the consumer, `onSelect` function will be\n * necessary to handle the selection of the related prompt and to trigger the stagger-fade-slide animation.\n *\n * @public\n */\nexport default defineComponent({\n name: 'RelatedPromptsTagList',\n xModule: relatedPromptsXModule.name,\n components: { DisplayEmitter, RelatedPrompt, SlidingPanel },\n props: {\n /**\n * The CSS class for the left and right button of the sliding panel.\n *\n * @public\n */\n buttonClass: String,\n /**\n * The boolean prop to handle the visiblity of sliding pannel buttons.\n *\n * @public\n */\n showButtons: { type: Boolean, default: true },\n /**\n * The CSS class for the wrapper of all the related prompt wrapper elements.\n *\n * @public\n */\n scrollContainerClass: String,\n /**\n * The CSS class for all the related prompt wrapper elements.\n *\n * @public\n */\n tagClass: String,\n /**\n * Array of colors to apply to the related prompts. It will be applied to tag\n * elements cyclically according to their index in the nex way: `tagColors[index % tagColors.length]`.\n *\n * @public\n */\n tagColors: Array as PropType<string[]>,\n /**\n * The duration of the total animation in milliseconds.\n *\n * @public\n */\n animationDurationInMs: {\n type: Number,\n default: 700,\n },\n },\n setup(props) {\n const x = use$x()\n const { relatedPrompts, selectedPrompt: selectedPromptIndex } = useState('relatedPrompts')\n\n const clickedListItemIndex = ref<number | null>(null)\n const initialOffsetLefts: Record<number, number> = {}\n const isAnimating = ref(false)\n const listItems = ref<HTMLElement[]>([])\n\n const sortedListItems = computed<HTMLElement[]>(() =>\n [...listItems.value].sort(\n (a: HTMLElement, b: HTMLElement) =>\n Number.parseInt(b.getAttribute('data-index')!) -\n Number.parseInt(a.getAttribute('data-index')!),\n ),\n )\n\n // The duration of a single animation (enter or leave) in milliseconds\n // if a related prompt is clicked (clickedListItemIndex.value !== null), the duration is divided by the number of related\n // prompts -1 (the clicked one is synchronized with the last one to leave or the first one to enter)\n const singleAnimationDurationInMs = computed(\n () =>\n props.animationDurationInMs /\n (clickedListItemIndex.value !== null\n ? relatedPrompts.value.length - 1\n : relatedPrompts.value.length),\n )\n\n const indexRelatedPrompts = computed(() =>\n relatedPrompts.value.map((relatedPrompt, index) => ({ ...relatedPrompt, index })),\n )\n\n const visibleRelatedPrompts = computed(() =>\n selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value,\n )\n\n let timeOutId: number\n const resetTransitionStyle = (excludedProperties: Array<string> = ['width']) => {\n if (timeOutId) {\n clearTimeout(timeOutId)\n }\n\n isAnimating.value = true\n timeOutId = +setTimeout(() => {\n isAnimating.value = false\n clickedListItemIndex.value = null\n\n sortedListItems.value.forEach(element => {\n element.style.cssText\n .split(';')\n .map(rule => rule.split(':')[0]?.trim())\n .forEach(property => {\n if (!excludedProperties.includes(property)) {\n element.style.removeProperty(property)\n }\n })\n })\n }, props.animationDurationInMs)\n }\n\n const onSelect = (selectedIndex: number): void => {\n resetTransitionStyle()\n\n clickedListItemIndex.value = selectedIndex\n const selected: HTMLElement = sortedListItems.value.find(\n element => Number.parseInt(element.getAttribute('data-index')!) === selectedIndex,\n )!\n\n // selectedPromptIndex.value === -1 ? 'SELECTING' : 'DESELECTING'\n if (selectedPromptIndex.value === -1) {\n // Prepare all the elements for the leave animation (~ 'beforeLeave' hook). Remember the elements are\n // sorted in descending order by index.\n sortedListItems.value.forEach(element => {\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n initialOffsetLefts[index] = element.offsetLeft\n element.style.left = `${element.offsetLeft}px`\n element.style.position = 'absolute'\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n\n if (index !== selectedIndex) {\n element.style.opacity = '1'\n element.style.transitionDelay = `${\n (index < selectedIndex ? index : index - 1) * singleAnimationDurationInMs.value\n }ms`\n }\n })\n\n // Synchronize the transition delay of the selected element with the last\n // element to leave\n selected.style.transitionDelay = `${\n (relatedPrompts.value.length > 1 ? relatedPrompts.value.length - 2 : 0) *\n singleAnimationDurationInMs.value\n }ms`\n\n // Trigger the animation (selecting) for the selected element\n requestAnimationFrame(() => {\n const maxWidth = getComputedStyle(selected).maxWidth\n\n selected.style.left = '0px'\n selected.style.setProperty(\n 'width',\n `${maxWidth !== 'none' ? maxWidth : '100%'}`,\n 'important',\n )\n })\n } else {\n // Prepare the selected element for the deselecting animation\n selected.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n selected.style.left = '0px'\n selected.style.position = 'absolute'\n\n // Trigger the animation (deselecting) for the selected element\n selected.style.removeProperty('width')\n requestAnimationFrame(() => {\n selected.style.left = `${initialOffsetLefts[selectedIndex]}px`\n })\n }\n\n x.emit('UserSelectedARelatedPrompt', selectedIndex, {\n relatedPrompt: relatedPrompts.value[selectedIndex],\n selectedPrompt: selectedPromptIndex.value,\n })\n }\n\n const onBeforeEnter = (el: Element) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Prepare the element for the enter animation\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n element.style.transitionDelay = `${\n (clickedListItemIndex.value !== null && index > clickedListItemIndex.value\n ? index - 1\n : index) * singleAnimationDurationInMs.value\n }ms`\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n }\n\n const onEnter = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Also part of the preparation for the enter animation, but it needs to be done\n // once the element is inserted in DOM (if not the offsetLeft will be always 0)\n element.style.left = `${initialOffsetLefts[index] ?? element.offsetLeft}px`\n\n // trigger enter animation\n requestAnimationFrame(() => {\n element.style.opacity = '1'\n element.style.position = 'absolute'\n element.style.transform = 'translateY(0)'\n })\n\n done()\n }\n\n const onLeave = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n\n // trigger leave animation\n requestAnimationFrame(() => {\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n })\n\n // Wait for the animation to finish (done() exectution extracts the element from the DOM)\n setTimeout(done, props.animationDurationInMs)\n }\n\n // Changing the request will trigger the appear animation, so we need to reset the\n // style after it finishes\n x.on('SearchRequestChanged', false).subscribe(() => {\n resetTransitionStyle([])\n })\n\n onBeforeUnmount(() => {\n x.emit('RelatedPromptsUnmounted')\n })\n\n return {\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-related-prompts-tag-list-scroll-container {\n height: 100%;\n position: relative;\n}\n.x-related-prompts-tag-list {\n display: flex;\n gap: 16px;\n min-width: 100%;\n width: 100%;\n}\n.x-related-prompts-tag-list-item {\n height: 100%;\n flex-shrink: 0;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\n### Basic usage\n\n```vue live\n<template>\n <RelatedPromptsTagList />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing tag colors and classes\n\n```vue live\n<template>\n <RelatedPromptsTagList :tagColors=\"['x-bg-neutral-50', 'x-bg-lead-50']\" tagClass=\"rounded\" />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Using the default slot to customize prompt rendering\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #default=\"{ relatedPrompt, onSelect, isSelected }\">\n <button :class=\"{ selected: isSelected }\" @click=\"onSelect()\">\n {{ relatedPrompt.suggestionText }}\n </button>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing extra content in RelatedPrompt\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #related-prompt-extra-content=\"{ relatedPrompt }\">\n <span>Extra: {{ relatedPrompt.suggestionText }}</span>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n</docs>\n"],"names":["_createBlock","_withCtx","_renderSlot","_createVNode","_TransitionGroup","_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"related-prompts-tag-list.vue2.js","sources":["../../../../../src/x-modules/related-prompts/components/related-prompts-tag-list.vue"],"sourcesContent":["<template>\n <SlidingPanel\n :key=\"x.query.search\"\n :reset-on-content-change=\"false\"\n :button-class=\"buttonClass\"\n :show-buttons=\"showButtons && selectedPromptIndex === -1\"\n :scroll-container-class=\"[\n 'x-related-prompts-tag-list-scroll-container',\n scrollContainerClass || '',\n ]\"\n >\n <template #sliding-panel-left-button>\n <!--\n @slot sliding-panel-left-button - The button to be displayed on the left side of the sliding panel.\n -->\n <slot name=\"sliding-panel-left-button\" />\n </template>\n <transition-group\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\n @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n >\n <li\n v-for=\"{ index, ...relatedPrompt } in visibleRelatedPrompts\"\n ref=\"listItems\"\n :key=\"relatedPrompt.suggestionText\"\n class=\"x-related-prompts-tag-list-item\"\n :class=\"[tagClass, tagColors && tagColors[index % tagColors.length]]\"\n :data-index=\"index\"\n :style=\"{\n ...(selectedPromptIndex === index && { width: '100%' }),\n ...(isAnimating && { pointerEvents: 'none' }),\n }\"\n data-test=\"related-prompts-tag-list-item\"\n >\n <!--\n @slot - The slot to render related prompt information.\n @prop {Object} relatedPrompt - The related prompt object.\n @prop {Function} onSelect - The function to select the related prompt.\n @prop {Boolean} isSelected - Indicates if the related prompt is currently selected.\n -->\n <slot\n :related-prompt=\"relatedPrompt\"\n :on-select=\"() => onSelect(index)\"\n :is-selected=\"selectedPromptIndex === index\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.tagging?.toolingDisplayTagging!\"\n :event-metadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false,\n }\"\n >\n <RelatedPrompt\n :related-prompt=\"relatedPrompt\"\n :selected=\"selectedPromptIndex === index\"\n @click=\"onSelect(index)\"\n >\n <template #related-prompt-extra-content>\n <!--\n @slot related-prompt-extra-content - The slot to render related prompt extra information.\n @prop {Object} relatedPrompt - The related prompt object.\n -->\n <slot name=\"related-prompt-extra-content\" :related-prompt=\"relatedPrompt\" />\n </template>\n </RelatedPrompt>\n </DisplayEmitter>\n </slot>\n </li>\n </transition-group>\n <template #sliding-panel-right-button>\n <!--\n @slot sliding-panel-right-button - The button to be displayed on the right side of the sliding panel.\n -->\n <slot name=\"sliding-panel-right-button\" />\n </template>\n </SlidingPanel>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { computed, defineComponent, onBeforeUnmount, ref } from 'vue'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport SlidingPanel from '../../../components/sliding-panel.vue'\nimport { use$x, useState } from '../../../composables'\nimport { relatedPromptsXModule } from '../x-module'\nimport RelatedPrompt from './related-prompt.vue'\n\n/**\n * This component shows the list of `RelatedPrompts` components.\n *\n * If the default slot is reimplemented in the consumer, `onSelect` function will be\n * necessary to handle the selection of the related prompt and to trigger the stagger-fade-slide animation.\n *\n * @public\n */\nexport default defineComponent({\n name: 'RelatedPromptsTagList',\n xModule: relatedPromptsXModule.name,\n components: { DisplayEmitter, RelatedPrompt, SlidingPanel },\n props: {\n /**\n * The CSS class for the left and right button of the sliding panel.\n *\n * @public\n */\n buttonClass: String,\n /**\n * The boolean prop to handle the visiblity of sliding pannel buttons.\n *\n * @public\n */\n showButtons: { type: Boolean, default: true },\n /**\n * The CSS class for the wrapper of all the related prompt wrapper elements.\n *\n * @public\n */\n scrollContainerClass: String,\n /**\n * The CSS class for all the related prompt wrapper elements.\n *\n * @public\n */\n tagClass: String,\n /**\n * Array of colors to apply to the related prompts. It will be applied to tag\n * elements cyclically according to their index in the nex way: `tagColors[index % tagColors.length]`.\n *\n * @public\n */\n tagColors: Array as PropType<string[]>,\n /**\n * The duration of the total animation in milliseconds.\n *\n * @public\n */\n animationDurationInMs: {\n type: Number,\n default: 700,\n },\n },\n setup(props) {\n const x = use$x()\n const { relatedPrompts, selectedPrompt: selectedPromptIndex } = useState('relatedPrompts')\n\n const clickedListItemIndex = ref<number | null>(null)\n const initialOffsetLefts: Record<number, number> = {}\n const isAnimating = ref(false)\n const listItems = ref<HTMLElement[]>([])\n\n const sortedListItems = computed<HTMLElement[]>(() =>\n [...listItems.value].sort(\n (a: HTMLElement, b: HTMLElement) =>\n Number.parseInt(b.getAttribute('data-index')!) -\n Number.parseInt(a.getAttribute('data-index')!),\n ),\n )\n\n // The duration of a single animation (enter or leave) in milliseconds\n // if a related prompt is clicked (clickedListItemIndex.value !== null), the duration is divided by the number of related\n // prompts -1 (the clicked one is synchronized with the last one to leave or the first one to enter)\n const singleAnimationDurationInMs = computed(\n () =>\n props.animationDurationInMs /\n (clickedListItemIndex.value !== null\n ? relatedPrompts.value.length - 1\n : relatedPrompts.value.length),\n )\n\n const indexRelatedPrompts = computed(() =>\n relatedPrompts.value.map((relatedPrompt, index) => ({ ...relatedPrompt, index })),\n )\n\n const visibleRelatedPrompts = computed(() =>\n selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value,\n )\n\n let timeOutId: number\n const resetTransitionStyle = (excludedProperties: Array<string> = ['width']) => {\n if (timeOutId) {\n clearTimeout(timeOutId)\n }\n\n isAnimating.value = true\n timeOutId = +setTimeout(() => {\n isAnimating.value = false\n clickedListItemIndex.value = null\n\n sortedListItems.value.forEach(element => {\n element.style.cssText\n .split(';')\n .map(rule => rule.split(':')[0]?.trim())\n .forEach(property => {\n if (!excludedProperties.includes(property)) {\n element.style.removeProperty(property)\n }\n })\n })\n }, props.animationDurationInMs)\n }\n\n const onSelect = (selectedIndex: number): void => {\n resetTransitionStyle()\n\n clickedListItemIndex.value = selectedIndex\n const selected: HTMLElement = sortedListItems.value.find(\n element => Number.parseInt(element.getAttribute('data-index')!) === selectedIndex,\n )!\n\n // selectedPromptIndex.value === -1 ? 'SELECTING' : 'DESELECTING'\n if (selectedPromptIndex.value === -1) {\n // Prepare all the elements for the leave animation (~ 'beforeLeave' hook). Remember the elements are\n // sorted in descending order by index.\n sortedListItems.value.forEach(element => {\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n initialOffsetLefts[index] = element.offsetLeft\n element.style.left = `${element.offsetLeft}px`\n element.style.position = 'absolute'\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n\n if (index !== selectedIndex) {\n element.style.opacity = '1'\n element.style.transitionDelay = `${\n (index < selectedIndex ? index : index - 1) * singleAnimationDurationInMs.value\n }ms`\n }\n })\n\n // Synchronize the transition delay of the selected element with the last\n // element to leave\n selected.style.transitionDelay = `${\n (relatedPrompts.value.length > 1 ? relatedPrompts.value.length - 2 : 0) *\n singleAnimationDurationInMs.value\n }ms`\n\n // Trigger the animation (selecting) for the selected element\n requestAnimationFrame(() => {\n const maxWidth = getComputedStyle(selected).maxWidth\n\n selected.style.left = '0px'\n selected.style.setProperty(\n 'width',\n `${maxWidth !== 'none' ? maxWidth : '100%'}`,\n 'important',\n )\n })\n } else {\n // Prepare the selected element for the deselecting animation\n selected.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n selected.style.left = '0px'\n selected.style.position = 'absolute'\n\n // Trigger the animation (deselecting) for the selected element\n selected.style.removeProperty('width')\n requestAnimationFrame(() => {\n selected.style.left = `${initialOffsetLefts[selectedIndex]}px`\n })\n }\n\n x.emit('UserSelectedARelatedPrompt', selectedIndex, {\n relatedPrompt: relatedPrompts.value[selectedIndex],\n selectedPrompt: selectedPromptIndex.value,\n })\n }\n\n const onBeforeEnter = (el: Element) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Prepare the element for the enter animation\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n element.style.transitionDelay = `${\n (clickedListItemIndex.value !== null && index > clickedListItemIndex.value\n ? index - 1\n : index) * singleAnimationDurationInMs.value\n }ms`\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n }\n\n const onEnter = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Also part of the preparation for the enter animation, but it needs to be done\n // once the element is inserted in DOM (if not the offsetLeft will be always 0)\n element.style.left = `${initialOffsetLefts[index] ?? element.offsetLeft}px`\n\n // trigger enter animation\n requestAnimationFrame(() => {\n element.style.opacity = '1'\n element.style.position = 'absolute'\n element.style.transform = 'translateY(0)'\n })\n\n done()\n }\n\n const onLeave = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n\n // trigger leave animation\n requestAnimationFrame(() => {\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n })\n\n // Wait for the animation to finish (done() exectution extracts the element from the DOM)\n setTimeout(done, props.animationDurationInMs)\n }\n\n // Changing the request will trigger the appear animation, so we need to reset the\n // style after it finishes\n x.on('SearchRequestChanged', false).subscribe(() => {\n resetTransitionStyle([])\n })\n\n onBeforeUnmount(() => {\n x.emit('RelatedPromptsUnmounted')\n })\n\n return {\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-related-prompts-tag-list-scroll-container {\n height: 100%;\n position: relative;\n}\n.x-related-prompts-tag-list {\n display: flex;\n gap: 16px;\n min-width: 100%;\n width: 100%;\n}\n.x-related-prompts-tag-list-item {\n height: 100%;\n flex-shrink: 0;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\n### Basic usage\n\n```vue live\n<template>\n <RelatedPromptsTagList />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing tag colors and classes\n\n```vue live\n<template>\n <RelatedPromptsTagList :tagColors=\"['x-bg-neutral-50', 'x-bg-lead-50']\" tagClass=\"rounded\" />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Using the default slot to customize prompt rendering\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #default=\"{ relatedPrompt, onSelect, isSelected }\">\n <button :class=\"{ selected: isSelected }\" @click=\"onSelect()\">\n {{ relatedPrompt.suggestionText }}\n </button>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing extra content in RelatedPrompt\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #related-prompt-extra-content=\"{ relatedPrompt }\">\n <span>Extra: {{ relatedPrompt.suggestionText }}</span>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n</docs>\n"],"names":["DisplayEmitter"],"mappings":";;;;;;;;;;;;;;;AA6FA;;;;;;;AAOE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,qBAAqB,CAAC,IAAI;AACnC,IAAA,UAAU,EAAE,kBAAEA,WAAc,EAAE,aAAa,EAAE,YAAW,EAAG;AAC3D,IAAA,KAAK,EAAE;AACL;;;;AAIE;AACF,QAAA,WAAW,EAAE,MAAM;AACnB;;;;AAIE;QACF,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;AAC7C;;;;AAIE;AACF,QAAA,oBAAoB,EAAE,MAAM;AAC5B;;;;AAIE;AACF,QAAA,QAAQ,EAAE,MAAM;AAChB;;;;;AAKE;AACF,QAAA,SAAS,EAAE,KAA2B;AACtC;;;;AAIE;AACF,QAAA,qBAAqB,EAAE;AACrB,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,GAAG;AACb,SAAA;AACF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAA;AACT,QAAA,MAAM,CAAA,GAAI,KAAK,EAAC;AAChB,QAAA,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAkB,EAAE,GAAI,QAAQ,CAAC,gBAAgB,CAAA;AAEzF,QAAA,MAAM,oBAAmB,GAAI,GAAG,CAAgB,IAAI,CAAA;QACpD,MAAM,kBAAkB,GAA2B,EAAC;AACpD,QAAA,MAAM,WAAU,GAAI,GAAG,CAAC,KAAK,CAAA;AAC7B,QAAA,MAAM,SAAQ,GAAI,GAAG,CAAgB,EAAE,CAAA;AAEvC,QAAA,MAAM,eAAc,GAAI,QAAQ,CAAgB,MAC9C,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CACvB,CAAC,CAAc,EAAE,CAAc,KAC7B,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,CAAE,CAAA;AAC7C,YAAA,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,CAAE,CAAC,CACjD,CACH;;;;QAKA,MAAM,2BAA0B,GAAI,QAAQ,CAC1C,MACE,KAAK,CAAC,qBAAoB;AAC1B,aAAC,oBAAoB,CAAC,KAAI,KAAM;AAC9B,kBAAE,cAAc,CAAC,KAAK,CAAC,MAAK,GAAI;kBAC9B,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CACpC;AAEA,QAAA,MAAM,mBAAkB,GAAI,QAAQ,CAAC,MACnC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,KAAK,MAAM,EAAE,GAAG,aAAa,EAAE,KAAI,EAAG,CAAC,CAAC,CACnF;AAEA,QAAA,MAAM,qBAAoB,GAAI,QAAQ,CAAC,MACrC,mBAAmB,CAAC,KAAI,KAAM;cAC1B,CAAC,mBAAmB,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC;AACvD,cAAE,mBAAmB,CAAC,KAAK,CAC/B;AAEA,QAAA,IAAI,SAAgB;QACpB,MAAM,oBAAmB,GAAI,CAAC,kBAAA,GAAoC,CAAC,OAAO,CAAC,KAAG;YAC5E,IAAI,SAAS,EAAE;gBACb,YAAY,CAAC,SAAS,CAAA;YACxB;AAEA,YAAA,WAAW,CAAC,QAAQ,IAAG;AACvB,YAAA,SAAQ,GAAI,CAAC,UAAU,CAAC,MAAI;AAC1B,gBAAA,WAAW,CAAC,KAAI,GAAI,KAAI;AACxB,gBAAA,oBAAoB,CAAC,KAAI,GAAI,IAAG;AAEhC,gBAAA,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,OAAM,IAAG;oBACrC,OAAO,CAAC,KAAK,CAAC;yBACX,KAAK,CAAC,GAAG;AACT,yBAAA,GAAG,CAAC,IAAG,IAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;yBACtC,OAAO,CAAC,QAAO,IAAG;wBACjB,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;AAC1C,4BAAA,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAA;wBACvC;AACF,oBAAA,CAAC,CAAA;AACL,gBAAA,CAAC,CAAA;AACH,YAAA,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAA;AAChC,QAAA,CAAA;AAEA,QAAA,MAAM,WAAW,CAAC,aAAqB,KAAS;AAC9C,YAAA,oBAAoB,EAAC;AAErB,YAAA,oBAAoB,CAAC,KAAI,GAAI,aAAY;YACzC,MAAM,QAAQ,GAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,CACtD,OAAM,IAAK,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAE,MAAM,aAAa,CAClF;;AAGD,YAAA,IAAI,mBAAmB,CAAC,KAAI,KAAM,EAAE,EAAE;;;AAGpC,gBAAA,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,OAAM,IAAG;AACrC,oBAAA,MAAM,KAAI,GAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAE,CAAA;AAEjE,oBAAA,kBAAkB,CAAC,KAAK,CAAA,GAAI,OAAO,CAAC,UAAS;oBAC7C,OAAO,CAAC,KAAK,CAAC,IAAG,GAAI,GAAG,OAAO,CAAC,UAAU,CAAA,EAAA,CAAG;AAC7C,oBAAA,OAAO,CAAC,KAAK,CAAC,QAAO,GAAI,UAAS;oBAClC,OAAO,CAAC,KAAK,CAAC,kBAAiB,GAAI,GAAG,2BAA2B,CAAC,KAAK,CAAA,EAAA,CAAG;AAE1E,oBAAA,IAAI,KAAI,KAAM,aAAa,EAAE;AAC3B,wBAAA,OAAO,CAAC,KAAK,CAAC,OAAM,GAAI,GAAE;wBAC1B,OAAO,CAAC,KAAK,CAAC,eAAc,GAAI,CAAA,EAC9B,CAAC,KAAI,GAAI,aAAY,GAAI,KAAI,GAAI,QAAQ,CAAC,IAAI,2BAA2B,CAAC,KAC5E,CAAA,EAAA,CAAG;oBACL;AACF,gBAAA,CAAC,CAAA;;;AAID,gBAAA,QAAQ,CAAC,KAAK,CAAC,eAAc,GAAI,CAAA,EAC/B,CAAC,cAAc,CAAC,KAAK,CAAC,MAAK,GAAI,CAAA,GAAI,cAAc,CAAC,KAAK,CAAC,MAAK,GAAI,CAAA,GAAI,CAAC;oBACtE,2BAA2B,CAAC,KAC9B,CAAA,EAAA,CAAG;;gBAGH,qBAAqB,CAAC,MAAI;oBACxB,MAAM,QAAO,GAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,QAAO;AAEnD,oBAAA,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAI;oBAC1B,QAAQ,CAAC,KAAK,CAAC,WAAW,CACxB,OAAO,EACP,CAAA,EAAG,QAAO,KAAM,MAAK,GAAI,QAAO,GAAI,MAAM,CAAA,CAAE,EAC5C,WAAW,CACb;AACF,gBAAA,CAAC,CAAA;YACH;iBAAO;;gBAEL,QAAQ,CAAC,KAAK,CAAC,kBAAiB,GAAI,GAAG,2BAA2B,CAAC,KAAK,CAAA,EAAA,CAAG;AAC3E,gBAAA,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAI;AAC1B,gBAAA,QAAQ,CAAC,KAAK,CAAC,WAAW,UAAS;;AAGnC,gBAAA,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAA;gBACrC,qBAAqB,CAAC,MAAI;oBACxB,QAAQ,CAAC,KAAK,CAAC,IAAG,GAAI,CAAA,EAAG,kBAAkB,CAAC,aAAa,CAAC,CAAA,EAAA,CAAG;AAC/D,gBAAA,CAAC,CAAA;YACH;AAEA,YAAA,CAAC,CAAC,IAAI,CAAC,4BAA4B,EAAE,aAAa,EAAE;AAClD,gBAAA,aAAa,EAAE,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC;gBAClD,cAAc,EAAE,mBAAmB,CAAC,KAAK;AAC1C,aAAA,CAAA;AACH,QAAA,CAAA;AAEA,QAAA,MAAM,aAAY,GAAI,CAAC,EAAW,KAAG;YACnC,MAAM,OAAM,GAAI,EAAgB;AAChC,YAAA,MAAM,KAAI,GAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAE,CAAA;;AAGjE,YAAA,OAAO,CAAC,KAAK,CAAC,OAAM,GAAI,GAAE;AAC1B,YAAA,OAAO,CAAC,KAAK,CAAC,YAAY,iBAAgB;AAC1C,YAAA,OAAO,CAAC,KAAK,CAAC,eAAc,GAAI,GAC9B,CAAC,oBAAoB,CAAC,KAAI,KAAM,IAAG,IAAK,KAAI,GAAI,oBAAoB,CAAC;kBACjE,QAAQ;kBACR,KAAK,IAAI,2BAA2B,CAAC,KAC3C,IAAG;YACH,OAAO,CAAC,KAAK,CAAC,kBAAiB,GAAI,GAAG,2BAA2B,CAAC,KAAK,CAAA,EAAA,CAAG;AAC5E,QAAA,CAAA;AAEA,QAAA,MAAM,UAAU,CAAC,EAAW,EAAE,IAAgB,KAAG;YAC/C,MAAM,OAAM,GAAI,EAAgB;AAChC,YAAA,MAAM,KAAI,GAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAE,CAAA;;;AAIjE,YAAA,OAAO,CAAC,KAAK,CAAC,IAAG,GAAI,CAAA,EAAG,kBAAkB,CAAC,KAAK,CAAA,IAAK,OAAO,CAAC,UAAU,IAAG;;YAG1E,qBAAqB,CAAC,MAAI;AACxB,gBAAA,OAAO,CAAC,KAAK,CAAC,OAAM,GAAI,GAAE;AAC1B,gBAAA,OAAO,CAAC,KAAK,CAAC,QAAO,GAAI,UAAS;AAClC,gBAAA,OAAO,CAAC,KAAK,CAAC,SAAQ,GAAI,eAAc;AAC1C,YAAA,CAAC,CAAA;AAED,YAAA,IAAI,EAAC;AACP,QAAA,CAAA;AAEA,QAAA,MAAM,UAAU,CAAC,EAAW,EAAE,IAAgB,KAAG;YAC/C,MAAM,OAAM,GAAI,EAAgB;;YAGhC,qBAAqB,CAAC,MAAI;AACxB,gBAAA,OAAO,CAAC,KAAK,CAAC,OAAM,GAAI,GAAE;AAC1B,gBAAA,OAAO,CAAC,KAAK,CAAC,YAAY,iBAAgB;AAC5C,YAAA,CAAC,CAAA;;AAGD,YAAA,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,qBAAqB,CAAA;AAC9C,QAAA,CAAA;;;QAIA,CAAC,CAAC,EAAE,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,MAAI;YAChD,oBAAoB,CAAC,EAAE,CAAA;AACzB,QAAA,CAAC,CAAA;QAED,eAAe,CAAC,MAAI;AAClB,YAAA,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAA;AAClC,QAAA,CAAC,CAAA;QAED,OAAO;YACL,QAAQ;YACR,aAAa;YACb,OAAO;YACP,OAAO;YACP,mBAAmB;YACnB,qBAAqB;YACrB,SAAS;YACT,WAAW;YACX,CAAC;SACH;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"related-prompts-tag-list.vue2.js","sources":["../../../../../src/x-modules/related-prompts/components/related-prompts-tag-list.vue"],"sourcesContent":["<template>\n <SlidingPanel\n :key=\"x.query.search\"\n :fade=\"selectedPromptIndex === -1\"\n :reset-on-content-change=\"false\"\n :button-class=\"buttonClass\"\n :show-buttons=\"showButtons && selectedPromptIndex === -1\"\n :scroll-container-class=\"[\n 'x-related-prompts-tag-list-scroll-container',\n scrollContainerClass || '',\n ]\"\n >\n <template #sliding-panel-left-button>\n <!--\n @slot sliding-panel-left-button - The button to be displayed on the left side of the sliding panel.\n -->\n <slot name=\"sliding-panel-left-button\" />\n </template>\n <transition-group\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\n @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n >\n <li\n v-for=\"{ index, ...relatedPrompt } in visibleRelatedPrompts\"\n ref=\"listItems\"\n :key=\"relatedPrompt.suggestionText\"\n class=\"x-related-prompts-tag-list-item\"\n :class=\"[tagClass, tagColors && tagColors[index % tagColors.length]]\"\n :data-index=\"index\"\n :style=\"{\n ...(selectedPromptIndex === index && { width: '100%' }),\n ...(isAnimating && { pointerEvents: 'none' }),\n }\"\n data-test=\"related-prompts-tag-list-item\"\n >\n <!--\n @slot - The slot to render related prompt information.\n @prop {Object} relatedPrompt - The related prompt object.\n @prop {Function} onSelect - The function to select the related prompt.\n @prop {Boolean} isSelected - Indicates if the related prompt is currently selected.\n -->\n <slot\n :related-prompt=\"relatedPrompt\"\n :on-select=\"() => onSelect(index)\"\n :is-selected=\"selectedPromptIndex === index\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.tagging?.toolingDisplayTagging!\"\n :event-metadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false,\n }\"\n >\n <RelatedPrompt\n :related-prompt=\"relatedPrompt\"\n :selected=\"selectedPromptIndex === index\"\n @click=\"onSelect(index)\"\n >\n <template #related-prompt-extra-content>\n <!--\n @slot related-prompt-extra-content - The slot to render related prompt extra information.\n @prop {Object} relatedPrompt - The related prompt object.\n -->\n <slot name=\"related-prompt-extra-content\" :related-prompt=\"relatedPrompt\" />\n </template>\n </RelatedPrompt>\n </DisplayEmitter>\n </slot>\n </li>\n </transition-group>\n <template #sliding-panel-right-button>\n <!--\n @slot sliding-panel-right-button - The button to be displayed on the right side of the sliding panel.\n -->\n <slot name=\"sliding-panel-right-button\" />\n </template>\n </SlidingPanel>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { computed, defineComponent, onBeforeUnmount, ref } from 'vue'\nimport DisplayEmitter from '../../../components/display-emitter.vue'\nimport SlidingPanel from '../../../components/sliding-panel.vue'\nimport { use$x, useState } from '../../../composables'\nimport { relatedPromptsXModule } from '../x-module'\nimport RelatedPrompt from './related-prompt.vue'\n\n/**\n * This component shows the list of `RelatedPrompts` components.\n *\n * If the default slot is reimplemented in the consumer, `onSelect` function will be\n * necessary to handle the selection of the related prompt and to trigger the stagger-fade-slide animation.\n *\n * @public\n */\nexport default defineComponent({\n name: 'RelatedPromptsTagList',\n xModule: relatedPromptsXModule.name,\n components: { DisplayEmitter, RelatedPrompt, SlidingPanel },\n props: {\n /**\n * The CSS class for the left and right button of the sliding panel.\n *\n * @public\n */\n buttonClass: String,\n /**\n * The boolean prop to handle the visiblity of sliding pannel buttons.\n *\n * @public\n */\n showButtons: { type: Boolean, default: true },\n /**\n * The CSS class for the wrapper of all the related prompt wrapper elements.\n *\n * @public\n */\n scrollContainerClass: String,\n /**\n * The CSS class for all the related prompt wrapper elements.\n *\n * @public\n */\n tagClass: String,\n /**\n * Array of colors to apply to the related prompts. It will be applied to tag\n * elements cyclically according to their index in the nex way: `tagColors[index % tagColors.length]`.\n *\n * @public\n */\n tagColors: Array as PropType<string[]>,\n /**\n * The duration of the total animation in milliseconds.\n *\n * @public\n */\n animationDurationInMs: {\n type: Number,\n default: 700,\n },\n },\n setup(props) {\n const x = use$x()\n const { relatedPrompts, selectedPrompt: selectedPromptIndex } = useState('relatedPrompts')\n\n const clickedListItemIndex = ref<number | null>(null)\n const initialOffsetLefts: Record<number, number> = {}\n const isAnimating = ref(false)\n const listItems = ref<HTMLElement[]>([])\n\n const sortedListItems = computed<HTMLElement[]>(() =>\n [...listItems.value].sort(\n (a: HTMLElement, b: HTMLElement) =>\n Number.parseInt(b.getAttribute('data-index')!) -\n Number.parseInt(a.getAttribute('data-index')!),\n ),\n )\n\n // The duration of a single animation (enter or leave) in milliseconds\n // if a related prompt is clicked (clickedListItemIndex.value !== null), the duration is divided by the number of related\n // prompts -1 (the clicked one is synchronized with the last one to leave or the first one to enter)\n const singleAnimationDurationInMs = computed(\n () =>\n props.animationDurationInMs /\n (clickedListItemIndex.value !== null\n ? relatedPrompts.value.length - 1\n : relatedPrompts.value.length),\n )\n\n const indexRelatedPrompts = computed(() =>\n relatedPrompts.value.map((relatedPrompt, index) => ({ ...relatedPrompt, index })),\n )\n\n const visibleRelatedPrompts = computed(() =>\n selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value,\n )\n\n let timeOutId: number\n const resetTransitionStyle = (excludedProperties: Array<string> = ['width']) => {\n if (timeOutId) {\n clearTimeout(timeOutId)\n }\n\n isAnimating.value = true\n timeOutId = +setTimeout(() => {\n isAnimating.value = false\n clickedListItemIndex.value = null\n\n sortedListItems.value.forEach(element => {\n element.style.cssText\n .split(';')\n .map(rule => rule.split(':')[0]?.trim())\n .forEach(property => {\n if (!excludedProperties.includes(property)) {\n element.style.removeProperty(property)\n }\n })\n })\n }, props.animationDurationInMs)\n }\n\n const onSelect = (selectedIndex: number): void => {\n resetTransitionStyle()\n\n clickedListItemIndex.value = selectedIndex\n const selected: HTMLElement = sortedListItems.value.find(\n element => Number.parseInt(element.getAttribute('data-index')!) === selectedIndex,\n )!\n\n // selectedPromptIndex.value === -1 ? 'SELECTING' : 'DESELECTING'\n if (selectedPromptIndex.value === -1) {\n // Prepare all the elements for the leave animation (~ 'beforeLeave' hook). Remember the elements are\n // sorted in descending order by index.\n sortedListItems.value.forEach(element => {\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n initialOffsetLefts[index] = element.offsetLeft\n element.style.left = `${element.offsetLeft}px`\n element.style.position = 'absolute'\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n\n if (index !== selectedIndex) {\n element.style.opacity = '1'\n element.style.transitionDelay = `${\n (index < selectedIndex ? index : index - 1) * singleAnimationDurationInMs.value\n }ms`\n }\n })\n\n // Synchronize the transition delay of the selected element with the last\n // element to leave\n selected.style.transitionDelay = `${\n (relatedPrompts.value.length > 1 ? relatedPrompts.value.length - 2 : 0) *\n singleAnimationDurationInMs.value\n }ms`\n\n // Trigger the animation (selecting) for the selected element\n requestAnimationFrame(() => {\n const maxWidth = getComputedStyle(selected).maxWidth\n\n selected.style.left = '0px'\n selected.style.setProperty(\n 'width',\n `${maxWidth !== 'none' ? maxWidth : '100%'}`,\n 'important',\n )\n })\n } else {\n // Prepare the selected element for the deselecting animation\n selected.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n selected.style.left = '0px'\n selected.style.position = 'absolute'\n\n // Trigger the animation (deselecting) for the selected element\n selected.style.removeProperty('width')\n requestAnimationFrame(() => {\n selected.style.left = `${initialOffsetLefts[selectedIndex]}px`\n })\n }\n\n x.emit('UserSelectedARelatedPrompt', selectedIndex, {\n relatedPrompt: relatedPrompts.value[selectedIndex],\n selectedPrompt: selectedPromptIndex.value,\n })\n }\n\n const onBeforeEnter = (el: Element) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Prepare the element for the enter animation\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n element.style.transitionDelay = `${\n (clickedListItemIndex.value !== null && index > clickedListItemIndex.value\n ? index - 1\n : index) * singleAnimationDurationInMs.value\n }ms`\n element.style.transitionDuration = `${singleAnimationDurationInMs.value}ms`\n }\n\n const onEnter = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n const index = Number.parseInt(element.getAttribute('data-index')!)\n\n // Also part of the preparation for the enter animation, but it needs to be done\n // once the element is inserted in DOM (if not the offsetLeft will be always 0)\n element.style.left = `${initialOffsetLefts[index] ?? element.offsetLeft}px`\n\n // trigger enter animation\n requestAnimationFrame(() => {\n element.style.opacity = '1'\n element.style.position = 'absolute'\n element.style.transform = 'translateY(0)'\n })\n\n done()\n }\n\n const onLeave = (el: Element, done: () => void) => {\n const element = el as HTMLElement\n\n // trigger leave animation\n requestAnimationFrame(() => {\n element.style.opacity = '0'\n element.style.transform = 'translateY(5px)'\n })\n\n // Wait for the animation to finish (done() exectution extracts the element from the DOM)\n setTimeout(done, props.animationDurationInMs)\n }\n\n // Changing the request will trigger the appear animation, so we need to reset the\n // style after it finishes\n x.on('SearchRequestChanged', false).subscribe(() => {\n resetTransitionStyle([])\n })\n\n onBeforeUnmount(() => {\n x.emit('RelatedPromptsUnmounted')\n })\n\n return {\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x,\n }\n },\n})\n</script>\n\n<style lang=\"css\">\n.x-related-prompts-tag-list-scroll-container {\n height: 100%;\n position: relative;\n}\n.x-related-prompts-tag-list {\n display: flex;\n gap: 16px;\n min-width: 100%;\n width: 100%;\n}\n.x-related-prompts-tag-list-item {\n height: 100%;\n flex-shrink: 0;\n}\n</style>\n\n<docs lang=\"mdx\">\n## See it in action\n\n### Basic usage\n\n```vue live\n<template>\n <RelatedPromptsTagList />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing tag colors and classes\n\n```vue live\n<template>\n <RelatedPromptsTagList :tagColors=\"['x-bg-neutral-50', 'x-bg-lead-50']\" tagClass=\"rounded\" />\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Using the default slot to customize prompt rendering\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #default=\"{ relatedPrompt, onSelect, isSelected }\">\n <button :class=\"{ selected: isSelected }\" @click=\"onSelect()\">\n {{ relatedPrompt.suggestionText }}\n </button>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n\n### Customizing extra content in RelatedPrompt\n\n```vue live\n<template>\n <RelatedPromptsTagList>\n <template #related-prompt-extra-content=\"{ relatedPrompt }\">\n <span>Extra: {{ relatedPrompt.suggestionText }}</span>\n </template>\n </RelatedPromptsTagList>\n</template>\n\n<script setup>\nimport { RelatedPromptsTagList } from '@empathyco/x-components/related-prompts'\n</script>\n```\n</docs>\n"],"names":["DisplayEmitter"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empathyco/x-components",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.2",
|
|
4
4
|
"description": "Empathy X Components",
|
|
5
5
|
"author": "Empathy Systems Corporation S.L.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -67,10 +67,10 @@
|
|
|
67
67
|
"vuex": "4.0.2"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@empathyco/x-adapter": "8.1.
|
|
71
|
-
"@empathyco/x-adapter-platform": "1.2.
|
|
72
|
-
"@empathyco/x-types": "10.2.
|
|
73
|
-
"@empathyco/x-utils": "1.0.
|
|
70
|
+
"@empathyco/x-adapter": "8.1.6",
|
|
71
|
+
"@empathyco/x-adapter-platform": "1.2.2",
|
|
72
|
+
"@empathyco/x-types": "10.2.2",
|
|
73
|
+
"@empathyco/x-utils": "1.0.7",
|
|
74
74
|
"@vue/devtools-api": "~6.6.4",
|
|
75
75
|
"@vueuse/core": "~12.8.2",
|
|
76
76
|
"js-md5": "~0.8.3",
|
|
@@ -78,36 +78,36 @@
|
|
|
78
78
|
"rxjs": "~7.8.2",
|
|
79
79
|
"tslib": "~2.8.1",
|
|
80
80
|
"vue-global-events": "~3.0.1",
|
|
81
|
-
"vue-tsc": "~3.2.
|
|
81
|
+
"vue-tsc": "~3.2.9"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@babel/preset-env": "7.29.5",
|
|
85
|
-
"@empathyco/x-design-system": "1.0.
|
|
85
|
+
"@empathyco/x-design-system": "1.0.6",
|
|
86
86
|
"@microsoft/api-documenter": "7.30.5",
|
|
87
87
|
"@microsoft/api-extractor": "7.58.7",
|
|
88
|
-
"@tailwindcss/vite": "4.
|
|
88
|
+
"@tailwindcss/vite": "4.3.0",
|
|
89
89
|
"@testing-library/vue": "8.1.0",
|
|
90
90
|
"@types/aria-query": "5.0.4",
|
|
91
|
-
"@types/node": "24.12.
|
|
91
|
+
"@types/node": "24.12.4",
|
|
92
92
|
"@vitejs/plugin-vue": "5.2.4",
|
|
93
|
-
"@vitest/browser": "4.1.
|
|
94
|
-
"@vitest/ui": "4.1.
|
|
93
|
+
"@vitest/browser": "4.1.6",
|
|
94
|
+
"@vitest/ui": "4.1.6",
|
|
95
95
|
"@vue/test-utils": "2.4.10",
|
|
96
96
|
"convert-source-map": "2.0.0",
|
|
97
97
|
"esbuild": "0.28.0",
|
|
98
98
|
"jsdom": "29.1.1",
|
|
99
|
-
"rollup": "4.60.
|
|
99
|
+
"rollup": "4.60.4",
|
|
100
100
|
"rollup-plugin-copy": "3.5.0",
|
|
101
101
|
"rollup-plugin-delete": "2.2.0",
|
|
102
102
|
"rollup-plugin-styles": "4.0.0",
|
|
103
103
|
"rollup-plugin-typescript2": "0.37.0",
|
|
104
104
|
"rollup-plugin-vue": "6.0.0",
|
|
105
|
-
"tailwindcss": "4.
|
|
105
|
+
"tailwindcss": "4.3.0",
|
|
106
106
|
"ts-node": "10.9.2",
|
|
107
107
|
"typescript": "5.9.3",
|
|
108
108
|
"vite": "6.4.2",
|
|
109
109
|
"vite-plugin-vue-inspector": "5.4.0",
|
|
110
|
-
"vitest": "4.1.
|
|
110
|
+
"vitest": "4.1.6",
|
|
111
111
|
"vue": "3.5.34",
|
|
112
112
|
"vue-docgen-cli": "4.79.0",
|
|
113
113
|
"vue-router": "4.6.4",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"access": "public",
|
|
118
118
|
"directory": "dist"
|
|
119
119
|
},
|
|
120
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "ea86587eca39f8e31be423a8ab3938435336c0d6"
|
|
121
121
|
}
|
|
@@ -72642,6 +72642,15 @@
|
|
|
72642
72642
|
"text": "BooleanConstructor",
|
|
72643
72643
|
"canonicalReference": "!BooleanConstructor:interface"
|
|
72644
72644
|
},
|
|
72645
|
+
{
|
|
72646
|
+
"kind": "Content",
|
|
72647
|
+
"text": ";\n default: boolean;\n };\n fade: {\n type: "
|
|
72648
|
+
},
|
|
72649
|
+
{
|
|
72650
|
+
"kind": "Reference",
|
|
72651
|
+
"text": "BooleanConstructor",
|
|
72652
|
+
"canonicalReference": "!BooleanConstructor:interface"
|
|
72653
|
+
},
|
|
72645
72654
|
{
|
|
72646
72655
|
"kind": "Content",
|
|
72647
72656
|
"text": ";\n default: boolean;\n };\n buttonClass: {\n type: "
|
|
@@ -72822,6 +72831,15 @@
|
|
|
72822
72831
|
"text": "BooleanConstructor",
|
|
72823
72832
|
"canonicalReference": "!BooleanConstructor:interface"
|
|
72824
72833
|
},
|
|
72834
|
+
{
|
|
72835
|
+
"kind": "Content",
|
|
72836
|
+
"text": ";\n default: boolean;\n };\n fade: {\n type: "
|
|
72837
|
+
},
|
|
72838
|
+
{
|
|
72839
|
+
"kind": "Reference",
|
|
72840
|
+
"text": "BooleanConstructor",
|
|
72841
|
+
"canonicalReference": "!BooleanConstructor:interface"
|
|
72842
|
+
},
|
|
72825
72843
|
{
|
|
72826
72844
|
"kind": "Content",
|
|
72827
72845
|
"text": ";\n default: boolean;\n };\n buttonClass: {\n type: "
|
|
@@ -72869,7 +72887,7 @@
|
|
|
72869
72887
|
},
|
|
72870
72888
|
{
|
|
72871
72889
|
"kind": "Content",
|
|
72872
|
-
"text": "<{}>, {\n scrollFactor: number;\n showButtons: boolean;\n resetOnContentChange: boolean;\n}, {}, {}, {}, string, import(\"vue\")."
|
|
72890
|
+
"text": "<{}>, {\n scrollFactor: number;\n showButtons: boolean;\n resetOnContentChange: boolean;\n fade: boolean;\n}, {}, {}, {}, string, import(\"vue\")."
|
|
72873
72891
|
},
|
|
72874
72892
|
{
|
|
72875
72893
|
"kind": "Reference",
|
|
@@ -72887,7 +72905,7 @@
|
|
|
72887
72905
|
"name": "SlidingPanel",
|
|
72888
72906
|
"variableTypeTokenRange": {
|
|
72889
72907
|
"startIndex": 1,
|
|
72890
|
-
"endIndex":
|
|
72908
|
+
"endIndex": 68
|
|
72891
72909
|
}
|
|
72892
72910
|
},
|
|
72893
72911
|
{
|
|
@@ -7880,6 +7880,10 @@ resetOnContentChange: {
|
|
|
7880
7880
|
type: BooleanConstructor;
|
|
7881
7881
|
default: boolean;
|
|
7882
7882
|
};
|
|
7883
|
+
fade: {
|
|
7884
|
+
type: BooleanConstructor;
|
|
7885
|
+
default: boolean;
|
|
7886
|
+
};
|
|
7883
7887
|
buttonClass: {
|
|
7884
7888
|
type: PropType<VueCSSClasses>;
|
|
7885
7889
|
};
|
|
@@ -7916,6 +7920,10 @@ resetOnContentChange: {
|
|
|
7916
7920
|
type: BooleanConstructor;
|
|
7917
7921
|
default: boolean;
|
|
7918
7922
|
};
|
|
7923
|
+
fade: {
|
|
7924
|
+
type: BooleanConstructor;
|
|
7925
|
+
default: boolean;
|
|
7926
|
+
};
|
|
7919
7927
|
buttonClass: {
|
|
7920
7928
|
type: PropType<VueCSSClasses>;
|
|
7921
7929
|
};
|
|
@@ -7926,6 +7934,7 @@ type: PropType<VueCSSClasses>;
|
|
|
7926
7934
|
scrollFactor: number;
|
|
7927
7935
|
showButtons: boolean;
|
|
7928
7936
|
resetOnContentChange: boolean;
|
|
7937
|
+
fade: boolean;
|
|
7929
7938
|
}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
|
|
7930
7939
|
|
|
7931
7940
|
// @public
|
|
@@ -31,6 +31,13 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
31
31
|
type: BooleanConstructor;
|
|
32
32
|
default: boolean;
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* When true, applies the design-system edge fade mask to the scroll container.
|
|
36
|
+
*/
|
|
37
|
+
fade: {
|
|
38
|
+
type: BooleanConstructor;
|
|
39
|
+
default: boolean;
|
|
40
|
+
};
|
|
34
41
|
buttonClass: {
|
|
35
42
|
type: PropType<VueCSSClasses>;
|
|
36
43
|
};
|
|
@@ -75,6 +82,13 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
75
82
|
type: BooleanConstructor;
|
|
76
83
|
default: boolean;
|
|
77
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* When true, applies the design-system edge fade mask to the scroll container.
|
|
87
|
+
*/
|
|
88
|
+
fade: {
|
|
89
|
+
type: BooleanConstructor;
|
|
90
|
+
default: boolean;
|
|
91
|
+
};
|
|
78
92
|
buttonClass: {
|
|
79
93
|
type: PropType<VueCSSClasses>;
|
|
80
94
|
};
|
|
@@ -85,6 +99,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
85
99
|
scrollFactor: number;
|
|
86
100
|
showButtons: boolean;
|
|
87
101
|
resetOnContentChange: boolean;
|
|
102
|
+
fade: boolean;
|
|
88
103
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
89
104
|
export default _default;
|
|
90
105
|
//# sourceMappingURL=sliding-panel.vue?vue&type=script&lang.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sliding-panel.vue?vue&type=script&lang.d.ts","sourceRoot":"","sources":["../../../../src/components/sliding-panel.vue?vue&type=script&lang.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAUnD;;;;;;;;;GASG;;IAIC;;OAEG;;;;;IAKH,yFAAyF;;;;;IAKzF;;;OAGG;;;;;;cAK6C,QAAQ,CAAC,aAAa,CAAC;;;cACd,QAAQ,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"sliding-panel.vue?vue&type=script&lang.d.ts","sourceRoot":"","sources":["../../../../src/components/sliding-panel.vue?vue&type=script&lang.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAUnD;;;;;;;;;GASG;;IAIC;;OAEG;;;;;IAKH,yFAAyF;;;;;IAKzF;;;OAGG;;;;;IAKH;;OAEG;;;;;;cAK6C,QAAQ,CAAC,aAAa,CAAC;;;cACd,QAAQ,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;IA5BhF;;OAEG;;;;;IAKH,yFAAyF;;;;;IAKzF;;;OAGG;;;;;IAKH;;OAEG;;;;;;cAK6C,QAAQ,CAAC,aAAa,CAAC;;;cACd,QAAQ,CAAC,aAAa,CAAC;;;;;;;;AA/BpF,wBAiFE"}
|