@shopware/cms-base-layer 3.0.0 → 3.0.1

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 (102) hide show
  1. package/README.md +47 -63
  2. package/app/components/SwCategoryNavigation.vue +1 -0
  3. package/app/components/SwCategoryNavigationLink.vue +16 -8
  4. package/app/components/SwContactForm.vue +1 -0
  5. package/app/components/SwFilterChips.vue +1 -0
  6. package/app/components/SwListingProductPrice.vue +16 -4
  7. package/app/components/SwMedia3D.vue +1 -4
  8. package/app/components/SwNewsletterForm.vue +4 -3
  9. package/app/components/SwProductAddToCart.vue +24 -7
  10. package/app/components/SwProductCard.vue +1 -0
  11. package/app/components/SwProductCardDetails.vue +27 -9
  12. package/app/components/SwProductCardImage.vue +31 -12
  13. package/app/components/SwProductCardSkeleton.vue +37 -14
  14. package/app/components/SwProductGallery.vue +1 -0
  15. package/app/components/SwProductListingFilter.vue +5 -1
  16. package/app/components/SwProductListingFilters.vue +21 -6
  17. package/app/components/SwProductListingFiltersHorizontal.vue +4 -1
  18. package/app/components/SwProductPrice.vue +1 -0
  19. package/app/components/SwProductReviews.vue +14 -6
  20. package/app/components/SwProductReviewsForm.vue +15 -3
  21. package/app/components/SwProductUnits.vue +1 -0
  22. package/app/components/SwQuantitySelect.vue +10 -3
  23. package/app/components/SwSharedPrice.vue +1 -0
  24. package/app/components/SwSlider.vue +1 -0
  25. package/app/components/SwStockInfo.vue +12 -6
  26. package/app/components/SwVariantConfigurator.vue +4 -1
  27. package/app/components/listing-filters/SwFilterPrice.vue +79 -30
  28. package/app/components/listing-filters/SwFilterProperties.vue +40 -25
  29. package/app/components/listing-filters/SwFilterRating.vue +21 -9
  30. package/app/components/listing-filters/SwFilterShippingFree.vue +16 -8
  31. package/app/components/public/cms/CmsBlockSpatialViewer.vue +1 -0
  32. package/app/components/public/cms/CmsGenericBlock.vue +2 -0
  33. package/app/components/public/cms/CmsGenericElement.vue +1 -0
  34. package/app/components/public/cms/CmsNoComponent.vue +1 -0
  35. package/app/components/public/cms/CmsPage.md +1 -1
  36. package/app/components/public/cms/CmsPage.vue +2 -0
  37. package/app/components/public/cms/block/CmsBlockCategoryNavigation.vue +1 -0
  38. package/app/components/public/cms/block/CmsBlockCenterText.vue +1 -0
  39. package/app/components/public/cms/block/CmsBlockCrossSelling.vue +1 -0
  40. package/app/components/public/cms/block/CmsBlockCustomForm.vue +1 -0
  41. package/app/components/public/cms/block/CmsBlockForm.vue +1 -0
  42. package/app/components/public/cms/block/CmsBlockGalleryBuybox.vue +4 -1
  43. package/app/components/public/cms/block/CmsBlockImage.vue +1 -0
  44. package/app/components/public/cms/block/CmsBlockImageBubbleRow.vue +4 -1
  45. package/app/components/public/cms/block/CmsBlockImageCover.vue +1 -0
  46. package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +4 -1
  47. package/app/components/public/cms/block/CmsBlockImageGallery.vue +1 -0
  48. package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +1 -0
  49. package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +4 -1
  50. package/app/components/public/cms/block/CmsBlockImageSimpleGrid.vue +1 -0
  51. package/app/components/public/cms/block/CmsBlockImageSlider.vue +1 -0
  52. package/app/components/public/cms/block/CmsBlockImageText.vue +4 -1
  53. package/app/components/public/cms/block/CmsBlockImageTextBubble.vue +4 -1
  54. package/app/components/public/cms/block/CmsBlockImageTextCover.vue +4 -1
  55. package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +4 -12
  56. package/app/components/public/cms/block/CmsBlockImageTextRow.vue +4 -1
  57. package/app/components/public/cms/block/CmsBlockImageThreeColumn.vue +1 -0
  58. package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +4 -1
  59. package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +4 -1
  60. package/app/components/public/cms/block/CmsBlockProductDescriptionReviews.vue +1 -0
  61. package/app/components/public/cms/block/CmsBlockProductHeading.vue +1 -0
  62. package/app/components/public/cms/block/CmsBlockProductListing.vue +1 -0
  63. package/app/components/public/cms/block/CmsBlockProductThreeColumn.vue +1 -0
  64. package/app/components/public/cms/block/CmsBlockSidebarFilter.vue +1 -0
  65. package/app/components/public/cms/block/CmsBlockText.vue +1 -0
  66. package/app/components/public/cms/block/CmsBlockTextHero.vue +1 -0
  67. package/app/components/public/cms/block/CmsBlockTextOnImage.vue +2 -4
  68. package/app/components/public/cms/block/CmsBlockTextThreeColumn.vue +1 -0
  69. package/app/components/public/cms/block/CmsBlockTextTwoColumn.vue +4 -1
  70. package/app/components/public/cms/block/CmsBlockVimeoVideo.vue +1 -0
  71. package/app/components/public/cms/block/CmsBlockYoutubeVideo.vue +1 -0
  72. package/app/components/public/cms/element/CmsElementBuyBox.vue +90 -72
  73. package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +14 -3
  74. package/app/components/public/cms/element/CmsElementCrossSelling.vue +3 -1
  75. package/app/components/public/cms/element/CmsElementCustomForm.vue +1 -0
  76. package/app/components/public/cms/element/CmsElementForm.vue +1 -0
  77. package/app/components/public/cms/element/CmsElementHtml.vue +0 -1
  78. package/app/components/public/cms/element/CmsElementImage.vue +2 -0
  79. package/app/components/public/cms/element/CmsElementImageGallery.vue +6 -2
  80. package/app/components/public/cms/element/CmsElementManufacturerLogo.vue +1 -0
  81. package/app/components/public/cms/element/CmsElementProductBox.vue +1 -0
  82. package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +77 -29
  83. package/app/components/public/cms/element/CmsElementProductListing.vue +16 -5
  84. package/app/components/public/cms/element/CmsElementProductSlider.vue +6 -4
  85. package/app/components/public/cms/element/CmsElementText.vue +2 -0
  86. package/app/components/public/cms/element/CmsElementVimeoVideo.vue +1 -0
  87. package/app/components/public/cms/element/CmsElementYoutubeVideo.vue +1 -0
  88. package/app/components/public/cms/element/SwProductListingPagination.vue +8 -2
  89. package/app/components/public/cms/section/CmsSectionSidebar.vue +13 -8
  90. package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +16 -5
  91. package/app/components/ui/SwitchButton.vue +53 -14
  92. package/app/components/ui/WishlistIcon.vue +8 -2
  93. package/app/composables/useLcpImagePreload.test.ts +1 -0
  94. package/app/composables/useLcpImagePreload.ts +2 -0
  95. package/app/composables/useTypedAppConfig.ts +1 -0
  96. package/app/helpers/cms/getImageSizes.test.ts +1 -0
  97. package/app/helpers/html-to-vue/ast.ts +1 -0
  98. package/app/helpers/html-to-vue/getOptionsFromNode.test.ts +1 -0
  99. package/app/helpers/html-to-vue/renderToHtml.ts +1 -0
  100. package/app/helpers/html-to-vue/renderer.ts +1 -0
  101. package/app/providers/shopware.test.ts +1 -0
  102. package/package.json +19 -20
@@ -4,6 +4,7 @@ import type {
4
4
  SliderElementConfig,
5
5
  } from "@shopware/composables";
6
6
  import { ref, watch } from "vue";
7
+
7
8
  import type { Schemas } from "#shopware";
8
9
 
9
10
  const { product, config = {} } = defineProps<{
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts" generic="ListingFilter extends { code: string }">
2
2
  import { computed } from "vue";
3
3
  import type { Component } from "vue";
4
+
4
5
  import SwFilterPriceVue from "./listing-filters/SwFilterPrice.vue";
5
6
  import SwFilterPropertiesVue from "./listing-filters/SwFilterProperties.vue";
6
7
  import SwFilterRatingVue from "./listing-filters/SwFilterRating.vue";
@@ -58,7 +59,10 @@ const filterComponent = computed<Component | undefined>(() => {
58
59
  const handleSelectValue = ({
59
60
  code,
60
61
  value,
61
- }: { code: string; value: string | number | boolean }) => {
62
+ }: {
63
+ code: string;
64
+ value: string | number | boolean;
65
+ }) => {
62
66
  emit("filter-change", { code, value });
63
67
  };
64
68
  </script>
@@ -8,6 +8,7 @@ import { defu } from "defu";
8
8
  import { computed, reactive } from "vue";
9
9
  import type { ComputedRef, UnwrapNestedRefs } from "vue";
10
10
  import type { LocationQueryRaw } from "vue-router";
11
+
11
12
  import { useCategoryListing, useRoute, useRouter } from "#imports";
12
13
  import type { Schemas, operations } from "#shopware";
13
14
 
@@ -268,8 +269,11 @@ const handleRemoveFilterChip = async (chip: {
268
269
  <!-- Filters Header -->
269
270
  <div class="self-stretch flex flex-col justify-start items-start gap-4">
270
271
  <div
271
- class="flex flex-row items-center justify-between w-full mb-4 py-3 border-b border-outline-outline-variant">
272
- <div class="flex-1 text-surface-on-surface text-base font-bold leading-normal">
272
+ class="flex flex-row items-center justify-between w-full mb-4 py-3 border-b border-outline-outline-variant"
273
+ >
274
+ <div
275
+ class="flex-1 text-surface-on-surface text-base font-bold leading-normal"
276
+ >
273
277
  {{ translations.listing.filters }}
274
278
  </div>
275
279
  <SwSortDropdown
@@ -283,7 +287,9 @@ const handleRemoveFilterChip = async (chip: {
283
287
 
284
288
  <!-- Filters List -->
285
289
  <div class="self-stretch flex flex-col justify-start items-start gap-4">
286
- <SwProductListingFilter v-for="filter in getInitialFilters" :key="filter.id"
290
+ <SwProductListingFilter
291
+ v-for="filter in getInitialFilters"
292
+ :key="filter.id"
287
293
  :filter="filter"
288
294
  :selected-manufacturer="sidebarSelectedFilters.manufacturer"
289
295
  :selected-properties="sidebarSelectedFilters.properties"
@@ -292,11 +298,20 @@ const handleRemoveFilterChip = async (chip: {
292
298
  :selected-rating="sidebarSelectedFilters.rating"
293
299
  :selected-shipping-free="sidebarSelectedFilters['shipping-free']"
294
300
  @filter-change="handleFilterChange"
295
- class="w-full" />
301
+ class="w-full"
302
+ />
296
303
  <div v-if="showResetFiltersButton" class="w-full">
297
- <SwBaseButton variant="primary" size="medium" block @click="invokeCleanFilters" type="button">
304
+ <SwBaseButton
305
+ variant="primary"
306
+ size="medium"
307
+ block
308
+ @click="invokeCleanFilters"
309
+ type="button"
310
+ >
298
311
  {{ translations.listing.resetFilters }}
299
- <span class="w-6 h-6 i-carbon-close-filled inline-block align-middle ml-2"></span>
312
+ <span
313
+ class="w-6 h-6 i-carbon-close-filled inline-block align-middle ml-2"
314
+ ></span>
300
315
  </SwBaseButton>
301
316
  </div>
302
317
  </div>
@@ -8,6 +8,7 @@ import { defu } from "defu";
8
8
  import { computed, reactive } from "vue";
9
9
  import type { ComputedRef, UnwrapNestedRefs } from "vue";
10
10
  import type { LocationQueryRaw } from "vue-router";
11
+
11
12
  import { useCategoryListing, useRoute, useRouter } from "#imports";
12
13
  import type { Schemas, operations } from "#shopware";
13
14
 
@@ -299,7 +300,9 @@ const hasActiveFilter = (filter: { code: string }) => {
299
300
  type="button"
300
301
  >
301
302
  {{ translations.listing.resetFilters }}
302
- <span class="w-5 h-5 i-carbon-close inline-block align-middle ml-1"></span>
303
+ <span
304
+ class="w-5 h-5 i-carbon-close inline-block align-middle ml-1"
305
+ ></span>
303
306
  </SwBaseButton>
304
307
  </div>
305
308
  </div>
@@ -2,6 +2,7 @@
2
2
  import { useCmsTranslations } from "@shopware/composables";
3
3
  import { defu } from "defu";
4
4
  import { toRefs } from "vue";
5
+
5
6
  import { usePrice, useProductPrice } from "#imports";
6
7
  import type { Schemas } from "#shopware";
7
8
 
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { defu } from "defu";
3
3
  import { computed, onMounted, ref, toRefs } from "vue";
4
+
4
5
  import {
5
6
  useCmsTranslations,
6
7
  useProductReviews,
@@ -77,7 +78,10 @@ const formatDate = (date: string) => {
77
78
  v-for="(review, index) in reviewsList"
78
79
  :key="review.id"
79
80
  class="pb-6"
80
- :class="{ 'border-b border-surface-surface-container-highest': index < reviewsList.length - 1 }"
81
+ :class="{
82
+ 'border-b border-surface-surface-container-highest':
83
+ index < reviewsList.length - 1,
84
+ }"
81
85
  >
82
86
  <div
83
87
  v-if="review.createdAt"
@@ -87,19 +91,23 @@ const formatDate = (date: string) => {
87
91
  <span>{{ formatDate(review.createdAt) }}</span>
88
92
  </div>
89
93
  <div
90
- v-if="!review.status"
91
- class="mt-2 text-3 p-2 bg-states-info-container text-states-on-info-container flex gap-2 items-center"
92
- >
94
+ v-if="!review.status"
95
+ class="mt-2 text-3 p-2 bg-states-info-container text-states-on-info-container flex gap-2 items-center"
96
+ >
93
97
  <div class="w-6 h-6 i-carbon-warning" />
94
98
  {{ translations.product.reviewNotAccepted }}
95
99
  </div>
96
- <div class="cms-block-product-description-reviews__reviews-rating inline-flex items-center mt-2">
100
+ <div
101
+ class="cms-block-product-description-reviews__reviews-rating inline-flex items-center mt-2"
102
+ >
97
103
  <SwProductRating
98
104
  :rating="review.points ?? 0"
99
105
  :star-size="20"
100
106
  :show-count="false"
101
107
  />
102
- <div class="cms-block-product-description-reviews__reviews-title font-semibold ml-2">
108
+ <div
109
+ class="cms-block-product-description-reviews__reviews-title font-semibold ml-2"
110
+ >
103
111
  <p>{{ review.title }}</p>
104
112
  </div>
105
113
  </div>
@@ -7,6 +7,7 @@ import type { ValidationRuleWithoutParams } from "@vuelidate/core";
7
7
  import { minLength, required } from "@vuelidate/validators";
8
8
  import { defu } from "defu";
9
9
  import { computed, reactive, ref } from "vue";
10
+
10
11
  import { useShopwareContext } from "#imports";
11
12
 
12
13
  const props = defineProps<{
@@ -154,7 +155,10 @@ const invokeRating = (value: number) => {
154
155
  </script>
155
156
 
156
157
  <template>
157
- <form class="flex flex-col gap-4 md:gap-5 relative" @submit.prevent="invokeSend">
158
+ <form
159
+ class="flex flex-col gap-4 md:gap-5 relative"
160
+ @submit.prevent="invokeSend"
161
+ >
158
162
  <div
159
163
  v-if="isLoading"
160
164
  class="absolute inset-0 flex items-center justify-center z-10 bg-surface-surface/80 rounded-md"
@@ -171,7 +175,11 @@ const invokeRating = (value: number) => {
171
175
  <span class="text-sm text-surface-on-surface-variant">{{
172
176
  translations.product.reviewsForm.rating
173
177
  }}</span>
174
- <div class="flex flex-row gap-2" role="group" :aria-label="translations.product.reviewsForm.rating">
178
+ <div
179
+ class="flex flex-row gap-2"
180
+ role="group"
181
+ :aria-label="translations.product.reviewsForm.rating"
182
+ >
175
183
  <SwStarIcon
176
184
  v-for="index in state.rating || 0"
177
185
  :key="`filled-${index}`"
@@ -217,7 +225,11 @@ const invokeRating = (value: number) => {
217
225
  <SwExclamationIcon :size="20" />
218
226
  </div>
219
227
  <div class="flex-1">
220
- <p v-for="(error, index) in errorMessages" :key="index" class="text-sm text-states-error">
228
+ <p
229
+ v-for="(error, index) in errorMessages"
230
+ :key="index"
231
+ class="text-sm text-states-error"
232
+ >
221
233
  {{ error.detail }}
222
234
  </p>
223
235
  </div>
@@ -2,6 +2,7 @@
2
2
  import { useCmsTranslations } from "@shopware/composables";
3
3
  import { defu } from "defu";
4
4
  import { computed } from "vue";
5
+
5
6
  import type { Schemas } from "#shopware";
6
7
 
7
8
  const { product, showContent = true } = defineProps<{
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { defu } from "defu";
3
3
  import { computed, useId } from "vue";
4
+
4
5
  import { useCmsTranslations } from "#imports";
5
6
 
6
7
  type Translations = {
@@ -63,7 +64,9 @@ const sizeClasses = {
63
64
  };
64
65
  </script>
65
66
  <template>
66
- <div class="rounded outline outline-1 outline-offset-[-1px] outline-outline-outline inline-flex">
67
+ <div
68
+ class="rounded outline outline-1 outline-offset-[-1px] outline-outline-outline inline-flex"
69
+ >
67
70
  <button
68
71
  type="button"
69
72
  :class="sizeClasses[size]"
@@ -73,9 +76,13 @@ const sizeClasses = {
73
76
  >
74
77
  -
75
78
  </button>
76
- <div class="bg-white border-l border-r border-outline-outline inline-flex flex-col justify-center items-center">
79
+ <div
80
+ class="bg-white border-l border-r border-outline-outline inline-flex flex-col justify-center items-center"
81
+ >
77
82
  <!-- visually hidden label for screen readers -->
78
- <label :for="inputId" class="sr-only">{{ translations.form.quantitySelect.label }}</label>
83
+ <label :for="inputId" class="sr-only">{{
84
+ translations.form.quantitySelect.label
85
+ }}</label>
79
86
 
80
87
  <input
81
88
  :id="inputId"
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from "vue";
3
+
3
4
  import { usePrice } from "#imports";
4
5
 
5
6
  const { getFormattedPrice } = usePrice();
@@ -11,6 +11,7 @@ import {
11
11
  watch,
12
12
  } from "vue";
13
13
  import type { CSSProperties, VNode, VNodeArrayChildren } from "vue";
14
+
14
15
  import { useCmsElementConfig, useHead, useId } from "#imports";
15
16
  import type { Schemas } from "#shopware";
16
17
 
@@ -31,14 +31,20 @@ translations = defu(useCmsTranslations(), translations) as Translations;
31
31
  </script>
32
32
  <template>
33
33
  <div class="inline-flex justify-start items-center gap-2">
34
- <div class="w-2 h-2 bg-states-success rounded-full" v-if="availableStock > 0"></div>
34
+ <div
35
+ class="w-2 h-2 bg-states-success rounded-full"
36
+ v-if="availableStock > 0"
37
+ ></div>
35
38
  <div class="w-2 h-2 bg-states-error rounded-full" v-else></div>
36
- <span v-if="availableStock >= minPurchase && deliveryTime">{{ translations.product.deliveryTime }} {{
37
- deliveryTime?.name }}
39
+ <span v-if="availableStock >= minPurchase && deliveryTime"
40
+ >{{ translations.product.deliveryTime }} {{ deliveryTime?.name }}
38
41
  </span>
39
- <span v-else-if="availableStock < minPurchase && deliveryTime && restockTime">
42
+ <span
43
+ v-else-if="availableStock < minPurchase && deliveryTime && restockTime"
44
+ >
40
45
  {{ translations.product.deliveryTime }} {{ restockTime }}
41
- {{ translations.product.days }} {{ deliveryTime?.name }}</span>
46
+ {{ translations.product.days }} {{ deliveryTime?.name }}</span
47
+ >
42
48
  <span v-else>{{ translations.product.noAvailable }}</span>
43
49
  </div>
44
- </template>
50
+ </template>
@@ -4,6 +4,7 @@ import { buildUrlPrefix, getProductRoute } from "@shopware/helpers";
4
4
  import { defu } from "defu";
5
5
  import { computed, ref, unref } from "vue";
6
6
  import type { ComputedRef } from "vue";
7
+
7
8
  import { useProductConfigurator, useRouter, useUrlResolver } from "#imports";
8
9
  import type { Schemas } from "#shopware";
9
10
 
@@ -84,7 +85,9 @@ const onHandleChange = async () => {
84
85
  :key="optionGroup.id"
85
86
  class="mt-6"
86
87
  >
87
- <div class="text-sm text-gray-900 font-medium">{{ optionGroup.name }}</div>
88
+ <div class="text-sm text-gray-900 font-medium">
89
+ {{ optionGroup.name }}
90
+ </div>
88
91
  <fieldset class="mt-4 flex-1">
89
92
  <legend class="sr-only">
90
93
  {{ translations.product.chooseA }} {{ optionGroup.name }}
@@ -1,15 +1,20 @@
1
- <script setup lang="ts" generic="
1
+ <script
2
+ setup
3
+ lang="ts"
4
+ generic="
2
5
  ListingFilter extends {
3
6
  code: string;
4
7
  min?: number;
5
8
  max?: number;
6
9
  label: string;
7
10
  }
8
- ">
11
+ "
12
+ >
9
13
  import { useCmsTranslations } from "@shopware/composables";
10
14
  import { onClickOutside, useDebounceFn, useEventListener } from "@vueuse/core";
11
15
  import { defu } from "defu";
12
16
  import { onMounted, reactive, ref, watch } from "vue";
17
+
13
18
  import type { Schemas } from "#shopware";
14
19
 
15
20
  const emits =
@@ -149,15 +154,17 @@ const startDrag = (type: "min" | "max", event: MouseEvent | TouchEvent) => {
149
154
  @keydown.space.prevent="toggle"
150
155
  >
151
156
  <div class="flex-1 flex items-center gap-2.5">
152
- <div class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left">
157
+ <div
158
+ class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left"
159
+ >
153
160
  {{ filter.label }}
154
161
  </div>
155
162
  </div>
156
- <span
157
- class="flex items-center justify-center"
158
- aria-hidden="true"
159
- >
160
- <SwChevronIcon :direction="isFilterVisible ? 'up' : 'down'" :size="24" />
163
+ <span class="flex items-center justify-center" aria-hidden="true">
164
+ <SwChevronIcon
165
+ :direction="isFilterVisible ? 'up' : 'down'"
166
+ :size="24"
167
+ />
161
168
  </span>
162
169
  </div>
163
170
  </div>
@@ -165,52 +172,94 @@ const startDrag = (type: "min" | "max", event: MouseEvent | TouchEvent) => {
165
172
 
166
173
  <!-- Filter content -->
167
174
  <transition name="filter-collapse">
168
- <div v-if="isFilterVisible || displayMode === 'dropdown'" :id="filter.code"
169
- class="self-stretch flex flex-col justify-start items-start gap-2.5">
175
+ <div
176
+ v-if="isFilterVisible || displayMode === 'dropdown'"
177
+ :id="filter.code"
178
+ class="self-stretch flex flex-col justify-start items-start gap-2.5"
179
+ >
170
180
  <div class="self-stretch flex flex-col justify-start items-start gap-1">
171
- <div class="self-stretch inline-flex justify-between items-center gap-2">
181
+ <div
182
+ class="self-stretch inline-flex justify-between items-center gap-2"
183
+ >
172
184
  <div
173
- class="w-16 h-10 px-2 py-1 rounded-lg outline outline-1 outline-offset-[-1px] outline-outline-outline-variant inline-flex flex-col justify-center items-start gap-2.5">
174
- <input type="number" :placeholder="translations.listing.min" v-model.number="prices.min"
185
+ class="w-16 h-10 px-2 py-1 rounded-lg outline outline-1 outline-offset-[-1px] outline-outline-outline-variant inline-flex flex-col justify-center items-start gap-2.5"
186
+ >
187
+ <input
188
+ type="number"
189
+ :placeholder="translations.listing.min"
190
+ v-model.number="prices.min"
175
191
  class="w-full bg-transparent border-none outline-none text-surface-on-surface text-sm font-normal leading-tight"
176
- @change="emits('select-value', { code: filter.code, value: { min: prices.min, max: prices.max } })"
177
- :min="filter.min" :max="prices.max" />
192
+ @change="
193
+ emits('select-value', {
194
+ code: filter.code,
195
+ value: { min: prices.min, max: prices.max },
196
+ })
197
+ "
198
+ :min="filter.min"
199
+ :max="prices.max"
200
+ />
178
201
  </div>
179
202
  <div
180
- class="w-16 h-10 px-2 py-1 rounded-lg outline outline-1 outline-offset-[-1px] outline-outline-outline-variant inline-flex flex-col justify-center items-start gap-2.5">
181
- <input type="number" :placeholder="translations.listing.max" v-model.number="prices.max"
203
+ class="w-16 h-10 px-2 py-1 rounded-lg outline outline-1 outline-offset-[-1px] outline-outline-outline-variant inline-flex flex-col justify-center items-start gap-2.5"
204
+ >
205
+ <input
206
+ type="number"
207
+ :placeholder="translations.listing.max"
208
+ v-model.number="prices.max"
182
209
  class="w-full bg-transparent border-none outline-none text-surface-on-surface text-sm font-normal leading-tight"
183
- @change="emits('select-value', { code: filter.code, value: { min: prices.min, max: prices.max } })"
184
- :min="prices.min" :max="filter.max" />
210
+ @change="
211
+ emits('select-value', {
212
+ code: filter.code,
213
+ value: { min: prices.min, max: prices.max },
214
+ })
215
+ "
216
+ :min="prices.min"
217
+ :max="filter.max"
218
+ />
185
219
  </div>
186
220
  </div>
187
221
  <!-- Custom slider UI -->
188
- <div class="relative w-64 h-10 mt-2 mx-auto flex items-center select-none">
222
+ <div
223
+ class="relative w-64 h-10 mt-2 mx-auto flex items-center select-none"
224
+ >
189
225
  <!-- Track -->
190
226
  <div
191
- class="absolute left-0 top-1/2 -translate-y-1/2 w-full h-2 bg-surface-surface-container-highest rounded-full">
192
- </div>
227
+ class="absolute left-0 top-1/2 -translate-y-1/2 w-full h-2 bg-surface-surface-container-highest rounded-full"
228
+ ></div>
193
229
  <!-- Active range -->
194
- <div class="absolute top-1/2 -translate-y-1/2 h-2 bg-surface-surface-primary rounded-full" :style="{
195
- left: ((prices.min - (filter.min ?? 0)) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100 + '%',
196
- width: ((prices.max - prices.min) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100 + '%',
197
- }"></div>
230
+ <div
231
+ class="absolute top-1/2 -translate-y-1/2 h-2 bg-surface-surface-primary rounded-full"
232
+ :style="{
233
+ left:
234
+ ((prices.min - (filter.min ?? 0)) /
235
+ ((filter.max ?? 100) - (filter.min ?? 0))) *
236
+ 100 +
237
+ '%',
238
+ width:
239
+ ((prices.max - prices.min) /
240
+ ((filter.max ?? 100) - (filter.min ?? 0))) *
241
+ 100 +
242
+ '%',
243
+ }"
244
+ ></div>
198
245
  <!-- Min thumb -->
199
246
  <div
200
247
  class="absolute top-1/2 -translate-y-1/2 w-5 h-5 bg-brand-primary rounded-full shadow-[2px_2px_10px_0px_rgba(0,0,0,0.15)] cursor-pointer touch-none"
201
248
  :style="{
202
- left: `calc(${((prices.min - (filter.min ?? 0)) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100}% - 10px)`
249
+ left: `calc(${((prices.min - (filter.min ?? 0)) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100}% - 10px)`,
203
250
  }"
204
251
  @mousedown.prevent="startDrag('min', $event)"
205
- @touchstart.prevent="startDrag('min', $event)"></div>
252
+ @touchstart.prevent="startDrag('min', $event)"
253
+ ></div>
206
254
  <!-- Max thumb -->
207
255
  <div
208
256
  class="absolute top-1/2 -translate-y-1/2 w-5 h-5 bg-brand-primary rounded-full shadow-[2px_2px_10px_0px_rgba(0,0,0,0.15)] cursor-pointer touch-none"
209
257
  :style="{
210
- left: `calc(${((prices.max - (filter.min ?? 0)) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100}% - 10px)`
258
+ left: `calc(${((prices.max - (filter.min ?? 0)) / ((filter.max ?? 100) - (filter.min ?? 0))) * 100}% - 10px)`,
211
259
  }"
212
260
  @mousedown.prevent="startDrag('max', $event)"
213
- @touchstart.prevent="startDrag('max', $event)"></div>
261
+ @touchstart.prevent="startDrag('max', $event)"
262
+ ></div>
214
263
  </div>
215
264
  </div>
216
265
  </div>
@@ -13,6 +13,7 @@
13
13
  >
14
14
  import { getTranslatedProperty } from "@shopware/helpers";
15
15
  import { computed, ref } from "vue";
16
+
16
17
  import type { Schemas } from "#shopware";
17
18
 
18
19
  const {
@@ -75,15 +76,17 @@ const selectValue = (id: string) => {
75
76
  @keydown.space.prevent="toggle"
76
77
  >
77
78
  <div class="flex-1 flex items-center gap-2.5">
78
- <div class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left">
79
+ <div
80
+ class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left"
81
+ >
79
82
  {{ filter.label }}
80
83
  </div>
81
84
  </div>
82
- <span
83
- class="flex items-center justify-center"
84
- aria-hidden="true"
85
- >
86
- <SwChevronIcon :direction="isFilterVisible ? 'up' : 'down'" :size="24" />
85
+ <span class="flex items-center justify-center" aria-hidden="true">
86
+ <SwChevronIcon
87
+ :direction="isFilterVisible ? 'up' : 'down'"
88
+ :size="24"
89
+ />
87
90
  </span>
88
91
  </div>
89
92
  </div>
@@ -91,28 +94,40 @@ const selectValue = (id: string) => {
91
94
 
92
95
  <!-- Filter content -->
93
96
  <transition name="filter-collapse">
94
- <div v-if="isFilterVisible || displayMode === 'dropdown'" :id="filter.code" class="self-stretch flex flex-col justify-start items-start gap-4">
95
- <fieldset class="self-stretch flex flex-col justify-start items-start gap-4">
96
- <legend class="sr-only">{{ filter.name }}</legend>
97
- <label
98
- v-for="option in filter.options || filter.entities"
99
- :key="`${option.id}-${isChecked(option.id)}`"
100
- class="self-stretch inline-flex justify-start items-start gap-2 cursor-pointer"
97
+ <div
98
+ v-if="isFilterVisible || displayMode === 'dropdown'"
99
+ :id="filter.code"
100
+ class="self-stretch flex flex-col justify-start items-start gap-4"
101
+ >
102
+ <fieldset
103
+ class="self-stretch flex flex-col justify-start items-start gap-4"
101
104
  >
102
- <div class="w-4 self-stretch pt-[3px] flex justify-start items-start gap-2.5">
103
- <SwCheckbox
104
- :model-value="isChecked(option.id)"
105
- @update:model-value="() => selectValue(option.id)"
106
- />
107
- </div>
108
- <div class="flex-1 inline-flex flex-col justify-start items-start gap-0.5">
109
- <div class="inline-flex justify-start items-center gap-1">
110
- <div class="flex-1 text-surface-on-surface text-base font-normal leading-normal">
111
- {{ getTranslatedProperty(option, 'name') }}
105
+ <legend class="sr-only">{{ filter.name }}</legend>
106
+ <label
107
+ v-for="option in filter.options || filter.entities"
108
+ :key="`${option.id}-${isChecked(option.id)}`"
109
+ class="self-stretch inline-flex justify-start items-start gap-2 cursor-pointer"
110
+ >
111
+ <div
112
+ class="w-4 self-stretch pt-[3px] flex justify-start items-start gap-2.5"
113
+ >
114
+ <SwCheckbox
115
+ :model-value="isChecked(option.id)"
116
+ @update:model-value="() => selectValue(option.id)"
117
+ />
118
+ </div>
119
+ <div
120
+ class="flex-1 inline-flex flex-col justify-start items-start gap-0.5"
121
+ >
122
+ <div class="inline-flex justify-start items-center gap-1">
123
+ <div
124
+ class="flex-1 text-surface-on-surface text-base font-normal leading-normal"
125
+ >
126
+ {{ getTranslatedProperty(option, "name") }}
127
+ </div>
112
128
  </div>
113
129
  </div>
114
- </div>
115
- </label>
130
+ </label>
116
131
  </fieldset>
117
132
  </div>
118
133
  </transition>
@@ -9,6 +9,7 @@
9
9
  "
10
10
  >
11
11
  import { computed, ref } from "vue";
12
+
12
13
  import type { Schemas } from "#shopware";
13
14
 
14
15
  const emits =
@@ -65,15 +66,17 @@ const toggle = () => {
65
66
  @keydown.space.prevent="toggle"
66
67
  >
67
68
  <div class="flex-1 flex items-center gap-2.5">
68
- <div class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left">
69
+ <div
70
+ class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left"
71
+ >
69
72
  {{ filter.label }}
70
73
  </div>
71
74
  </div>
72
- <span
73
- class="flex items-center justify-center"
74
- aria-hidden="true"
75
- >
76
- <SwChevronIcon :direction="isFilterVisible ? 'up' : 'down'" :size="24" />
75
+ <span class="flex items-center justify-center" aria-hidden="true">
76
+ <SwChevronIcon
77
+ :direction="isFilterVisible ? 'up' : 'down'"
78
+ :size="24"
79
+ />
77
80
  </span>
78
81
  </div>
79
82
  </div>
@@ -81,14 +84,23 @@ const toggle = () => {
81
84
 
82
85
  <!-- Filter content -->
83
86
  <transition name="filter-collapse">
84
- <div v-if="isFilterVisible || displayMode === 'dropdown'" class="self-stretch flex flex-col justify-start items-start gap-4">
87
+ <div
88
+ v-if="isFilterVisible || displayMode === 'dropdown'"
89
+ class="self-stretch flex flex-col justify-start items-start gap-4"
90
+ >
85
91
  <div class="flex flex-row items-center gap-2 mt-2">
86
92
  <div
87
93
  v-for="i in 5"
88
94
  :key="i"
89
- :class="['h-6 w-6 cursor-pointer', displayedScore >= i ? 'i-carbon-star-filled' : 'i-carbon-star']"
95
+ :class="[
96
+ 'h-6 w-6 cursor-pointer',
97
+ displayedScore >= i ? 'i-carbon-star-filled' : 'i-carbon-star',
98
+ ]"
90
99
  @mouseleave="isHoverActive = false"
91
- @click="hoverRating(i); onChangeRating()"
100
+ @click="
101
+ hoverRating(i);
102
+ onChangeRating();
103
+ "
92
104
  @mouseover="hoverRating(i)"
93
105
  :aria-label="`${i} star${i !== 1 ? 's' : ''}`"
94
106
  />