@xsolla/xui-avatar 0.128.0 → 0.129.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.
package/README.md CHANGED
@@ -290,7 +290,7 @@ Avatar uses the design system theme for colors:
290
290
  ```typescript
291
291
  // Colors accessed via theme
292
292
  theme.colors.background.secondary // Default avatar background
293
- theme.colors.background.brand.primary // Brand background (e.g. #80EAFF in xsolla-dark)
293
+ theme.colors.background.brand.primary // Brand background (e.g. #80EAFF in dark)
294
294
  theme.colors.content.primary // Text/icon color
295
295
  theme.colors.border.primary // Stroke color
296
296
  ```
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { useDesignSystem } from '@xsolla/xui-core';
2
+ import { ThemeOverrideProps, useResolvedTheme } from '@xsolla/xui-core';
3
3
 
4
- interface AvatarProps {
4
+ interface AvatarProps extends ThemeOverrideProps {
5
5
  /** Image source URL */
6
6
  src?: string;
7
7
  /** Icon component to display when no image is provided */
@@ -9,7 +9,7 @@ interface AvatarProps {
9
9
  /** Text/Initials to display when no image or icon is provided */
10
10
  text?: string;
11
11
  /** Size of the avatar */
12
- size?: "xl" | "lg" | "md" | "sm" | "xs";
12
+ size?: "xl" | "lg" | "md" | "sm" | "xs" | "xxs";
13
13
  /** If true, the avatar will be square with small border radius. If false, it will be a circle. */
14
14
  square?: boolean;
15
15
  /** Whether to show an alert badge */
@@ -34,7 +34,7 @@ interface AvatarProps {
34
34
  declare const Avatar: React.FC<AvatarProps>;
35
35
 
36
36
  /** Theme type from the design system */
37
- type Theme = ReturnType<typeof useDesignSystem>["theme"];
37
+ type Theme = ReturnType<typeof useResolvedTheme>["theme"];
38
38
  /** Item in the avatar group list */
39
39
  interface AvatarGroupItem {
40
40
  /** Image source URL */
@@ -48,7 +48,7 @@ interface AvatarGroupItem {
48
48
  }
49
49
  /** Avatar background mode - preset colors, 'mixed' for cycling, or a theme function */
50
50
  type AvatarBackgroundMode = "mixed" | "brand" | "brandExtra" | "success" | "warning" | "alert" | "neutral" | ((theme: Theme) => string);
51
- interface AvatarGroupProps {
51
+ interface AvatarGroupProps extends ThemeOverrideProps {
52
52
  /**
53
53
  * List of avatars to display in the group.
54
54
  * `tooltip` property is text to be displayed in the tooltip when hovering over the avatar.
package/native/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { useDesignSystem } from '@xsolla/xui-core';
2
+ import { ThemeOverrideProps, useResolvedTheme } from '@xsolla/xui-core';
3
3
 
4
- interface AvatarProps {
4
+ interface AvatarProps extends ThemeOverrideProps {
5
5
  /** Image source URL */
6
6
  src?: string;
7
7
  /** Icon component to display when no image is provided */
@@ -9,7 +9,7 @@ interface AvatarProps {
9
9
  /** Text/Initials to display when no image or icon is provided */
10
10
  text?: string;
11
11
  /** Size of the avatar */
12
- size?: "xl" | "lg" | "md" | "sm" | "xs";
12
+ size?: "xl" | "lg" | "md" | "sm" | "xs" | "xxs";
13
13
  /** If true, the avatar will be square with small border radius. If false, it will be a circle. */
14
14
  square?: boolean;
15
15
  /** Whether to show an alert badge */
@@ -34,7 +34,7 @@ interface AvatarProps {
34
34
  declare const Avatar: React.FC<AvatarProps>;
35
35
 
36
36
  /** Theme type from the design system */
37
- type Theme = ReturnType<typeof useDesignSystem>["theme"];
37
+ type Theme = ReturnType<typeof useResolvedTheme>["theme"];
38
38
  /** Item in the avatar group list */
39
39
  interface AvatarGroupItem {
40
40
  /** Image source URL */
@@ -48,7 +48,7 @@ interface AvatarGroupItem {
48
48
  }
49
49
  /** Avatar background mode - preset colors, 'mixed' for cycling, or a theme function */
50
50
  type AvatarBackgroundMode = "mixed" | "brand" | "brandExtra" | "success" | "warning" | "alert" | "neutral" | ((theme: Theme) => string);
51
- interface AvatarGroupProps {
51
+ interface AvatarGroupProps extends ThemeOverrideProps {
52
52
  /**
53
53
  * List of avatars to display in the group.
54
54
  * `tooltip` property is text to be displayed in the tooltip when hovering over the avatar.
package/native/index.js CHANGED
@@ -78,6 +78,10 @@ var Box = ({
78
78
  left,
79
79
  right,
80
80
  width,
81
+ minWidth,
82
+ minHeight,
83
+ maxWidth,
84
+ maxHeight,
81
85
  flex,
82
86
  overflow,
83
87
  zIndex,
@@ -109,6 +113,10 @@ var Box = ({
109
113
  zIndex,
110
114
  height,
111
115
  width,
116
+ minWidth,
117
+ minHeight,
118
+ maxWidth,
119
+ maxHeight,
112
120
  padding,
113
121
  paddingHorizontal,
114
122
  paddingVertical,
@@ -237,7 +245,7 @@ var Text = ({
237
245
  }
238
246
  const incomingStyle = import_react_native2.StyleSheet.flatten(styleProp);
239
247
  const baseStyle = {
240
- color,
248
+ color: color ?? incomingStyle?.color,
241
249
  fontSize: typeof fontSize === "number" ? fontSize : void 0,
242
250
  fontWeight,
243
251
  fontFamily: resolvedFontFamily,
@@ -297,32 +305,51 @@ var Avatar = ({
297
305
  src,
298
306
  icon,
299
307
  text,
300
- size = "md",
308
+ size = "xl",
301
309
  square = false,
302
310
  badge = false,
303
311
  badgeCount,
304
312
  badgeTone = "alert",
305
313
  stroke = false,
306
314
  backgroundColor,
307
- disableHover = false,
315
+ disableHover = true,
308
316
  "aria-label": ariaLabel,
309
317
  alt,
310
- onClick
318
+ onClick,
319
+ themeMode,
320
+ themeProductContext
311
321
  }) => {
312
- const { theme } = (0, import_xui_core.useDesignSystem)();
322
+ const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
313
323
  const sizeStyles = theme.sizing.avatar(size);
314
324
  const borderRadius = square ? sizeStyles.borderRadiusSquare : sizeStyles.borderRadiusCircle;
315
- const badgeSize = badgeCount ? "xl" : "sm";
325
+ const countSizeMap = {
326
+ xl: "xl",
327
+ lg: "xl",
328
+ md: "lg",
329
+ sm: "lg",
330
+ xs: "sm",
331
+ xxs: "xs"
332
+ };
333
+ const dotSizeMap = {
334
+ xl: "md",
335
+ lg: "md",
336
+ md: "sm",
337
+ sm: "sm",
338
+ xs: "sm",
339
+ xxs: "xxs"
340
+ };
341
+ const badgeSize = badgeCount ? countSizeMap[size] : dotSizeMap[size];
316
342
  const getDotOffset = () => {
317
343
  if (square) {
318
- return { right: -3, top: -3 };
344
+ return size === "xxs" ? { right: -1, top: -1 } : { right: -3, top: -3 };
319
345
  }
320
346
  const circleOffsets = {
321
- xl: { right: 4, top: 4 },
322
- lg: { right: 3, top: 3 },
347
+ xl: { right: 2, top: 2 },
348
+ lg: { right: 2, top: 2 },
323
349
  md: { right: 2, top: 2 },
324
- sm: { right: 1, top: 1 },
325
- xs: { right: 0, top: 0 }
350
+ sm: { right: 2, top: 2 },
351
+ xs: { right: 0, top: 0 },
352
+ xxs: { right: 1, top: 1 }
326
353
  };
327
354
  return circleOffsets[size];
328
355
  };
@@ -354,18 +381,18 @@ var Avatar = ({
354
381
  width: sizeStyles.size,
355
382
  height: sizeStyles.size,
356
383
  borderRadius,
357
- backgroundColor: backgroundColor || theme.colors.background.secondary,
358
- ...!disableHover && !src && {
359
- hoverStyle: {
360
- backgroundColor: theme.colors.overlay.mono
361
- }
362
- },
384
+ backgroundColor: backgroundColor || theme.colors.overlay.mono,
363
385
  alignItems: "center",
364
386
  justifyContent: "center",
365
387
  position: "relative",
366
388
  overflow: "hidden",
367
389
  borderWidth: stroke ? 1 : 0,
368
390
  borderColor: theme.colors.background.primary,
391
+ ...!disableHover && !src && {
392
+ hoverStyle: {
393
+ backgroundColor: theme.colors.overlay.monoHover
394
+ }
395
+ },
369
396
  children: src ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
370
397
  Box,
371
398
  {
@@ -384,7 +411,8 @@ var Avatar = ({
384
411
  {
385
412
  fontSize: sizeStyles.fontSize,
386
413
  color: theme.colors.content.primary,
387
- fontWeight: "600",
414
+ fontWeight: "400",
415
+ letterSpacing: 0.4,
388
416
  children: text
389
417
  }
390
418
  ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -407,7 +435,7 @@ var Avatar = ({
407
435
  {
408
436
  size: badgeSize,
409
437
  tone: badgeTone,
410
- showStroke: true,
438
+ showStroke: size !== "xxs",
411
439
  "aria-label": displayBadgeCount ? `${displayBadgeCount} notifications` : "Notification",
412
440
  children: displayBadgeCount
413
441
  }
@@ -435,9 +463,11 @@ var AvatarGroup = ({
435
463
  maxVisible = 6,
436
464
  stroke = true,
437
465
  avatarBackgroundMode = "mixed",
438
- "aria-label": ariaLabel
466
+ "aria-label": ariaLabel,
467
+ themeMode,
468
+ themeProductContext
439
469
  }) => {
440
- const { theme } = (0, import_xui_core2.useDesignSystem)();
470
+ const { theme } = (0, import_xui_core2.useResolvedTheme)({ themeMode, themeProductContext });
441
471
  const internalSize = sizeMap[size];
442
472
  const totalCount = list.length;
443
473
  const visibleCount = Math.min(totalCount, Math.max(0, maxVisible));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx","../../src/Avatar.tsx","../../src/AvatarGroup.tsx"],"sourcesContent":["export * from \"./Avatar\";\nexport * from \"./AvatarGroup\";\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 {\n Text as RNText,\n TextStyle,\n AccessibilityRole,\n StyleSheet,\n} from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nconst parseNumericValue = (\n value: string | number | undefined\n): number | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = parseFloat(value);\n return isNaN(parsed) ? undefined : parsed;\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n textAlign,\n lineHeight,\n numberOfLines,\n id,\n role,\n style: styleProp,\n ...props\n}) => {\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const incomingStyle = StyleSheet.flatten(styleProp) as TextStyle | undefined;\n\n const baseStyle: 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 textAlign: textAlign ?? incomingStyle?.textAlign,\n lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),\n marginTop: parseNumericValue(\n incomingStyle?.marginTop as number | string | undefined\n ),\n marginBottom: parseNumericValue(\n incomingStyle?.marginBottom as number | string | undefined\n ),\n };\n\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText\n style={baseStyle}\n numberOfLines={numberOfLines}\n testID={id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\nimport { View, ViewStyle } from \"react-native\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Icon: React.FC<IconProps> = ({ children, color, size }) => {\n const style: ViewStyle = {\n width: typeof size === \"number\" ? size : undefined,\n height: typeof size === \"number\" ? size : undefined,\n alignItems: \"center\",\n justifyContent: \"center\",\n };\n\n // On native, we try to pass the color down to children (like Text primitives)\n // to mimic the CSS inheritance behavior of the web version.\n const childrenWithProps = React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n color: child.props.color || color,\n // Also pass size if child seems to be an icon that needs it\n size: child.props.size || size,\n });\n }\n return child;\n });\n\n return <View style={style}>{childrenWithProps}</View>;\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport { User } from \"@xsolla/xui-icons-base\";\n\nexport interface AvatarProps {\n /** Image source URL */\n src?: string;\n /** Icon component to display when no image is provided */\n icon?: React.ReactNode;\n /** Text/Initials to display when no image or icon is provided */\n text?: string;\n /** Size of the avatar */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** If true, the avatar will be square with small border radius. If false, it will be a circle. */\n square?: boolean;\n /** Whether to show an alert badge */\n badge?: boolean;\n /** Number or text to display in the badge notification */\n badgeCount?: React.ReactNode;\n /** If true, the avatar will have a border to separate it from other avatars in a group */\n stroke?: boolean;\n /** Background color for the avatar. Defaults to theme background secondary. */\n backgroundColor?: string;\n /** Disable hover effect. Used internally by AvatarGroup. */\n disableHover?: boolean;\n /** Accessible label for the avatar. Recommended for screen readers. */\n \"aria-label\"?: string;\n /** Alternative text for the avatar image */\n alt?: string;\n /** Click handler for the avatar */\n onClick?: () => void;\n /** Color tone for the badge */\n badgeTone?:\n | \"primary\"\n | \"secondary\"\n | \"brand\"\n | \"brandExtra\"\n | \"success\"\n | \"warning\"\n | \"alert\"\n | \"neutral\";\n}\n\nexport const Avatar: React.FC<AvatarProps> = ({\n src,\n icon,\n text,\n size = \"md\",\n square = false,\n badge = false,\n badgeCount,\n badgeTone = \"alert\",\n stroke = false,\n backgroundColor,\n disableHover = false,\n \"aria-label\": ariaLabel,\n alt,\n onClick,\n}) => {\n const { theme } = useDesignSystem();\n\n const sizeStyles = theme.sizing.avatar(size);\n\n // Border radius based on square or circle variant\n const borderRadius = square\n ? sizeStyles.borderRadiusSquare\n : sizeStyles.borderRadiusCircle;\n\n // Badge size: XL (20px) when showing count, S (8px) for dot-only\n const badgeSize = badgeCount ? \"xl\" : \"sm\";\n\n // Badge offset differs for circle vs square, and for dot vs count\n // Dot badge (8px) needs different offset per avatar size\n const getDotOffset = () => {\n if (square) {\n return { right: -3, top: -3 };\n }\n // Circle - position dot on the edge based on avatar size\n const circleOffsets = {\n xl: { right: 4, top: 4 },\n lg: { right: 3, top: 3 },\n md: { right: 2, top: 2 },\n sm: { right: 1, top: 1 },\n xs: { right: 0, top: 0 },\n };\n return circleOffsets[size];\n };\n\n const badgeOffset = badgeCount\n ? square\n ? sizeStyles.badgeOffsetSquare\n : sizeStyles.badgeOffsetCircle\n : getDotOffset();\n\n // Display badge count\n const displayBadgeCount = badgeCount;\n\n return (\n <Box\n width={sizeStyles.size}\n height={sizeStyles.size}\n position=\"relative\"\n {...(!src && { role: \"img\", \"aria-label\": ariaLabel })}\n {...(onClick && {\n onPress: onClick,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick();\n }\n },\n cursor: \"pointer\",\n role: \"button\",\n tabIndex: 0,\n })}\n >\n <Box\n width={sizeStyles.size}\n height={sizeStyles.size}\n borderRadius={borderRadius}\n backgroundColor={backgroundColor || theme.colors.background.secondary}\n {...(!disableHover &&\n !src && {\n hoverStyle: {\n backgroundColor: theme.colors.overlay.mono,\n },\n })}\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n overflow=\"hidden\"\n borderWidth={stroke ? 1 : 0}\n borderColor={theme.colors.background.primary}\n >\n {src ? (\n <Box\n as=\"img\"\n src={src}\n alt={alt || ariaLabel || \"\"}\n position=\"absolute\"\n top={0}\n left={0}\n width={sizeStyles.size}\n height={sizeStyles.size}\n borderRadius={borderRadius}\n />\n ) : icon ? (\n <Icon size={sizeStyles.iconSize} color={theme.colors.content.primary}>\n {icon}\n </Icon>\n ) : text ? (\n <Text\n fontSize={sizeStyles.fontSize}\n color={theme.colors.content.primary}\n fontWeight=\"600\"\n >\n {text}\n </Text>\n ) : (\n <User\n size={sizeStyles.iconSize}\n color={theme.colors.content.primary}\n />\n )}\n </Box>\n\n {badge && (\n <Box\n position=\"absolute\"\n right={badgeOffset.right}\n top={badgeOffset.top}\n >\n <Badge\n size={badgeSize}\n tone={badgeTone}\n showStroke\n aria-label={\n displayBadgeCount\n ? `${displayBadgeCount} notifications`\n : \"Notification\"\n }\n >\n {displayBadgeCount}\n </Badge>\n </Box>\n )}\n </Box>\n );\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Tooltip } from \"@xsolla/xui-tooltip\";\nimport { Avatar } from \"./Avatar\";\n\n/** Theme type from the design system */\ntype Theme = ReturnType<typeof useDesignSystem>[\"theme\"];\n\n/** Item in the avatar group list */\nexport interface AvatarGroupItem {\n /** Image source URL */\n src?: string;\n /** Initials to display when no image is provided */\n initials?: string;\n /** Click handler for the avatar */\n onClick?: () => void;\n /** Tooltip text to display on hover */\n tooltip?: string;\n}\n\n/** Avatar background mode - preset colors, 'mixed' for cycling, or a theme function */\nexport type AvatarBackgroundMode =\n | \"mixed\"\n | \"brand\"\n | \"brandExtra\"\n | \"success\"\n | \"warning\"\n | \"alert\"\n | \"neutral\"\n | ((theme: Theme) => string);\n\nexport interface AvatarGroupProps {\n /**\n * List of avatars to display in the group.\n * `tooltip` property is text to be displayed in the tooltip when hovering over the avatar.\n */\n list: AvatarGroupItem[];\n /** Size of the avatars in the group */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * The maximum number of avatars to display before collapsing the rest into a \"+N\" counter.\n * If the number of avatars exceeds this value, the extra avatars will be hidden.\n */\n maxVisible?: number;\n /** Whether to show a stroke/border around each avatar */\n stroke?: boolean;\n /**\n * Controls the background color mode for avatars in the group.\n * - 'mixed' (default): Avatars cycle through different colors\n * - 'brand', 'brandExtra', 'success', 'warning', 'alert', 'neutral': Single color for all avatars\n * - Theme function: A function that receives theme and returns any color from the design system.\n * Example: (theme) => theme.colors.core.link.link\n */\n avatarBackgroundMode?: AvatarBackgroundMode;\n /** Accessible label for the avatar group. Defaults to \"Group of X users\". */\n \"aria-label\"?: string;\n}\n\n// Map external size values to internal Avatar size values\nconst sizeMap: Record<\n \"sm\" | \"md\" | \"lg\" | \"xl\",\n \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n> = {\n sm: \"sm\",\n md: \"md\",\n lg: \"lg\",\n xl: \"xl\",\n};\n\nexport const AvatarGroup: React.FC<AvatarGroupProps> = ({\n list,\n size = \"md\",\n maxVisible = 6,\n stroke = true,\n avatarBackgroundMode = \"mixed\",\n \"aria-label\": ariaLabel,\n}) => {\n const { theme } = useDesignSystem();\n\n // Map external size to internal Avatar size\n const internalSize = sizeMap[size];\n\n const totalCount = list.length;\n\n // Determine which avatars to show\n // Ensure maxVisible is non-negative and doesn't exceed totalCount\n const visibleCount = Math.min(totalCount, Math.max(0, maxVisible));\n const visibleListItems = list.slice(0, visibleCount);\n const remainingCount = totalCount - visibleCount;\n\n // Overlap amount: 4px in Figma\n const overlap = -4;\n\n // Background colors for text/icon avatars (cycling through theme colors)\n const mixedBackgrounds = [\n theme.colors.background.alert.secondary,\n theme.colors.background.warning.secondary,\n theme.colors.background.brandExtra.secondary,\n theme.colors.background.neutral.secondary,\n theme.colors.background.brand.secondary,\n theme.colors.background.success.secondary,\n theme.colors.background.success.primary,\n ];\n\n // Preset color mapping\n const presetColors: Record<string, string> = {\n brand: theme.colors.background.brand.secondary,\n brandExtra: theme.colors.background.brandExtra.secondary,\n success: theme.colors.background.success.secondary,\n warning: theme.colors.background.warning.secondary,\n alert: theme.colors.background.alert.secondary,\n neutral: theme.colors.background.neutral.secondary,\n };\n\n // Get background color based on avatarBackgroundMode\n const getBackgroundColor = (index: number): string => {\n if (typeof avatarBackgroundMode === \"function\") {\n return avatarBackgroundMode(theme);\n }\n if (avatarBackgroundMode === \"mixed\") {\n return mixedBackgrounds[index % mixedBackgrounds.length];\n }\n // Preset color mode\n return (\n presetColors[avatarBackgroundMode] || theme.colors.background.secondary\n );\n };\n\n // Default accessible label for the group\n const defaultAriaLabel =\n totalCount === 1\n ? \"1 user\"\n : totalCount === visibleCount\n ? `${totalCount} users`\n : `${visibleCount} of ${totalCount} users`;\n\n // Render an avatar with optional tooltip wrapper\n const renderAvatarWithTooltip = (\n avatar: React.ReactNode,\n tooltip: string | undefined,\n key: number\n ) => {\n if (tooltip) {\n return (\n <Tooltip key={key} content={tooltip} placement=\"top\">\n {avatar}\n </Tooltip>\n );\n }\n return avatar;\n };\n\n return (\n <Box\n flexDirection=\"row\"\n alignItems=\"center\"\n role=\"group\"\n aria-label={ariaLabel || defaultAriaLabel}\n >\n {visibleListItems.map((item, index) => {\n const shouldApplyBackground = !item.src;\n const backgroundColor = shouldApplyBackground\n ? getBackgroundColor(index)\n : undefined;\n\n // Only enable hover for image avatars with onClick\n const shouldEnableHover = !!item.src && !!item.onClick;\n\n const avatar = (\n <Box\n key={index}\n marginLeft={index === 0 ? 0 : overlap}\n zIndex={totalCount - index}\n >\n <Avatar\n src={item.src}\n text={item.initials}\n size={internalSize}\n stroke={stroke}\n backgroundColor={backgroundColor}\n disableHover={!shouldEnableHover}\n onClick={item.onClick}\n {...(item.tooltip ? { \"aria-label\": item.tooltip } : {})}\n />\n </Box>\n );\n\n return renderAvatarWithTooltip(avatar, item.tooltip, index);\n })}\n\n {remainingCount > 0 && (\n <Box marginLeft={overlap} zIndex={0}>\n <Avatar\n size={internalSize}\n text={`+${remainingCount}`}\n stroke={stroke}\n backgroundColor={theme.colors.background.secondary}\n disableHover={true}\n aria-label={`${remainingCount} more ${remainingCount === 1 ? \"user\" : \"users\"}`}\n />\n </Box>\n )}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,0BAQO;AAmID;AAhIC,IAAM,MAA0B,CAAC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,oBAAoB,CAAC,aAAkC;AAAA,IAC3D,iBACE,WAAW,YAAY,kBACnB,WAAW,kBACX;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI;AAAA,EACN;AAEA,QAAM,cAAc,cAAc;AAIlC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb;AAAA,IACA,eAAe;AAAA,IACf,GAAG;AAAA,EACL,IAAI;AAGJ,MAAI,OAAO,SAAS,KAAK;AACvB,UAAM,aAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI;AAAA,IACN;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,EAAE,KAAK,IAAI;AAAA,QACnB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,YAAW;AAAA,QACV,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AAEA,MAAI,SAAS;AACX,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,CAAC,EAAE,QAAQ,MAAM,kBAAkB,OAAO;AAAA,QACjD,QAAQ;AAAA,QACP,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,kBAAkB;AAAA,MACzB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;;;ACvLA,IAAAA,uBAKO;AAmEH,IAAAC,sBAAA;AAhEJ,IAAM,UAA6C;AAAA,EACjD,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AACR;AAEA,IAAM,oBAAoB,CACxB,UACuB;AACvB,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,SAAS,WAAW,KAAK;AAC/B,SAAO,MAAM,MAAM,IAAI,SAAY;AACrC;AAEO,IAAM,OAA4B,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,GAAG;AACL,MAAM;AACJ,MAAI,qBAAqB,aACrB,WAAW,MAAM,GAAG,EAAE,CAAC,EAAE,QAAQ,SAAS,EAAE,EAAE,KAAK,IACnD;AAEJ,MACE,uBAAuB,gBACvB,uBAAuB,qBACvB,uBAAuB,iBACvB;AACA,yBAAqB;AAAA,EACvB;AAEA,QAAM,gBAAgB,gCAAW,QAAQ,SAAS;AAElD,QAAM,YAAuB;AAAA,IAC3B;AAAA,IACA,UAAU,OAAO,aAAa,WAAW,WAAW;AAAA,IACpD;AAAA,IACA,YAAY;AAAA,IACZ,oBAAoB,MAAM;AAAA,IAC1B,WAAW,aAAa,eAAe;AAAA,IACvC,YAAY,kBAAkB,cAAc,eAAe,UAAU;AAAA,IACrE,WAAW;AAAA,MACT,eAAe;AAAA,IACjB;AAAA,IACA,cAAc;AAAA,MACZ,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,oBAAoB,OAAO,QAAQ,IAAI,IAAI;AAEjD,SACE;AAAA,IAAC,qBAAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;AClFA,mBAAkB;AAClB,IAAAC,uBAAgC;AAwBvB,IAAAC,sBAAA;AArBF,IAAM,OAA4B,CAAC,EAAE,UAAU,OAAO,KAAK,MAAM;AACtE,QAAM,QAAmB;AAAA,IACvB,OAAO,OAAO,SAAS,WAAW,OAAO;AAAA,IACzC,QAAQ,OAAO,SAAS,WAAW,OAAO;AAAA,IAC1C,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AAIA,QAAM,oBAAoB,aAAAC,QAAM,SAAS,IAAI,UAAU,CAAC,UAAU;AAChE,QAAI,aAAAA,QAAM,eAAe,KAAK,GAAG;AAC/B,aAAO,aAAAA,QAAM,aAAa,OAAO;AAAA,QAC/B,OAAO,MAAM,MAAM,SAAS;AAAA;AAAA,QAE5B,MAAM,MAAM,MAAM,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO,6CAAC,6BAAK,OAAe,6BAAkB;AAChD;;;ACvBA,sBAAgC;AAChC,uBAAsB;AACtB,4BAAqB;AAgGjB,IAAAC,sBAAA;AAvDG,IAAM,SAAgC,CAAC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR;AAAA,EACA,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,QAAI,iCAAgB;AAElC,QAAM,aAAa,MAAM,OAAO,OAAO,IAAI;AAG3C,QAAM,eAAe,SACjB,WAAW,qBACX,WAAW;AAGf,QAAM,YAAY,aAAa,OAAO;AAItC,QAAM,eAAe,MAAM;AACzB,QAAI,QAAQ;AACV,aAAO,EAAE,OAAO,IAAI,KAAK,GAAG;AAAA,IAC9B;AAEA,UAAM,gBAAgB;AAAA,MACpB,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,MACvB,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,MACvB,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,MACvB,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,MACvB,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IACzB;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B;AAEA,QAAM,cAAc,aAChB,SACE,WAAW,oBACX,WAAW,oBACb,aAAa;AAGjB,QAAM,oBAAoB;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MACnB,UAAS;AAAA,MACR,GAAI,CAAC,OAAO,EAAE,MAAM,OAAO,cAAc,UAAU;AAAA,MACnD,GAAI,WAAW;AAAA,QACd,SAAS;AAAA,QACT,WAAW,CAAC,MAA2B;AACrC,cAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,cAAE,eAAe;AACjB,oBAAQ;AAAA,UACV;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB,QAAQ,WAAW;AAAA,YACnB;AAAA,YACA,iBAAiB,mBAAmB,MAAM,OAAO,WAAW;AAAA,YAC3D,GAAI,CAAC,gBACJ,CAAC,OAAO;AAAA,cACN,YAAY;AAAA,gBACV,iBAAiB,MAAM,OAAO,QAAQ;AAAA,cACxC;AAAA,YACF;AAAA,YACF,YAAW;AAAA,YACX,gBAAe;AAAA,YACf,UAAS;AAAA,YACT,UAAS;AAAA,YACT,aAAa,SAAS,IAAI;AAAA,YAC1B,aAAa,MAAM,OAAO,WAAW;AAAA,YAEpC,gBACC;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH;AAAA,gBACA,KAAK,OAAO,aAAa;AAAA,gBACzB,UAAS;AAAA,gBACT,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN,OAAO,WAAW;AAAA,gBAClB,QAAQ,WAAW;AAAA,gBACnB;AAAA;AAAA,YACF,IACE,OACF,6CAAC,QAAK,MAAM,WAAW,UAAU,OAAO,MAAM,OAAO,QAAQ,SAC1D,gBACH,IACE,OACF;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU,WAAW;AAAA,gBACrB,OAAO,MAAM,OAAO,QAAQ;AAAA,gBAC5B,YAAW;AAAA,gBAEV;AAAA;AAAA,YACH,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM,WAAW;AAAA,gBACjB,OAAO,MAAM,OAAO,QAAQ;AAAA;AAAA,YAC9B;AAAA;AAAA,QAEJ;AAAA,QAEC,SACC;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,OAAO,YAAY;AAAA,YACnB,KAAK,YAAY;AAAA,YAEjB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,YAAU;AAAA,gBACV,cACE,oBACI,GAAG,iBAAiB,mBACpB;AAAA,gBAGL;AAAA;AAAA,YACH;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AC5LA,IAAAC,mBAAgC;AAChC,yBAAwB;AA8IhB,IAAAC,sBAAA;AArFR,IAAM,UAGF;AAAA,EACF,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEO,IAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA,OAAO;AAAA,EACP,aAAa;AAAA,EACb,SAAS;AAAA,EACT,uBAAuB;AAAA,EACvB,cAAc;AAChB,MAAM;AACJ,QAAM,EAAE,MAAM,QAAI,kCAAgB;AAGlC,QAAM,eAAe,QAAQ,IAAI;AAEjC,QAAM,aAAa,KAAK;AAIxB,QAAM,eAAe,KAAK,IAAI,YAAY,KAAK,IAAI,GAAG,UAAU,CAAC;AACjE,QAAM,mBAAmB,KAAK,MAAM,GAAG,YAAY;AACnD,QAAM,iBAAiB,aAAa;AAGpC,QAAM,UAAU;AAGhB,QAAM,mBAAmB;AAAA,IACvB,MAAM,OAAO,WAAW,MAAM;AAAA,IAC9B,MAAM,OAAO,WAAW,QAAQ;AAAA,IAChC,MAAM,OAAO,WAAW,WAAW;AAAA,IACnC,MAAM,OAAO,WAAW,QAAQ;AAAA,IAChC,MAAM,OAAO,WAAW,MAAM;AAAA,IAC9B,MAAM,OAAO,WAAW,QAAQ;AAAA,IAChC,MAAM,OAAO,WAAW,QAAQ;AAAA,EAClC;AAGA,QAAM,eAAuC;AAAA,IAC3C,OAAO,MAAM,OAAO,WAAW,MAAM;AAAA,IACrC,YAAY,MAAM,OAAO,WAAW,WAAW;AAAA,IAC/C,SAAS,MAAM,OAAO,WAAW,QAAQ;AAAA,IACzC,SAAS,MAAM,OAAO,WAAW,QAAQ;AAAA,IACzC,OAAO,MAAM,OAAO,WAAW,MAAM;AAAA,IACrC,SAAS,MAAM,OAAO,WAAW,QAAQ;AAAA,EAC3C;AAGA,QAAM,qBAAqB,CAAC,UAA0B;AACpD,QAAI,OAAO,yBAAyB,YAAY;AAC9C,aAAO,qBAAqB,KAAK;AAAA,IACnC;AACA,QAAI,yBAAyB,SAAS;AACpC,aAAO,iBAAiB,QAAQ,iBAAiB,MAAM;AAAA,IACzD;AAEA,WACE,aAAa,oBAAoB,KAAK,MAAM,OAAO,WAAW;AAAA,EAElE;AAGA,QAAM,mBACJ,eAAe,IACX,WACA,eAAe,eACb,GAAG,UAAU,WACb,GAAG,YAAY,OAAO,UAAU;AAGxC,QAAM,0BAA0B,CAC9B,QACA,SACA,QACG;AACH,QAAI,SAAS;AACX,aACE,6CAAC,8BAAkB,SAAS,SAAS,WAAU,OAC5C,oBADW,GAEd;AAAA,IAEJ;AACA,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,YAAW;AAAA,MACX,MAAK;AAAA,MACL,cAAY,aAAa;AAAA,MAExB;AAAA,yBAAiB,IAAI,CAAC,MAAM,UAAU;AACrC,gBAAM,wBAAwB,CAAC,KAAK;AACpC,gBAAM,kBAAkB,wBACpB,mBAAmB,KAAK,IACxB;AAGJ,gBAAM,oBAAoB,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK;AAE/C,gBAAM,SACJ;AAAA,YAAC;AAAA;AAAA,cAEC,YAAY,UAAU,IAAI,IAAI;AAAA,cAC9B,QAAQ,aAAa;AAAA,cAErB;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAK,KAAK;AAAA,kBACV,MAAM,KAAK;AAAA,kBACX,MAAM;AAAA,kBACN;AAAA,kBACA;AAAA,kBACA,cAAc,CAAC;AAAA,kBACf,SAAS,KAAK;AAAA,kBACb,GAAI,KAAK,UAAU,EAAE,cAAc,KAAK,QAAQ,IAAI,CAAC;AAAA;AAAA,cACxD;AAAA;AAAA,YAbK;AAAA,UAcP;AAGF,iBAAO,wBAAwB,QAAQ,KAAK,SAAS,KAAK;AAAA,QAC5D,CAAC;AAAA,QAEA,iBAAiB,KAChB,6CAAC,OAAI,YAAY,SAAS,QAAQ,GAChC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,MAAM,IAAI,cAAc;AAAA,YACxB;AAAA,YACA,iBAAiB,MAAM,OAAO,WAAW;AAAA,YACzC,cAAc;AAAA,YACd,cAAY,GAAG,cAAc,SAAS,mBAAmB,IAAI,SAAS,OAAO;AAAA;AAAA,QAC/E,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":["import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime","import_xui_core","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx","../../src/Avatar.tsx","../../src/AvatarGroup.tsx"],"sourcesContent":["export * from \"./Avatar\";\nexport * from \"./AvatarGroup\";\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 minWidth,\n minHeight,\n maxWidth,\n maxHeight,\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 minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight 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 {\n Text as RNText,\n TextStyle,\n AccessibilityRole,\n StyleSheet,\n} from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nconst parseNumericValue = (\n value: string | number | undefined\n): number | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = parseFloat(value);\n return isNaN(parsed) ? undefined : parsed;\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n textAlign,\n lineHeight,\n numberOfLines,\n id,\n role,\n style: styleProp,\n ...props\n}) => {\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const incomingStyle = StyleSheet.flatten(styleProp) as TextStyle | undefined;\n\n const baseStyle: TextStyle = {\n color: color ?? incomingStyle?.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 textAlign: textAlign ?? incomingStyle?.textAlign,\n lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),\n marginTop: parseNumericValue(\n incomingStyle?.marginTop as number | string | undefined\n ),\n marginBottom: parseNumericValue(\n incomingStyle?.marginBottom as number | string | undefined\n ),\n };\n\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText\n style={baseStyle}\n numberOfLines={numberOfLines}\n testID={id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\nimport { View, ViewStyle } from \"react-native\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Icon: React.FC<IconProps> = ({ children, color, size }) => {\n const style: ViewStyle = {\n width: typeof size === \"number\" ? size : undefined,\n height: typeof size === \"number\" ? size : undefined,\n alignItems: \"center\",\n justifyContent: \"center\",\n };\n\n // On native, we try to pass the color down to children (like Text primitives)\n // to mimic the CSS inheritance behavior of the web version.\n const childrenWithProps = React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n color: child.props.color || color,\n // Also pass size if child seems to be an icon that needs it\n size: child.props.size || size,\n });\n }\n return child;\n });\n\n return <View style={style}>{childrenWithProps}</View>;\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport { User } from \"@xsolla/xui-icons-base\";\n\nexport interface AvatarProps extends ThemeOverrideProps {\n /** Image source URL */\n src?: string;\n /** Icon component to display when no image is provided */\n icon?: React.ReactNode;\n /** Text/Initials to display when no image or icon is provided */\n text?: string;\n /** Size of the avatar */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\" | \"xxs\";\n /** If true, the avatar will be square with small border radius. If false, it will be a circle. */\n square?: boolean;\n /** Whether to show an alert badge */\n badge?: boolean;\n /** Number or text to display in the badge notification */\n badgeCount?: React.ReactNode;\n /** If true, the avatar will have a border to separate it from other avatars in a group */\n stroke?: boolean;\n /** Background color for the avatar. Defaults to theme background secondary. */\n backgroundColor?: string;\n /** Disable hover effect. Used internally by AvatarGroup. */\n disableHover?: boolean;\n /** Accessible label for the avatar. Recommended for screen readers. */\n \"aria-label\"?: string;\n /** Alternative text for the avatar image */\n alt?: string;\n /** Click handler for the avatar */\n onClick?: () => void;\n /** Color tone for the badge */\n badgeTone?:\n | \"primary\"\n | \"secondary\"\n | \"brand\"\n | \"brandExtra\"\n | \"success\"\n | \"warning\"\n | \"alert\"\n | \"neutral\";\n}\n\nexport const Avatar: React.FC<AvatarProps> = ({\n src,\n icon,\n text,\n size = \"xl\",\n square = false,\n badge = false,\n badgeCount,\n badgeTone = \"alert\",\n stroke = false,\n backgroundColor,\n disableHover = true,\n \"aria-label\": ariaLabel,\n alt,\n onClick,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const sizeStyles = theme.sizing.avatar(size);\n\n // Border radius based on square or circle variant\n const borderRadius = square\n ? sizeStyles.borderRadiusSquare\n : sizeStyles.borderRadiusCircle;\n\n const countSizeMap = {\n xl: \"xl\",\n lg: \"xl\",\n md: \"lg\",\n sm: \"lg\",\n xs: \"sm\",\n xxs: \"xs\",\n } as const;\n const dotSizeMap = {\n xl: \"md\",\n lg: \"md\",\n md: \"sm\",\n sm: \"sm\",\n xs: \"sm\",\n xxs: \"xxs\",\n } as const;\n const badgeSize = badgeCount ? countSizeMap[size] : dotSizeMap[size];\n\n // Badge offset differs for circle vs square, and for dot vs count\n // Dot badge (8px) needs different offset per avatar size\n const getDotOffset = () => {\n if (square) {\n return size === \"xxs\" ? { right: -1, top: -1 } : { right: -3, top: -3 };\n }\n // Circle - position dot on the edge based on avatar size\n const circleOffsets = {\n xl: { right: 2, top: 2 },\n lg: { right: 2, top: 2 },\n md: { right: 2, top: 2 },\n sm: { right: 2, top: 2 },\n xs: { right: 0, top: 0 },\n xxs: { right: 1, top: 1 },\n };\n return circleOffsets[size];\n };\n\n const badgeOffset = badgeCount\n ? square\n ? sizeStyles.badgeOffsetSquare\n : sizeStyles.badgeOffsetCircle\n : getDotOffset();\n\n // Display badge count\n const displayBadgeCount = badgeCount;\n\n return (\n <Box\n width={sizeStyles.size}\n height={sizeStyles.size}\n position=\"relative\"\n {...(!src && { role: \"img\", \"aria-label\": ariaLabel })}\n {...(onClick && {\n onPress: onClick,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick();\n }\n },\n cursor: \"pointer\",\n role: \"button\",\n tabIndex: 0,\n })}\n >\n <Box\n width={sizeStyles.size}\n height={sizeStyles.size}\n borderRadius={borderRadius}\n backgroundColor={backgroundColor || theme.colors.overlay.mono}\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n overflow=\"hidden\"\n borderWidth={stroke ? 1 : 0}\n borderColor={theme.colors.background.primary}\n {...(!disableHover &&\n !src && {\n hoverStyle: {\n backgroundColor: theme.colors.overlay.monoHover,\n },\n })}\n >\n {src ? (\n <Box\n as=\"img\"\n src={src}\n alt={alt || ariaLabel || \"\"}\n position=\"absolute\"\n top={0}\n left={0}\n width={sizeStyles.size}\n height={sizeStyles.size}\n borderRadius={borderRadius}\n />\n ) : icon ? (\n <Icon size={sizeStyles.iconSize} color={theme.colors.content.primary}>\n {icon}\n </Icon>\n ) : text ? (\n <Text\n fontSize={sizeStyles.fontSize}\n color={theme.colors.content.primary}\n fontWeight=\"400\"\n letterSpacing={0.4}\n >\n {text}\n </Text>\n ) : (\n <User\n size={sizeStyles.iconSize}\n color={theme.colors.content.primary}\n />\n )}\n </Box>\n\n {badge && (\n <Box\n position=\"absolute\"\n right={badgeOffset.right}\n top={badgeOffset.top}\n >\n <Badge\n size={badgeSize}\n tone={badgeTone}\n showStroke={size !== \"xxs\"}\n aria-label={\n displayBadgeCount\n ? `${displayBadgeCount} notifications`\n : \"Notification\"\n }\n >\n {displayBadgeCount}\n </Badge>\n </Box>\n )}\n </Box>\n );\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Tooltip } from \"@xsolla/xui-tooltip\";\nimport { Avatar } from \"./Avatar\";\n\n/** Theme type from the design system */\ntype Theme = ReturnType<typeof useResolvedTheme>[\"theme\"];\n\n/** Item in the avatar group list */\nexport interface AvatarGroupItem {\n /** Image source URL */\n src?: string;\n /** Initials to display when no image is provided */\n initials?: string;\n /** Click handler for the avatar */\n onClick?: () => void;\n /** Tooltip text to display on hover */\n tooltip?: string;\n}\n\n/** Avatar background mode - preset colors, 'mixed' for cycling, or a theme function */\nexport type AvatarBackgroundMode =\n | \"mixed\"\n | \"brand\"\n | \"brandExtra\"\n | \"success\"\n | \"warning\"\n | \"alert\"\n | \"neutral\"\n | ((theme: Theme) => string);\n\nexport interface AvatarGroupProps extends ThemeOverrideProps {\n /**\n * List of avatars to display in the group.\n * `tooltip` property is text to be displayed in the tooltip when hovering over the avatar.\n */\n list: AvatarGroupItem[];\n /** Size of the avatars in the group */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * The maximum number of avatars to display before collapsing the rest into a \"+N\" counter.\n * If the number of avatars exceeds this value, the extra avatars will be hidden.\n */\n maxVisible?: number;\n /** Whether to show a stroke/border around each avatar */\n stroke?: boolean;\n /**\n * Controls the background color mode for avatars in the group.\n * - 'mixed' (default): Avatars cycle through different colors\n * - 'brand', 'brandExtra', 'success', 'warning', 'alert', 'neutral': Single color for all avatars\n * - Theme function: A function that receives theme and returns any color from the design system.\n * Example: (theme) => theme.colors.core.link.link\n */\n avatarBackgroundMode?: AvatarBackgroundMode;\n /** Accessible label for the avatar group. Defaults to \"Group of X users\". */\n \"aria-label\"?: string;\n}\n\n// Map external size values to internal Avatar size values\nconst sizeMap: Record<\n \"sm\" | \"md\" | \"lg\" | \"xl\",\n \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n> = {\n sm: \"sm\",\n md: \"md\",\n lg: \"lg\",\n xl: \"xl\",\n};\n\nexport const AvatarGroup: React.FC<AvatarGroupProps> = ({\n list,\n size = \"md\",\n maxVisible = 6,\n stroke = true,\n avatarBackgroundMode = \"mixed\",\n \"aria-label\": ariaLabel,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n // Map external size to internal Avatar size\n const internalSize = sizeMap[size];\n\n const totalCount = list.length;\n\n // Determine which avatars to show\n // Ensure maxVisible is non-negative and doesn't exceed totalCount\n const visibleCount = Math.min(totalCount, Math.max(0, maxVisible));\n const visibleListItems = list.slice(0, visibleCount);\n const remainingCount = totalCount - visibleCount;\n\n // Overlap amount: 4px in Figma\n const overlap = -4;\n\n // Background colors for text/icon avatars (cycling through theme colors)\n const mixedBackgrounds = [\n theme.colors.background.alert.secondary,\n theme.colors.background.warning.secondary,\n theme.colors.background.brandExtra.secondary,\n theme.colors.background.neutral.secondary,\n theme.colors.background.brand.secondary,\n theme.colors.background.success.secondary,\n theme.colors.background.success.primary,\n ];\n\n // Preset color mapping\n const presetColors: Record<string, string> = {\n brand: theme.colors.background.brand.secondary,\n brandExtra: theme.colors.background.brandExtra.secondary,\n success: theme.colors.background.success.secondary,\n warning: theme.colors.background.warning.secondary,\n alert: theme.colors.background.alert.secondary,\n neutral: theme.colors.background.neutral.secondary,\n };\n\n // Get background color based on avatarBackgroundMode\n const getBackgroundColor = (index: number): string => {\n if (typeof avatarBackgroundMode === \"function\") {\n return avatarBackgroundMode(theme);\n }\n if (avatarBackgroundMode === \"mixed\") {\n return mixedBackgrounds[index % mixedBackgrounds.length];\n }\n // Preset color mode\n return (\n presetColors[avatarBackgroundMode] || theme.colors.background.secondary\n );\n };\n\n // Default accessible label for the group\n const defaultAriaLabel =\n totalCount === 1\n ? \"1 user\"\n : totalCount === visibleCount\n ? `${totalCount} users`\n : `${visibleCount} of ${totalCount} users`;\n\n // Render an avatar with optional tooltip wrapper\n const renderAvatarWithTooltip = (\n avatar: React.ReactNode,\n tooltip: string | undefined,\n key: number\n ) => {\n if (tooltip) {\n return (\n <Tooltip key={key} content={tooltip} placement=\"top\">\n {avatar}\n </Tooltip>\n );\n }\n return avatar;\n };\n\n return (\n <Box\n flexDirection=\"row\"\n alignItems=\"center\"\n role=\"group\"\n aria-label={ariaLabel || defaultAriaLabel}\n >\n {visibleListItems.map((item, index) => {\n const shouldApplyBackground = !item.src;\n const backgroundColor = shouldApplyBackground\n ? getBackgroundColor(index)\n : undefined;\n\n // Only enable hover for image avatars with onClick\n const shouldEnableHover = !!item.src && !!item.onClick;\n\n const avatar = (\n <Box\n key={index}\n marginLeft={index === 0 ? 0 : overlap}\n zIndex={totalCount - index}\n >\n <Avatar\n src={item.src}\n text={item.initials}\n size={internalSize}\n stroke={stroke}\n backgroundColor={backgroundColor}\n disableHover={!shouldEnableHover}\n onClick={item.onClick}\n {...(item.tooltip ? { \"aria-label\": item.tooltip } : {})}\n />\n </Box>\n );\n\n return renderAvatarWithTooltip(avatar, item.tooltip, index);\n })}\n\n {remainingCount > 0 && (\n <Box marginLeft={overlap} zIndex={0}>\n <Avatar\n size={internalSize}\n text={`+${remainingCount}`}\n stroke={stroke}\n backgroundColor={theme.colors.background.secondary}\n disableHover={true}\n aria-label={`${remainingCount} more ${remainingCount === 1 ? \"user\" : \"users\"}`}\n />\n </Box>\n )}\n </Box>\n );\n};\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime","import_xui_core","import_jsx_runtime"]}
package/native/index.mjs CHANGED
@@ -45,6 +45,10 @@ var Box = ({
45
45
  left,
46
46
  right,
47
47
  width,
48
+ minWidth,
49
+ minHeight,
50
+ maxWidth,
51
+ maxHeight,
48
52
  flex,
49
53
  overflow,
50
54
  zIndex,
@@ -76,6 +80,10 @@ var Box = ({
76
80
  zIndex,
77
81
  height,
78
82
  width,
83
+ minWidth,
84
+ minHeight,
85
+ maxWidth,
86
+ maxHeight,
79
87
  padding,
80
88
  paddingHorizontal,
81
89
  paddingVertical,
@@ -207,7 +215,7 @@ var Text = ({
207
215
  }
208
216
  const incomingStyle = StyleSheet.flatten(styleProp);
209
217
  const baseStyle = {
210
- color,
218
+ color: color ?? incomingStyle?.color,
211
219
  fontSize: typeof fontSize === "number" ? fontSize : void 0,
212
220
  fontWeight,
213
221
  fontFamily: resolvedFontFamily,
@@ -259,7 +267,7 @@ var Icon = ({ children, color, size }) => {
259
267
  };
260
268
 
261
269
  // src/Avatar.tsx
262
- import { useDesignSystem } from "@xsolla/xui-core";
270
+ import { useResolvedTheme } from "@xsolla/xui-core";
263
271
  import { Badge } from "@xsolla/xui-badge";
264
272
  import { User } from "@xsolla/xui-icons-base";
265
273
  import { jsx as jsx4, jsxs } from "react/jsx-runtime";
@@ -267,32 +275,51 @@ var Avatar = ({
267
275
  src,
268
276
  icon,
269
277
  text,
270
- size = "md",
278
+ size = "xl",
271
279
  square = false,
272
280
  badge = false,
273
281
  badgeCount,
274
282
  badgeTone = "alert",
275
283
  stroke = false,
276
284
  backgroundColor,
277
- disableHover = false,
285
+ disableHover = true,
278
286
  "aria-label": ariaLabel,
279
287
  alt,
280
- onClick
288
+ onClick,
289
+ themeMode,
290
+ themeProductContext
281
291
  }) => {
282
- const { theme } = useDesignSystem();
292
+ const { theme } = useResolvedTheme({ themeMode, themeProductContext });
283
293
  const sizeStyles = theme.sizing.avatar(size);
284
294
  const borderRadius = square ? sizeStyles.borderRadiusSquare : sizeStyles.borderRadiusCircle;
285
- const badgeSize = badgeCount ? "xl" : "sm";
295
+ const countSizeMap = {
296
+ xl: "xl",
297
+ lg: "xl",
298
+ md: "lg",
299
+ sm: "lg",
300
+ xs: "sm",
301
+ xxs: "xs"
302
+ };
303
+ const dotSizeMap = {
304
+ xl: "md",
305
+ lg: "md",
306
+ md: "sm",
307
+ sm: "sm",
308
+ xs: "sm",
309
+ xxs: "xxs"
310
+ };
311
+ const badgeSize = badgeCount ? countSizeMap[size] : dotSizeMap[size];
286
312
  const getDotOffset = () => {
287
313
  if (square) {
288
- return { right: -3, top: -3 };
314
+ return size === "xxs" ? { right: -1, top: -1 } : { right: -3, top: -3 };
289
315
  }
290
316
  const circleOffsets = {
291
- xl: { right: 4, top: 4 },
292
- lg: { right: 3, top: 3 },
317
+ xl: { right: 2, top: 2 },
318
+ lg: { right: 2, top: 2 },
293
319
  md: { right: 2, top: 2 },
294
- sm: { right: 1, top: 1 },
295
- xs: { right: 0, top: 0 }
320
+ sm: { right: 2, top: 2 },
321
+ xs: { right: 0, top: 0 },
322
+ xxs: { right: 1, top: 1 }
296
323
  };
297
324
  return circleOffsets[size];
298
325
  };
@@ -324,18 +351,18 @@ var Avatar = ({
324
351
  width: sizeStyles.size,
325
352
  height: sizeStyles.size,
326
353
  borderRadius,
327
- backgroundColor: backgroundColor || theme.colors.background.secondary,
328
- ...!disableHover && !src && {
329
- hoverStyle: {
330
- backgroundColor: theme.colors.overlay.mono
331
- }
332
- },
354
+ backgroundColor: backgroundColor || theme.colors.overlay.mono,
333
355
  alignItems: "center",
334
356
  justifyContent: "center",
335
357
  position: "relative",
336
358
  overflow: "hidden",
337
359
  borderWidth: stroke ? 1 : 0,
338
360
  borderColor: theme.colors.background.primary,
361
+ ...!disableHover && !src && {
362
+ hoverStyle: {
363
+ backgroundColor: theme.colors.overlay.monoHover
364
+ }
365
+ },
339
366
  children: src ? /* @__PURE__ */ jsx4(
340
367
  Box,
341
368
  {
@@ -354,7 +381,8 @@ var Avatar = ({
354
381
  {
355
382
  fontSize: sizeStyles.fontSize,
356
383
  color: theme.colors.content.primary,
357
- fontWeight: "600",
384
+ fontWeight: "400",
385
+ letterSpacing: 0.4,
358
386
  children: text
359
387
  }
360
388
  ) : /* @__PURE__ */ jsx4(
@@ -377,7 +405,7 @@ var Avatar = ({
377
405
  {
378
406
  size: badgeSize,
379
407
  tone: badgeTone,
380
- showStroke: true,
408
+ showStroke: size !== "xxs",
381
409
  "aria-label": displayBadgeCount ? `${displayBadgeCount} notifications` : "Notification",
382
410
  children: displayBadgeCount
383
411
  }
@@ -390,7 +418,7 @@ var Avatar = ({
390
418
  };
391
419
 
392
420
  // src/AvatarGroup.tsx
393
- import { useDesignSystem as useDesignSystem2 } from "@xsolla/xui-core";
421
+ import { useResolvedTheme as useResolvedTheme2 } from "@xsolla/xui-core";
394
422
  import { Tooltip } from "@xsolla/xui-tooltip";
395
423
  import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
396
424
  var sizeMap = {
@@ -405,9 +433,11 @@ var AvatarGroup = ({
405
433
  maxVisible = 6,
406
434
  stroke = true,
407
435
  avatarBackgroundMode = "mixed",
408
- "aria-label": ariaLabel
436
+ "aria-label": ariaLabel,
437
+ themeMode,
438
+ themeProductContext
409
439
  }) => {
410
- const { theme } = useDesignSystem2();
440
+ const { theme } = useResolvedTheme2({ themeMode, themeProductContext });
411
441
  const internalSize = sizeMap[size];
412
442
  const totalCount = list.length;
413
443
  const visibleCount = Math.min(totalCount, Math.max(0, maxVisible));