@xsolla/xui-b2c-media-card 0.217.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 +7 -0
- package/native/index.d.mts +64 -0
- package/native/index.d.ts +64 -0
- package/native/index.js +542 -0
- package/native/index.js.map +1 -0
- package/native/index.mjs +522 -0
- package/native/index.mjs.map +1 -0
- package/package.json +56 -0
- package/web/index.d.mts +64 -0
- package/web/index.d.ts +64 -0
- package/web/index.js +4114 -0
- package/web/index.js.map +1 -0
- package/web/index.mjs +4100 -0
- package/web/index.mjs.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @xsolla/xui-b2c-media-card
|
|
2
|
+
|
|
3
|
+
B2C watchable-media thumbnail with a centred Watch call to action, in landscape
|
|
4
|
+
and portrait orientations, with an optional rewarded variant.
|
|
5
|
+
|
|
6
|
+
Not the B2B `MediaCard` (`@xsolla/xui-b2b-media-card`), which is an
|
|
7
|
+
upload-management tile.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Figma `Orientation`. `horizontal` is the 319×179 landscape plate used in a
|
|
6
|
+
* video row; `vertical` is the 95×169 portrait plate used in a shorts rail.
|
|
7
|
+
*/
|
|
8
|
+
type MediaCardOrientation = "horizontal" | "vertical";
|
|
9
|
+
interface MediaCardProps extends ThemeOverrideProps {
|
|
10
|
+
/** Thumbnail image URL. Fills the whole plate, cropped to cover. */
|
|
11
|
+
src: string;
|
|
12
|
+
/**
|
|
13
|
+
* Human-readable name of the media this card represents, e.g.
|
|
14
|
+
* `"Chapter 3: The Ascent"`.
|
|
15
|
+
*
|
|
16
|
+
* This is what makes a grid of cards usable with a screen reader: the Watch
|
|
17
|
+
* control is named `"Watch {mediaName}"` rather than a bare `"Watch"`, so ten
|
|
18
|
+
* cards in a row do not all announce as the same button. Required for that
|
|
19
|
+
* reason — pass the title even when it is not drawn on the card.
|
|
20
|
+
*/
|
|
21
|
+
mediaName: string;
|
|
22
|
+
/**
|
|
23
|
+
* Alt text for the thumbnail. Defaults to `""` (decorative): the thumbnail is
|
|
24
|
+
* a picture *of* the media that `mediaName` already names, so describing it
|
|
25
|
+
* again duplicates the announcement. Pass a value only when the image carries
|
|
26
|
+
* information the name does not.
|
|
27
|
+
*/
|
|
28
|
+
alt?: string;
|
|
29
|
+
/** Figma `Orientation`. Defaults to `horizontal`. */
|
|
30
|
+
orientation?: MediaCardOrientation;
|
|
31
|
+
/**
|
|
32
|
+
* Figma `Rewarded`. Marks the media as granting a reward for watching, which
|
|
33
|
+
* appends the `rewardIcon` to the Watch control and to its accessible name.
|
|
34
|
+
*/
|
|
35
|
+
rewarded?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The reward glyph shown inside the Watch control when `rewarded` is set.
|
|
38
|
+
* Unopinionated slot — pass the product's own coin/currency icon. Omit it and
|
|
39
|
+
* the card draws a neutral 16 px placeholder mark instead.
|
|
40
|
+
*/
|
|
41
|
+
rewardIcon?: ReactNode;
|
|
42
|
+
/** Figma `Watch Button`. Set `false` to render the bare thumbnail. Defaults to `true`. */
|
|
43
|
+
showWatchButton?: boolean;
|
|
44
|
+
/** Visible label on the Watch control. Defaults to `"Watch"`. */
|
|
45
|
+
watchLabel?: string;
|
|
46
|
+
/** Called when the Watch control is activated. */
|
|
47
|
+
onWatchPress?: () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Called when the plate itself is pressed. Optional — a card can be a pure
|
|
50
|
+
* thumbnail whose only action is the Watch control.
|
|
51
|
+
*/
|
|
52
|
+
onPress?: () => void;
|
|
53
|
+
/** Removes interactivity from both the plate and the Watch control, and dims the card. */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
/** Plate width. Defaults to the Figma frame width for the orientation. */
|
|
56
|
+
width?: number | string;
|
|
57
|
+
/** Plate height. Overrides the orientation's aspect ratio when supplied. */
|
|
58
|
+
height?: number | string;
|
|
59
|
+
testID?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare const MediaCard: React.FC<MediaCardProps>;
|
|
63
|
+
|
|
64
|
+
export { MediaCard, type MediaCardOrientation, type MediaCardProps };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Figma `Orientation`. `horizontal` is the 319×179 landscape plate used in a
|
|
6
|
+
* video row; `vertical` is the 95×169 portrait plate used in a shorts rail.
|
|
7
|
+
*/
|
|
8
|
+
type MediaCardOrientation = "horizontal" | "vertical";
|
|
9
|
+
interface MediaCardProps extends ThemeOverrideProps {
|
|
10
|
+
/** Thumbnail image URL. Fills the whole plate, cropped to cover. */
|
|
11
|
+
src: string;
|
|
12
|
+
/**
|
|
13
|
+
* Human-readable name of the media this card represents, e.g.
|
|
14
|
+
* `"Chapter 3: The Ascent"`.
|
|
15
|
+
*
|
|
16
|
+
* This is what makes a grid of cards usable with a screen reader: the Watch
|
|
17
|
+
* control is named `"Watch {mediaName}"` rather than a bare `"Watch"`, so ten
|
|
18
|
+
* cards in a row do not all announce as the same button. Required for that
|
|
19
|
+
* reason — pass the title even when it is not drawn on the card.
|
|
20
|
+
*/
|
|
21
|
+
mediaName: string;
|
|
22
|
+
/**
|
|
23
|
+
* Alt text for the thumbnail. Defaults to `""` (decorative): the thumbnail is
|
|
24
|
+
* a picture *of* the media that `mediaName` already names, so describing it
|
|
25
|
+
* again duplicates the announcement. Pass a value only when the image carries
|
|
26
|
+
* information the name does not.
|
|
27
|
+
*/
|
|
28
|
+
alt?: string;
|
|
29
|
+
/** Figma `Orientation`. Defaults to `horizontal`. */
|
|
30
|
+
orientation?: MediaCardOrientation;
|
|
31
|
+
/**
|
|
32
|
+
* Figma `Rewarded`. Marks the media as granting a reward for watching, which
|
|
33
|
+
* appends the `rewardIcon` to the Watch control and to its accessible name.
|
|
34
|
+
*/
|
|
35
|
+
rewarded?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The reward glyph shown inside the Watch control when `rewarded` is set.
|
|
38
|
+
* Unopinionated slot — pass the product's own coin/currency icon. Omit it and
|
|
39
|
+
* the card draws a neutral 16 px placeholder mark instead.
|
|
40
|
+
*/
|
|
41
|
+
rewardIcon?: ReactNode;
|
|
42
|
+
/** Figma `Watch Button`. Set `false` to render the bare thumbnail. Defaults to `true`. */
|
|
43
|
+
showWatchButton?: boolean;
|
|
44
|
+
/** Visible label on the Watch control. Defaults to `"Watch"`. */
|
|
45
|
+
watchLabel?: string;
|
|
46
|
+
/** Called when the Watch control is activated. */
|
|
47
|
+
onWatchPress?: () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Called when the plate itself is pressed. Optional — a card can be a pure
|
|
50
|
+
* thumbnail whose only action is the Watch control.
|
|
51
|
+
*/
|
|
52
|
+
onPress?: () => void;
|
|
53
|
+
/** Removes interactivity from both the plate and the Watch control, and dims the card. */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
/** Plate width. Defaults to the Figma frame width for the orientation. */
|
|
56
|
+
width?: number | string;
|
|
57
|
+
/** Plate height. Overrides the orientation's aspect ratio when supplied. */
|
|
58
|
+
height?: number | string;
|
|
59
|
+
testID?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare const MediaCard: React.FC<MediaCardProps>;
|
|
63
|
+
|
|
64
|
+
export { MediaCard, type MediaCardOrientation, type MediaCardProps };
|
package/native/index.js
ADDED
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.tsx
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
MediaCard: () => MediaCard
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// ../../foundation/primitives-native/src/Box.tsx
|
|
28
|
+
var import_react_native = require("react-native");
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
var roleToAccessibilityRole = {
|
|
31
|
+
button: "button",
|
|
32
|
+
link: "link",
|
|
33
|
+
img: "image",
|
|
34
|
+
image: "image",
|
|
35
|
+
summary: "summary",
|
|
36
|
+
switch: "switch",
|
|
37
|
+
checkbox: "checkbox",
|
|
38
|
+
radio: "radio",
|
|
39
|
+
heading: "header",
|
|
40
|
+
text: "text",
|
|
41
|
+
search: "search",
|
|
42
|
+
alert: "alert",
|
|
43
|
+
none: "none",
|
|
44
|
+
presentation: "none",
|
|
45
|
+
progressbar: "progressbar",
|
|
46
|
+
scrollbar: "scrollbar",
|
|
47
|
+
adjustable: "adjustable",
|
|
48
|
+
tab: "tab",
|
|
49
|
+
menu: "menu",
|
|
50
|
+
menuitem: "menuitem",
|
|
51
|
+
list: "list",
|
|
52
|
+
timer: "timer"
|
|
53
|
+
};
|
|
54
|
+
var toGapValue = (gap) => {
|
|
55
|
+
if (gap === void 0) return void 0;
|
|
56
|
+
if (typeof gap === "number") return gap;
|
|
57
|
+
const pxMatch = /^(\d+(?:\.\d+)?)px$/.exec(gap);
|
|
58
|
+
if (pxMatch) return Number(pxMatch[1]);
|
|
59
|
+
const asNumber = Number(gap);
|
|
60
|
+
return Number.isFinite(asNumber) ? asNumber : void 0;
|
|
61
|
+
};
|
|
62
|
+
var Box = ({
|
|
63
|
+
children,
|
|
64
|
+
onPress,
|
|
65
|
+
onLayout,
|
|
66
|
+
onMoveShouldSetResponder,
|
|
67
|
+
onResponderGrant,
|
|
68
|
+
onResponderMove,
|
|
69
|
+
onResponderRelease,
|
|
70
|
+
onResponderTerminate,
|
|
71
|
+
backgroundColor,
|
|
72
|
+
borderColor,
|
|
73
|
+
borderWidth,
|
|
74
|
+
borderBottomWidth,
|
|
75
|
+
borderBottomColor,
|
|
76
|
+
borderTopWidth,
|
|
77
|
+
borderTopColor,
|
|
78
|
+
borderLeftWidth,
|
|
79
|
+
borderLeftColor,
|
|
80
|
+
borderRightWidth,
|
|
81
|
+
borderRightColor,
|
|
82
|
+
borderRadius,
|
|
83
|
+
borderStyle,
|
|
84
|
+
height,
|
|
85
|
+
padding,
|
|
86
|
+
paddingHorizontal,
|
|
87
|
+
paddingVertical,
|
|
88
|
+
margin,
|
|
89
|
+
marginTop,
|
|
90
|
+
marginBottom,
|
|
91
|
+
marginLeft,
|
|
92
|
+
marginRight,
|
|
93
|
+
flexDirection,
|
|
94
|
+
flexWrap,
|
|
95
|
+
alignItems,
|
|
96
|
+
justifyContent,
|
|
97
|
+
alignSelf,
|
|
98
|
+
position,
|
|
99
|
+
top,
|
|
100
|
+
bottom,
|
|
101
|
+
left,
|
|
102
|
+
right,
|
|
103
|
+
width,
|
|
104
|
+
minWidth,
|
|
105
|
+
minHeight,
|
|
106
|
+
maxWidth,
|
|
107
|
+
maxHeight,
|
|
108
|
+
flex,
|
|
109
|
+
flexShrink,
|
|
110
|
+
gap,
|
|
111
|
+
overflow,
|
|
112
|
+
opacity,
|
|
113
|
+
zIndex,
|
|
114
|
+
hoverStyle,
|
|
115
|
+
pressStyle,
|
|
116
|
+
style,
|
|
117
|
+
disabled,
|
|
118
|
+
"data-testid": dataTestId,
|
|
119
|
+
testID,
|
|
120
|
+
as,
|
|
121
|
+
src,
|
|
122
|
+
alt,
|
|
123
|
+
...rest
|
|
124
|
+
}) => {
|
|
125
|
+
const getContainerStyle = (pressed) => ({
|
|
126
|
+
backgroundColor: pressed && pressStyle?.backgroundColor ? pressStyle.backgroundColor : backgroundColor,
|
|
127
|
+
borderColor,
|
|
128
|
+
borderWidth,
|
|
129
|
+
borderBottomWidth,
|
|
130
|
+
borderBottomColor,
|
|
131
|
+
borderTopWidth,
|
|
132
|
+
borderTopColor,
|
|
133
|
+
borderLeftWidth,
|
|
134
|
+
borderLeftColor,
|
|
135
|
+
borderRightWidth,
|
|
136
|
+
borderRightColor,
|
|
137
|
+
borderRadius,
|
|
138
|
+
borderStyle,
|
|
139
|
+
overflow,
|
|
140
|
+
opacity: opacity ?? (disabled ? 0.5 : void 0),
|
|
141
|
+
zIndex,
|
|
142
|
+
height,
|
|
143
|
+
width,
|
|
144
|
+
minWidth,
|
|
145
|
+
minHeight,
|
|
146
|
+
maxWidth,
|
|
147
|
+
maxHeight,
|
|
148
|
+
padding,
|
|
149
|
+
paddingHorizontal,
|
|
150
|
+
paddingVertical,
|
|
151
|
+
margin,
|
|
152
|
+
marginTop,
|
|
153
|
+
marginBottom,
|
|
154
|
+
marginLeft,
|
|
155
|
+
marginRight,
|
|
156
|
+
flexDirection,
|
|
157
|
+
flexWrap,
|
|
158
|
+
alignItems,
|
|
159
|
+
justifyContent,
|
|
160
|
+
alignSelf,
|
|
161
|
+
position,
|
|
162
|
+
top,
|
|
163
|
+
bottom,
|
|
164
|
+
left,
|
|
165
|
+
right,
|
|
166
|
+
flex,
|
|
167
|
+
flexShrink,
|
|
168
|
+
gap: toGapValue(gap),
|
|
169
|
+
...style
|
|
170
|
+
});
|
|
171
|
+
const finalTestID = dataTestId || testID;
|
|
172
|
+
const {
|
|
173
|
+
role,
|
|
174
|
+
tabIndex,
|
|
175
|
+
onKeyDown,
|
|
176
|
+
onKeyUp,
|
|
177
|
+
"aria-label": ariaLabel,
|
|
178
|
+
"aria-labelledby": _ariaLabelledBy,
|
|
179
|
+
"aria-current": _ariaCurrent,
|
|
180
|
+
"aria-disabled": ariaDisabled,
|
|
181
|
+
"aria-live": ariaLive,
|
|
182
|
+
"aria-busy": ariaBusy,
|
|
183
|
+
className,
|
|
184
|
+
"data-testid": _dataTestId,
|
|
185
|
+
cursor: _cursor,
|
|
186
|
+
type: _type,
|
|
187
|
+
...nativeRest
|
|
188
|
+
} = rest;
|
|
189
|
+
const accessibilityRole = typeof role === "string" && roleToAccessibilityRole[role] || (as === "button" ? "button" : void 0);
|
|
190
|
+
const isDisabled = Boolean(disabled || ariaDisabled);
|
|
191
|
+
const accessibilityState = {
|
|
192
|
+
disabled: isDisabled || void 0,
|
|
193
|
+
busy: Boolean(ariaBusy) || void 0
|
|
194
|
+
};
|
|
195
|
+
const accessibilityLiveRegion = ariaLive === "polite" || ariaLive === "assertive" ? ariaLive : void 0;
|
|
196
|
+
if (as === "img" && src) {
|
|
197
|
+
const imageStyle = {
|
|
198
|
+
width,
|
|
199
|
+
height,
|
|
200
|
+
borderRadius,
|
|
201
|
+
position,
|
|
202
|
+
top,
|
|
203
|
+
bottom,
|
|
204
|
+
left,
|
|
205
|
+
right,
|
|
206
|
+
...style
|
|
207
|
+
};
|
|
208
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
209
|
+
import_react_native.Image,
|
|
210
|
+
{
|
|
211
|
+
source: { uri: src },
|
|
212
|
+
style: imageStyle,
|
|
213
|
+
testID: finalTestID,
|
|
214
|
+
accessibilityLabel: typeof ariaLabel === "string" ? ariaLabel : alt,
|
|
215
|
+
resizeMode: "cover",
|
|
216
|
+
...nativeRest
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
if (onPress || as === "button") {
|
|
221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
222
|
+
import_react_native.Pressable,
|
|
223
|
+
{
|
|
224
|
+
onPress: !isDisabled && onPress ? onPress : void 0,
|
|
225
|
+
disabled: isDisabled,
|
|
226
|
+
onLayout,
|
|
227
|
+
onMoveShouldSetResponder,
|
|
228
|
+
onResponderGrant,
|
|
229
|
+
onResponderMove,
|
|
230
|
+
onResponderRelease,
|
|
231
|
+
onResponderTerminate,
|
|
232
|
+
style: ({ pressed }) => getContainerStyle(pressed),
|
|
233
|
+
testID: finalTestID,
|
|
234
|
+
accessibilityRole,
|
|
235
|
+
accessibilityLabel: typeof ariaLabel === "string" ? ariaLabel : void 0,
|
|
236
|
+
accessibilityState,
|
|
237
|
+
accessibilityLiveRegion,
|
|
238
|
+
...nativeRest,
|
|
239
|
+
children
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
244
|
+
import_react_native.View,
|
|
245
|
+
{
|
|
246
|
+
style: getContainerStyle(),
|
|
247
|
+
testID: finalTestID,
|
|
248
|
+
onLayout,
|
|
249
|
+
onMoveShouldSetResponder,
|
|
250
|
+
onResponderGrant,
|
|
251
|
+
onResponderMove,
|
|
252
|
+
onResponderRelease,
|
|
253
|
+
onResponderTerminate,
|
|
254
|
+
accessibilityRole,
|
|
255
|
+
accessibilityLabel: typeof ariaLabel === "string" ? ariaLabel : void 0,
|
|
256
|
+
accessibilityState,
|
|
257
|
+
accessibilityLiveRegion,
|
|
258
|
+
...nativeRest,
|
|
259
|
+
children
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// ../../foundation/primitives-native/src/Text.tsx
|
|
265
|
+
var import_react_native2 = require("react-native");
|
|
266
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
267
|
+
var roleMap = {
|
|
268
|
+
alert: "alert",
|
|
269
|
+
heading: "header",
|
|
270
|
+
button: "button",
|
|
271
|
+
link: "link",
|
|
272
|
+
text: "text"
|
|
273
|
+
};
|
|
274
|
+
var parseNumericValue = (value) => {
|
|
275
|
+
if (value === void 0) return void 0;
|
|
276
|
+
if (typeof value === "number") return value;
|
|
277
|
+
const parsed = parseFloat(value);
|
|
278
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
279
|
+
};
|
|
280
|
+
var Text = ({
|
|
281
|
+
children,
|
|
282
|
+
color,
|
|
283
|
+
fontSize,
|
|
284
|
+
fontWeight,
|
|
285
|
+
fontFamily,
|
|
286
|
+
textAlign,
|
|
287
|
+
lineHeight,
|
|
288
|
+
numberOfLines,
|
|
289
|
+
id,
|
|
290
|
+
role,
|
|
291
|
+
testID,
|
|
292
|
+
"data-testid": dataTestId,
|
|
293
|
+
style: styleProp,
|
|
294
|
+
...props
|
|
295
|
+
}) => {
|
|
296
|
+
let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
|
|
297
|
+
if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
|
|
298
|
+
resolvedFontFamily = void 0;
|
|
299
|
+
}
|
|
300
|
+
const incomingStyle = import_react_native2.StyleSheet.flatten(styleProp);
|
|
301
|
+
const baseStyle = {
|
|
302
|
+
color: color ?? incomingStyle?.color,
|
|
303
|
+
fontSize: typeof fontSize === "number" ? fontSize : void 0,
|
|
304
|
+
fontWeight,
|
|
305
|
+
fontFamily: resolvedFontFamily,
|
|
306
|
+
textDecorationLine: props.textDecoration,
|
|
307
|
+
textAlign: textAlign ?? incomingStyle?.textAlign,
|
|
308
|
+
lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),
|
|
309
|
+
marginTop: parseNumericValue(
|
|
310
|
+
incomingStyle?.marginTop
|
|
311
|
+
),
|
|
312
|
+
marginBottom: parseNumericValue(
|
|
313
|
+
incomingStyle?.marginBottom
|
|
314
|
+
)
|
|
315
|
+
};
|
|
316
|
+
const accessibilityRole = role ? roleMap[role] : void 0;
|
|
317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
318
|
+
import_react_native2.Text,
|
|
319
|
+
{
|
|
320
|
+
style: baseStyle,
|
|
321
|
+
numberOfLines,
|
|
322
|
+
testID: dataTestId || testID || id,
|
|
323
|
+
accessibilityRole,
|
|
324
|
+
children
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// ../../foundation/primitives-native/src/index.tsx
|
|
330
|
+
var isWeb = false;
|
|
331
|
+
|
|
332
|
+
// src/MediaCard.tsx
|
|
333
|
+
var import_xui_core = require("@xsolla/xui-core");
|
|
334
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
335
|
+
var FRAME = {
|
|
336
|
+
horizontal: { width: 319, height: 179 },
|
|
337
|
+
vertical: { width: 95, height: 169 }
|
|
338
|
+
};
|
|
339
|
+
var CARD_RADIUS = 8;
|
|
340
|
+
var WATCH_RADIUS = 4;
|
|
341
|
+
var WATCH_PADDING_X = 16;
|
|
342
|
+
var WATCH_PADDING_Y = 8;
|
|
343
|
+
var WATCH_GAP = 8;
|
|
344
|
+
var WATCH_FONT_SIZE = 14;
|
|
345
|
+
var WATCH_LINE_HEIGHT = 20;
|
|
346
|
+
var WATCH_FONT_WEIGHT = "500";
|
|
347
|
+
var REWARD_GLYPH_SIZE = 16;
|
|
348
|
+
var WatchControl = ({
|
|
349
|
+
label,
|
|
350
|
+
accessibleName,
|
|
351
|
+
disabled,
|
|
352
|
+
onPress,
|
|
353
|
+
background,
|
|
354
|
+
foreground,
|
|
355
|
+
fontFamily,
|
|
356
|
+
children
|
|
357
|
+
}) => {
|
|
358
|
+
if (isWeb) {
|
|
359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
360
|
+
"button",
|
|
361
|
+
{
|
|
362
|
+
type: "button",
|
|
363
|
+
"aria-label": accessibleName,
|
|
364
|
+
disabled,
|
|
365
|
+
"data-testid": "media-card-watch",
|
|
366
|
+
onClick: (event) => {
|
|
367
|
+
event.stopPropagation();
|
|
368
|
+
onPress?.();
|
|
369
|
+
},
|
|
370
|
+
style: {
|
|
371
|
+
alignItems: "center",
|
|
372
|
+
background,
|
|
373
|
+
border: 0,
|
|
374
|
+
borderRadius: WATCH_RADIUS,
|
|
375
|
+
color: foreground,
|
|
376
|
+
cursor: onPress && !disabled ? "pointer" : "default",
|
|
377
|
+
display: "inline-flex",
|
|
378
|
+
fontFamily,
|
|
379
|
+
fontSize: WATCH_FONT_SIZE,
|
|
380
|
+
fontWeight: WATCH_FONT_WEIGHT,
|
|
381
|
+
gap: WATCH_GAP,
|
|
382
|
+
lineHeight: `${WATCH_LINE_HEIGHT}px`,
|
|
383
|
+
margin: 0,
|
|
384
|
+
padding: `${WATCH_PADDING_Y}px ${WATCH_PADDING_X}px`,
|
|
385
|
+
whiteSpace: "nowrap",
|
|
386
|
+
zIndex: 10
|
|
387
|
+
},
|
|
388
|
+
children: [
|
|
389
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "data-testid": "media-card-watch-label", children: label }),
|
|
390
|
+
children
|
|
391
|
+
]
|
|
392
|
+
}
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
396
|
+
Box,
|
|
397
|
+
{
|
|
398
|
+
flexDirection: "row",
|
|
399
|
+
alignItems: "center",
|
|
400
|
+
gap: WATCH_GAP,
|
|
401
|
+
paddingHorizontal: WATCH_PADDING_X,
|
|
402
|
+
paddingVertical: WATCH_PADDING_Y,
|
|
403
|
+
borderRadius: WATCH_RADIUS,
|
|
404
|
+
backgroundColor: background,
|
|
405
|
+
zIndex: 10,
|
|
406
|
+
onPress: disabled ? void 0 : onPress,
|
|
407
|
+
accessibilityRole: "button",
|
|
408
|
+
accessibilityLabel: accessibleName,
|
|
409
|
+
testID: "media-card-watch",
|
|
410
|
+
children: [
|
|
411
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
412
|
+
Text,
|
|
413
|
+
{
|
|
414
|
+
color: foreground,
|
|
415
|
+
fontFamily,
|
|
416
|
+
fontSize: WATCH_FONT_SIZE,
|
|
417
|
+
lineHeight: WATCH_LINE_HEIGHT,
|
|
418
|
+
fontWeight: WATCH_FONT_WEIGHT,
|
|
419
|
+
numberOfLines: 1,
|
|
420
|
+
testID: "media-card-watch-label",
|
|
421
|
+
children: label
|
|
422
|
+
}
|
|
423
|
+
),
|
|
424
|
+
children
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
);
|
|
428
|
+
};
|
|
429
|
+
var MediaCard = ({
|
|
430
|
+
src,
|
|
431
|
+
mediaName,
|
|
432
|
+
alt = "",
|
|
433
|
+
orientation = "horizontal",
|
|
434
|
+
rewarded = false,
|
|
435
|
+
rewardIcon,
|
|
436
|
+
showWatchButton = true,
|
|
437
|
+
watchLabel = "Watch",
|
|
438
|
+
onWatchPress,
|
|
439
|
+
onPress,
|
|
440
|
+
disabled = false,
|
|
441
|
+
width,
|
|
442
|
+
height,
|
|
443
|
+
testID,
|
|
444
|
+
themeMode,
|
|
445
|
+
themeProductContext = "b2c"
|
|
446
|
+
}) => {
|
|
447
|
+
const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
|
|
448
|
+
const frame = FRAME[orientation];
|
|
449
|
+
const isPlateInteractive = Boolean(onPress) && !disabled;
|
|
450
|
+
const aspectRatio = frame.width / frame.height;
|
|
451
|
+
const watchAccessibleName = rewarded ? `${watchLabel} ${mediaName}, rewarded` : `${watchLabel} ${mediaName}`;
|
|
452
|
+
const plateInteractiveProps = isWeb && isPlateInteractive ? {
|
|
453
|
+
role: "button",
|
|
454
|
+
tabIndex: 0,
|
|
455
|
+
onKeyDown: (event) => {
|
|
456
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
457
|
+
event.preventDefault();
|
|
458
|
+
onPress?.();
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
} : {};
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
463
|
+
Box,
|
|
464
|
+
{
|
|
465
|
+
width: width ?? frame.width,
|
|
466
|
+
height,
|
|
467
|
+
position: "relative",
|
|
468
|
+
overflow: "hidden",
|
|
469
|
+
borderRadius: CARD_RADIUS,
|
|
470
|
+
borderWidth: 1,
|
|
471
|
+
borderStyle: "solid",
|
|
472
|
+
borderColor: theme.colors.border.secondary,
|
|
473
|
+
backgroundColor: theme.colors.background.secondary,
|
|
474
|
+
alignItems: "center",
|
|
475
|
+
justifyContent: "center",
|
|
476
|
+
opacity: disabled ? 0.48 : 1,
|
|
477
|
+
onPress: isPlateInteractive ? onPress : void 0,
|
|
478
|
+
"aria-label": mediaName,
|
|
479
|
+
"aria-disabled": disabled || void 0,
|
|
480
|
+
...!isWeb ? { accessibilityLabel: mediaName } : {},
|
|
481
|
+
style: {
|
|
482
|
+
aspectRatio: height ? void 0 : aspectRatio,
|
|
483
|
+
...isWeb && isPlateInteractive ? { cursor: "pointer" } : {}
|
|
484
|
+
},
|
|
485
|
+
"data-testid": testID || "media-card",
|
|
486
|
+
testID: testID || "media-card",
|
|
487
|
+
...plateInteractiveProps,
|
|
488
|
+
children: [
|
|
489
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
490
|
+
Box,
|
|
491
|
+
{
|
|
492
|
+
as: "img",
|
|
493
|
+
src,
|
|
494
|
+
alt,
|
|
495
|
+
position: "absolute",
|
|
496
|
+
top: 0,
|
|
497
|
+
left: 0,
|
|
498
|
+
width: "100%",
|
|
499
|
+
height: "100%",
|
|
500
|
+
style: isWeb ? { objectFit: "cover" } : void 0,
|
|
501
|
+
"data-testid": "media-card-thumbnail",
|
|
502
|
+
testID: "media-card-thumbnail"
|
|
503
|
+
}
|
|
504
|
+
),
|
|
505
|
+
showWatchButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
506
|
+
WatchControl,
|
|
507
|
+
{
|
|
508
|
+
label: watchLabel,
|
|
509
|
+
accessibleName: watchAccessibleName,
|
|
510
|
+
disabled,
|
|
511
|
+
onPress: onWatchPress,
|
|
512
|
+
background: theme.colors.control.brandExtra.primary.bg,
|
|
513
|
+
foreground: theme.colors.content.on.brandExtra,
|
|
514
|
+
fontFamily: theme.fonts.body,
|
|
515
|
+
children: rewarded && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
516
|
+
Box,
|
|
517
|
+
{
|
|
518
|
+
width: REWARD_GLYPH_SIZE,
|
|
519
|
+
height: REWARD_GLYPH_SIZE,
|
|
520
|
+
flexShrink: 0,
|
|
521
|
+
alignItems: "center",
|
|
522
|
+
justifyContent: "center",
|
|
523
|
+
borderRadius: REWARD_GLYPH_SIZE / 2,
|
|
524
|
+
backgroundColor: rewardIcon ? void 0 : theme.colors.content.on.brandExtra,
|
|
525
|
+
"aria-hidden": true,
|
|
526
|
+
"data-testid": "media-card-reward",
|
|
527
|
+
testID: "media-card-reward",
|
|
528
|
+
children: rewardIcon
|
|
529
|
+
}
|
|
530
|
+
)
|
|
531
|
+
}
|
|
532
|
+
)
|
|
533
|
+
]
|
|
534
|
+
}
|
|
535
|
+
);
|
|
536
|
+
};
|
|
537
|
+
MediaCard.displayName = "MediaCard";
|
|
538
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
539
|
+
0 && (module.exports = {
|
|
540
|
+
MediaCard
|
|
541
|
+
});
|
|
542
|
+
//# sourceMappingURL=index.js.map
|