@empathyco/x-components 6.0.0-alpha.23 → 6.0.0-alpha.25
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 +18 -0
- package/design-system/deprecated-full-theme.css +1943 -1943
- package/docs/API-reference/api/x-components.installxoptions.installextraplugins.md +2 -2
- package/js/components/animations/fade-and-slide.vue.js +1 -2
- package/js/components/animations/fade-and-slide.vue.js.map +1 -1
- package/js/components/base-dropdown.vue.js +1 -3
- package/js/components/base-dropdown.vue.js.map +1 -1
- package/js/components/base-event-button.vue.js +1 -2
- package/js/components/base-event-button.vue.js.map +1 -1
- package/js/components/base-grid.vue.js +11 -18
- package/js/components/base-grid.vue.js.map +1 -1
- package/js/components/base-keyboard-navigation.vue.js +1 -2
- package/js/components/base-keyboard-navigation.vue.js.map +1 -1
- package/js/components/base-rating.vue.js +1 -3
- package/js/components/base-rating.vue.js.map +1 -1
- package/js/components/base-slider.vue.js +1 -2
- package/js/components/base-slider.vue.js.map +1 -1
- package/js/components/base-variable-column-grid.vue.js +1 -2
- package/js/components/base-variable-column-grid.vue.js.map +1 -1
- package/js/components/column-picker/base-column-picker-dropdown.vue.js +1 -3
- package/js/components/column-picker/base-column-picker-dropdown.vue.js.map +1 -1
- package/js/components/column-picker/base-column-picker-list.vue.js +1 -3
- package/js/components/column-picker/base-column-picker-list.vue.js.map +1 -1
- package/js/components/filters/labels/base-rating-filter-label.vue.js +1 -3
- package/js/components/filters/labels/base-rating-filter-label.vue.js.map +1 -1
- package/js/components/items-list.vue.js +1 -2
- package/js/components/items-list.vue.js.map +1 -1
- package/js/components/layouts/fixed-header-and-asides-layout.vue.js +1 -7
- package/js/components/layouts/fixed-header-and-asides-layout.vue.js.map +1 -1
- package/js/components/layouts/multi-column-max-width-layout.vue.js +1 -9
- package/js/components/layouts/multi-column-max-width-layout.vue.js.map +1 -1
- package/js/components/layouts/single-column-layout.vue.js +1 -9
- package/js/components/layouts/single-column-layout.vue.js.map +1 -1
- package/js/components/modals/base-events-modal-close.vue.js +1 -2
- package/js/components/modals/base-events-modal-close.vue.js.map +1 -1
- package/js/components/modals/base-events-modal-open.vue.js +1 -2
- package/js/components/modals/base-events-modal-open.vue.js.map +1 -1
- package/js/components/modals/base-id-modal-close.vue.js +1 -2
- package/js/components/modals/base-id-modal-close.vue.js.map +1 -1
- package/js/components/modals/base-id-modal-open.vue.js +1 -2
- package/js/components/modals/base-id-modal-open.vue.js.map +1 -1
- package/js/components/modals/base-modal.vue.js +1 -2
- package/js/components/modals/base-modal.vue.js.map +1 -1
- package/js/components/page-loader-button.vue.js +1 -4
- package/js/components/page-loader-button.vue.js.map +1 -1
- package/js/components/panels/base-header-toggle-panel.vue.js +1 -5
- package/js/components/panels/base-header-toggle-panel.vue.js.map +1 -1
- package/js/components/panels/base-id-toggle-panel-button.vue.js +1 -2
- package/js/components/panels/base-id-toggle-panel-button.vue.js.map +1 -1
- package/js/components/panels/base-id-toggle-panel.vue.js +1 -2
- package/js/components/panels/base-id-toggle-panel.vue.js.map +1 -1
- package/js/components/panels/base-tabs-panel.vue.js +1 -4
- package/js/components/panels/base-tabs-panel.vue.js.map +1 -1
- package/js/components/panels/base-toggle-panel.vue.js +1 -2
- package/js/components/panels/base-toggle-panel.vue.js.map +1 -1
- package/js/components/result/base-result-add-to-cart.vue.js +1 -2
- package/js/components/result/base-result-add-to-cart.vue.js.map +1 -1
- package/js/components/result/base-result-current-price.vue.js +1 -2
- package/js/components/result/base-result-current-price.vue.js.map +1 -1
- package/js/components/result/base-result-image.vue.js +39 -59
- package/js/components/result/base-result-image.vue.js.map +1 -1
- package/js/components/result/base-result-link.vue.js +1 -2
- package/js/components/result/base-result-link.vue.js.map +1 -1
- package/js/components/result/base-result-previous-price.vue.js +1 -2
- package/js/components/result/base-result-previous-price.vue.js.map +1 -1
- package/js/components/result/base-result-rating.vue.js +1 -4
- package/js/components/result/base-result-rating.vue.js.map +1 -1
- package/js/components/result/result-variant-selector.vue.js +1 -3
- package/js/components/result/result-variant-selector.vue.js.map +1 -1
- package/js/components/sliding-panel.vue.js +1 -4
- package/js/components/sliding-panel.vue.js.map +1 -1
- package/js/components/suggestions/base-suggestion.vue.js +1 -2
- package/js/components/suggestions/base-suggestion.vue.js.map +1 -1
- package/js/components/suggestions/base-suggestions.vue.js +1 -2
- package/js/components/suggestions/base-suggestions.vue.js.map +1 -1
- package/js/x-modules/empathize/components/empathize.vue.js +1 -2
- package/js/x-modules/empathize/components/empathize.vue.js.map +1 -1
- package/js/x-modules/facets/components/facets/facets.vue.js +20 -33
- package/js/x-modules/facets/components/facets/facets.vue.js.map +1 -1
- package/js/x-modules/facets/components/filters/all-filter.vue.js +1 -2
- package/js/x-modules/facets/components/filters/all-filter.vue.js.map +1 -1
- package/js/x-modules/facets/components/filters/editable-number-range-filter.vue.js +1 -6
- package/js/x-modules/facets/components/filters/editable-number-range-filter.vue.js.map +1 -1
- package/js/x-modules/facets/components/filters/hierarchical-filter.vue.js +1 -3
- package/js/x-modules/facets/components/filters/hierarchical-filter.vue.js.map +1 -1
- package/js/x-modules/facets/components/filters/number-range-filter.vue.js +1 -3
- package/js/x-modules/facets/components/filters/number-range-filter.vue.js.map +1 -1
- package/js/x-modules/facets/components/filters/simple-filter.vue.js +1 -3
- package/js/x-modules/facets/components/filters/simple-filter.vue.js.map +1 -1
- package/js/x-modules/facets/components/lists/filters-list.vue.js +1 -2
- package/js/x-modules/facets/components/lists/filters-list.vue.js.map +1 -1
- package/js/x-modules/facets/components/lists/filters-search.vue.js +1 -3
- package/js/x-modules/facets/components/lists/filters-search.vue.js.map +1 -1
- package/js/x-modules/facets/components/lists/selected-filters-list.vue.js +11 -18
- package/js/x-modules/facets/components/lists/selected-filters-list.vue.js.map +1 -1
- package/js/x-modules/facets/components/lists/sliced-filters.vue.js +1 -4
- package/js/x-modules/facets/components/lists/sliced-filters.vue.js.map +1 -1
- package/js/x-modules/history-queries/components/clear-history-queries.vue.js +1 -2
- package/js/x-modules/history-queries/components/clear-history-queries.vue.js.map +1 -1
- package/js/x-modules/history-queries/components/history-queries.vue.js +1 -10
- package/js/x-modules/history-queries/components/history-queries.vue.js.map +1 -1
- package/js/x-modules/history-queries/components/history-query.vue.js +1 -6
- package/js/x-modules/history-queries/components/history-query.vue.js.map +1 -1
- package/js/x-modules/history-queries/components/my-history.vue.js +1 -4
- package/js/x-modules/history-queries/components/my-history.vue.js.map +1 -1
- package/js/x-modules/history-queries/components/remove-history-query.vue.js +1 -2
- package/js/x-modules/history-queries/components/remove-history-query.vue.js.map +1 -1
- package/js/x-modules/identifier-results/components/identifier-results.vue.js +1 -2
- package/js/x-modules/identifier-results/components/identifier-results.vue.js.map +1 -1
- package/js/x-modules/next-queries/components/next-queries.vue.js +1 -7
- package/js/x-modules/next-queries/components/next-queries.vue.js.map +1 -1
- package/js/x-modules/next-queries/components/next-query-preview.vue.js +1 -3
- package/js/x-modules/next-queries/components/next-query-preview.vue.js.map +1 -1
- package/js/x-modules/next-queries/components/next-query.vue.js +1 -4
- package/js/x-modules/next-queries/components/next-query.vue.js.map +1 -1
- package/js/x-modules/popular-searches/components/popular-search.vue.js +1 -4
- package/js/x-modules/popular-searches/components/popular-search.vue.js.map +1 -1
- package/js/x-modules/popular-searches/components/popular-searches.vue.js +1 -7
- package/js/x-modules/popular-searches/components/popular-searches.vue.js.map +1 -1
- package/js/x-modules/queries-preview/components/query-preview-button.vue.js +1 -2
- package/js/x-modules/queries-preview/components/query-preview-button.vue.js.map +1 -1
- package/js/x-modules/queries-preview/components/query-preview.vue.js +1 -2
- package/js/x-modules/queries-preview/components/query-preview.vue.js.map +1 -1
- package/js/x-modules/query-suggestions/components/query-suggestion.vue.js +1 -4
- package/js/x-modules/query-suggestions/components/query-suggestion.vue.js.map +1 -1
- package/js/x-modules/query-suggestions/components/query-suggestions.vue.js +1 -7
- package/js/x-modules/query-suggestions/components/query-suggestions.vue.js.map +1 -1
- package/js/x-modules/recommendations/components/recommendations.vue.js +1 -2
- package/js/x-modules/recommendations/components/recommendations.vue.js.map +1 -1
- package/js/x-modules/related-tags/components/related-tag.vue.js +1 -2
- package/js/x-modules/related-tags/components/related-tag.vue.js.map +1 -1
- package/js/x-modules/related-tags/components/related-tags.vue.js +1 -4
- package/js/x-modules/related-tags/components/related-tags.vue.js.map +1 -1
- package/js/x-modules/scroll/components/scroll-to-top.vue.js +1 -2
- package/js/x-modules/scroll/components/scroll-to-top.vue.js.map +1 -1
- package/js/x-modules/search/components/partial-results-list.vue.js +1 -2
- package/js/x-modules/search/components/partial-results-list.vue.js.map +1 -1
- package/js/x-modules/search/components/sort-dropdown.vue.js +1 -3
- package/js/x-modules/search/components/sort-dropdown.vue.js.map +1 -1
- package/js/x-modules/search-box/components/clear-search-input.vue.js +1 -2
- package/js/x-modules/search-box/components/clear-search-input.vue.js.map +1 -1
- package/js/x-modules/search-box/components/search-button.vue.js +1 -2
- package/js/x-modules/search-box/components/search-button.vue.js.map +1 -1
- package/js/x-modules/semantic-queries/components/semantic-queries.vue.js +1 -3
- package/js/x-modules/semantic-queries/components/semantic-queries.vue.js.map +1 -1
- package/js/x-modules/semantic-queries/components/semantic-query.vue.js +1 -4
- package/js/x-modules/semantic-queries/components/semantic-query.vue.js.map +1 -1
- package/package.json +2 -2
- package/report/x-components.api.json +11 -2
- package/report/x-components.api.md +1 -1
- package/types/x-installer/x-installer/types.d.ts +1 -1
- package/types/x-installer/x-installer/types.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result-variant-selector.vue.js","sources":["../../../../src/components/result/result-variant-selector.vue"],"sourcesContent":["<template>\n <ul v-if=\"result && variants\" class=\"x-result-variant-selector__list\" data-test=\"variants-list\">\n <li\n v-for=\"(variant, index) in variants\"\n :key=\"index\"\n class=\"x-result-variant-selector__item\"\n :class=\"{ 'x-result-variant-selector__item--is-selected': variantIsSelected(variant) }\"\n data-test=\"variant-item\"\n >\n <!--\n @slot Variant item\n @binding {ResultVariant} variant - The variant item\n @binding {boolean} isSelected - Indicates if the variant is selected\n @binding {() => void} selectVariant - Callback to select the variant\n -->\n <slot\n name=\"variant\"\n :variant=\"variant\"\n :isSelected=\"variantIsSelected(variant)\"\n :selectVariant=\"() => selectVariant(variant)\"\n >\n <button @click=\"selectVariant(variant)\" data-test=\"variant-button\" class=\"x-button\">\n <!--\n @slot Variant content\n @binding {ResultVariant} variant - The variant item\n @binding {boolean} isSelected - Indicates if the variant is selected\n -->\n <slot name=\"variant-content\" :variant=\"variant\" :isSelected=\"variantIsSelected(variant)\">\n {{ variant }}\n </slot>\n </button>\n </slot>\n </li>\n </ul>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, inject, Ref } from 'vue';\n import { Result, ResultVariant } from '@empathyco/x-types';\n import {\n RESULT_WITH_VARIANTS_KEY,\n SELECTED_VARIANTS_KEY,\n SELECT_RESULT_VARIANT_KEY\n } from '../decorators/injection.consts';\n\n /**\n * Component to show and select the available variants of a product for a given nest level.\n * TODO: Add logger warning on mount when result is not injected.\n *\n * @public\n */\n export default defineComponent({\n name: 'ResultVariantSelector',\n props: {\n /** The nest level of the variants to be rendered. */\n level: {\n type: Number,\n default: 0\n }\n },\n setup(props, { slots }) {\n /**\n * Callback to be called when a variant is selected.\n *\n * @public\n * @returns The 'selectResultVariant' injection key.\n */\n const selectResultVariant = inject<(variant: ResultVariant, level?: number) => void>(\n SELECT_RESULT_VARIANT_KEY as string\n );\n\n /** The original result, used to retrieve the available variants for the level. */\n const result = inject<Ref<Result>>(RESULT_WITH_VARIANTS_KEY as string);\n\n /** Array containing the selected variants. */\n const selectedVariants = inject<Ref<ResultVariant[]>>(SELECTED_VARIANTS_KEY as string);\n\n /**\n * It retrieves the available variants from the result.\n *\n * @returns - The variants of the result for the current level.\n */\n const variants = computed<ResultVariant[] | undefined>(() => {\n if (props.level === 0) {\n return result!.value?.variants;\n }\n return selectedVariants!.value[props.level - 1]?.variants;\n });\n\n /**\n * Gets the selected variant of the current level.\n *\n * @returns - The selected variant.\n */\n const selectedVariant = computed<ResultVariant | undefined>(() =>\n variants.value?.find(variant => variant === selectedVariants!.value[props.level])\n );\n\n /**\n * Calls the provided method to select a variant.\n *\n * @param variant - Variant to select.\n */\n const selectVariant = (variant: ResultVariant) => {\n selectResultVariant!(variant, props.level);\n };\n\n /**\n * Checks if a variant is selected.\n *\n * @param variant - Variant to check.\n * @returns True if the variant is selected, false if not.\n */\n const variantIsSelected = (variant: ResultVariant) => {\n return selectedVariant.value === variant;\n };\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n * If there are no result or variants, nothing is rendered.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are\n * no result or variants.\n */\n function renderDefaultSlot() {\n const slotProps = {\n variants: variants.value,\n selectedVariant: selectedVariant.value,\n selectVariant\n };\n return result && variants.value ? slots.default?.(slotProps)[0] : '';\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { result, variants, variantIsSelected, selectVariant };\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps;\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-result-variant-selector__list {\n display: flex;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component doesn't emit events.\n\n## See it in action\n\nHere you have a basic example of how the `ResultVariantSelector` component is rendered.\n\nTake into account that this component **must** be a child of a `ResultVariantsProvider` component.\n\nAlso, the component is intended to be used overwriting the content with the slots.\n\nBy default it will render a list of buttons containing the available variants.\n\nThis component only has a required `level` prop, that indicates the level of the variants to be\nrendered.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <h1>Select color</h1>\n <ResultVariantSelector :level=\"0\" #variant=\"{ variant, selectVariant }\" />\n\n <h1>Select size</h1>\n <ResultVariantSelector :level=\"1\" #variant=\"{ variant, selectVariant }\" />\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red',\n variants: [\n {\n name: 'red XL'\n },\n {\n name: 'red L'\n }\n ]\n },\n {\n name: 'blue',\n variants: [\n {\n name: 'blue S'\n },\n {\n name: 'blue M'\n },\n {\n name: 'blue L'\n }\n ]\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with the default slot\n\nIn this example the default slot is used to customize the list.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector :level=\"0\" #default=\"{ variants, selectedVariant, selectVariant }\">\n <div>\n <p v-if=\"selectedVariant\">Selected variant: {{ selectedVariant.name }}</p>\n <ul class=\"x-flex\">\n <li v-for=\"(variant, index) in variants\" :key=\"index\">\n <button @click=\"selectVariant(variant)\">{{ variant.name }}</button>\n </li>\n </ul>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with variant-slot\n\nIn this example the variant-slot is used to customize the variant item.\n\nThe variant will be rendered inside a list.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector :level=\"0\" #variant=\"{ variant, isSelected, selectVariant }\">\n <div>\n <button @click=\"selectVariant\">\n {{ variant.name }}\n <span v-if=\"isSelected\">SELECTED!</span>\n </button>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with variant-content slot\n\nIn this example the variant-content slot is used to customize the content of the default variant\nbutton.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector #variant-content=\"{ variant, isSelected }\">\n <div>\n {{ variant.name }}\n <span v-if=\"isSelected\">SELECTED!</span>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_createCommentVNode","_renderSlot","variantIsSelected","_createElementVNode","_toDisplayString"],"mappings":";;;;;MACgC,UAAM,GAAA;AAAA,EAAkC,GAAA,EAAA,CAAA;AAAA,EAAA,KAAA,EAAA,iCAAA;;;;AAAtE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,MAAA,EAgCK,QAhCL,KAgCK,EAAA,QAAA,EAAA;6BA/BH,QA8BK,IAAAA,SAAA,EAAA,EAAAC,kBAAA,CAAA,IAAA,EAAA,UAAA,EAAA;AAAA,KAAAD,SAAA,CA5BG,IAAK,CAAA,EAAAC,kBAAA;AAAA,MAAAC,QAAA;AAAA,MAAA,IAAA;AAAA,MAAAC,UAAA,CAAA,IAAA,CAAA,QAAA,EAAA,CAAA,OAAA,EAAA,KAAA,KAAA;eACNH,SALX,EAAA,EAAAC,kBAAA;AAAA,UAKY,IAAA;AAAA,UAAA;AAAA,YAEN,GAAA,EAAA,KAAA;AAAA,YAAA,KAAA,EAAAG,cAAA,CAAA,CAAA,iCAAA,EAAA,EAAA,8CAAA,EAAA,IAAA,CAAA,iBAAA,CAAA,OAAA,CAAA,EAAA,CAAA,CAAA;AAEA,YAAA,WAAA,EAAA,cAAA;AAAA,WAAA;AAMA,UAAA;AAAA,YAEmBC,kBAAA,CAAA,+PAAA,CAAA;AAAA,YAAAC,UAAA,CACN,KAAEC,MAAiB,EAAA,SAAA,EAAA;AAAA,cAC7B,OAAA;AAAA,cAYI,UAAA,EAAA,IAAA,CAAA,iBAAA,CAAA,OAAA,CAAA;AAAA,cAVL,aASS,EAAA,MAAA,IAAA,CAAA,aAAA,CAAA,OAAA,CAAA;AAAA,aATA,EAAA,MAAA;AAAA,cAAyCC,kBAAA,CAAA,QAAA,EAAA;AAAA,gBAAiB,SAAM,CAAU,MAAA,KAAA,IAAA,CAAA,aAAA,CAAA,OAAA,CAAA;AAAA,gBAAA,WAAA,EAAA,gBAAA;AACjF,gBAAA,KAAA,EAAA,UAAA;AAAA,eAKA,EAAA;AAAA,gBAA8CH,kBAAA,CAAA,oMAAA,CAAA;AAAA,gBAAAC,UAAA,CAAa,KAAEC,MAAyB,EAAA,iBAAA,EAAA;AAAA,kBAAA,OAAA;AA3BhG,kBAAA,UAAA,EAAA,IAAA,CAAA,iBAAA,CA4Be,OAAO,CAAA;AAAA,iBAAA,EAAA,MAAA;;AA5BtB,oBAAAE,eAAA,CAAA,OAAA,CAAA;AAAA,oBAAA,CAAA;AAAA;AAAA,mBAAA;AAAA,iBAAA,EAAA,IAAA,CAAA;;;;;;;AAAA,OAAA,CAAA;AAAA,MAAA,GAAA;AAAA;AAAA,KAAA;AAAA,GAAA,CAAA,IAAAJ,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"result-variant-selector.vue.js","sources":["../../../../src/components/result/result-variant-selector.vue"],"sourcesContent":["<template>\n <ul v-if=\"result && variants\" class=\"x-result-variant-selector__list\" data-test=\"variants-list\">\n <li\n v-for=\"(variant, index) in variants\"\n :key=\"index\"\n class=\"x-result-variant-selector__item\"\n :class=\"{ 'x-result-variant-selector__item--is-selected': variantIsSelected(variant) }\"\n data-test=\"variant-item\"\n >\n <!--\n @slot Variant item\n @binding {ResultVariant} variant - The variant item\n @binding {boolean} isSelected - Indicates if the variant is selected\n @binding {() => void} selectVariant - Callback to select the variant\n -->\n <slot\n name=\"variant\"\n :variant=\"variant\"\n :isSelected=\"variantIsSelected(variant)\"\n :selectVariant=\"() => selectVariant(variant)\"\n >\n <button @click=\"selectVariant(variant)\" data-test=\"variant-button\" class=\"x-button\">\n <!--\n @slot Variant content\n @binding {ResultVariant} variant - The variant item\n @binding {boolean} isSelected - Indicates if the variant is selected\n -->\n <slot name=\"variant-content\" :variant=\"variant\" :isSelected=\"variantIsSelected(variant)\">\n {{ variant }}\n </slot>\n </button>\n </slot>\n </li>\n </ul>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, inject, Ref } from 'vue';\n import { Result, ResultVariant } from '@empathyco/x-types';\n import {\n RESULT_WITH_VARIANTS_KEY,\n SELECTED_VARIANTS_KEY,\n SELECT_RESULT_VARIANT_KEY\n } from '../decorators/injection.consts';\n\n /**\n * Component to show and select the available variants of a product for a given nest level.\n * TODO: Add logger warning on mount when result is not injected.\n *\n * @public\n */\n export default defineComponent({\n name: 'ResultVariantSelector',\n props: {\n /** The nest level of the variants to be rendered. */\n level: {\n type: Number,\n default: 0\n }\n },\n setup(props, { slots }) {\n /**\n * Callback to be called when a variant is selected.\n *\n * @public\n * @returns The 'selectResultVariant' injection key.\n */\n const selectResultVariant = inject<(variant: ResultVariant, level?: number) => void>(\n SELECT_RESULT_VARIANT_KEY as string\n );\n\n /** The original result, used to retrieve the available variants for the level. */\n const result = inject<Ref<Result>>(RESULT_WITH_VARIANTS_KEY as string);\n\n /** Array containing the selected variants. */\n const selectedVariants = inject<Ref<ResultVariant[]>>(SELECTED_VARIANTS_KEY as string);\n\n /**\n * It retrieves the available variants from the result.\n *\n * @returns - The variants of the result for the current level.\n */\n const variants = computed<ResultVariant[] | undefined>(() => {\n if (props.level === 0) {\n return result!.value?.variants;\n }\n return selectedVariants!.value[props.level - 1]?.variants;\n });\n\n /**\n * Gets the selected variant of the current level.\n *\n * @returns - The selected variant.\n */\n const selectedVariant = computed<ResultVariant | undefined>(() =>\n variants.value?.find(variant => variant === selectedVariants!.value[props.level])\n );\n\n /**\n * Calls the provided method to select a variant.\n *\n * @param variant - Variant to select.\n */\n const selectVariant = (variant: ResultVariant) => {\n selectResultVariant!(variant, props.level);\n };\n\n /**\n * Checks if a variant is selected.\n *\n * @param variant - Variant to check.\n * @returns True if the variant is selected, false if not.\n */\n const variantIsSelected = (variant: ResultVariant) => {\n return selectedVariant.value === variant;\n };\n\n /**\n * Render function to execute the `default` slot, binding `slotsProps` and getting only the\n * first `vNode` to avoid Fragments and Text root nodes.\n * If there are no result or variants, nothing is rendered.\n *\n * @remarks `slotProps` must be values without Vue reactivity and located inside the\n * render-function to update the binding data properly.\n *\n * @returns The root `vNode` of the `default` slot or empty string if there are\n * no result or variants.\n */\n function renderDefaultSlot() {\n const slotProps = {\n variants: variants.value,\n selectedVariant: selectedVariant.value,\n selectVariant\n };\n return result && variants.value ? slots.default?.(slotProps)[0] : '';\n }\n\n /* Hack to render through a render-function, the `default` slot or, in its absence,\n the component itself. It is the alternative for the NoElement antipattern. */\n const componentProps = { result, variants, variantIsSelected, selectVariant };\n return (slots.default ? renderDefaultSlot : componentProps) as typeof componentProps;\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-result-variant-selector__list {\n display: flex;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component doesn't emit events.\n\n## See it in action\n\nHere you have a basic example of how the `ResultVariantSelector` component is rendered.\n\nTake into account that this component **must** be a child of a `ResultVariantsProvider` component.\n\nAlso, the component is intended to be used overwriting the content with the slots.\n\nBy default it will render a list of buttons containing the available variants.\n\nThis component only has a required `level` prop, that indicates the level of the variants to be\nrendered.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <h1>Select color</h1>\n <ResultVariantSelector :level=\"0\" #variant=\"{ variant, selectVariant }\" />\n\n <h1>Select size</h1>\n <ResultVariantSelector :level=\"1\" #variant=\"{ variant, selectVariant }\" />\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red',\n variants: [\n {\n name: 'red XL'\n },\n {\n name: 'red L'\n }\n ]\n },\n {\n name: 'blue',\n variants: [\n {\n name: 'blue S'\n },\n {\n name: 'blue M'\n },\n {\n name: 'blue L'\n }\n ]\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with the default slot\n\nIn this example the default slot is used to customize the list.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector :level=\"0\" #default=\"{ variants, selectedVariant, selectVariant }\">\n <div>\n <p v-if=\"selectedVariant\">Selected variant: {{ selectedVariant.name }}</p>\n <ul class=\"x-flex\">\n <li v-for=\"(variant, index) in variants\" :key=\"index\">\n <button @click=\"selectVariant(variant)\">{{ variant.name }}</button>\n </li>\n </ul>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with variant-slot\n\nIn this example the variant-slot is used to customize the variant item.\n\nThe variant will be rendered inside a list.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector :level=\"0\" #variant=\"{ variant, isSelected, selectVariant }\">\n <div>\n <button @click=\"selectVariant\">\n {{ variant.name }}\n <span v-if=\"isSelected\">SELECTED!</span>\n </button>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n\n### Play with variant-content slot\n\nIn this example the variant-content slot is used to customize the content of the default variant\nbutton.\n\n```vue\n<template>\n <ResultVariantsProvider :result=\"result\" #default=\"{ result }\">\n <p>Result name: {{ result.name }}</p>\n\n <ResultVariantSelector #variant-content=\"{ variant, isSelected }\">\n <div>\n {{ variant.name }}\n <span v-if=\"isSelected\">SELECTED!</span>\n </div>\n </ResultVariantSelector>\n </ResultVariantsProvider>\n</template>\n\n<script>\n import { ResultVariantsProvider, ResultVariantSelector } from '@empathyco/x-components';\n\n export default {\n name: 'ResultVariantSelectorDemo',\n components: {\n ResultVariantsProvider,\n ResultVariantSelector\n },\n data() {\n return {\n result: {\n id: 'jacket',\n modelName: 'Result',\n type: 'Product',\n isWishlisted: false,\n identifier: { value: 'jacket' },\n images: [],\n name: 'jacket',\n price: { hasDiscount: false, originalValue: 10, value: 10 },\n url: '/products/jacket',\n variants: [\n {\n name: 'red'\n },\n {\n name: 'blue'\n }\n ]\n }\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_renderSlot","variantIsSelected","_createElementVNode","_toDisplayString","_createCommentVNode"],"mappings":";;;;;MACgC,UAAM,GAAA;AAAA,EAAkC,GAAA,EAAA,CAAA;AAAA,EAAA,KAAA,EAAA,iCAAA;;;;AAAtE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,MAAA,EAgCK,QAhCL,KAgCK,EAAA,QAAA,EAAA;6BA/BH,QA8BK,IAAAA,SAAA,EAAA,EAAAC,kBAAA,CAAA,IAAA,EAAA,UAAA,EAAA;AAAA,KAAAD,SAAA,CA5BG,IAAK,CAAA,EAAAC,kBAAA;AAAA,MAAAC,QAAA;AAAA,MAAA,IAAA;AAAA,MAAAC,UAAA,CAAA,IAAA,CAAA,QAAA,EAAA,CAAA,OAAA,EAAA,KAAA,KAAA;eACNH,SALX,EAAA,EAAAC,kBAAA;AAAA,UAKY,IAAA;AAAA,UAAA;AAAA,YAEN,GAAA,EAAA,KAAA;AAAA,YAAA,KAAA,EAAAG,cAAA,CAAA,CAAA,iCAAA,EAAA,EAAA,8CAAA,EAAA,IAAA,CAAA,iBAAA,CAAA,OAAA,CAAA,EAAA,CAAA,CAAA;YAQA,WAgBO,EAAA,cAAA;AAAA,WAAA;;AAbM,YAAAC,UAAA,CAAA,IAAA,CAAEC,MAAiB,EAAA,SAAA,EAAA;AAAA,cAC7B,OAAA;AAAA,cAYI,UAAA,EAAA,IAAA,CAAA,iBAAA,CAAA,OAAA,CAAA;AAAA,cAVL,aASS,EAAA,MAAA,IAAA,CAAA,aAAA,CAAA,OAAA,CAAA;AAAA,aATA,EAAA,MAAA;AAAA,cAAyCC,kBAAA,CAAA,QAAA,EAAA;AAAA,gBAAiB,SAAM,CAAU,MAAA,KAAA,IAAA,CAAA,aAAA,CAAA,OAAA,CAAA;AAAA,gBAAA,WAAA,EAAA,gBAAA;AAMjF,gBAAA,KAAA,EAAA,UAAA;AAAA,eAAA,EAAA;AAA2D,gBAAAF,UAAA,CAAA,IAAA,CAAEC,MAAyB,EAAA,iBAAA,EAAA;AAAA,kBAAA,OAAA;AA3BhG,kBAAA,UAAA,EAAA,IAAA,CAAA,iBAAA,CA4Be,OAAO,CAAA;AAAA,iBAAA,EAAA,MAAA;;AA5BtB,oBAAAE,eAAA,CAAA,OAAA,CAAA;AAAA,oBAAA,CAAA;AAAA;AAAA,mBAAA;AAAA,iBAAA,EAAA,IAAA,CAAA;;;;;;;AAAA,OAAA,CAAA;AAAA,MAAA,GAAA;AAAA;AAAA,KAAA;AAAA,GAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './sliding-panel.vue2.js';
|
|
2
|
-
import { openBlock, createElementBlock, normalizeClass,
|
|
2
|
+
import { openBlock, createElementBlock, normalizeClass, renderSlot, createTextVNode, createCommentVNode, createElementVNode } from 'vue';
|
|
3
3
|
import './sliding-panel.vue3.js';
|
|
4
4
|
import _export_sfc from '../_virtual/_plugin-vue_export-helper.js';
|
|
5
5
|
|
|
@@ -21,7 +21,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
21
21
|
"data-test": "sliding-panel-left-button"
|
|
22
22
|
},
|
|
23
23
|
[
|
|
24
|
-
createCommentVNode(" @slot Left button content "),
|
|
25
24
|
renderSlot(_ctx.$slots, "sliding-panel-left-button", {}, () => [
|
|
26
25
|
createTextVNode("\u1438")
|
|
27
26
|
], true)
|
|
@@ -40,7 +39,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
40
39
|
"data-test": "sliding-panel-scroll"
|
|
41
40
|
},
|
|
42
41
|
[
|
|
43
|
-
createCommentVNode(" @slot (Required) Sliding panel content "),
|
|
44
42
|
renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
45
43
|
],
|
|
46
44
|
34
|
|
@@ -55,7 +53,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
55
53
|
"data-test": "sliding-panel-right-button"
|
|
56
54
|
},
|
|
57
55
|
[
|
|
58
|
-
createCommentVNode(" @slot Right button content "),
|
|
59
56
|
renderSlot(_ctx.$slots, "sliding-panel-right-button", {}, () => [
|
|
60
57
|
createTextVNode("\u1433")
|
|
61
58
|
], true)
|
|
@@ -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","_renderSlot","_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;AAErC,UAAA,WAAA,EAAA,2BAAA;AAAA,SAAA;AACA,QAAA;AAAA,UAAAE,kBAAA,CAAuC,6BAAC,CAAA;AAAA,UAAAC,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,2BAAA,EAAA,EAAA,EAAA,MAAA;;AAV9C,WAAA,EAAA,IAAA,CAAA;AAAA,SAYI;AAAA,QAAA,CAAA;AAAA;AAAA,OAWM,IAVJD,mBAAI,MAAoB,EAAA,IAAA,CAAA;AAAA,MAAAE,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,EAAAL,cAAA,CAAA,CAAA,IAAA,CAAA,oBAAA,EAAA,yBAAA,CAAA,CAAA;AAEhC,UAAA,WAAA,EAAA,sBAAA;AAAA,SAAA;AACA,QAAA;AAAA,UAAAE,kBAAA,CAAA,0CAAA,CAAA;UAGMD,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;AAEtC,UAAA,WAAA,EAAA,4BAAA;AAAA,SAAA;AACA,QAAA;AAAA,UAAAE,kBAAA,CAAwC,8BAAC,CAAA;AAAA,UAAAC,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,4BAAA,EAAA,EAAA,EAAA,MAAA;;AAhC/C,WAAA,EAAA,IAAA,CAAA;AAAA,SAAA;;;AAAA,OAAA,IAAAD,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, 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,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './base-suggestion.vue2.js';
|
|
2
|
-
import { resolveComponent, openBlock, createElementBlock, normalizeClass,
|
|
2
|
+
import { resolveComponent, openBlock, createElementBlock, normalizeClass, renderSlot, normalizeProps, guardReactiveProps, createVNode, toDisplayString, createCommentVNode } from 'vue';
|
|
3
3
|
import _export_sfc from '../../_virtual/_plugin-vue_export-helper.js';
|
|
4
4
|
|
|
5
5
|
const _hoisted_1 = {
|
|
@@ -16,7 +16,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
16
16
|
class: normalizeClass(_ctx.dynamicCSSClasses)
|
|
17
17
|
},
|
|
18
18
|
[
|
|
19
|
-
createCommentVNode("\n @slot Button content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {String} query - The query that the suggestion belongs to\n @binding {Filter} filter - Suggestion's filter\n "),
|
|
20
19
|
renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps({ query: _ctx.query, suggestion: _ctx.suggestion, filter: _ctx.filter })), () => [
|
|
21
20
|
createVNode(_component_Highlight, {
|
|
22
21
|
class: "x-suggestion__query",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-suggestion.vue.js","sources":["../../../../src/components/suggestions/base-suggestion.vue"],"sourcesContent":["<template>\n <button ref=\"el\" @click=\"emitEvents\" :class=\"dynamicCSSClasses\">\n <!--\n @slot Button content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {String} query - The query that the suggestion belongs to\n @binding {Filter} filter - Suggestion's filter\n -->\n <slot v-bind=\"{ query, suggestion, filter }\">\n <Highlight class=\"x-suggestion__query\" :text=\"suggestion.query\" :highlight=\"query\" />\n <span v-if=\"filter\" class=\"x-suggestion__filter\">{{ filter.label }}</span>\n </slot>\n </button>\n</template>\n\n<script lang=\"ts\">\n import { BooleanFilter, Suggestion } from '@empathyco/x-types';\n import { forEach } from '@empathyco/x-utils';\n import { computed, defineComponent, PropType, ref } from 'vue';\n import { QueryFeature } from '../../types';\n import { VueCSSClasses } from '../../utils/types';\n import { XEventsTypes } from '../../wiring/events.types';\n import Highlight from '../highlight.vue';\n import { use$x } from '../../composables/index';\n\n /**\n * Renders a button with a default slot. It receives a query, which should be the query of the\n * module using this component, a suggestion, the {@link XEvent} that will be emitted\n * on click with a given feature.\n *\n * The default slot receives the suggestion and the matched query has props.\n *\n * @public\n */\n export default defineComponent({\n components: { Highlight },\n props: {\n /**\n * The normalized query of the module using this component.\n *\n * @public\n */\n query: {\n type: String,\n default: ''\n },\n\n /**\n * The suggestion to render and use in the default slot.\n *\n * @public\n */\n suggestion: {\n type: Object as PropType<Suggestion>,\n required: true\n },\n\n /**\n * The feature from which the events will be emitted.\n *\n * @public\n */\n //TODO: set to true when the suggestions components pass it.\n feature: {\n type: String as PropType<QueryFeature>\n },\n\n /**\n * The {@link XEvent} that will be emitted when selecting a suggestion.\n *\n * @public\n */\n suggestionSelectedEvents: {\n type: Object as PropType<Partial<XEventsTypes>>,\n required: true\n },\n\n /**\n * Indicates if the curated suggestion should be highlighted.\n *\n * @public\n */\n highlightCurated: {\n type: Boolean\n }\n },\n\n setup(props) {\n const el = ref<HTMLElement | null>(null);\n\n const $x = use$x();\n\n /**\n * Returns the suggestion filter object.\n * It is a BooleanFilter because the label is needed.\n * It returns only the first element because the facets and filters are being planned\n * in the BaseSuggestions component.\n *\n * @returns The filter.\n * @public\n */\n const filter = computed<BooleanFilter | undefined>(\n () => props.suggestion.facets?.[0]?.filters[0] as BooleanFilter\n );\n\n /**\n * The event handler that will be triggered when clicking on a suggestion.\n *\n * @remarks\n * UserAcceptedAQuery: suggestion.query\n * UserSelectedASuggestion: suggestion\n * UserClickedAFilter: suggestion.facets[0].filters[0]\n * Merges the events defined in the suggestionSelectedEvents prop and also emits them\n *\n * @returns The {@link XEvent} to emit.\n * @public\n */\n const events = computed<Partial<XEventsTypes>>(() => {\n const filterEvent: Partial<XEventsTypes> = filter.value\n ? { UserClickedAFilter: filter.value }\n : {};\n return {\n UserAcceptedAQuery: props.suggestion.query,\n UserSelectedASuggestion: props.suggestion,\n ...props.suggestionSelectedEvents,\n ...filterEvent\n };\n });\n\n /**\n * Emits the events when the button is clicked.\n *\n * @public\n */\n const emitEvents = (): void => {\n forEach(events.value, (event, payload): void => {\n $x.emit(event, payload, {\n target: el.value!,\n feature: props.feature\n });\n });\n };\n\n /**\n * Checks if the suggestion is curated and if it should be highlighted.\n *\n * @returns True if the suggestion is curated and should be highlighted.\n *\n * @internal\n */\n const shouldHighlightCurated = computed<boolean>(\n () => props.highlightCurated && !!props.suggestion.isCurated\n );\n\n /**\n * Generates css classes dynamically.\n *\n * @remarks\n * 'x-suggestion--matching added when the query should be matched.\n *\n * @returns The {@link VueCSSClasses} classes.\n * @public\n */\n const dynamicCSSClasses = computed<VueCSSClasses>(() => ({\n 'x-suggestion--is-curated': shouldHighlightCurated.value\n }));\n\n return {\n el,\n filter,\n emitEvents,\n dynamicCSSClasses\n };\n }\n });\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserAcceptedAQuery`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button. The event payload is the suggestion query\n data.\n- [`UserSelectedASuggestion`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button. The event payload is the suggestion data.\n- [`UserClickedAFilter`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button if the suggestion includes a filter. The\n event payload is the suggestion filter.\n- The component can emit more events on click using the `suggestionSelectedEvents` prop.\n\n## See it in action\n\nThis suggestion component expects a suggestion to render and pass to its default slot, a normalized\nquery to compare with the suggestion's query and highlight its matching parts, and events to emit\nwhen the suggestion is selected.\n\nIf the suggestion contains a filter, it is displayed next to the suggestion.\n\n```vue live\n<template>\n <BaseSuggestion v-bind=\"{ query, suggestion }\" />\n</template>\n<script>\n import { BaseSuggestion } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionDemo',\n components: {\n BaseSuggestion\n },\n data() {\n return {\n query: 'st',\n suggestion: {\n modelName: 'QuerySuggestion',\n query: 'steak',\n facet: {\n namedModel: 'SimpleFacet',\n id: 'category',\n label: 'Category',\n filters: [\n {\n id: 'category:groceries',\n modelName: 'SimpleFilter',\n facetId: 'category-facet',\n label: 'Groceries',\n selected: false,\n totalResults: 10\n }\n ]\n }\n }\n };\n }\n };\n</script>\n```\n\n### Customise the content\n\nYou can make this component render any content you want by using the `default` slot.\n\n```vue live\n<template>\n <BaseSuggestion v-bind=\"{ query, suggestion }\" #default=\"{ suggestion, query, filter }\">\n <span>🔍</span>\n <Highlight :text=\"suggestion.query\" :highlight=\"query\" />\n <span v-if=\"filter\">{{ filter.label }}</span>\n </BaseSuggestion>\n</template>\n<script>\n import { BaseSuggestion } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionDemo',\n components: {\n BaseSuggestion\n },\n data() {\n return {\n query: 'st',\n suggestion: {\n modelName: 'QuerySuggestion',\n query: 'steak'\n }\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_normalizeClass","
|
|
1
|
+
{"version":3,"file":"base-suggestion.vue.js","sources":["../../../../src/components/suggestions/base-suggestion.vue"],"sourcesContent":["<template>\n <button ref=\"el\" @click=\"emitEvents\" :class=\"dynamicCSSClasses\">\n <!--\n @slot Button content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {String} query - The query that the suggestion belongs to\n @binding {Filter} filter - Suggestion's filter\n -->\n <slot v-bind=\"{ query, suggestion, filter }\">\n <Highlight class=\"x-suggestion__query\" :text=\"suggestion.query\" :highlight=\"query\" />\n <span v-if=\"filter\" class=\"x-suggestion__filter\">{{ filter.label }}</span>\n </slot>\n </button>\n</template>\n\n<script lang=\"ts\">\n import { BooleanFilter, Suggestion } from '@empathyco/x-types';\n import { forEach } from '@empathyco/x-utils';\n import { computed, defineComponent, PropType, ref } from 'vue';\n import { QueryFeature } from '../../types';\n import { VueCSSClasses } from '../../utils/types';\n import { XEventsTypes } from '../../wiring/events.types';\n import Highlight from '../highlight.vue';\n import { use$x } from '../../composables/index';\n\n /**\n * Renders a button with a default slot. It receives a query, which should be the query of the\n * module using this component, a suggestion, the {@link XEvent} that will be emitted\n * on click with a given feature.\n *\n * The default slot receives the suggestion and the matched query has props.\n *\n * @public\n */\n export default defineComponent({\n components: { Highlight },\n props: {\n /**\n * The normalized query of the module using this component.\n *\n * @public\n */\n query: {\n type: String,\n default: ''\n },\n\n /**\n * The suggestion to render and use in the default slot.\n *\n * @public\n */\n suggestion: {\n type: Object as PropType<Suggestion>,\n required: true\n },\n\n /**\n * The feature from which the events will be emitted.\n *\n * @public\n */\n //TODO: set to true when the suggestions components pass it.\n feature: {\n type: String as PropType<QueryFeature>\n },\n\n /**\n * The {@link XEvent} that will be emitted when selecting a suggestion.\n *\n * @public\n */\n suggestionSelectedEvents: {\n type: Object as PropType<Partial<XEventsTypes>>,\n required: true\n },\n\n /**\n * Indicates if the curated suggestion should be highlighted.\n *\n * @public\n */\n highlightCurated: {\n type: Boolean\n }\n },\n\n setup(props) {\n const el = ref<HTMLElement | null>(null);\n\n const $x = use$x();\n\n /**\n * Returns the suggestion filter object.\n * It is a BooleanFilter because the label is needed.\n * It returns only the first element because the facets and filters are being planned\n * in the BaseSuggestions component.\n *\n * @returns The filter.\n * @public\n */\n const filter = computed<BooleanFilter | undefined>(\n () => props.suggestion.facets?.[0]?.filters[0] as BooleanFilter\n );\n\n /**\n * The event handler that will be triggered when clicking on a suggestion.\n *\n * @remarks\n * UserAcceptedAQuery: suggestion.query\n * UserSelectedASuggestion: suggestion\n * UserClickedAFilter: suggestion.facets[0].filters[0]\n * Merges the events defined in the suggestionSelectedEvents prop and also emits them\n *\n * @returns The {@link XEvent} to emit.\n * @public\n */\n const events = computed<Partial<XEventsTypes>>(() => {\n const filterEvent: Partial<XEventsTypes> = filter.value\n ? { UserClickedAFilter: filter.value }\n : {};\n return {\n UserAcceptedAQuery: props.suggestion.query,\n UserSelectedASuggestion: props.suggestion,\n ...props.suggestionSelectedEvents,\n ...filterEvent\n };\n });\n\n /**\n * Emits the events when the button is clicked.\n *\n * @public\n */\n const emitEvents = (): void => {\n forEach(events.value, (event, payload): void => {\n $x.emit(event, payload, {\n target: el.value!,\n feature: props.feature\n });\n });\n };\n\n /**\n * Checks if the suggestion is curated and if it should be highlighted.\n *\n * @returns True if the suggestion is curated and should be highlighted.\n *\n * @internal\n */\n const shouldHighlightCurated = computed<boolean>(\n () => props.highlightCurated && !!props.suggestion.isCurated\n );\n\n /**\n * Generates css classes dynamically.\n *\n * @remarks\n * 'x-suggestion--matching added when the query should be matched.\n *\n * @returns The {@link VueCSSClasses} classes.\n * @public\n */\n const dynamicCSSClasses = computed<VueCSSClasses>(() => ({\n 'x-suggestion--is-curated': shouldHighlightCurated.value\n }));\n\n return {\n el,\n filter,\n emitEvents,\n dynamicCSSClasses\n };\n }\n });\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserAcceptedAQuery`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button. The event payload is the suggestion query\n data.\n- [`UserSelectedASuggestion`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button. The event payload is the suggestion data.\n- [`UserClickedAFilter`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks the button if the suggestion includes a filter. The\n event payload is the suggestion filter.\n- The component can emit more events on click using the `suggestionSelectedEvents` prop.\n\n## See it in action\n\nThis suggestion component expects a suggestion to render and pass to its default slot, a normalized\nquery to compare with the suggestion's query and highlight its matching parts, and events to emit\nwhen the suggestion is selected.\n\nIf the suggestion contains a filter, it is displayed next to the suggestion.\n\n```vue live\n<template>\n <BaseSuggestion v-bind=\"{ query, suggestion }\" />\n</template>\n<script>\n import { BaseSuggestion } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionDemo',\n components: {\n BaseSuggestion\n },\n data() {\n return {\n query: 'st',\n suggestion: {\n modelName: 'QuerySuggestion',\n query: 'steak',\n facet: {\n namedModel: 'SimpleFacet',\n id: 'category',\n label: 'Category',\n filters: [\n {\n id: 'category:groceries',\n modelName: 'SimpleFilter',\n facetId: 'category-facet',\n label: 'Groceries',\n selected: false,\n totalResults: 10\n }\n ]\n }\n }\n };\n }\n };\n</script>\n```\n\n### Customise the content\n\nYou can make this component render any content you want by using the `default` slot.\n\n```vue live\n<template>\n <BaseSuggestion v-bind=\"{ query, suggestion }\" #default=\"{ suggestion, query, filter }\">\n <span>🔍</span>\n <Highlight :text=\"suggestion.query\" :highlight=\"query\" />\n <span v-if=\"filter\">{{ filter.label }}</span>\n </BaseSuggestion>\n</template>\n<script>\n import { BaseSuggestion } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionDemo',\n components: {\n BaseSuggestion\n },\n data() {\n return {\n query: 'st',\n suggestion: {\n modelName: 'QuerySuggestion',\n query: 'steak'\n }\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_normalizeClass","_normalizeProps","_guardReactiveProps","_createVNode","suggestion","filter"],"mappings":";;;;MAU0B,UAAM,GAAA;AAAA,EAAA,GAAA,EAAA,CAAA;;;;+BAT9BA,gBAWS,CAAA,WAAA,CAAA,CAAA;SAXSC,SAAK,EAAA,EAAAC,kBAAA;AAAA,IAAA,QAAA;AAAA,IAAE;AAAA,MAAa,GAAK,EAAA,IAAA;AAAA,MAAA,OAAA,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,UAAA,IAAA,IAAA,CAAA,UAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAOzC,MAAA,KAAA,EAAAC,cAAA,CAGO,IAXX,CAAA,iBAAA,CAAA;AAAA,KAAA;;iBASuB,IAAqB,CAAA,MAAA,EAAA,SAAA,EAAAC,cAAA,CAAAC,kBAAA,CAAA,EAAA,KAAA,EAAA,IAAA,CAAA,KAAA,EAAA,UAAA,EAAA,IAAA,CAAA,UAAA,EAAA,MAAA,EAAA,IAAA,CAAA,MAAA,EAAA,CAAA,CAAA,EAAA,MAAA;AAAA,QAAAC,WAAA,CAAQC,oBAAgB,EAAA;AAAA,UAAG,KAAA,EAAA,qBAAA;AAAA,UAAA,IAAA,EAAA,IAAA,CAAA,UAAA,CAAA,KAAA;UACrDC,SAAM,EAAA,IAAA,CAAA,KAAA;AAAA,SAAA,EAAA,IAAA,EAAA,CAAA,EAAlB,CAA0E,MAAA,EAAA,WAAA,CAAA,CAAA;AAAA,QAVhF,IAAA,CAAA,MAAA,IAAAP,SAAA,EAAA,EAAAC,kBAAA;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './base-suggestions.vue2.js';
|
|
2
|
-
import { openBlock, createBlock, resolveDynamicComponent, withCtx, createElementBlock, Fragment, renderList, normalizeClass,
|
|
2
|
+
import { openBlock, createBlock, resolveDynamicComponent, withCtx, createElementBlock, Fragment, renderList, normalizeClass, renderSlot, mergeProps, createCommentVNode } from 'vue';
|
|
3
3
|
import './base-suggestions.vue3.js';
|
|
4
4
|
import _export_sfc from '../../_virtual/_plugin-vue_export-helper.js';
|
|
5
5
|
|
|
@@ -22,7 +22,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
22
22
|
"data-test": "suggestion-item"
|
|
23
23
|
},
|
|
24
24
|
[
|
|
25
|
-
createCommentVNode("\n @slot (Required) List item content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {number} index - Suggestion index\n @binding {Filter | undefined} filter - Suggestion's filter\n "),
|
|
26
25
|
renderSlot(_ctx.$slots, "default", mergeProps({ ref_for: true }, { suggestion, index, filter: _ctx.getSuggestionFilter(suggestion) }), void 0, true)
|
|
27
26
|
],
|
|
28
27
|
2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-suggestions.vue.js","sources":["../../../../src/components/suggestions/base-suggestions.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" v-if=\"suggestions.length\" tag=\"ul\" class=\"x-suggestions\">\n <li\n v-for=\"(suggestion, index) in suggestionsToRender\"\n :key=\"suggestionsKeys[index]\"\n class=\"x-suggestions__item\"\n :class=\"suggestionItemClass\"\n data-test=\"suggestion-item\"\n >\n <!--\n @slot (Required) List item content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {number} index - Suggestion index\n @binding {Filter | undefined} filter - Suggestion's filter\n -->\n <slot v-bind=\"{ suggestion, index, filter: getSuggestionFilter(suggestion) }\" />\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, PropType } from 'vue';\n import { Suggestion, Facet } from '@empathyco/x-types';\n import { isArrayEmpty } from '../../utils/array';\n import { AnimationProp } from '../../types';\n\n /**\n * Paints a list of suggestions passed in by prop. Requires a component for a single suggestion\n * in the default slot for working.\n *\n * @public\n */\n export default defineComponent({\n name: 'BaseSuggestions',\n props: {\n /**\n * The list of suggestions to render.\n *\n * @public\n */\n suggestions: {\n type: Array as PropType<Suggestion[]>,\n required: true\n },\n /**\n * Animation component that will be used to animate the suggestion.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul'\n },\n /**\n * Number of suggestions to be rendered.\n *\n * @public\n */\n maxItemsToRender: Number,\n /**\n * Boolean value to indicate if the facets should be rendered.\n *\n * @public\n */\n showFacets: {\n type: Boolean,\n default: false\n },\n /**\n * When `showFacets` property of `BaseSuggestions` component is true, it indicates if the suggestion without\n * filter should be rendered.\n *\n * @public\n */\n showPlainSuggestion: {\n type: Boolean,\n default: false\n },\n /** Class inherited by content element. */\n suggestionItemClass: String\n },\n setup: function (props) {\n /**\n * Creates a suggestion for each one of the filter inside each facet.\n *\n * @param suggestion - Suggestion to expand.\n * @returns A list of suggestions, each one with a single filter.\n *\n * @internal\n */\n const expandSuggestionFilters = (suggestion: Suggestion): Suggestion[] => {\n return (\n suggestion.facets?.flatMap(facet =>\n facet.filters.map(filter => ({\n ...suggestion,\n facets: [{ ...facet, filters: [filter] }]\n }))\n ) ?? []\n );\n };\n\n /**\n * Creates a list of suggestions to render based on the configuration of this component.\n *\n * @returns - The list of suggestions to be rendered by this component.\n *\n * @internal\n */\n const suggestionsToRender = computed(() =>\n props.suggestions\n .flatMap(suggestion =>\n props.showFacets && suggestion.facets?.length\n ? props.showPlainSuggestion\n ? [{ ...suggestion, facets: [] }, ...expandSuggestionFilters(suggestion)]\n : expandSuggestionFilters(suggestion)\n : { ...suggestion, facets: [] }\n )\n .slice(0, props.maxItemsToRender)\n );\n\n /**\n * Generates a string from the given facet.\n *\n * @param facet - The facet to reduce to a string.\n * @returns - A string representing the facet.\n * @internal\n */\n const getFacetKey = (facet: Facet) => facet.filters.map(filter => filter.id).join('&');\n\n /**\n * Generates a string from the given facets.\n *\n * @param facets - The list of facets to reduce to a string.\n * @returns - A string representing the list of facets.\n * @internal\n */\n const getFacetsKey = (facets: Facet[]) => facets.map(getFacetKey).join('&');\n\n /**\n * An array with the unique keys for each suggestion. Required by the `v-for` loop.\n *\n * @returns An array with the unique keys of the suggestions.\n * @internal\n */\n const suggestionsKeys = computed(() =>\n suggestionsToRender.value.map(suggestion =>\n isArrayEmpty(suggestion.facets)\n ? suggestion.query\n : `${suggestion.query}-in-${getFacetsKey(suggestion.facets)}`\n )\n );\n\n /**\n * Returns the filter contained by the suggestion.\n *\n * @param suggestion - Suggestion containing the filter.\n * @returns The suggestion filter.\n * @internal\n */\n const getSuggestionFilter = (suggestion: Suggestion) => suggestion.facets?.[0]?.filters[0];\n\n return { suggestionsToRender, suggestionsKeys, getSuggestionFilter };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-suggestions {\n list-style-type: none;\n }\n\n .x-suggestions,\n .x-suggestions__item {\n display: flex;\n flex-flow: column nowrap;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\nFor this component to work, you will need to set a list of suggestions as prop, and also to\nimplement the component for single suggestion, which handles the click event. In the following\nexample, the suggestions are retrieved from a property called `suggestions`, and the implementation\nof the suggestion component is a simple `button`, that calls the `emitSuggestionSelected` method\nwhen clicked.\n\n```vue\n<BaseSuggestions :suggestions=\"suggestions\">\n <template #default=\"{ suggestion }\">\n <button @click=\"emitSuggestionSelected($event, suggestion)\">\n {{ suggestion.query }}\n </button>\n </template>\n</BaseSuggestions>\n```\n\nFollowing the previous example, the component options object could be something like this:\n\n```js\nexport default {\n computed: {\n ...mapGetters(['x', 'querySuggestions'], { suggestions: 'suggestions' })\n },\n methods: {\n emitSuggestionSelected(event, suggestion) {\n this.$x.emit('UserAcceptedAQuery', suggestion.query, { target: event.target });\n this.$x.emit('UserSelectedAQuerySuggestion', suggestion, { target: event.target });\n }\n }\n};\n```\n\n### Play with props\n\nIn this example, the suggestions has been limited to render a maximum of 3 items. _Type \"puzzle\" or\nanother toy in the input field to try it out!_\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" :maxItemsToRender=\"3\" />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n\nIn this example, the filters of the suggestion will be rendered along with the query.\n\nThe `showPlainSuggestion` prop can be used to indicate if the suggestion without filter must be\nrendered along with the suggestion with filters.\n\nThis will render:\n\n- Chips //If `showPlainSuggestion` is true\n- Chips EXAMPLE\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" showFacets showPlainSuggestion />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [\n {\n id: 'exampleFacet',\n label: 'exampleFacet',\n modelName: 'SimpleFacet',\n filters: [\n {\n facetId: 'exampleFacet',\n id: '{!tag=exampleFacet}exampleFacet_60361120_64009600:\"EXAMPLE\"',\n label: 'EXAMPLE',\n selected: false,\n totalResults: 10,\n modelName: 'SimpleFilter'\n }\n ]\n }\n ],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n\nIn this example, the `contentClass` prop can be used to add classes to the suggestion item.\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" suggestionItemClass=\"x-custom-class\" />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["animation","_openBlock","_createBlock","_resolveDynamicComponent","suggestionsKeys","_Fragment","_renderList","_createElementBlock","_normalizeClass","_createCommentVNode"],"mappings":";;;;;AACE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EADF,MACkBA,EAAAA,MAAAA,EAAAA,KAAAA,EAAAA,QAAAA,EAAAA;SADlB,IAC+D,CAAA,WAAA,CAAA,MAAA,IAAAC,SAAA,EAAA,EAAAC,WAAA,CAAAC,uBAAA,CAAA,IAAA,CAAA,SAAA,CAAA,EAAA;AAAA,IAAC,GAAK,EAAA,CAAA;AAAA,IAAA,GAAA,EAAA,IAAA;AADrE,IAAA,KAAA,EAAA,eAAA;AAAA,GAAA,EAAA;;AAIYC,OAAAA,SAAAA,CAAAA,IAAAA,CAAAA,EAAAA,kBAAAA;AAAAA,QAAqBC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAAA,IAAA,CAAA,mBAAA,EAAA,CAAA,UAAA,EAAA,KAAA,KAAA;iBACtBL,SALX,EAAA,EAAAM,kBAAA;AAAA,YAKY,IAAA;AAAA,YAAqB;AAAA,cAE3B,0BAAU,KAAiB,CAAA;AAAA,cAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,qBAAA,EAAA,IAAA,CAAA,mBAAA,CAAA,CAAA;AAE3B,cAAA,WAAA,EAAA,iBAAA;AAAA,aAAA;AAMA,YAAA;AAAA,cAAAC,kBAAA,CAAA,uPAAA,CAAA;;;;;;AAfN,SAAA,CAAA;AAAA,QAAA,GAAA;AAAA;AAAA,OAAA;AAAA,KAAA,CAAA;AAAA,IAAA,CAAA,EAAA,CAAA;AAAA;AAAA,GAAA,CAAA,IAAAA,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"base-suggestions.vue.js","sources":["../../../../src/components/suggestions/base-suggestions.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" v-if=\"suggestions.length\" tag=\"ul\" class=\"x-suggestions\">\n <li\n v-for=\"(suggestion, index) in suggestionsToRender\"\n :key=\"suggestionsKeys[index]\"\n class=\"x-suggestions__item\"\n :class=\"suggestionItemClass\"\n data-test=\"suggestion-item\"\n >\n <!--\n @slot (Required) List item content\n @binding {Suggestion} suggestion - Suggestion data\n @binding {number} index - Suggestion index\n @binding {Filter | undefined} filter - Suggestion's filter\n -->\n <slot v-bind=\"{ suggestion, index, filter: getSuggestionFilter(suggestion) }\" />\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, PropType } from 'vue';\n import { Suggestion, Facet } from '@empathyco/x-types';\n import { isArrayEmpty } from '../../utils/array';\n import { AnimationProp } from '../../types';\n\n /**\n * Paints a list of suggestions passed in by prop. Requires a component for a single suggestion\n * in the default slot for working.\n *\n * @public\n */\n export default defineComponent({\n name: 'BaseSuggestions',\n props: {\n /**\n * The list of suggestions to render.\n *\n * @public\n */\n suggestions: {\n type: Array as PropType<Suggestion[]>,\n required: true\n },\n /**\n * Animation component that will be used to animate the suggestion.\n *\n * @public\n */\n animation: {\n type: AnimationProp,\n default: 'ul'\n },\n /**\n * Number of suggestions to be rendered.\n *\n * @public\n */\n maxItemsToRender: Number,\n /**\n * Boolean value to indicate if the facets should be rendered.\n *\n * @public\n */\n showFacets: {\n type: Boolean,\n default: false\n },\n /**\n * When `showFacets` property of `BaseSuggestions` component is true, it indicates if the suggestion without\n * filter should be rendered.\n *\n * @public\n */\n showPlainSuggestion: {\n type: Boolean,\n default: false\n },\n /** Class inherited by content element. */\n suggestionItemClass: String\n },\n setup: function (props) {\n /**\n * Creates a suggestion for each one of the filter inside each facet.\n *\n * @param suggestion - Suggestion to expand.\n * @returns A list of suggestions, each one with a single filter.\n *\n * @internal\n */\n const expandSuggestionFilters = (suggestion: Suggestion): Suggestion[] => {\n return (\n suggestion.facets?.flatMap(facet =>\n facet.filters.map(filter => ({\n ...suggestion,\n facets: [{ ...facet, filters: [filter] }]\n }))\n ) ?? []\n );\n };\n\n /**\n * Creates a list of suggestions to render based on the configuration of this component.\n *\n * @returns - The list of suggestions to be rendered by this component.\n *\n * @internal\n */\n const suggestionsToRender = computed(() =>\n props.suggestions\n .flatMap(suggestion =>\n props.showFacets && suggestion.facets?.length\n ? props.showPlainSuggestion\n ? [{ ...suggestion, facets: [] }, ...expandSuggestionFilters(suggestion)]\n : expandSuggestionFilters(suggestion)\n : { ...suggestion, facets: [] }\n )\n .slice(0, props.maxItemsToRender)\n );\n\n /**\n * Generates a string from the given facet.\n *\n * @param facet - The facet to reduce to a string.\n * @returns - A string representing the facet.\n * @internal\n */\n const getFacetKey = (facet: Facet) => facet.filters.map(filter => filter.id).join('&');\n\n /**\n * Generates a string from the given facets.\n *\n * @param facets - The list of facets to reduce to a string.\n * @returns - A string representing the list of facets.\n * @internal\n */\n const getFacetsKey = (facets: Facet[]) => facets.map(getFacetKey).join('&');\n\n /**\n * An array with the unique keys for each suggestion. Required by the `v-for` loop.\n *\n * @returns An array with the unique keys of the suggestions.\n * @internal\n */\n const suggestionsKeys = computed(() =>\n suggestionsToRender.value.map(suggestion =>\n isArrayEmpty(suggestion.facets)\n ? suggestion.query\n : `${suggestion.query}-in-${getFacetsKey(suggestion.facets)}`\n )\n );\n\n /**\n * Returns the filter contained by the suggestion.\n *\n * @param suggestion - Suggestion containing the filter.\n * @returns The suggestion filter.\n * @internal\n */\n const getSuggestionFilter = (suggestion: Suggestion) => suggestion.facets?.[0]?.filters[0];\n\n return { suggestionsToRender, suggestionsKeys, getSuggestionFilter };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-suggestions {\n list-style-type: none;\n }\n\n .x-suggestions,\n .x-suggestions__item {\n display: flex;\n flex-flow: column nowrap;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\nFor this component to work, you will need to set a list of suggestions as prop, and also to\nimplement the component for single suggestion, which handles the click event. In the following\nexample, the suggestions are retrieved from a property called `suggestions`, and the implementation\nof the suggestion component is a simple `button`, that calls the `emitSuggestionSelected` method\nwhen clicked.\n\n```vue\n<BaseSuggestions :suggestions=\"suggestions\">\n <template #default=\"{ suggestion }\">\n <button @click=\"emitSuggestionSelected($event, suggestion)\">\n {{ suggestion.query }}\n </button>\n </template>\n</BaseSuggestions>\n```\n\nFollowing the previous example, the component options object could be something like this:\n\n```js\nexport default {\n computed: {\n ...mapGetters(['x', 'querySuggestions'], { suggestions: 'suggestions' })\n },\n methods: {\n emitSuggestionSelected(event, suggestion) {\n this.$x.emit('UserAcceptedAQuery', suggestion.query, { target: event.target });\n this.$x.emit('UserSelectedAQuerySuggestion', suggestion, { target: event.target });\n }\n }\n};\n```\n\n### Play with props\n\nIn this example, the suggestions has been limited to render a maximum of 3 items. _Type \"puzzle\" or\nanother toy in the input field to try it out!_\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" :maxItemsToRender=\"3\" />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n\nIn this example, the filters of the suggestion will be rendered along with the query.\n\nThe `showPlainSuggestion` prop can be used to indicate if the suggestion without filter must be\nrendered along with the suggestion with filters.\n\nThis will render:\n\n- Chips //If `showPlainSuggestion` is true\n- Chips EXAMPLE\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" showFacets showPlainSuggestion />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [\n {\n id: 'exampleFacet',\n label: 'exampleFacet',\n modelName: 'SimpleFacet',\n filters: [\n {\n facetId: 'exampleFacet',\n id: '{!tag=exampleFacet}exampleFacet_60361120_64009600:\"EXAMPLE\"',\n label: 'EXAMPLE',\n selected: false,\n totalResults: 10,\n modelName: 'SimpleFilter'\n }\n ]\n }\n ],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n\nIn this example, the `contentClass` prop can be used to add classes to the suggestion item.\n\n```vue\n<template>\n <BaseSuggestions :suggestions=\"suggestions\" suggestionItemClass=\"x-custom-class\" />\n</template>\n\n<script>\n import { BaseSuggestions } from '@empathyco/x-components';\n\n export default {\n name: 'BaseSuggestionsDemo',\n components: {\n BaseSuggestions\n },\n data() {\n return {\n suggestions: [\n {\n facets: [],\n key: 'chips',\n query: 'Chips',\n totalResults: 10,\n results: [],\n modelName: 'PopularSearch'\n }\n ]\n };\n }\n };\n</script>\n```\n</docs>\n"],"names":["animation","_openBlock","_createBlock","_resolveDynamicComponent","suggestionsKeys","_Fragment","_renderList","_createElementBlock","_normalizeClass","_createCommentVNode"],"mappings":";;;;;AACE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EADF,MACkBA,EAAAA,MAAAA,EAAAA,KAAAA,EAAAA,QAAAA,EAAAA;SADlB,IAC+D,CAAA,WAAA,CAAA,MAAA,IAAAC,SAAA,EAAA,EAAAC,WAAA,CAAAC,uBAAA,CAAA,IAAA,CAAA,SAAA,CAAA,EAAA;AAAA,IAAC,GAAK,EAAA,CAAA;AAAA,IAAA,GAAA,EAAA,IAAA;AADrE,IAAA,KAAA,EAAA,eAAA;AAAA,GAAA,EAAA;;AAIYC,OAAAA,SAAAA,CAAAA,IAAAA,CAAAA,EAAAA,kBAAAA;AAAAA,QAAqBC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAAA,IAAA,CAAA,mBAAA,EAAA,CAAA,UAAA,EAAA,KAAA,KAAA;iBACtBL,SALX,EAAA,EAAAM,kBAAA;AAAA,YAKY,IAAA;AAAA,YAAqB;AAAA,cAE3B,0BAAU,KAAiB,CAAA;AAAA,cAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,qBAAA,EAAA,IAAA,CAAA,mBAAA,CAAA,CAAA;cAQ3B,WAAgF,EAAA,iBAAA;AAAA,aAAA;;;;;;;AAftF,SAAA,CAAA;AAAA,QAAA,GAAA;AAAA;AAAA,OAAA;AAAA,KAAA,CAAA;AAAA,IAAA,CAAA,EAAA,CAAA;AAAA;AAAA,GAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './empathize.vue2.js';
|
|
2
|
-
import { openBlock, createBlock, resolveDynamicComponent, withCtx, withDirectives, createElementVNode, withModifiers,
|
|
2
|
+
import { openBlock, createBlock, resolveDynamicComponent, withCtx, withDirectives, createElementVNode, withModifiers, renderSlot, vShow } from 'vue';
|
|
3
3
|
import _export_sfc from '../../../_virtual/_plugin-vue_export-helper.js';
|
|
4
4
|
|
|
5
5
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
@@ -17,7 +17,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
17
17
|
"data-test": "empathize"
|
|
18
18
|
},
|
|
19
19
|
[
|
|
20
|
-
createCommentVNode(" @slot (Required) Modal container content "),
|
|
21
20
|
renderSlot(_ctx.$slots, "default")
|
|
22
21
|
],
|
|
23
22
|
544
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empathize.vue.js","sources":["../../../../../src/x-modules/empathize/components/empathize.vue"],"sourcesContent":["<template>\n <component :is=\"animation\">\n <div\n v-show=\"isOpen && hasContent\"\n ref=\"empathizeRef\"\n @mousedown.prevent\n @focusin=\"open\"\n @focusout=\"close\"\n class=\"x-empathize\"\n data-test=\"empathize\"\n >\n <!-- @slot (Required) Modal container content -->\n <slot />\n </div>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent, PropType, ref } from 'vue';\n import { NoAnimation } from '../../../components';\n import { use$x, useDebounce } from '../../../composables';\n import { AnimationProp } from '../../../types';\n import { XEvent } from '../../../wiring';\n import { empathizeXModule } from '../x-module';\n import { getActiveElement } from '../../../utils/html';\n\n /**\n * Component containing the empathize. It has a required slot to define its content and two props\n * to define when to open and close it: `eventsToOpenEmpathize` and `eventsToCloseEmpathize`.\n *\n * @public\n */\n export default defineComponent({\n name: 'Empathize',\n xModule: empathizeXModule.name,\n props: {\n /** Array of {@link XEvent} to open the empathize. */\n eventsToOpenEmpathize: {\n type: Array as PropType<XEvent[]>,\n default: () => ['UserFocusedSearchBox', 'UserIsTypingAQuery', 'UserClickedSearchBox']\n },\n /** Array of {@link XEvent} to close the empathize. */\n eventsToCloseEmpathize: {\n type: Array as PropType<XEvent[]>,\n default: () => [\n 'UserClosedEmpathize',\n 'UserSelectedASuggestion',\n 'UserPressedEnterKey',\n 'UserBlurredSearchBox'\n ]\n },\n /** Animation component that will be used to animate the empathize. */\n animation: {\n type: AnimationProp,\n default: () => NoAnimation\n }\n },\n setup(props) {\n const $x = use$x();\n\n const empathizeRef = ref<HTMLDivElement>();\n\n const isOpen = ref(false);\n const hasContent = ref(!!empathizeRef.value?.children.length);\n\n /**\n * Changes the state of {@link Empathize.isOpen} assigning to it the value of `newOpen`\n * parameter. Also emits the {@link XEvent} `EmpathizeOpened` or `EmpathizeClosed` if\n * the state really changes.\n *\n * @param newOpen - The new open state to assign to {@link Empathize.isOpen}.\n */\n const changeOpen = useDebounce((newOpen: boolean) => {\n if (isOpen.value !== newOpen) {\n isOpen.value = newOpen;\n const empathizeEvent = isOpen.value ? 'EmpathizeOpened' : 'EmpathizeClosed';\n $x.emit(empathizeEvent, undefined, { target: empathizeRef.value });\n }\n }, 0);\n\n /**\n * Open empathize. This method will be executed on any event in\n * {@link Empathize.eventsToOpenEmpathize} and on DOM event `focusin` on Empathize root\n * element.\n */\n function open() {\n hasContent.value = !!empathizeRef.value?.children.length;\n if (hasContent.value) {\n changeOpen(true);\n }\n }\n\n /**\n * Close empathize. This method will be executed on any event in\n * {@link Empathize.eventsToCloseEmpathize} and on DOM event `focusout` on Empathize root\n * element.\n */\n function close() {\n const activeElement = getActiveElement();\n if (!empathizeRef.value?.contains(activeElement)) {\n changeOpen(false);\n }\n }\n\n props.eventsToOpenEmpathize.forEach(event => $x.on(event, false).subscribe(open));\n props.eventsToCloseEmpathize.forEach(event => $x.on(event, false).subscribe(close));\n\n return {\n close,\n empathizeRef,\n hasContent,\n isOpen,\n open\n };\n }\n });\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`EmpathizeOpened`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after receiving an event to change the state `isOpen` to `true`. The event\n payload is undefined and can have a metadata with the module and the element that emitted it.\n- [`EmpathizeClosed`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after receiving an event to change the state `isOpen` to `false`. The event\n payload is undefined and can have a metadata with the module and the element that emitted it.\n\n## Examples\n\nThis component will listen to the configured events in `eventsToOpenEmpathize` and\n`eventsToCloseEmpathize` props and open/close itself accordingly. By default, those props values\nare:\n\n- Open: `UserFocusedSearchBox`, `'`UserIsTypingAQuery`, `'`UserClickedSearchBox` and\n- Close: `UserClosedEmpathize`, `UserSelectedASuggestion`, `UserPressedEnter`,\n 'UserBlurredSearchBox`\n\n### Basic examples\n\nThe component rendering the query suggestions, popular searches and history queries with keyboard\nnavigation.\n\n```vue\n<Empathize>\n <template #default>\n <BaseKeyboardNavigation>\n <QuerySuggestions/>\n <PopularSearches/>\n <HistoryQueries/>\n </BaseKeyboardNavigation>\n </template>\n</Empathize>\n```\n\nDefining custom values for the events to open and close the Empathize. For example opening it when\nthe search box loses the focus and closing it when the search box receives the focus:\n\n```vue\n<Empathize\n :eventsToOpenEmpathize=\"['UserBlurredSearchBox']\"\n :eventsToCloseEmpathize=\"['UserFocusedSearchBox']\"\n>\n <template #default>\n Please, type a query in the Search Box.\n </template>\n</Empathize>\n```\n\nAn animation can be used for the opening and closing using the `animation` prop. The animation, must\nbe a Component with a `Transition` with a slot inside:\n\n```vue\n<Empathize :animation=\"collapseFromTop\">\n <template #default>\n <PopularSearches/>\n </template>\n</Empathize>\n```\n</docs>\n"],"names":["_createBlock","_resolveDynamicComponent","_withCtx","_withDirectives","_createElementVNode","_withModifiers","
|
|
1
|
+
{"version":3,"file":"empathize.vue.js","sources":["../../../../../src/x-modules/empathize/components/empathize.vue"],"sourcesContent":["<template>\n <component :is=\"animation\">\n <div\n v-show=\"isOpen && hasContent\"\n ref=\"empathizeRef\"\n @mousedown.prevent\n @focusin=\"open\"\n @focusout=\"close\"\n class=\"x-empathize\"\n data-test=\"empathize\"\n >\n <!-- @slot (Required) Modal container content -->\n <slot />\n </div>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent, PropType, ref } from 'vue';\n import { NoAnimation } from '../../../components';\n import { use$x, useDebounce } from '../../../composables';\n import { AnimationProp } from '../../../types';\n import { XEvent } from '../../../wiring';\n import { empathizeXModule } from '../x-module';\n import { getActiveElement } from '../../../utils/html';\n\n /**\n * Component containing the empathize. It has a required slot to define its content and two props\n * to define when to open and close it: `eventsToOpenEmpathize` and `eventsToCloseEmpathize`.\n *\n * @public\n */\n export default defineComponent({\n name: 'Empathize',\n xModule: empathizeXModule.name,\n props: {\n /** Array of {@link XEvent} to open the empathize. */\n eventsToOpenEmpathize: {\n type: Array as PropType<XEvent[]>,\n default: () => ['UserFocusedSearchBox', 'UserIsTypingAQuery', 'UserClickedSearchBox']\n },\n /** Array of {@link XEvent} to close the empathize. */\n eventsToCloseEmpathize: {\n type: Array as PropType<XEvent[]>,\n default: () => [\n 'UserClosedEmpathize',\n 'UserSelectedASuggestion',\n 'UserPressedEnterKey',\n 'UserBlurredSearchBox'\n ]\n },\n /** Animation component that will be used to animate the empathize. */\n animation: {\n type: AnimationProp,\n default: () => NoAnimation\n }\n },\n setup(props) {\n const $x = use$x();\n\n const empathizeRef = ref<HTMLDivElement>();\n\n const isOpen = ref(false);\n const hasContent = ref(!!empathizeRef.value?.children.length);\n\n /**\n * Changes the state of {@link Empathize.isOpen} assigning to it the value of `newOpen`\n * parameter. Also emits the {@link XEvent} `EmpathizeOpened` or `EmpathizeClosed` if\n * the state really changes.\n *\n * @param newOpen - The new open state to assign to {@link Empathize.isOpen}.\n */\n const changeOpen = useDebounce((newOpen: boolean) => {\n if (isOpen.value !== newOpen) {\n isOpen.value = newOpen;\n const empathizeEvent = isOpen.value ? 'EmpathizeOpened' : 'EmpathizeClosed';\n $x.emit(empathizeEvent, undefined, { target: empathizeRef.value });\n }\n }, 0);\n\n /**\n * Open empathize. This method will be executed on any event in\n * {@link Empathize.eventsToOpenEmpathize} and on DOM event `focusin` on Empathize root\n * element.\n */\n function open() {\n hasContent.value = !!empathizeRef.value?.children.length;\n if (hasContent.value) {\n changeOpen(true);\n }\n }\n\n /**\n * Close empathize. This method will be executed on any event in\n * {@link Empathize.eventsToCloseEmpathize} and on DOM event `focusout` on Empathize root\n * element.\n */\n function close() {\n const activeElement = getActiveElement();\n if (!empathizeRef.value?.contains(activeElement)) {\n changeOpen(false);\n }\n }\n\n props.eventsToOpenEmpathize.forEach(event => $x.on(event, false).subscribe(open));\n props.eventsToCloseEmpathize.forEach(event => $x.on(event, false).subscribe(close));\n\n return {\n close,\n empathizeRef,\n hasContent,\n isOpen,\n open\n };\n }\n });\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`EmpathizeOpened`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after receiving an event to change the state `isOpen` to `true`. The event\n payload is undefined and can have a metadata with the module and the element that emitted it.\n- [`EmpathizeClosed`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after receiving an event to change the state `isOpen` to `false`. The event\n payload is undefined and can have a metadata with the module and the element that emitted it.\n\n## Examples\n\nThis component will listen to the configured events in `eventsToOpenEmpathize` and\n`eventsToCloseEmpathize` props and open/close itself accordingly. By default, those props values\nare:\n\n- Open: `UserFocusedSearchBox`, `'`UserIsTypingAQuery`, `'`UserClickedSearchBox` and\n- Close: `UserClosedEmpathize`, `UserSelectedASuggestion`, `UserPressedEnter`,\n 'UserBlurredSearchBox`\n\n### Basic examples\n\nThe component rendering the query suggestions, popular searches and history queries with keyboard\nnavigation.\n\n```vue\n<Empathize>\n <template #default>\n <BaseKeyboardNavigation>\n <QuerySuggestions/>\n <PopularSearches/>\n <HistoryQueries/>\n </BaseKeyboardNavigation>\n </template>\n</Empathize>\n```\n\nDefining custom values for the events to open and close the Empathize. For example opening it when\nthe search box loses the focus and closing it when the search box receives the focus:\n\n```vue\n<Empathize\n :eventsToOpenEmpathize=\"['UserBlurredSearchBox']\"\n :eventsToCloseEmpathize=\"['UserFocusedSearchBox']\"\n>\n <template #default>\n Please, type a query in the Search Box.\n </template>\n</Empathize>\n```\n\nAn animation can be used for the opening and closing using the `animation` prop. The animation, must\nbe a Component with a `Transition` with a slot inside:\n\n```vue\n<Empathize :animation=\"collapseFromTop\">\n <template #default>\n <PopularSearches/>\n </template>\n</Empathize>\n```\n</docs>\n"],"names":["_createBlock","_resolveDynamicComponent","_withCtx","_withDirectives","_createElementVNode","_withModifiers","isOpen","hasContent"],"mappings":";;;;SAAA,WAaU,CAAA,IAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,QAAA,EAAA;sBAXNA,WAWM,CAAAC,uBAAA,CAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA;AAAA,IAAA,OAAA,EATAC,OAAc,CAAA,MAAA;AAAA,MACRC,cAAA,CAAAC,kBAAA;AAAA,QAAA,KAAA;AAAA,QALhB;AAAA,UAMO,GAAA,EAAA,cAAA;AAAA,UACA,aAAQ,MAAE,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAC,aAAA,CAAA,MAAA;AAAA,WAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA;AAAA,UACX,WAAM,MAAa,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,IAAA,IAAA,IAAA,CAAA,IAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UACnB,UAAA,EAAS,OAAC,CAAW,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,KAAA,IAAA,IAAA,CAAA,KAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAA,aAAA;UAGrB,WAAQ,EAAA,WAAA;AAAA,SAAA;;qBATAC,IAAUC,CAAAA,MAAAA,EAAAA,SAAAA,CAAAA;AAAAA,SAAAA;;;;;AAHxB,OAAA,CAAA;AAAA,KAAA,CAAA;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './facets.vue2.js';
|
|
2
|
-
import { openBlock, createBlock, resolveDynamicComponent, withCtx, createElementBlock, Fragment, renderList,
|
|
2
|
+
import { openBlock, createBlock, resolveDynamicComponent, withCtx, createElementBlock, Fragment, renderList, renderSlot, mergeProps, createTextVNode, toDisplayString, createCommentVNode } from 'vue';
|
|
3
3
|
import './facets.vue3.js';
|
|
4
4
|
import _export_sfc from '../../../../_virtual/_plugin-vue_export-helper.js';
|
|
5
5
|
|
|
@@ -20,44 +20,31 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
20
20
|
class: "x-facets-list__item",
|
|
21
21
|
"data-test": "facets-facet"
|
|
22
22
|
}, [
|
|
23
|
-
createCommentVNode("\n @slot Customized Facet rendering. Specifying a slot with the facet's name will result in the\n facet using that slot composition to render.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n "),
|
|
24
23
|
_ctx.hasSlot(slotNameById) ? renderSlot(_ctx.$slots, slotNameById, mergeProps({
|
|
25
24
|
key: 0,
|
|
26
25
|
ref_for: true
|
|
27
26
|
}, {
|
|
28
27
|
facet,
|
|
29
28
|
selectedFilters: _ctx.selectedFiltersByFacet[facetId] || []
|
|
30
|
-
}), void 0, true) : _ctx.hasSlot(slotNameByModelName) ? (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
selectedFilters: _ctx.selectedFiltersByFacet[facetId] || []
|
|
50
|
-
}), () => [
|
|
51
|
-
createTextVNode(
|
|
52
|
-
" This is the " + toDisplayString(facet.label) + " facet. Pass something into its slot to display content. ",
|
|
53
|
-
1
|
|
54
|
-
/* TEXT */
|
|
55
|
-
)
|
|
56
|
-
], true)
|
|
57
|
-
],
|
|
58
|
-
2112
|
|
59
|
-
/* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
|
|
60
|
-
))
|
|
29
|
+
}), void 0, true) : _ctx.hasSlot(slotNameByModelName) ? renderSlot(_ctx.$slots, slotNameByModelName, mergeProps({
|
|
30
|
+
key: 1,
|
|
31
|
+
ref_for: true
|
|
32
|
+
}, {
|
|
33
|
+
facet,
|
|
34
|
+
selectedFilters: _ctx.selectedFiltersByFacet[facetId] || []
|
|
35
|
+
}), void 0, true) : renderSlot(_ctx.$slots, "default", mergeProps({
|
|
36
|
+
key: 2,
|
|
37
|
+
ref_for: true
|
|
38
|
+
}, {
|
|
39
|
+
facet,
|
|
40
|
+
selectedFilters: _ctx.selectedFiltersByFacet[facetId] || []
|
|
41
|
+
}), () => [
|
|
42
|
+
createTextVNode(
|
|
43
|
+
" This is the " + toDisplayString(facet.label) + " facet. Pass something into its slot to display content. ",
|
|
44
|
+
1
|
|
45
|
+
/* TEXT */
|
|
46
|
+
)
|
|
47
|
+
], true)
|
|
61
48
|
]);
|
|
62
49
|
}),
|
|
63
50
|
128
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facets.vue.js","sources":["../../../../../../src/x-modules/facets/components/facets/facets.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" v-if=\"hasFacets\" class=\"x-facets-list\" data-test=\"facets\" tag=\"ul\">\n <li\n v-for=\"({ facet, slotNameById, slotNameByModelName }, facetId) in mappedFacets\"\n :key=\"facetId\"\n class=\"x-facets-list__item\"\n data-test=\"facets-facet\"\n >\n <!--\n @slot Customized Facet rendering. Specifying a slot with the facet's name will result in the\n facet using that slot composition to render.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-if=\"hasSlot(slotNameById)\"\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n :name=\"slotNameById\"\n />\n <!--\n @slot Customized Facet rendering. Specifying a slot with the facet's modelName will result\n in the facet using that slot composition to render.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-else-if=\"hasSlot(slotNameByModelName)\"\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n :name=\"slotNameByModelName\"\n />\n <!--\n @slot (required) Default Facet rendering. This slot will be used by default for rendering\n the facets without an specific slot implementation.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-else\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n >\n This is the {{ facet.label }} facet. Pass something into its slot to display content.\n </slot>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { Facet } from '@empathyco/x-types';\n import { Dictionary, map, objectFilter } from '@empathyco/x-utils';\n import { computed, ComputedRef, defineComponent, PropType } from 'vue';\n import { useGetter } from '../../../../composables/use-getter';\n import { toKebabCase } from '../../../../utils/string';\n import { useFacets } from '../../composables/use-facets';\n import { facetsXModule } from '../../x-module';\n import { AnimationProp } from '../../../../types';\n\n /**\n * Custom interface to provide a slot name to a Facet.\n *\n * @internal\n */\n interface RenderFacet {\n slotNameById: string;\n slotNameByModelName: string;\n facet: Facet;\n }\n\n /**\n * This component renders the list of facets stored in the Facets module. Facets can be rendered\n * differently based on their purpose and this can be achieved using the exposed slots:\n * - A default and required slot.\n * - A custom slot for each facet with the facetId as its name. This allows each facet to be\n * rendered differently based on its needs.\n *\n * @public\n */\n export default defineComponent({\n name: 'Facets',\n xModule: facetsXModule.name,\n props: {\n /** Array of facets ids used to get the selected filters for those facets. */\n facetsIds: Array as PropType<Array<Facet['id']>>,\n /** Flag to render the component even if there are no filters selected. */\n alwaysVisible: Boolean,\n /** Animation component that will be used to animate the facets. */\n animation: {\n type: AnimationProp,\n default: 'ul'\n },\n /**\n * Discriminates the facets rendered by this component. It expects a string containing facets\n * ids, comma separated. This property will include or exclude facets based on its value.\n * The default value is an empty string and the component will render all existing facets.\n *\n * @remarks\n * To behave as a `include`, simply set the facets ids, comma separated:\n * `existingFacets=[{ brand: ... }, category: { ... }, color: { ... }, price: { ... }]`\n * `renderableFacets=\"brand, category\"`\n *\n * The component will render brand and category facets.\n *\n * On the other hand, to simulate an `exclude` behaviour and exclude a facet from being\n * rendered, append a '!' before its id:\n * `existingFacets=[{ brand: ... }, category: { ... }, color: { ... }, price: { ... }]`\n * `renderableFacets=\"!brand,!price\"`\n *\n * The component will render category and color facets.\n */\n renderableFacets: String\n },\n setup: function (props, { slots }) {\n const { selectedFiltersByFacet } = useFacets(props);\n\n const { facets } = useGetter('facets', ['facets']) as {\n /** Dictionary of facets in the state. */\n facets: ComputedRef<Record<Facet['id'], Facet>>;\n };\n\n /**\n * The facets to be rendered after filtering {@link Facets.facets} by\n * {@link Facets.renderableFacets} content.\n *\n * @returns The list of facets to be rendered.\n */\n const facetsToRender = computed<Dictionary<Facet>>(() => {\n if (!props.renderableFacets) {\n return facets.value;\n } else {\n const excludedRegExp = /^!/;\n const facetIds: string[] = props.renderableFacets\n .split(',')\n .map(facetId => facetId.trim());\n const included: string[] = [];\n const excluded: string[] = [];\n facetIds.forEach(facetId => {\n if (excludedRegExp.test(facetId)) {\n excluded.push(facetId.replace(excludedRegExp, ''));\n } else {\n included.push(facetId);\n }\n });\n\n return filterFacetsToRender(included, excluded);\n }\n });\n\n /**\n * Transforms a dictionary of Facets including the slot name.\n *\n * @returns A dictionary of facets with the slot name.\n */\n const mappedFacets = computed<Dictionary<RenderFacet>>(() => {\n return map(facetsToRender.value, (facetId, facet) => ({\n slotNameById: toKebabCase(facetId),\n slotNameByModelName: toKebabCase(facet.modelName),\n facet\n }));\n });\n\n /**\n * Indicates if there are facets available to show.\n *\n * @returns True if there are facets available and false otherwise.\n */\n const hasFacets = computed<boolean>(() => !!Object.keys(facetsToRender.value).length);\n\n /**\n * Filter facets dictionary retrieving those included and/or removing excluded.\n *\n * @param included - List of facets to render.\n * @param excluded - List of not renderable facets.\n *\n * @returns The filtered list of facets to render.\n */\n function filterFacetsToRender(included: string[], excluded: string[]): Dictionary<Facet> {\n const hasAnyFacetIncluded = included.length > 0;\n return objectFilter(facets.value, facetKey => {\n const isIncluded = included.includes(String(facetKey));\n const isExcluded = excluded.includes(String(facetKey));\n\n return hasAnyFacetIncluded ? isIncluded && !isExcluded : !isExcluded;\n });\n }\n\n /**\n * Whether the slot is present in the template or not.\n *\n * @param name - The slot name.\n *\n * @returns True is the slot is present in the template. False otherwise.\n */\n function hasSlot(name: string): boolean {\n return !!slots[name];\n }\n\n return {\n selectedFiltersByFacet,\n hasFacets,\n mappedFacets,\n hasSlot\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-facets-list {\n display: flex;\n flex-flow: column nowrap;\n list-style-type: none;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Example\n\nThis component renders the list of facets stored in the Facets module. Facets can be rendered\ndifferently based on their purpose and this can be achieved using the exposed slots:\n\n- A default and required slot.\n- A custom slot for each facet with the facetId as its name. This allows each facet to be rendered\n differently based on its needs.\n\nBelow, there are some examples showing how to use the component with its different configurations.\n\n### Default usage\n\nThe default slot of this component is mandatory. If no other slot is defined, every Facet will be\nrendered as specified in the default slot.\n\n```vue\n<template>\n <Facets>\n <template #default=\"{ facet, selectedFilters }\">\n <h1>{{ ${facet.label} }}</h1>\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} selected` }}</span>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Customized usage\n\nCustomized compositions for a specific Facet can be achieved by using a slot with the same id as the\nfacet to customize. For example, the Facet with the id \"color\" requires a composition that differs\nfrom the rest of the Facets. Doing it in a slot with the name \"color\" will apply this customization\njust to the \"color\" Facet. The other facets will fallback to the composition of the default slot.\n\nIt is also possible to customize the Facet content by the facet \"model name\". For example, to\nconfigure different content for \"Hierarchical Facets\" the \"hierarchical-facet\" slot will apply that\ncustomization. This can be combined with the facets by facet id. If some hierarchical facet needs\nsome different customization from the rest of the hierarchical, it can be achieve using the slot\nwith the facet id.\n\n```vue\n<template>\n <Facets>\n <template #color=\"{ facet, selectedFilters }\">\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} colors chosen` }}</span>\n\n <ul v-for=\"filter in facet.filters\" :key=\"filter.id\">\n <li v-if=\"!filter.selected\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n\n <template #hierarchical-facet=\"{ facet, selectedFilters }\">\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} colors chosen` }}</span>\n\n <ul v-for=\"filter in facet.filters\" :key=\"filter.id\">\n <li v-if=\"!filter.selected\">\n {{ filter.label }}\n <ul v-for=\"childFilter in filter.children\" :key=\"filter.id\">\n <li v-if=\"!childFilter.selected\">\n {{ childFilter.label }}\n </li>\n </ul>\n </li>\n </ul>\n </template>\n\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Render specific facets I\n\nBy default, this component will render all existing facets. However, it has the renderableFacets\nprop to filter which facets will be rendered. Its value is a string containing the different facets\nids. This value is treated as an include or exclude list (to exclude a facet from being rendered,\njust prefix its id with a `!`). The component will only render included facets and discard excluded\nones. In the following example, the component will only render color and category facets.\n\n```vue\n<template>\n <Facets renderableFacets=\"color, category\">\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Render specific facets II\n\nExclude facets so the component does not render them. In the following example, the component will\nrender every facet except color and price.\n\n```vue\n<template>\n <Facets renderableFacets=\"!color, !price\">\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Integrating with the filters components\n\nThere are many components that will help you build your own awesome filters list. `Facets` just\nrenders the list, but what to render for each facet is up to you. Below you can see an example. of\nthe `Facets` component using the `FiltersSearch` `MultiSelectFilters`, `SimpleFilter`, `Filters`,\n`HierarchicalFilter`, `NumberRangeFilter` and `BasePriceFilterLabel`.\n\n```vue\n<template>\n <Facets>\n <template #default=\"{ facet, selectedFilters }\">\n <h1>{{ facet.label }}</h1>\n <FiltersSearch :filters=\"facet.filters\">\n <MultiSelectFilters v-slot=\"{ filter }\">\n <SimpleFilter :filter=\"filter\" />\n </MultiSelectFilters>\n </FiltersSearch>\n </template>\n\n <template #category=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n <Filters v-slot=\"{ filter }\" :filters=\"facet.filters\">\n <HierarchicalFilter :filter=\"filter\" />\n </Filters>\n </template>\n\n <template #price=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n <Filters v-slot=\"{ filter }\" :filters=\"facet.filters\">\n <NumberRangeFilter :filter=\"filter\">\n <BasePriceFilterLabel :filter=\"filter\" />\n </NumberRangeFilter>\n </Filters>\n </template>\n </Facets>\n</template>\n\n<script>\n import {\n Facets,\n Filters,\n FiltersSearch,\n HierarchicalFilter,\n MultiSelectFilters,\n NumberRangeFilter,\n SimpleFilter\n } from '@empathyco/x-components/facets';\n\n import { BasePriceFilterLabel } from '@empathyco/x-components';\n\n export default {\n components: {\n Facets,\n MultiSelectFilters,\n FiltersSearch,\n SimpleFilter,\n Filters,\n HierarchicalFilter,\n NumberRangeFilter,\n BasePriceFilterLabel\n }\n };\n</script>\n```\n</docs>\n"],"names":["animation","_openBlock","_createBlock","_resolveDynamicComponent","_createElementBlock","_Fragment","_renderList","hasSlot","_createCommentVNode","_renderSlot","_mergeProps","selectedFiltersByFacet"],"mappings":";;;;;AACE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EADF,MACkBA,EAAAA,MAAAA,EAAAA,KAAAA,EAAAA,QAAAA,EAAAA;AADlB,EAAA,OAAA,IAAA,CAAA,SAAA,IAAAC,SAAA,EACmE,EAAAC,WAAA,CAAAC,uBAAA,CAAA,IAAA,CAAA,SAAA,CAAA,EAAA;AAAA,IAAC,GAAA,EAAA,CAAA;AAAA,IAAmB,KAAI,EAAA,eAAA;AAAA,IAAA,WAAA,EAAA,QAAA;AAD3F,IAAA,GAAA,EAAA,IAAA;AAAA,GAAA,EAAA;;iBAIY,IAAO,CAAA,EAAAC,kBAAA;AAAA,QAAAC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAAA,IAAA,CAAA,YAAA,EAAA,CAAA,EAAA,KAAA,EAAA,YAAA,EAAA,mBAAA,EAAA,EAAA,OAAA,KAAA;AACR,UAAA,OAAAL,SAAA,EAAsB,EAAAG,kBAAA,CAAA,IAAA,EAAA;AAAA,YAC3B,GAAA,EAAA,OAAA;AAAA,YAAA,KAAA,EAAA,qBAAA;AAEA,YAAA,WAAA,EAAA,cAAA;AAAA,WAOQG,EAAAA;AAAAA,YAMNC,kBAAA,CAAA,2TAAA,CAAA;AAAA,YArBR,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,GAAAC,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,YAAA,EAAAC,UAAA,CAAA;AAAA,cAAA,GAAA,EAAA,CAAA;AAgBiC,cAAA,OAAA,EAAA,IAAA;AAAA,aAAA,EAAA;;AAadH,cAAAA,eAAAA,EAAAA,IAAAA,CAAQ,sBAAmB,CAAA,OAAA,CAAA,IAAA,EAAA;AAAA,aAAA,CAAA,EAAA,KAAA,CAAA,EAAA,IAAA,CAAA,GAAA,IAAA,CAPxC,2CAaE,EAAAH,kBAAA;AAAA,cADOC,QAAA;AAAA,cAAmB,EAN5B,GAAA,EAAA,CAAA,EAAA;AAAA,cAAA;AAAA,gBAE2BG,kBAAA,CAAA,gUAAA,CAAA;AAAA,gBAAAC,UAAA,CAA6BE,IAA8B,CAAA,MAAA,EAAA,mBAAA,EAAAD,UAAA,CAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA;AAAA,kBAAA,KAAA;;;;AAMtF,cAAA,IAAA;AAAA;AAAA,aAAA,KAAAT,SAAA,EAcO,EAAAG,kBAAA;AAAA,cAAAC,QAAA;AAAA,cARP,EA1CN,GAAA,EAAA,CAAA,EAAA;AAAA,cAAA;AAAA,gBA4CiCG,kBAAA,CAAA,+TAAA,CAAA;AAAA,gBAAAC,UAAA,CAA6BE,wBAAuBD,UAAO,CAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA;AAAA,kBAAA,KAAA;AA5C5F,kBAAA,eAAA,EAAA,IAAA,CAAA,sBAAA,CAgDO,OACa,CAAA,IAAA,EAAA;AAAA,iBAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;AAjDpB,SAAA,CAAA;AAAA,QAAA,GAAA;AAAA;AAAA,OAAA;AAAA,KAAA,CAAA;AAAA,IAAA,CAAA,EAAA,CAAA;AAAA;AAAA,GAAA,CAAA,IAAAF,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"facets.vue.js","sources":["../../../../../../src/x-modules/facets/components/facets/facets.vue"],"sourcesContent":["<template>\n <component :is=\"animation\" v-if=\"hasFacets\" class=\"x-facets-list\" data-test=\"facets\" tag=\"ul\">\n <li\n v-for=\"({ facet, slotNameById, slotNameByModelName }, facetId) in mappedFacets\"\n :key=\"facetId\"\n class=\"x-facets-list__item\"\n data-test=\"facets-facet\"\n >\n <!--\n @slot Customized Facet rendering. Specifying a slot with the facet's name will result in the\n facet using that slot composition to render.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-if=\"hasSlot(slotNameById)\"\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n :name=\"slotNameById\"\n />\n <!--\n @slot Customized Facet rendering. Specifying a slot with the facet's modelName will result\n in the facet using that slot composition to render.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-else-if=\"hasSlot(slotNameByModelName)\"\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n :name=\"slotNameByModelName\"\n />\n <!--\n @slot (required) Default Facet rendering. This slot will be used by default for rendering\n the facets without an specific slot implementation.\n @binding {Facet} facet - Facet to render\n @binding {Filter[]} selectedFilters - List of selected filters of the given facet\n -->\n <slot\n v-else\n v-bind=\"{\n facet,\n selectedFilters: selectedFiltersByFacet[facetId] || []\n }\"\n >\n This is the {{ facet.label }} facet. Pass something into its slot to display content.\n </slot>\n </li>\n </component>\n</template>\n\n<script lang=\"ts\">\n import { Facet } from '@empathyco/x-types';\n import { Dictionary, map, objectFilter } from '@empathyco/x-utils';\n import { computed, ComputedRef, defineComponent, PropType } from 'vue';\n import { useGetter } from '../../../../composables/use-getter';\n import { toKebabCase } from '../../../../utils/string';\n import { useFacets } from '../../composables/use-facets';\n import { facetsXModule } from '../../x-module';\n import { AnimationProp } from '../../../../types';\n\n /**\n * Custom interface to provide a slot name to a Facet.\n *\n * @internal\n */\n interface RenderFacet {\n slotNameById: string;\n slotNameByModelName: string;\n facet: Facet;\n }\n\n /**\n * This component renders the list of facets stored in the Facets module. Facets can be rendered\n * differently based on their purpose and this can be achieved using the exposed slots:\n * - A default and required slot.\n * - A custom slot for each facet with the facetId as its name. This allows each facet to be\n * rendered differently based on its needs.\n *\n * @public\n */\n export default defineComponent({\n name: 'Facets',\n xModule: facetsXModule.name,\n props: {\n /** Array of facets ids used to get the selected filters for those facets. */\n facetsIds: Array as PropType<Array<Facet['id']>>,\n /** Flag to render the component even if there are no filters selected. */\n alwaysVisible: Boolean,\n /** Animation component that will be used to animate the facets. */\n animation: {\n type: AnimationProp,\n default: 'ul'\n },\n /**\n * Discriminates the facets rendered by this component. It expects a string containing facets\n * ids, comma separated. This property will include or exclude facets based on its value.\n * The default value is an empty string and the component will render all existing facets.\n *\n * @remarks\n * To behave as a `include`, simply set the facets ids, comma separated:\n * `existingFacets=[{ brand: ... }, category: { ... }, color: { ... }, price: { ... }]`\n * `renderableFacets=\"brand, category\"`\n *\n * The component will render brand and category facets.\n *\n * On the other hand, to simulate an `exclude` behaviour and exclude a facet from being\n * rendered, append a '!' before its id:\n * `existingFacets=[{ brand: ... }, category: { ... }, color: { ... }, price: { ... }]`\n * `renderableFacets=\"!brand,!price\"`\n *\n * The component will render category and color facets.\n */\n renderableFacets: String\n },\n setup: function (props, { slots }) {\n const { selectedFiltersByFacet } = useFacets(props);\n\n const { facets } = useGetter('facets', ['facets']) as {\n /** Dictionary of facets in the state. */\n facets: ComputedRef<Record<Facet['id'], Facet>>;\n };\n\n /**\n * The facets to be rendered after filtering {@link Facets.facets} by\n * {@link Facets.renderableFacets} content.\n *\n * @returns The list of facets to be rendered.\n */\n const facetsToRender = computed<Dictionary<Facet>>(() => {\n if (!props.renderableFacets) {\n return facets.value;\n } else {\n const excludedRegExp = /^!/;\n const facetIds: string[] = props.renderableFacets\n .split(',')\n .map(facetId => facetId.trim());\n const included: string[] = [];\n const excluded: string[] = [];\n facetIds.forEach(facetId => {\n if (excludedRegExp.test(facetId)) {\n excluded.push(facetId.replace(excludedRegExp, ''));\n } else {\n included.push(facetId);\n }\n });\n\n return filterFacetsToRender(included, excluded);\n }\n });\n\n /**\n * Transforms a dictionary of Facets including the slot name.\n *\n * @returns A dictionary of facets with the slot name.\n */\n const mappedFacets = computed<Dictionary<RenderFacet>>(() => {\n return map(facetsToRender.value, (facetId, facet) => ({\n slotNameById: toKebabCase(facetId),\n slotNameByModelName: toKebabCase(facet.modelName),\n facet\n }));\n });\n\n /**\n * Indicates if there are facets available to show.\n *\n * @returns True if there are facets available and false otherwise.\n */\n const hasFacets = computed<boolean>(() => !!Object.keys(facetsToRender.value).length);\n\n /**\n * Filter facets dictionary retrieving those included and/or removing excluded.\n *\n * @param included - List of facets to render.\n * @param excluded - List of not renderable facets.\n *\n * @returns The filtered list of facets to render.\n */\n function filterFacetsToRender(included: string[], excluded: string[]): Dictionary<Facet> {\n const hasAnyFacetIncluded = included.length > 0;\n return objectFilter(facets.value, facetKey => {\n const isIncluded = included.includes(String(facetKey));\n const isExcluded = excluded.includes(String(facetKey));\n\n return hasAnyFacetIncluded ? isIncluded && !isExcluded : !isExcluded;\n });\n }\n\n /**\n * Whether the slot is present in the template or not.\n *\n * @param name - The slot name.\n *\n * @returns True is the slot is present in the template. False otherwise.\n */\n function hasSlot(name: string): boolean {\n return !!slots[name];\n }\n\n return {\n selectedFiltersByFacet,\n hasFacets,\n mappedFacets,\n hasSlot\n };\n }\n });\n</script>\n\n<style lang=\"css\" scoped>\n .x-facets-list {\n display: flex;\n flex-flow: column nowrap;\n list-style-type: none;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Example\n\nThis component renders the list of facets stored in the Facets module. Facets can be rendered\ndifferently based on their purpose and this can be achieved using the exposed slots:\n\n- A default and required slot.\n- A custom slot for each facet with the facetId as its name. This allows each facet to be rendered\n differently based on its needs.\n\nBelow, there are some examples showing how to use the component with its different configurations.\n\n### Default usage\n\nThe default slot of this component is mandatory. If no other slot is defined, every Facet will be\nrendered as specified in the default slot.\n\n```vue\n<template>\n <Facets>\n <template #default=\"{ facet, selectedFilters }\">\n <h1>{{ ${facet.label} }}</h1>\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} selected` }}</span>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Customized usage\n\nCustomized compositions for a specific Facet can be achieved by using a slot with the same id as the\nfacet to customize. For example, the Facet with the id \"color\" requires a composition that differs\nfrom the rest of the Facets. Doing it in a slot with the name \"color\" will apply this customization\njust to the \"color\" Facet. The other facets will fallback to the composition of the default slot.\n\nIt is also possible to customize the Facet content by the facet \"model name\". For example, to\nconfigure different content for \"Hierarchical Facets\" the \"hierarchical-facet\" slot will apply that\ncustomization. This can be combined with the facets by facet id. If some hierarchical facet needs\nsome different customization from the rest of the hierarchical, it can be achieve using the slot\nwith the facet id.\n\n```vue\n<template>\n <Facets>\n <template #color=\"{ facet, selectedFilters }\">\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} colors chosen` }}</span>\n\n <ul v-for=\"filter in facet.filters\" :key=\"filter.id\">\n <li v-if=\"!filter.selected\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n\n <template #hierarchical-facet=\"{ facet, selectedFilters }\">\n <span v-if=\"selectedFilters.length > 0\">{{ `${selectedFilters.length} colors chosen` }}</span>\n\n <ul v-for=\"filter in facet.filters\" :key=\"filter.id\">\n <li v-if=\"!filter.selected\">\n {{ filter.label }}\n <ul v-for=\"childFilter in filter.children\" :key=\"filter.id\">\n <li v-if=\"!childFilter.selected\">\n {{ childFilter.label }}\n </li>\n </ul>\n </li>\n </ul>\n </template>\n\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Render specific facets I\n\nBy default, this component will render all existing facets. However, it has the renderableFacets\nprop to filter which facets will be rendered. Its value is a string containing the different facets\nids. This value is treated as an include or exclude list (to exclude a facet from being rendered,\njust prefix its id with a `!`). The component will only render included facets and discard excluded\nones. In the following example, the component will only render color and category facets.\n\n```vue\n<template>\n <Facets renderableFacets=\"color, category\">\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Render specific facets II\n\nExclude facets so the component does not render them. In the following example, the component will\nrender every facet except color and price.\n\n```vue\n<template>\n <Facets renderableFacets=\"!color, !price\">\n <template #default=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n\n <ul>\n <li v-for=\"filter in facet.filters\" :key=\"filter.id\">\n {{ filter.label }}\n </li>\n </ul>\n </template>\n </Facets>\n</template>\n\n<script>\n import { Facets } from '@empathyco/x-components/facets';\n\n export default {\n components: {\n Facets\n }\n };\n</script>\n```\n\n### Integrating with the filters components\n\nThere are many components that will help you build your own awesome filters list. `Facets` just\nrenders the list, but what to render for each facet is up to you. Below you can see an example. of\nthe `Facets` component using the `FiltersSearch` `MultiSelectFilters`, `SimpleFilter`, `Filters`,\n`HierarchicalFilter`, `NumberRangeFilter` and `BasePriceFilterLabel`.\n\n```vue\n<template>\n <Facets>\n <template #default=\"{ facet, selectedFilters }\">\n <h1>{{ facet.label }}</h1>\n <FiltersSearch :filters=\"facet.filters\">\n <MultiSelectFilters v-slot=\"{ filter }\">\n <SimpleFilter :filter=\"filter\" />\n </MultiSelectFilters>\n </FiltersSearch>\n </template>\n\n <template #category=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n <Filters v-slot=\"{ filter }\" :filters=\"facet.filters\">\n <HierarchicalFilter :filter=\"filter\" />\n </Filters>\n </template>\n\n <template #price=\"{ facet }\">\n <h1>{{ facet.label }}</h1>\n <Filters v-slot=\"{ filter }\" :filters=\"facet.filters\">\n <NumberRangeFilter :filter=\"filter\">\n <BasePriceFilterLabel :filter=\"filter\" />\n </NumberRangeFilter>\n </Filters>\n </template>\n </Facets>\n</template>\n\n<script>\n import {\n Facets,\n Filters,\n FiltersSearch,\n HierarchicalFilter,\n MultiSelectFilters,\n NumberRangeFilter,\n SimpleFilter\n } from '@empathyco/x-components/facets';\n\n import { BasePriceFilterLabel } from '@empathyco/x-components';\n\n export default {\n components: {\n Facets,\n MultiSelectFilters,\n FiltersSearch,\n SimpleFilter,\n Filters,\n HierarchicalFilter,\n NumberRangeFilter,\n BasePriceFilterLabel\n }\n };\n</script>\n```\n</docs>\n"],"names":["animation","_openBlock","_createBlock","_resolveDynamicComponent","_createElementBlock","_Fragment","_renderList","_renderSlot","_mergeProps","hasSlot","_createCommentVNode"],"mappings":";;;;;AACE,SAAA,WAAA,CAAA,IAAA,EAAA,MAAA,EADF,MACkBA,EAAAA,MAAAA,EAAAA,KAAAA,EAAAA,QAAAA,EAAAA;AADlB,EAAA,OAAA,IAAA,CAAA,SAAA,IAAAC,SAAA,EACmE,EAAAC,WAAA,CAAAC,uBAAA,CAAA,IAAA,CAAA,SAAA,CAAA,EAAA;AAAA,IAAC,GAAA,EAAA,CAAA;AAAA,IAAmB,KAAI,EAAA,eAAA;AAAA,IAAA,WAAA,EAAA,QAAA;AAD3F,IAAA,GAAA,EAAA,IAAA;AAAA,GAAA,EAAA;;iBAIY,IAAO,CAAA,EAAAC,kBAAA;AAAA,QAAAC,QAAA;AAAA,QAAA,IAAA;AAAA,QAAAC,UAAA,CAAA,IAAA,CAAA,YAAA,EAAA,CAAA,EAAA,KAAA,EAAA,YAAA,EAAA,mBAAA,EAAA,EAAA,OAAA,KAAA;AACR,UAAA,OAAAL,SAAA,EAAsB,EAAAG,kBAAA,CAAA,IAAA,EAAA;AAAA,YAC3B,GAAA,EAAA,OAAA;AAAA,YAAA,KAAA,EAAA,qBAAA;AASe,YAAA,WAAA,EAAA,cAAA;AAAA,WAAA,EAAA;AAfrB,YAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,GAAAG,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,YAAA,EAAAC,UAAA,CAAA;AAAA,cAAA,GAAA,EAAA,CAAA;AAgBiC,cAAA,OAAA,EAAA,IAAA;AAAA,aAAA,EAAA;;AAadC,cAAAA,eAAAA,EAAAA,IAAAA,CAAQ,sBAAmB,CAAA,OAAA,CAAA,IAAA,EAAA;AAAA,aAAA,CAAA,EAAA,KAAA,CAAA,EADxC,IA5BN,CAAA,GAAA,IAAA,CAAA,OAAA,CAAA,mBAAA,CAAA,GAAAF,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,mBAAA,EAAAC,UAAA,CAAA;AAAA,cAAA,GAAA,EAAA,CAAA;AA8BiC,cAAA,OAAA,EAAA,IAAA;AAAA,aAAA,EAAA;;AAY3B,cAAA,eAAA,EAAA,IAAA,CAQO,8BARP,CAQO,IAAA,EAAA;AAAA,aAlDb,CAAA,EAAA,KAAA,CAAA,EAAA,IAAA,CAAA,GAAAD,UAAA,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAAC,UAAA,CAAA;AAAA,cAAA,GAAA,EAAA,CAAA;AA4CiC,cAAA,OAAA,EAAA,IAAA;AAAA,aAAA,EAAA;;+BA5CjC,IAiDoB,CAAA,sBAAA,CAAA,OAAA,CAAA,IAAA,EAAA;AAAA,aAAA,CAAA,EAAA,MAAA;;;;;;;;AAjDpB,SAAA,CAAA;AAAA,QAAA,GAAA;AAAA;AAAA,OAAA;AAAA,KAAA,CAAA;AAAA,IAAA,CAAA,EAAA,CAAA;AAAA;AAAA,GAAA,CAAA,IAAAE,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA,CAAA;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _sfc_main from './all-filter.vue2.js';
|
|
2
|
-
import { resolveComponent, openBlock, createBlock, normalizeClass, withCtx,
|
|
2
|
+
import { resolveComponent, openBlock, createBlock, normalizeClass, withCtx, renderSlot, createTextVNode } from 'vue';
|
|
3
3
|
import _export_sfc from '../../../../_virtual/_plugin-vue_export-helper.js';
|
|
4
4
|
|
|
5
5
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
@@ -12,7 +12,6 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
12
12
|
events: _ctx.clickEvent
|
|
13
13
|
}, {
|
|
14
14
|
default: withCtx(() => [
|
|
15
|
-
createCommentVNode("\n @slot The content to render inside the button\n @binding {Facet} Facet - The facet data\n "),
|
|
16
15
|
renderSlot(_ctx.$slots, "default", {
|
|
17
16
|
facet: _ctx.facet,
|
|
18
17
|
isSelected: _ctx.isSelected
|