@empathyco/x-components 6.0.0-alpha.203 → 6.0.0-alpha.205

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/docs/API-reference/api/x-components.addquerytohistory.md +15 -1
  3. package/docs/API-reference/api/x-components.addquerytohistoryaction.addquerytohistory.md +15 -1
  4. package/docs/API-reference/api/x-components.addquerytohistoryaction.md +1 -1
  5. package/docs/API-reference/api/x-components.basedropdown.md +1 -1
  6. package/docs/API-reference/api/x-components.baseidmodal.md +1 -1
  7. package/docs/API-reference/api/x-components.baseresultimage.md +1 -1
  8. package/docs/API-reference/api/x-components.collapseheight.md +3 -3
  9. package/docs/API-reference/api/x-components.collapsewidth.md +3 -3
  10. package/docs/API-reference/api/x-components.createfetchandsaveactions.md +15 -1
  11. package/docs/API-reference/api/x-components.createrelatedtagsquerygetter.md +15 -1
  12. package/docs/API-reference/api/x-components.debouncefunction.md +17 -1
  13. package/docs/API-reference/api/x-components.defaultfacetsservice.clearfilterswithmetadata.md +17 -1
  14. package/docs/API-reference/api/x-components.defaultfacetsservice.md +1 -1
  15. package/docs/API-reference/api/x-components.historyqueriesgetter.historyqueries.md +15 -1
  16. package/docs/API-reference/api/x-components.historyqueriesgetter.md +1 -1
  17. package/docs/API-reference/api/x-components.isinrange.md +15 -1
  18. package/docs/API-reference/api/x-components.md +10 -10
  19. package/docs/API-reference/api/x-components.querysuggestionsgetter.md +1 -1
  20. package/docs/API-reference/api/x-components.querysuggestionsgetter.querysuggestions.md +15 -1
  21. package/docs/API-reference/api/x-components.usecollapseanimation.md +4 -4
  22. package/docs/API-reference/api/x-components.useemitdisplayevent.md +15 -1
  23. package/docs/API-reference/api/x-components.useondisplay.md +15 -1
  24. package/docs/API-reference/api/x-components.usescroll.md +15 -1
  25. package/docs/API-reference/api/x-types.suggestion.key.md +1 -1
  26. package/docs/API-reference/api/x-types.suggestion.md +4 -4
  27. package/js/components/animations/animate-scale/animate-scale.style.css.js +1 -1
  28. package/js/components/animations/use-collapse-animation.js +9 -0
  29. package/js/components/animations/use-collapse-animation.js.map +1 -1
  30. package/js/components/base-dropdown.vue.js +3 -3
  31. package/js/components/base-dropdown.vue.js.map +1 -1
  32. package/js/components/base-dropdown.vue2.js +6 -4
  33. package/js/components/base-dropdown.vue2.js.map +1 -1
  34. package/js/components/base-grid.vue.js.map +1 -1
  35. package/js/components/base-grid.vue2.js.map +1 -1
  36. package/js/components/base-rating.vue3.js +1 -1
  37. package/js/components/column-picker/base-column-picker-list.vue.js.map +1 -1
  38. package/js/components/column-picker/base-column-picker-list.vue2.js.map +1 -1
  39. package/js/components/modals/base-id-modal.vue.js +1 -1
  40. package/js/components/modals/base-id-modal.vue.js.map +1 -1
  41. package/js/components/modals/base-id-modal.vue2.js +3 -3
  42. package/js/components/modals/base-id-modal.vue2.js.map +1 -1
  43. package/js/components/panels/base-tabs-panel.vue.js +1 -1
  44. package/js/components/panels/base-tabs-panel.vue.js.map +1 -1
  45. package/js/components/panels/base-tabs-panel.vue2.js.map +1 -1
  46. package/js/components/result/base-result-current-price.vue.js +4 -3
  47. package/js/components/result/base-result-current-price.vue.js.map +1 -1
  48. package/js/components/result/base-result-current-price.vue2.js.map +1 -1
  49. package/js/components/result/base-result-image.vue.js.map +1 -1
  50. package/js/components/result/base-result-image.vue2.js +2 -1
  51. package/js/components/result/base-result-image.vue2.js.map +1 -1
  52. package/js/components/result/base-result-previous-price.vue.js +1 -1
  53. package/js/components/result/base-result-previous-price.vue.js.map +1 -1
  54. package/js/components/result/base-result-previous-price.vue2.js.map +1 -1
  55. package/js/components/sliding-panel.vue3.js +1 -1
  56. package/js/x-modules/facets/components/facets/facets.vue.js.map +1 -1
  57. package/js/x-modules/facets/components/facets/facets.vue2.js.map +1 -1
  58. package/js/x-modules/facets/components/filters/editable-number-range-filter.vue.js +2 -2
  59. package/js/x-modules/facets/components/filters/editable-number-range-filter.vue.js.map +1 -1
  60. package/js/x-modules/facets/components/filters/editable-number-range-filter.vue2.js.map +1 -1
  61. package/js/x-modules/facets/components/lists/filters-search.vue.js +1 -1
  62. package/js/x-modules/facets/components/lists/filters-search.vue.js.map +1 -1
  63. package/js/x-modules/facets/components/lists/filters-search.vue2.js.map +1 -1
  64. package/js/x-modules/facets/components/lists/filters-search.vue3.js +1 -1
  65. package/js/x-modules/facets/components/lists/selected-filters-list.vue.js.map +1 -1
  66. package/js/x-modules/facets/components/lists/selected-filters-list.vue2.js.map +1 -1
  67. package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue.js.map +1 -1
  68. package/js/x-modules/related-prompts/components/related-prompts-tag-list.vue2.js.map +1 -1
  69. package/js/x-modules/search/components/sort-picker-list.vue.js.map +1 -1
  70. package/js/x-modules/search/components/sort-picker-list.vue2.js.map +1 -1
  71. package/package.json +18 -18
  72. package/report/tsdoc-metadata.json +1 -1
  73. package/report/x-adapter-platform.api.json +1 -1
  74. package/report/x-components.api.json +161 -67
  75. package/report/x-components.api.md +46 -45
  76. package/report/x-types.api.json +4 -4
  77. package/types/components/animations/collapse-height.vue.d.ts +3 -3
  78. package/types/components/animations/collapse-width.vue.d.ts +3 -3
  79. package/types/components/animations/use-collapse-animation.d.ts +3 -3
  80. package/types/components/animations/use-collapse-animation.d.ts.map +1 -1
  81. package/types/components/base-dropdown.vue.d.ts +1 -1
  82. package/types/components/base-dropdown.vue.d.ts.map +1 -1
  83. package/types/components/base-grid.types.d.ts +11 -0
  84. package/types/components/base-grid.types.d.ts.map +1 -0
  85. package/types/components/base-grid.vue.d.ts +2 -10
  86. package/types/components/base-grid.vue.d.ts.map +1 -1
  87. package/types/components/column-picker/base-column-picker-list.types.d.ts +9 -0
  88. package/types/components/column-picker/base-column-picker-list.types.d.ts.map +1 -0
  89. package/types/components/column-picker/base-column-picker-list.vue.d.ts +1 -8
  90. package/types/components/column-picker/base-column-picker-list.vue.d.ts.map +1 -1
  91. package/types/components/modals/base-id-modal.vue.d.ts +1 -1
  92. package/types/components/result/base-result-image.vue.d.ts +1 -1
  93. package/types/components/result/base-result-image.vue.d.ts.map +1 -1
  94. package/types/x-modules/facets/components/facets/facets.types.d.ts +12 -0
  95. package/types/x-modules/facets/components/facets/facets.types.d.ts.map +1 -0
  96. package/types/x-modules/facets/components/facets/facets.vue.d.ts +1 -10
  97. package/types/x-modules/facets/components/facets/facets.vue.d.ts.map +1 -1
  98. package/types/x-modules/facets/components/lists/selected-filters-list.types.d.ts +11 -0
  99. package/types/x-modules/facets/components/lists/selected-filters-list.types.d.ts.map +1 -0
  100. package/types/x-modules/facets/components/lists/selected-filters-list.vue.d.ts +1 -9
  101. package/types/x-modules/facets/components/lists/selected-filters-list.vue.d.ts.map +1 -1
  102. package/types/x-modules/search/components/sort-picker-list.types.d.ts +12 -0
  103. package/types/x-modules/search/components/sort-picker-list.types.d.ts.map +1 -0
  104. package/types/x-modules/search/components/sort-picker-list.vue.d.ts +1 -10
  105. package/types/x-modules/search/components/sort-picker-list.vue.d.ts.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"base-column-picker-list.vue2.js","sources":["../../../../src/components/column-picker/base-column-picker-list.vue"],"sourcesContent":["<template>\n <div class=\"x-column-picker-list x-button-group\" data-test=\"column-picker-list\" role=\"list\">\n <template\n v-for=\"({ column, cssClasses, events, isSelected }, index) in columnsWithCssClasses\"\n :key=\"column\"\n >\n <BaseEventButton\n class=\"x-column-picker-list__button x-button\"\n :class=\"[buttonClass, cssClasses]\"\n data-test=\"column-picker-button\"\n :aria-pressed=\"isSelected.toString()\"\n :events=\"events\"\n :aria-label=\"`${column} columns`\"\n role=\"listitem\"\n >\n <!--\n @slot Customized Column Picker Button content. Specifying a slot with the column value\n will result in the column using that slot composition to render.\n @binding {number} column - Columns Number to pick.\n @binding {boolean} isSelected - True if the columns number are the chosen value.\n -->\n <slot v-bind=\"{ column, isSelected }\">\n {{ column }}\n </slot>\n </BaseEventButton>\n\n <!--\n @slot Customized Column Picker divider. Specify an element to act as divider for\n the items in the column picker. Empty by default.\n -->\n <slot v-if=\"index !== columnsWithCssClasses.length - 1\" name=\"divider\"></slot>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../../utils/types'\nimport type { XEventsTypes } from '../../wiring'\nimport { computed, defineComponent, onBeforeMount, ref, watch } from 'vue'\nimport { use$x } from '../../composables/use-$x'\nimport BaseEventButton from '../base-event-button.vue'\n\ninterface ColumnPickerItem {\n column: number\n cssClasses: VueCSSClasses\n events: Partial<XEventsTypes>\n isSelected: boolean\n}\n\n/**\n * Column picker list component renders a list of buttons to choose the columns number.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseColumnPickerList',\n components: { BaseEventButton },\n props: {\n /** An array of numbers that represents the number of columns to render. */\n columns: {\n type: Array as PropType<number[]>,\n required: true,\n },\n /** The value of the selected columns number. */\n modelValue: Number,\n /** Class inherited by each button. */\n buttonClass: String,\n },\n emits: ['update:modelValue'],\n setup(props, { emit }) {\n const $x = use$x()\n\n const providedSelectedColumns = computed(() => props.modelValue ?? props.columns[0])\n const selectedColumns = ref(providedSelectedColumns.value)\n\n /**\n * Assigns `selectedColumns` value and emits `ColumnsNumberProvided`.\n *\n * @param column - Column number provided.\n */\n function emitColumnsNumberProvided(column: number) {\n selectedColumns.value = column\n $x.emit('ColumnsNumberProvided', column)\n }\n\n /**\n * Emits `update:modelValue` with the column selected.\n *\n * @param column - Column number selected.\n */\n function emitUpdateModelValue(column: number) {\n if (props.modelValue !== column) {\n emit('update:modelValue', column)\n }\n }\n\n watch(providedSelectedColumns, emitColumnsNumberProvided)\n watch(selectedColumns, emitUpdateModelValue)\n\n $x.on('ColumnsNumberProvided', false).subscribe(column => (selectedColumns.value = column))\n\n /**\n * Synchronizes the columns number before mounting the component. If the real number of selected\n * columns equals the provided columns, it emits the event to sync it with every other component.\n * If it is not equal it means that the user has already selected a number of columns, so we emit\n * a `update:modelValue` event so developers can sync the provided value.\n */\n onBeforeMount(() => {\n if (selectedColumns.value === providedSelectedColumns.value) {\n emitColumnsNumberProvided(selectedColumns.value)\n } else {\n emitUpdateModelValue(selectedColumns.value)\n }\n })\n\n /**\n * Maps the column to an object containing: the `column` and `CSS classes`.\n *\n * @returns An array of objects containing the column number and CSS classes.\n */\n const columnsWithCssClasses = computed<ColumnPickerItem[]>(() =>\n props.columns.map(column => ({\n column,\n cssClasses: [\n `x-column-picker-list__button--${column}-cols`,\n { 'x-selected': selectedColumns.value === column },\n ],\n isSelected: selectedColumns.value === column,\n events: {\n UserClickedColumnPicker: column,\n ColumnsNumberProvided: column,\n },\n })),\n )\n\n return { columnsWithCssClasses }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\nThis component renders a list of elements in different slots depending on the columns prop. Each\nbutton emits the needed events to sync other instances of column pickers or grids with the\nnumber of columns being selected when clicked.\n\n### Default usage\n\nIt is required to send the columns prop.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n### Using v-model\n\nIt is possible to do two-way binding in order to synchronize the value with the parent. It will be\nupdated if the value changes or if the parent changes it.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" v-model=\"selectedColumns\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\nconst selectedColumns = ref(4)\n</script>\n```\n\n### Customized usage\n\n#### Overriding the slots\n\nIt is possible to override the column picker button content.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\">\n <template #default=\"{ column, isSelected }\">\n <span>{{ column }} {{ isSelected ? '🟢' : '' }}</span>\n </template>\n </BaseColumnPickerList>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\nIt is also possible to add a divider element between the column picker buttons by overriding the\n`divider` slot.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\">\n <template #divider>\n <ChevronRightIcon aria-hidden=\"true\" />\n </template>\n </BaseColumnPickerList>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\nimport ChevronRightIcon from '@empathyco/x-components/js/components/icons/chevron-right.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n#### Customizing the buttons with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" buttonClass=\"x-button--round\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedColumnPicker`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks an item. The event payload is the number of columns\n that the clicked item represents.\n- [`ColumnsNumberProvided`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted on component mount. The event payload is the current `selectedColumns` value.\n</docs>\n"],"names":[],"mappings":";;;;AAkDA;;;;;;;AAOE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,sBAAsB;IAC5B,UAAU,EAAE,EAAE,eAAc,EAAG;AAC/B,IAAA,KAAK,EAAE;;AAEL,QAAA,OAAO,EAAE;AACP,YAAA,IAAI,EAAE,KAA2B;AACjC,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;;AAED,QAAA,UAAU,EAAE,MAAM;;AAElB,QAAA,WAAW,EAAE,MAAM;AACpB,KAAA;IACD,KAAK,EAAE,CAAC,mBAAmB,CAAC;AAC5B,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,IAAG,EAAG,EAAA;AACnB,QAAA,MAAM,EAAC,GAAI,KAAK,EAAC;AAEjB,QAAA,MAAM,uBAAsB,GAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,UAAS,IAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACnF,MAAM,eAAc,GAAI,GAAG,CAAC,uBAAuB,CAAC,KAAK,CAAA;AAEzD;;;;AAIE;QACF,SAAS,yBAAyB,CAAC,MAAc,EAAA;AAC/C,YAAA,eAAe,CAAC,KAAI,GAAI,MAAK;AAC7B,YAAA,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,CAAA;QACzC;AAEA;;;;AAIE;QACF,SAAS,oBAAoB,CAAC,MAAc,EAAA;AAC1C,YAAA,IAAI,KAAK,CAAC,UAAS,KAAM,MAAM,EAAE;AAC/B,gBAAA,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAA;YAClC;QACF;AAEA,QAAA,KAAK,CAAC,uBAAuB,EAAE,yBAAyB,CAAA;AACxD,QAAA,KAAK,CAAC,eAAe,EAAE,oBAAoB,CAAA;QAE3C,EAAE,CAAC,EAAE,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,MAAK,KAAM,eAAe,CAAC,KAAI,GAAI,MAAM,CAAC,CAAA;AAE1F;;;;;AAKE;QACF,aAAa,CAAC,MAAI;YAChB,IAAI,eAAe,CAAC,KAAI,KAAM,uBAAuB,CAAC,KAAK,EAAE;AAC3D,gBAAA,yBAAyB,CAAC,eAAe,CAAC,KAAK,CAAA;YACjD;iBAAO;AACL,gBAAA,oBAAoB,CAAC,eAAe,CAAC,KAAK,CAAA;YAC5C;AACF,QAAA,CAAC,CAAA;AAED;;;;AAIE;AACF,QAAA,MAAM,qBAAoB,GAAI,QAAQ,CAAqB,MACzD,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAK,KAAM;YAC3B,MAAM;AACN,YAAA,UAAU,EAAE;AACV,gBAAA,CAAA,8BAAA,EAAiC,MAAM,CAAA,KAAA,CAAO;AAC9C,gBAAA,EAAE,YAAY,EAAE,eAAe,CAAC,UAAU,QAAQ;AACnD,aAAA;AACD,YAAA,UAAU,EAAE,eAAe,CAAC,KAAI,KAAM,MAAM;AAC5C,YAAA,MAAM,EAAE;AACN,gBAAA,uBAAuB,EAAE,MAAM;AAC/B,gBAAA,qBAAqB,EAAE,MAAM;AAC9B,aAAA;SACF,CAAC,CAAC,CACL;QAEA,OAAO,EAAE,qBAAoB,EAAE;IACjC,CAAC;AACF,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"base-column-picker-list.vue2.js","sources":["../../../../src/components/column-picker/base-column-picker-list.vue"],"sourcesContent":["<template>\n <div class=\"x-column-picker-list x-button-group\" data-test=\"column-picker-list\" role=\"list\">\n <template\n v-for=\"({ column, cssClasses, events, isSelected }, index) in columnsWithCssClasses\"\n :key=\"column\"\n >\n <BaseEventButton\n class=\"x-column-picker-list__button x-button\"\n :class=\"[buttonClass, cssClasses]\"\n data-test=\"column-picker-button\"\n :aria-pressed=\"isSelected.toString()\"\n :events=\"events\"\n :aria-label=\"`${column} columns`\"\n role=\"listitem\"\n >\n <!--\n @slot Customized Column Picker Button content. Specifying a slot with the column value\n will result in the column using that slot composition to render.\n @binding {number} column - Columns Number to pick.\n @binding {boolean} isSelected - True if the columns number are the chosen value.\n -->\n <slot v-bind=\"{ column, isSelected }\">\n {{ column }}\n </slot>\n </BaseEventButton>\n\n <!--\n @slot Customized Column Picker divider. Specify an element to act as divider for\n the items in the column picker. Empty by default.\n -->\n <slot v-if=\"index !== columnsWithCssClasses.length - 1\" name=\"divider\"></slot>\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport type { ColumnPickerItem } from './base-column-picker-list.types'\nimport { computed, defineComponent, onBeforeMount, ref, watch } from 'vue'\nimport { use$x } from '../../composables/use-$x'\nimport BaseEventButton from '../base-event-button.vue'\n\n/**\n * Column picker list component renders a list of buttons to choose the columns number.\n *\n * Additionally, this component exposes the following props to modify the classes of the\n * elements: `buttonClass`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseColumnPickerList',\n components: { BaseEventButton },\n props: {\n /** An array of numbers that represents the number of columns to render. */\n columns: {\n type: Array as PropType<number[]>,\n required: true,\n },\n /** The value of the selected columns number. */\n modelValue: Number,\n /** Class inherited by each button. */\n buttonClass: String,\n },\n emits: ['update:modelValue'],\n setup(props, { emit }) {\n const $x = use$x()\n\n const providedSelectedColumns = computed(() => props.modelValue ?? props.columns[0])\n const selectedColumns = ref(providedSelectedColumns.value)\n\n /**\n * Assigns `selectedColumns` value and emits `ColumnsNumberProvided`.\n *\n * @param column - Column number provided.\n */\n function emitColumnsNumberProvided(column: number) {\n selectedColumns.value = column\n $x.emit('ColumnsNumberProvided', column)\n }\n\n /**\n * Emits `update:modelValue` with the column selected.\n *\n * @param column - Column number selected.\n */\n function emitUpdateModelValue(column: number) {\n if (props.modelValue !== column) {\n emit('update:modelValue', column)\n }\n }\n\n watch(providedSelectedColumns, emitColumnsNumberProvided)\n watch(selectedColumns, emitUpdateModelValue)\n\n $x.on('ColumnsNumberProvided', false).subscribe(column => (selectedColumns.value = column))\n\n /**\n * Synchronizes the columns number before mounting the component. If the real number of selected\n * columns equals the provided columns, it emits the event to sync it with every other component.\n * If it is not equal it means that the user has already selected a number of columns, so we emit\n * a `update:modelValue` event so developers can sync the provided value.\n */\n onBeforeMount(() => {\n if (selectedColumns.value === providedSelectedColumns.value) {\n emitColumnsNumberProvided(selectedColumns.value)\n } else {\n emitUpdateModelValue(selectedColumns.value)\n }\n })\n\n /**\n * Maps the column to an object containing: the `column` and `CSS classes`.\n *\n * @returns An array of objects containing the column number and CSS classes.\n */\n const columnsWithCssClasses = computed<ColumnPickerItem[]>(() =>\n props.columns.map(column => ({\n column,\n cssClasses: [\n `x-column-picker-list__button--${column}-cols`,\n { 'x-selected': selectedColumns.value === column },\n ],\n isSelected: selectedColumns.value === column,\n events: {\n UserClickedColumnPicker: column,\n ColumnsNumberProvided: column,\n },\n })),\n )\n\n return { columnsWithCssClasses }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\nThis component renders a list of elements in different slots depending on the columns prop. Each\nbutton emits the needed events to sync other instances of column pickers or grids with the\nnumber of columns being selected when clicked.\n\n### Default usage\n\nIt is required to send the columns prop.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n### Using v-model\n\nIt is possible to do two-way binding in order to synchronize the value with the parent. It will be\nupdated if the value changes or if the parent changes it.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" v-model=\"selectedColumns\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\nconst selectedColumns = ref(4)\n</script>\n```\n\n### Customized usage\n\n#### Overriding the slots\n\nIt is possible to override the column picker button content.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\">\n <template #default=\"{ column, isSelected }\">\n <span>{{ column }} {{ isSelected ? '🟢' : '' }}</span>\n </template>\n </BaseColumnPickerList>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\nIt is also possible to add a divider element between the column picker buttons by overriding the\n`divider` slot.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\">\n <template #divider>\n <ChevronRightIcon aria-hidden=\"true\" />\n </template>\n </BaseColumnPickerList>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\nimport ChevronRightIcon from '@empathyco/x-components/js/components/icons/chevron-right.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n#### Customizing the buttons with classes\n\nThe `buttonClass` prop can be used to add classes to the buttons.\n\n```vue live\n<template>\n <BaseColumnPickerList :columns=\"columns\" buttonClass=\"x-button--round\" />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport BaseColumnPickerList from '@empathyco/x-components/js/components/column-picker/base-column-picker-list.vue'\n\nconst columns = ref([2, 4, 6])\n</script>\n```\n\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedColumnPicker`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks an item. The event payload is the number of columns\n that the clicked item represents.\n- [`ColumnsNumberProvided`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted on component mount. The event payload is the current `selectedColumns` value.\n</docs>\n"],"names":[],"mappings":";;;;AA0CA;;;;;;;AAOE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,sBAAsB;IAC5B,UAAU,EAAE,EAAE,eAAc,EAAG;AAC/B,IAAA,KAAK,EAAE;;AAEL,QAAA,OAAO,EAAE;AACP,YAAA,IAAI,EAAE,KAA2B;AACjC,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;;AAED,QAAA,UAAU,EAAE,MAAM;;AAElB,QAAA,WAAW,EAAE,MAAM;AACpB,KAAA;IACD,KAAK,EAAE,CAAC,mBAAmB,CAAC;AAC5B,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,IAAG,EAAG,EAAA;AACnB,QAAA,MAAM,EAAC,GAAI,KAAK,EAAC;AAEjB,QAAA,MAAM,uBAAsB,GAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,UAAS,IAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACnF,MAAM,eAAc,GAAI,GAAG,CAAC,uBAAuB,CAAC,KAAK,CAAA;AAEzD;;;;AAIE;QACF,SAAS,yBAAyB,CAAC,MAAc,EAAA;AAC/C,YAAA,eAAe,CAAC,KAAI,GAAI,MAAK;AAC7B,YAAA,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,CAAA;QACzC;AAEA;;;;AAIE;QACF,SAAS,oBAAoB,CAAC,MAAc,EAAA;AAC1C,YAAA,IAAI,KAAK,CAAC,UAAS,KAAM,MAAM,EAAE;AAC/B,gBAAA,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAA;YAClC;QACF;AAEA,QAAA,KAAK,CAAC,uBAAuB,EAAE,yBAAyB,CAAA;AACxD,QAAA,KAAK,CAAC,eAAe,EAAE,oBAAoB,CAAA;QAE3C,EAAE,CAAC,EAAE,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,MAAK,KAAM,eAAe,CAAC,KAAI,GAAI,MAAM,CAAC,CAAA;AAE1F;;;;;AAKE;QACF,aAAa,CAAC,MAAI;YAChB,IAAI,eAAe,CAAC,KAAI,KAAM,uBAAuB,CAAC,KAAK,EAAE;AAC3D,gBAAA,yBAAyB,CAAC,eAAe,CAAC,KAAK,CAAA;YACjD;iBAAO;AACL,gBAAA,oBAAoB,CAAC,eAAe,CAAC,KAAK,CAAA;YAC5C;AACF,QAAA,CAAC,CAAA;AAED;;;;AAIE;AACF,QAAA,MAAM,qBAAoB,GAAI,QAAQ,CAAqB,MACzD,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAK,KAAM;YAC3B,MAAM;AACN,YAAA,UAAU,EAAE;AACV,gBAAA,CAAA,8BAAA,EAAiC,MAAM,CAAA,KAAA,CAAO;AAC9C,gBAAA,EAAE,YAAY,EAAE,eAAe,CAAC,UAAU,QAAQ;AACnD,aAAA;AACD,YAAA,UAAU,EAAE,eAAe,CAAC,KAAI,KAAM,MAAM;AAC5C,YAAA,MAAM,EAAE;AACN,gBAAA,uBAAuB,EAAE,MAAM;AAC/B,gBAAA,qBAAqB,EAAE,MAAM;AAC9B,aAAA;SACF,CAAC,CAAC,CACL;QAEA,OAAO,EAAE,qBAAoB,EAAE;IACjC,CAAC;AACF,CAAA,CAAA;;;;"}
@@ -5,7 +5,7 @@ import _export_sfc from '../../_virtual/_plugin-vue_export-helper.js';
5
5
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
6
6
  const _component_BaseModal = resolveComponent("BaseModal");
7
7
  return openBlock(), createBlock(_component_BaseModal, {
8
- ref: _ctx.el,
8
+ ref: "modal",
9
9
  animation: _ctx.animation,
10
10
  open: _ctx.isOpen,
11
11
  "onClick:overlay": _ctx.emitClickOutOfModal,
@@ -1 +1 @@
1
- {"version":3,"file":"base-id-modal.vue.js","sources":["../../../../src/components/modals/base-id-modal.vue"],"sourcesContent":["<template>\n <BaseModal\n :ref=\"el\"\n :animation=\"animation\"\n :open=\"isOpen\"\n @click:overlay=\"emitClickOutOfModal\"\n @focusin:body=\"emitClickOutOfModal\"\n >\n <slot />\n </BaseModal>\n</template>\n\n<script lang=\"ts\">\nimport type { XEvent } from '../../wiring/events.types'\nimport type { WireMetadata } from '../../wiring/wiring.types'\nimport { defineComponent, ref } from 'vue'\nimport { useXBus } from '../../composables'\nimport { AnimationProp } from '../../types/animation-prop'\nimport { getTargetElement, isElementEqualOrContained } from '../../utils/html'\nimport BaseModal from './base-modal.vue'\n\n/**\n * Component containing a modal expecting a required prop, named `modalId`. It reacts to\n * `UserClickedOpenModal`, `UserClickedCloseModal` and `UserClickedOutOfModal` events, when their\n * payload matches the component's 'modalId' prop, to handle its open/close state. The default\n * slot offers the possibility to customise the modal content.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseIdModal',\n components: { BaseModal },\n props: {\n /**\n * Animation to use for opening/closing the modal.\n */\n animation: {\n type: AnimationProp,\n },\n /**\n * The modalId to use for the open and close event listeners.\n */\n modalId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n /** The element that opened the modal. */\n let openerElement: HTMLElement | undefined\n\n /** Whether the modal is open or not. */\n const isOpen = ref(false)\n\n const el = ref<HTMLElement>()\n\n const closeModalEvents: XEvent[] = ['UserClickedCloseModal', 'UserClickedOutOfModal']\n\n const xBus = useXBus()\n\n /**\n * Opens the modal.\n *\n * @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.\n * @param metadata - The metadata of the emitted event.\n * @public\n */\n function openModal(modalId: string, metadata: WireMetadata): void {\n if (!isOpen.value && props.modalId === modalId) {\n openerElement = metadata.target\n isOpen.value = true\n }\n }\n\n /**\n * Closes the modal.\n *\n * @param payload - The payload of the closing events:\n * {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.\n *\n * @public\n */\n function closeModal(payload: string): void {\n if (isOpen.value && props.modalId === payload) {\n isOpen.value = false\n }\n }\n\n /**\n * Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target\n * is the button that opened the modal.\n *\n * @param event - The event that triggered the close attempt.\n * @public\n */\n function emitClickOutOfModal(event: MouseEvent | FocusEvent): void {\n // Prevents clicking the open button when the panel is already open to close the panel.\n if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {\n xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value as HTMLElement })\n }\n }\n\n xBus\n .on('UserClickedOpenModal', true)\n .subscribe(({ eventPayload, metadata }) => openModal(eventPayload, metadata))\n\n closeModalEvents.forEach(event => {\n xBus.on(event, false).subscribe(eventPayload => closeModal(eventPayload as string))\n })\n\n return {\n el,\n isOpen,\n emitClickOutOfModal,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedOutOfModal`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks outside the modal. The event payload is the id of the\n modal and a metadata with the target element that emitted it.\n\n## Examples\n\nThe `BaseIdModal` component reacts to the `UserClickedOpenModal`, `UserClickedCloseModal` and\n`UserClickedOutOfModal` to handle its open/close state. The component filters out the events which\npayload doesn't match its `modalId` prop and reacts only to those who match this criteria.\n\n### Basic usage\n\nThe component interacts with both `BaseIdModalOpen` and `BaseIdModalClose` components, which have to\nshare the same value in their `modalId` prop to work:\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n\n### Customized usage\n\n#### Customizing the content with classes\n\nThe `contentClass` prop can be used to add classes to the modal content.\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\" contentClass=\"x-bg-neutral-75\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["_createBlock","_renderSlot"],"mappings":";;;;;;sBACEA,WAAA,CAQY,oBAAA,EAAA;AAAA,IAPT,GAAA,EAAK,IAAA,CAAA,EAAA;AAAA,IACL,SAAA,EAAW,IAAA,CAAA,SAAA;AAAA,IACX,IAAA,EAAM,IAAA,CAAA,MAAA;AAAA,IACN,iBAAA,EAAe,IAAA,CAAA,mBAAA;AAAA,IACf,gBAAA,EAAc,IAAA,CAAA;AAAA,GAAA,EAAA;qBAEf,MAAQ;AAAA,MAARC,UAAA,CAAQ,IAAA,CAAA,MAAA,EAAA,SAAA;AAAA,KAAA,CAAA;;;;;;;;;"}
1
+ {"version":3,"file":"base-id-modal.vue.js","sources":["../../../../src/components/modals/base-id-modal.vue"],"sourcesContent":["<template>\n <BaseModal\n ref=\"modal\"\n :animation=\"animation\"\n :open=\"isOpen\"\n @click:overlay=\"emitClickOutOfModal\"\n @focusin:body=\"emitClickOutOfModal\"\n >\n <slot />\n </BaseModal>\n</template>\n\n<script lang=\"ts\">\nimport type { XEvent } from '../../wiring/events.types'\nimport type { WireMetadata } from '../../wiring/wiring.types'\nimport { defineComponent, ref, useTemplateRef } from 'vue'\nimport { useXBus } from '../../composables'\nimport { AnimationProp } from '../../types/animation-prop'\nimport { getTargetElement, isElementEqualOrContained } from '../../utils/html'\nimport BaseModal from './base-modal.vue'\n\n/**\n * Component containing a modal expecting a required prop, named `modalId`. It reacts to\n * `UserClickedOpenModal`, `UserClickedCloseModal` and `UserClickedOutOfModal` events, when their\n * payload matches the component's 'modalId' prop, to handle its open/close state. The default\n * slot offers the possibility to customise the modal content.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseIdModal',\n components: { BaseModal },\n props: {\n /**\n * Animation to use for opening/closing the modal.\n */\n animation: {\n type: AnimationProp,\n },\n /**\n * The modalId to use for the open and close event listeners.\n */\n modalId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n /** The element that opened the modal. */\n let openerElement: HTMLElement | undefined\n\n /** Whether the modal is open or not. */\n const isOpen = ref(false)\n\n const el = useTemplateRef<InstanceType<typeof BaseModal>>('modal')\n\n const closeModalEvents: XEvent[] = ['UserClickedCloseModal', 'UserClickedOutOfModal']\n\n const xBus = useXBus()\n\n /**\n * Opens the modal.\n *\n * @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.\n * @param metadata - The metadata of the emitted event.\n * @public\n */\n function openModal(modalId: string, metadata: WireMetadata): void {\n if (!isOpen.value && props.modalId === modalId) {\n openerElement = metadata.target\n isOpen.value = true\n }\n }\n\n /**\n * Closes the modal.\n *\n * @param payload - The payload of the closing events:\n * {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.\n *\n * @public\n */\n function closeModal(payload: string): void {\n if (isOpen.value && props.modalId === payload) {\n isOpen.value = false\n }\n }\n\n /**\n * Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target\n * is the button that opened the modal.\n *\n * @param event - The event that triggered the close attempt.\n * @public\n */\n function emitClickOutOfModal(event: MouseEvent | FocusEvent): void {\n // Prevents clicking the open button when the panel is already open to close the panel.\n if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {\n xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value?.$el as HTMLElement })\n }\n }\n\n xBus\n .on('UserClickedOpenModal', true)\n .subscribe(({ eventPayload, metadata }) => openModal(eventPayload, metadata))\n\n closeModalEvents.forEach(event => {\n xBus.on(event, false).subscribe(eventPayload => closeModal(eventPayload as string))\n })\n\n return {\n el,\n isOpen,\n emitClickOutOfModal,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedOutOfModal`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks outside the modal. The event payload is the id of the\n modal and a metadata with the target element that emitted it.\n\n## Examples\n\nThe `BaseIdModal` component reacts to the `UserClickedOpenModal`, `UserClickedCloseModal` and\n`UserClickedOutOfModal` to handle its open/close state. The component filters out the events which\npayload doesn't match its `modalId` prop and reacts only to those who match this criteria.\n\n### Basic usage\n\nThe component interacts with both `BaseIdModalOpen` and `BaseIdModalClose` components, which have to\nshare the same value in their `modalId` prop to work:\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n\n### Customized usage\n\n#### Customizing the content with classes\n\nThe `contentClass` prop can be used to add classes to the modal content.\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\" contentClass=\"x-bg-neutral-75\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["_createBlock","_renderSlot"],"mappings":";;;;;;sBACEA,WAAA,CAQY,oBAAA,EAAA;AAAA,IAPV,GAAA,EAAI,OAAA;AAAA,IACH,SAAA,EAAW,IAAA,CAAA,SAAA;AAAA,IACX,IAAA,EAAM,IAAA,CAAA,MAAA;AAAA,IACN,iBAAA,EAAe,IAAA,CAAA,mBAAA;AAAA,IACf,gBAAA,EAAc,IAAA,CAAA;AAAA,GAAA,EAAA;qBAEf,MAAQ;AAAA,MAARC,UAAA,CAAQ,IAAA,CAAA,MAAA,EAAA,SAAA;AAAA,KAAA,CAAA;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- import { defineComponent, ref } from 'vue';
1
+ import { defineComponent, ref, useTemplateRef } from 'vue';
2
2
  import '../../composables/create-use-device.js';
3
3
  import 'vuex';
4
4
  import '@vue/devtools-api';
@@ -46,7 +46,7 @@ var _sfc_main = defineComponent({
46
46
  let openerElement;
47
47
  /** Whether the modal is open or not. */
48
48
  const isOpen = ref(false);
49
- const el = ref();
49
+ const el = useTemplateRef('modal');
50
50
  const closeModalEvents = ['UserClickedCloseModal', 'UserClickedOutOfModal'];
51
51
  const xBus = useXBus();
52
52
  /**
@@ -85,7 +85,7 @@ var _sfc_main = defineComponent({
85
85
  function emitClickOutOfModal(event) {
86
86
  // Prevents clicking the open button when the panel is already open to close the panel.
87
87
  if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {
88
- xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value });
88
+ xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value?.$el });
89
89
  }
90
90
  }
91
91
  xBus
@@ -1 +1 @@
1
- {"version":3,"file":"base-id-modal.vue2.js","sources":["../../../../src/components/modals/base-id-modal.vue"],"sourcesContent":["<template>\n <BaseModal\n :ref=\"el\"\n :animation=\"animation\"\n :open=\"isOpen\"\n @click:overlay=\"emitClickOutOfModal\"\n @focusin:body=\"emitClickOutOfModal\"\n >\n <slot />\n </BaseModal>\n</template>\n\n<script lang=\"ts\">\nimport type { XEvent } from '../../wiring/events.types'\nimport type { WireMetadata } from '../../wiring/wiring.types'\nimport { defineComponent, ref } from 'vue'\nimport { useXBus } from '../../composables'\nimport { AnimationProp } from '../../types/animation-prop'\nimport { getTargetElement, isElementEqualOrContained } from '../../utils/html'\nimport BaseModal from './base-modal.vue'\n\n/**\n * Component containing a modal expecting a required prop, named `modalId`. It reacts to\n * `UserClickedOpenModal`, `UserClickedCloseModal` and `UserClickedOutOfModal` events, when their\n * payload matches the component's 'modalId' prop, to handle its open/close state. The default\n * slot offers the possibility to customise the modal content.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseIdModal',\n components: { BaseModal },\n props: {\n /**\n * Animation to use for opening/closing the modal.\n */\n animation: {\n type: AnimationProp,\n },\n /**\n * The modalId to use for the open and close event listeners.\n */\n modalId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n /** The element that opened the modal. */\n let openerElement: HTMLElement | undefined\n\n /** Whether the modal is open or not. */\n const isOpen = ref(false)\n\n const el = ref<HTMLElement>()\n\n const closeModalEvents: XEvent[] = ['UserClickedCloseModal', 'UserClickedOutOfModal']\n\n const xBus = useXBus()\n\n /**\n * Opens the modal.\n *\n * @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.\n * @param metadata - The metadata of the emitted event.\n * @public\n */\n function openModal(modalId: string, metadata: WireMetadata): void {\n if (!isOpen.value && props.modalId === modalId) {\n openerElement = metadata.target\n isOpen.value = true\n }\n }\n\n /**\n * Closes the modal.\n *\n * @param payload - The payload of the closing events:\n * {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.\n *\n * @public\n */\n function closeModal(payload: string): void {\n if (isOpen.value && props.modalId === payload) {\n isOpen.value = false\n }\n }\n\n /**\n * Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target\n * is the button that opened the modal.\n *\n * @param event - The event that triggered the close attempt.\n * @public\n */\n function emitClickOutOfModal(event: MouseEvent | FocusEvent): void {\n // Prevents clicking the open button when the panel is already open to close the panel.\n if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {\n xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value as HTMLElement })\n }\n }\n\n xBus\n .on('UserClickedOpenModal', true)\n .subscribe(({ eventPayload, metadata }) => openModal(eventPayload, metadata))\n\n closeModalEvents.forEach(event => {\n xBus.on(event, false).subscribe(eventPayload => closeModal(eventPayload as string))\n })\n\n return {\n el,\n isOpen,\n emitClickOutOfModal,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedOutOfModal`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks outside the modal. The event payload is the id of the\n modal and a metadata with the target element that emitted it.\n\n## Examples\n\nThe `BaseIdModal` component reacts to the `UserClickedOpenModal`, `UserClickedCloseModal` and\n`UserClickedOutOfModal` to handle its open/close state. The component filters out the events which\npayload doesn't match its `modalId` prop and reacts only to those who match this criteria.\n\n### Basic usage\n\nThe component interacts with both `BaseIdModalOpen` and `BaseIdModalClose` components, which have to\nshare the same value in their `modalId` prop to work:\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n\n### Customized usage\n\n#### Customizing the content with classes\n\nThe `contentClass` prop can be used to add classes to the modal content.\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\" contentClass=\"x-bg-neutral-75\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAqBA;;;;;;;AAOE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,aAAa;IACnB,UAAU,EAAE,EAAE,WAAW;AACzB,IAAA,KAAK,EAAE;AACL;;AAEE;AACF,QAAA,SAAS,EAAE;AACT,YAAA,IAAI,EAAE,aAAa;AACpB,SAAA;AACD;;AAEE;AACF,QAAA,OAAO,EAAE;AACP,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;AACF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAA;;AAET,QAAA,IAAI,aAAqC;;AAGzC,QAAA,MAAM,SAAS,GAAG,CAAC,KAAK,CAAA;AAExB,QAAA,MAAM,EAAC,GAAI,GAAG,EAAc;AAE5B,QAAA,MAAM,gBAAgB,GAAa,CAAC,uBAAuB,EAAE,uBAAuB,CAAA;AAEpF,QAAA,MAAM,IAAG,GAAI,OAAO,EAAC;AAErB;;;;;;AAME;AACF,QAAA,SAAS,SAAS,CAAC,OAAe,EAAE,QAAsB,EAAA;YACxD,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,CAAC,OAAM,KAAM,OAAO,EAAE;AAC9C,gBAAA,aAAY,GAAI,QAAQ,CAAC,MAAK;AAC9B,gBAAA,MAAM,CAAC,KAAI,GAAI,IAAG;YACpB;QACF;AAEA;;;;;;;AAOE;QACF,SAAS,UAAU,CAAC,OAAe,EAAA;YACjC,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,OAAM,KAAM,OAAO,EAAE;AAC7C,gBAAA,MAAM,CAAC,KAAI,GAAI,KAAI;YACrB;QACF;AAEA;;;;;;AAME;QACF,SAAS,mBAAmB,CAAC,KAA8B,EAAA;;AAEzD,YAAA,IAAI,CAAC,aAAY,IAAK,CAAC,yBAAyB,CAAC,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AACxF,gBAAA,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,OAAsB,CAAA;YACvF;QACF;QAEA;AACG,aAAA,EAAE,CAAC,sBAAsB,EAAE,IAAI;AAC/B,aAAA,SAAS,CAAC,CAAC,EAAE,YAAY,EAAE,QAAO,EAAG,KAAK,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAE9E,QAAA,gBAAgB,CAAC,OAAO,CAAC,KAAI,IAAG;AAC9B,YAAA,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,YAAW,IAAK,UAAU,CAAC,YAAsB,CAAC,CAAA;AACpF,QAAA,CAAC,CAAA;QAED,OAAO;YACL,EAAE;YACF,MAAM;YACN,mBAAmB;SACrB;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"base-id-modal.vue2.js","sources":["../../../../src/components/modals/base-id-modal.vue"],"sourcesContent":["<template>\n <BaseModal\n ref=\"modal\"\n :animation=\"animation\"\n :open=\"isOpen\"\n @click:overlay=\"emitClickOutOfModal\"\n @focusin:body=\"emitClickOutOfModal\"\n >\n <slot />\n </BaseModal>\n</template>\n\n<script lang=\"ts\">\nimport type { XEvent } from '../../wiring/events.types'\nimport type { WireMetadata } from '../../wiring/wiring.types'\nimport { defineComponent, ref, useTemplateRef } from 'vue'\nimport { useXBus } from '../../composables'\nimport { AnimationProp } from '../../types/animation-prop'\nimport { getTargetElement, isElementEqualOrContained } from '../../utils/html'\nimport BaseModal from './base-modal.vue'\n\n/**\n * Component containing a modal expecting a required prop, named `modalId`. It reacts to\n * `UserClickedOpenModal`, `UserClickedCloseModal` and `UserClickedOutOfModal` events, when their\n * payload matches the component's 'modalId' prop, to handle its open/close state. The default\n * slot offers the possibility to customise the modal content.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseIdModal',\n components: { BaseModal },\n props: {\n /**\n * Animation to use for opening/closing the modal.\n */\n animation: {\n type: AnimationProp,\n },\n /**\n * The modalId to use for the open and close event listeners.\n */\n modalId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n /** The element that opened the modal. */\n let openerElement: HTMLElement | undefined\n\n /** Whether the modal is open or not. */\n const isOpen = ref(false)\n\n const el = useTemplateRef<InstanceType<typeof BaseModal>>('modal')\n\n const closeModalEvents: XEvent[] = ['UserClickedCloseModal', 'UserClickedOutOfModal']\n\n const xBus = useXBus()\n\n /**\n * Opens the modal.\n *\n * @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.\n * @param metadata - The metadata of the emitted event.\n * @public\n */\n function openModal(modalId: string, metadata: WireMetadata): void {\n if (!isOpen.value && props.modalId === modalId) {\n openerElement = metadata.target\n isOpen.value = true\n }\n }\n\n /**\n * Closes the modal.\n *\n * @param payload - The payload of the closing events:\n * {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.\n *\n * @public\n */\n function closeModal(payload: string): void {\n if (isOpen.value && props.modalId === payload) {\n isOpen.value = false\n }\n }\n\n /**\n * Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target\n * is the button that opened the modal.\n *\n * @param event - The event that triggered the close attempt.\n * @public\n */\n function emitClickOutOfModal(event: MouseEvent | FocusEvent): void {\n // Prevents clicking the open button when the panel is already open to close the panel.\n if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {\n xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value?.$el as HTMLElement })\n }\n }\n\n xBus\n .on('UserClickedOpenModal', true)\n .subscribe(({ eventPayload, metadata }) => openModal(eventPayload, metadata))\n\n closeModalEvents.forEach(event => {\n xBus.on(event, false).subscribe(eventPayload => closeModal(eventPayload as string))\n })\n\n return {\n el,\n isOpen,\n emitClickOutOfModal,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nA list of events that the component will emit:\n\n- [`UserClickedOutOfModal`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts):\n the event is emitted after the user clicks outside the modal. The event payload is the id of the\n modal and a metadata with the target element that emitted it.\n\n## Examples\n\nThe `BaseIdModal` component reacts to the `UserClickedOpenModal`, `UserClickedCloseModal` and\n`UserClickedOutOfModal` to handle its open/close state. The component filters out the events which\npayload doesn't match its `modalId` prop and reacts only to those who match this criteria.\n\n### Basic usage\n\nThe component interacts with both `BaseIdModalOpen` and `BaseIdModalClose` components, which have to\nshare the same value in their `modalId` prop to work:\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n\n### Customized usage\n\n#### Customizing the content with classes\n\nThe `contentClass` prop can be used to add classes to the modal content.\n\n```vue\n<template>\n <div>\n <BaseIdModalOpen modalId=\"myModal\">Open</BaseIdModalOpen>\n <BaseIdModal modalId=\"myModal\" contentClass=\"x-bg-neutral-75\">\n <img src=\"success.png\" />\n <BaseIdModalClose modalId=\"myModal\">Close</BaseIdModalClose>\n </BaseIdModal>\n </div>\n</template>\n\n<script setup>\nimport { BaseIdModalOpen, BaseIdModal, BaseIdModalClose } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAqBA;;;;;;;AAOE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,aAAa;IACnB,UAAU,EAAE,EAAE,WAAW;AACzB,IAAA,KAAK,EAAE;AACL;;AAEE;AACF,QAAA,SAAS,EAAE;AACT,YAAA,IAAI,EAAE,aAAa;AACpB,SAAA;AACD;;AAEE;AACF,QAAA,OAAO,EAAE;AACP,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;AACF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAA;;AAET,QAAA,IAAI,aAAqC;;AAGzC,QAAA,MAAM,SAAS,GAAG,CAAC,KAAK,CAAA;AAExB,QAAA,MAAM,EAAC,GAAI,cAAc,CAAiC,OAAO,CAAA;AAEjE,QAAA,MAAM,gBAAgB,GAAa,CAAC,uBAAuB,EAAE,uBAAuB,CAAA;AAEpF,QAAA,MAAM,IAAG,GAAI,OAAO,EAAC;AAErB;;;;;;AAME;AACF,QAAA,SAAS,SAAS,CAAC,OAAe,EAAE,QAAsB,EAAA;YACxD,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,CAAC,OAAM,KAAM,OAAO,EAAE;AAC9C,gBAAA,aAAY,GAAI,QAAQ,CAAC,MAAK;AAC9B,gBAAA,MAAM,CAAC,KAAI,GAAI,IAAG;YACpB;QACF;AAEA;;;;;;;AAOE;QACF,SAAS,UAAU,CAAC,OAAe,EAAA;YACjC,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,OAAM,KAAM,OAAO,EAAE;AAC7C,gBAAA,MAAM,CAAC,KAAI,GAAI,KAAI;YACrB;QACF;AAEA;;;;;;AAME;QACF,SAAS,mBAAmB,CAAC,KAA8B,EAAA;;AAEzD,YAAA,IAAI,CAAC,aAAY,IAAK,CAAC,yBAAyB,CAAC,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AACxF,gBAAA,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,KAAoB,CAAA;YAC5F;QACF;QAEA;AACG,aAAA,EAAE,CAAC,sBAAsB,EAAE,IAAI;AAC/B,aAAA,SAAS,CAAC,CAAC,EAAE,YAAY,EAAE,QAAO,EAAG,KAAK,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAE9E,QAAA,gBAAgB,CAAC,OAAO,CAAC,KAAI,IAAG;AAC9B,YAAA,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,YAAW,IAAK,UAAU,CAAC,YAAsB,CAAC,CAAA;AACpF,QAAA,CAAC,CAAA;QAED,OAAO;YACL,EAAE;YACF,MAAM;YACN,mBAAmB;SACrB;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
@@ -27,7 +27,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
27
27
  id: `base-tabs-panel-${tab}`,
28
28
  key: tab,
29
29
  class: normalizeClass(["x-tabs-panel__list-item x-tabs-panel__button x-button", _ctx.tabIsSelected(tab) ? _ctx.activeTabClass : _ctx.tabClass]),
30
- "aria-selected": _ctx.tabIsSelected(tab).toString(),
30
+ "aria-selected": _ctx.tabIsSelected(tab),
31
31
  "data-test": "base-tabs-panel-button",
32
32
  role: "tab",
33
33
  onClick: ($event) => _ctx.selectTab(tab)
@@ -1 +1 @@
1
- {"version":3,"file":"base-tabs-panel.vue.js","sources":["../../../../src/components/panels/base-tabs-panel.vue"],"sourcesContent":["<template>\n <section v-if=\"getTabs().length > 0\" class=\"x-tabs-panel\" data-test=\"base-tabs-panel\">\n <component\n :is=\"tabsAnimation\"\n class=\"x-tabs-panel__items-list\"\n :class=\"tabsListClass\"\n data-test=\"base-tabs-panel-list\"\n role=\"tablist\"\n >\n <!--\n @slot Slot used to replace the whole tab.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n @binding {function} select - Function to select the tab.\n -->\n <slot\n v-for=\"tab in getTabs()\"\n name=\"tab\"\n v-bind=\"{ tab, isSelected: tabIsSelected(tab), select: () => selectTab(tab) }\"\n >\n <button\n :id=\"`base-tabs-panel-${tab}`\"\n :key=\"tab\"\n class=\"x-tabs-panel__list-item x-tabs-panel__button x-button\"\n :class=\"tabIsSelected(tab) ? activeTabClass : tabClass\"\n :aria-selected=\"tabIsSelected(tab).toString()\"\n data-test=\"base-tabs-panel-button\"\n role=\"tab\"\n @click=\"selectTab(tab)\"\n >\n <!--\n @slot Slot used to just pass the content.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n -->\n <slot name=\"tab-content\" v-bind=\"{ tab, isSelected: tabIsSelected(tab) }\">\n {{ tab }}\n </slot>\n </button>\n </slot>\n </component>\n\n <component :is=\"contentAnimation\">\n <div\n v-if=\"selectedTab && slots[selectedTab]\"\n :key=\"selectedTab\"\n :class=\"contentClass\"\n :aria-labelledby=\"`base-tabs-panel-${selectedTab}`\"\n data-test=\"base-tabs-panel-content\"\n role=\"tabpanel\"\n >\n <!--\n @slot Slot used to display the selected tab content.\n @binding {string} tab - This content's tab name.\n @binding {function} selectTab - Function to select a tab.\n @binding {function} deselectTab - Function to deselect the tab.\n -->\n <slot\n :name=\"selectedTab\"\n v-bind=\"{ tab: selectedTab, selectTab, deselectTab: () => selectTab(selectedTab) }\"\n />\n </div>\n </component>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Base Tabs Panel.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseTabsPanel',\n props: {\n /**\n * Animation component that will be used to animate the tabs list.\n *\n * @public\n */\n tabsAnimation: {\n type: AnimationProp,\n default: 'header',\n },\n /**\n * Animation component that will be used to animate the selected tab content.\n *\n * @public\n */\n contentAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /**\n * The tab to be initially selected.\n *\n * @public\n */\n initialTab: {\n type: String,\n default: '',\n },\n /**\n * Allows the tabs to be unselected.\n *\n * @public\n */\n allowTabDeselect: {\n type: Boolean,\n default: false,\n },\n /** Class inherited by content element. */\n activeTabClass: String,\n /** Class inherited by content element. */\n contentClass: String,\n /** Class inherited by content element. */\n tabClass: String,\n /** Class inherited by content element. */\n tabsListClass: String,\n },\n setup(props, { slots }) {\n /**\n * The currently selected tab.\n *\n * @internal\n */\n const selectedTab = ref(props.initialTab)\n\n /**\n * Extracts the tab from the slots.\n *\n * @returns The list of tabs.\n *\n * @internal\n */\n const getTabs = () =>\n Object.keys(slots).filter(slotName => !['tab', 'tab-content'].includes(slotName))\n\n /**\n * Changes the current selected tab. If the tab is already selected\n * and `allowTabDeselect` is `true`, the tab will be unselected.\n *\n * @param tab - The tab to be selected.\n *\n * @internal\n */\n const selectTab = (tab: string) => {\n if (props.allowTabDeselect && selectedTab.value === tab) {\n selectedTab.value = ''\n } else {\n selectedTab.value = tab\n }\n }\n\n /**\n * Checks if a tab is selected.\n *\n * @param tab - Tab to check.\n * @returns True if the tab is selected, false otherwise.\n *\n * @internal\n */\n const tabIsSelected = (tab: string) => selectedTab.value === tab\n\n return {\n selectedTab,\n slots,\n getTabs,\n selectTab,\n tabIsSelected,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-tabs-panel__items-list {\n display: flex;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## Examples\n\nThis component renders a list of tabs based on the name of the slots passed on its template. By\ndefault, the name of each slot will be used as tab label. If an initial tab is passed by prop, the\ncontent of its correspondent slot will be displayed in a panel. Otherwise, no content will be displayed\nuntil a tab is selected.\n\n### Basic example\n\nIt renders a list of tabs and, when a tab is clicked, a panel with its content will be displayed.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n### Play with props\n\n#### Define the tab to be initially opened\n\nBy default, no tab is selected so any panel is displayed. The `initialTab` prop allows to indicate\nwhich tab should be opened at first.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Allowing tabs deselection\n\nThe prop `allowTabDeselect` allows the tabs to be deselected. When a tab that is already selected is\nclicked again, the tab will be deselected and no panel content will be displayed. By default, this\nbehavior is deactivated.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\" allowTabDeselect>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the content with classes\n\n- The `activeTabClass` prop can be used to add classes to the active tab button.\n- The `contentClass` prop can be used to add classes to the content.\n- The `tabClass` prop can be used to add classes to the tab buttons.\n- The `tabsListClass` prop can be used to add classes to the tabs list.\n\n```vue\n<template>\n <BaseTabsPanel\n activeTabClass=\"x-button-auxiliary\"\n contentClass=\"x-p-12 x-bg-auxiliary-25\"\n tabClass=\"x-button-ghost\"\n tabsListClass=\"x-flex-col\"\n >\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Play with the animations\n\n- The `tabsAnimation` prop can be used to animate the tabs list.\n- The `contentAnimation` prop can be used to animate the selected tab content.\n\n```vue\n<template>\n <BaseTabsPanel :tabsAnimation=\"staggeredFadeAndSlide\" :contentAnimation=\"staggeredFadeAndSlide\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, StaggeredFadeAndSlide } from '@empathyco/x-components'\nconst staggeredFadeAndSlide = StaggeredFadeAndSlide\n</script>\n```\n\n### Overriding the slots\n\n#### Customizing the tab button\n\nBy default, the component is rendering a button for each tab to be displayed. This button can be\nreplaced entirely through the `tab` slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab=\"{ tab, isSelected, select }\">\n <CheckIcon v-if=\"isSelected\" />\n This is the {{ tab }} tab.\n <button @click=\"select\">Open tab</button>\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab button content\n\nAlternatively to the previous example, instead of changing the whole tab button, the slot\n`tab-content` offers the possibility of changing just its contents.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab-content=\"{ tab, isSelected }\">\n <CheckIcon v-if=\"isSelected\" />\n {{ tab }}\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab panel content\n\nThe displayed tab name and a method to select a tab are exposed to the tab panel content slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer=\"{ tab, selectTab, deselectTab }\">\n <h1>{{ tab }}</h1>\n <button @click=\"() => selectTab('fall')\">Open Fall</button>\n <button @click=\"deselectTab\">Close tab</button>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_createBlock","_resolveDynamicComponent","_normalizeClass","_Fragment","_renderList","_renderSlot","_mergeProps","_createTextVNode","_withCtx","_normalizeProps","_guardReactiveProps","_createCommentVNode"],"mappings":"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"}
1
+ {"version":3,"file":"base-tabs-panel.vue.js","sources":["../../../../src/components/panels/base-tabs-panel.vue"],"sourcesContent":["<template>\n <section v-if=\"getTabs().length > 0\" class=\"x-tabs-panel\" data-test=\"base-tabs-panel\">\n <component\n :is=\"tabsAnimation\"\n class=\"x-tabs-panel__items-list\"\n :class=\"tabsListClass\"\n data-test=\"base-tabs-panel-list\"\n role=\"tablist\"\n >\n <!--\n @slot Slot used to replace the whole tab.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n @binding {function} select - Function to select the tab.\n -->\n <slot\n v-for=\"tab in getTabs()\"\n name=\"tab\"\n v-bind=\"{ tab, isSelected: tabIsSelected(tab), select: () => selectTab(tab) }\"\n >\n <button\n :id=\"`base-tabs-panel-${tab}`\"\n :key=\"tab\"\n class=\"x-tabs-panel__list-item x-tabs-panel__button x-button\"\n :class=\"tabIsSelected(tab) ? activeTabClass : tabClass\"\n :aria-selected=\"tabIsSelected(tab)\"\n data-test=\"base-tabs-panel-button\"\n role=\"tab\"\n @click=\"selectTab(tab)\"\n >\n <!--\n @slot Slot used to just pass the content.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n -->\n <slot name=\"tab-content\" v-bind=\"{ tab, isSelected: tabIsSelected(tab) }\">\n {{ tab }}\n </slot>\n </button>\n </slot>\n </component>\n\n <component :is=\"contentAnimation\">\n <div\n v-if=\"selectedTab && slots[selectedTab]\"\n :key=\"selectedTab\"\n :class=\"contentClass\"\n :aria-labelledby=\"`base-tabs-panel-${selectedTab}`\"\n data-test=\"base-tabs-panel-content\"\n role=\"tabpanel\"\n >\n <!--\n @slot Slot used to display the selected tab content.\n @binding {string} tab - This content's tab name.\n @binding {function} selectTab - Function to select a tab.\n @binding {function} deselectTab - Function to deselect the tab.\n -->\n <slot\n :name=\"selectedTab\"\n v-bind=\"{ tab: selectedTab, selectTab, deselectTab: () => selectTab(selectedTab) }\"\n />\n </div>\n </component>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Base Tabs Panel.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseTabsPanel',\n props: {\n /**\n * Animation component that will be used to animate the tabs list.\n *\n * @public\n */\n tabsAnimation: {\n type: AnimationProp,\n default: 'header',\n },\n /**\n * Animation component that will be used to animate the selected tab content.\n *\n * @public\n */\n contentAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /**\n * The tab to be initially selected.\n *\n * @public\n */\n initialTab: {\n type: String,\n default: '',\n },\n /**\n * Allows the tabs to be unselected.\n *\n * @public\n */\n allowTabDeselect: {\n type: Boolean,\n default: false,\n },\n /** Class inherited by content element. */\n activeTabClass: String,\n /** Class inherited by content element. */\n contentClass: String,\n /** Class inherited by content element. */\n tabClass: String,\n /** Class inherited by content element. */\n tabsListClass: String,\n },\n setup(props, { slots }) {\n /**\n * The currently selected tab.\n *\n * @internal\n */\n const selectedTab = ref(props.initialTab)\n\n /**\n * Extracts the tab from the slots.\n *\n * @returns The list of tabs.\n *\n * @internal\n */\n const getTabs = () =>\n Object.keys(slots).filter(slotName => !['tab', 'tab-content'].includes(slotName))\n\n /**\n * Changes the current selected tab. If the tab is already selected\n * and `allowTabDeselect` is `true`, the tab will be unselected.\n *\n * @param tab - The tab to be selected.\n *\n * @internal\n */\n const selectTab = (tab: string) => {\n if (props.allowTabDeselect && selectedTab.value === tab) {\n selectedTab.value = ''\n } else {\n selectedTab.value = tab\n }\n }\n\n /**\n * Checks if a tab is selected.\n *\n * @param tab - Tab to check.\n * @returns True if the tab is selected, false otherwise.\n *\n * @internal\n */\n const tabIsSelected = (tab: string) => selectedTab.value === tab\n\n return {\n selectedTab,\n slots,\n getTabs,\n selectTab,\n tabIsSelected,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-tabs-panel__items-list {\n display: flex;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## Examples\n\nThis component renders a list of tabs based on the name of the slots passed on its template. By\ndefault, the name of each slot will be used as tab label. If an initial tab is passed by prop, the\ncontent of its correspondent slot will be displayed in a panel. Otherwise, no content will be displayed\nuntil a tab is selected.\n\n### Basic example\n\nIt renders a list of tabs and, when a tab is clicked, a panel with its content will be displayed.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n### Play with props\n\n#### Define the tab to be initially opened\n\nBy default, no tab is selected so any panel is displayed. The `initialTab` prop allows to indicate\nwhich tab should be opened at first.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Allowing tabs deselection\n\nThe prop `allowTabDeselect` allows the tabs to be deselected. When a tab that is already selected is\nclicked again, the tab will be deselected and no panel content will be displayed. By default, this\nbehavior is deactivated.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\" allowTabDeselect>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the content with classes\n\n- The `activeTabClass` prop can be used to add classes to the active tab button.\n- The `contentClass` prop can be used to add classes to the content.\n- The `tabClass` prop can be used to add classes to the tab buttons.\n- The `tabsListClass` prop can be used to add classes to the tabs list.\n\n```vue\n<template>\n <BaseTabsPanel\n activeTabClass=\"x-button-auxiliary\"\n contentClass=\"x-p-12 x-bg-auxiliary-25\"\n tabClass=\"x-button-ghost\"\n tabsListClass=\"x-flex-col\"\n >\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Play with the animations\n\n- The `tabsAnimation` prop can be used to animate the tabs list.\n- The `contentAnimation` prop can be used to animate the selected tab content.\n\n```vue\n<template>\n <BaseTabsPanel :tabsAnimation=\"staggeredFadeAndSlide\" :contentAnimation=\"staggeredFadeAndSlide\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, StaggeredFadeAndSlide } from '@empathyco/x-components'\nconst staggeredFadeAndSlide = StaggeredFadeAndSlide\n</script>\n```\n\n### Overriding the slots\n\n#### Customizing the tab button\n\nBy default, the component is rendering a button for each tab to be displayed. This button can be\nreplaced entirely through the `tab` slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab=\"{ tab, isSelected, select }\">\n <CheckIcon v-if=\"isSelected\" />\n This is the {{ tab }} tab.\n <button @click=\"select\">Open tab</button>\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab button content\n\nAlternatively to the previous example, instead of changing the whole tab button, the slot\n`tab-content` offers the possibility of changing just its contents.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab-content=\"{ tab, isSelected }\">\n <CheckIcon v-if=\"isSelected\" />\n {{ tab }}\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab panel content\n\nThe displayed tab name and a method to select a tab are exposed to the tab panel content slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer=\"{ tab, selectTab, deselectTab }\">\n <h1>{{ tab }}</h1>\n <button @click=\"() => selectTab('fall')\">Open Fall</button>\n <button @click=\"deselectTab\">Close tab</button>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_createBlock","_resolveDynamicComponent","_normalizeClass","_Fragment","_renderList","_renderSlot","_mergeProps","_createTextVNode","_withCtx","_normalizeProps","_guardReactiveProps","_createCommentVNode"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"base-tabs-panel.vue2.js","sources":["../../../../src/components/panels/base-tabs-panel.vue"],"sourcesContent":["<template>\n <section v-if=\"getTabs().length > 0\" class=\"x-tabs-panel\" data-test=\"base-tabs-panel\">\n <component\n :is=\"tabsAnimation\"\n class=\"x-tabs-panel__items-list\"\n :class=\"tabsListClass\"\n data-test=\"base-tabs-panel-list\"\n role=\"tablist\"\n >\n <!--\n @slot Slot used to replace the whole tab.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n @binding {function} select - Function to select the tab.\n -->\n <slot\n v-for=\"tab in getTabs()\"\n name=\"tab\"\n v-bind=\"{ tab, isSelected: tabIsSelected(tab), select: () => selectTab(tab) }\"\n >\n <button\n :id=\"`base-tabs-panel-${tab}`\"\n :key=\"tab\"\n class=\"x-tabs-panel__list-item x-tabs-panel__button x-button\"\n :class=\"tabIsSelected(tab) ? activeTabClass : tabClass\"\n :aria-selected=\"tabIsSelected(tab).toString()\"\n data-test=\"base-tabs-panel-button\"\n role=\"tab\"\n @click=\"selectTab(tab)\"\n >\n <!--\n @slot Slot used to just pass the content.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n -->\n <slot name=\"tab-content\" v-bind=\"{ tab, isSelected: tabIsSelected(tab) }\">\n {{ tab }}\n </slot>\n </button>\n </slot>\n </component>\n\n <component :is=\"contentAnimation\">\n <div\n v-if=\"selectedTab && slots[selectedTab]\"\n :key=\"selectedTab\"\n :class=\"contentClass\"\n :aria-labelledby=\"`base-tabs-panel-${selectedTab}`\"\n data-test=\"base-tabs-panel-content\"\n role=\"tabpanel\"\n >\n <!--\n @slot Slot used to display the selected tab content.\n @binding {string} tab - This content's tab name.\n @binding {function} selectTab - Function to select a tab.\n @binding {function} deselectTab - Function to deselect the tab.\n -->\n <slot\n :name=\"selectedTab\"\n v-bind=\"{ tab: selectedTab, selectTab, deselectTab: () => selectTab(selectedTab) }\"\n />\n </div>\n </component>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Base Tabs Panel.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseTabsPanel',\n props: {\n /**\n * Animation component that will be used to animate the tabs list.\n *\n * @public\n */\n tabsAnimation: {\n type: AnimationProp,\n default: 'header',\n },\n /**\n * Animation component that will be used to animate the selected tab content.\n *\n * @public\n */\n contentAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /**\n * The tab to be initially selected.\n *\n * @public\n */\n initialTab: {\n type: String,\n default: '',\n },\n /**\n * Allows the tabs to be unselected.\n *\n * @public\n */\n allowTabDeselect: {\n type: Boolean,\n default: false,\n },\n /** Class inherited by content element. */\n activeTabClass: String,\n /** Class inherited by content element. */\n contentClass: String,\n /** Class inherited by content element. */\n tabClass: String,\n /** Class inherited by content element. */\n tabsListClass: String,\n },\n setup(props, { slots }) {\n /**\n * The currently selected tab.\n *\n * @internal\n */\n const selectedTab = ref(props.initialTab)\n\n /**\n * Extracts the tab from the slots.\n *\n * @returns The list of tabs.\n *\n * @internal\n */\n const getTabs = () =>\n Object.keys(slots).filter(slotName => !['tab', 'tab-content'].includes(slotName))\n\n /**\n * Changes the current selected tab. If the tab is already selected\n * and `allowTabDeselect` is `true`, the tab will be unselected.\n *\n * @param tab - The tab to be selected.\n *\n * @internal\n */\n const selectTab = (tab: string) => {\n if (props.allowTabDeselect && selectedTab.value === tab) {\n selectedTab.value = ''\n } else {\n selectedTab.value = tab\n }\n }\n\n /**\n * Checks if a tab is selected.\n *\n * @param tab - Tab to check.\n * @returns True if the tab is selected, false otherwise.\n *\n * @internal\n */\n const tabIsSelected = (tab: string) => selectedTab.value === tab\n\n return {\n selectedTab,\n slots,\n getTabs,\n selectTab,\n tabIsSelected,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-tabs-panel__items-list {\n display: flex;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## Examples\n\nThis component renders a list of tabs based on the name of the slots passed on its template. By\ndefault, the name of each slot will be used as tab label. If an initial tab is passed by prop, the\ncontent of its correspondent slot will be displayed in a panel. Otherwise, no content will be displayed\nuntil a tab is selected.\n\n### Basic example\n\nIt renders a list of tabs and, when a tab is clicked, a panel with its content will be displayed.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n### Play with props\n\n#### Define the tab to be initially opened\n\nBy default, no tab is selected so any panel is displayed. The `initialTab` prop allows to indicate\nwhich tab should be opened at first.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Allowing tabs deselection\n\nThe prop `allowTabDeselect` allows the tabs to be deselected. When a tab that is already selected is\nclicked again, the tab will be deselected and no panel content will be displayed. By default, this\nbehavior is deactivated.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\" allowTabDeselect>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the content with classes\n\n- The `activeTabClass` prop can be used to add classes to the active tab button.\n- The `contentClass` prop can be used to add classes to the content.\n- The `tabClass` prop can be used to add classes to the tab buttons.\n- The `tabsListClass` prop can be used to add classes to the tabs list.\n\n```vue\n<template>\n <BaseTabsPanel\n activeTabClass=\"x-button-auxiliary\"\n contentClass=\"x-p-12 x-bg-auxiliary-25\"\n tabClass=\"x-button-ghost\"\n tabsListClass=\"x-flex-col\"\n >\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Play with the animations\n\n- The `tabsAnimation` prop can be used to animate the tabs list.\n- The `contentAnimation` prop can be used to animate the selected tab content.\n\n```vue\n<template>\n <BaseTabsPanel :tabsAnimation=\"staggeredFadeAndSlide\" :contentAnimation=\"staggeredFadeAndSlide\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, StaggeredFadeAndSlide } from '@empathyco/x-components'\nconst staggeredFadeAndSlide = StaggeredFadeAndSlide\n</script>\n```\n\n### Overriding the slots\n\n#### Customizing the tab button\n\nBy default, the component is rendering a button for each tab to be displayed. This button can be\nreplaced entirely through the `tab` slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab=\"{ tab, isSelected, select }\">\n <CheckIcon v-if=\"isSelected\" />\n This is the {{ tab }} tab.\n <button @click=\"select\">Open tab</button>\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab button content\n\nAlternatively to the previous example, instead of changing the whole tab button, the slot\n`tab-content` offers the possibility of changing just its contents.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab-content=\"{ tab, isSelected }\">\n <CheckIcon v-if=\"isSelected\" />\n {{ tab }}\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab panel content\n\nThe displayed tab name and a method to select a tab are exposed to the tab panel content slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer=\"{ tab, selectTab, deselectTab }\">\n <h1>{{ tab }}</h1>\n <button @click=\"() => selectTab('fall')\">Open Fall</button>\n <button @click=\"deselectTab\">Close tab</button>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["NoAnimation"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuEA;;;;AAIE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,eAAe;AACrB,IAAA,KAAK,EAAE;AACL;;;;AAIE;AACF,QAAA,aAAa,EAAE;AACb,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,OAAO,EAAE,QAAQ;AAClB,SAAA;AACD;;;;AAIE;AACF,QAAA,gBAAgB,EAAE;AAChB,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,OAAO,EAAE,MAAMA,WAAW;AAC3B,SAAA;AACD;;;;AAIE;AACF,QAAA,UAAU,EAAE;AACV,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,EAAE;AACZ,SAAA;AACD;;;;AAIE;AACF,QAAA,gBAAgB,EAAE;AAChB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,KAAK;AACf,SAAA;;AAED,QAAA,cAAc,EAAE,MAAM;;AAEtB,QAAA,YAAY,EAAE,MAAM;;AAEpB,QAAA,QAAQ,EAAE,MAAM;;AAEhB,QAAA,aAAa,EAAE,MAAM;AACtB,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,KAAI,EAAG,EAAA;AACpB;;;;AAIE;QACF,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA;AAExC;;;;;;AAME;AACF,QAAA,MAAM,OAAM,GAAI,MACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAO,IAAK,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAElF;;;;;;;AAOE;AACF,QAAA,MAAM,SAAQ,GAAI,CAAC,GAAW,KAAG;YAC/B,IAAI,KAAK,CAAC,gBAAe,IAAK,WAAW,CAAC,KAAI,KAAM,GAAG,EAAE;AACvD,gBAAA,WAAW,CAAC,KAAI,GAAI,EAAC;YACvB;iBAAO;AACL,gBAAA,WAAW,CAAC,KAAI,GAAI,GAAE;YACxB;AACF,QAAA,CAAA;AAEA;;;;;;;AAOE;AACF,QAAA,MAAM,aAAY,GAAI,CAAC,GAAW,KAAK,WAAW,CAAC,KAAI,KAAM,GAAE;QAE/D,OAAO;YACL,WAAW;YACX,KAAK;YACL,OAAO;YACP,SAAS;YACT,aAAa;SACf;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"base-tabs-panel.vue2.js","sources":["../../../../src/components/panels/base-tabs-panel.vue"],"sourcesContent":["<template>\n <section v-if=\"getTabs().length > 0\" class=\"x-tabs-panel\" data-test=\"base-tabs-panel\">\n <component\n :is=\"tabsAnimation\"\n class=\"x-tabs-panel__items-list\"\n :class=\"tabsListClass\"\n data-test=\"base-tabs-panel-list\"\n role=\"tablist\"\n >\n <!--\n @slot Slot used to replace the whole tab.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n @binding {function} select - Function to select the tab.\n -->\n <slot\n v-for=\"tab in getTabs()\"\n name=\"tab\"\n v-bind=\"{ tab, isSelected: tabIsSelected(tab), select: () => selectTab(tab) }\"\n >\n <button\n :id=\"`base-tabs-panel-${tab}`\"\n :key=\"tab\"\n class=\"x-tabs-panel__list-item x-tabs-panel__button x-button\"\n :class=\"tabIsSelected(tab) ? activeTabClass : tabClass\"\n :aria-selected=\"tabIsSelected(tab)\"\n data-test=\"base-tabs-panel-button\"\n role=\"tab\"\n @click=\"selectTab(tab)\"\n >\n <!--\n @slot Slot used to just pass the content.\n @binding {string} tab - The tab name.\n @binding {boolean} isSelected - Indicates if the tab is selected.\n -->\n <slot name=\"tab-content\" v-bind=\"{ tab, isSelected: tabIsSelected(tab) }\">\n {{ tab }}\n </slot>\n </button>\n </slot>\n </component>\n\n <component :is=\"contentAnimation\">\n <div\n v-if=\"selectedTab && slots[selectedTab]\"\n :key=\"selectedTab\"\n :class=\"contentClass\"\n :aria-labelledby=\"`base-tabs-panel-${selectedTab}`\"\n data-test=\"base-tabs-panel-content\"\n role=\"tabpanel\"\n >\n <!--\n @slot Slot used to display the selected tab content.\n @binding {string} tab - This content's tab name.\n @binding {function} selectTab - Function to select a tab.\n @binding {function} deselectTab - Function to deselect the tab.\n -->\n <slot\n :name=\"selectedTab\"\n v-bind=\"{ tab: selectedTab, selectTab, deselectTab: () => selectTab(selectedTab) }\"\n />\n </div>\n </component>\n </section>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Base Tabs Panel.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseTabsPanel',\n props: {\n /**\n * Animation component that will be used to animate the tabs list.\n *\n * @public\n */\n tabsAnimation: {\n type: AnimationProp,\n default: 'header',\n },\n /**\n * Animation component that will be used to animate the selected tab content.\n *\n * @public\n */\n contentAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /**\n * The tab to be initially selected.\n *\n * @public\n */\n initialTab: {\n type: String,\n default: '',\n },\n /**\n * Allows the tabs to be unselected.\n *\n * @public\n */\n allowTabDeselect: {\n type: Boolean,\n default: false,\n },\n /** Class inherited by content element. */\n activeTabClass: String,\n /** Class inherited by content element. */\n contentClass: String,\n /** Class inherited by content element. */\n tabClass: String,\n /** Class inherited by content element. */\n tabsListClass: String,\n },\n setup(props, { slots }) {\n /**\n * The currently selected tab.\n *\n * @internal\n */\n const selectedTab = ref(props.initialTab)\n\n /**\n * Extracts the tab from the slots.\n *\n * @returns The list of tabs.\n *\n * @internal\n */\n const getTabs = () =>\n Object.keys(slots).filter(slotName => !['tab', 'tab-content'].includes(slotName))\n\n /**\n * Changes the current selected tab. If the tab is already selected\n * and `allowTabDeselect` is `true`, the tab will be unselected.\n *\n * @param tab - The tab to be selected.\n *\n * @internal\n */\n const selectTab = (tab: string) => {\n if (props.allowTabDeselect && selectedTab.value === tab) {\n selectedTab.value = ''\n } else {\n selectedTab.value = tab\n }\n }\n\n /**\n * Checks if a tab is selected.\n *\n * @param tab - Tab to check.\n * @returns True if the tab is selected, false otherwise.\n *\n * @internal\n */\n const tabIsSelected = (tab: string) => selectedTab.value === tab\n\n return {\n selectedTab,\n slots,\n getTabs,\n selectTab,\n tabIsSelected,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-tabs-panel__items-list {\n display: flex;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits no events.\n\n## Examples\n\nThis component renders a list of tabs based on the name of the slots passed on its template. By\ndefault, the name of each slot will be used as tab label. If an initial tab is passed by prop, the\ncontent of its correspondent slot will be displayed in a panel. Otherwise, no content will be displayed\nuntil a tab is selected.\n\n### Basic example\n\nIt renders a list of tabs and, when a tab is clicked, a panel with its content will be displayed.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n### Play with props\n\n#### Define the tab to be initially opened\n\nBy default, no tab is selected so any panel is displayed. The `initialTab` prop allows to indicate\nwhich tab should be opened at first.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Allowing tabs deselection\n\nThe prop `allowTabDeselect` allows the tabs to be deselected. When a tab that is already selected is\nclicked again, the tab will be deselected and no panel content will be displayed. By default, this\nbehavior is deactivated.\n\n```vue\n<template>\n <BaseTabsPanel initialTab=\"summer\" allowTabDeselect>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the content with classes\n\n- The `activeTabClass` prop can be used to add classes to the active tab button.\n- The `contentClass` prop can be used to add classes to the content.\n- The `tabClass` prop can be used to add classes to the tab buttons.\n- The `tabsListClass` prop can be used to add classes to the tabs list.\n\n```vue\n<template>\n <BaseTabsPanel\n activeTabClass=\"x-button-auxiliary\"\n contentClass=\"x-p-12 x-bg-auxiliary-25\"\n tabClass=\"x-button-ghost\"\n tabsListClass=\"x-flex-col\"\n >\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n\n#### Play with the animations\n\n- The `tabsAnimation` prop can be used to animate the tabs list.\n- The `contentAnimation` prop can be used to animate the selected tab content.\n\n```vue\n<template>\n <BaseTabsPanel :tabsAnimation=\"staggeredFadeAndSlide\" :contentAnimation=\"staggeredFadeAndSlide\">\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, StaggeredFadeAndSlide } from '@empathyco/x-components'\nconst staggeredFadeAndSlide = StaggeredFadeAndSlide\n</script>\n```\n\n### Overriding the slots\n\n#### Customizing the tab button\n\nBy default, the component is rendering a button for each tab to be displayed. This button can be\nreplaced entirely through the `tab` slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab=\"{ tab, isSelected, select }\">\n <CheckIcon v-if=\"isSelected\" />\n This is the {{ tab }} tab.\n <button @click=\"select\">Open tab</button>\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab button content\n\nAlternatively to the previous example, instead of changing the whole tab button, the slot\n`tab-content` offers the possibility of changing just its contents.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #tab-content=\"{ tab, isSelected }\">\n <CheckIcon v-if=\"isSelected\" />\n {{ tab }}\n </template>\n <template #summer>\n <div>Summer Top Sales</div>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n <template #outlet>\n <div>Outlet Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel, CheckIcon } from '@empathyco/x-components'\n</script>\n```\n\n#### Customizing the tab panel content\n\nThe displayed tab name and a method to select a tab are exposed to the tab panel content slot.\n\n```vue\n<template>\n <BaseTabsPanel>\n <template #summer=\"{ tab, selectTab, deselectTab }\">\n <h1>{{ tab }}</h1>\n <button @click=\"() => selectTab('fall')\">Open Fall</button>\n <button @click=\"deselectTab\">Close tab</button>\n </template>\n <template #fall>\n <div>Fall Top Sales</div>\n </template>\n </BaseTabsPanel>\n</template>\n\n<script setup>\nimport { BaseTabsPanel } from '@empathyco/x-components'\n</script>\n```\n</docs>\n"],"names":["NoAnimation"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuEA;;;;AAIE;AACF,gBAAe,eAAe,CAAC;AAC7B,IAAA,IAAI,EAAE,eAAe;AACrB,IAAA,KAAK,EAAE;AACL;;;;AAIE;AACF,QAAA,aAAa,EAAE;AACb,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,OAAO,EAAE,QAAQ;AAClB,SAAA;AACD;;;;AAIE;AACF,QAAA,gBAAgB,EAAE;AAChB,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,OAAO,EAAE,MAAMA,WAAW;AAC3B,SAAA;AACD;;;;AAIE;AACF,QAAA,UAAU,EAAE;AACV,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,EAAE;AACZ,SAAA;AACD;;;;AAIE;AACF,QAAA,gBAAgB,EAAE;AAChB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,OAAO,EAAE,KAAK;AACf,SAAA;;AAED,QAAA,cAAc,EAAE,MAAM;;AAEtB,QAAA,YAAY,EAAE,MAAM;;AAEpB,QAAA,QAAQ,EAAE,MAAM;;AAEhB,QAAA,aAAa,EAAE,MAAM;AACtB,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,KAAI,EAAG,EAAA;AACpB;;;;AAIE;QACF,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA;AAExC;;;;;;AAME;AACF,QAAA,MAAM,OAAM,GAAI,MACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAO,IAAK,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAElF;;;;;;;AAOE;AACF,QAAA,MAAM,SAAQ,GAAI,CAAC,GAAW,KAAG;YAC/B,IAAI,KAAK,CAAC,gBAAe,IAAK,WAAW,CAAC,KAAI,KAAM,GAAG,EAAE;AACvD,gBAAA,WAAW,CAAC,KAAI,GAAI,EAAC;YACvB;iBAAO;AACL,gBAAA,WAAW,CAAC,KAAI,GAAI,GAAE;YACxB;AACF,QAAA,CAAA;AAEA;;;;;;;AAOE;AACF,QAAA,MAAM,aAAY,GAAI,CAAC,GAAW,KAAK,WAAW,CAAC,KAAI,KAAM,GAAE;QAE/D,OAAO;YACL,WAAW;YACX,KAAK;YACL,OAAO;YACP,SAAS;YACT,aAAa;SACf;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
@@ -1,5 +1,5 @@
1
1
  import _sfc_main from './base-result-current-price.vue2.js';
2
- import { resolveComponent, openBlock, createElementBlock, normalizeClass, renderSlot, createVNode } from 'vue';
2
+ import { resolveComponent, openBlock, createElementBlock, normalizeClass, renderSlot, createBlock, createCommentVNode } 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,10 +12,11 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
12
12
  },
13
13
  [
14
14
  renderSlot(_ctx.$slots, "default", { result: _ctx.result }, () => [
15
- createVNode(_component_BaseCurrency, {
15
+ _ctx.result.price ? (openBlock(), createBlock(_component_BaseCurrency, {
16
+ key: 0,
16
17
  value: _ctx.result.price.value,
17
18
  format: _ctx.format
18
- }, null, 8, ["value", "format"])
19
+ }, null, 8, ["value", "format"])) : createCommentVNode("v-if", true)
19
20
  ])
20
21
  ],
21
22
  2
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-current-price.vue.js","sources":["../../../../src/components/result/base-result-current-price.vue"],"sourcesContent":["<template>\n <div :class=\"dynamicClasses\" class=\"x-result-current-price\" data-test=\"result-current-price\">\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency :value=\"result.price.value\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../../utils/types'\nimport { computed, defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} current price\n * that may or may not be on sale.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n * - Default mask: 'i.iii,dd' which returns '1.345,67'.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n setup(props) {\n /**\n * Dynamic CSS classes to add to the root element of this component.\n *\n * @returns A booleans dictionary where each key is the class name to add,\n * and the boolean value tells if it should be added or not.\n * @internal\n */\n const dynamicClasses = computed<VueCSSClasses>(() => ({\n 'x-result-current-price--on-sale': props.result.price?.hasDiscount ?? false,\n }))\n\n return {\n dynamicClasses,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the current price formatted. You can provide the `format` by property or let\nthe `BaseCurrency` component use an injected one.\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\">\n <span class=\"custom-base-result-current-price\">{{ result.price.value }}</span>\n </BaseResultCurrentPrice>\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeClass","_renderSlot","_createVNode"],"mappings":";;;;;;AACE,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAQM,KAAA;AAAA,IAAA;AAAA,MARA,KAAA,EAAKC,cAAA,CAAA,CAAE,IAAA,CAAA,cAAA,EAAsB,wBAAwB,CAAA,CAAA;AAAA,MAAC,WAAA,EAAU;AAAA,KAAA;;AAKpE,MAAAC,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAFA,MAAA,EAAQ,IAAA,CAAA,MAAA,EAAM,EAArB,MAEO;AAAA,QADLC,WAAA,CAA6D,uBAAA,EAAA;AAAA,UAA9C,KAAA,EAAO,YAAO,KAAA,CAAM,KAAA;AAAA,UAAQ,MAAA,EAAQ,IAAA,CAAA;AAAA,SAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,OAAA,EAAA,QAAA,CAAA;;;;;;;;;;;"}
1
+ {"version":3,"file":"base-result-current-price.vue.js","sources":["../../../../src/components/result/base-result-current-price.vue"],"sourcesContent":["<template>\n <div :class=\"dynamicClasses\" class=\"x-result-current-price\" data-test=\"result-current-price\">\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency v-if=\"result.price\" :value=\"result.price.value\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../../utils/types'\nimport { computed, defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} current price\n * that may or may not be on sale.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n * - Default mask: 'i.iii,dd' which returns '1.345,67'.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n setup(props) {\n /**\n * Dynamic CSS classes to add to the root element of this component.\n *\n * @returns A booleans dictionary where each key is the class name to add,\n * and the boolean value tells if it should be added or not.\n * @internal\n */\n const dynamicClasses = computed<VueCSSClasses>(() => ({\n 'x-result-current-price--on-sale': props.result.price?.hasDiscount ?? false,\n }))\n\n return {\n dynamicClasses,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the current price formatted. You can provide the `format` by property or let\nthe `BaseCurrency` component use an injected one.\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\">\n <span class=\"custom-base-result-current-price\">{{ result.price.value }}</span>\n </BaseResultCurrentPrice>\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeClass","_renderSlot","_createBlock","_createCommentVNode"],"mappings":";;;;;;AACE,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAQM,KAAA;AAAA,IAAA;AAAA,MARA,KAAA,EAAKC,cAAA,CAAA,CAAE,IAAA,CAAA,cAAA,EAAsB,wBAAwB,CAAA,CAAA;AAAA,MAAC,WAAA,EAAU;AAAA,KAAA;;AAKpE,MAAAC,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAFA,MAAA,EAAQ,IAAA,CAAA,MAAA,EAAM,EAArB,MAEO;AAAA,QADe,IAAA,CAAA,MAAA,CAAO,sBAA3BC,WAAA,CAAiF,uBAAA,EAAA;AAAA,UAAA,GAAA,EAAA,CAAA;AAA9C,UAAA,KAAA,EAAO,YAAO,KAAA,CAAM,KAAA;AAAA,UAAQ,MAAA,EAAQ,IAAA,CAAA;AAAA,SAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,OAAA,EAAA,QAAA,CAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-current-price.vue2.js","sources":["../../../../src/components/result/base-result-current-price.vue"],"sourcesContent":["<template>\n <div :class=\"dynamicClasses\" class=\"x-result-current-price\" data-test=\"result-current-price\">\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency :value=\"result.price.value\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../../utils/types'\nimport { computed, defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} current price\n * that may or may not be on sale.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n * - Default mask: 'i.iii,dd' which returns '1.345,67'.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n setup(props) {\n /**\n * Dynamic CSS classes to add to the root element of this component.\n *\n * @returns A booleans dictionary where each key is the class name to add,\n * and the boolean value tells if it should be added or not.\n * @internal\n */\n const dynamicClasses = computed<VueCSSClasses>(() => ({\n 'x-result-current-price--on-sale': props.result.price?.hasDiscount ?? false,\n }))\n\n return {\n dynamicClasses,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the current price formatted. You can provide the `format` by property or let\nthe `BaseCurrency` component use an injected one.\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\">\n <span class=\"custom-base-result-current-price\">{{ result.price.value }}</span>\n </BaseResultCurrentPrice>\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;AAmBA;;;;;AAKE;AACF,gBAAe,eAAe,CAAC;IAC7B,UAAU,EAAE,EAAE,YAAW,EAAG;AAC5B,IAAA,KAAK,EAAE;AACL;;;;AAIE;AACF,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,MAA0B;AAChC,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;AACD;;;;;;;;;;;;;;;;AAgBE;AACF,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAA;AACT;;;;;;AAME;AACF,QAAA,MAAM,cAAa,GAAI,QAAQ,CAAgB,OAAO;YACpD,iCAAiC,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,WAAU,IAAK,KAAK;AAC5E,SAAA,CAAC,CAAA;QAEF,OAAO;YACL,cAAc;SAChB;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"base-result-current-price.vue2.js","sources":["../../../../src/components/result/base-result-current-price.vue"],"sourcesContent":["<template>\n <div :class=\"dynamicClasses\" class=\"x-result-current-price\" data-test=\"result-current-price\">\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency v-if=\"result.price\" :value=\"result.price.value\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport type { VueCSSClasses } from '../../utils/types'\nimport { computed, defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} current price\n * that may or may not be on sale.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n * - Default mask: 'i.iii,dd' which returns '1.345,67'.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n setup(props) {\n /**\n * Dynamic CSS classes to add to the root element of this component.\n *\n * @returns A booleans dictionary where each key is the class name to add,\n * and the boolean value tells if it should be added or not.\n * @internal\n */\n const dynamicClasses = computed<VueCSSClasses>(() => ({\n 'x-result-current-price--on-sale': props.result.price?.hasDiscount ?? false,\n }))\n\n return {\n dynamicClasses,\n }\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the current price formatted. You can provide the `format` by property or let\nthe `BaseCurrency` component use an injected one.\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultCurrentPrice :result=\"result\">\n <span class=\"custom-base-result-current-price\">{{ result.price.value }}</span>\n </BaseResultCurrentPrice>\n</template>\n\n<script setup>\nimport { BaseResultCurrentPrice } from '@empathyco/x-components'\nconst result = {\n price: { value: 123.45, hasDiscount: false },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;AAmBA;;;;;AAKE;AACF,gBAAe,eAAe,CAAC;IAC7B,UAAU,EAAE,EAAE,YAAW,EAAG;AAC5B,IAAA,KAAK,EAAE;AACL;;;;AAIE;AACF,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,MAA0B;AAChC,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA;AACD;;;;;;;;;;;;;;;;AAgBE;AACF,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACF,KAAA;AACD,IAAA,KAAK,CAAC,KAAK,EAAA;AACT;;;;;;AAME;AACF,QAAA,MAAM,cAAa,GAAI,QAAQ,CAAgB,OAAO;YACpD,iCAAiC,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,WAAU,IAAK,KAAK;AAC5E,SAAA,CAAC,CAAA;QAEF,OAAO;YACL,cAAc;SAChB;IACF,CAAC;AACF,CAAA,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-image.vue.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <!-- This is a div because using a picture causes the onload event of the image to fire twice. -->\n <!-- eslint-disable-next-line vuejs-accessibility/mouse-events-have-key-events -->\n <div\n class=\"x-result-picture x-picture\"\n data-test=\"result-picture\"\n @mouseenter.once=\"userHasHoveredImage = true\"\n @mouseenter=\"isHovering = true\"\n @mouseleave=\"isHovering = false\"\n >\n <img\n v-if=\"shouldLoadNextImage\"\n loading=\"lazy\"\n :src=\"pendingImages[0]\"\n :style=\"loaderStyles\"\n class=\"x-picture-image\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n @load=\"flagImageLoaded\"\n @error=\"flagImageAsFailed\"\n />\n <component :is=\"animation\" class=\"x-picture-image\" :appear=\"false\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!loadedImages.length && !pendingImages.length\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!loadedImages.length\" name=\"placeholder\" />\n\n <img\n v-else\n :key=\"imageSrc\"\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-result-picture-image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseResultImage',\n props: {\n /** (Required) The {@link @empathyco/x-types#Result} information. */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n */\n loadAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /** Animation to use when switching between the loaded image and the hover image. */\n hoverAnimation: {\n type: AnimationProp,\n },\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n showNextImageOnHover: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n const pendingImages: Ref<string[]> = ref([])\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n const loadedImages: Ref<string[]> = ref([])\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n const isHovering = ref(false)\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n const userHasHoveredImage = ref(false)\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n const loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important',\n }\n\n /**\n * Initializes images state and resets when the result's images change.\n *\n * @internal\n */\n watch(\n () => props.result.images,\n () => {\n pendingImages.value = [...(props.result.images ?? [])]\n loadedImages.value = pendingImages.value.filter(image => loadedImages.value.includes(image))\n },\n { immediate: true },\n )\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n const animation = computed(() => {\n return userHasHoveredImage.value\n ? (props.hoverAnimation ?? props.loadAnimation)\n : props.loadAnimation\n })\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n const imageSrc = computed(() => {\n return loadedImages.value[\n !props.showNextImageOnHover || !isHovering.value ? 0 : loadedImages.value.length - 1\n ]\n })\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n const shouldLoadNextImage = computed(() => {\n const numImagesToLoad = props.showNextImageOnHover && userHasHoveredImage.value ? 2 : 1\n return !!pendingImages.value.length && loadedImages.value.length < numImagesToLoad\n })\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n const flagImageAsFailed = () => {\n pendingImages.value.shift()\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n const flagImageLoaded = () => {\n const image = pendingImages.value.shift()\n if (image) {\n loadedImages.value.push(image)\n }\n }\n\n return {\n pendingImages,\n loadedImages,\n isHovering,\n userHasHoveredImage,\n loaderStyles,\n animation,\n imageSrc,\n shouldLoadNextImage,\n flagImageAsFailed,\n flagImageLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-result-picture {\n position: relative;\n min-width: 1px;\n min-height: 1px;\n}\n\n.x-result-picture-image {\n max-width: 100%;\n max-height: 100%;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Showing the next image on hover\n\nIf a result has multiple images, it can show the next one on hover.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" showNextImageOnHover />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\">\n <template #placeholder>\n <img alt=\"Placeholder image\" src=\"./placeholder-image.svg\" />\n </template>\n <template #fallback>\n <img alt=\"Fallback image\" src=\"./fallback-image.svg\" />\n </template>\n </BaseResultImage>\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Customizing the animations\n\nTwo animations can be used in this component.\n\nThe `loadAnimation` is used to transition between the placeholder, the fallback and the image.\n\nThe `hoverAnimation` is used to transition between the image and the hover image, if the\n`showNextImageOnHover` prop is `true`.\n\n`hoverAnimation` will default to `loadAnimation` if it is not provided.\n\n```vue\n<template>\n <BaseResultImage\n :result=\"result\"\n :loadAnimation=\"loadAnimation\"\n :hoverAnimation=\"hoverAnimation\"\n showNextImageOnHover\n />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nimport { CrossFade, CollapseHeight } from '@empathyco/x-components/animations'\nconst loadAnimation = CrossFade\nconst hoverAnimation = CollapseHeight\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeStyle","_createCommentVNode","_createBlock","_resolveDynamicComponent","_renderSlot"],"mappings":";;;;;;;;AAGE,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAmCM,KAAA;AAAA,IAAA;AAAA,MAlCJ,KAAA,EAAM,4BAAA;AAAA,MACN,WAAA,EAAU,gBAAA;AAAA,MAAA,gBAAA,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KACQ,IAAA,CAAA,mBAAA,GAAmB,IAAA,CAAA;AAAA,MACpC,YAAA,EAAU,sCAAE,IAAA,CAAA,UAAA,GAAU,IAAA,CAAA;AAAA,MACtB,YAAA,EAAU,sCAAE,IAAA,CAAA,UAAA,GAAU,KAAA;AAAA,KAAA;;AAGf,MAAA,IAAA,CAAA,mBAAA,IAAAD,SAAA,EAAA,EADRC,kBAAA,CAWE,KAAA,EAAA;AAAA,QAAA,GAAA,EAAA,CAAA;QATA,OAAA,EAAQ,MAAA;AAAA,QACP,KAAK,IAAA,CAAA,aAAA,CAAa,CAAA,CAAA;AAAA,QAClB,KAAA,EAAKC,eAAE,IAAA,CAAA,YAAY,CAAA;AAAA,QACpB,KAAA,EAAM,iBAAA;AAAA,QACN,WAAA,EAAU,uBAAA;AAAA,QACV,GAAA,EAAI,EAAA;AAAA,QACJ,IAAA,EAAK,cAAA;AAAA,QACJ,QAAI,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAE,IAAA,CAAA,eAAA,IAAA,IAAA,CAAA,eAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,QACN,SAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAE,IAAA,CAAA,iBAAA,IAAA,IAAA,CAAA,iBAAA,CAAA,GAAA,IAAA,CAAA;AAAA,OAAA,EAAA,IAAA,EAAA,EAAA,EAAA,UAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AAEV,OAAAH,SAAA,EAAA,EAAAI,WAAA,CAeYC,wBAfI,IAAA,CAAA,SAAS,CAAA,EAAA;AAAA,QAAE,KAAA,EAAM,iBAAA;AAAA,QAAmB,MAAA,EAAQ;AAAA,OAAA,EAAA;yBAE1D,MAA6E;AAAA,UAAA,CAAhE,IAAA,CAAA,YAAA,CAAa,MAAA,IAAM,CAAK,IAAA,CAAA,aAAA,CAAc,MAAA,GAAnDC,UAAA,CAA6E,IAAA,CAAA,MAAA,EAAA,UAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA,MAAA,EAAA,IAAA,CAAA,GAAA,CAG3D,IAAA,CAAA,YAAA,CAAa,MAAA,GAA/BA,UAAA,CAA4D,IAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA,MAAA,EAAA,IAAA,CAAA,IAAAN,SAAA,EAAA,EAE5DC,kBAAA,CAOE,KAAA,EAAA;AAAA,YALC,GAAA,EAAK,IAAA,CAAA,QAAA;AAAA,YACL,KAAK,IAAA,CAAA,MAAA,CAAO,IAAA;AAAA,YACZ,GAAA,EAAK,IAAA,CAAA,QAAA;AAAA,YACN,KAAA,EAAM,wBAAA;AAAA,YACN,WAAA,EAAU;AAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,UAAA,CAAA;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"base-result-image.vue.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <!-- This is a div because using a picture causes the onload event of the image to fire twice. -->\n <!-- eslint-disable-next-line vuejs-accessibility/mouse-events-have-key-events -->\n <div\n class=\"x-result-picture x-picture\"\n data-test=\"result-picture\"\n @mouseenter.once=\"userHasHoveredImage = true\"\n @mouseenter=\"isHovering = true\"\n @mouseleave=\"isHovering = false\"\n >\n <img\n v-if=\"shouldLoadNextImage\"\n loading=\"lazy\"\n :src=\"pendingImages[0]\"\n :style=\"loaderStyles\"\n class=\"x-picture-image\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n @load=\"flagImageLoaded\"\n @error=\"flagImageAsFailed\"\n />\n <component :is=\"animation\" class=\"x-picture-image\" :appear=\"false\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!loadedImages.length && !pendingImages.length\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!loadedImages.length\" name=\"placeholder\" />\n\n <img\n v-else\n :key=\"imageSrc\"\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-result-picture-image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType, Ref, StyleValue } from 'vue'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseResultImage',\n props: {\n /** (Required) The {@link @empathyco/x-types#Result} information. */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n */\n loadAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /** Animation to use when switching between the loaded image and the hover image. */\n hoverAnimation: {\n type: AnimationProp,\n },\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n showNextImageOnHover: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n const pendingImages: Ref<string[]> = ref([])\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n const loadedImages: Ref<string[]> = ref([])\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n const isHovering = ref(false)\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n const userHasHoveredImage = ref(false)\n\n /**\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n const loaderStyles: StyleValue = {\n // csstype issue: https://github.com/frenic/csstype/issues/160\n position: 'absolute !important' as 'absolute',\n top: '0 !important' as '0',\n left: '0 !important' as '0',\n width: '100% !important' as '100%',\n height: '100% !important' as '100%',\n pointerEvents: 'none !important' as 'none',\n visibility: 'hidden !important' as 'hidden',\n }\n\n /**\n * Initializes images state and resets when the result's images change.\n *\n * @internal\n */\n watch(\n () => props.result.images,\n () => {\n pendingImages.value = [...(props.result.images ?? [])]\n loadedImages.value = pendingImages.value.filter(image => loadedImages.value.includes(image))\n },\n { immediate: true },\n )\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n const animation = computed(() => {\n return userHasHoveredImage.value\n ? (props.hoverAnimation ?? props.loadAnimation)\n : props.loadAnimation\n })\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n const imageSrc = computed(() => {\n return loadedImages.value[\n !props.showNextImageOnHover || !isHovering.value ? 0 : loadedImages.value.length - 1\n ]\n })\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n const shouldLoadNextImage = computed(() => {\n const numImagesToLoad = props.showNextImageOnHover && userHasHoveredImage.value ? 2 : 1\n return !!pendingImages.value.length && loadedImages.value.length < numImagesToLoad\n })\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n const flagImageAsFailed = () => {\n pendingImages.value.shift()\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n const flagImageLoaded = () => {\n const image = pendingImages.value.shift()\n if (image) {\n loadedImages.value.push(image)\n }\n }\n\n return {\n pendingImages,\n loadedImages,\n isHovering,\n userHasHoveredImage,\n loaderStyles,\n animation,\n imageSrc,\n shouldLoadNextImage,\n flagImageAsFailed,\n flagImageLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-result-picture {\n position: relative;\n min-width: 1px;\n min-height: 1px;\n}\n\n.x-result-picture-image {\n max-width: 100%;\n max-height: 100%;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Showing the next image on hover\n\nIf a result has multiple images, it can show the next one on hover.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" showNextImageOnHover />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\">\n <template #placeholder>\n <img alt=\"Placeholder image\" src=\"./placeholder-image.svg\" />\n </template>\n <template #fallback>\n <img alt=\"Fallback image\" src=\"./fallback-image.svg\" />\n </template>\n </BaseResultImage>\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Customizing the animations\n\nTwo animations can be used in this component.\n\nThe `loadAnimation` is used to transition between the placeholder, the fallback and the image.\n\nThe `hoverAnimation` is used to transition between the image and the hover image, if the\n`showNextImageOnHover` prop is `true`.\n\n`hoverAnimation` will default to `loadAnimation` if it is not provided.\n\n```vue\n<template>\n <BaseResultImage\n :result=\"result\"\n :loadAnimation=\"loadAnimation\"\n :hoverAnimation=\"hoverAnimation\"\n showNextImageOnHover\n />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nimport { CrossFade, CollapseHeight } from '@empathyco/x-components/animations'\nconst loadAnimation = CrossFade\nconst hoverAnimation = CollapseHeight\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_normalizeStyle","_createCommentVNode","_createBlock","_resolveDynamicComponent","_renderSlot"],"mappings":";;;;;;;;AAGE,EAAA,OAAAA,SAAA,EAAA,EAAAC,kBAAA;AAAA,IAmCM,KAAA;AAAA,IAAA;AAAA,MAlCJ,KAAA,EAAM,4BAAA;AAAA,MACN,WAAA,EAAU,gBAAA;AAAA,MAAA,gBAAA,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,MAAA,KACQ,IAAA,CAAA,mBAAA,GAAmB,IAAA,CAAA;AAAA,MACpC,YAAA,EAAU,sCAAE,IAAA,CAAA,UAAA,GAAU,IAAA,CAAA;AAAA,MACtB,YAAA,EAAU,sCAAE,IAAA,CAAA,UAAA,GAAU,KAAA;AAAA,KAAA;;AAGf,MAAA,IAAA,CAAA,mBAAA,IAAAD,SAAA,EAAA,EADRC,kBAAA,CAWE,KAAA,EAAA;AAAA,QAAA,GAAA,EAAA,CAAA;QATA,OAAA,EAAQ,MAAA;AAAA,QACP,KAAK,IAAA,CAAA,aAAA,CAAa,CAAA,CAAA;AAAA,QAClB,KAAA,EAAKC,eAAE,IAAA,CAAA,YAAY,CAAA;AAAA,QACpB,KAAA,EAAM,iBAAA;AAAA,QACN,WAAA,EAAU,uBAAA;AAAA,QACV,GAAA,EAAI,EAAA;AAAA,QACJ,IAAA,EAAK,cAAA;AAAA,QACJ,QAAI,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAE,IAAA,CAAA,eAAA,IAAA,IAAA,CAAA,eAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,QACN,SAAK,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAE,IAAA,CAAA,iBAAA,IAAA,IAAA,CAAA,iBAAA,CAAA,GAAA,IAAA,CAAA;AAAA,OAAA,EAAA,IAAA,EAAA,EAAA,EAAA,UAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AAEV,OAAAH,SAAA,EAAA,EAAAI,WAAA,CAeYC,wBAfI,IAAA,CAAA,SAAS,CAAA,EAAA;AAAA,QAAE,KAAA,EAAM,iBAAA;AAAA,QAAmB,MAAA,EAAQ;AAAA,OAAA,EAAA;yBAE1D,MAA6E;AAAA,UAAA,CAAhE,IAAA,CAAA,YAAA,CAAa,MAAA,IAAM,CAAK,IAAA,CAAA,aAAA,CAAc,MAAA,GAAnDC,UAAA,CAA6E,IAAA,CAAA,MAAA,EAAA,UAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA,MAAA,EAAA,IAAA,CAAA,GAAA,CAG3D,IAAA,CAAA,YAAA,CAAa,MAAA,GAA/BA,UAAA,CAA4D,IAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA,MAAA,EAAA,IAAA,CAAA,IAAAN,SAAA,EAAA,EAE5DC,kBAAA,CAOE,KAAA,EAAA;AAAA,YALC,GAAA,EAAK,IAAA,CAAA,QAAA;AAAA,YACL,KAAK,IAAA,CAAA,MAAA,CAAO,IAAA;AAAA,YACZ,GAAA,EAAK,IAAA,CAAA,QAAA;AAAA,YACN,KAAA,EAAM,wBAAA;AAAA,YACN,WAAA,EAAU;AAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,UAAA,CAAA;;;;;;;;;;;;;;"}
@@ -83,12 +83,13 @@ var _sfc_main = defineComponent({
83
83
  * @internal
84
84
  */
85
85
  const userHasHoveredImage = ref(false);
86
- /**.
86
+ /**
87
87
  * Styles to use inline in the image loader, to prevent override from CSS
88
88
  *
89
89
  * @internal
90
90
  */
91
91
  const loaderStyles = {
92
+ // csstype issue: https://github.com/frenic/csstype/issues/160
92
93
  position: 'absolute !important',
93
94
  top: '0 !important',
94
95
  left: '0 !important',
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-image.vue2.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <!-- This is a div because using a picture causes the onload event of the image to fire twice. -->\n <!-- eslint-disable-next-line vuejs-accessibility/mouse-events-have-key-events -->\n <div\n class=\"x-result-picture x-picture\"\n data-test=\"result-picture\"\n @mouseenter.once=\"userHasHoveredImage = true\"\n @mouseenter=\"isHovering = true\"\n @mouseleave=\"isHovering = false\"\n >\n <img\n v-if=\"shouldLoadNextImage\"\n loading=\"lazy\"\n :src=\"pendingImages[0]\"\n :style=\"loaderStyles\"\n class=\"x-picture-image\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n @load=\"flagImageLoaded\"\n @error=\"flagImageAsFailed\"\n />\n <component :is=\"animation\" class=\"x-picture-image\" :appear=\"false\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!loadedImages.length && !pendingImages.length\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!loadedImages.length\" name=\"placeholder\" />\n\n <img\n v-else\n :key=\"imageSrc\"\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-result-picture-image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType, Ref } from 'vue'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseResultImage',\n props: {\n /** (Required) The {@link @empathyco/x-types#Result} information. */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n */\n loadAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /** Animation to use when switching between the loaded image and the hover image. */\n hoverAnimation: {\n type: AnimationProp,\n },\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n showNextImageOnHover: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n const pendingImages: Ref<string[]> = ref([])\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n const loadedImages: Ref<string[]> = ref([])\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n const isHovering = ref(false)\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n const userHasHoveredImage = ref(false)\n\n /**.\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n const loaderStyles: Partial<CSSStyleDeclaration> = {\n position: 'absolute !important',\n top: '0 !important',\n left: '0 !important',\n width: '100% !important',\n height: '100% !important',\n pointerEvents: 'none !important',\n visibility: 'hidden !important',\n }\n\n /**\n * Initializes images state and resets when the result's images change.\n *\n * @internal\n */\n watch(\n () => props.result.images,\n () => {\n pendingImages.value = [...(props.result.images ?? [])]\n loadedImages.value = pendingImages.value.filter(image => loadedImages.value.includes(image))\n },\n { immediate: true },\n )\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n const animation = computed(() => {\n return userHasHoveredImage.value\n ? (props.hoverAnimation ?? props.loadAnimation)\n : props.loadAnimation\n })\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n const imageSrc = computed(() => {\n return loadedImages.value[\n !props.showNextImageOnHover || !isHovering.value ? 0 : loadedImages.value.length - 1\n ]\n })\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n const shouldLoadNextImage = computed(() => {\n const numImagesToLoad = props.showNextImageOnHover && userHasHoveredImage.value ? 2 : 1\n return !!pendingImages.value.length && loadedImages.value.length < numImagesToLoad\n })\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n const flagImageAsFailed = () => {\n pendingImages.value.shift()\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n const flagImageLoaded = () => {\n const image = pendingImages.value.shift()\n if (image) {\n loadedImages.value.push(image)\n }\n }\n\n return {\n pendingImages,\n loadedImages,\n isHovering,\n userHasHoveredImage,\n loaderStyles,\n animation,\n imageSrc,\n shouldLoadNextImage,\n flagImageAsFailed,\n flagImageLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-result-picture {\n position: relative;\n min-width: 1px;\n min-height: 1px;\n}\n\n.x-result-picture-image {\n max-width: 100%;\n max-height: 100%;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Showing the next image on hover\n\nIf a result has multiple images, it can show the next one on hover.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" showNextImageOnHover />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\">\n <template #placeholder>\n <img alt=\"Placeholder image\" src=\"./placeholder-image.svg\" />\n </template>\n <template #fallback>\n <img alt=\"Fallback image\" src=\"./fallback-image.svg\" />\n </template>\n </BaseResultImage>\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Customizing the animations\n\nTwo animations can be used in this component.\n\nThe `loadAnimation` is used to transition between the placeholder, the fallback and the image.\n\nThe `hoverAnimation` is used to transition between the image and the hover image, if the\n`showNextImageOnHover` prop is `true`.\n\n`hoverAnimation` will default to `loadAnimation` if it is not provided.\n\n```vue\n<template>\n <BaseResultImage\n :result=\"result\"\n :loadAnimation=\"loadAnimation\"\n :hoverAnimation=\"hoverAnimation\"\n showNextImageOnHover\n />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nimport { CrossFade, CollapseHeight } from '@empathyco/x-components/animations'\nconst loadAnimation = CrossFade\nconst hoverAnimation = CollapseHeight\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n</docs>\n"],"names":["NoAnimation"],"mappings":"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"}
1
+ {"version":3,"file":"base-result-image.vue2.js","sources":["../../../../src/components/result/base-result-image.vue"],"sourcesContent":["<template>\n <!-- This is a div because using a picture causes the onload event of the image to fire twice. -->\n <!-- eslint-disable-next-line vuejs-accessibility/mouse-events-have-key-events -->\n <div\n class=\"x-result-picture x-picture\"\n data-test=\"result-picture\"\n @mouseenter.once=\"userHasHoveredImage = true\"\n @mouseenter=\"isHovering = true\"\n @mouseleave=\"isHovering = false\"\n >\n <img\n v-if=\"shouldLoadNextImage\"\n loading=\"lazy\"\n :src=\"pendingImages[0]\"\n :style=\"loaderStyles\"\n class=\"x-picture-image\"\n data-test=\"result-picture-loader\"\n alt=\"\"\n role=\"presentation\"\n @load=\"flagImageLoaded\"\n @error=\"flagImageAsFailed\"\n />\n <component :is=\"animation\" class=\"x-picture-image\" :appear=\"false\">\n <!-- @slot Fallback image content. It will be rendered when all the images failed -->\n <slot v-if=\"!loadedImages.length && !pendingImages.length\" name=\"fallback\" />\n\n <!-- @slot Loading image content. It will be rendered while the real image is not loaded -->\n <slot v-else-if=\"!loadedImages.length\" name=\"placeholder\" />\n\n <img\n v-else\n :key=\"imageSrc\"\n :alt=\"result.name\"\n :src=\"imageSrc\"\n class=\"x-result-picture-image\"\n data-test=\"result-picture-image\"\n />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType, Ref, StyleValue } from 'vue'\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { AnimationProp } from '../../types'\nimport { NoAnimation } from '../animations'\n\n/**\n * Component to be reused that renders an `<img>`.\n *\n * @public\n */\nexport default defineComponent({\n name: 'BaseResultImage',\n props: {\n /** (Required) The {@link @empathyco/x-types#Result} information. */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Animation to use when switching between the placeholder, the loaded image, or the failed\n * image fallback.\n */\n loadAnimation: {\n type: AnimationProp,\n default: () => NoAnimation,\n },\n /** Animation to use when switching between the loaded image and the hover image. */\n hoverAnimation: {\n type: AnimationProp,\n },\n /**\n * Indicates if the next valid image should be displayed on hover.\n *\n * @public\n */\n showNextImageOnHover: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n /**\n * Copy of the images of the result.\n *\n * It is used as a queue of images to load, once an image loads/fails to load, it is removed\n * from this array.\n *\n * @internal\n */\n const pendingImages: Ref<string[]> = ref([])\n\n /**\n * Contains the images that have been loaded successfully.\n *\n * @internal\n */\n const loadedImages: Ref<string[]> = ref([])\n\n /**\n * Indicates if the user is hovering the image.\n *\n * @internal\n */\n const isHovering = ref(false)\n\n /**\n * Indicates if the user has hovered the image.\n *\n * @internal\n */\n const userHasHoveredImage = ref(false)\n\n /**\n * Styles to use inline in the image loader, to prevent override from CSS\n *\n * @internal\n */\n const loaderStyles: StyleValue = {\n // csstype issue: https://github.com/frenic/csstype/issues/160\n position: 'absolute !important' as 'absolute',\n top: '0 !important' as '0',\n left: '0 !important' as '0',\n width: '100% !important' as '100%',\n height: '100% !important' as '100%',\n pointerEvents: 'none !important' as 'none',\n visibility: 'hidden !important' as 'hidden',\n }\n\n /**\n * Initializes images state and resets when the result's images change.\n *\n * @internal\n */\n watch(\n () => props.result.images,\n () => {\n pendingImages.value = [...(props.result.images ?? [])]\n loadedImages.value = pendingImages.value.filter(image => loadedImages.value.includes(image))\n },\n { immediate: true },\n )\n\n /**\n * Animation to be used.\n *\n * @returns The animation to be used, taking into account if the user has hovered the image.\n *\n * @internal\n */\n const animation = computed(() => {\n return userHasHoveredImage.value\n ? (props.hoverAnimation ?? props.loadAnimation)\n : props.loadAnimation\n })\n\n /**\n * Gets the src from the result image.\n *\n * @returns The result image src.\n *\n * @internal\n */\n const imageSrc = computed(() => {\n return loadedImages.value[\n !props.showNextImageOnHover || !isHovering.value ? 0 : loadedImages.value.length - 1\n ]\n })\n\n /**\n * Indicates if the loader should try to load the next image.\n *\n * @returns True if it should try to load the next image.\n *\n * @internal\n */\n const shouldLoadNextImage = computed(() => {\n const numImagesToLoad = props.showNextImageOnHover && userHasHoveredImage.value ? 2 : 1\n return !!pendingImages.value.length && loadedImages.value.length < numImagesToLoad\n })\n\n /**\n * Sets an image as failed.\n *\n * @internal\n */\n const flagImageAsFailed = () => {\n pendingImages.value.shift()\n }\n\n /**\n * Sets an image as loaded.\n *\n * @internal\n */\n const flagImageLoaded = () => {\n const image = pendingImages.value.shift()\n if (image) {\n loadedImages.value.push(image)\n }\n }\n\n return {\n pendingImages,\n loadedImages,\n isHovering,\n userHasHoveredImage,\n loaderStyles,\n animation,\n imageSrc,\n shouldLoadNextImage,\n flagImageAsFailed,\n flagImageLoaded,\n }\n },\n})\n</script>\n\n<style lang=\"css\" scoped>\n.x-result-picture {\n position: relative;\n min-width: 1px;\n min-height: 1px;\n}\n\n.x-result-picture-image {\n max-width: 100%;\n max-height: 100%;\n}\n</style>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component is for the result image. It may be part of the search result page, recommendations or\nother section which needs to include results.\n\nThe result prop is required. It will render a `<img/>` with the result image:\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Showing the next image on hover\n\nIf a result has multiple images, it can show the next one on hover.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\" showNextImageOnHover />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n\n### Customizing slots content\n\nFallback and placeholder contents can be customized.\n\nThe fallback slot allows you to replace the content of the fallback image.\n\nThe other slot is called `placeholder`, and allows you to set the image that its going to be\ndisplayed while the real one is loaded.\n\n```vue\n<template>\n <BaseResultImage :result=\"result\">\n <template #placeholder>\n <img alt=\"Placeholder image\" src=\"./placeholder-image.svg\" />\n </template>\n <template #fallback>\n <img alt=\"Fallback image\" src=\"./fallback-image.svg\" />\n </template>\n </BaseResultImage>\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg'],\n}\n</script>\n```\n\n### Customizing the animations\n\nTwo animations can be used in this component.\n\nThe `loadAnimation` is used to transition between the placeholder, the fallback and the image.\n\nThe `hoverAnimation` is used to transition between the image and the hover image, if the\n`showNextImageOnHover` prop is `true`.\n\n`hoverAnimation` will default to `loadAnimation` if it is not provided.\n\n```vue\n<template>\n <BaseResultImage\n :result=\"result\"\n :loadAnimation=\"loadAnimation\"\n :hoverAnimation=\"hoverAnimation\"\n showNextImageOnHover\n />\n</template>\n\n<script setup>\nimport { BaseResultImage } from '@empathyco/x-components'\nimport { CrossFade, CollapseHeight } from '@empathyco/x-components/animations'\nconst loadAnimation = CrossFade\nconst hoverAnimation = CollapseHeight\nconst result = {\n name: 'Jacket',\n images: ['https://some-image-url.com/image1.jpg', 'https://some-image-url.com/image2.jpg'],\n}\n</script>\n```\n</docs>\n"],"names":["NoAnimation"],"mappings":"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"}
@@ -9,7 +9,7 @@ const _hoisted_1 = {
9
9
  };
10
10
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
11
11
  const _component_BaseCurrency = resolveComponent("BaseCurrency");
12
- return _ctx.result.price.hasDiscount ? (openBlock(), createElementBlock("div", _hoisted_1, [
12
+ return _ctx.result.price?.hasDiscount ? (openBlock(), createElementBlock("div", _hoisted_1, [
13
13
  renderSlot(_ctx.$slots, "default", { result: _ctx.result }, () => [
14
14
  createVNode(_component_BaseCurrency, {
15
15
  value: _ctx.result.price.originalValue,
@@ -1 +1 @@
1
- {"version":3,"file":"base-result-previous-price.vue.js","sources":["../../../../src/components/result/base-result-previous-price.vue"],"sourcesContent":["<template>\n <div\n v-if=\"result.price.hasDiscount\"\n class=\"x-result-previous-price\"\n data-test=\"result-previous-price\"\n >\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency :value=\"result.price.originalValue\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport { defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} previous price.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the previous price formatted if it has discount. The component has an optional\n`format` prop to select the currency format to be applied.\n\n```vue\n<template>\n <BaseResultPreviousPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultPreviousPrice } from '@empathyco/x-components'\nconst result = {\n price: { originalValue: 199.99, hasDiscount: true },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultPreviousPrice :result=\"result\">\n <span class=\"custom-base-result-previous-price\">{{ result.price.originalValue }}</span>\n </BaseResultPreviousPrice>\n</template>\n\n<script setup>\nimport { BaseResultPreviousPrice } from '@empathyco/x-components'\nconst result = {\n price: { originalValue: 199.99, hasDiscount: true },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_renderSlot","_createVNode"],"mappings":";;;;;;EAGI,KAAA,EAAM,yBAAA;AAAA,EACN,WAAA,EAAU;;;;AAFJ,EAAA,OAAA,IAAA,CAAA,MAAA,CAAO,KAAA,CAAM,WAAA,IAAAA,SAAA,EAAA,EADrBC,kBAAA,CAYM,KAAA,EAZN,UAAA,EAYM;AAAA,IAHJC,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAFA,MAAA,EAAQ,IAAA,CAAA,MAAA,IAAf,MAEO;AAAA,MADLC,WAAA,CAAqE,uBAAA,EAAA;AAAA,QAAtD,KAAA,EAAO,YAAO,KAAA,CAAM,aAAA;AAAA,QAAgB,MAAA,EAAQ,IAAA,CAAA;AAAA,OAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,OAAA,EAAA,QAAA,CAAA;;;;;;;;"}
1
+ {"version":3,"file":"base-result-previous-price.vue.js","sources":["../../../../src/components/result/base-result-previous-price.vue"],"sourcesContent":["<template>\n <div\n v-if=\"result.price?.hasDiscount\"\n class=\"x-result-previous-price\"\n data-test=\"result-previous-price\"\n >\n <!--\n @slot Base currency item\n @binding {result} result - Result data\n -->\n <slot :result=\"result\">\n <BaseCurrency :value=\"result.price.originalValue\" :format=\"format\" />\n </slot>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport type { Result } from '@empathyco/x-types'\nimport type { PropType } from 'vue'\nimport { defineComponent } from 'vue'\nimport BaseCurrency from '../currency/base-currency.vue'\n\n/**\n * Component that renders the {@link @empathyco/x-types#Result} previous price.\n *\n * @public\n */\nexport default defineComponent({\n components: { BaseCurrency },\n props: {\n /**\n * (Required) The {@link @empathyco/x-types#Result} information.\n *\n * @public\n */\n result: {\n type: Object as PropType<Result>,\n required: true,\n },\n /**\n * Format or mask to be defined as string.\n * - Use 'i' to define integer numbers.\n * - Use 'd' to define decimal numbers. You can define the length of the decimal part. If the\n * doesn't include decimals, it is filled with zeros until reach the length defined with 'd's.\n * - Integer separator must be defined between the 3rd and the 4th integer 'i' of a group.\n * - Decimal separator must be defined between the last 'i' and the first 'd'. It can be more\n * than one character.\n * - Set whatever you need around the integers and decimals marks.\n *\n * @remarks The number of 'd', which is the maximum decimal length, MUST match with the length\n * of decimals provided from the adapter. Otherwise, when the component truncate the decimal\n * part, delete significant digits.\n *\n * @public\n */\n format: {\n type: String,\n },\n },\n})\n</script>\n\n<docs lang=\"mdx\">\n## Examples\n\n### Basic example\n\nThis component shows the previous price formatted if it has discount. The component has an optional\n`format` prop to select the currency format to be applied.\n\n```vue\n<template>\n <BaseResultPreviousPrice :result=\"result\" :format=\"'i.iii,ddd €'\" />\n</template>\n\n<script setup>\nimport { BaseResultPreviousPrice } from '@empathyco/x-components'\nconst result = {\n price: { originalValue: 199.99, hasDiscount: true },\n // ...other result properties\n}\n</script>\n```\n\n### Overriding default slot\n\n```vue\n<template>\n <BaseResultPreviousPrice :result=\"result\">\n <span class=\"custom-base-result-previous-price\">{{ result.price.originalValue }}</span>\n </BaseResultPreviousPrice>\n</template>\n\n<script setup>\nimport { BaseResultPreviousPrice } from '@empathyco/x-components'\nconst result = {\n price: { originalValue: 199.99, hasDiscount: true },\n // ...other result properties\n}\n</script>\n```\n</docs>\n"],"names":["_openBlock","_createElementBlock","_renderSlot","_createVNode"],"mappings":";;;;;;EAGI,KAAA,EAAM,yBAAA;AAAA,EACN,WAAA,EAAU;;;;AAFJ,EAAA,OAAA,IAAA,CAAA,MAAA,CAAO,KAAA,EAAO,WAAA,IAAAA,SAAA,EAAA,EADtBC,kBAAA,CAYM,KAAA,EAZN,UAAA,EAYM;AAAA,IAHJC,UAAA,CAEO,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAFA,MAAA,EAAQ,IAAA,CAAA,MAAA,IAAf,MAEO;AAAA,MADLC,WAAA,CAAqE,uBAAA,EAAA;AAAA,QAAtD,KAAA,EAAO,YAAO,KAAA,CAAM,aAAA;AAAA,QAAgB,MAAA,EAAQ,IAAA,CAAA;AAAA,OAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,OAAA,EAAA,QAAA,CAAA;;;;;;;;"}