@xsolla/xui-game-card 0.104.0 → 0.105.0

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.
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  type GameCardSize = "lg" | "md" | "sm";
4
+ type LootBadgeTier = "best" | "better" | "good";
4
5
  interface GameCardProps {
5
6
  /** Game artwork image URL */
6
7
  image: string;
@@ -10,6 +11,8 @@ interface GameCardProps {
10
11
  subtitle?: string;
11
12
  /** Size variant of the card */
12
13
  size?: GameCardSize;
14
+ /** Loot tier badge displayed above tags on the image */
15
+ lootBadge?: LootBadgeTier;
13
16
  /** Custom content for top-left corner tags */
14
17
  tagsTopLeft?: React.ReactNode;
15
18
  /** Custom content for top-right corner tags */
@@ -30,4 +33,4 @@ interface GameCardProps {
30
33
 
31
34
  declare const GameCard: React.FC<GameCardProps>;
32
35
 
33
- export { GameCard, type GameCardProps, type GameCardSize };
36
+ export { GameCard, type GameCardProps, type GameCardSize, type LootBadgeTier };
package/native/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  type GameCardSize = "lg" | "md" | "sm";
4
+ type LootBadgeTier = "best" | "better" | "good";
4
5
  interface GameCardProps {
5
6
  /** Game artwork image URL */
6
7
  image: string;
@@ -10,6 +11,8 @@ interface GameCardProps {
10
11
  subtitle?: string;
11
12
  /** Size variant of the card */
12
13
  size?: GameCardSize;
14
+ /** Loot tier badge displayed above tags on the image */
15
+ lootBadge?: LootBadgeTier;
13
16
  /** Custom content for top-left corner tags */
14
17
  tagsTopLeft?: React.ReactNode;
15
18
  /** Custom content for top-right corner tags */
@@ -30,4 +33,4 @@ interface GameCardProps {
30
33
 
31
34
  declare const GameCard: React.FC<GameCardProps>;
32
35
 
33
- export { GameCard, type GameCardProps, type GameCardSize };
36
+ export { GameCard, type GameCardProps, type GameCardSize, type LootBadgeTier };
package/native/index.js CHANGED
@@ -233,10 +233,10 @@ var getSizeConfig = (size) => {
233
233
  case "lg":
234
234
  return {
235
235
  imageAspectRatio: 366 / 206,
236
- titleFontSize: 14,
237
- titleLineHeight: 18,
238
- subtitleFontSize: 11,
239
- subtitleLineHeight: 14,
236
+ titleFontSize: 16,
237
+ titleLineHeight: 20,
238
+ subtitleFontSize: 12,
239
+ subtitleLineHeight: 18,
240
240
  padding: 8,
241
241
  tagGap: 4,
242
242
  buttonHeight: 32,
@@ -244,15 +244,19 @@ var getSizeConfig = (size) => {
244
244
  buttonFontSize: 12,
245
245
  buttonLineHeight: 14,
246
246
  borderRadius: 4,
247
- fadeHeight: 64
247
+ fadeHeight: 64,
248
+ lootBadgeFontSize: 12,
249
+ lootBadgeLineHeight: 16,
250
+ lootBadgePaddingX: 6,
251
+ lootBadgePaddingY: 4
248
252
  };
249
253
  case "md":
250
254
  return {
251
255
  imageAspectRatio: 280 / 158,
252
- titleFontSize: 13,
253
- titleLineHeight: 16,
254
- subtitleFontSize: 10,
255
- subtitleLineHeight: 12,
256
+ titleFontSize: 14,
257
+ titleLineHeight: 18,
258
+ subtitleFontSize: 11,
259
+ subtitleLineHeight: 16,
256
260
  padding: 6,
257
261
  tagGap: 3,
258
262
  buttonHeight: 28,
@@ -260,15 +264,19 @@ var getSizeConfig = (size) => {
260
264
  buttonFontSize: 11,
261
265
  buttonLineHeight: 13,
262
266
  borderRadius: 4,
263
- fadeHeight: 48
267
+ fadeHeight: 48,
268
+ lootBadgeFontSize: 11,
269
+ lootBadgeLineHeight: 14,
270
+ lootBadgePaddingX: 5,
271
+ lootBadgePaddingY: 3
264
272
  };
265
273
  case "sm":
266
274
  return {
267
275
  imageAspectRatio: 200 / 113,
268
276
  titleFontSize: 12,
269
- titleLineHeight: 14,
270
- subtitleFontSize: 9,
271
- subtitleLineHeight: 11,
277
+ titleLineHeight: 16,
278
+ subtitleFontSize: 10,
279
+ subtitleLineHeight: 14,
272
280
  padding: 4,
273
281
  tagGap: 2,
274
282
  buttonHeight: 24,
@@ -276,15 +284,39 @@ var getSizeConfig = (size) => {
276
284
  buttonFontSize: 10,
277
285
  buttonLineHeight: 12,
278
286
  borderRadius: 4,
279
- fadeHeight: 32
287
+ fadeHeight: 32,
288
+ lootBadgeFontSize: 10,
289
+ lootBadgeLineHeight: 12,
290
+ lootBadgePaddingX: 4,
291
+ lootBadgePaddingY: 2
280
292
  };
281
293
  }
282
294
  };
295
+ var LOOT_BADGE_LABELS = {
296
+ best: "Best Loot",
297
+ better: "Better Loot",
298
+ good: "Good Loot"
299
+ };
300
+ var LOOT_BADGE_WEB_BACKGROUNDS = {
301
+ best: { backgroundColor: "#cef655" },
302
+ better: {
303
+ backgroundImage: "linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)"
304
+ },
305
+ good: {
306
+ backgroundImage: "linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)"
307
+ }
308
+ };
309
+ var LOOT_BADGE_NATIVE_COLORS = {
310
+ best: "#cef655",
311
+ better: "#dff98f",
312
+ good: "#f0fccc"
313
+ };
283
314
  var GameCard = ({
284
315
  image,
285
316
  title,
286
317
  subtitle,
287
318
  size = "lg",
319
+ lootBadge,
288
320
  tagsTopLeft,
289
321
  tagsTopRight,
290
322
  trailing,
@@ -316,7 +348,6 @@ var GameCard = ({
316
348
  borderRadius: `${config.borderRadius}px`,
317
349
  overflow: "hidden"
318
350
  } : {
319
- // React Native shadow properties
320
351
  shadowColor: "#070708",
321
352
  shadowOffset: { width: 0, height: 2 },
322
353
  shadowOpacity: 0.15,
@@ -363,12 +394,11 @@ var GameCard = ({
363
394
  style: import_xui_core.isWeb ? {
364
395
  background: "linear-gradient(to top, rgba(0, 0, 0, 0.48) 0%, transparent 100%)"
365
396
  } : {
366
- // Fallback for React Native - solid semi-transparent overlay
367
397
  backgroundColor: "rgba(0, 0, 0, 0.24)"
368
398
  }
369
399
  }
370
400
  ),
371
- tagsTopLeft && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
401
+ (lootBadge || tagsTopLeft) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
372
402
  Box,
373
403
  {
374
404
  position: "absolute",
@@ -377,7 +407,37 @@ var GameCard = ({
377
407
  flexDirection: "column",
378
408
  gap: config.tagGap,
379
409
  alignItems: "flex-start",
380
- children: tagsTopLeft
410
+ children: [
411
+ lootBadge && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
412
+ Box,
413
+ {
414
+ borderRadius: config.borderRadius,
415
+ paddingHorizontal: config.lootBadgePaddingX,
416
+ paddingVertical: config.lootBadgePaddingY,
417
+ style: import_xui_core.isWeb ? {
418
+ ...LOOT_BADGE_WEB_BACKGROUNDS[lootBadge],
419
+ border: "1px solid rgba(0, 0, 0, 0.15)",
420
+ borderRadius: `${config.borderRadius}px`
421
+ } : {
422
+ backgroundColor: LOOT_BADGE_NATIVE_COLORS[lootBadge],
423
+ borderWidth: 1,
424
+ borderColor: "rgba(0, 0, 0, 0.15)",
425
+ borderRadius: config.borderRadius
426
+ },
427
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
428
+ Text,
429
+ {
430
+ color: theme.colors.content.on.brandExtra,
431
+ fontSize: config.lootBadgeFontSize,
432
+ lineHeight: config.lootBadgeLineHeight,
433
+ fontWeight: "500",
434
+ children: LOOT_BADGE_LABELS[lootBadge]
435
+ }
436
+ )
437
+ }
438
+ ),
439
+ tagsTopLeft
440
+ ]
381
441
  }
382
442
  ),
383
443
  tagsTopRight && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -411,7 +471,7 @@ var GameCard = ({
411
471
  color: theme.colors.content.primary,
412
472
  fontSize: config.titleFontSize,
413
473
  lineHeight: config.titleLineHeight,
414
- fontWeight: "600",
474
+ fontWeight: "500",
415
475
  numberOfLines: 1,
416
476
  style: import_xui_core.isWeb ? {
417
477
  overflow: "hidden",
@@ -443,20 +503,22 @@ var GameCard = ({
443
503
  Box,
444
504
  {
445
505
  onPress: onButtonClick,
446
- backgroundColor: "rgba(0, 0, 0, 0.12)",
447
- borderRadius: 2,
506
+ backgroundColor: theme.colors.control.mono.secondary.bg,
507
+ borderRadius: config.borderRadius,
448
508
  height: config.buttonHeight,
449
509
  paddingHorizontal: config.buttonPaddingX,
450
510
  alignItems: "center",
451
511
  justifyContent: "center",
452
512
  style: import_xui_core.isWeb ? {
453
- backdropFilter: "blur(6px)",
513
+ backdropFilter: "blur(30px)",
514
+ WebkitBackdropFilter: "blur(30px)",
515
+ border: `1px solid ${theme.colors.control.mono.secondary.border}`,
454
516
  cursor: onButtonClick ? "pointer" : "default"
455
517
  } : void 0,
456
518
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
457
519
  Text,
458
520
  {
459
- color: theme.colors.content.primary,
521
+ color: theme.colors.control.mono.text.secondary,
460
522
  fontSize: config.buttonFontSize,
461
523
  lineHeight: config.buttonLineHeight,
462
524
  fontWeight: "500",
@@ -7,6 +7,7 @@
7
7
 
8
8
  import React from "react";
9
9
  declare type GameCardSize = "lg" | "md" | "sm";
10
+ declare type LootBadgeTier = "best" | "better" | "good";
10
11
  declare interface GameCardProps {
11
12
  /**
12
13
  * Game artwork image URL
@@ -28,6 +29,11 @@ declare interface GameCardProps {
28
29
  */
29
30
  size?: GameCardSize;
30
31
 
32
+ /**
33
+ * Loot tier badge displayed above tags on the image
34
+ */
35
+ lootBadge?: LootBadgeTier;
36
+
31
37
  /**
32
38
  * Custom content for top-left corner tags
33
39
  */
@@ -69,5 +75,5 @@ declare interface GameCardProps {
69
75
  className?: string;
70
76
  }
71
77
  declare var GameCard: React.FC<GameCardProps>;
72
- export type { GameCardProps, GameCardSize };
78
+ export type { GameCardProps, GameCardSize, LootBadgeTier };
73
79
  declare export { GameCard };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../src/GameCard.tsx"],"sourcesContent":["export * from \"./GameCard\";\nexport * from \"./types\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, fall back to the system font\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem, isWeb } from \"@xsolla/xui-core\";\nimport type { GameCardProps, GameCardSize } from \"./types\";\n\nconst getSizeConfig = (size: GameCardSize) => {\n switch (size) {\n case \"lg\":\n return {\n imageAspectRatio: 366 / 206,\n titleFontSize: 14,\n titleLineHeight: 18,\n subtitleFontSize: 11,\n subtitleLineHeight: 14,\n padding: 8,\n tagGap: 4,\n buttonHeight: 32,\n buttonPaddingX: 20,\n buttonFontSize: 12,\n buttonLineHeight: 14,\n borderRadius: 4,\n fadeHeight: 64,\n };\n case \"md\":\n return {\n imageAspectRatio: 280 / 158,\n titleFontSize: 13,\n titleLineHeight: 16,\n subtitleFontSize: 10,\n subtitleLineHeight: 12,\n padding: 6,\n tagGap: 3,\n buttonHeight: 28,\n buttonPaddingX: 16,\n buttonFontSize: 11,\n buttonLineHeight: 13,\n borderRadius: 4,\n fadeHeight: 48,\n };\n case \"sm\":\n return {\n imageAspectRatio: 200 / 113,\n titleFontSize: 12,\n titleLineHeight: 14,\n subtitleFontSize: 9,\n subtitleLineHeight: 11,\n padding: 4,\n tagGap: 2,\n buttonHeight: 24,\n buttonPaddingX: 12,\n buttonFontSize: 10,\n buttonLineHeight: 12,\n borderRadius: 4,\n fadeHeight: 32,\n };\n }\n};\n\nexport const GameCard: React.FC<GameCardProps> = ({\n image,\n title,\n subtitle,\n size = \"lg\",\n tagsTopLeft,\n tagsTopRight,\n trailing,\n buttonText,\n onButtonClick,\n onPress,\n imageAlt,\n className,\n}) => {\n const { theme } = useDesignSystem();\n const config = getSizeConfig(size);\n\n const wrapperProps = onPress ? { onPress } : {};\n\n return (\n <Box\n className={className}\n flexDirection=\"column\"\n width=\"100%\"\n {...wrapperProps}\n >\n <Box\n backgroundColor={theme.colors.background.primary}\n borderRadius={config.borderRadius}\n overflow=\"hidden\"\n flexDirection=\"column\"\n style={\n isWeb\n ? {\n boxShadow: theme.shadow.surface,\n borderRadius: `${config.borderRadius}px`,\n overflow: \"hidden\",\n }\n : {\n // React Native shadow properties\n shadowColor: \"#070708\",\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 6,\n elevation: 4,\n borderRadius: config.borderRadius,\n overflow: \"hidden\",\n }\n }\n >\n {/* Image Container */}\n <Box\n position=\"relative\"\n width=\"100%\"\n overflow=\"hidden\"\n style={{\n aspectRatio: config.imageAspectRatio,\n borderTopLeftRadius: config.borderRadius,\n borderTopRightRadius: config.borderRadius,\n }}\n >\n {/* Game Image */}\n <Box\n as=\"img\"\n src={image}\n alt={imageAlt || title}\n position=\"absolute\"\n top={0}\n left={0}\n width=\"100%\"\n height=\"100%\"\n style={isWeb ? { objectFit: \"cover\" } : undefined}\n />\n\n {/* Bottom Gradient Fade */}\n <Box\n position=\"absolute\"\n bottom={0}\n left={0}\n right={0}\n height={config.fadeHeight}\n style={\n isWeb\n ? {\n background:\n \"linear-gradient(to top, rgba(0, 0, 0, 0.48) 0%, transparent 100%)\",\n }\n : {\n // Fallback for React Native - solid semi-transparent overlay\n backgroundColor: \"rgba(0, 0, 0, 0.24)\",\n }\n }\n />\n\n {/* Top Left Tags */}\n {tagsTopLeft && (\n <Box\n position=\"absolute\"\n top={config.padding}\n left={config.padding}\n flexDirection=\"column\"\n gap={config.tagGap}\n alignItems=\"flex-start\"\n >\n {tagsTopLeft}\n </Box>\n )}\n\n {/* Top Right Tags */}\n {tagsTopRight && (\n <Box\n position=\"absolute\"\n top={config.padding}\n right={config.padding}\n flexDirection=\"column\"\n gap={config.tagGap}\n alignItems=\"flex-end\"\n >\n {tagsTopRight}\n </Box>\n )}\n </Box>\n\n {/* Card Footer */}\n <Box\n backgroundColor={theme.colors.background.primary}\n padding={config.padding}\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={8}\n >\n {/* Title and Subtitle */}\n <Box flex={1} flexDirection=\"column\" style={{ minWidth: 0 }}>\n <Text\n color={theme.colors.content.primary}\n fontSize={config.titleFontSize}\n lineHeight={config.titleLineHeight}\n fontWeight=\"600\"\n numberOfLines={1}\n style={\n isWeb\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : undefined\n }\n >\n {title}\n </Text>\n {subtitle && (\n <Text\n color={theme.colors.content.tertiary}\n fontSize={config.subtitleFontSize}\n lineHeight={config.subtitleLineHeight}\n fontWeight=\"400\"\n numberOfLines={1}\n style={\n isWeb\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : undefined\n }\n >\n {subtitle}\n </Text>\n )}\n </Box>\n\n {/* Trailing Content (custom or default button) */}\n {trailing}\n {!trailing && buttonText && (\n <Box\n onPress={onButtonClick}\n backgroundColor=\"rgba(0, 0, 0, 0.12)\"\n borderRadius={2}\n height={config.buttonHeight}\n paddingHorizontal={config.buttonPaddingX}\n alignItems=\"center\"\n justifyContent=\"center\"\n style={\n isWeb\n ? {\n backdropFilter: \"blur(6px)\",\n cursor: onButtonClick ? \"pointer\" : \"default\",\n }\n : undefined\n }\n >\n <Text\n color={theme.colors.content.primary}\n fontSize={config.buttonFontSize}\n lineHeight={config.buttonLineHeight}\n fontWeight=\"500\"\n letterSpacing={0.4}\n >\n {buttonText}\n </Text>\n </Box>\n )}\n </Box>\n </Box>\n </Box>\n );\n};\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../src/GameCard.tsx"],"sourcesContent":["export * from \"./GameCard\";\nexport * from \"./types\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, fall back to the system font\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem, isWeb } from \"@xsolla/xui-core\";\nimport type { GameCardProps, GameCardSize, LootBadgeTier } from \"./types\";\n\nconst getSizeConfig = (size: GameCardSize) => {\n switch (size) {\n case \"lg\":\n return {\n imageAspectRatio: 366 / 206,\n titleFontSize: 16,\n titleLineHeight: 20,\n subtitleFontSize: 12,\n subtitleLineHeight: 18,\n padding: 8,\n tagGap: 4,\n buttonHeight: 32,\n buttonPaddingX: 20,\n buttonFontSize: 12,\n buttonLineHeight: 14,\n borderRadius: 4,\n fadeHeight: 64,\n lootBadgeFontSize: 12,\n lootBadgeLineHeight: 16,\n lootBadgePaddingX: 6,\n lootBadgePaddingY: 4,\n };\n case \"md\":\n return {\n imageAspectRatio: 280 / 158,\n titleFontSize: 14,\n titleLineHeight: 18,\n subtitleFontSize: 11,\n subtitleLineHeight: 16,\n padding: 6,\n tagGap: 3,\n buttonHeight: 28,\n buttonPaddingX: 16,\n buttonFontSize: 11,\n buttonLineHeight: 13,\n borderRadius: 4,\n fadeHeight: 48,\n lootBadgeFontSize: 11,\n lootBadgeLineHeight: 14,\n lootBadgePaddingX: 5,\n lootBadgePaddingY: 3,\n };\n case \"sm\":\n return {\n imageAspectRatio: 200 / 113,\n titleFontSize: 12,\n titleLineHeight: 16,\n subtitleFontSize: 10,\n subtitleLineHeight: 14,\n padding: 4,\n tagGap: 2,\n buttonHeight: 24,\n buttonPaddingX: 12,\n buttonFontSize: 10,\n buttonLineHeight: 12,\n borderRadius: 4,\n fadeHeight: 32,\n lootBadgeFontSize: 10,\n lootBadgeLineHeight: 12,\n lootBadgePaddingX: 4,\n lootBadgePaddingY: 2,\n };\n }\n};\n\nconst LOOT_BADGE_LABELS: Record<LootBadgeTier, string> = {\n best: \"Best Loot\",\n better: \"Better Loot\",\n good: \"Good Loot\",\n};\n\nconst LOOT_BADGE_WEB_BACKGROUNDS: Record<LootBadgeTier, React.CSSProperties> =\n {\n best: { backgroundColor: \"#cef655\" },\n better: {\n backgroundImage:\n \"linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), \" +\n \"linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), \" +\n \"linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), \" +\n \"linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)\",\n },\n good: {\n backgroundImage:\n \"linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), \" +\n \"linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)\",\n },\n };\n\nconst LOOT_BADGE_NATIVE_COLORS: Record<LootBadgeTier, string> = {\n best: \"#cef655\",\n better: \"#dff98f\",\n good: \"#f0fccc\",\n};\n\nexport const GameCard: React.FC<GameCardProps> = ({\n image,\n title,\n subtitle,\n size = \"lg\",\n lootBadge,\n tagsTopLeft,\n tagsTopRight,\n trailing,\n buttonText,\n onButtonClick,\n onPress,\n imageAlt,\n className,\n}) => {\n const { theme } = useDesignSystem();\n const config = getSizeConfig(size);\n\n const wrapperProps = onPress ? { onPress } : {};\n\n return (\n <Box\n className={className}\n flexDirection=\"column\"\n width=\"100%\"\n {...wrapperProps}\n >\n <Box\n backgroundColor={theme.colors.background.primary}\n borderRadius={config.borderRadius}\n overflow=\"hidden\"\n flexDirection=\"column\"\n style={\n isWeb\n ? {\n boxShadow: theme.shadow.surface,\n borderRadius: `${config.borderRadius}px`,\n overflow: \"hidden\",\n }\n : {\n shadowColor: \"#070708\",\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 6,\n elevation: 4,\n borderRadius: config.borderRadius,\n overflow: \"hidden\",\n }\n }\n >\n {/* Image Container */}\n <Box\n position=\"relative\"\n width=\"100%\"\n overflow=\"hidden\"\n style={{\n aspectRatio: config.imageAspectRatio,\n borderTopLeftRadius: config.borderRadius,\n borderTopRightRadius: config.borderRadius,\n }}\n >\n <Box\n as=\"img\"\n src={image}\n alt={imageAlt || title}\n position=\"absolute\"\n top={0}\n left={0}\n width=\"100%\"\n height=\"100%\"\n style={isWeb ? { objectFit: \"cover\" } : undefined}\n />\n\n <Box\n position=\"absolute\"\n bottom={0}\n left={0}\n right={0}\n height={config.fadeHeight}\n style={\n isWeb\n ? {\n background:\n \"linear-gradient(to top, rgba(0, 0, 0, 0.48) 0%, transparent 100%)\",\n }\n : {\n backgroundColor: \"rgba(0, 0, 0, 0.24)\",\n }\n }\n />\n\n {(lootBadge || tagsTopLeft) && (\n <Box\n position=\"absolute\"\n top={config.padding}\n left={config.padding}\n flexDirection=\"column\"\n gap={config.tagGap}\n alignItems=\"flex-start\"\n >\n {lootBadge && (\n <Box\n borderRadius={config.borderRadius}\n paddingHorizontal={config.lootBadgePaddingX}\n paddingVertical={config.lootBadgePaddingY}\n style={\n isWeb\n ? {\n ...LOOT_BADGE_WEB_BACKGROUNDS[lootBadge],\n border: \"1px solid rgba(0, 0, 0, 0.15)\",\n borderRadius: `${config.borderRadius}px`,\n }\n : {\n backgroundColor:\n LOOT_BADGE_NATIVE_COLORS[lootBadge],\n borderWidth: 1,\n borderColor: \"rgba(0, 0, 0, 0.15)\",\n borderRadius: config.borderRadius,\n }\n }\n >\n <Text\n color={theme.colors.content.on.brandExtra}\n fontSize={config.lootBadgeFontSize}\n lineHeight={config.lootBadgeLineHeight}\n fontWeight=\"500\"\n >\n {LOOT_BADGE_LABELS[lootBadge]}\n </Text>\n </Box>\n )}\n {tagsTopLeft}\n </Box>\n )}\n\n {tagsTopRight && (\n <Box\n position=\"absolute\"\n top={config.padding}\n right={config.padding}\n flexDirection=\"column\"\n gap={config.tagGap}\n alignItems=\"flex-end\"\n >\n {tagsTopRight}\n </Box>\n )}\n </Box>\n\n {/* Card Footer */}\n <Box\n backgroundColor={theme.colors.background.primary}\n padding={config.padding}\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={8}\n >\n <Box flex={1} flexDirection=\"column\" style={{ minWidth: 0 }}>\n <Text\n color={theme.colors.content.primary}\n fontSize={config.titleFontSize}\n lineHeight={config.titleLineHeight}\n fontWeight=\"500\"\n numberOfLines={1}\n style={\n isWeb\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : undefined\n }\n >\n {title}\n </Text>\n {subtitle && (\n <Text\n color={theme.colors.content.tertiary}\n fontSize={config.subtitleFontSize}\n lineHeight={config.subtitleLineHeight}\n fontWeight=\"400\"\n numberOfLines={1}\n style={\n isWeb\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : undefined\n }\n >\n {subtitle}\n </Text>\n )}\n </Box>\n\n {trailing}\n {!trailing && buttonText && (\n <Box\n onPress={onButtonClick}\n backgroundColor={theme.colors.control.mono.secondary.bg}\n borderRadius={config.borderRadius}\n height={config.buttonHeight}\n paddingHorizontal={config.buttonPaddingX}\n alignItems=\"center\"\n justifyContent=\"center\"\n style={\n isWeb\n ? {\n backdropFilter: \"blur(30px)\",\n WebkitBackdropFilter: \"blur(30px)\",\n border: `1px solid ${theme.colors.control.mono.secondary.border}`,\n cursor: onButtonClick ? \"pointer\" : \"default\",\n }\n : undefined\n }\n >\n <Text\n color={theme.colors.control.mono.text.secondary}\n fontSize={config.buttonFontSize}\n lineHeight={config.buttonLineHeight}\n fontWeight=\"500\"\n letterSpacing={0.4}\n >\n {buttonText}\n </Text>\n </Box>\n )}\n </Box>\n </Box>\n </Box>\n );\n};\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_jsx_runtime"]}
package/native/index.mjs CHANGED
@@ -211,10 +211,10 @@ var getSizeConfig = (size) => {
211
211
  case "lg":
212
212
  return {
213
213
  imageAspectRatio: 366 / 206,
214
- titleFontSize: 14,
215
- titleLineHeight: 18,
216
- subtitleFontSize: 11,
217
- subtitleLineHeight: 14,
214
+ titleFontSize: 16,
215
+ titleLineHeight: 20,
216
+ subtitleFontSize: 12,
217
+ subtitleLineHeight: 18,
218
218
  padding: 8,
219
219
  tagGap: 4,
220
220
  buttonHeight: 32,
@@ -222,15 +222,19 @@ var getSizeConfig = (size) => {
222
222
  buttonFontSize: 12,
223
223
  buttonLineHeight: 14,
224
224
  borderRadius: 4,
225
- fadeHeight: 64
225
+ fadeHeight: 64,
226
+ lootBadgeFontSize: 12,
227
+ lootBadgeLineHeight: 16,
228
+ lootBadgePaddingX: 6,
229
+ lootBadgePaddingY: 4
226
230
  };
227
231
  case "md":
228
232
  return {
229
233
  imageAspectRatio: 280 / 158,
230
- titleFontSize: 13,
231
- titleLineHeight: 16,
232
- subtitleFontSize: 10,
233
- subtitleLineHeight: 12,
234
+ titleFontSize: 14,
235
+ titleLineHeight: 18,
236
+ subtitleFontSize: 11,
237
+ subtitleLineHeight: 16,
234
238
  padding: 6,
235
239
  tagGap: 3,
236
240
  buttonHeight: 28,
@@ -238,15 +242,19 @@ var getSizeConfig = (size) => {
238
242
  buttonFontSize: 11,
239
243
  buttonLineHeight: 13,
240
244
  borderRadius: 4,
241
- fadeHeight: 48
245
+ fadeHeight: 48,
246
+ lootBadgeFontSize: 11,
247
+ lootBadgeLineHeight: 14,
248
+ lootBadgePaddingX: 5,
249
+ lootBadgePaddingY: 3
242
250
  };
243
251
  case "sm":
244
252
  return {
245
253
  imageAspectRatio: 200 / 113,
246
254
  titleFontSize: 12,
247
- titleLineHeight: 14,
248
- subtitleFontSize: 9,
249
- subtitleLineHeight: 11,
255
+ titleLineHeight: 16,
256
+ subtitleFontSize: 10,
257
+ subtitleLineHeight: 14,
250
258
  padding: 4,
251
259
  tagGap: 2,
252
260
  buttonHeight: 24,
@@ -254,15 +262,39 @@ var getSizeConfig = (size) => {
254
262
  buttonFontSize: 10,
255
263
  buttonLineHeight: 12,
256
264
  borderRadius: 4,
257
- fadeHeight: 32
265
+ fadeHeight: 32,
266
+ lootBadgeFontSize: 10,
267
+ lootBadgeLineHeight: 12,
268
+ lootBadgePaddingX: 4,
269
+ lootBadgePaddingY: 2
258
270
  };
259
271
  }
260
272
  };
273
+ var LOOT_BADGE_LABELS = {
274
+ best: "Best Loot",
275
+ better: "Better Loot",
276
+ good: "Good Loot"
277
+ };
278
+ var LOOT_BADGE_WEB_BACKGROUNDS = {
279
+ best: { backgroundColor: "#cef655" },
280
+ better: {
281
+ backgroundImage: "linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)"
282
+ },
283
+ good: {
284
+ backgroundImage: "linear-gradient(90deg, rgba(206,246,85,0.3) 0%, rgba(206,246,85,0.3) 100%), linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%)"
285
+ }
286
+ };
287
+ var LOOT_BADGE_NATIVE_COLORS = {
288
+ best: "#cef655",
289
+ better: "#dff98f",
290
+ good: "#f0fccc"
291
+ };
261
292
  var GameCard = ({
262
293
  image,
263
294
  title,
264
295
  subtitle,
265
296
  size = "lg",
297
+ lootBadge,
266
298
  tagsTopLeft,
267
299
  tagsTopRight,
268
300
  trailing,
@@ -294,7 +326,6 @@ var GameCard = ({
294
326
  borderRadius: `${config.borderRadius}px`,
295
327
  overflow: "hidden"
296
328
  } : {
297
- // React Native shadow properties
298
329
  shadowColor: "#070708",
299
330
  shadowOffset: { width: 0, height: 2 },
300
331
  shadowOpacity: 0.15,
@@ -341,12 +372,11 @@ var GameCard = ({
341
372
  style: isWeb ? {
342
373
  background: "linear-gradient(to top, rgba(0, 0, 0, 0.48) 0%, transparent 100%)"
343
374
  } : {
344
- // Fallback for React Native - solid semi-transparent overlay
345
375
  backgroundColor: "rgba(0, 0, 0, 0.24)"
346
376
  }
347
377
  }
348
378
  ),
349
- tagsTopLeft && /* @__PURE__ */ jsx3(
379
+ (lootBadge || tagsTopLeft) && /* @__PURE__ */ jsxs(
350
380
  Box,
351
381
  {
352
382
  position: "absolute",
@@ -355,7 +385,37 @@ var GameCard = ({
355
385
  flexDirection: "column",
356
386
  gap: config.tagGap,
357
387
  alignItems: "flex-start",
358
- children: tagsTopLeft
388
+ children: [
389
+ lootBadge && /* @__PURE__ */ jsx3(
390
+ Box,
391
+ {
392
+ borderRadius: config.borderRadius,
393
+ paddingHorizontal: config.lootBadgePaddingX,
394
+ paddingVertical: config.lootBadgePaddingY,
395
+ style: isWeb ? {
396
+ ...LOOT_BADGE_WEB_BACKGROUNDS[lootBadge],
397
+ border: "1px solid rgba(0, 0, 0, 0.15)",
398
+ borderRadius: `${config.borderRadius}px`
399
+ } : {
400
+ backgroundColor: LOOT_BADGE_NATIVE_COLORS[lootBadge],
401
+ borderWidth: 1,
402
+ borderColor: "rgba(0, 0, 0, 0.15)",
403
+ borderRadius: config.borderRadius
404
+ },
405
+ children: /* @__PURE__ */ jsx3(
406
+ Text,
407
+ {
408
+ color: theme.colors.content.on.brandExtra,
409
+ fontSize: config.lootBadgeFontSize,
410
+ lineHeight: config.lootBadgeLineHeight,
411
+ fontWeight: "500",
412
+ children: LOOT_BADGE_LABELS[lootBadge]
413
+ }
414
+ )
415
+ }
416
+ ),
417
+ tagsTopLeft
418
+ ]
359
419
  }
360
420
  ),
361
421
  tagsTopRight && /* @__PURE__ */ jsx3(
@@ -389,7 +449,7 @@ var GameCard = ({
389
449
  color: theme.colors.content.primary,
390
450
  fontSize: config.titleFontSize,
391
451
  lineHeight: config.titleLineHeight,
392
- fontWeight: "600",
452
+ fontWeight: "500",
393
453
  numberOfLines: 1,
394
454
  style: isWeb ? {
395
455
  overflow: "hidden",
@@ -421,20 +481,22 @@ var GameCard = ({
421
481
  Box,
422
482
  {
423
483
  onPress: onButtonClick,
424
- backgroundColor: "rgba(0, 0, 0, 0.12)",
425
- borderRadius: 2,
484
+ backgroundColor: theme.colors.control.mono.secondary.bg,
485
+ borderRadius: config.borderRadius,
426
486
  height: config.buttonHeight,
427
487
  paddingHorizontal: config.buttonPaddingX,
428
488
  alignItems: "center",
429
489
  justifyContent: "center",
430
490
  style: isWeb ? {
431
- backdropFilter: "blur(6px)",
491
+ backdropFilter: "blur(30px)",
492
+ WebkitBackdropFilter: "blur(30px)",
493
+ border: `1px solid ${theme.colors.control.mono.secondary.border}`,
432
494
  cursor: onButtonClick ? "pointer" : "default"
433
495
  } : void 0,
434
496
  children: /* @__PURE__ */ jsx3(
435
497
  Text,
436
498
  {
437
- color: theme.colors.content.primary,
499
+ color: theme.colors.control.mono.text.secondary,
438
500
  fontSize: config.buttonFontSize,
439
501
  lineHeight: config.buttonLineHeight,
440
502
  fontWeight: "500",