@xsolla/xui-dropdown 0.91.0 → 0.92.0-pr146.1771218879
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/native/index.d.mts +9 -0
- package/native/index.d.ts +9 -0
- package/native/index.js +85 -15
- package/native/index.js.flow +24 -0
- package/native/index.js.map +1 -1
- package/native/index.mjs +86 -16
- package/native/index.mjs.map +1 -1
- package/package.json +10 -7
- package/web/index.d.mts +9 -0
- package/web/index.d.ts +9 -0
- package/web/index.js +85 -15
- package/web/index.js.flow +24 -0
- package/web/index.js.map +1 -1
- package/web/index.mjs +86 -16
- package/web/index.mjs.map +1 -1
package/native/index.d.mts
CHANGED
|
@@ -5,7 +5,14 @@ interface DropdownProps {
|
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
isOpen?: boolean;
|
|
7
7
|
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
/** Width of the dropdown menu (does not affect trigger width) */
|
|
8
9
|
width?: string | number;
|
|
10
|
+
/** Horizontal alignment of dropdown menu relative to trigger. Default: "start" */
|
|
11
|
+
align?: "start" | "end";
|
|
12
|
+
/** Accessible label for the dropdown menu */
|
|
13
|
+
"aria-label"?: string;
|
|
14
|
+
/** Test ID for testing frameworks */
|
|
15
|
+
testID?: string;
|
|
9
16
|
}
|
|
10
17
|
declare const Dropdown: React.FC<DropdownProps>;
|
|
11
18
|
interface DropdownItemProps {
|
|
@@ -16,6 +23,8 @@ interface DropdownItemProps {
|
|
|
16
23
|
selected?: boolean;
|
|
17
24
|
disabled?: boolean;
|
|
18
25
|
icon?: React.ReactNode;
|
|
26
|
+
/** Test ID for testing frameworks */
|
|
27
|
+
testID?: string;
|
|
19
28
|
}
|
|
20
29
|
declare const DropdownItem: React.FC<DropdownItemProps>;
|
|
21
30
|
|
package/native/index.d.ts
CHANGED
|
@@ -5,7 +5,14 @@ interface DropdownProps {
|
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
isOpen?: boolean;
|
|
7
7
|
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
/** Width of the dropdown menu (does not affect trigger width) */
|
|
8
9
|
width?: string | number;
|
|
10
|
+
/** Horizontal alignment of dropdown menu relative to trigger. Default: "start" */
|
|
11
|
+
align?: "start" | "end";
|
|
12
|
+
/** Accessible label for the dropdown menu */
|
|
13
|
+
"aria-label"?: string;
|
|
14
|
+
/** Test ID for testing frameworks */
|
|
15
|
+
testID?: string;
|
|
9
16
|
}
|
|
10
17
|
declare const Dropdown: React.FC<DropdownProps>;
|
|
11
18
|
interface DropdownItemProps {
|
|
@@ -16,6 +23,8 @@ interface DropdownItemProps {
|
|
|
16
23
|
selected?: boolean;
|
|
17
24
|
disabled?: boolean;
|
|
18
25
|
icon?: React.ReactNode;
|
|
26
|
+
/** Test ID for testing frameworks */
|
|
27
|
+
testID?: string;
|
|
19
28
|
}
|
|
20
29
|
declare const DropdownItem: React.FC<DropdownItemProps>;
|
|
21
30
|
|
package/native/index.js
CHANGED
|
@@ -237,63 +237,119 @@ var Dropdown = ({
|
|
|
237
237
|
children,
|
|
238
238
|
isOpen: propIsOpen,
|
|
239
239
|
onOpenChange,
|
|
240
|
-
width = "auto"
|
|
240
|
+
width = "auto",
|
|
241
|
+
align = "start",
|
|
242
|
+
"aria-label": ariaLabel,
|
|
243
|
+
testID
|
|
241
244
|
}) => {
|
|
242
245
|
const [internalIsOpen, setInternalIsOpen] = (0, import_react.useState)(false);
|
|
243
246
|
const isOpen = propIsOpen !== void 0 ? propIsOpen : internalIsOpen;
|
|
244
247
|
const containerRef = (0, import_react.useRef)(null);
|
|
248
|
+
const triggerRef = (0, import_react.useRef)(null);
|
|
249
|
+
const menuRef = (0, import_react.useRef)(null);
|
|
245
250
|
const { theme } = (0, import_xui_core.useDesignSystem)();
|
|
246
|
-
const
|
|
251
|
+
const closeMenu = (0, import_react.useCallback)(() => {
|
|
252
|
+
if (propIsOpen === void 0) {
|
|
253
|
+
setInternalIsOpen(false);
|
|
254
|
+
}
|
|
255
|
+
if (onOpenChange) onOpenChange(false);
|
|
256
|
+
}, [propIsOpen, onOpenChange]);
|
|
257
|
+
const toggleOpen = (0, import_react.useCallback)(() => {
|
|
247
258
|
const nextOpen = !isOpen;
|
|
248
259
|
if (propIsOpen === void 0) {
|
|
249
260
|
setInternalIsOpen(nextOpen);
|
|
250
261
|
}
|
|
251
262
|
if (onOpenChange) onOpenChange(nextOpen);
|
|
252
|
-
};
|
|
263
|
+
}, [isOpen, propIsOpen, onOpenChange]);
|
|
264
|
+
const handleKeyDown = (0, import_react.useCallback)(
|
|
265
|
+
(event) => {
|
|
266
|
+
if (event.key === "Escape" && isOpen) {
|
|
267
|
+
event.preventDefault();
|
|
268
|
+
closeMenu();
|
|
269
|
+
triggerRef.current?.focus();
|
|
270
|
+
} else if (event.key === "Tab" && isOpen) {
|
|
271
|
+
closeMenu();
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
[isOpen, closeMenu]
|
|
275
|
+
);
|
|
276
|
+
const handleTriggerKeyDown = (0, import_react.useCallback)(
|
|
277
|
+
(event) => {
|
|
278
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
279
|
+
event.preventDefault();
|
|
280
|
+
toggleOpen();
|
|
281
|
+
} else if (event.key === "ArrowDown" && !isOpen) {
|
|
282
|
+
event.preventDefault();
|
|
283
|
+
if (propIsOpen === void 0) {
|
|
284
|
+
setInternalIsOpen(true);
|
|
285
|
+
}
|
|
286
|
+
if (onOpenChange) onOpenChange(true);
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
[isOpen, toggleOpen, propIsOpen, onOpenChange]
|
|
290
|
+
);
|
|
253
291
|
(0, import_react.useEffect)(() => {
|
|
254
292
|
const handleClickOutside = (event) => {
|
|
255
293
|
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
256
|
-
|
|
257
|
-
setInternalIsOpen(false);
|
|
258
|
-
}
|
|
259
|
-
if (onOpenChange) onOpenChange(false);
|
|
294
|
+
closeMenu();
|
|
260
295
|
}
|
|
261
296
|
};
|
|
262
|
-
if (isOpen) {
|
|
297
|
+
if (isOpen && typeof document !== "undefined") {
|
|
263
298
|
document.addEventListener("mousedown", handleClickOutside);
|
|
264
299
|
}
|
|
265
300
|
return () => {
|
|
266
|
-
document
|
|
301
|
+
if (typeof document !== "undefined") {
|
|
302
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
303
|
+
}
|
|
267
304
|
};
|
|
268
|
-
}, [isOpen,
|
|
305
|
+
}, [isOpen, closeMenu]);
|
|
269
306
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
270
307
|
"div",
|
|
271
308
|
{
|
|
272
309
|
ref: containerRef,
|
|
273
310
|
style: {
|
|
274
311
|
position: "relative",
|
|
275
|
-
width:
|
|
312
|
+
width: "fit-content",
|
|
276
313
|
alignSelf: "flex-start",
|
|
277
314
|
height: "fit-content"
|
|
278
315
|
},
|
|
316
|
+
onKeyDown: handleKeyDown,
|
|
317
|
+
"data-testid": testID,
|
|
279
318
|
children: [
|
|
280
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
319
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
320
|
+
"div",
|
|
321
|
+
{
|
|
322
|
+
ref: triggerRef,
|
|
323
|
+
onClick: toggleOpen,
|
|
324
|
+
onKeyDown: handleTriggerKeyDown,
|
|
325
|
+
role: "button",
|
|
326
|
+
tabIndex: 0,
|
|
327
|
+
"aria-haspopup": "menu",
|
|
328
|
+
"aria-expanded": isOpen,
|
|
329
|
+
style: { cursor: "pointer" },
|
|
330
|
+
children: trigger
|
|
331
|
+
}
|
|
332
|
+
),
|
|
281
333
|
isOpen && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
282
334
|
Box,
|
|
283
335
|
{
|
|
336
|
+
ref: menuRef,
|
|
284
337
|
position: "absolute",
|
|
285
338
|
top: "100%",
|
|
286
|
-
left: 0,
|
|
339
|
+
...align === "end" ? { right: 0 } : { left: 0 },
|
|
287
340
|
marginTop: 4,
|
|
288
341
|
backgroundColor: theme.colors.background.secondary,
|
|
289
342
|
borderColor: theme.colors.border.secondary,
|
|
290
343
|
borderWidth: 1,
|
|
291
344
|
borderRadius: theme.radius.button,
|
|
292
345
|
paddingVertical: 4,
|
|
346
|
+
role: "menu",
|
|
347
|
+
"aria-label": ariaLabel,
|
|
293
348
|
style: {
|
|
294
349
|
zIndex: 1e3,
|
|
295
350
|
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
|
|
296
|
-
minWidth: "100%"
|
|
351
|
+
minWidth: width === "auto" ? "100%" : width,
|
|
352
|
+
width: width !== "auto" ? width : void 0
|
|
297
353
|
},
|
|
298
354
|
children
|
|
299
355
|
}
|
|
@@ -308,7 +364,8 @@ var DropdownItem = ({
|
|
|
308
364
|
active,
|
|
309
365
|
selected,
|
|
310
366
|
disabled,
|
|
311
|
-
icon
|
|
367
|
+
icon,
|
|
368
|
+
testID
|
|
312
369
|
}) => {
|
|
313
370
|
const { theme } = (0, import_xui_core.useDesignSystem)();
|
|
314
371
|
const brandColors = theme.colors.control.brand.primary;
|
|
@@ -328,6 +385,12 @@ var DropdownItem = ({
|
|
|
328
385
|
}
|
|
329
386
|
return theme.colors.content.secondary;
|
|
330
387
|
};
|
|
388
|
+
const handleKeyDown = (event) => {
|
|
389
|
+
if ((event.key === "Enter" || event.key === " ") && !disabled && onPress) {
|
|
390
|
+
event.preventDefault();
|
|
391
|
+
onPress();
|
|
392
|
+
}
|
|
393
|
+
};
|
|
331
394
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
332
395
|
Box,
|
|
333
396
|
{
|
|
@@ -340,6 +403,11 @@ var DropdownItem = ({
|
|
|
340
403
|
hoverStyle: !disabled && !selected ? {
|
|
341
404
|
backgroundColor: theme.colors.control.input.bgHover
|
|
342
405
|
} : void 0,
|
|
406
|
+
role: "menuitem",
|
|
407
|
+
tabIndex: disabled ? -1 : 0,
|
|
408
|
+
"aria-disabled": disabled,
|
|
409
|
+
onKeyDown: handleKeyDown,
|
|
410
|
+
testID,
|
|
343
411
|
style: {
|
|
344
412
|
opacity: disabled ? 0.5 : 1,
|
|
345
413
|
cursor: disabled ? "not-allowed" : "pointer"
|
|
@@ -351,6 +419,8 @@ var DropdownItem = ({
|
|
|
351
419
|
}
|
|
352
420
|
);
|
|
353
421
|
};
|
|
422
|
+
Dropdown.displayName = "Dropdown";
|
|
423
|
+
DropdownItem.displayName = "DropdownItem";
|
|
354
424
|
// Annotate the CommonJS export names for ESM import in node:
|
|
355
425
|
0 && (module.exports = {
|
|
356
426
|
Dropdown,
|
package/native/index.js.flow
CHANGED
|
@@ -11,7 +11,26 @@ declare interface DropdownProps {
|
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
isOpen?: boolean;
|
|
13
13
|
onOpenChange?: (open: boolean) => void;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Width of the dropdown menu (does not affect trigger width)
|
|
17
|
+
*/
|
|
14
18
|
width?: string | number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Horizontal alignment of dropdown menu relative to trigger. Default: "start"
|
|
22
|
+
*/
|
|
23
|
+
align?: "start" | "end";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Accessible label for the dropdown menu
|
|
27
|
+
*/
|
|
28
|
+
"aria-label"?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Test ID for testing frameworks
|
|
32
|
+
*/
|
|
33
|
+
testID?: string;
|
|
15
34
|
}
|
|
16
35
|
declare var Dropdown: React.FC<DropdownProps>;
|
|
17
36
|
declare interface DropdownItemProps {
|
|
@@ -25,6 +44,11 @@ declare interface DropdownItemProps {
|
|
|
25
44
|
selected?: boolean;
|
|
26
45
|
disabled?: boolean;
|
|
27
46
|
icon?: React.ReactNode;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Test ID for testing frameworks
|
|
50
|
+
*/
|
|
51
|
+
testID?: string;
|
|
28
52
|
}
|
|
29
53
|
declare var DropdownItem: React.FC<DropdownItemProps>;
|
|
30
54
|
export type { DropdownItemProps, DropdownProps };
|
package/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../src/Dropdown.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx"],"sourcesContent":["export * from \"./Dropdown\";\n","import React, { useState, useRef, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface DropdownProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n isOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n width?: string | number;\n}\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n trigger,\n children,\n isOpen: propIsOpen,\n onOpenChange,\n width = \"auto\",\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const containerRef = useRef<any>(null);\n const { theme } = useDesignSystem();\n\n const toggleOpen = () => {\n const nextOpen = !isOpen;\n if (propIsOpen === undefined) {\n setInternalIsOpen(nextOpen);\n }\n if (onOpenChange) onOpenChange(nextOpen);\n };\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target)\n ) {\n if (propIsOpen === undefined) {\n setInternalIsOpen(false);\n }\n if (onOpenChange) onOpenChange(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen, propIsOpen, onOpenChange]);\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: width === \"auto\" ? \"fit-content\" : width,\n alignSelf: \"flex-start\",\n height: \"fit-content\",\n }}\n >\n <div onClick={toggleOpen} style={{ cursor: \"pointer\" }}>\n {trigger}\n </div>\n {isOpen && (\n <Box\n position=\"absolute\"\n top=\"100%\"\n left={0}\n marginTop={4}\n backgroundColor={theme.colors.background.secondary}\n borderColor={theme.colors.border.secondary}\n borderWidth={1}\n borderRadius={theme.radius.button}\n paddingVertical={4}\n style={{\n zIndex: 1000,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.1)\",\n minWidth: \"100%\",\n }}\n >\n {children}\n </Box>\n )}\n </div>\n );\n};\n\nexport interface DropdownItemProps {\n children: React.ReactNode;\n onPress?: () => void;\n active?: boolean;\n /** Whether this item is selected (shows trailing checkmark with control/check/bg color) */\n selected?: boolean;\n disabled?: boolean;\n icon?: React.ReactNode;\n}\n\nexport const DropdownItem: React.FC<DropdownItemProps> = ({\n children,\n onPress,\n active,\n selected,\n disabled,\n icon,\n}) => {\n const { theme } = useDesignSystem();\n const brandColors = theme.colors.control.brand.primary;\n const contentColors = theme.colors.content;\n\n // Determine background color\n const getBackgroundColor = () => {\n if (selected) {\n return brandColors?.bg || theme.colors.control.input.bg; // Cyan background for selected items\n }\n if (active) {\n return theme.colors.control.input.bgHover;\n }\n return \"transparent\";\n };\n\n // Determine text/icon color\n const getContentColor = () => {\n if (selected) {\n return contentColors?.on?.brand || theme.colors.content.primary; // Black text on cyan background\n }\n return theme.colors.content.secondary;\n };\n\n return (\n <Box\n onPress={!disabled ? onPress : undefined}\n paddingHorizontal={16}\n paddingVertical={8}\n flexDirection=\"row\"\n alignItems=\"center\"\n backgroundColor={getBackgroundColor()}\n hoverStyle={\n !disabled && !selected\n ? {\n backgroundColor: theme.colors.control.input.bgHover,\n }\n : undefined\n }\n style={{\n opacity: disabled ? 0.5 : 1,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n }}\n >\n {icon && (\n <Box marginRight={12} alignItems=\"center\" justifyContent=\"center\">\n {icon}\n </Box>\n )}\n <Box flex={1}>\n <Text color={getContentColor()} fontSize={14} fontWeight=\"400\">\n {children}\n </Text>\n </Box>\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 flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, it's better to use the system font\n // to avoid rendering issues or missing text.\n if (resolvedFontFamily === \"Pilat Wide Bold\") {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/Dropdown.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx"],"sourcesContent":["export * from \"./Dropdown\";\n","import React, { useState, useRef, useEffect, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface DropdownProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n isOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Width of the dropdown menu (does not affect trigger width) */\n width?: string | number;\n /** Horizontal alignment of dropdown menu relative to trigger. Default: \"start\" */\n align?: \"start\" | \"end\";\n /** Accessible label for the dropdown menu */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n trigger,\n children,\n isOpen: propIsOpen,\n onOpenChange,\n width = \"auto\",\n align = \"start\",\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const containerRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const { theme } = useDesignSystem();\n\n const closeMenu = useCallback(() => {\n if (propIsOpen === undefined) {\n setInternalIsOpen(false);\n }\n if (onOpenChange) onOpenChange(false);\n }, [propIsOpen, onOpenChange]);\n\n const toggleOpen = useCallback(() => {\n const nextOpen = !isOpen;\n if (propIsOpen === undefined) {\n setInternalIsOpen(nextOpen);\n }\n if (onOpenChange) onOpenChange(nextOpen);\n }, [isOpen, propIsOpen, onOpenChange]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Escape\" && isOpen) {\n event.preventDefault();\n closeMenu();\n triggerRef.current?.focus();\n } else if (event.key === \"Tab\" && isOpen) {\n closeMenu();\n }\n },\n [isOpen, closeMenu]\n );\n\n // Handle trigger keyboard events\n const handleTriggerKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleOpen();\n } else if (event.key === \"ArrowDown\" && !isOpen) {\n event.preventDefault();\n if (propIsOpen === undefined) {\n setInternalIsOpen(true);\n }\n if (onOpenChange) onOpenChange(true);\n }\n },\n [isOpen, toggleOpen, propIsOpen, onOpenChange]\n );\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n closeMenu();\n }\n };\n\n if (isOpen && typeof document !== \"undefined\") {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return () => {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }\n };\n }, [isOpen, closeMenu]);\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: \"fit-content\",\n alignSelf: \"flex-start\",\n height: \"fit-content\",\n }}\n onKeyDown={handleKeyDown}\n data-testid={testID}\n >\n <div\n ref={triggerRef}\n onClick={toggleOpen}\n onKeyDown={handleTriggerKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n style={{ cursor: \"pointer\" }}\n >\n {trigger}\n </div>\n {isOpen && (\n <Box\n ref={menuRef}\n position=\"absolute\"\n top=\"100%\"\n {...(align === \"end\" ? { right: 0 } : { left: 0 })}\n marginTop={4}\n backgroundColor={theme.colors.background.secondary}\n borderColor={theme.colors.border.secondary}\n borderWidth={1}\n borderRadius={theme.radius.button}\n paddingVertical={4}\n role=\"menu\"\n aria-label={ariaLabel}\n style={{\n zIndex: 1000,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.1)\",\n minWidth: width === \"auto\" ? \"100%\" : width,\n width: width !== \"auto\" ? width : undefined,\n }}\n >\n {children}\n </Box>\n )}\n </div>\n );\n};\n\nexport interface DropdownItemProps {\n children: React.ReactNode;\n onPress?: () => void;\n active?: boolean;\n /** Whether this item is selected (shows trailing checkmark with control/check/bg color) */\n selected?: boolean;\n disabled?: boolean;\n icon?: React.ReactNode;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const DropdownItem: React.FC<DropdownItemProps> = ({\n children,\n onPress,\n active,\n selected,\n disabled,\n icon,\n testID,\n}) => {\n const { theme } = useDesignSystem();\n const brandColors = theme.colors.control.brand.primary;\n const contentColors = theme.colors.content;\n\n // Determine background color\n const getBackgroundColor = () => {\n if (selected) {\n return brandColors?.bg || theme.colors.control.input.bg; // Cyan background for selected items\n }\n if (active) {\n return theme.colors.control.input.bgHover;\n }\n return \"transparent\";\n };\n\n // Determine text/icon color\n const getContentColor = () => {\n if (selected) {\n return contentColors?.on?.brand || theme.colors.content.primary; // Black text on cyan background\n }\n return theme.colors.content.secondary;\n };\n\n // Handle keyboard activation\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if ((event.key === \"Enter\" || event.key === \" \") && !disabled && onPress) {\n event.preventDefault();\n onPress();\n }\n };\n\n return (\n <Box\n onPress={!disabled ? onPress : undefined}\n paddingHorizontal={16}\n paddingVertical={8}\n flexDirection=\"row\"\n alignItems=\"center\"\n backgroundColor={getBackgroundColor()}\n hoverStyle={\n !disabled && !selected\n ? {\n backgroundColor: theme.colors.control.input.bgHover,\n }\n : undefined\n }\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n onKeyDown={handleKeyDown}\n testID={testID}\n style={{\n opacity: disabled ? 0.5 : 1,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n }}\n >\n {icon && (\n <Box marginRight={12} alignItems=\"center\" justifyContent=\"center\">\n {icon}\n </Box>\n )}\n <Box flex={1}>\n <Text color={getContentColor()} fontSize={14} fontWeight=\"400\">\n {children}\n </Text>\n </Box>\n </Box>\n );\n};\n\nDropdown.displayName = \"Dropdown\";\nDropdownItem.displayName = \"DropdownItem\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, it's better to use the system font\n // to avoid rendering issues or missing text.\n if (resolvedFontFamily === \"Pilat Wide Bold\") {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_jsx_runtime"]}
|
package/native/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/Dropdown.tsx
|
|
2
|
-
import { useState, useRef, useEffect } from "react";
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from "react";
|
|
3
3
|
|
|
4
4
|
// ../primitives-native/src/Box.tsx
|
|
5
5
|
import {
|
|
@@ -214,63 +214,119 @@ var Dropdown = ({
|
|
|
214
214
|
children,
|
|
215
215
|
isOpen: propIsOpen,
|
|
216
216
|
onOpenChange,
|
|
217
|
-
width = "auto"
|
|
217
|
+
width = "auto",
|
|
218
|
+
align = "start",
|
|
219
|
+
"aria-label": ariaLabel,
|
|
220
|
+
testID
|
|
218
221
|
}) => {
|
|
219
222
|
const [internalIsOpen, setInternalIsOpen] = useState(false);
|
|
220
223
|
const isOpen = propIsOpen !== void 0 ? propIsOpen : internalIsOpen;
|
|
221
224
|
const containerRef = useRef(null);
|
|
225
|
+
const triggerRef = useRef(null);
|
|
226
|
+
const menuRef = useRef(null);
|
|
222
227
|
const { theme } = useDesignSystem();
|
|
223
|
-
const
|
|
228
|
+
const closeMenu = useCallback(() => {
|
|
229
|
+
if (propIsOpen === void 0) {
|
|
230
|
+
setInternalIsOpen(false);
|
|
231
|
+
}
|
|
232
|
+
if (onOpenChange) onOpenChange(false);
|
|
233
|
+
}, [propIsOpen, onOpenChange]);
|
|
234
|
+
const toggleOpen = useCallback(() => {
|
|
224
235
|
const nextOpen = !isOpen;
|
|
225
236
|
if (propIsOpen === void 0) {
|
|
226
237
|
setInternalIsOpen(nextOpen);
|
|
227
238
|
}
|
|
228
239
|
if (onOpenChange) onOpenChange(nextOpen);
|
|
229
|
-
};
|
|
240
|
+
}, [isOpen, propIsOpen, onOpenChange]);
|
|
241
|
+
const handleKeyDown = useCallback(
|
|
242
|
+
(event) => {
|
|
243
|
+
if (event.key === "Escape" && isOpen) {
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
closeMenu();
|
|
246
|
+
triggerRef.current?.focus();
|
|
247
|
+
} else if (event.key === "Tab" && isOpen) {
|
|
248
|
+
closeMenu();
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
[isOpen, closeMenu]
|
|
252
|
+
);
|
|
253
|
+
const handleTriggerKeyDown = useCallback(
|
|
254
|
+
(event) => {
|
|
255
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
256
|
+
event.preventDefault();
|
|
257
|
+
toggleOpen();
|
|
258
|
+
} else if (event.key === "ArrowDown" && !isOpen) {
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
if (propIsOpen === void 0) {
|
|
261
|
+
setInternalIsOpen(true);
|
|
262
|
+
}
|
|
263
|
+
if (onOpenChange) onOpenChange(true);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
[isOpen, toggleOpen, propIsOpen, onOpenChange]
|
|
267
|
+
);
|
|
230
268
|
useEffect(() => {
|
|
231
269
|
const handleClickOutside = (event) => {
|
|
232
270
|
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
233
|
-
|
|
234
|
-
setInternalIsOpen(false);
|
|
235
|
-
}
|
|
236
|
-
if (onOpenChange) onOpenChange(false);
|
|
271
|
+
closeMenu();
|
|
237
272
|
}
|
|
238
273
|
};
|
|
239
|
-
if (isOpen) {
|
|
274
|
+
if (isOpen && typeof document !== "undefined") {
|
|
240
275
|
document.addEventListener("mousedown", handleClickOutside);
|
|
241
276
|
}
|
|
242
277
|
return () => {
|
|
243
|
-
document
|
|
278
|
+
if (typeof document !== "undefined") {
|
|
279
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
280
|
+
}
|
|
244
281
|
};
|
|
245
|
-
}, [isOpen,
|
|
282
|
+
}, [isOpen, closeMenu]);
|
|
246
283
|
return /* @__PURE__ */ jsxs(
|
|
247
284
|
"div",
|
|
248
285
|
{
|
|
249
286
|
ref: containerRef,
|
|
250
287
|
style: {
|
|
251
288
|
position: "relative",
|
|
252
|
-
width:
|
|
289
|
+
width: "fit-content",
|
|
253
290
|
alignSelf: "flex-start",
|
|
254
291
|
height: "fit-content"
|
|
255
292
|
},
|
|
293
|
+
onKeyDown: handleKeyDown,
|
|
294
|
+
"data-testid": testID,
|
|
256
295
|
children: [
|
|
257
|
-
/* @__PURE__ */ jsx3(
|
|
296
|
+
/* @__PURE__ */ jsx3(
|
|
297
|
+
"div",
|
|
298
|
+
{
|
|
299
|
+
ref: triggerRef,
|
|
300
|
+
onClick: toggleOpen,
|
|
301
|
+
onKeyDown: handleTriggerKeyDown,
|
|
302
|
+
role: "button",
|
|
303
|
+
tabIndex: 0,
|
|
304
|
+
"aria-haspopup": "menu",
|
|
305
|
+
"aria-expanded": isOpen,
|
|
306
|
+
style: { cursor: "pointer" },
|
|
307
|
+
children: trigger
|
|
308
|
+
}
|
|
309
|
+
),
|
|
258
310
|
isOpen && /* @__PURE__ */ jsx3(
|
|
259
311
|
Box,
|
|
260
312
|
{
|
|
313
|
+
ref: menuRef,
|
|
261
314
|
position: "absolute",
|
|
262
315
|
top: "100%",
|
|
263
|
-
left: 0,
|
|
316
|
+
...align === "end" ? { right: 0 } : { left: 0 },
|
|
264
317
|
marginTop: 4,
|
|
265
318
|
backgroundColor: theme.colors.background.secondary,
|
|
266
319
|
borderColor: theme.colors.border.secondary,
|
|
267
320
|
borderWidth: 1,
|
|
268
321
|
borderRadius: theme.radius.button,
|
|
269
322
|
paddingVertical: 4,
|
|
323
|
+
role: "menu",
|
|
324
|
+
"aria-label": ariaLabel,
|
|
270
325
|
style: {
|
|
271
326
|
zIndex: 1e3,
|
|
272
327
|
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
|
|
273
|
-
minWidth: "100%"
|
|
328
|
+
minWidth: width === "auto" ? "100%" : width,
|
|
329
|
+
width: width !== "auto" ? width : void 0
|
|
274
330
|
},
|
|
275
331
|
children
|
|
276
332
|
}
|
|
@@ -285,7 +341,8 @@ var DropdownItem = ({
|
|
|
285
341
|
active,
|
|
286
342
|
selected,
|
|
287
343
|
disabled,
|
|
288
|
-
icon
|
|
344
|
+
icon,
|
|
345
|
+
testID
|
|
289
346
|
}) => {
|
|
290
347
|
const { theme } = useDesignSystem();
|
|
291
348
|
const brandColors = theme.colors.control.brand.primary;
|
|
@@ -305,6 +362,12 @@ var DropdownItem = ({
|
|
|
305
362
|
}
|
|
306
363
|
return theme.colors.content.secondary;
|
|
307
364
|
};
|
|
365
|
+
const handleKeyDown = (event) => {
|
|
366
|
+
if ((event.key === "Enter" || event.key === " ") && !disabled && onPress) {
|
|
367
|
+
event.preventDefault();
|
|
368
|
+
onPress();
|
|
369
|
+
}
|
|
370
|
+
};
|
|
308
371
|
return /* @__PURE__ */ jsxs(
|
|
309
372
|
Box,
|
|
310
373
|
{
|
|
@@ -317,6 +380,11 @@ var DropdownItem = ({
|
|
|
317
380
|
hoverStyle: !disabled && !selected ? {
|
|
318
381
|
backgroundColor: theme.colors.control.input.bgHover
|
|
319
382
|
} : void 0,
|
|
383
|
+
role: "menuitem",
|
|
384
|
+
tabIndex: disabled ? -1 : 0,
|
|
385
|
+
"aria-disabled": disabled,
|
|
386
|
+
onKeyDown: handleKeyDown,
|
|
387
|
+
testID,
|
|
320
388
|
style: {
|
|
321
389
|
opacity: disabled ? 0.5 : 1,
|
|
322
390
|
cursor: disabled ? "not-allowed" : "pointer"
|
|
@@ -328,6 +396,8 @@ var DropdownItem = ({
|
|
|
328
396
|
}
|
|
329
397
|
);
|
|
330
398
|
};
|
|
399
|
+
Dropdown.displayName = "Dropdown";
|
|
400
|
+
DropdownItem.displayName = "DropdownItem";
|
|
331
401
|
export {
|
|
332
402
|
Dropdown,
|
|
333
403
|
DropdownItem
|
package/native/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Dropdown.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface DropdownProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n isOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n width?: string | number;\n}\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n trigger,\n children,\n isOpen: propIsOpen,\n onOpenChange,\n width = \"auto\",\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const containerRef = useRef<any>(null);\n const { theme } = useDesignSystem();\n\n const toggleOpen = () => {\n const nextOpen = !isOpen;\n if (propIsOpen === undefined) {\n setInternalIsOpen(nextOpen);\n }\n if (onOpenChange) onOpenChange(nextOpen);\n };\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target)\n ) {\n if (propIsOpen === undefined) {\n setInternalIsOpen(false);\n }\n if (onOpenChange) onOpenChange(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen, propIsOpen, onOpenChange]);\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: width === \"auto\" ? \"fit-content\" : width,\n alignSelf: \"flex-start\",\n height: \"fit-content\",\n }}\n >\n <div onClick={toggleOpen} style={{ cursor: \"pointer\" }}>\n {trigger}\n </div>\n {isOpen && (\n <Box\n position=\"absolute\"\n top=\"100%\"\n left={0}\n marginTop={4}\n backgroundColor={theme.colors.background.secondary}\n borderColor={theme.colors.border.secondary}\n borderWidth={1}\n borderRadius={theme.radius.button}\n paddingVertical={4}\n style={{\n zIndex: 1000,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.1)\",\n minWidth: \"100%\",\n }}\n >\n {children}\n </Box>\n )}\n </div>\n );\n};\n\nexport interface DropdownItemProps {\n children: React.ReactNode;\n onPress?: () => void;\n active?: boolean;\n /** Whether this item is selected (shows trailing checkmark with control/check/bg color) */\n selected?: boolean;\n disabled?: boolean;\n icon?: React.ReactNode;\n}\n\nexport const DropdownItem: React.FC<DropdownItemProps> = ({\n children,\n onPress,\n active,\n selected,\n disabled,\n icon,\n}) => {\n const { theme } = useDesignSystem();\n const brandColors = theme.colors.control.brand.primary;\n const contentColors = theme.colors.content;\n\n // Determine background color\n const getBackgroundColor = () => {\n if (selected) {\n return brandColors?.bg || theme.colors.control.input.bg; // Cyan background for selected items\n }\n if (active) {\n return theme.colors.control.input.bgHover;\n }\n return \"transparent\";\n };\n\n // Determine text/icon color\n const getContentColor = () => {\n if (selected) {\n return contentColors?.on?.brand || theme.colors.content.primary; // Black text on cyan background\n }\n return theme.colors.content.secondary;\n };\n\n return (\n <Box\n onPress={!disabled ? onPress : undefined}\n paddingHorizontal={16}\n paddingVertical={8}\n flexDirection=\"row\"\n alignItems=\"center\"\n backgroundColor={getBackgroundColor()}\n hoverStyle={\n !disabled && !selected\n ? {\n backgroundColor: theme.colors.control.input.bgHover,\n }\n : undefined\n }\n style={{\n opacity: disabled ? 0.5 : 1,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n }}\n >\n {icon && (\n <Box marginRight={12} alignItems=\"center\" justifyContent=\"center\">\n {icon}\n </Box>\n )}\n <Box flex={1}>\n <Text color={getContentColor()} fontSize={14} fontWeight=\"400\">\n {children}\n </Text>\n </Box>\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 flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, it's better to use the system font\n // to avoid rendering issues or missing text.\n if (resolvedFontFamily === \"Pilat Wide Bold\") {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n"],"mappings":"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","names":["jsx","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Dropdown.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface DropdownProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n isOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Width of the dropdown menu (does not affect trigger width) */\n width?: string | number;\n /** Horizontal alignment of dropdown menu relative to trigger. Default: \"start\" */\n align?: \"start\" | \"end\";\n /** Accessible label for the dropdown menu */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n trigger,\n children,\n isOpen: propIsOpen,\n onOpenChange,\n width = \"auto\",\n align = \"start\",\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const containerRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const { theme } = useDesignSystem();\n\n const closeMenu = useCallback(() => {\n if (propIsOpen === undefined) {\n setInternalIsOpen(false);\n }\n if (onOpenChange) onOpenChange(false);\n }, [propIsOpen, onOpenChange]);\n\n const toggleOpen = useCallback(() => {\n const nextOpen = !isOpen;\n if (propIsOpen === undefined) {\n setInternalIsOpen(nextOpen);\n }\n if (onOpenChange) onOpenChange(nextOpen);\n }, [isOpen, propIsOpen, onOpenChange]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Escape\" && isOpen) {\n event.preventDefault();\n closeMenu();\n triggerRef.current?.focus();\n } else if (event.key === \"Tab\" && isOpen) {\n closeMenu();\n }\n },\n [isOpen, closeMenu]\n );\n\n // Handle trigger keyboard events\n const handleTriggerKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleOpen();\n } else if (event.key === \"ArrowDown\" && !isOpen) {\n event.preventDefault();\n if (propIsOpen === undefined) {\n setInternalIsOpen(true);\n }\n if (onOpenChange) onOpenChange(true);\n }\n },\n [isOpen, toggleOpen, propIsOpen, onOpenChange]\n );\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n closeMenu();\n }\n };\n\n if (isOpen && typeof document !== \"undefined\") {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return () => {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }\n };\n }, [isOpen, closeMenu]);\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: \"fit-content\",\n alignSelf: \"flex-start\",\n height: \"fit-content\",\n }}\n onKeyDown={handleKeyDown}\n data-testid={testID}\n >\n <div\n ref={triggerRef}\n onClick={toggleOpen}\n onKeyDown={handleTriggerKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n style={{ cursor: \"pointer\" }}\n >\n {trigger}\n </div>\n {isOpen && (\n <Box\n ref={menuRef}\n position=\"absolute\"\n top=\"100%\"\n {...(align === \"end\" ? { right: 0 } : { left: 0 })}\n marginTop={4}\n backgroundColor={theme.colors.background.secondary}\n borderColor={theme.colors.border.secondary}\n borderWidth={1}\n borderRadius={theme.radius.button}\n paddingVertical={4}\n role=\"menu\"\n aria-label={ariaLabel}\n style={{\n zIndex: 1000,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.1)\",\n minWidth: width === \"auto\" ? \"100%\" : width,\n width: width !== \"auto\" ? width : undefined,\n }}\n >\n {children}\n </Box>\n )}\n </div>\n );\n};\n\nexport interface DropdownItemProps {\n children: React.ReactNode;\n onPress?: () => void;\n active?: boolean;\n /** Whether this item is selected (shows trailing checkmark with control/check/bg color) */\n selected?: boolean;\n disabled?: boolean;\n icon?: React.ReactNode;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const DropdownItem: React.FC<DropdownItemProps> = ({\n children,\n onPress,\n active,\n selected,\n disabled,\n icon,\n testID,\n}) => {\n const { theme } = useDesignSystem();\n const brandColors = theme.colors.control.brand.primary;\n const contentColors = theme.colors.content;\n\n // Determine background color\n const getBackgroundColor = () => {\n if (selected) {\n return brandColors?.bg || theme.colors.control.input.bg; // Cyan background for selected items\n }\n if (active) {\n return theme.colors.control.input.bgHover;\n }\n return \"transparent\";\n };\n\n // Determine text/icon color\n const getContentColor = () => {\n if (selected) {\n return contentColors?.on?.brand || theme.colors.content.primary; // Black text on cyan background\n }\n return theme.colors.content.secondary;\n };\n\n // Handle keyboard activation\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if ((event.key === \"Enter\" || event.key === \" \") && !disabled && onPress) {\n event.preventDefault();\n onPress();\n }\n };\n\n return (\n <Box\n onPress={!disabled ? onPress : undefined}\n paddingHorizontal={16}\n paddingVertical={8}\n flexDirection=\"row\"\n alignItems=\"center\"\n backgroundColor={getBackgroundColor()}\n hoverStyle={\n !disabled && !selected\n ? {\n backgroundColor: theme.colors.control.input.bgHover,\n }\n : undefined\n }\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n onKeyDown={handleKeyDown}\n testID={testID}\n style={{\n opacity: disabled ? 0.5 : 1,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n }}\n >\n {icon && (\n <Box marginRight={12} alignItems=\"center\" justifyContent=\"center\">\n {icon}\n </Box>\n )}\n <Box flex={1}>\n <Text color={getContentColor()} fontSize={14} fontWeight=\"400\">\n {children}\n </Text>\n </Box>\n </Box>\n );\n};\n\nDropdown.displayName = \"Dropdown\";\nDropdownItem.displayName = \"DropdownItem\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, it's better to use the system font\n // to avoid rendering issues or missing text.\n if (resolvedFontFamily === \"Pilat Wide Bold\") {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n"],"mappings":"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","names":["jsx","jsx"]}
|
package/package.json
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-dropdown",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.92.0-pr146.1771218879",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "yarn build:web && yarn build:native",
|
|
9
9
|
"build:web": "PLATFORM=web tsup",
|
|
10
|
-
"build:native": "PLATFORM=native tsup"
|
|
10
|
+
"build:native": "PLATFORM=native tsup",
|
|
11
|
+
"test": "vitest",
|
|
12
|
+
"test:run": "vitest run",
|
|
13
|
+
"test:coverage": "vitest run --coverage"
|
|
11
14
|
},
|
|
12
15
|
"dependencies": {
|
|
13
|
-
"@xsolla/xui-button": "0.
|
|
14
|
-
"@xsolla/xui-core": "0.
|
|
15
|
-
"@xsolla/xui-divider": "0.
|
|
16
|
-
"@xsolla/xui-icons": "0.
|
|
17
|
-
"@xsolla/xui-primitives-core": "0.
|
|
16
|
+
"@xsolla/xui-button": "0.92.0-pr146.1771218879",
|
|
17
|
+
"@xsolla/xui-core": "0.92.0-pr146.1771218879",
|
|
18
|
+
"@xsolla/xui-divider": "0.92.0-pr146.1771218879",
|
|
19
|
+
"@xsolla/xui-icons": "0.92.0-pr146.1771218879",
|
|
20
|
+
"@xsolla/xui-primitives-core": "0.92.0-pr146.1771218879"
|
|
18
21
|
},
|
|
19
22
|
"peerDependencies": {
|
|
20
23
|
"react": ">=16.8.0",
|