@empathyco/x-components 6.0.0-alpha.50 → 6.0.0-alpha.52
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 +17 -0
- package/design-system/deprecated-full-theme.css +1542 -1542
- package/docs/API-reference/api/x-components.slidingpanel.md +13 -5
- package/docs/API-reference/components/common/x-components.sliding-panel.md +7 -7
- package/js/components/sliding-panel.vue.js.map +1 -1
- package/js/components/sliding-panel.vue2.js +2 -2
- package/js/components/sliding-panel.vue2.js.map +1 -1
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue.js +4 -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 +7 -5
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue2.js.map +1 -1
- package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue3.js +1 -1
- package/package.json +10 -10
- package/report/x-components.api.json +52 -16
- package/report/x-components.api.md +12 -4
- package/types/components/sliding-panel.vue.d.ts +15 -5
- package/types/components/sliding-panel.vue.d.ts.map +1 -1
- package/types/x-modules/related-prompts/components/related-prompts-tag-list.vue.d.ts.map +1 -1
|
@@ -24,14 +24,18 @@ _default: import("vue").DefineComponent<{
|
|
|
24
24
|
type: BooleanConstructor;
|
|
25
25
|
default: boolean;
|
|
26
26
|
};
|
|
27
|
-
buttonClass:
|
|
28
|
-
|
|
27
|
+
buttonClass: {
|
|
28
|
+
type: PropType<VueCSSClasses>;
|
|
29
|
+
};
|
|
30
|
+
scrollContainerClass: {
|
|
31
|
+
type: PropType<VueCSSClasses>;
|
|
32
|
+
};
|
|
29
33
|
}, {
|
|
30
34
|
cssClasses: import("vue").ComputedRef<{
|
|
31
35
|
'x-sliding-panel-at-start': boolean;
|
|
32
36
|
'x-sliding-panel-at-end': boolean;
|
|
33
37
|
}>;
|
|
34
|
-
debouncedUpdateScroll: import("
|
|
38
|
+
debouncedUpdateScroll: import("../utils/types").DebouncedFunction<[]>;
|
|
35
39
|
scrollContainerRef: import("vue").Ref<HTMLDivElement | undefined>;
|
|
36
40
|
scrollLeft: () => void;
|
|
37
41
|
scrollRight: () => void;
|
|
@@ -51,8 +55,12 @@ _default: import("vue").DefineComponent<{
|
|
|
51
55
|
type: BooleanConstructor;
|
|
52
56
|
default: boolean;
|
|
53
57
|
};
|
|
54
|
-
buttonClass:
|
|
55
|
-
|
|
58
|
+
buttonClass: {
|
|
59
|
+
type: PropType<VueCSSClasses>;
|
|
60
|
+
};
|
|
61
|
+
scrollContainerClass: {
|
|
62
|
+
type: PropType<VueCSSClasses>;
|
|
63
|
+
};
|
|
56
64
|
}>>, {
|
|
57
65
|
scrollFactor: number;
|
|
58
66
|
showButtons: boolean;
|
|
@@ -14,13 +14,13 @@ Additionally, this component exposes the following props to modify the classes o
|
|
|
14
14
|
|
|
15
15
|
## Props
|
|
16
16
|
|
|
17
|
-
| Name | Description | Type
|
|
18
|
-
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
-
| <code>scrollFactor</code> | Scroll factor that will dictate how much the scroll moves when pressing a navigation button. | <code>number</code>
|
|
20
|
-
| <code>showButtons</code> | Would make the navigation buttons visible when they're needed or always hide them. | <code>boolean</code>
|
|
21
|
-
| <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>
|
|
22
|
-
| <code>buttonClass</code> | | <code>
|
|
23
|
-
| <code>scrollContainerClass</code> | | <code>
|
|
17
|
+
| Name | Description | Type | Default |
|
|
18
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------- | ----------------- |
|
|
19
|
+
| <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> |
|
|
20
|
+
| <code>showButtons</code> | Would make the navigation buttons visible when they're needed or always hide them. | <code>boolean</code> | <code>true</code> |
|
|
21
|
+
| <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> |
|
|
22
|
+
| <code>buttonClass</code> | | <code>VueCSSClasses</code> | <code></code> |
|
|
23
|
+
| <code>scrollContainerClass</code> | | <code>VueCSSClasses</code> | <code></code> |
|
|
24
24
|
|
|
25
25
|
## Slots
|
|
26
26
|
|
|
@@ -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=\"x-sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <button\n v-if=\"showButtons\"\n @click=\"scrollLeft\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <div\n ref=\"scrollContainerRef\"\n @scroll=\"debouncedUpdateScroll\"\n @transitionend=\"debouncedUpdateScroll\"\n @animationend=\"debouncedUpdateScroll\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <button\n v-if=\"showButtons\"\n @click=\"scrollRight\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue';\n import { useDebounce } from '../composables/use-debounce';\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 */\n export 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: String,\n scrollContainerClass: String\n },\n setup(props, { slots }) {\n /** Indicates if the scroll is at the start of the sliding panel. */\n const isScrollAtStart = ref(true);\n /** Indicates if the scroll is at the end of the sliding panel. */\n const isScrollAtEnd = ref(true);\n const scrollContainerRef = ref<HTMLDivElement>();\n\n /**\n * Updates the values of the scroll positions to show or hide the buttons depending on it.\n *\n * @remarks The 2px extra is to fix some cases in some resolutions where the scroll + client\n * size is less than the scroll width even when the scroll is at the end.\n */\n function updateScrollPosition() {\n if (scrollContainerRef.value) {\n const { scrollLeft, clientWidth, scrollWidth } = scrollContainerRef.value;\n isScrollAtStart.value = !scrollLeft;\n isScrollAtEnd.value = scrollLeft + clientWidth + 2 >= scrollWidth;\n }\n }\n\n /**\n * Debounced version of the {@link SlidingPanel.updateScrollPosition} method.\n */\n const debouncedUpdateScroll = useDebounce(updateScrollPosition, 50, { leading: true });\n\n /**\n * Resets the scroll and updates the values of the scroll for the buttons to react.\n */\n const debouncedRestoreAndUpdateScroll = useDebounce(\n () => {\n scrollContainerRef.value!.scroll({ left: 0, behavior: 'smooth' });\n updateScrollPosition();\n },\n 50,\n { leading: true }\n );\n\n /**\n * Scrolls the wrapper element towards the provided scroll value.\n *\n * @param scrollValue - The value the scroll will go towards.\n */\n function scrollTo(scrollValue: number) {\n scrollContainerRef.value!.scrollBy({\n left: scrollValue * props.scrollFactor,\n behavior: 'smooth'\n });\n }\n\n /** Scrolls the wrapper element to the left. */\n function scrollLeft() {\n scrollTo(-scrollContainerRef.value!.clientWidth);\n }\n\n /** Scrolls the wrapper element to the right. */\n function scrollRight() {\n scrollTo(scrollContainerRef.value!.clientWidth);\n }\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'x-sliding-panel-at-start': isScrollAtStart.value,\n 'x-sliding-panel-at-end': isScrollAtEnd.value\n }));\n\n let resizeObserver: ResizeObserver;\n let contentChangedObserver: MutationObserver;\n\n /**\n * Initialises browser platform code:\n * - Creates a mutation observer to detect content changes and reset scroll position.\n * - Stores initial size and scroll position values.\n */\n onMounted(() => {\n resizeObserver = new ResizeObserver(debouncedUpdateScroll);\n resizeObserver.observe(scrollContainerRef.value!);\n contentChangedObserver = new MutationObserver(debouncedRestoreAndUpdateScroll);\n\n watch(\n () => props.resetOnContentChange,\n shouldReset => {\n if (shouldReset) {\n contentChangedObserver.observe(scrollContainerRef.value!, {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false\n });\n } else {\n contentChangedObserver.disconnect();\n }\n },\n { immediate: true }\n );\n\n updateScrollPosition();\n });\n\n onBeforeUnmount(() => {\n contentChangedObserver.disconnect();\n resizeObserver.disconnect();\n });\n\n return {\n cssClasses,\n debouncedUpdateScroll,\n scrollContainerRef,\n scrollLeft,\n scrollRight,\n slots\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-sliding-panel {\n align-items: center;\n display: flex;\n flex-flow: row nowrap;\n position: relative;\n }\n\n .x-sliding-panel__button {\n opacity: 0;\n pointer-events: none;\n position: absolute;\n transition: all ease-out 0.2s;\n z-index: 2; /* To overlay the design system gradient with z-index:1 */\n }\n .x-sliding-panel-button-left {\n left: 0;\n }\n .x-sliding-panel-button-right {\n right: 0;\n }\n\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\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-start) .x-sliding-panel-button-left {\n opacity: 1;\n pointer-events: all;\n }\n\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-end) .x-sliding-panel-button-right {\n opacity: 1;\n pointer-events: all;\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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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","showButtons","_createCommentVNode","_createElementVNode","scrollContainerClass"],"mappings":";;;;;qBACE,IAiCM,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,QAAA,EAAA;AAlCR,EAAA,OAAA,IAAA,CAAA,KAAA,CAAA,OAAA,IAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IACkC,KAAA;AAAA,IAAA;AAAA,MAAsC,GAAA,EAAA,CAAA;AAAA,MAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,iBAAA,EAAA,IAAA,CAAA,UAAA,CAAA,CAAA;AAE5DC,MAAAA,WAAAA,EAAAA,eAAAA;AAAAA,KAAAA;;WAHZ,WAIY,IAAAH,SAAA,EAAA,EAAAC,kBAAA;AAAA,QAAA,QAAA;AAAA,QAAA;AAAA,UACN,GAAK,EAAA,CAAA;AAAA,UAEL,gBAAU,CAA2B,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,UAAA,IAAA,IAAA,CAAA,UAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,8DAAA,EAAA,IAAA,CAAA,WAAA,CAAA,CAAA;UAGrC,WAA+C,EAAA,2BAAA;AAAA,SAAA;;;;AAVrD,WAAA,EAAA,IAAA,CAAA;AAAA,SAYI;AAAA,QAAA,CAAA;AAAA;AAAA,OAWM,IAVJE,mBAAI,MAAoB,EAAA,IAAA,CAAA;AAAA,MAAAC,kBAAA;AACjB,QAAA,KAAA;AAAA,QAAA;AAAA,UACN,GAAA,EAAA,oBAAA;AAAA,UACA,iBAAY,CAAE,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UACd,eAAA,EAjBP,MAiBcC,CAAAA,CAAAA,CAAAA,KAAAA,MAAAA,CAAAA,CAAAA,CAAAA,GAAAA,CAAAA,GAAAA,IAAAA,KACF,IAAyB,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAC/B,gBAAU,MAAsB,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAJ,cAAA,CAAA,CAAA,IAAA,CAAA,oBAAA,EAAA,yBAAA,CAAA,CAAA;UAGhC,WAAQ,EAAA,sBAAA;AAAA,SAAA;;UAGFC,UAAW,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAA,EAAA,KAAA,CAAA,EAAA,IAAA,CAAA;AAAA,SAAA;;;AADnB,OAAA;AAAA,MAAA,IAAA,CAxBJ,WA0BY,IAAAH,SAAA,EAAA,EAAAC,kBAAA;AAAA,QAAA,QAAA;AAAA,QAAA;AAAA,UACN,GAAK,EAAA,CAAA;AAAA,UAEL,gBAAU,CAA4B,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,WAAA,IAAA,IAAA,CAAA,WAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,+DAAA,EAAA,IAAA,CAAA,WAAA,CAAA,CAAA;UAGtC,WAAgD,EAAA,4BAAA;AAAA,SAAA;;;;AAhCtD,WAAA,EAAA,IAAA,CAAA;AAAA,SAAA;;;AAAA,OAAA,IAAAE,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AAAA,KAAA;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"sliding-panel.vue.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"x-sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <button\n v-if=\"showButtons\"\n @click=\"scrollLeft\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <div\n ref=\"scrollContainerRef\"\n @scroll=\"debouncedUpdateScroll\"\n @transitionend=\"debouncedUpdateScroll\"\n @animationend=\"debouncedUpdateScroll\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <button\n v-if=\"showButtons\"\n @click=\"scrollRight\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, onBeforeUnmount, onMounted, PropType, ref, watch } from 'vue';\n import { useDebounce } from '../composables/use-debounce';\n import { VueCSSClasses } from '../utils/types';\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 */\n export 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 /** Indicates if the scroll is at the start of the sliding panel. */\n const isScrollAtStart = ref(true);\n /** Indicates if the scroll is at the end of the sliding panel. */\n const isScrollAtEnd = ref(true);\n const scrollContainerRef = ref<HTMLDivElement>();\n\n /**\n * Updates the values of the scroll positions to show or hide the buttons depending on it.\n *\n * @remarks The 2px extra is to fix some cases in some resolutions where the scroll + client\n * size is less than the scroll width even when the scroll is at the end.\n */\n function updateScrollPosition() {\n if (scrollContainerRef.value) {\n const { scrollLeft, clientWidth, scrollWidth } = scrollContainerRef.value;\n isScrollAtStart.value = !scrollLeft;\n isScrollAtEnd.value = scrollLeft + clientWidth + 2 >= scrollWidth;\n }\n }\n\n /**\n * Debounced version of the {@link SlidingPanel.updateScrollPosition} method.\n */\n const debouncedUpdateScroll = useDebounce(updateScrollPosition, 50, { leading: true });\n\n /**\n * Resets the scroll and updates the values of the scroll for the buttons to react.\n */\n const debouncedRestoreAndUpdateScroll = useDebounce(\n () => {\n scrollContainerRef.value!.scroll({ left: 0, behavior: 'smooth' });\n updateScrollPosition();\n },\n 50,\n { leading: true }\n );\n\n /**\n * Scrolls the wrapper element towards the provided scroll value.\n *\n * @param scrollValue - The value the scroll will go towards.\n */\n function scrollTo(scrollValue: number) {\n scrollContainerRef.value!.scrollBy({\n left: scrollValue * props.scrollFactor,\n behavior: 'smooth'\n });\n }\n\n /** Scrolls the wrapper element to the left. */\n function scrollLeft() {\n scrollTo(-scrollContainerRef.value!.clientWidth);\n }\n\n /** Scrolls the wrapper element to the right. */\n function scrollRight() {\n scrollTo(scrollContainerRef.value!.clientWidth);\n }\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'x-sliding-panel-at-start': isScrollAtStart.value,\n 'x-sliding-panel-at-end': isScrollAtEnd.value\n }));\n\n let resizeObserver: ResizeObserver;\n let contentChangedObserver: MutationObserver;\n\n /**\n * Initialises browser platform code:\n * - Creates a mutation observer to detect content changes and reset scroll position.\n * - Stores initial size and scroll position values.\n */\n onMounted(() => {\n resizeObserver = new ResizeObserver(debouncedUpdateScroll);\n resizeObserver.observe(scrollContainerRef.value!);\n contentChangedObserver = new MutationObserver(debouncedRestoreAndUpdateScroll);\n\n watch(\n () => props.resetOnContentChange,\n shouldReset => {\n if (shouldReset) {\n contentChangedObserver.observe(scrollContainerRef.value!, {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false\n });\n } else {\n contentChangedObserver.disconnect();\n }\n },\n { immediate: true }\n );\n\n updateScrollPosition();\n });\n\n onBeforeUnmount(() => {\n contentChangedObserver.disconnect();\n resizeObserver.disconnect();\n });\n\n return {\n cssClasses,\n debouncedUpdateScroll,\n scrollContainerRef,\n scrollLeft,\n scrollRight,\n slots\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-sliding-panel {\n align-items: center;\n display: flex;\n flex-flow: row nowrap;\n position: relative;\n }\n\n .x-sliding-panel__button {\n opacity: 0;\n pointer-events: none;\n position: absolute;\n transition: all ease-out 0.2s;\n z-index: 2; /* To overlay the design system gradient with z-index:1 */\n }\n .x-sliding-panel-button-left {\n left: 0;\n }\n .x-sliding-panel-button-right {\n right: 0;\n }\n\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\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-start) .x-sliding-panel-button-left {\n opacity: 1;\n pointer-events: all;\n }\n\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-end) .x-sliding-panel-button-right {\n opacity: 1;\n pointer-events: all;\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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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","showButtons","_createCommentVNode","_createElementVNode","scrollContainerClass"],"mappings":";;;;;qBACE,IAiCM,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,QAAA,EAAA;AAlCR,EAAA,OAAA,IAAA,CAAA,KAAA,CAAA,OAAA,IAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IACkC,KAAA;AAAA,IAAA;AAAA,MAAsC,GAAA,EAAA,CAAA;AAAA,MAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,iBAAA,EAAA,IAAA,CAAA,UAAA,CAAA,CAAA;AAE5DC,MAAAA,WAAAA,EAAAA,eAAAA;AAAAA,KAAAA;;WAHZ,WAIY,IAAAH,SAAA,EAAA,EAAAC,kBAAA;AAAA,QAAA,QAAA;AAAA,QAAA;AAAA,UACN,GAAK,EAAA,CAAA;AAAA,UAEL,gBAAU,CAA2B,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,UAAA,IAAA,IAAA,CAAA,UAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,8DAAA,EAAA,IAAA,CAAA,WAAA,CAAA,CAAA;UAGrC,WAA+C,EAAA,2BAAA;AAAA,SAAA;;;;AAVrD,WAAA,EAAA,IAAA,CAAA;AAAA,SAYI;AAAA,QAAA,CAAA;AAAA;AAAA,OAWM,IAVJE,mBAAI,MAAoB,EAAA,IAAA,CAAA;AAAA,MAAAC,kBAAA;AACjB,QAAA,KAAA;AAAA,QAAA;AAAA,UACN,GAAA,EAAA,oBAAA;AAAA,UACA,iBAAY,CAAE,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UACd,eAAA,EAjBP,MAiBcC,CAAAA,CAAAA,CAAAA,KAAAA,MAAAA,CAAAA,CAAAA,CAAAA,GAAAA,CAAAA,GAAAA,IAAAA,KACF,IAAyB,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAC/B,gBAAU,MAAsB,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,qBAAA,IAAA,IAAA,CAAA,qBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAJ,cAAA,CAAA,CAAA,IAAA,CAAA,oBAAA,EAAA,yBAAA,CAAA,CAAA;UAGhC,WAAQ,EAAA,sBAAA;AAAA,SAAA;;UAGFC,UAAW,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAA,EAAA,KAAA,CAAA,EAAA,IAAA,CAAA;AAAA,SAAA;;;AADnB,OAAA;AAAA,MAAA,IAAA,CAxBJ,WA0BY,IAAAH,SAAA,EAAA,EAAAC,kBAAA;AAAA,QAAA,QAAA;AAAA,QAAA;AAAA,UACN,GAAK,EAAA,CAAA;AAAA,UAEL,gBAAU,CAA4B,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,WAAA,IAAA,IAAA,CAAA,WAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,+DAAA,EAAA,IAAA,CAAA,WAAA,CAAA,CAAA;UAGtC,WAAgD,EAAA,4BAAA;AAAA,SAAA;;;;AAhCtD,WAAA,EAAA,IAAA,CAAA;AAAA,SAAA;;;AAAA,OAAA,IAAAE,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AAAA,KAAA;;;;;;;;;"}
|
|
@@ -34,8 +34,8 @@ var _sfc_main = defineComponent({
|
|
|
34
34
|
type: Boolean,
|
|
35
35
|
default: true
|
|
36
36
|
},
|
|
37
|
-
buttonClass: String,
|
|
38
|
-
scrollContainerClass: String
|
|
37
|
+
buttonClass: { type: [String, Object, Array] },
|
|
38
|
+
scrollContainerClass: { type: [String, Object, Array] }
|
|
39
39
|
},
|
|
40
40
|
setup(props, { slots }) {
|
|
41
41
|
/** Indicates if the scroll is at the start of the sliding panel. */
|
|
@@ -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=\"x-sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <button\n v-if=\"showButtons\"\n @click=\"scrollLeft\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <div\n ref=\"scrollContainerRef\"\n @scroll=\"debouncedUpdateScroll\"\n @transitionend=\"debouncedUpdateScroll\"\n @animationend=\"debouncedUpdateScroll\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <button\n v-if=\"showButtons\"\n @click=\"scrollRight\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue';\n import { useDebounce } from '../composables/use-debounce';\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 */\n export 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: String,\n scrollContainerClass: String\n },\n setup(props, { slots }) {\n /** Indicates if the scroll is at the start of the sliding panel. */\n const isScrollAtStart = ref(true);\n /** Indicates if the scroll is at the end of the sliding panel. */\n const isScrollAtEnd = ref(true);\n const scrollContainerRef = ref<HTMLDivElement>();\n\n /**\n * Updates the values of the scroll positions to show or hide the buttons depending on it.\n *\n * @remarks The 2px extra is to fix some cases in some resolutions where the scroll + client\n * size is less than the scroll width even when the scroll is at the end.\n */\n function updateScrollPosition() {\n if (scrollContainerRef.value) {\n const { scrollLeft, clientWidth, scrollWidth } = scrollContainerRef.value;\n isScrollAtStart.value = !scrollLeft;\n isScrollAtEnd.value = scrollLeft + clientWidth + 2 >= scrollWidth;\n }\n }\n\n /**\n * Debounced version of the {@link SlidingPanel.updateScrollPosition} method.\n */\n const debouncedUpdateScroll = useDebounce(updateScrollPosition, 50, { leading: true });\n\n /**\n * Resets the scroll and updates the values of the scroll for the buttons to react.\n */\n const debouncedRestoreAndUpdateScroll = useDebounce(\n () => {\n scrollContainerRef.value!.scroll({ left: 0, behavior: 'smooth' });\n updateScrollPosition();\n },\n 50,\n { leading: true }\n );\n\n /**\n * Scrolls the wrapper element towards the provided scroll value.\n *\n * @param scrollValue - The value the scroll will go towards.\n */\n function scrollTo(scrollValue: number) {\n scrollContainerRef.value!.scrollBy({\n left: scrollValue * props.scrollFactor,\n behavior: 'smooth'\n });\n }\n\n /** Scrolls the wrapper element to the left. */\n function scrollLeft() {\n scrollTo(-scrollContainerRef.value!.clientWidth);\n }\n\n /** Scrolls the wrapper element to the right. */\n function scrollRight() {\n scrollTo(scrollContainerRef.value!.clientWidth);\n }\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'x-sliding-panel-at-start': isScrollAtStart.value,\n 'x-sliding-panel-at-end': isScrollAtEnd.value\n }));\n\n let resizeObserver: ResizeObserver;\n let contentChangedObserver: MutationObserver;\n\n /**\n * Initialises browser platform code:\n * - Creates a mutation observer to detect content changes and reset scroll position.\n * - Stores initial size and scroll position values.\n */\n onMounted(() => {\n resizeObserver = new ResizeObserver(debouncedUpdateScroll);\n resizeObserver.observe(scrollContainerRef.value!);\n contentChangedObserver = new MutationObserver(debouncedRestoreAndUpdateScroll);\n\n watch(\n () => props.resetOnContentChange,\n shouldReset => {\n if (shouldReset) {\n contentChangedObserver.observe(scrollContainerRef.value!, {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false\n });\n } else {\n contentChangedObserver.disconnect();\n }\n },\n { immediate: true }\n );\n\n updateScrollPosition();\n });\n\n onBeforeUnmount(() => {\n contentChangedObserver.disconnect();\n resizeObserver.disconnect();\n });\n\n return {\n cssClasses,\n debouncedUpdateScroll,\n scrollContainerRef,\n scrollLeft,\n scrollRight,\n slots\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-sliding-panel {\n align-items: center;\n display: flex;\n flex-flow: row nowrap;\n position: relative;\n }\n\n .x-sliding-panel__button {\n opacity: 0;\n pointer-events: none;\n position: absolute;\n transition: all ease-out 0.2s;\n z-index: 2; /* To overlay the design system gradient with z-index:1 */\n }\n .x-sliding-panel-button-left {\n left: 0;\n }\n .x-sliding-panel-button-right {\n right: 0;\n }\n\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\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-start) .x-sliding-panel-button-left {\n opacity: 1;\n pointer-events: all;\n }\n\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-end) .x-sliding-panel-button-right {\n opacity: 1;\n pointer-events: all;\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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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":";;;AAyCE;;;;;;;;;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,GAAE;AACZ,SAAA;;AAED,QAAA,WAAW,EAAE;AACX,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAG;AACb,SAAA;AACD;;;AAGE;AACF,QAAA,oBAAoB,EAAE;AACpB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,IAAG;AACb,SAAA;AACD,QAAA,WAAW,EAAE,MAAM;AACnB,QAAA,oBAAoB,EAAE,MAAK;AAC5B,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,KAAI,EAAG,EAAA;;AAEpB,QAAA,MAAM,eAAgB,GAAE,GAAG,CAAC,IAAI,CAAC,CAAA;;AAEjC,QAAA,MAAM,aAAc,GAAE,GAAG,CAAC,IAAI,CAAC,CAAA;AAC/B,QAAA,MAAM,qBAAqB,GAAG,EAAkB,CAAA;AAEhD;;;;;AAKE;AACF,QAAA,SAAS,oBAAoB,GAAA;YAC3B,IAAI,kBAAkB,CAAC,KAAK,EAAE;gBAC5B,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAY,EAAA,GAAI,kBAAkB,CAAC,KAAK,CAAA;AACzE,gBAAA,eAAe,CAAC,KAAM,GAAE,CAAC,UAAU,CAAA;gBACnC,aAAa,CAAC,KAAM,GAAE,UAAW,GAAE,WAAY,GAAE,KAAK,WAAW,CAAA;AACnE,aAAA;SACF;AAEA;;AAEE;AACF,QAAA,MAAM,qBAAoB,GAAI,WAAW,CAAC,oBAAoB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAG,EAAG,CAAC,CAAA;AAEtF;;AAEE;AACF,QAAA,MAAM,+BAA8B,GAAI,WAAW,CACjD,MAAM;AACJ,YAAA,kBAAkB,CAAC,KAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAS,EAAC,CAAC,CAAA;AACjE,YAAA,oBAAoB,EAAE,CAAA;SACvB,EACD,EAAE,EACF,EAAE,OAAO,EAAE,IAAK,EAAA,CACjB,CAAA;AAED;;;;AAIE;QACF,SAAS,QAAQ,CAAC,WAAmB,EAAA;AACnC,YAAA,kBAAkB,CAAC,KAAM,CAAC,QAAQ,CAAC;AACjC,gBAAA,IAAI,EAAE,WAAY,GAAE,KAAK,CAAC,YAAY;AACtC,gBAAA,QAAQ,EAAE,QAAO;AAClB,aAAA,CAAC,CAAA;SACJ;;AAGA,QAAA,SAAS,UAAU,GAAA;YACjB,QAAQ,CAAC,CAAC,kBAAkB,CAAC,KAAM,CAAC,WAAW,CAAC,CAAA;SAClD;;AAGA,QAAA,SAAS,WAAW,GAAA;AAClB,YAAA,QAAQ,CAAC,kBAAkB,CAAC,KAAM,CAAC,WAAW,CAAC,CAAA;SACjD;;AAGA,QAAA,MAAM,UAAS,GAAI,QAAQ,CAAC,OAAO;YACjC,0BAA0B,EAAE,eAAe,CAAC,KAAK;YACjD,wBAAwB,EAAE,aAAa,CAAC,KAAI;AAC7C,SAAA,CAAC,CAAC,CAAA;AAEH,QAAA,IAAI,cAA8B,CAAA;AAClC,QAAA,IAAI,sBAAwC,CAAA;AAE5C;;;;AAIE;QACF,SAAS,CAAC,MAAM;AACd,YAAA,iBAAiB,IAAI,cAAc,CAAC,qBAAqB,CAAC,CAAA;AAC1D,YAAA,cAAc,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAM,CAAC,CAAA;AACjD,YAAA,sBAAqB,GAAI,IAAI,gBAAgB,CAAC,+BAA+B,CAAC,CAAA;YAE9E,KAAK,CACH,MAAM,KAAK,CAAC,oBAAoB,EAChC,WAAY,IAAG;AACb,gBAAA,IAAI,WAAW,EAAE;AACf,oBAAA,sBAAsB,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAM,EAAE;AACxD,wBAAA,OAAO,EAAE,IAAI;AACb,wBAAA,SAAS,EAAE,IAAI;AACf,wBAAA,UAAU,EAAE,KAAK;AACjB,wBAAA,aAAa,EAAE,KAAI;AACpB,qBAAA,CAAC,CAAA;AACF,iBAAA;AAAK,qBAAA;oBACL,sBAAsB,CAAC,UAAU,EAAE,CAAA;AACrC,iBAAA;AACF,aAAC,EACD,EAAE,SAAS,EAAE,IAAK,EAAA,CACnB,CAAA;AAED,YAAA,oBAAoB,EAAE,CAAA;AACxB,SAAC,CAAC,CAAA;QAEF,eAAe,CAAC,MAAM;YACpB,sBAAsB,CAAC,UAAU,EAAE,CAAA;YACnC,cAAc,CAAC,UAAU,EAAE,CAAA;AAC7B,SAAC,CAAC,CAAA;QAEF,OAAO;YACL,UAAU;YACV,qBAAqB;YACrB,kBAAkB;YAClB,UAAU;YACV,WAAW;YACX,KAAI;SACL,CAAA;KACH;AACD,CAAA,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"sliding-panel.vue2.js","sources":["../../../src/components/sliding-panel.vue"],"sourcesContent":["<template>\n <div v-if=\"slots.default\" class=\"x-sliding-panel\" :class=\"cssClasses\" data-test=\"sliding-panel\">\n <button\n v-if=\"showButtons\"\n @click=\"scrollLeft\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-left\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-left-button\"\n >\n <!-- @slot Left button content -->\n <slot name=\"sliding-panel-left-button\">ᐸ</slot>\n </button>\n <div\n ref=\"scrollContainerRef\"\n @scroll=\"debouncedUpdateScroll\"\n @transitionend=\"debouncedUpdateScroll\"\n @animationend=\"debouncedUpdateScroll\"\n :class=\"scrollContainerClass\"\n class=\"x-sliding-panel__scroll\"\n data-test=\"sliding-panel-scroll\"\n >\n <!-- @slot (Required) Sliding panel content -->\n <slot />\n </div>\n <button\n v-if=\"showButtons\"\n @click=\"scrollRight\"\n class=\"x-sliding-panel__button x-button x-sliding-panel-button-right\"\n :class=\"buttonClass\"\n data-test=\"sliding-panel-right-button\"\n >\n <!-- @slot Right button content -->\n <slot name=\"sliding-panel-right-button\">ᐳ</slot>\n </button>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, onBeforeUnmount, onMounted, PropType, ref, watch } from 'vue';\n import { useDebounce } from '../composables/use-debounce';\n import { VueCSSClasses } from '../utils/types';\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 */\n export 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 /** Indicates if the scroll is at the start of the sliding panel. */\n const isScrollAtStart = ref(true);\n /** Indicates if the scroll is at the end of the sliding panel. */\n const isScrollAtEnd = ref(true);\n const scrollContainerRef = ref<HTMLDivElement>();\n\n /**\n * Updates the values of the scroll positions to show or hide the buttons depending on it.\n *\n * @remarks The 2px extra is to fix some cases in some resolutions where the scroll + client\n * size is less than the scroll width even when the scroll is at the end.\n */\n function updateScrollPosition() {\n if (scrollContainerRef.value) {\n const { scrollLeft, clientWidth, scrollWidth } = scrollContainerRef.value;\n isScrollAtStart.value = !scrollLeft;\n isScrollAtEnd.value = scrollLeft + clientWidth + 2 >= scrollWidth;\n }\n }\n\n /**\n * Debounced version of the {@link SlidingPanel.updateScrollPosition} method.\n */\n const debouncedUpdateScroll = useDebounce(updateScrollPosition, 50, { leading: true });\n\n /**\n * Resets the scroll and updates the values of the scroll for the buttons to react.\n */\n const debouncedRestoreAndUpdateScroll = useDebounce(\n () => {\n scrollContainerRef.value!.scroll({ left: 0, behavior: 'smooth' });\n updateScrollPosition();\n },\n 50,\n { leading: true }\n );\n\n /**\n * Scrolls the wrapper element towards the provided scroll value.\n *\n * @param scrollValue - The value the scroll will go towards.\n */\n function scrollTo(scrollValue: number) {\n scrollContainerRef.value!.scrollBy({\n left: scrollValue * props.scrollFactor,\n behavior: 'smooth'\n });\n }\n\n /** Scrolls the wrapper element to the left. */\n function scrollLeft() {\n scrollTo(-scrollContainerRef.value!.clientWidth);\n }\n\n /** Scrolls the wrapper element to the right. */\n function scrollRight() {\n scrollTo(scrollContainerRef.value!.clientWidth);\n }\n\n /** CSS classes to apply based on the scroll position. */\n const cssClasses = computed(() => ({\n 'x-sliding-panel-at-start': isScrollAtStart.value,\n 'x-sliding-panel-at-end': isScrollAtEnd.value\n }));\n\n let resizeObserver: ResizeObserver;\n let contentChangedObserver: MutationObserver;\n\n /**\n * Initialises browser platform code:\n * - Creates a mutation observer to detect content changes and reset scroll position.\n * - Stores initial size and scroll position values.\n */\n onMounted(() => {\n resizeObserver = new ResizeObserver(debouncedUpdateScroll);\n resizeObserver.observe(scrollContainerRef.value!);\n contentChangedObserver = new MutationObserver(debouncedRestoreAndUpdateScroll);\n\n watch(\n () => props.resetOnContentChange,\n shouldReset => {\n if (shouldReset) {\n contentChangedObserver.observe(scrollContainerRef.value!, {\n subtree: true,\n childList: true,\n attributes: false,\n characterData: false\n });\n } else {\n contentChangedObserver.disconnect();\n }\n },\n { immediate: true }\n );\n\n updateScrollPosition();\n });\n\n onBeforeUnmount(() => {\n contentChangedObserver.disconnect();\n resizeObserver.disconnect();\n });\n\n return {\n cssClasses,\n debouncedUpdateScroll,\n scrollContainerRef,\n scrollLeft,\n scrollRight,\n slots\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-sliding-panel {\n align-items: center;\n display: flex;\n flex-flow: row nowrap;\n position: relative;\n }\n\n .x-sliding-panel__button {\n opacity: 0;\n pointer-events: none;\n position: absolute;\n transition: all ease-out 0.2s;\n z-index: 2; /* To overlay the design system gradient with z-index:1 */\n }\n .x-sliding-panel-button-left {\n left: 0;\n }\n .x-sliding-panel-button-right {\n right: 0;\n }\n\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\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-start) .x-sliding-panel-button-left {\n opacity: 1;\n pointer-events: all;\n }\n\n /* prettier-ignore */\n .x-sliding-panel:not(.x-sliding-panel-show-buttons-on-hover):not(.x-sliding-panel-at-end) .x-sliding-panel-button-right {\n opacity: 1;\n pointer-events: all;\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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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>\n import { SlidingPanel } from '@empathyco/x-components';\n\n export 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":"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"}
|
|
@@ -13,7 +13,10 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
13
13
|
"reset-on-content-change": false,
|
|
14
14
|
"button-class": _ctx.buttonClass,
|
|
15
15
|
"show-buttons": _ctx.showButtons && _ctx.selectedPromptIndex === -1,
|
|
16
|
-
"scroll-container-class": [
|
|
16
|
+
"scroll-container-class": [
|
|
17
|
+
"x-related-prompts-tag-list-scroll-container",
|
|
18
|
+
_ctx.scrollContainerClass || ""
|
|
19
|
+
]
|
|
17
20
|
}, {
|
|
18
21
|
"sliding-panel-left-button": withCtx(() => [
|
|
19
22
|
renderSlot(_ctx.$slots, "sliding-panel-left-button")
|
|
@@ -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=\"['x-related-prompts-tag-list-scroll-container', scrollContainerClass]\"\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 @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\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=\"isAnimating && { pointerEvents: 'none' }\"\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 :relatedPrompt=\"relatedPrompt\"\n :onSelect=\"() => onSelect(index)\"\n :isSelected=\"isSelected(index)\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.toolingDisplayTagging\"\n :eventMetadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false\n }\"\n >\n <RelatedPrompt\n @click=\"onSelect(index)\"\n :related-prompt=\"relatedPrompt\"\n :selected=\"isSelected(index)\"\n >\n <template #related-prompt-extra-content>\n <slot name=\"related-prompt-extra-content\" :relatedPrompt=\"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\">\n import { RelatedPrompt as RelatedPromptModel } from '@empathyco/x-types';\n import { computed, defineComponent, PropType, ref, watch } from 'vue';\n import SlidingPanel from '../../../components/sliding-panel.vue';\n import { relatedPromptsXModule } from '../x-module';\n import { use$x, useState } from '../../../composables';\n import DisplayEmitter from '../../../components/display-emitter.vue';\n import 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 */\n export 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 'relatedPrompts',\n 'selectedPrompt'\n ]);\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 as RelatedPromptModel[]).map(\n (relatedPrompt: RelatedPromptModel, index: number) => ({\n ...relatedPrompt,\n index\n })\n )\n );\n\n const visibleRelatedPrompts = computed(() => {\n return selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value;\n });\n\n let timeOutId: number;\n const resetTransitionStyle = () => {\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 (property !== 'width') {\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 const isSelected = (index: number): boolean => selectedPromptIndex.value === index;\n\n // Changing the query will trigger the appear animation, so we need to reset the\n // style after it finishes\n watch(() => x.query.search, resetTransitionStyle, { immediate: true });\n\n return {\n isSelected,\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x\n };\n }\n });\n</script>\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 }\n</style>\n"],"names":["_resolveComponent","_openBlock","_createBlock","buttonClass","showButtons","_renderSlot","_withCtx","onBeforeEnter","onEnter","onLeave","_createElementBlock","_Fragment","_renderList","_normalizeClass","isAnimating","_normalizeStyle","onSelect","_createVNode","isSelected"],"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 :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 @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\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=\"isAnimating && { pointerEvents: 'none' }\"\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 :relatedPrompt=\"relatedPrompt\"\n :onSelect=\"() => onSelect(index)\"\n :isSelected=\"isSelected(index)\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.toolingDisplayTagging\"\n :eventMetadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false\n }\"\n >\n <RelatedPrompt\n @click=\"onSelect(index)\"\n :related-prompt=\"relatedPrompt\"\n :selected=\"isSelected(index)\"\n >\n <template #related-prompt-extra-content>\n <slot name=\"related-prompt-extra-content\" :relatedPrompt=\"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\">\n import { RelatedPrompt as RelatedPromptModel } from '@empathyco/x-types';\n import { computed, defineComponent, PropType, ref } from 'vue';\n import SlidingPanel from '../../../components/sliding-panel.vue';\n import { relatedPromptsXModule } from '../x-module';\n import { use$x, useState } from '../../../composables';\n import DisplayEmitter from '../../../components/display-emitter.vue';\n import 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 */\n export 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 'relatedPrompts',\n 'selectedPrompt'\n ]);\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 as RelatedPromptModel[]).map(\n (relatedPrompt: RelatedPromptModel, index: number) => ({\n ...relatedPrompt,\n index\n })\n )\n );\n\n const visibleRelatedPrompts = computed(() => {\n return 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 const isSelected = (index: number): boolean => selectedPromptIndex.value === index;\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 return {\n isSelected,\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x\n };\n }\n });\n</script>\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"],"names":["_resolveComponent","_openBlock","_createBlock","buttonClass","showButtons","scrollContainerClass","_renderSlot","_withCtx","onBeforeEnter","onEnter","onLeave","_createElementBlock","_Fragment","_renderList","_normalizeClass","isAnimating","_normalizeStyle","onSelect","_createVNode","isSelected"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, ref, computed
|
|
1
|
+
import { defineComponent, ref, computed } from 'vue';
|
|
2
2
|
import SlidingPanel from '../../../components/sliding-panel.vue.js';
|
|
3
3
|
import { relatedPromptsXModule } from '../x-module.js';
|
|
4
4
|
import '../../../composables/create-use-device.js';
|
|
@@ -100,7 +100,7 @@ var _sfc_main = defineComponent({
|
|
|
100
100
|
: indexRelatedPrompts.value;
|
|
101
101
|
});
|
|
102
102
|
let timeOutId;
|
|
103
|
-
const resetTransitionStyle = () => {
|
|
103
|
+
const resetTransitionStyle = (excludedProperties = ['width']) => {
|
|
104
104
|
if (timeOutId) {
|
|
105
105
|
clearTimeout(timeOutId);
|
|
106
106
|
}
|
|
@@ -113,7 +113,7 @@ var _sfc_main = defineComponent({
|
|
|
113
113
|
.split(';')
|
|
114
114
|
.map(rule => rule.split(':')[0]?.trim())
|
|
115
115
|
.forEach(property => {
|
|
116
|
-
if (property
|
|
116
|
+
if (!excludedProperties.includes(property)) {
|
|
117
117
|
element.style.removeProperty(property);
|
|
118
118
|
}
|
|
119
119
|
});
|
|
@@ -202,9 +202,11 @@ var _sfc_main = defineComponent({
|
|
|
202
202
|
setTimeout(done, props.animationDurationInMs);
|
|
203
203
|
};
|
|
204
204
|
const isSelected = (index) => selectedPromptIndex.value === index;
|
|
205
|
-
// Changing the
|
|
205
|
+
// Changing the request will trigger the appear animation, so we need to reset the
|
|
206
206
|
// style after it finishes
|
|
207
|
-
|
|
207
|
+
x.on('SearchRequestChanged', false).subscribe(() => {
|
|
208
|
+
resetTransitionStyle([]);
|
|
209
|
+
});
|
|
208
210
|
return {
|
|
209
211
|
isSelected,
|
|
210
212
|
onSelect,
|
|
@@ -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=\"['x-related-prompts-tag-list-scroll-container', scrollContainerClass]\"\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 @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\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=\"isAnimating && { pointerEvents: 'none' }\"\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 :relatedPrompt=\"relatedPrompt\"\n :onSelect=\"() => onSelect(index)\"\n :isSelected=\"isSelected(index)\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.toolingDisplayTagging\"\n :eventMetadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false\n }\"\n >\n <RelatedPrompt\n @click=\"onSelect(index)\"\n :related-prompt=\"relatedPrompt\"\n :selected=\"isSelected(index)\"\n >\n <template #related-prompt-extra-content>\n <slot name=\"related-prompt-extra-content\" :relatedPrompt=\"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\">\n import { RelatedPrompt as RelatedPromptModel } from '@empathyco/x-types';\n import { computed, defineComponent, PropType, ref, watch } from 'vue';\n import SlidingPanel from '../../../components/sliding-panel.vue';\n import { relatedPromptsXModule } from '../x-module';\n import { use$x, useState } from '../../../composables';\n import DisplayEmitter from '../../../components/display-emitter.vue';\n import 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 */\n export 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 'relatedPrompts',\n 'selectedPrompt'\n ]);\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 as RelatedPromptModel[]).map(\n (relatedPrompt: RelatedPromptModel, index: number) => ({\n ...relatedPrompt,\n index\n })\n )\n );\n\n const visibleRelatedPrompts = computed(() => {\n return selectedPromptIndex.value !== -1\n ? [indexRelatedPrompts.value[selectedPromptIndex.value]]\n : indexRelatedPrompts.value;\n });\n\n let timeOutId: number;\n const resetTransitionStyle = () => {\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 (property !== 'width') {\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 const isSelected = (index: number): boolean => selectedPromptIndex.value === index;\n\n // Changing the query will trigger the appear animation, so we need to reset the\n // style after it finishes\n watch(() => x.query.search, resetTransitionStyle, { immediate: true });\n\n return {\n isSelected,\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x\n };\n }\n });\n</script>\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 }\n</style>\n"],"names":["DisplayEmitter"],"mappings":"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"}
|
|
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 @before-enter=\"onBeforeEnter\"\n @enter=\"onEnter\"\n @leave=\"onLeave\"\n class=\"x-related-prompts-tag-list\"\n :css=\"false\"\n tag=\"ul\"\n appear\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=\"isAnimating && { pointerEvents: 'none' }\"\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 :relatedPrompt=\"relatedPrompt\"\n :onSelect=\"() => onSelect(index)\"\n :isSelected=\"isSelected(index)\"\n >\n <DisplayEmitter\n :payload=\"relatedPrompt.toolingDisplayTagging\"\n :eventMetadata=\"{\n feature: 'related-prompts',\n displayOriginalQuery: x.query.searchBox,\n replaceable: false\n }\"\n >\n <RelatedPrompt\n @click=\"onSelect(index)\"\n :related-prompt=\"relatedPrompt\"\n :selected=\"isSelected(index)\"\n >\n <template #related-prompt-extra-content>\n <slot name=\"related-prompt-extra-content\" :relatedPrompt=\"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\">\n import { RelatedPrompt as RelatedPromptModel } from '@empathyco/x-types';\n import { computed, defineComponent, PropType, ref } from 'vue';\n import SlidingPanel from '../../../components/sliding-panel.vue';\n import { relatedPromptsXModule } from '../x-module';\n import { use$x, useState } from '../../../composables';\n import DisplayEmitter from '../../../components/display-emitter.vue';\n import 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 */\n export 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 'relatedPrompts',\n 'selectedPrompt'\n ]);\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 as RelatedPromptModel[]).map(\n (relatedPrompt: RelatedPromptModel, index: number) => ({\n ...relatedPrompt,\n index\n })\n )\n );\n\n const visibleRelatedPrompts = computed(() => {\n return 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 const isSelected = (index: number): boolean => selectedPromptIndex.value === index;\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 return {\n isSelected,\n onSelect,\n onBeforeEnter,\n onEnter,\n onLeave,\n selectedPromptIndex,\n visibleRelatedPrompts,\n listItems,\n isAnimating,\n x\n };\n }\n });\n</script>\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"],"names":["DisplayEmitter"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import injectCss from '../../../../tools/inject-css.js';
|
|
2
2
|
|
|
3
|
-
var css = ".x-related-prompts-tag-list-scroll-container{height:100%;position:relative}.x-related-prompts-tag-list{display:flex;gap:16px;min-width:100%;width:100%}.x-related-prompts-tag-list-item{height:100%}";
|
|
3
|
+
var css = ".x-related-prompts-tag-list-scroll-container{height:100%;position:relative}.x-related-prompts-tag-list{display:flex;gap:16px;min-width:100%;width:100%}.x-related-prompts-tag-list-item{flex-shrink:0;height:100%}";
|
|
4
4
|
injectCss(css);
|
|
5
5
|
|
|
6
6
|
export { css, css as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empathyco/x-components",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.52",
|
|
4
4
|
"description": "Empathy X Components",
|
|
5
5
|
"author": "Empathy Systems Corporation S.L.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
"prepublishOnly": "pnpm run build"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@empathyco/x-adapter": "^8.1.0-alpha.
|
|
73
|
-
"@empathyco/x-adapter-platform": "^1.1.0-alpha.
|
|
72
|
+
"@empathyco/x-adapter": "^8.1.0-alpha.2",
|
|
73
|
+
"@empathyco/x-adapter-platform": "^1.1.0-alpha.14",
|
|
74
74
|
"@empathyco/x-bus": "^1.0.3-alpha.2",
|
|
75
|
-
"@empathyco/x-deep-merge": "^2.0.3-alpha.
|
|
75
|
+
"@empathyco/x-deep-merge": "^2.0.3-alpha.3",
|
|
76
76
|
"@empathyco/x-logger": "^1.2.0-alpha.11",
|
|
77
77
|
"@empathyco/x-storage-service": "^2.0.3-alpha.1",
|
|
78
|
-
"@empathyco/x-types": "^10.1.0-alpha.
|
|
78
|
+
"@empathyco/x-types": "^10.1.0-alpha.11",
|
|
79
79
|
"@empathyco/x-utils": "^1.0.3-alpha.2",
|
|
80
80
|
"@vue/devtools-api": "~6.5.0",
|
|
81
81
|
"@vueuse/core": "~10.7.1",
|
|
@@ -92,16 +92,16 @@
|
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@badeball/cypress-cucumber-preprocessor": "20.0.0",
|
|
94
94
|
"@bahmutov/cypress-esbuild-preprocessor": "2.2.0",
|
|
95
|
-
"@empathyco/x-tailwindcss": "^2.0.0-alpha.
|
|
95
|
+
"@empathyco/x-tailwindcss": "^2.0.0-alpha.4",
|
|
96
96
|
"@microsoft/api-documenter": "7.23.0",
|
|
97
97
|
"@microsoft/api-extractor": "7.39.0",
|
|
98
98
|
"@testing-library/jest-dom": "5.17.0",
|
|
99
99
|
"@types/autoprefixer": "10.2.0",
|
|
100
|
-
"@types/glob": "8.0
|
|
100
|
+
"@types/glob": "8.1.0",
|
|
101
101
|
"@types/jest": "27.5.0",
|
|
102
102
|
"@types/node": "18.19.0",
|
|
103
|
-
"@types/testing-library__jest-dom": "5.14.
|
|
104
|
-
"@vitejs/plugin-vue": "5.1
|
|
103
|
+
"@types/testing-library__jest-dom": "5.14.9",
|
|
104
|
+
"@vitejs/plugin-vue": "5.2.1",
|
|
105
105
|
"@vue/test-utils": "~2.4.6",
|
|
106
106
|
"@vue/vue3-jest": "27.0.0",
|
|
107
107
|
"autoprefixer": "10.4.4",
|
|
@@ -138,5 +138,5 @@
|
|
|
138
138
|
"access": "public",
|
|
139
139
|
"directory": "dist"
|
|
140
140
|
},
|
|
141
|
-
"gitHead": "
|
|
141
|
+
"gitHead": "7fb87a6957a3c93bd169e814d48cc47d46a02889"
|
|
142
142
|
}
|