spoko-design-system 1.8.1 → 1.9.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.
- package/.claude/settings.json +1 -1
- package/CHANGELOG.md +35 -0
- package/index.ts +8 -2
- package/package.json +4 -3
- package/src/components/Product/ProductEngine.astro +67 -0
- package/src/components/Product/ProductEngines.astro +43 -0
- package/src/pages/components/product-engine.mdx +75 -31
- package/src/pages/index.astro +108 -209
- package/src/scripts/tooltips.ts +33 -28
- package/src/styles/main.css +4 -0
- package/src/utils/product/getEngineTooltipContent.ts +163 -0
- package/uno-config/index.ts +1 -1
- package/src/components/Product/ProductEngine.vue +0 -240
- package/src/components/Product/ProductEngines.vue +0 -116
package/src/pages/index.astro
CHANGED
|
@@ -27,6 +27,68 @@ const navItems = [
|
|
|
27
27
|
icon: 'streamline-freehand-color:layouts-array-1',
|
|
28
28
|
},
|
|
29
29
|
];
|
|
30
|
+
|
|
31
|
+
const features = [
|
|
32
|
+
{
|
|
33
|
+
title: 'Astro-Powered',
|
|
34
|
+
icon: 'vscode-icons:file-type-light-astro',
|
|
35
|
+
description:
|
|
36
|
+
'Built with <a href="https://astro.build/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">Astro</a> for lightning-fast performance and seamless integration with modern frameworks.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
title: 'Rich Components',
|
|
40
|
+
icon: 'streamline-freehand-color:data-transfer-document-module',
|
|
41
|
+
description:
|
|
42
|
+
'20+ production-ready components including buttons, modals, carousels, and specialized automotive elements.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
title: 'UnoCSS Styling',
|
|
46
|
+
icon: 'vscode-icons:file-type-unocss',
|
|
47
|
+
description:
|
|
48
|
+
'Atomic CSS approach with <a href="https://unocss.dev/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">UnoCSS</a> for flexible, maintainable styling and consistent design tokens.',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: 'Vue Integration',
|
|
52
|
+
icon: 'vscode-icons:file-type-vue',
|
|
53
|
+
description:
|
|
54
|
+
'Seamless <a href="https://vuejs.org/" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:text-blue-800 underline transition-colors">Vue 3</a> component integration with TypeScript support for interactive elements.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
title: 'Design Patterns',
|
|
58
|
+
icon: 'streamline-freehand-color:design-process-drawing-board',
|
|
59
|
+
description:
|
|
60
|
+
'Proven patterns and layouts for common use cases, from landing pages to product catalogs.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: 'Developer Ready',
|
|
64
|
+
icon: 'streamline-freehand-color:app-window-source-code',
|
|
65
|
+
description:
|
|
66
|
+
'Complete documentation, TypeScript support, and easy npm installation for quick project setup.',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const exampleSites = [
|
|
71
|
+
{
|
|
72
|
+
url: 'https://catalog.polo.blue',
|
|
73
|
+
title: 'catalog.polo.blue',
|
|
74
|
+
description: 'Car parts catalog',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
url: 'https://polo.blue',
|
|
78
|
+
title: 'polo.blue',
|
|
79
|
+
description: 'Polo 6R DIY workshop & guides',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
url: 'https://sale.polo.blue/',
|
|
83
|
+
title: 'sale.polo.blue',
|
|
84
|
+
description: 'Used car parts marketplace',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
url: 'https://polo6r.pl',
|
|
88
|
+
title: 'polo6r.pl',
|
|
89
|
+
description: 'Polo V Manual',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
30
92
|
---
|
|
31
93
|
|
|
32
94
|
<Layout>
|
|
@@ -61,13 +123,13 @@ const navItems = [
|
|
|
61
123
|
>
|
|
62
124
|
<Headline
|
|
63
125
|
as="h2"
|
|
64
|
-
|
|
126
|
+
class="text-3xl"
|
|
65
127
|
underline={false}
|
|
66
128
|
>
|
|
67
129
|
<Icon
|
|
68
130
|
name={icon}
|
|
69
131
|
aria-hidden="true"
|
|
70
|
-
class="text-blue-400 mr-
|
|
132
|
+
class="text-blue-400 mr-3 text-4xl"
|
|
71
133
|
/>
|
|
72
134
|
{title}
|
|
73
135
|
</Headline>
|
|
@@ -83,9 +145,8 @@ const navItems = [
|
|
|
83
145
|
<div class="text-center mb-12">
|
|
84
146
|
<Headline
|
|
85
147
|
as="h2"
|
|
86
|
-
|
|
148
|
+
class="text-3xl md:text-4xl text-gray-900 mb-6"
|
|
87
149
|
underline="center"
|
|
88
|
-
class="text-gray-900 mb-6"
|
|
89
150
|
>
|
|
90
151
|
Why Spoko Design System?
|
|
91
152
|
</Headline>
|
|
@@ -96,140 +157,28 @@ const navItems = [
|
|
|
96
157
|
</div>
|
|
97
158
|
|
|
98
159
|
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
</p>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
125
|
-
<Headline
|
|
126
|
-
as="h3"
|
|
127
|
-
textSize="xl"
|
|
128
|
-
underline={false}
|
|
129
|
-
class="mb-3 text-gray-900 flex items-center justify-center"
|
|
130
|
-
>
|
|
131
|
-
<Icon
|
|
132
|
-
name="streamline-freehand-color:data-transfer-document-module"
|
|
133
|
-
aria-hidden="true"
|
|
134
|
-
class="text-4xl text-blue-400 mr-3"
|
|
135
|
-
/>
|
|
136
|
-
Rich Components
|
|
137
|
-
</Headline>
|
|
138
|
-
<p class="text-gray-600">
|
|
139
|
-
20+ production-ready components including buttons, modals, carousels, and specialized
|
|
140
|
-
automotive elements.
|
|
141
|
-
</p>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
145
|
-
<Headline
|
|
146
|
-
as="h3"
|
|
147
|
-
textSize="xl"
|
|
148
|
-
underline={false}
|
|
149
|
-
class="mb-3 text-gray-900 flex items-center justify-center"
|
|
150
|
-
>
|
|
151
|
-
<Icon
|
|
152
|
-
name="vscode-icons:file-type-unocss"
|
|
153
|
-
aria-hidden="true"
|
|
154
|
-
class="text-4xl text-blue-400 mr-3"
|
|
155
|
-
/>
|
|
156
|
-
UnoCSS Styling
|
|
157
|
-
</Headline>
|
|
158
|
-
<p class="text-gray-600">
|
|
159
|
-
Atomic CSS approach with <a
|
|
160
|
-
href="https://unocss.dev/"
|
|
161
|
-
target="_blank"
|
|
162
|
-
rel="noopener noreferrer"
|
|
163
|
-
class="text-blue-600 hover:text-blue-800 underline transition-colors"
|
|
164
|
-
>UnoCSS</a
|
|
165
|
-
> for flexible, maintainable styling and consistent design tokens.
|
|
166
|
-
</p>
|
|
167
|
-
</div>
|
|
168
|
-
|
|
169
|
-
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
170
|
-
<Headline
|
|
171
|
-
as="h3"
|
|
172
|
-
textSize="xl"
|
|
173
|
-
underline={false}
|
|
174
|
-
class="mb-3 text-gray-900 flex items-center justify-center"
|
|
175
|
-
>
|
|
176
|
-
<Icon
|
|
177
|
-
name="vscode-icons:file-type-vue"
|
|
178
|
-
aria-hidden="true"
|
|
179
|
-
class="text-4xl text-blue-400 mr-3"
|
|
180
|
-
/>
|
|
181
|
-
Vue Integration
|
|
182
|
-
</Headline>
|
|
183
|
-
<p class="text-gray-600">
|
|
184
|
-
Seamless <a
|
|
185
|
-
href="https://vuejs.org/"
|
|
186
|
-
target="_blank"
|
|
187
|
-
rel="noopener noreferrer"
|
|
188
|
-
class="text-blue-600 hover:text-blue-800 underline transition-colors"
|
|
189
|
-
>Vue 3</a
|
|
190
|
-
> component integration with TypeScript support for interactive elements.
|
|
191
|
-
</p>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
195
|
-
<Headline
|
|
196
|
-
as="h3"
|
|
197
|
-
textSize="xl"
|
|
198
|
-
underline={false}
|
|
199
|
-
class="mb-3 text-gray-900 flex items-center justify-center"
|
|
200
|
-
>
|
|
201
|
-
<Icon
|
|
202
|
-
name="streamline-freehand-color:design-process-drawing-board"
|
|
203
|
-
aria-hidden="true"
|
|
204
|
-
class="text-4xl text-blue-400 mr-3"
|
|
205
|
-
/>
|
|
206
|
-
Design Patterns
|
|
207
|
-
</Headline>
|
|
208
|
-
<p class="text-gray-600">
|
|
209
|
-
Proven patterns and layouts for common use cases, from landing pages to product
|
|
210
|
-
catalogs.
|
|
211
|
-
</p>
|
|
212
|
-
</div>
|
|
213
|
-
|
|
214
|
-
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
215
|
-
<Headline
|
|
216
|
-
as="h3"
|
|
217
|
-
textSize="xl"
|
|
218
|
-
underline={false}
|
|
219
|
-
class="mb-3 text-gray-900 flex items-center justify-center"
|
|
220
|
-
>
|
|
221
|
-
<Icon
|
|
222
|
-
name="streamline-freehand-color:app-window-source-code"
|
|
223
|
-
aria-hidden="true"
|
|
224
|
-
class="text-4xl text-blue-400 mr-3"
|
|
225
|
-
/>
|
|
226
|
-
Developer Ready
|
|
227
|
-
</Headline>
|
|
228
|
-
<p class="text-gray-600">
|
|
229
|
-
Complete documentation, TypeScript support, and easy npm installation for quick project
|
|
230
|
-
setup.
|
|
231
|
-
</p>
|
|
232
|
-
</div>
|
|
160
|
+
{
|
|
161
|
+
features.map(({ title, icon, description }) => (
|
|
162
|
+
<div class="text-center p-6 bg-white rounded-lg shadow-sm border border-gray-100">
|
|
163
|
+
<Headline
|
|
164
|
+
as="h3"
|
|
165
|
+
class="text-2xl mb-3 text-gray-900 flex items-center justify-center"
|
|
166
|
+
underline={false}
|
|
167
|
+
>
|
|
168
|
+
<Icon
|
|
169
|
+
name={icon}
|
|
170
|
+
aria-hidden="true"
|
|
171
|
+
class="text-4xl text-blue-400 mr-3"
|
|
172
|
+
/>
|
|
173
|
+
{title}
|
|
174
|
+
</Headline>
|
|
175
|
+
<p
|
|
176
|
+
class="text-gray-600"
|
|
177
|
+
set:html={description}
|
|
178
|
+
/>
|
|
179
|
+
</div>
|
|
180
|
+
))
|
|
181
|
+
}
|
|
233
182
|
</div>
|
|
234
183
|
</section>
|
|
235
184
|
|
|
@@ -252,8 +201,7 @@ const navItems = [
|
|
|
252
201
|
<Headline
|
|
253
202
|
underline
|
|
254
203
|
as="h2"
|
|
255
|
-
class="text-gray-900 mb-8"
|
|
256
|
-
textSize="3xl"
|
|
204
|
+
class="text-3xl text-gray-900 mb-8"
|
|
257
205
|
>
|
|
258
206
|
<Icon
|
|
259
207
|
name="streamline-freehand-color:archive-box"
|
|
@@ -313,8 +261,7 @@ const navItems = [
|
|
|
313
261
|
<Headline
|
|
314
262
|
underline
|
|
315
263
|
as="h2"
|
|
316
|
-
class="text-gray-900 mb-8"
|
|
317
|
-
textSize="3xl"
|
|
264
|
+
class="text-3xl text-gray-900 mb-8"
|
|
318
265
|
>
|
|
319
266
|
<Icon
|
|
320
267
|
name="streamline-freehand-color:coding-files-network-folder"
|
|
@@ -326,73 +273,25 @@ const navItems = [
|
|
|
326
273
|
|
|
327
274
|
<!-- Example Sites Grid -->
|
|
328
275
|
<div class="grid gap-4 mb-6">
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
href="https://polo.blue"
|
|
349
|
-
target="_blank"
|
|
350
|
-
rel="noopener noreferrer"
|
|
351
|
-
class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group"
|
|
352
|
-
>
|
|
353
|
-
<div class="text-left">
|
|
354
|
-
<h4 class="font-semibold text-gray-900 group-hover:text-blue-600">polo.blue</h4>
|
|
355
|
-
<p class="text-sm text-gray-600">Polo 6R DIY workshop & guides</p>
|
|
356
|
-
</div>
|
|
357
|
-
<Icon
|
|
358
|
-
name="lucide:link"
|
|
359
|
-
class="text-gray-400 group-hover:text-blue-400"
|
|
360
|
-
/>
|
|
361
|
-
</a>
|
|
362
|
-
|
|
363
|
-
<a
|
|
364
|
-
href="https://sale.polo.blue/"
|
|
365
|
-
target="_blank"
|
|
366
|
-
rel="noopener noreferrer"
|
|
367
|
-
class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group"
|
|
368
|
-
>
|
|
369
|
-
<div class="text-left">
|
|
370
|
-
<h4 class="font-semibold text-gray-900 group-hover:text-blue-600">
|
|
371
|
-
sale.polo.blue
|
|
372
|
-
</h4>
|
|
373
|
-
<p class="text-sm text-gray-600">Used car parts marketplace</p>
|
|
374
|
-
</div>
|
|
375
|
-
<Icon
|
|
376
|
-
name="lucide:link"
|
|
377
|
-
class="text-gray-400 group-hover:text-blue-400"
|
|
378
|
-
/>
|
|
379
|
-
</a>
|
|
380
|
-
|
|
381
|
-
<a
|
|
382
|
-
href="https://polo6r.pl"
|
|
383
|
-
target="_blank"
|
|
384
|
-
rel="noopener noreferrer"
|
|
385
|
-
class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group"
|
|
386
|
-
>
|
|
387
|
-
<div class="text-left">
|
|
388
|
-
<h4 class="font-semibold text-gray-900 group-hover:text-blue-600">polo6r.pl</h4>
|
|
389
|
-
<p class="text-sm text-gray-600">Polo V Manual</p>
|
|
390
|
-
</div>
|
|
391
|
-
<Icon
|
|
392
|
-
name="lucide:link"
|
|
393
|
-
class="text-gray-400 group-hover:text-blue-400"
|
|
394
|
-
/>
|
|
395
|
-
</a>
|
|
276
|
+
{
|
|
277
|
+
exampleSites.map(({ url, title, description }) => (
|
|
278
|
+
<a
|
|
279
|
+
href={url}
|
|
280
|
+
target="_blank"
|
|
281
|
+
rel="noopener noreferrer"
|
|
282
|
+
class="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all group"
|
|
283
|
+
>
|
|
284
|
+
<div class="text-left">
|
|
285
|
+
<h4 class="font-semibold text-gray-900 group-hover:text-blue-600">{title}</h4>
|
|
286
|
+
<p class="text-sm text-gray-600">{description}</p>
|
|
287
|
+
</div>
|
|
288
|
+
<Icon
|
|
289
|
+
name="lucide:link"
|
|
290
|
+
class="text-gray-400 group-hover:text-blue-400"
|
|
291
|
+
/>
|
|
292
|
+
</a>
|
|
293
|
+
))
|
|
294
|
+
}
|
|
396
295
|
</div>
|
|
397
296
|
|
|
398
297
|
<p class="text-gray-600 text-sm">
|
package/src/scripts/tooltips.ts
CHANGED
|
@@ -1,46 +1,51 @@
|
|
|
1
|
-
import tippy from 'tippy.js';
|
|
2
|
-
import 'tippy.js/dist/tippy.css';
|
|
3
|
-
import '../styles/tippy-theme.css';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
|
-
* Global
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* Global tooltip delegation script for SDS
|
|
3
|
+
* Uses Tippy.js delegation pattern for performance
|
|
4
|
+
* Handles tooltips for:
|
|
5
|
+
* - Engine codes (.engine-code)
|
|
6
|
+
* - PR codes (.btn-prcode)
|
|
7
|
+
* - Any other elements with data-tippy-content
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
// Destroy existing tooltips to avoid duplicates
|
|
13
|
-
document.querySelectorAll('[data-tippy-content]').forEach((el: any) => {
|
|
14
|
-
if (el._tippy) {
|
|
15
|
-
el._tippy.destroy();
|
|
16
|
-
}
|
|
17
|
-
});
|
|
10
|
+
import { delegate } from 'tippy.js';
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Initialize tooltips with delegation pattern
|
|
14
|
+
* Call this once in your layout after page load
|
|
15
|
+
*/
|
|
16
|
+
export function initTooltips() {
|
|
17
|
+
// Delegate to body for all tooltip targets
|
|
18
|
+
delegate('body', {
|
|
19
|
+
target: '[data-tippy-content]', // Any element with data-tippy-content
|
|
20
|
+
allowHTML: true,
|
|
21
21
|
theme: 'sds',
|
|
22
22
|
placement: 'top',
|
|
23
23
|
arrow: true,
|
|
24
24
|
animation: 'shift-away',
|
|
25
25
|
duration: [200, 150],
|
|
26
26
|
maxWidth: 280,
|
|
27
|
-
|
|
27
|
+
// Only show tooltip if there's actual content
|
|
28
|
+
onShow(instance) {
|
|
29
|
+
const content = instance.props.content;
|
|
30
|
+
if (!content || content === '' || content === 'undefined') {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
28
34
|
});
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
//
|
|
32
|
-
if (typeof
|
|
33
|
-
|
|
34
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
37
|
+
// Auto-initialize on Astro page load (for View Transitions)
|
|
38
|
+
if (typeof document !== 'undefined') {
|
|
39
|
+
document.addEventListener('astro:page-load', () => {
|
|
35
40
|
initTooltips();
|
|
36
|
-
// Reinitialize after a short delay to catch Vue components
|
|
37
|
-
setTimeout(initTooltips, 100);
|
|
38
41
|
});
|
|
39
42
|
|
|
40
|
-
//
|
|
41
|
-
document.
|
|
43
|
+
// Fallback for non-Astro or initial load
|
|
44
|
+
if (document.readyState === 'loading') {
|
|
45
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
46
|
+
initTooltips();
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
42
49
|
initTooltips();
|
|
43
|
-
|
|
44
|
-
setTimeout(initTooltips, 100);
|
|
45
|
-
});
|
|
50
|
+
}
|
|
46
51
|
}
|
package/src/styles/main.css
CHANGED
|
@@ -0,0 +1,163 @@
|
|
|
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(
|
|
85
|
+
engine: Engine,
|
|
86
|
+
translations: EngineTranslations = {}
|
|
87
|
+
): string {
|
|
88
|
+
const t = { ...defaultTranslations, ...translations };
|
|
89
|
+
|
|
90
|
+
// Header section
|
|
91
|
+
let headerContent = `<strong>${engine.name || engine.code}</strong>`;
|
|
92
|
+
if (engine.info) {
|
|
93
|
+
headerContent += ` <span class="info">${engine.info}</span>`;
|
|
94
|
+
}
|
|
95
|
+
const serieValue = getSerieValue(engine);
|
|
96
|
+
if (serieValue) {
|
|
97
|
+
headerContent += `<div class="series-badge">${serieValue}</div>`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const header = `<div class="tooltip-header">${headerContent}</div>`;
|
|
101
|
+
|
|
102
|
+
// Specs rows
|
|
103
|
+
const rows: string[] = [];
|
|
104
|
+
|
|
105
|
+
// Power (supports both new and old API structure)
|
|
106
|
+
const power = engine.power;
|
|
107
|
+
const oldKw = engine.kw;
|
|
108
|
+
const oldPs = engine.ps;
|
|
109
|
+
|
|
110
|
+
if (power || oldKw || oldPs) {
|
|
111
|
+
const powerValues: string[] = [];
|
|
112
|
+
const kw = power?.kw || oldKw;
|
|
113
|
+
const ps = power?.ps || oldPs;
|
|
114
|
+
const psLabel = power?.ps_label || t.horsepowerUnit;
|
|
115
|
+
const powerLabel = power?.label || t.power;
|
|
116
|
+
|
|
117
|
+
if (kw) powerValues.push(`${kw} kW`);
|
|
118
|
+
if (ps) powerValues.push(`${ps} ${psLabel}`);
|
|
119
|
+
|
|
120
|
+
if (powerValues.length) {
|
|
121
|
+
rows.push(
|
|
122
|
+
`<div class="tooltip-row"><span class="tooltip-label">${powerLabel}:</span><span class="tooltip-value">${powerValues.join(' / ')}</span></div>`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Displacement (CC)
|
|
128
|
+
const displacement = engine.displacement;
|
|
129
|
+
const oldCc = engine.cc;
|
|
130
|
+
|
|
131
|
+
if (displacement || oldCc) {
|
|
132
|
+
const ccValue = displacement?.value || oldCc;
|
|
133
|
+
const ccLabel = displacement?.label || t.cc;
|
|
134
|
+
|
|
135
|
+
if (ccValue) {
|
|
136
|
+
rows.push(
|
|
137
|
+
`<div class="tooltip-row"><span class="tooltip-label">${ccLabel}:</span><span class="tooltip-value">${ccValue} cm³</span></div>`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Euro standard
|
|
143
|
+
const euro = engine.euro;
|
|
144
|
+
|
|
145
|
+
if (euro && typeof euro === 'object') {
|
|
146
|
+
if (euro.value) {
|
|
147
|
+
rows.push(
|
|
148
|
+
`<div class="tooltip-row"><span class="tooltip-label">${euro.label}:</span><span class="tooltip-value">Euro ${euro.value}</span></div>`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
} else if (euro) {
|
|
152
|
+
// Backward compatibility - old API
|
|
153
|
+
rows.push(
|
|
154
|
+
`<div class="tooltip-row"><span class="tooltip-label">${t.euro}:</span><span class="tooltip-value">Euro ${euro}</span></div>`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const specsContent = rows.length
|
|
159
|
+
? `<div class="tooltip-specs">${rows.join('')}</div>`
|
|
160
|
+
: '';
|
|
161
|
+
|
|
162
|
+
return header + specsContent;
|
|
163
|
+
}
|
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',
|