spoko-design-system 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +1 -1
- package/.husky/pre-commit +17 -1
- package/.prettierrc +8 -4
- package/CHANGELOG.md +35 -0
- package/index.ts +8 -2
- package/package.json +4 -3
- package/src/components/Badge.vue +1 -4
- package/src/components/Badges.vue +1 -4
- package/src/components/Breadcrumbs.vue +10 -44
- package/src/components/Button.vue +1 -5
- package/src/components/ButtonCopy.astro +2 -7
- package/src/components/ButtonCopy.vue +2 -9
- package/src/components/Card.astro +1 -4
- package/src/components/Category/CategoriesCarousel.astro +3 -11
- package/src/components/Category/CategoryDetails.astro +7 -32
- package/src/components/Category/CategoryLink.vue +1 -5
- package/src/components/Category/CategorySidebarToggler.vue +1 -5
- package/src/components/Category/CategoryTile.astro +2 -9
- package/src/components/Category/CategoryViewToggler.astro +3 -16
- package/src/components/Copyright.astro +1 -4
- package/src/components/Date.astro +1 -4
- package/src/components/Faq.astro +1 -5
- package/src/components/FaqItem.astro +3 -14
- package/src/components/FeaturesList.vue +2 -9
- package/src/components/FuckRussia.vue +9 -36
- package/src/components/HandDrive.astro +2 -12
- package/src/components/Header/Header.astro +3 -14
- package/src/components/Header/SkipToContent.astro +1 -5
- package/src/components/Input.vue +19 -31
- package/src/components/Jumbotron/index.astro +7 -41
- package/src/components/Jumbotron/variants/Default.astro +2 -17
- package/src/components/Jumbotron/variants/Hero.astro +3 -17
- package/src/components/Jumbotron/variants/Post.astro +3 -13
- package/src/components/Jumbotron/variants/PostSplit.astro +3 -13
- package/src/components/Jumbotron.astro +3 -12
- package/src/components/LanguageSuggestion.astro +3 -14
- package/src/components/MainColors.vue +7 -25
- package/src/components/MainInput.vue +2 -1
- package/src/components/Modal.astro +43 -41
- package/src/components/PageContent.astro +1 -4
- package/src/components/PartNumber.vue +1 -4
- package/src/components/PostHeader.astro +3 -13
- package/src/components/PrCode.vue +2 -2
- package/src/components/Product/ProductButton.vue +1 -4
- package/src/components/Product/ProductDetailName.vue +1 -4
- package/src/components/Product/ProductDetails.vue +19 -65
- package/src/components/Product/ProductDoc.vue +1 -4
- package/src/components/Product/ProductEngine.astro +67 -0
- package/src/components/Product/ProductEngineType.vue +1 -4
- package/src/components/Product/ProductEngines.astro +43 -0
- package/src/components/Product/ProductLink.astro +8 -32
- package/src/components/Product/ProductLink.vue +8 -36
- package/src/components/Product/ProductLinkInfo.astro +4 -19
- package/src/components/Product/ProductModel.vue +3 -5
- package/src/components/Product/ProductModels.vue +2 -10
- package/src/components/Product/ProductNumber.astro +6 -26
- package/src/components/Product/ProductPositions.vue +1 -5
- package/src/components/ProductCodes.vue +6 -14
- package/src/components/ProductDetailName.vue +2 -7
- package/src/components/ProductDetailsList.vue +7 -33
- package/src/components/ProductTile.astro +3 -13
- package/src/components/ReloadPrompt.astro +1 -5
- package/src/components/SlimBanner.vue +10 -15
- package/src/components/Table.vue +3 -15
- package/src/components/Translations.vue +1 -4
- package/src/components/layout/CallToAction.astro +2 -7
- package/src/components/layout/Container.astro +1 -3
- package/src/components/layout/Header.astro +2 -12
- package/src/layouts/Layout.astro +2 -9
- package/src/layouts/MainLayout.astro +4 -17
- package/src/layouts/partials/HeadCommon.astro +7 -24
- package/src/layouts/partials/HeadSEO.astro +12 -48
- package/src/pages/components/icons.astro +1 -4
- package/src/pages/components/product-engine.mdx +75 -31
- package/src/pages/core/typography.astro +2 -6
- package/src/pages/index.astro +16 -63
- package/src/scripts/tooltips.ts +33 -28
- package/src/styles/main.css +4 -0
- package/src/styles/tippy-theme.css +4 -2
- package/src/utils/product/getEngineTooltipContent.ts +158 -0
- package/src/utils/product/getPriceFormatted.ts +2 -6
- package/src/utils/product/useFormatProductNumber.ts +1 -4
- package/src/utils/seo/getShorterDescription.ts +1 -4
- package/uno-config/index.ts +1 -1
- package/src/components/Product/ProductEngine.vue +0 -240
- package/src/components/Product/ProductEngines.vue +0 -116
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates HTML content for engine tooltip
|
|
3
|
+
* Used by both SSR (Astro) and CSR (Tippy.js delegation)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface Engine {
|
|
7
|
+
id?: number;
|
|
8
|
+
code: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
info?: string | null;
|
|
11
|
+
serie?: {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
type?: {
|
|
16
|
+
value: string;
|
|
17
|
+
translated: string;
|
|
18
|
+
label: string;
|
|
19
|
+
};
|
|
20
|
+
power?: {
|
|
21
|
+
kw: number;
|
|
22
|
+
ps: number;
|
|
23
|
+
ps_label: string;
|
|
24
|
+
label: string;
|
|
25
|
+
};
|
|
26
|
+
date?: {
|
|
27
|
+
value: string;
|
|
28
|
+
label: string;
|
|
29
|
+
};
|
|
30
|
+
displacement?: {
|
|
31
|
+
value: number;
|
|
32
|
+
label: string;
|
|
33
|
+
};
|
|
34
|
+
compression_ratio?: {
|
|
35
|
+
value: string | null;
|
|
36
|
+
label: string;
|
|
37
|
+
};
|
|
38
|
+
valves?: {
|
|
39
|
+
value: number | null;
|
|
40
|
+
label: string;
|
|
41
|
+
};
|
|
42
|
+
euro?: {
|
|
43
|
+
value: number;
|
|
44
|
+
label: string;
|
|
45
|
+
};
|
|
46
|
+
pivot?: any;
|
|
47
|
+
|
|
48
|
+
// Backward compatibility - old flat structure
|
|
49
|
+
kw?: number;
|
|
50
|
+
ps?: number;
|
|
51
|
+
cc?: number;
|
|
52
|
+
c_ratio?: string | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface EngineTranslations {
|
|
56
|
+
power?: string;
|
|
57
|
+
cc?: string;
|
|
58
|
+
compressionRatio?: string;
|
|
59
|
+
valves?: string;
|
|
60
|
+
euro?: string;
|
|
61
|
+
horsepowerUnit?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const defaultTranslations: EngineTranslations = {
|
|
65
|
+
power: 'Power',
|
|
66
|
+
cc: 'CC',
|
|
67
|
+
compressionRatio: 'C. Ratio',
|
|
68
|
+
valves: 'Valves',
|
|
69
|
+
euro: 'Euro',
|
|
70
|
+
horsepowerUnit: 'PS',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Helper to get series value (supports both old and new API)
|
|
74
|
+
function getSerieValue(engine: Engine): string {
|
|
75
|
+
if (engine.serie && typeof engine.serie === 'object') {
|
|
76
|
+
return engine.serie.value;
|
|
77
|
+
}
|
|
78
|
+
// Backward compatibility - old API
|
|
79
|
+
const serie = engine.serie as any;
|
|
80
|
+
if (!serie) return '';
|
|
81
|
+
return serie === 3 ? 'EA288' : serie === 2 ? 'EA189' : `Serie ${serie}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function getEngineTooltipContent(engine: Engine, translations: EngineTranslations = {}): string {
|
|
85
|
+
const t = { ...defaultTranslations, ...translations };
|
|
86
|
+
|
|
87
|
+
// Header section
|
|
88
|
+
let headerContent = `<strong>${engine.name || engine.code}</strong>`;
|
|
89
|
+
if (engine.info) {
|
|
90
|
+
headerContent += ` <span class="info">${engine.info}</span>`;
|
|
91
|
+
}
|
|
92
|
+
const serieValue = getSerieValue(engine);
|
|
93
|
+
if (serieValue) {
|
|
94
|
+
headerContent += `<div class="series-badge">${serieValue}</div>`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const header = `<div class="tooltip-header">${headerContent}</div>`;
|
|
98
|
+
|
|
99
|
+
// Specs rows
|
|
100
|
+
const rows: string[] = [];
|
|
101
|
+
|
|
102
|
+
// Power (supports both new and old API structure)
|
|
103
|
+
const power = engine.power;
|
|
104
|
+
const oldKw = engine.kw;
|
|
105
|
+
const oldPs = engine.ps;
|
|
106
|
+
|
|
107
|
+
if (power || oldKw || oldPs) {
|
|
108
|
+
const powerValues: string[] = [];
|
|
109
|
+
const kw = power?.kw || oldKw;
|
|
110
|
+
const ps = power?.ps || oldPs;
|
|
111
|
+
const psLabel = power?.ps_label || t.horsepowerUnit;
|
|
112
|
+
const powerLabel = power?.label || t.power;
|
|
113
|
+
|
|
114
|
+
if (kw) powerValues.push(`${kw} kW`);
|
|
115
|
+
if (ps) powerValues.push(`${ps} ${psLabel}`);
|
|
116
|
+
|
|
117
|
+
if (powerValues.length) {
|
|
118
|
+
rows.push(
|
|
119
|
+
`<div class="tooltip-row"><span class="tooltip-label">${powerLabel}:</span><span class="tooltip-value">${powerValues.join(' / ')}</span></div>`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Displacement (CC)
|
|
125
|
+
const displacement = engine.displacement;
|
|
126
|
+
const oldCc = engine.cc;
|
|
127
|
+
|
|
128
|
+
if (displacement || oldCc) {
|
|
129
|
+
const ccValue = displacement?.value || oldCc;
|
|
130
|
+
const ccLabel = displacement?.label || t.cc;
|
|
131
|
+
|
|
132
|
+
if (ccValue) {
|
|
133
|
+
rows.push(
|
|
134
|
+
`<div class="tooltip-row"><span class="tooltip-label">${ccLabel}:</span><span class="tooltip-value">${ccValue} cm³</span></div>`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Euro standard
|
|
140
|
+
const euro = engine.euro;
|
|
141
|
+
|
|
142
|
+
if (euro && typeof euro === 'object') {
|
|
143
|
+
if (euro.value) {
|
|
144
|
+
rows.push(
|
|
145
|
+
`<div class="tooltip-row"><span class="tooltip-label">${euro.label}:</span><span class="tooltip-value">Euro ${euro.value}</span></div>`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
} else if (euro) {
|
|
149
|
+
// Backward compatibility - old API
|
|
150
|
+
rows.push(
|
|
151
|
+
`<div class="tooltip-row"><span class="tooltip-label">${t.euro}:</span><span class="tooltip-value">Euro ${euro}</span></div>`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const specsContent = rows.length ? `<div class="tooltip-specs">${rows.join('')}</div>` : '';
|
|
156
|
+
|
|
157
|
+
return header + specsContent;
|
|
158
|
+
}
|
|
@@ -6,14 +6,10 @@ interface Product {
|
|
|
6
6
|
export const getPriceFormatted = (product: Product) => {
|
|
7
7
|
// Default to EUR formatting for English-only design system
|
|
8
8
|
if (product.price_eur) {
|
|
9
|
-
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(
|
|
10
|
-
product.price_eur
|
|
11
|
-
);
|
|
9
|
+
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(product.price_eur);
|
|
12
10
|
}
|
|
13
11
|
if (product.price_pln) {
|
|
14
|
-
return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(
|
|
15
|
-
product.price_pln
|
|
16
|
-
);
|
|
12
|
+
return new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price_pln);
|
|
17
13
|
}
|
|
18
14
|
return 'no price';
|
|
19
15
|
};
|
|
@@ -20,10 +20,7 @@ export default function useFormatProductNumber(productNumber: string | null): {
|
|
|
20
20
|
let formatted = number;
|
|
21
21
|
|
|
22
22
|
if (isLetter(number[0]) && !isLetter(number[1]) && number.length === 9) {
|
|
23
|
-
formatted = formatted.replace(
|
|
24
|
-
LIQUIDS_PATTERN,
|
|
25
|
-
`$1${separator}$2${separator}$3${separator}$4`
|
|
26
|
-
);
|
|
23
|
+
formatted = formatted.replace(LIQUIDS_PATTERN, `$1${separator}$2${separator}$3${separator}$4`);
|
|
27
24
|
} else if (number.length >= 13) {
|
|
28
25
|
formatted = formatted.replace(
|
|
29
26
|
WHEELS_EMBLEMS_PATTERN,
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
const MAX_DESCRIPTION_LENGTH = 150;
|
|
2
2
|
|
|
3
|
-
export const getShorterDescription = (
|
|
4
|
-
description: string | null,
|
|
5
|
-
limit = MAX_DESCRIPTION_LENGTH
|
|
6
|
-
) => {
|
|
3
|
+
export const getShorterDescription = (description: string | null, limit = MAX_DESCRIPTION_LENGTH) => {
|
|
7
4
|
function cutString(s: string, n: number) {
|
|
8
5
|
const text = s.replaceAll('\n', ' ');
|
|
9
6
|
const cut = text.indexOf('. ', n);
|
package/uno-config/index.ts
CHANGED
|
@@ -207,7 +207,7 @@ export function createSdsConfig(customConfig: CustomConfig = {}) {
|
|
|
207
207
|
presetAttributify(),
|
|
208
208
|
presetIcons({
|
|
209
209
|
scale: 1.2,
|
|
210
|
-
warn:
|
|
210
|
+
warn: false, // Disabled to prevent false positives from JS code scanning
|
|
211
211
|
prefix: 'i-',
|
|
212
212
|
extraProperties: {
|
|
213
213
|
'display': 'inline-block',
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { ref, onMounted, onUnmounted } from 'vue';
|
|
3
|
-
import type { PropType } from 'vue';
|
|
4
|
-
import tippy, { type Instance } from 'tippy.js';
|
|
5
|
-
import 'tippy.js/dist/tippy.css';
|
|
6
|
-
import '../../styles/tippy-theme.css';
|
|
7
|
-
|
|
8
|
-
/*
|
|
9
|
-
VAG group (VW/Audi/Skoda/Seat/Porsche/Bentley/Lamborghini/Ducati/Cupra/Scania/MAN) manufacturer Engine Code
|
|
10
|
-
Displays engine code with detailed tooltip showing: name, power, displacement, dates, etc.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
interface Engine {
|
|
14
|
-
id?: number;
|
|
15
|
-
code: string;
|
|
16
|
-
name?: string;
|
|
17
|
-
info?: string | null;
|
|
18
|
-
serie?: {
|
|
19
|
-
value: string;
|
|
20
|
-
label: string;
|
|
21
|
-
};
|
|
22
|
-
type?: {
|
|
23
|
-
value: string;
|
|
24
|
-
translated: string;
|
|
25
|
-
label: string;
|
|
26
|
-
};
|
|
27
|
-
power?: {
|
|
28
|
-
kw: number;
|
|
29
|
-
ps: number;
|
|
30
|
-
ps_label: string;
|
|
31
|
-
label: string;
|
|
32
|
-
};
|
|
33
|
-
date?: {
|
|
34
|
-
value: string;
|
|
35
|
-
label: string;
|
|
36
|
-
};
|
|
37
|
-
displacement?: {
|
|
38
|
-
value: number;
|
|
39
|
-
label: string;
|
|
40
|
-
};
|
|
41
|
-
compression_ratio?: {
|
|
42
|
-
value: string | null;
|
|
43
|
-
label: string;
|
|
44
|
-
};
|
|
45
|
-
valves?: {
|
|
46
|
-
value: number | null;
|
|
47
|
-
label: string;
|
|
48
|
-
};
|
|
49
|
-
euro?: {
|
|
50
|
-
value: number;
|
|
51
|
-
label: string;
|
|
52
|
-
};
|
|
53
|
-
pivot?: any;
|
|
54
|
-
|
|
55
|
-
// Backward compatibility - old flat structure
|
|
56
|
-
kw?: number;
|
|
57
|
-
ps?: number;
|
|
58
|
-
cc?: number;
|
|
59
|
-
c_ratio?: string | null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const props = defineProps({
|
|
63
|
-
engine: {
|
|
64
|
-
type: Object as PropType<Engine>,
|
|
65
|
-
required: true,
|
|
66
|
-
},
|
|
67
|
-
showComma: {
|
|
68
|
-
type: Boolean,
|
|
69
|
-
default: false,
|
|
70
|
-
required: false,
|
|
71
|
-
},
|
|
72
|
-
translations: {
|
|
73
|
-
type: Object as PropType<{
|
|
74
|
-
power?: string;
|
|
75
|
-
cc?: string;
|
|
76
|
-
compressionRatio?: string;
|
|
77
|
-
valves?: string;
|
|
78
|
-
euro?: string;
|
|
79
|
-
horsepowerUnit?: string; // 'PS' for German, 'KM' for Polish, 'HP' for English
|
|
80
|
-
}>,
|
|
81
|
-
default: () => ({
|
|
82
|
-
power: 'Power',
|
|
83
|
-
cc: 'CC',
|
|
84
|
-
compressionRatio: 'C. Ratio',
|
|
85
|
-
valves: 'Valves',
|
|
86
|
-
euro: 'Euro',
|
|
87
|
-
horsepowerUnit: 'PS',
|
|
88
|
-
}),
|
|
89
|
-
required: false,
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const engineRef = ref<HTMLElement | null>(null);
|
|
94
|
-
let tippyInstance: Instance | null = null;
|
|
95
|
-
|
|
96
|
-
// Helper to get series value (supports both old and new API)
|
|
97
|
-
const getSerieValue = (): string => {
|
|
98
|
-
if (props.engine.serie && typeof props.engine.serie === 'object') {
|
|
99
|
-
return props.engine.serie.value;
|
|
100
|
-
}
|
|
101
|
-
// Backward compatibility - old API
|
|
102
|
-
const serie = props.engine.serie as any;
|
|
103
|
-
if (!serie) return '';
|
|
104
|
-
return serie === 3 ? 'EA288' : serie === 2 ? 'EA189' : `Serie ${serie}`;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// Generate tooltip HTML content
|
|
108
|
-
const getTooltipContent = () => {
|
|
109
|
-
// Header section
|
|
110
|
-
let headerContent = `<strong>${props.engine.name || props.engine.code}</strong>`;
|
|
111
|
-
if (props.engine.info) {
|
|
112
|
-
headerContent += ` <span class="info">${props.engine.info}</span>`;
|
|
113
|
-
}
|
|
114
|
-
const serieValue = getSerieValue();
|
|
115
|
-
if (serieValue) {
|
|
116
|
-
headerContent += `<div class="series-badge">${serieValue}</div>`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const header = `<div class="tooltip-header">${headerContent}</div>`;
|
|
120
|
-
|
|
121
|
-
// Specs rows
|
|
122
|
-
const rows = [];
|
|
123
|
-
|
|
124
|
-
// Power (supports both new and old API structure)
|
|
125
|
-
const power = props.engine.power;
|
|
126
|
-
const oldKw = props.engine.kw;
|
|
127
|
-
const oldPs = props.engine.ps;
|
|
128
|
-
|
|
129
|
-
if (power || oldKw || oldPs) {
|
|
130
|
-
const powerValues = [];
|
|
131
|
-
const kw = power?.kw || oldKw;
|
|
132
|
-
const ps = power?.ps || oldPs;
|
|
133
|
-
const psLabel = power?.ps_label || props.translations.horsepowerUnit;
|
|
134
|
-
const powerLabel = power?.label || props.translations.power;
|
|
135
|
-
|
|
136
|
-
if (kw) powerValues.push(`${kw} kW`);
|
|
137
|
-
if (ps) powerValues.push(`${ps} ${psLabel}`);
|
|
138
|
-
|
|
139
|
-
if (powerValues.length) {
|
|
140
|
-
rows.push(`<div class="tooltip-row"><span class="tooltip-label">${powerLabel}:</span><span class="tooltip-value">${powerValues.join(' / ')}</span></div>`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Displacement (CC)
|
|
145
|
-
const displacement = props.engine.displacement;
|
|
146
|
-
const oldCc = props.engine.cc;
|
|
147
|
-
|
|
148
|
-
if (displacement || oldCc) {
|
|
149
|
-
const ccValue = displacement?.value || oldCc;
|
|
150
|
-
const ccLabel = displacement?.label || props.translations.cc;
|
|
151
|
-
|
|
152
|
-
if (ccValue) {
|
|
153
|
-
rows.push(`<div class="tooltip-row"><span class="tooltip-label">${ccLabel}:</span><span class="tooltip-value">${ccValue} cm³</span></div>`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Euro standard
|
|
158
|
-
const euro = props.engine.euro;
|
|
159
|
-
|
|
160
|
-
if (euro && typeof euro === 'object') {
|
|
161
|
-
if (euro.value) {
|
|
162
|
-
rows.push(`<div class="tooltip-row"><span class="tooltip-label">${euro.label}:</span><span class="tooltip-value">Euro ${euro.value}</span></div>`);
|
|
163
|
-
}
|
|
164
|
-
} else if (euro) {
|
|
165
|
-
// Backward compatibility - old API
|
|
166
|
-
rows.push(`<div class="tooltip-row"><span class="tooltip-label">${props.translations.euro}:</span><span class="tooltip-value">Euro ${euro}</span></div>`);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const specsContent = rows.length
|
|
170
|
-
? `<div class="tooltip-specs">${rows.join('')}</div>`
|
|
171
|
-
: '';
|
|
172
|
-
|
|
173
|
-
return header + specsContent;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
onMounted(() => {
|
|
177
|
-
if (engineRef.value) {
|
|
178
|
-
tippyInstance = tippy(engineRef.value, {
|
|
179
|
-
content: getTooltipContent(),
|
|
180
|
-
allowHTML: true,
|
|
181
|
-
theme: 'sds',
|
|
182
|
-
placement: 'top',
|
|
183
|
-
arrow: true,
|
|
184
|
-
animation: 'shift-away',
|
|
185
|
-
duration: [200, 150],
|
|
186
|
-
maxWidth: 280,
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
onUnmounted(() => {
|
|
192
|
-
if (tippyInstance) {
|
|
193
|
-
tippyInstance.destroy();
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
</script>
|
|
197
|
-
|
|
198
|
-
<template>
|
|
199
|
-
<span
|
|
200
|
-
ref="engineRef"
|
|
201
|
-
class="engine-code"
|
|
202
|
-
:class="`engine-code-${engine.code}`"
|
|
203
|
-
>
|
|
204
|
-
{{ engine.code }}<span v-if="showComma">,</span>
|
|
205
|
-
</span>
|
|
206
|
-
</template>
|
|
207
|
-
|
|
208
|
-
<style scoped>
|
|
209
|
-
/* Engine Code Styles */
|
|
210
|
-
.engine-code {
|
|
211
|
-
@apply inline-block mr-1;
|
|
212
|
-
@apply underline decoration-dotted underline-offset-4 py-0.5;
|
|
213
|
-
@apply decoration-neutral-light cursor-default;
|
|
214
|
-
@apply transition-colors duration-200;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.engine-code:hover {
|
|
218
|
-
@apply decoration-blue-darker dark:decoration-blue-light;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/* Semantic Engine Code Colors */
|
|
222
|
-
/* GTI Engines - Red */
|
|
223
|
-
.engine-code-CAVE,
|
|
224
|
-
.engine-code-CTHE,
|
|
225
|
-
.engine-code-DAJA,
|
|
226
|
-
.engine-code-DAYB {
|
|
227
|
-
@apply text-red-600 dark:text-red-500;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/* WRC R Engine - Blue */
|
|
231
|
-
.engine-code-CDLJ {
|
|
232
|
-
@apply text-blue-600 dark:text-blue-500;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/* Special Blue Engines */
|
|
236
|
-
.engine-code-CPTA,
|
|
237
|
-
.engine-code-CZEA {
|
|
238
|
-
@apply text-blue-700 dark:text-blue-600;
|
|
239
|
-
}
|
|
240
|
-
</style>
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import type { PropType } from 'vue';
|
|
4
|
-
import ProductEngine from './ProductEngine.vue';
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
ProductEngines wrapper component
|
|
8
|
-
Displays a list of engine codes with tooltips
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
interface Engine {
|
|
12
|
-
id?: number;
|
|
13
|
-
code: string;
|
|
14
|
-
name?: string;
|
|
15
|
-
info?: string | null;
|
|
16
|
-
serie?: {
|
|
17
|
-
value: string;
|
|
18
|
-
label: string;
|
|
19
|
-
} | number;
|
|
20
|
-
type?: {
|
|
21
|
-
value: string;
|
|
22
|
-
translated: string;
|
|
23
|
-
label: string;
|
|
24
|
-
};
|
|
25
|
-
power?: {
|
|
26
|
-
kw: number;
|
|
27
|
-
ps: number;
|
|
28
|
-
ps_label: string;
|
|
29
|
-
label: string;
|
|
30
|
-
};
|
|
31
|
-
date?: {
|
|
32
|
-
value: string;
|
|
33
|
-
label: string;
|
|
34
|
-
};
|
|
35
|
-
displacement?: {
|
|
36
|
-
value: number;
|
|
37
|
-
label: string;
|
|
38
|
-
};
|
|
39
|
-
compression_ratio?: {
|
|
40
|
-
value: string | null;
|
|
41
|
-
label: string;
|
|
42
|
-
};
|
|
43
|
-
valves?: {
|
|
44
|
-
value: number | null;
|
|
45
|
-
label: string;
|
|
46
|
-
};
|
|
47
|
-
euro?: {
|
|
48
|
-
value: number;
|
|
49
|
-
label: string;
|
|
50
|
-
} | number;
|
|
51
|
-
pivot?: any;
|
|
52
|
-
|
|
53
|
-
// Backward compatibility
|
|
54
|
-
kw?: number;
|
|
55
|
-
ps?: number;
|
|
56
|
-
cc?: number;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const props = defineProps({
|
|
60
|
-
engines: {
|
|
61
|
-
type: Array as PropType<Engine[]>,
|
|
62
|
-
default: () => [],
|
|
63
|
-
required: true,
|
|
64
|
-
},
|
|
65
|
-
isPdp: {
|
|
66
|
-
type: Boolean,
|
|
67
|
-
default: false,
|
|
68
|
-
required: false,
|
|
69
|
-
},
|
|
70
|
-
translations: {
|
|
71
|
-
type: Object as PropType<{
|
|
72
|
-
power?: string;
|
|
73
|
-
cc?: string;
|
|
74
|
-
compressionRatio?: string;
|
|
75
|
-
valves?: string;
|
|
76
|
-
euro?: string;
|
|
77
|
-
horsepowerUnit?: string;
|
|
78
|
-
}>,
|
|
79
|
-
default: () => ({
|
|
80
|
-
power: 'Power',
|
|
81
|
-
cc: 'CC',
|
|
82
|
-
compressionRatio: 'C. Ratio',
|
|
83
|
-
valves: 'Valves',
|
|
84
|
-
euro: 'Euro',
|
|
85
|
-
horsepowerUnit: 'PS',
|
|
86
|
-
}),
|
|
87
|
-
required: false,
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Sort engines by code
|
|
92
|
-
const sortedEngines = computed(() => {
|
|
93
|
-
if (!props.engines || !props.engines.length) return [];
|
|
94
|
-
return [...props.engines].sort((a, b) => {
|
|
95
|
-
return (a.code || '').localeCompare(b.code || '');
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
</script>
|
|
99
|
-
|
|
100
|
-
<template>
|
|
101
|
-
<div v-if="sortedEngines.length" class="engines-list inline-flex flex-wrap items-center gap-x-0.5">
|
|
102
|
-
<ProductEngine
|
|
103
|
-
v-for="(engine, index) in sortedEngines"
|
|
104
|
-
:key="engine.id || index"
|
|
105
|
-
:engine="engine"
|
|
106
|
-
:show-comma="index !== sortedEngines.length - 1"
|
|
107
|
-
:translations="translations"
|
|
108
|
-
/>
|
|
109
|
-
</div>
|
|
110
|
-
</template>
|
|
111
|
-
|
|
112
|
-
<style scoped>
|
|
113
|
-
.engines-list {
|
|
114
|
-
@apply leading-none;
|
|
115
|
-
}
|
|
116
|
-
</style>
|