|
3 | 3 | import React, { forwardRef, useRef, useState, useLayoutEffect, useEffect } from 'react'; |
4 | 4 | import { GermanPlateConfig, PlateStyle, GermanState, AustrianState, SwissCanton } from '@/types/plate'; |
5 | 5 | import EUBand from './EUBand'; |
| 6 | +import UKBand from './UKBand'; |
6 | 7 | import StatePlakette from './StatePlakette'; |
7 | 8 | import AustrianStatePlakette from './AustrianStatePlakette'; |
8 | 9 | import HungarianCoatOfArms from './HungarianCoatOfArms'; |
@@ -92,7 +93,7 @@ function getCountryFeatures(country: string): { |
92 | 93 |
|
93 | 94 | const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
94 | 95 | ({ config, scale = 1 }, ref) => { |
95 | | - const { cityCode, letters, numbers, suffix, showStatePlakette, showHUPlakette, state, city, huYear, huMonth, width, plateStyle, plateType, country, fontColor, backgroundColor, plateText, rightBandText, seasonalPlate } = config; |
| 96 | + const { cityCode, letters, numbers, suffix, showStatePlakette, showHUPlakette, state, city, huYear, huMonth, width, plateStyle, plateType, country, fontColor, backgroundColor, plateText, rightBandText, seasonalPlate, showUKFlag, isEV } = config; |
96 | 97 |
|
97 | 98 | const contentRef = useRef<HTMLDivElement>(null); |
98 | 99 | const plateRef = useRef<HTMLDivElement>(null); |
@@ -127,7 +128,8 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
127 | 128 | const fontPromises = [ |
128 | 129 | document.fonts.load('105px EuroPlate'), |
129 | 130 | document.fonts.load('105px "Google Sans"'), |
130 | | - document.fonts.load('105px Tratex') |
| 131 | + document.fonts.load('105px Tratex'), |
| 132 | + document.fonts.load('105px UKNumberPlate') |
131 | 133 | ]; |
132 | 134 |
|
133 | 135 | Promise.all(fontPromises).then(() => { |
@@ -162,13 +164,16 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
162 | 164 | const textColor = fontColor; |
163 | 165 | const plateBgColor = backgroundColor; |
164 | 166 | const redStripeHeight = 2 * scale; |
| 167 | + const hasUkBand = country === 'GB' && (showUKFlag || isEV); |
| 168 | + const ukBandWidth = hasUkBand ? 40 * scale : 0; // UK band width when shown |
165 | 169 |
|
166 | 170 | // Available width for content (after EU band, borders, padding, and right band if present) |
167 | | - // Switzerland (CH) has no EU band |
168 | | - const effectiveEuBandWidth = country === 'CH' ? 0 : euBandWidth; |
| 171 | + // Switzerland (CH) has no EU band, UK (GB) has UK band instead |
| 172 | + const effectiveEuBandWidth = (country === 'CH' || country === 'GB') ? 0 : euBandWidth; |
| 173 | + const effectiveLeftOffset = country === 'GB' ? ukBandWidth : effectiveEuBandWidth; |
169 | 174 | const rightBandWidth = countryFeatures.hasRightBand ? euBandWidth : 0; |
170 | 175 | const seasonalPlateWidth = (isGermany && seasonalPlate) ? 37 * scale : 0; // Reserve space for seasonal numbers |
171 | | - const availableWidth = plateWidth - effectiveEuBandWidth - rightBandWidth - seasonalPlateWidth - (borderWidth * 2) - (padding * 2); |
| 176 | + const availableWidth = plateWidth - effectiveLeftOffset - rightBandWidth - seasonalPlateWidth - (borderWidth * 2) - (padding * 2); |
172 | 177 |
|
173 | 178 | // Create a content key that changes when content changes - forces remeasurement |
174 | 179 | const contentKey = `${cityCode}-${letters}-${numbers}-${suffix}-${showStatePlakette}-${showHUPlakette}-${plateText}-${plateType}-${country}-${seasonalPlate?.startMonth}-${seasonalPlate?.endMonth}`; |
@@ -221,12 +226,19 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
221 | 226 | } |
222 | 227 | }, [contentKey, availableWidth, scale, fontLoaded, width, euBandWidth, effectiveEuBandWidth, borderWidth, padding, isGermany, seasonalPlate, minCompactWidth, countryFeatures.hasRightBand]); |
223 | 228 |
|
| 229 | + // Select font based on country |
| 230 | + const getFontFamily = () => { |
| 231 | + if (country === 'S') return 'Tratex, Normal'; |
| 232 | + if (country === 'GB') return 'UKNumberPlate, sans-serif'; |
| 233 | + return 'EuroPlate, sans-serif'; |
| 234 | + }; |
| 235 | + |
224 | 236 | const baseTextStyle: React.CSSProperties = { |
225 | 237 | fontSize: `${fontSize}px`, |
226 | 238 | fontWeight: 'normal', |
227 | 239 | letterSpacing: `${2 * scale}px`, |
228 | 240 | whiteSpace: 'nowrap', |
229 | | - fontFamily: country === 'S' ? 'Tratex, Normal' : 'EuroPlate, sans-serif', |
| 241 | + fontFamily: getFontFamily(), |
230 | 242 | }; |
231 | 243 |
|
232 | 244 | // Carbon fiber pattern - woven checkerboard |
@@ -330,7 +342,7 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
330 | 342 | backgroundColor: plateBgColor, |
331 | 343 | border: `${borderWidth}px solid ${country === 'A' ? 'transparent' : styles.borderColor}`, |
332 | 344 | borderRadius: `${8 * scale}px`, |
333 | | - fontFamily: country === 'S' ? 'Tratex, Normal' : 'EuroPlate, sans-serif', |
| 345 | + fontFamily: getFontFamily(), |
334 | 346 | transformStyle: 'preserve-3d', |
335 | 347 | overflow: 'hidden', |
336 | 348 | boxShadow: styles.is3D |
@@ -382,8 +394,8 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
382 | 394 | </> |
383 | 395 | )} |
384 | 396 |
|
385 | | - {/* EU Band or German Flag for military - not shown for Switzerland */} |
386 | | - {country === 'CH' ? null : country === 'D' && cityCode === 'Y' ? ( |
| 397 | + {/* EU Band or German Flag for military - not shown for Switzerland or UK */} |
| 398 | + {country === 'CH' || country === 'GB' ? null : country === 'D' && cityCode === 'Y' ? ( |
387 | 399 | /* German Flag for military plates */ |
388 | 400 | <div style={{ |
389 | 401 | position: 'absolute', |
@@ -424,7 +436,20 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
424 | 436 | padding: country === 'A' ? `0 ${3 * scale}px` : '0', |
425 | 437 | zIndex: 2, |
426 | 438 | }}> |
427 | | - <EUBand scale={scale} countryCode={country} height={country === 'A' ? '100%' : undefined} noBorderRadius={country === 'A'} showDinGepruft={isGermany} /> |
| 439 | + <EUBand scale={scale} countryCode={country} height={country === 'A' ? '100%' : undefined} noBorderRadius={country === 'A'} showDinGepruft={isGermany} borderRadius={5} /> |
| 440 | + </div> |
| 441 | + )} |
| 442 | + |
| 443 | + {/* UK Band - with flag and UK text, green for EV */} |
| 444 | + {country === 'GB' && (showUKFlag || isEV) && ( |
| 445 | + <div style={{ |
| 446 | + position: 'absolute', |
| 447 | + left: 0, |
| 448 | + top: 0, |
| 449 | + bottom: 0, |
| 450 | + zIndex: 2, |
| 451 | + }}> |
| 452 | + <UKBand scale={scale} height="100%" showFlag={showUKFlag} isEV={isEV} borderRadius={5} /> |
428 | 453 | </div> |
429 | 454 | )} |
430 | 455 |
|
@@ -457,7 +482,7 @@ const LicensePlate = forwardRef<HTMLDivElement, LicensePlateProps>( |
457 | 482 | <div |
458 | 483 | style={{ |
459 | 484 | position: 'absolute', |
460 | | - left: country === 'CH' ? 0 : `${euBandWidth}px`, |
| 485 | + left: country === 'CH' ? 0 : (country === 'GB' && hasUkBand) ? `${ukBandWidth}px` : country === 'GB' ? 0 : `${euBandWidth}px`, |
461 | 486 | right: countryFeatures.hasRightBand ? `${euBandWidth}px` : 0, |
462 | 487 | top: 0, |
463 | 488 | bottom: 0, |
|
0 commit comments