@akinon/projectzero 2.0.0-beta.20 → 2.0.0-beta.21

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 (138) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/app-template/CHANGELOG.md +138 -0
  3. package/app-template/next.config.mjs +0 -1
  4. package/app-template/package.json +31 -30
  5. package/app-template/src/app/[pz]/[...prettyurl]/page.tsx +2 -2
  6. package/app-template/src/app/[pz]/account/layout.tsx +2 -1
  7. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/blog/[slug]/page.tsx +4 -2
  8. package/app-template/src/app/[pz]/category/[pk]/page.tsx +11 -1
  9. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +2 -2
  10. package/app-template/src/app/[pz]/layout.tsx +3 -1
  11. package/app-template/src/app/[pz]/list/page.tsx +11 -1
  12. package/app-template/src/app/[pz]/page.tsx +13 -35
  13. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  14. package/app-template/src/app/[pz]/product/[pk]/page.tsx +2 -2
  15. package/app-template/src/app/api/barcode-search/route.ts +1 -1
  16. package/app-template/src/app/api/cache/route.ts +1 -1
  17. package/app-template/src/app/api/image-proxy/route.ts +1 -1
  18. package/app-template/src/app/api/logout/route.ts +1 -1
  19. package/app-template/src/app/api/product-categories/route.ts +1 -1
  20. package/app-template/src/app/api/similar-product-list/route.ts +1 -1
  21. package/app-template/src/app/api/similar-products/route.ts +1 -1
  22. package/app-template/src/app/api/virtual-try-on/route.ts +1 -1
  23. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  24. package/app-template/src/components/quantity-selector.tsx +16 -4
  25. package/app-template/src/components/widget-content.tsx +3 -3
  26. package/app-template/src/routes/index.ts +6 -6
  27. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  28. package/app-template/src/utils/theme-page-context.ts +309 -0
  29. package/app-template/src/views/basket/basket-item.tsx +107 -691
  30. package/app-template/src/views/basket/index.ts +0 -2
  31. package/app-template/src/views/basket/summary.tsx +75 -496
  32. package/app-template/src/views/breadcrumb.tsx +38 -13
  33. package/app-template/src/views/category/category-header.tsx +66 -289
  34. package/app-template/src/views/category/category-info.tsx +24 -173
  35. package/app-template/src/views/category/filters/index.tsx +48 -208
  36. package/app-template/src/views/category/layout.tsx +5 -7
  37. package/app-template/src/views/checkout/index.tsx +0 -5
  38. package/app-template/src/views/checkout/steps/payment/index.tsx +2 -5
  39. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -72
  40. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +40 -171
  41. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +12 -74
  42. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +45 -128
  43. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +27 -232
  44. package/app-template/src/views/checkout/summary.tsx +29 -303
  45. package/app-template/src/views/footer.tsx +13 -415
  46. package/app-template/src/views/guest-login/index.tsx +1 -1
  47. package/app-template/src/views/header/action-menu.tsx +45 -277
  48. package/app-template/src/views/header/band.tsx +21 -6
  49. package/app-template/src/views/header/index.tsx +47 -109
  50. package/app-template/src/views/header/mini-basket.tsx +45 -820
  51. package/app-template/src/views/header/navbar.tsx +111 -178
  52. package/app-template/src/views/header/search/index.tsx +32 -71
  53. package/app-template/src/views/header/search/results.tsx +65 -127
  54. package/app-template/src/views/product/accordion-wrapper.tsx +43 -135
  55. package/app-template/src/views/product/index.ts +1 -1
  56. package/app-template/src/views/product/layout.tsx +7 -2
  57. package/app-template/src/views/product/misc-buttons.tsx +25 -339
  58. package/app-template/src/views/product/product-actions.tsx +8 -137
  59. package/app-template/src/views/product/product-info.tsx +31 -69
  60. package/app-template/src/views/product/product-share.tsx +8 -11
  61. package/app-template/src/views/product/slider.tsx +79 -117
  62. package/app-template/src/views/product-item/index.tsx +46 -119
  63. package/app-template/src/widgets/footer-social.tsx +16 -47
  64. package/app-template/src/widgets/footer-subscription/index.tsx +17 -183
  65. package/dist/commands/plugins.js +23 -2
  66. package/package.json +1 -1
  67. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +0 -15
  68. package/app-template/src/views/basket/basket-summary-context.tsx +0 -560
  69. package/app-template/src/views/basket/designer-context.tsx +0 -617
  70. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +0 -190
  71. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +0 -286
  72. package/app-template/src/views/breadcrumb/constants.ts +0 -15
  73. package/app-template/src/views/breadcrumb/index.tsx +0 -127
  74. package/app-template/src/views/category/native-widget-context.tsx +0 -257
  75. package/app-template/src/views/category/product-list-registrar.tsx +0 -665
  76. package/app-template/src/views/checkout/checkout-address-registrar.tsx +0 -254
  77. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +0 -183
  78. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +0 -259
  79. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +0 -253
  80. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +0 -183
  81. package/app-template/src/views/checkout/constants.ts +0 -5
  82. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +0 -15
  83. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +0 -18
  84. package/app-template/src/views/footer/footer-app-banner-context.tsx +0 -326
  85. package/app-template/src/views/footer/footer-bottom-context.tsx +0 -215
  86. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +0 -74
  87. package/app-template/src/views/footer/footer-layout-constants.ts +0 -35
  88. package/app-template/src/views/footer/footer-layout-registrar.tsx +0 -342
  89. package/app-template/src/views/footer/footer-layout-switcher.tsx +0 -110
  90. package/app-template/src/views/footer/footer-menu-context.tsx +0 -211
  91. package/app-template/src/views/footer/footer-native-widgets.tsx +0 -60
  92. package/app-template/src/views/footer/footer-social-context.tsx +0 -254
  93. package/app-template/src/views/footer/footer-subscription-context.tsx +0 -210
  94. package/app-template/src/views/footer/footer-utils.ts +0 -43
  95. package/app-template/src/views/footer/footer-value-props-context.tsx +0 -326
  96. package/app-template/src/views/footer/logo-settings.ts +0 -183
  97. package/app-template/src/views/footer/native-widget-config.ts +0 -262
  98. package/app-template/src/views/footer/subscription-settings.ts +0 -122
  99. package/app-template/src/views/footer/use-footer-logo.ts +0 -162
  100. package/app-template/src/views/header/designer-context.tsx +0 -261
  101. package/app-template/src/views/header/header-announcement-registrar.tsx +0 -267
  102. package/app-template/src/views/header/header-client-wrapper.tsx +0 -496
  103. package/app-template/src/views/header/header-content.tsx +0 -1026
  104. package/app-template/src/views/header/header-currency-registrar.tsx +0 -348
  105. package/app-template/src/views/header/header-icons-context.tsx +0 -262
  106. package/app-template/src/views/header/header-language-registrar.tsx +0 -348
  107. package/app-template/src/views/header/header-layout-context.tsx +0 -143
  108. package/app-template/src/views/header/header-layout-registrar.tsx +0 -658
  109. package/app-template/src/views/header/header-logo-context.tsx +0 -228
  110. package/app-template/src/views/header/header-logo.tsx +0 -118
  111. package/app-template/src/views/header/header-mini-basket-context.tsx +0 -524
  112. package/app-template/src/views/header/header-search-registrar.tsx +0 -511
  113. package/app-template/src/views/header/header-text-slider-registrar.tsx +0 -382
  114. package/app-template/src/views/header/inline-search.tsx +0 -262
  115. package/app-template/src/views/header/navbar-menu-context.tsx +0 -219
  116. package/app-template/src/views/header/search/search-input.tsx +0 -61
  117. package/app-template/src/views/header/server-settings-parser.ts +0 -1105
  118. package/app-template/src/views/header/use-header-icons.ts +0 -241
  119. package/app-template/src/views/header/use-header-logo.ts +0 -213
  120. package/app-template/src/views/header/use-navbar-menu.ts +0 -179
  121. package/app-template/src/views/product/accordion-section.tsx +0 -61
  122. package/app-template/src/views/product/custom-button-group.tsx +0 -69
  123. package/app-template/src/views/product/favorites-button-section.tsx +0 -69
  124. package/app-template/src/views/product/find-in-store-section.tsx +0 -60
  125. package/app-template/src/views/product/product-info-section.tsx +0 -140
  126. package/app-template/src/views/product/quantity-section.tsx +0 -73
  127. package/app-template/src/views/product/sale-tag.tsx +0 -10
  128. package/app-template/src/views/product/share-section.tsx +0 -357
  129. package/app-template/src/views/product/variants-section.tsx +0 -126
  130. package/app-template/src/views/product-detail/constants.ts +0 -272
  131. package/app-template/src/views/product-detail/index.ts +0 -10
  132. package/app-template/src/views/product-detail/product-detail-registrar.tsx +0 -616
  133. package/app-template/src/widgets/footer-app-banner.tsx +0 -444
  134. package/app-template/src/widgets/footer-bottom.tsx +0 -127
  135. package/app-template/src/widgets/footer-menu-compact.tsx +0 -238
  136. package/app-template/src/widgets/footer-menu-two.tsx +0 -298
  137. package/app-template/src/widgets/footer-social-client.tsx +0 -251
  138. package/app-template/src/widgets/footer-value-props.tsx +0 -201
@@ -1,69 +0,0 @@
1
- 'use client';
2
-
3
- import { Icon, Button } from '@theme/components';
4
-
5
- type CustomButtonGroupProps = {
6
- carouselState?: {
7
- currentSlide: number;
8
- totalItems: number;
9
- };
10
- previous?: () => void;
11
- next?: () => void;
12
- goToSlide?: (slide: number) => void;
13
- };
14
-
15
- export default function CustomButtonGroup({
16
- carouselState,
17
- previous,
18
- next
19
- }: CustomButtonGroupProps) {
20
- const currentSlide = carouselState?.currentSlide ?? 0;
21
- const totalItems = carouselState?.totalItems ?? 0;
22
-
23
- if (!totalItems) return null;
24
-
25
- const isFirstSlide = currentSlide === 0;
26
- const isLastSlide = currentSlide >= totalItems - 1;
27
-
28
- const handlePrevClick = () => {
29
- if (isFirstSlide) return;
30
- previous?.();
31
- };
32
-
33
- const handleNextClick = () => {
34
- if (isLastSlide) return;
35
- next?.();
36
- };
37
-
38
- return (
39
- <div className="relative mt-3 w-full">
40
- <div className="flex items-center justify-center gap-2 text-[13px] font-medium text-gray-650">
41
- <Button
42
- type="button"
43
- aria-label="Previous image"
44
- aria-disabled={isFirstSlide}
45
- disabled={isFirstSlide}
46
- onClick={handlePrevClick}
47
- className="bg-transparent text-primary border-none"
48
- >
49
- <Icon name="chevron-start" size={12} />
50
- </Button>
51
-
52
- <span>
53
- {currentSlide + 1}/{totalItems}
54
- </span>
55
-
56
- <Button
57
- type="button"
58
- aria-label="Next image"
59
- aria-disabled={isLastSlide}
60
- disabled={isLastSlide}
61
- onClick={handleNextClick}
62
- className="bg-transparent text-primary border-none"
63
- >
64
- <Icon name="chevron-end" size={12} className="text-gray-900" />
65
- </Button>
66
- </div>
67
- </div>
68
- );
69
- }
@@ -1,69 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Favorites Button Section Wrapper
5
- *
6
- * Wraps favorites button with Theme Editor styling support.
7
- * Applies CSS variables for customization via Theme Editor.
8
- */
9
-
10
- import { PropsWithChildren, CSSProperties, useMemo } from 'react';
11
- import clsx from 'clsx';
12
- import {
13
- useProductDetail,
14
- FAVORITES_BUTTON_SECTION_ID
15
- } from '@theme/views/product-detail';
16
-
17
- export default function FavoritesButtonSection({
18
- children
19
- }: PropsWithChildren) {
20
- const { isDesigner, selectedSectionId, favoritesButtonStyles } =
21
- useProductDetail();
22
-
23
- // Check if this section is selected in designer mode
24
- const isSelected =
25
- isDesigner && selectedSectionId === FAVORITES_BUTTON_SECTION_ID;
26
-
27
- // Build CSS variables from favoritesButtonStyles
28
- const cssVariables = useMemo((): CSSProperties => {
29
- if (!favoritesButtonStyles) return {};
30
-
31
- const vars: Record<string, string> = {};
32
- Object.entries(favoritesButtonStyles).forEach(([key, value]) => {
33
- if (value) {
34
- vars[`--favorites-button-${key}`] = value;
35
- }
36
- });
37
- return vars as CSSProperties;
38
- }, [favoritesButtonStyles]);
39
-
40
- const handleClick = (e: React.MouseEvent) => {
41
- if (isDesigner) {
42
- e.stopPropagation();
43
- window.parent?.postMessage(
44
- {
45
- type: 'SELECT_SECTION',
46
- data: {
47
- placeholderId: 'product-detail',
48
- sectionId: FAVORITES_BUTTON_SECTION_ID
49
- }
50
- },
51
- '*'
52
- );
53
- }
54
- };
55
-
56
- return (
57
- <div
58
- className={clsx(
59
- 'favorites-button-section',
60
- isDesigner && 'cursor-pointer',
61
- isSelected && 'ring-2 ring-blue-500 ring-offset-2'
62
- )}
63
- style={cssVariables}
64
- onClick={handleClick}
65
- >
66
- {children}
67
- </div>
68
- );
69
- }
@@ -1,60 +0,0 @@
1
- 'use client';
2
-
3
- import React, { CSSProperties, useMemo } from 'react';
4
- import { useDesignerFeatures } from '@akinon/next/components/theme-editor/hooks/use-designer-features';
5
- import {
6
- useProductDetail,
7
- PRODUCT_DETAIL_PLACEHOLDER_ID,
8
- FIND_IN_STORE_SECTION_ID
9
- } from '@theme/views/product-detail';
10
-
11
- interface FindInStoreSectionProps {
12
- children: React.ReactNode;
13
- }
14
-
15
- export default function FindInStoreSection({
16
- children
17
- }: FindInStoreSectionProps) {
18
- const { isDesigner, selectedSectionId, findInStoreStyles } =
19
- useProductDetail();
20
-
21
- const { handleClick } = useDesignerFeatures({
22
- sectionId: FIND_IN_STORE_SECTION_ID,
23
- placeholderId: PRODUCT_DETAIL_PLACEHOLDER_ID,
24
- blockId: '',
25
- isDesigner
26
- });
27
-
28
- const isSelected = selectedSectionId === FIND_IN_STORE_SECTION_ID;
29
-
30
- const cssVariables = useMemo((): CSSProperties => {
31
- if (!findInStoreStyles) return {};
32
-
33
- const vars: Record<string, string> = {};
34
- Object.entries(findInStoreStyles).forEach(([key, value]) => {
35
- if (value) {
36
- vars[`--find-in-store-${key}`] = value;
37
- }
38
- });
39
- return vars as CSSProperties;
40
- }, [findInStoreStyles]);
41
-
42
- if (!isDesigner) {
43
- return <>{children}</>;
44
- }
45
-
46
- return (
47
- <div
48
- onClick={handleClick}
49
- style={{
50
- ...cssVariables,
51
- cursor: 'pointer',
52
- outline: isSelected ? '2px solid #3b82f6' : 'none',
53
- outlineOffset: '2px'
54
- }}
55
- data-section-id={FIND_IN_STORE_SECTION_ID}
56
- >
57
- {children}
58
- </div>
59
- );
60
- }
@@ -1,140 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import { Product } from '@akinon/next/types';
5
- import { Price } from '@theme/components';
6
- import {
7
- useProductDetail,
8
- PRODUCT_INFO_SECTION_ID
9
- } from '@theme/views/product-detail';
10
- import clsx from 'clsx';
11
-
12
- interface ProductInfoSectionProps {
13
- product: Product;
14
- }
15
-
16
- export const ProductInfoSection: React.FC<ProductInfoSectionProps> = ({
17
- product
18
- }) => {
19
- const { isDesigner, selectedSectionId, productInfoStyles } =
20
- useProductDetail();
21
-
22
- const isSelected = selectedSectionId === PRODUCT_INFO_SECTION_ID;
23
-
24
- // Handle designer click for section selection
25
- const handleDesignerClick = () => {
26
- if (isDesigner) {
27
- window.parent?.postMessage(
28
- {
29
- type: 'SELECT_SECTION',
30
- data: {
31
- placeholderId: 'product-detail',
32
- sectionId: PRODUCT_INFO_SECTION_ID
33
- }
34
- },
35
- '*'
36
- );
37
- }
38
- };
39
-
40
- const infoStyles: Record<string, string> = {};
41
-
42
- // Product name styles
43
- if (productInfoStyles['name-font-size'])
44
- infoStyles['--product-name-font-size'] =
45
- productInfoStyles['name-font-size'];
46
- if (productInfoStyles['name-font-weight'])
47
- infoStyles['--product-name-font-weight'] =
48
- productInfoStyles['name-font-weight'];
49
- if (productInfoStyles['name-color'])
50
- infoStyles['--product-name-color'] = productInfoStyles['name-color'];
51
- if (productInfoStyles['name-line-height'])
52
- infoStyles['--product-name-line-height'] =
53
- productInfoStyles['name-line-height'];
54
-
55
- // Price styles
56
- if (productInfoStyles['price-font-size'])
57
- infoStyles['--product-price-font-size'] =
58
- productInfoStyles['price-font-size'];
59
- if (productInfoStyles['price-font-weight'])
60
- infoStyles['--product-price-font-weight'] =
61
- productInfoStyles['price-font-weight'];
62
- if (productInfoStyles['price-color'])
63
- infoStyles['--product-price-color'] = productInfoStyles['price-color'];
64
-
65
- // Retail price styles
66
- if (productInfoStyles['retail-price-font-size'])
67
- infoStyles['--product-retail-price-font-size'] =
68
- productInfoStyles['retail-price-font-size'];
69
- if (productInfoStyles['retail-price-font-weight'])
70
- infoStyles['--product-retail-price-font-weight'] =
71
- productInfoStyles['retail-price-font-weight'];
72
- if (productInfoStyles['retail-price-color'])
73
- infoStyles['--product-retail-price-color'] =
74
- productInfoStyles['retail-price-color'];
75
-
76
- // Description styles
77
- if (productInfoStyles['description-font-size'])
78
- infoStyles['--product-description-font-size'] =
79
- productInfoStyles['description-font-size'];
80
- if (productInfoStyles['description-font-weight'])
81
- infoStyles['--product-description-font-weight'] =
82
- productInfoStyles['description-font-weight'];
83
- if (productInfoStyles['description-color'])
84
- infoStyles['--product-description-color'] =
85
- productInfoStyles['description-color'];
86
- if (productInfoStyles['description-line-height'])
87
- infoStyles['--product-description-line-height'] =
88
- productInfoStyles['description-line-height'];
89
-
90
- return (
91
- <div
92
- style={infoStyles}
93
- className={clsx('relative', {
94
- 'ring-2 ring-blue-500 ring-offset-2': isDesigner && isSelected
95
- })}
96
- onClick={handleDesignerClick}
97
- >
98
- {/* Product Name */}
99
- <h1
100
- className="text-3xl text-black-750 mb-4"
101
- style={{
102
- fontSize: 'var(--product-name-font-size, 24px)',
103
- fontWeight: 'var(--product-name-font-weight, 600)',
104
- color: 'var(--product-name-color, #1f2937)',
105
- lineHeight: 'var(--product-name-line-height, 1.2)'
106
- }}
107
- data-testid="product-name"
108
- >
109
- {product.name}
110
- </h1>
111
-
112
- {/* Price */}
113
- <div
114
- className="text-black-750 mb-4"
115
- style={{
116
- fontSize: 'var(--product-price-font-size, 28px)',
117
- fontWeight: 'var(--product-price-font-weight, 700)',
118
- color: 'var(--product-price-color, #030712)'
119
- }}
120
- >
121
- <Price value={product.price} data-testid="price" />
122
- </div>
123
-
124
- {/* Description */}
125
- {product.attributes?.description && (
126
- <p
127
- className="text-black-750 tracking-[0.64px] mb-4"
128
- style={{
129
- fontSize: 'var(--product-description-font-size, 14px)',
130
- fontWeight: 'var(--product-description-font-weight, 400)',
131
- color: 'var(--product-description-color, #6b7280)',
132
- lineHeight: 'var(--product-description-line-height, 1.6)'
133
- }}
134
- >
135
- {product.attributes.description}
136
- </p>
137
- )}
138
- </div>
139
- );
140
- };
@@ -1,73 +0,0 @@
1
- 'use client';
2
-
3
- import { useLocalization } from '@akinon/next/hooks';
4
- import { QuantitySelector } from '@theme/components';
5
- import {
6
- useProductDetail,
7
- QUANTITY_SECTION_ID
8
- } from '@theme/views/product-detail';
9
- import clsx from 'clsx';
10
-
11
- interface QuantitySectionProps {
12
- quantity: number;
13
- onChange: (quantity: number) => void;
14
- disabled?: boolean;
15
- min?: number;
16
- max?: number;
17
- }
18
-
19
- /**
20
- * QuantitySection Component
21
- *
22
- * Wraps QuantitySelector with Theme Editor integration.
23
- * Allows customization of display type (buttons/dropdown) and styles.
24
- */
25
- export function QuantitySection({
26
- quantity,
27
- onChange,
28
- disabled = false,
29
- min = 1,
30
- max = 999
31
- }: QuantitySectionProps) {
32
- const { t } = useLocalization();
33
- const { isDesigner, selectedSectionId, quantityStyles, quantityProperties } =
34
- useProductDetail();
35
-
36
- const isSelected = selectedSectionId === QUANTITY_SECTION_ID;
37
-
38
- // Handle designer click for section selection
39
- const handleDesignerClick = () => {
40
- if (isDesigner) {
41
- window.parent?.postMessage(
42
- {
43
- type: 'SELECT_SECTION',
44
- data: {
45
- placeholderId: 'product-detail',
46
- sectionId: QUANTITY_SECTION_ID
47
- }
48
- },
49
- '*'
50
- );
51
- }
52
- };
53
-
54
- return (
55
- <div className="flex flex-col gap-2.5 mb-4">
56
- <span className="text-[13px] text-black-750 tracking-[0.39px]">
57
- {t('product.quantity')}
58
- </span>
59
- <QuantitySelector
60
- quantity={quantity}
61
- onChange={onChange}
62
- disabled={disabled}
63
- min={min}
64
- max={max}
65
- displayType={quantityProperties.displayType}
66
- maxDropdownOptions={quantityProperties.maxDropdownOptions}
67
- styles={quantityStyles}
68
- isSelected={isSelected}
69
- onDesignerClick={isDesigner ? handleDesignerClick : undefined}
70
- />
71
- </div>
72
- );
73
- }
@@ -1,10 +0,0 @@
1
- import { useLocalization } from '@akinon/next/hooks';
2
-
3
- export function SaleTag() {
4
- const { t } = useLocalization();
5
- return (
6
- <span className="inline-flex items-center px-3 py-1 rounded-full bg-[#014D4E] text-white text-[13px] tracking-[0.39px]">
7
- {t('common.sale')}
8
- </span>
9
- );
10
- }