@xsolla/xui-avatar 0.158.0 → 0.160.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 +57 -51
- package/native/index.d.mts +4 -0
- package/native/index.d.ts +4 -0
- package/native/index.js +15 -3
- package/native/index.js.map +1 -1
- package/native/index.mjs +15 -3
- package/native/index.mjs.map +1 -1
- package/package.json +6 -6
- package/web/index.d.mts +4 -0
- package/web/index.d.ts +4 -0
- package/web/index.js +15 -3
- package/web/index.js.map +1 -1
- package/web/index.mjs +15 -3
- package/web/index.mjs.map +1 -1
package/README.md
CHANGED
|
@@ -11,14 +11,19 @@ npm install @xsolla/xui-avatar
|
|
|
11
11
|
## Imports
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
Avatar,
|
|
16
|
+
AvatarGroup,
|
|
17
|
+
type AvatarGroupItem,
|
|
18
|
+
type AvatarBackgroundMode,
|
|
19
|
+
} from "@xsolla/xui-avatar";
|
|
15
20
|
```
|
|
16
21
|
|
|
17
22
|
## Quick start
|
|
18
23
|
|
|
19
24
|
```tsx
|
|
20
|
-
import * as React from
|
|
21
|
-
import { Avatar } from
|
|
25
|
+
import * as React from "react";
|
|
26
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
22
27
|
|
|
23
28
|
export default function QuickStart() {
|
|
24
29
|
return <Avatar text="JD" aria-label="John Doe" />;
|
|
@@ -29,21 +34,22 @@ export default function QuickStart() {
|
|
|
29
34
|
|
|
30
35
|
### `<Avatar>`
|
|
31
36
|
|
|
32
|
-
| Prop
|
|
33
|
-
|
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
37
|
+
| Prop | Type | Default | Description |
|
|
38
|
+
| ------------ | ------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| `testID` | `string` | — | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
|
|
40
|
+
| `src` | `string` | — | Image source URL. |
|
|
41
|
+
| `icon` | `ReactNode` | — | Icon displayed when no `src` is supplied. |
|
|
42
|
+
| `text` | `string` | — | Text/initials displayed when no `src` or `icon` is supplied. |
|
|
43
|
+
| `size` | `"xl" \| "lg" \| "md" \| "sm" \| "xs" \| "xxs"` | `"xl"` | Avatar size. |
|
|
44
|
+
| `square` | `boolean` | `false` | Square (small radius) instead of circular. |
|
|
45
|
+
| `tone` | `"mono" \| "brand"` | `"mono"` | Visual tone. |
|
|
46
|
+
| `badge` | `boolean` | `false` | Show a notification badge. |
|
|
47
|
+
| `badgeCount` | `ReactNode` | — | Numeric or text content rendered inside the badge. |
|
|
48
|
+
| `badgeIcon` | `ReactNode` | — | Icon rendered inside the badge. |
|
|
49
|
+
| `badgeTone` | `"primary" \| "secondary" \| "brand" \| "brandExtra" \| "success" \| "warning" \| "alert" \| "neutral"` | `"alert"` | Badge colour tone. |
|
|
50
|
+
| `aria-label` | `string` | — | Accessible label. Recommended for screen readers. |
|
|
51
|
+
| `alt` | `string` | — | Alt text for the image (falls back to `aria-label`). |
|
|
52
|
+
| `onClick` | `() => void` | — | Click handler. When provided, the avatar becomes a focusable button. |
|
|
47
53
|
|
|
48
54
|
Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
49
55
|
|
|
@@ -51,13 +57,13 @@ Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
|
51
57
|
|
|
52
58
|
### `<AvatarGroup>`
|
|
53
59
|
|
|
54
|
-
| Prop
|
|
55
|
-
|
|
|
56
|
-
| `list`
|
|
57
|
-
| `size`
|
|
58
|
-
| `maxVisible`
|
|
59
|
-
| `avatarBackgroundMode` | `"mixed" \| "brand" \| "brandExtra" \| "success" \| "warning" \| "alert" \| "neutral" \| ((theme) => string)` | `"mixed"` | Background colour mode for non-image avatars.
|
|
60
|
-
| `aria-label`
|
|
60
|
+
| Prop | Type | Default | Description |
|
|
61
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------- |
|
|
62
|
+
| `list` | `AvatarGroupItem[]` | — | **Required.** Avatars to display. |
|
|
63
|
+
| `size` | `"xxs" \| "xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"sm"` | Size applied to every avatar. |
|
|
64
|
+
| `maxVisible` | `number` | `6` | Maximum slots rendered, including the "+N" overflow counter. |
|
|
65
|
+
| `avatarBackgroundMode` | `"mixed" \| "brand" \| "brandExtra" \| "success" \| "warning" \| "alert" \| "neutral" \| ((theme) => string)` | `"mixed"` | Background colour mode for non-image avatars. |
|
|
66
|
+
| `aria-label` | `string` | auto | Accessible label for the group. Defaults to "X users" / "N of M users". |
|
|
61
67
|
|
|
62
68
|
Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
63
69
|
|
|
@@ -80,12 +86,12 @@ interface AvatarGroupItem {
|
|
|
80
86
|
### Sizes
|
|
81
87
|
|
|
82
88
|
```tsx
|
|
83
|
-
import * as React from
|
|
84
|
-
import { Avatar } from
|
|
89
|
+
import * as React from "react";
|
|
90
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
85
91
|
|
|
86
92
|
export default function AvatarSizes() {
|
|
87
93
|
return (
|
|
88
|
-
<div style={{ display:
|
|
94
|
+
<div style={{ display: "flex", gap: 16, alignItems: "center" }}>
|
|
89
95
|
<Avatar size="xxs" text="A" />
|
|
90
96
|
<Avatar size="xs" text="A" />
|
|
91
97
|
<Avatar size="sm" text="A" />
|
|
@@ -100,12 +106,12 @@ export default function AvatarSizes() {
|
|
|
100
106
|
### Tones
|
|
101
107
|
|
|
102
108
|
```tsx
|
|
103
|
-
import * as React from
|
|
104
|
-
import { Avatar } from
|
|
109
|
+
import * as React from "react";
|
|
110
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
105
111
|
|
|
106
112
|
export default function AvatarTones() {
|
|
107
113
|
return (
|
|
108
|
-
<div style={{ display:
|
|
114
|
+
<div style={{ display: "flex", gap: 16 }}>
|
|
109
115
|
<Avatar tone="mono" text="JD" />
|
|
110
116
|
<Avatar tone="brand" text="JD" />
|
|
111
117
|
</div>
|
|
@@ -116,13 +122,13 @@ export default function AvatarTones() {
|
|
|
116
122
|
### With badge
|
|
117
123
|
|
|
118
124
|
```tsx
|
|
119
|
-
import * as React from
|
|
120
|
-
import { Avatar } from
|
|
121
|
-
import { Bell } from
|
|
125
|
+
import * as React from "react";
|
|
126
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
127
|
+
import { Bell } from "@xsolla/xui-icons-base";
|
|
122
128
|
|
|
123
129
|
export default function AvatarWithBadge() {
|
|
124
130
|
return (
|
|
125
|
-
<div style={{ display:
|
|
131
|
+
<div style={{ display: "flex", gap: 24 }}>
|
|
126
132
|
<Avatar text="JD" badge />
|
|
127
133
|
<Avatar text="JD" badge badgeCount={5} />
|
|
128
134
|
<Avatar text="JD" badge badgeIcon={<Bell />} badgeTone="brand" />
|
|
@@ -134,8 +140,8 @@ export default function AvatarWithBadge() {
|
|
|
134
140
|
### Square
|
|
135
141
|
|
|
136
142
|
```tsx
|
|
137
|
-
import * as React from
|
|
138
|
-
import { Avatar } from
|
|
143
|
+
import * as React from "react";
|
|
144
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
139
145
|
|
|
140
146
|
export default function SquareAvatar() {
|
|
141
147
|
return <Avatar text="AB" square size="lg" />;
|
|
@@ -145,9 +151,9 @@ export default function SquareAvatar() {
|
|
|
145
151
|
### Custom icon
|
|
146
152
|
|
|
147
153
|
```tsx
|
|
148
|
-
import * as React from
|
|
149
|
-
import { Avatar } from
|
|
150
|
-
import { Briefcase } from
|
|
154
|
+
import * as React from "react";
|
|
155
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
156
|
+
import { Briefcase } from "@xsolla/xui-icons-base";
|
|
151
157
|
|
|
152
158
|
export default function AvatarWithIcon() {
|
|
153
159
|
return <Avatar icon={<Briefcase />} tone="brand" aria-label="Work account" />;
|
|
@@ -157,8 +163,8 @@ export default function AvatarWithIcon() {
|
|
|
157
163
|
### Clickable
|
|
158
164
|
|
|
159
165
|
```tsx
|
|
160
|
-
import * as React from
|
|
161
|
-
import { Avatar } from
|
|
166
|
+
import * as React from "react";
|
|
167
|
+
import { Avatar } from "@xsolla/xui-avatar";
|
|
162
168
|
|
|
163
169
|
export default function ClickableAvatar() {
|
|
164
170
|
const [count, setCount] = React.useState(0);
|
|
@@ -176,18 +182,18 @@ export default function ClickableAvatar() {
|
|
|
176
182
|
### Avatar group
|
|
177
183
|
|
|
178
184
|
```tsx
|
|
179
|
-
import * as React from
|
|
180
|
-
import { AvatarGroup, type AvatarGroupItem } from
|
|
185
|
+
import * as React from "react";
|
|
186
|
+
import { AvatarGroup, type AvatarGroupItem } from "@xsolla/xui-avatar";
|
|
181
187
|
|
|
182
188
|
export default function AvatarGroupExample() {
|
|
183
189
|
const users: AvatarGroupItem[] = [
|
|
184
|
-
{ initials:
|
|
185
|
-
{ initials:
|
|
186
|
-
{ initials:
|
|
187
|
-
{ initials:
|
|
188
|
-
{ initials:
|
|
189
|
-
{ initials:
|
|
190
|
-
{ initials:
|
|
190
|
+
{ initials: "JD", tooltip: "John Doe" },
|
|
191
|
+
{ initials: "AB", tooltip: "Anna Brown" },
|
|
192
|
+
{ initials: "CD", tooltip: "Carl Davis" },
|
|
193
|
+
{ initials: "EF", tooltip: "Emma Frost" },
|
|
194
|
+
{ initials: "GH", tooltip: "Grace Hill" },
|
|
195
|
+
{ initials: "IJ", tooltip: "Ivan Jones" },
|
|
196
|
+
{ initials: "KL", tooltip: "Kim Lee" },
|
|
191
197
|
];
|
|
192
198
|
|
|
193
199
|
return <AvatarGroup list={users} maxVisible={5} size="md" />;
|
package/native/index.d.mts
CHANGED
|
@@ -36,6 +36,8 @@ interface AvatarProps extends ThemeOverrideProps {
|
|
|
36
36
|
onClick?: () => void;
|
|
37
37
|
/** Color tone for the badge */
|
|
38
38
|
badgeTone?: "primary" | "secondary" | "brand" | "brandExtra" | "success" | "warning" | "alert" | "neutral";
|
|
39
|
+
/** Test ID for testing frameworks */
|
|
40
|
+
testID?: string;
|
|
39
41
|
}
|
|
40
42
|
declare const Avatar: React.FC<AvatarProps>;
|
|
41
43
|
|
|
@@ -84,6 +86,8 @@ interface AvatarGroupProps extends ThemeOverrideProps {
|
|
|
84
86
|
avatarBackgroundMode?: AvatarBackgroundMode;
|
|
85
87
|
/** Accessible label for the avatar group. Defaults to "Group of X users". */
|
|
86
88
|
"aria-label"?: string;
|
|
89
|
+
/** Test ID for testing frameworks */
|
|
90
|
+
testID?: string;
|
|
87
91
|
}
|
|
88
92
|
declare const AvatarGroup: React.FC<AvatarGroupProps>;
|
|
89
93
|
|
package/native/index.d.ts
CHANGED
|
@@ -36,6 +36,8 @@ interface AvatarProps extends ThemeOverrideProps {
|
|
|
36
36
|
onClick?: () => void;
|
|
37
37
|
/** Color tone for the badge */
|
|
38
38
|
badgeTone?: "primary" | "secondary" | "brand" | "brandExtra" | "success" | "warning" | "alert" | "neutral";
|
|
39
|
+
/** Test ID for testing frameworks */
|
|
40
|
+
testID?: string;
|
|
39
41
|
}
|
|
40
42
|
declare const Avatar: React.FC<AvatarProps>;
|
|
41
43
|
|
|
@@ -84,6 +86,8 @@ interface AvatarGroupProps extends ThemeOverrideProps {
|
|
|
84
86
|
avatarBackgroundMode?: AvatarBackgroundMode;
|
|
85
87
|
/** Accessible label for the avatar group. Defaults to "Group of X users". */
|
|
86
88
|
"aria-label"?: string;
|
|
89
|
+
/** Test ID for testing frameworks */
|
|
90
|
+
testID?: string;
|
|
87
91
|
}
|
|
88
92
|
declare const AvatarGroup: React.FC<AvatarGroupProps>;
|
|
89
93
|
|
package/native/index.js
CHANGED
|
@@ -239,6 +239,8 @@ var Text = ({
|
|
|
239
239
|
numberOfLines,
|
|
240
240
|
id,
|
|
241
241
|
role,
|
|
242
|
+
testID,
|
|
243
|
+
"data-testid": dataTestId,
|
|
242
244
|
style: styleProp,
|
|
243
245
|
...props
|
|
244
246
|
}) => {
|
|
@@ -268,7 +270,7 @@ var Text = ({
|
|
|
268
270
|
{
|
|
269
271
|
style: baseStyle,
|
|
270
272
|
numberOfLines,
|
|
271
|
-
testID: id,
|
|
273
|
+
testID: dataTestId || testID || id,
|
|
272
274
|
accessibilityRole,
|
|
273
275
|
children
|
|
274
276
|
}
|
|
@@ -279,7 +281,13 @@ var Text = ({
|
|
|
279
281
|
var import_react = __toESM(require("react"));
|
|
280
282
|
var import_react_native3 = require("react-native");
|
|
281
283
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
282
|
-
var Icon = ({
|
|
284
|
+
var Icon = ({
|
|
285
|
+
children,
|
|
286
|
+
color,
|
|
287
|
+
size,
|
|
288
|
+
testID,
|
|
289
|
+
"data-testid": dataTestId
|
|
290
|
+
}) => {
|
|
283
291
|
const style = {
|
|
284
292
|
width: typeof size === "number" ? size : void 0,
|
|
285
293
|
height: typeof size === "number" ? size : void 0,
|
|
@@ -296,7 +304,7 @@ var Icon = ({ children, color, size }) => {
|
|
|
296
304
|
}
|
|
297
305
|
return child;
|
|
298
306
|
});
|
|
299
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style, children: childrenWithProps });
|
|
307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style, testID: dataTestId || testID, children: childrenWithProps });
|
|
300
308
|
};
|
|
301
309
|
|
|
302
310
|
// src/Avatar.tsx
|
|
@@ -320,6 +328,7 @@ var Avatar = ({
|
|
|
320
328
|
"aria-label": ariaLabel,
|
|
321
329
|
alt,
|
|
322
330
|
onClick,
|
|
331
|
+
testID,
|
|
323
332
|
themeMode,
|
|
324
333
|
themeProductContext
|
|
325
334
|
}) => {
|
|
@@ -372,6 +381,7 @@ var Avatar = ({
|
|
|
372
381
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
373
382
|
Box,
|
|
374
383
|
{
|
|
384
|
+
testID,
|
|
375
385
|
width: sizeStyles.size,
|
|
376
386
|
height: sizeStyles.size,
|
|
377
387
|
position: "relative",
|
|
@@ -475,6 +485,7 @@ var AvatarGroup = ({
|
|
|
475
485
|
maxVisible = DEFAULT_MAX_VISIBLE,
|
|
476
486
|
avatarBackgroundMode = "mixed",
|
|
477
487
|
"aria-label": ariaLabel,
|
|
488
|
+
testID,
|
|
478
489
|
themeMode,
|
|
479
490
|
themeProductContext
|
|
480
491
|
}) => {
|
|
@@ -527,6 +538,7 @@ var AvatarGroup = ({
|
|
|
527
538
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
528
539
|
Box,
|
|
529
540
|
{
|
|
541
|
+
testID,
|
|
530
542
|
flexDirection: "row",
|
|
531
543
|
alignItems: "center",
|
|
532
544
|
role: "group",
|
package/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../src/Avatar.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../../../foundation/primitives-native/src/Text.tsx","../../../../foundation/primitives-native/src/Icon.tsx","../../src/AvatarGroup.tsx"],"sourcesContent":["export * from \"./Avatar\";\nexport * from \"./AvatarGroup\";\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 /** Visual tone — 'mono' (default) or 'brand'. */\n tone?: \"mono\" | \"brand\";\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 /** Icon to display in the badge */\n badgeIcon?: React.ReactNode;\n /**\n * Background colour override. Intended for internal use by AvatarGroup to\n * drive its `avatarBackgroundMode` cycling; not part of the public API.\n * @internal\n */\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 tone = \"mono\",\n badge = false,\n badgeCount,\n badgeIcon,\n badgeTone = \"alert\",\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 [hasImageError, setHasImageError] = React.useState(false);\n\n React.useEffect(() => {\n setHasImageError(false);\n }, [src]);\n\n const useImage = !!src && !hasImageError;\n\n const sizeStyles = theme.sizing.avatar(size);\n\n const toneBackground =\n tone === \"brand\"\n ? theme.colors.background.brand.primary\n : theme.colors.overlay.mono;\n const toneHoverBackground =\n tone === \"brand\"\n ? theme.colors.background.brand.secondary\n : theme.colors.overlay.monoHover;\n const toneContent =\n tone === \"brand\"\n ? theme.colors.content.on.brand\n : theme.colors.content.primary;\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: \"xs\",\n } as const;\n const hasBadgeContent = !!(badgeCount || badgeIcon);\n const badgeSize = hasBadgeContent ? countSizeMap[size] : dotSizeMap[size];\n // Badge sizes sm/xs are dot-only — content is dropped, so position as a dot.\n const rendersAsDot = badgeSize === \"sm\" || badgeSize === \"xs\";\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 =\n hasBadgeContent && !rendersAsDot\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 {...(!useImage && { 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 || toneBackground}\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n overflow=\"hidden\"\n borderWidth={2}\n borderColor={theme.colors.border.secondary}\n {...(!disableHover &&\n !useImage && {\n hoverStyle: {\n backgroundColor: toneHoverBackground,\n },\n })}\n >\n {useImage ? (\n <Box\n as=\"img\"\n src={src}\n alt={alt || ariaLabel || \"\"}\n position=\"absolute\"\n top={0}\n left={0}\n width=\"100%\"\n height=\"100%\"\n borderRadius={borderRadius}\n onError={() => setHasImageError(true)}\n />\n ) : icon ? (\n <Icon size={sizeStyles.iconSize} color={toneContent}>\n {icon}\n </Icon>\n ) : text ? (\n <Text\n fontSize={sizeStyles.fontSize}\n color={toneContent}\n fontWeight=\"400\"\n letterSpacing={0.4}\n >\n {text}\n </Text>\n ) : (\n <User\n variant=\"solid\"\n size={sizeStyles.iconSize}\n color={toneContent}\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 icon={badgeIcon}\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\";\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 } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Tooltip } from \"@xsolla/xui-tooltip\";\nimport { Avatar, AvatarProps } 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 /** Tooltip text to display on hover */\n tooltip?: string;\n /** Whether to show a badge on the avatar */\n badge?: boolean;\n /** Number or text to display in the badge notification */\n badgeCount?: React.ReactNode;\n /** Icon to display in the badge */\n badgeIcon?: React.ReactNode;\n /** Color tone for the badge */\n badgeTone?: AvatarProps[\"badgeTone\"];\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?: \"xxs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Maximum number of slots rendered, including the \"+N\" overflow counter.\n * When the list exceeds this, (maxVisible - 1) avatars are shown plus a \"+N\" indicator.\n * When the list fits, all avatars are shown and no \"+N\" is rendered.\n */\n maxVisible?: number;\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\nconst DEFAULT_MAX_VISIBLE = 6;\n\nexport const AvatarGroup: React.FC<AvatarGroupProps> = ({\n list,\n size = \"sm\",\n maxVisible = DEFAULT_MAX_VISIBLE,\n avatarBackgroundMode = \"mixed\",\n \"aria-label\": ariaLabel,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n if (maxVisible < 1) {\n console.warn(\n `[AvatarGroup] \"maxVisible\" must be a positive number. Received ${maxVisible}, falling back to default (${DEFAULT_MAX_VISIBLE}).`\n );\n }\n const effectiveMaxVisible = maxVisible < 1 ? DEFAULT_MAX_VISIBLE : maxVisible;\n\n const totalCount = list.length;\n const overflows = totalCount > effectiveMaxVisible;\n const visibleCount = overflows ? effectiveMaxVisible - 1 : totalCount;\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 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={size}\n backgroundColor={backgroundColor}\n disableHover={true}\n badge={item.badge}\n badgeCount={item.badgeCount}\n badgeIcon={item.badgeIcon}\n badgeTone={item.badgeTone}\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={size}\n text={remainingCount > 99 ? \"99+\" : `+${remainingCount}`}\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;;;ACAA,IAAAA,gBAAkB;;;ACClB,0BAQO;AA2ID;AAxIC,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;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;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;;;AC/LA,IAAAC,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,OAAO,SAAS,eAAe;AAAA,IAC/B,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;;;AHvBA,sBAA0D;AAC1D,uBAAsB;AACtB,4BAAqB;AAkJjB,IAAAC,sBAAA;AAnGG,IAAM,SAAgC,CAAC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,QAAI,kCAAiB,EAAE,WAAW,oBAAoB,CAAC;AAErE,QAAM,CAAC,eAAe,gBAAgB,IAAI,cAAAC,QAAM,SAAS,KAAK;AAE9D,gBAAAA,QAAM,UAAU,MAAM;AACpB,qBAAiB,KAAK;AAAA,EACxB,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,WAAW,CAAC,CAAC,OAAO,CAAC;AAE3B,QAAM,aAAa,MAAM,OAAO,OAAO,IAAI;AAE3C,QAAM,iBACJ,SAAS,UACL,MAAM,OAAO,WAAW,MAAM,UAC9B,MAAM,OAAO,QAAQ;AAC3B,QAAM,sBACJ,SAAS,UACL,MAAM,OAAO,WAAW,MAAM,YAC9B,MAAM,OAAO,QAAQ;AAC3B,QAAM,cACJ,SAAS,UACL,MAAM,OAAO,QAAQ,GAAG,QACxB,MAAM,OAAO,QAAQ;AAG3B,QAAM,eAAe,SACjB,WAAW,qBACX,WAAW;AAEf,QAAM,eAAe;AAAA,IACnB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACA,QAAM,aAAa;AAAA,IACjB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACA,QAAM,kBAAkB,CAAC,EAAE,cAAc;AACzC,QAAM,YAAY,kBAAkB,aAAa,IAAI,IAAI,WAAW,IAAI;AAExE,QAAM,eAAe,cAAc,QAAQ,cAAc;AAIzD,QAAM,eAAe,MAAM;AACzB,QAAI,QAAQ;AACV,aAAO,SAAS,QAAQ,EAAE,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,OAAO,IAAI,KAAK,GAAG;AAAA,IACxE;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,MACvB,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IAC1B;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B;AAEA,QAAM,cACJ,mBAAmB,CAAC,eAChB,SACE,WAAW,oBACX,WAAW,oBACb,aAAa;AAGnB,QAAM,oBAAoB;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MACnB,UAAS;AAAA,MACR,GAAI,CAAC,YAAY,EAAE,MAAM,OAAO,cAAc,UAAU;AAAA,MACxD,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;AAAA,YACpC,YAAW;AAAA,YACX,gBAAe;AAAA,YACf,UAAS;AAAA,YACT,UAAS;AAAA,YACT,aAAa;AAAA,YACb,aAAa,MAAM,OAAO,OAAO;AAAA,YAChC,GAAI,CAAC,gBACJ,CAAC,YAAY;AAAA,cACX,YAAY;AAAA,gBACV,iBAAiB;AAAA,cACnB;AAAA,YACF;AAAA,YAED,qBACC;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH;AAAA,gBACA,KAAK,OAAO,aAAa;AAAA,gBACzB,UAAS;AAAA,gBACT,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP;AAAA,gBACA,SAAS,MAAM,iBAAiB,IAAI;AAAA;AAAA,YACtC,IACE,OACF,6CAAC,QAAK,MAAM,WAAW,UAAU,OAAO,aACrC,gBACH,IACE,OACF;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU,WAAW;AAAA,gBACrB,OAAO;AAAA,gBACP,YAAW;AAAA,gBACX,eAAe;AAAA,gBAEd;AAAA;AAAA,YACH,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAM,WAAW;AAAA,gBACjB,OAAO;AAAA;AAAA,YACT;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,MAAM;AAAA,gBACN,YAAY,SAAS;AAAA,gBACrB,cACE,oBACI,GAAG,iBAAiB,mBACpB;AAAA,gBAGL;AAAA;AAAA,YACH;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AIlPA,IAAAC,mBAA0D;AAC1D,yBAAwB;AA6IhB,IAAAC,sBAAA;AAhFR,IAAM,sBAAsB;AAErB,IAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA,OAAO;AAAA,EACP,aAAa;AAAA,EACb,uBAAuB;AAAA,EACvB,cAAc;AAAA,EACd;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,QAAI,mCAAiB,EAAE,WAAW,oBAAoB,CAAC;AAErE,MAAI,aAAa,GAAG;AAClB,YAAQ;AAAA,MACN,kEAAkE,UAAU,8BAA8B,mBAAmB;AAAA,IAC/H;AAAA,EACF;AACA,QAAM,sBAAsB,aAAa,IAAI,sBAAsB;AAEnE,QAAM,aAAa,KAAK;AACxB,QAAM,YAAY,aAAa;AAC/B,QAAM,eAAe,YAAY,sBAAsB,IAAI;AAC3D,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;AAEJ,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;AAAA,kBACA;AAAA,kBACA,cAAc;AAAA,kBACd,OAAO,KAAK;AAAA,kBACZ,YAAY,KAAK;AAAA,kBACjB,WAAW,KAAK;AAAA,kBAChB,WAAW,KAAK;AAAA,kBACf,GAAI,KAAK,UAAU,EAAE,cAAc,KAAK,QAAQ,IAAI,CAAC;AAAA;AAAA,cACxD;AAAA;AAAA,YAfK;AAAA,UAgBP;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;AAAA,YACA,MAAM,iBAAiB,KAAK,QAAQ,IAAI,cAAc;AAAA,YACtD,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","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime","React","import_xui_core","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/Avatar.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../../../foundation/primitives-native/src/Text.tsx","../../../../foundation/primitives-native/src/Icon.tsx","../../src/AvatarGroup.tsx"],"sourcesContent":["export * from \"./Avatar\";\nexport * from \"./AvatarGroup\";\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 /** Visual tone — 'mono' (default) or 'brand'. */\n tone?: \"mono\" | \"brand\";\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 /** Icon to display in the badge */\n badgeIcon?: React.ReactNode;\n /**\n * Background colour override. Intended for internal use by AvatarGroup to\n * drive its `avatarBackgroundMode` cycling; not part of the public API.\n * @internal\n */\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 /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const Avatar: React.FC<AvatarProps> = ({\n src,\n icon,\n text,\n size = \"xl\",\n square = false,\n tone = \"mono\",\n badge = false,\n badgeCount,\n badgeIcon,\n badgeTone = \"alert\",\n backgroundColor,\n disableHover = true,\n \"aria-label\": ariaLabel,\n alt,\n onClick,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const [hasImageError, setHasImageError] = React.useState(false);\n\n React.useEffect(() => {\n setHasImageError(false);\n }, [src]);\n\n const useImage = !!src && !hasImageError;\n\n const sizeStyles = theme.sizing.avatar(size);\n\n const toneBackground =\n tone === \"brand\"\n ? theme.colors.background.brand.primary\n : theme.colors.overlay.mono;\n const toneHoverBackground =\n tone === \"brand\"\n ? theme.colors.background.brand.secondary\n : theme.colors.overlay.monoHover;\n const toneContent =\n tone === \"brand\"\n ? theme.colors.content.on.brand\n : theme.colors.content.primary;\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: \"xs\",\n } as const;\n const hasBadgeContent = !!(badgeCount || badgeIcon);\n const badgeSize = hasBadgeContent ? countSizeMap[size] : dotSizeMap[size];\n // Badge sizes sm/xs are dot-only — content is dropped, so position as a dot.\n const rendersAsDot = badgeSize === \"sm\" || badgeSize === \"xs\";\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 =\n hasBadgeContent && !rendersAsDot\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 testID={testID}\n width={sizeStyles.size}\n height={sizeStyles.size}\n position=\"relative\"\n {...(!useImage && { 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 || toneBackground}\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n overflow=\"hidden\"\n borderWidth={2}\n borderColor={theme.colors.border.secondary}\n {...(!disableHover &&\n !useImage && {\n hoverStyle: {\n backgroundColor: toneHoverBackground,\n },\n })}\n >\n {useImage ? (\n <Box\n as=\"img\"\n src={src}\n alt={alt || ariaLabel || \"\"}\n position=\"absolute\"\n top={0}\n left={0}\n width=\"100%\"\n height=\"100%\"\n borderRadius={borderRadius}\n onError={() => setHasImageError(true)}\n />\n ) : icon ? (\n <Icon size={sizeStyles.iconSize} color={toneContent}>\n {icon}\n </Icon>\n ) : text ? (\n <Text\n fontSize={sizeStyles.fontSize}\n color={toneContent}\n fontWeight=\"400\"\n letterSpacing={0.4}\n >\n {text}\n </Text>\n ) : (\n <User\n variant=\"solid\"\n size={sizeStyles.iconSize}\n color={toneContent}\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 icon={badgeIcon}\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\";\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 testID,\n \"data-testid\": dataTestId,\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={dataTestId || 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> = ({\n children,\n color,\n size,\n testID,\n \"data-testid\": dataTestId,\n}) => {\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 (\n <View style={style} testID={dataTestId || testID}>\n {childrenWithProps}\n </View>\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, AvatarProps } 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 /** Tooltip text to display on hover */\n tooltip?: string;\n /** Whether to show a badge on the avatar */\n badge?: boolean;\n /** Number or text to display in the badge notification */\n badgeCount?: React.ReactNode;\n /** Icon to display in the badge */\n badgeIcon?: React.ReactNode;\n /** Color tone for the badge */\n badgeTone?: AvatarProps[\"badgeTone\"];\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?: \"xxs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n /**\n * Maximum number of slots rendered, including the \"+N\" overflow counter.\n * When the list exceeds this, (maxVisible - 1) avatars are shown plus a \"+N\" indicator.\n * When the list fits, all avatars are shown and no \"+N\" is rendered.\n */\n maxVisible?: number;\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 /** Test ID for testing frameworks */\n testID?: string;\n}\n\nconst DEFAULT_MAX_VISIBLE = 6;\n\nexport const AvatarGroup: React.FC<AvatarGroupProps> = ({\n list,\n size = \"sm\",\n maxVisible = DEFAULT_MAX_VISIBLE,\n avatarBackgroundMode = \"mixed\",\n \"aria-label\": ariaLabel,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n if (maxVisible < 1) {\n console.warn(\n `[AvatarGroup] \"maxVisible\" must be a positive number. Received ${maxVisible}, falling back to default (${DEFAULT_MAX_VISIBLE}).`\n );\n }\n const effectiveMaxVisible = maxVisible < 1 ? DEFAULT_MAX_VISIBLE : maxVisible;\n\n const totalCount = list.length;\n const overflows = totalCount > effectiveMaxVisible;\n const visibleCount = overflows ? effectiveMaxVisible - 1 : totalCount;\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 testID={testID}\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 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={size}\n backgroundColor={backgroundColor}\n disableHover={true}\n badge={item.badge}\n badgeCount={item.badgeCount}\n badgeIcon={item.badgeIcon}\n badgeTone={item.badgeTone}\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={size}\n text={remainingCount > 99 ? \"99+\" : `+${remainingCount}`}\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","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime","React","import_xui_core","import_jsx_runtime"]}
|
package/native/index.mjs
CHANGED
|
@@ -209,6 +209,8 @@ var Text = ({
|
|
|
209
209
|
numberOfLines,
|
|
210
210
|
id,
|
|
211
211
|
role,
|
|
212
|
+
testID,
|
|
213
|
+
"data-testid": dataTestId,
|
|
212
214
|
style: styleProp,
|
|
213
215
|
...props
|
|
214
216
|
}) => {
|
|
@@ -238,7 +240,7 @@ var Text = ({
|
|
|
238
240
|
{
|
|
239
241
|
style: baseStyle,
|
|
240
242
|
numberOfLines,
|
|
241
|
-
testID: id,
|
|
243
|
+
testID: dataTestId || testID || id,
|
|
242
244
|
accessibilityRole,
|
|
243
245
|
children
|
|
244
246
|
}
|
|
@@ -249,7 +251,13 @@ var Text = ({
|
|
|
249
251
|
import React from "react";
|
|
250
252
|
import { View as View2 } from "react-native";
|
|
251
253
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
252
|
-
var Icon = ({
|
|
254
|
+
var Icon = ({
|
|
255
|
+
children,
|
|
256
|
+
color,
|
|
257
|
+
size,
|
|
258
|
+
testID,
|
|
259
|
+
"data-testid": dataTestId
|
|
260
|
+
}) => {
|
|
253
261
|
const style = {
|
|
254
262
|
width: typeof size === "number" ? size : void 0,
|
|
255
263
|
height: typeof size === "number" ? size : void 0,
|
|
@@ -266,7 +274,7 @@ var Icon = ({ children, color, size }) => {
|
|
|
266
274
|
}
|
|
267
275
|
return child;
|
|
268
276
|
});
|
|
269
|
-
return /* @__PURE__ */ jsx3(View2, { style, children: childrenWithProps });
|
|
277
|
+
return /* @__PURE__ */ jsx3(View2, { style, testID: dataTestId || testID, children: childrenWithProps });
|
|
270
278
|
};
|
|
271
279
|
|
|
272
280
|
// src/Avatar.tsx
|
|
@@ -290,6 +298,7 @@ var Avatar = ({
|
|
|
290
298
|
"aria-label": ariaLabel,
|
|
291
299
|
alt,
|
|
292
300
|
onClick,
|
|
301
|
+
testID,
|
|
293
302
|
themeMode,
|
|
294
303
|
themeProductContext
|
|
295
304
|
}) => {
|
|
@@ -342,6 +351,7 @@ var Avatar = ({
|
|
|
342
351
|
return /* @__PURE__ */ jsxs(
|
|
343
352
|
Box,
|
|
344
353
|
{
|
|
354
|
+
testID,
|
|
345
355
|
width: sizeStyles.size,
|
|
346
356
|
height: sizeStyles.size,
|
|
347
357
|
position: "relative",
|
|
@@ -445,6 +455,7 @@ var AvatarGroup = ({
|
|
|
445
455
|
maxVisible = DEFAULT_MAX_VISIBLE,
|
|
446
456
|
avatarBackgroundMode = "mixed",
|
|
447
457
|
"aria-label": ariaLabel,
|
|
458
|
+
testID,
|
|
448
459
|
themeMode,
|
|
449
460
|
themeProductContext
|
|
450
461
|
}) => {
|
|
@@ -497,6 +508,7 @@ var AvatarGroup = ({
|
|
|
497
508
|
return /* @__PURE__ */ jsxs2(
|
|
498
509
|
Box,
|
|
499
510
|
{
|
|
511
|
+
testID,
|
|
500
512
|
flexDirection: "row",
|
|
501
513
|
alignItems: "center",
|
|
502
514
|
role: "group",
|