@xsolla/xui-button 0.128.0 → 0.130.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/Button.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Spinner.tsx","../../../primitives-native/src/Icon.tsx","../../src/IconButton.tsx","../../src/FlexButton.tsx","../../src/AppButton.tsx","../../src/ButtonGroup.tsx"],"sourcesContent":["export * from \"./Button\";\nexport * from \"./IconButton\";\nexport * from \"./FlexButton\";\nexport * from \"./AppButton\";\nexport * from \"./ButtonGroup\";\n","import React, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Spinner } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\n// Local type definitions for button styling\ninterface ControlVariantStyles {\n bg: string;\n bgHover: string;\n bgPress: string;\n bgDisable?: string;\n border: string;\n borderHover: string;\n borderPress: string;\n borderDisable?: string;\n}\n\ninterface ControlTextStyles {\n primary: string;\n secondary: string;\n tertiary: string;\n ghost: string;\n disable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n sublabelFontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n labelIconSize: number;\n labelIconGap: number;\n}\n\n/**\n * Helper to clone an icon element with default props.\n * Only applies size/color if not already specified by the user.\n * This allows users to override the default size: <ArrowRight size={16} />\n */\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps, // Preserve existing props (including accessibility attributes)\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface ButtonProps {\n /** Visual variant of the button */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\";\n /** Color tone of the button */\n tone?: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Button content */\n children: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /**\n * Icon to display on the left side.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `iconLeft={<ArrowLeft size={16} />}`\n */\n iconLeft?: React.ReactNode;\n /**\n * Icon to display on the right side.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `iconRight={<ArrowRight size={16} />}`\n */\n iconRight?: React.ReactNode;\n /** Secondary text displayed inline with the main label (e.g., price), shown with 40% opacity */\n sublabel?: string;\n /** Alignment of the label text */\n labelAlignment?: \"left\" | \"center\";\n /**\n * Small icon displayed directly next to the label text.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `labelIcon={<InfoIcon size={12} />}`\n */\n labelIcon?: React.ReactNode;\n /** Custom content slot for badges, tags, or other elements */\n customContent?: React.ReactNode;\n /** Accessible label for screen readers (use for icon-only buttons) */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Whether the button should stretch to fill the full width of its container */\n fullWidth?: boolean;\n}\n\n/**\n * Button - An accessible button component\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n * Supports various visual variants, sizes, and states including loading.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n *\n */\nexport const Button: React.FC<ButtonProps> = ({\n variant = \"primary\",\n tone = \"brand\",\n size = \"md\",\n disabled = false,\n loading = false,\n children,\n onPress,\n iconLeft,\n iconRight,\n sublabel,\n labelAlignment = \"center\",\n labelIcon,\n customContent,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n fullWidth = false,\n}) => {\n const { theme } = useDesignSystem();\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n // Resolve Config from Theme - type assertion for extended sizing properties\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n // Type assertion for control variant styles - the JSON tokens include tertiary\n const controlTone = theme?.colors?.control?.[tone] as unknown as\n | (Record<string, ControlVariantStyles> & { text: ControlTextStyles })\n | undefined;\n\n const variantStyles: ControlVariantStyles = controlTone?.[variant] ||\n (\n theme?.colors?.control?.brand as unknown as Record<\n string,\n ControlVariantStyles\n >\n )?.primary || {\n bg: \"transparent\",\n bgHover: \"transparent\",\n bgPress: \"transparent\",\n bgDisable: \"transparent\",\n border: \"transparent\",\n borderHover: \"transparent\",\n borderPress: \"transparent\",\n borderDisable: \"transparent\",\n };\n\n // Text colors are at the tone level, mapped by variant name\n const textStyles: ControlTextStyles = controlTone?.text ||\n (theme?.colors?.control?.brand as unknown as { text: ControlTextStyles })\n ?.text || {\n primary: \"#000\",\n secondary: \"#fff\",\n tertiary: \"#888\",\n ghost: \"#000\",\n disable: \"#666\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Determine background color based on state\n let backgroundColor = variantStyles.bg;\n if (disabled) {\n backgroundColor = variantStyles.bgDisable || variantStyles.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = variantStyles.bgPress || variantStyles.bg;\n }\n\n const borderColor = disabled\n ? variantStyles.borderDisable || variantStyles.border\n : variantStyles.border;\n\n // Text color is determined by variant, with disable color for disabled state\n const textColor = disabled ? textStyles.disable : textStyles[variant];\n\n // Only use aria-label when explicitly provided\n // Text content provides accessible name naturally for buttons with visible text\n const computedAriaLabel = ariaLabel;\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={computedAriaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\"\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={fullWidth ? \"100%\" : undefined}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles?.bgHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles?.bgPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {/* Loading Spinner - Absolutely positioned in center */}\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {/* Left Icon Section - Square container matching button height */}\n {iconLeft && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconLeft, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n\n {/* Center Section: Content Area */}\n <Box\n flex={fullWidth ? 1 : undefined}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent={labelAlignment === \"left\" ? \"flex-start\" : \"center\"}\n paddingHorizontal={sizeStyles.padding}\n height=\"100%\"\n gap={sizeStyles.labelIconGap}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n aria-hidden={loading ? true : undefined}\n >\n {/* Label Icon (left of text) */}\n {labelIcon && (\n <Box aria-hidden={true}>\n {cloneIconWithDefaults(\n labelIcon,\n sizeStyles.labelIconSize,\n textColor\n )}\n </Box>\n )}\n\n {/* Label */}\n <Text color={textColor} fontSize={sizeStyles.fontSize} fontWeight=\"500\">\n {children}\n </Text>\n\n {/* Sublabel - inline with label, 40% opacity as per Figma */}\n {sublabel && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"500\"\n style={{ opacity: 0.4 }}\n >\n {sublabel}\n </Text>\n )}\n\n {/* Custom Content Slot */}\n {customContent && <Box aria-hidden={true}>{customContent}</Box>}\n </Box>\n\n {/* Right Icon Section - Square container matching button height */}\n {iconRight && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconRight, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n </Box>\n );\n};\n\nButton.displayName = \"Button\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport {\n Text as RNText,\n TextStyle,\n AccessibilityRole,\n StyleSheet,\n} from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nconst parseNumericValue = (\n value: string | number | undefined\n): number | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = parseFloat(value);\n return isNaN(parsed) ? undefined : parsed;\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n textAlign,\n lineHeight,\n numberOfLines,\n id,\n role,\n style: styleProp,\n ...props\n}) => {\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const incomingStyle = StyleSheet.flatten(styleProp) as TextStyle | undefined;\n\n const baseStyle: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n textAlign: textAlign ?? incomingStyle?.textAlign,\n lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),\n marginTop: parseNumericValue(\n incomingStyle?.marginTop as number | string | undefined\n ),\n marginBottom: parseNumericValue(\n incomingStyle?.marginBottom as number | string | undefined\n ),\n };\n\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText\n style={baseStyle}\n numberOfLines={numberOfLines}\n testID={id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import type React from \"react\";\nimport { ActivityIndicator, View } from \"react-native\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n color,\n size,\n role,\n \"aria-label\": ariaLabel,\n \"aria-live\": ariaLive,\n testID,\n}) => {\n return (\n <View\n accessible={true}\n accessibilityRole={role === \"status\" ? \"none\" : undefined}\n accessibilityLabel={ariaLabel}\n accessibilityLiveRegion={\n ariaLive === \"polite\"\n ? \"polite\"\n : ariaLive === \"assertive\"\n ? \"assertive\"\n : \"none\"\n }\n testID={testID}\n >\n <ActivityIndicator\n color={color}\n size={typeof size === \"number\" ? size : \"small\"}\n />\n </View>\n );\n};\n\nSpinner.displayName = \"Spinner\";\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, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Spinner } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\n// Local type definitions for button styling\ninterface ControlVariantStyles {\n bg: string;\n bgHover: string;\n bgPress: string;\n bgDisable?: string;\n border: string;\n borderHover: string;\n borderPress: string;\n borderDisable?: string;\n}\n\ninterface ControlTextStyles {\n primary: string;\n secondary: string;\n tertiary: string;\n ghost: string;\n disable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n}\n\n/**\n * Helper to clone an icon element with default props.\n * Only applies size/color if not already specified by the user.\n * This allows users to override the default size: <ArrowRight size={16} />\n */\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps, // Preserve existing props (including accessibility attributes)\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface IconButtonProps {\n /** Visual variant of the button */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\";\n /** Color tone of the button */\n tone?: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /**\n * Icon to display in the button (required).\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `icon={<CloseIcon size={16} />}`\n */\n icon: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /**\n * Accessible label for screen readers (REQUIRED for icon-only buttons)\n * Since icon buttons have no visible text, this label is essential for accessibility.\n * @example aria-label=\"Close dialog\"\n * @example aria-label=\"Open settings menu\"\n */\n \"aria-label\": string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n}\n\n/**\n * IconButton - An accessible icon-only button component\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n * Supports various visual variants, sizes, and states including loading.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Required aria-label**: Ensures screen readers can announce the button's purpose\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n *\n * ## Usage\n *\n * ```tsx\n * // Basic usage - aria-label is required\n * <IconButton icon={<CloseIcon />} aria-label=\"Close dialog\" onPress={handleClose} />\n *\n * // Toggle button\n * <IconButton\n * icon={<MenuIcon />}\n * aria-label=\"Toggle menu\"\n * aria-expanded={isOpen}\n * aria-controls=\"menu-id\"\n * onPress={toggleMenu}\n * />\n *\n * // Loading state\n * <IconButton icon={<SaveIcon />} aria-label=\"Save changes\" loading />\n * ```\n */\nexport const IconButton: React.FC<IconButtonProps> = ({\n variant = \"primary\",\n tone = \"brand\",\n size = \"md\",\n disabled = false,\n loading = false,\n icon,\n onPress,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n}) => {\n const { theme } = useDesignSystem();\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n // Type assertion for extended sizing properties\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n // Type assertion for control variant styles - the JSON tokens include tertiary\n const controlTone = theme?.colors?.control?.[tone] as unknown as\n | (Record<string, ControlVariantStyles> & { text: ControlTextStyles })\n | undefined;\n\n const variantStyles: ControlVariantStyles = controlTone?.[variant] ||\n (\n theme?.colors?.control?.brand as unknown as Record<\n string,\n ControlVariantStyles\n >\n )?.primary || {\n bg: \"transparent\",\n bgHover: \"transparent\",\n bgPress: \"transparent\",\n bgDisable: \"transparent\",\n border: \"transparent\",\n borderHover: \"transparent\",\n borderPress: \"transparent\",\n borderDisable: \"transparent\",\n };\n\n // Text colors are at the tone level, mapped by variant name\n const textStyles: ControlTextStyles = controlTone?.text ||\n (theme?.colors?.control?.brand as unknown as { text: ControlTextStyles })\n ?.text || {\n primary: \"#000\",\n secondary: \"#fff\",\n tertiary: \"#888\",\n ghost: \"#000\",\n disable: \"#666\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Determine background color based on state\n let backgroundColor = variantStyles.bg;\n if (disabled) {\n backgroundColor = variantStyles.bgDisable || variantStyles.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = variantStyles.bgPress || variantStyles.bg;\n }\n\n const borderColor = disabled\n ? variantStyles.borderDisable || variantStyles.border\n : variantStyles.border;\n\n // Text color is determined by variant, with disable color for disabled state\n const textColor = disabled ? textStyles.disable : textStyles[variant];\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\"\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={sizeStyles.height}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles.bgHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles.bgPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {/* Loading Spinner - Absolutely positioned in center */}\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {/* Icon - Hidden when loading but maintains layout */}\n <Box\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(icon, sizeStyles.iconSize, textColor)}\n </Box>\n </Box>\n );\n};\n\nIconButton.displayName = \"IconButton\";\n","import React, {\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Spinner, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface FlexButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\"\n> {\n /** Button content */\n children: ReactNode;\n /** Visual variant of the button */\n variant?:\n | \"brand\"\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"brandExtra\"\n | \"inverse\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether to show background fill */\n background?: boolean;\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Icon to display on the left side */\n iconLeft?: ReactNode;\n /** Icon to display on the right side */\n iconRight?: ReactNode;\n /** Click handler */\n onPress?: () => void;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Accessible label for screen readers */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\ntype ButtonState = \"default\" | \"hover\" | \"press\";\n\nconst ICON_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nconst SPINNER_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nconst LINE_HEIGHTS: Record<NonNullable<FlexButtonProps[\"size\"]>, string> = {\n xs: \"14px\",\n sm: \"16px\",\n md: \"18px\",\n lg: \"20px\",\n xl: \"22px\",\n};\n\nconst FONT_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 14,\n lg: 16,\n xl: 18,\n};\n\nconst BORDER_RADIUS: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xl: 4,\n lg: 4,\n md: 2,\n sm: 2,\n xs: 2,\n};\n\n/**\n * FlexButton - A compact button component designed for use in modals and popups.\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n */\nexport const FlexButton: React.FC<FlexButtonProps> = ({\n children,\n variant = \"brand\",\n size = \"md\",\n background = false,\n disabled = false,\n loading = false,\n iconLeft,\n iconRight,\n onPress,\n onClick,\n className,\n type = \"button\",\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n tabIndex = 0,\n ...buttonProps\n}) => {\n const { theme } = useDesignSystem();\n const [state, setState] = useState<ButtonState>(\"default\");\n const [isFocused, setIsFocused] = useState(false);\n const isMouseOverRef = useRef(false);\n\n const isDisabled = disabled || loading;\n\n const getVariantColors = (\n currentState: ButtonState\n ): { bg: string; text: string; border?: string } => {\n if (isDisabled) {\n return {\n bg: background ? theme.colors.overlay.mono : \"transparent\",\n text: theme.colors.control.text.disable,\n border: undefined,\n };\n }\n\n const effectiveBackground = loading ? false : background;\n\n switch (variant) {\n case \"brand\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.brand.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.brand.primary.bgHover\n : theme.colors.background.brand.primary,\n text: theme.colors.content.on.brand,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.background.brand.primary\n : currentState === \"hover\"\n ? theme.colors.overlay.brand\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.on.brand\n : theme.colors.content.brand.primary,\n border: undefined,\n };\n\n case \"primary\":\n if (effectiveBackground) {\n return {\n bg: theme.colors.background.primary,\n text: theme.colors.content.primary,\n border:\n currentState === \"press\"\n ? theme.colors.border.primary\n : undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text: theme.colors.content.primary,\n border:\n currentState === \"press\" ? theme.colors.border.primary : undefined,\n };\n\n case \"secondary\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.secondary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.secondary.bgHover\n : theme.colors.background.secondary,\n text: theme.colors.content.secondary,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.primary\n : currentState === \"hover\"\n ? theme.colors.content.secondary\n : theme.colors.content.secondary,\n border: undefined,\n };\n\n case \"tertiary\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.secondary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.secondary.bgHover\n : theme.colors.background.secondary,\n text: theme.colors.content.tertiary,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.secondary\n : currentState === \"hover\"\n ? theme.colors.content.tertiary\n : theme.colors.content.tertiary,\n border: undefined,\n };\n\n case \"brandExtra\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.brandExtra.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.brandExtra.primary.bgHover\n : theme.colors.background.brandExtra.primary,\n text: theme.colors.content.on.brandExtra,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.background.brandExtra.primary\n : currentState === \"hover\"\n ? theme.colors.overlay.brandExtra\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.on.brandExtra\n : theme.colors.content.brandExtra.secondary,\n border: undefined,\n };\n\n case \"inverse\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.primary.bgHover\n : theme.colors.background.inverse,\n text: theme.colors.content.inverse,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text: theme.colors.content.inverse,\n border: undefined,\n };\n\n default:\n return {\n bg: \"transparent\",\n text: theme.colors.content.primary,\n border: undefined,\n };\n }\n };\n\n const getFocusRingColor = (): string => {\n switch (variant) {\n case \"brand\":\n return theme.colors.overlay.brand;\n case \"brandExtra\":\n return theme.colors.overlay.brandExtra;\n case \"inverse\":\n return \"rgba(255, 255, 255, 0.3)\";\n default:\n return theme.colors.overlay.mono;\n }\n };\n\n const getSpinnerColor = (): string => {\n switch (variant) {\n case \"brand\":\n return theme.colors.content.brand.primary;\n case \"primary\":\n return theme.colors.content.primary;\n case \"secondary\":\n return theme.colors.content.secondary;\n case \"tertiary\":\n return theme.colors.content.tertiary;\n case \"brandExtra\":\n return theme.colors.content.brandExtra.secondary;\n case \"inverse\":\n return theme.colors.content.inverse;\n default:\n return theme.colors.content.brand.primary;\n }\n };\n\n const colors = getVariantColors(state);\n const focusRingColor = getFocusRingColor();\n const spinnerColor = getSpinnerColor();\n const iconSize = ICON_SIZES[size];\n const spinnerSize = SPINNER_SIZES[size];\n const fontSize = FONT_SIZES[size];\n const borderRadius = BORDER_RADIUS[size];\n const lineHeight = LINE_HEIGHTS[size];\n\n const handleMouseEnter = () => {\n if (!isDisabled) {\n isMouseOverRef.current = true;\n setState(\"hover\");\n }\n };\n\n const handleMouseLeave = () => {\n if (!isDisabled) {\n isMouseOverRef.current = false;\n setState(\"default\");\n }\n };\n\n const handleMouseDown = () => {\n if (!isDisabled) {\n setState(\"press\");\n }\n };\n\n const handleMouseUp = () => {\n if (!isDisabled) {\n setState(isMouseOverRef.current ? \"hover\" : \"default\");\n }\n };\n\n const handleFocus = () => {\n if (!isDisabled) {\n setIsFocused(true);\n }\n };\n\n const handleBlur = () => {\n setIsFocused(false);\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (onPress) {\n onPress();\n }\n if (onClick) {\n onClick(event);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n setState(\"press\");\n }\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n setState(isMouseOverRef.current ? \"hover\" : \"default\");\n if (onPress) {\n onPress();\n }\n }\n };\n\n const borderShadow = colors.border\n ? `inset 0 0 0 1px ${colors.border}`\n : undefined;\n const focusShadow =\n isFocused && !isDisabled ? `0 0 0 2px ${focusRingColor}` : undefined;\n\n const boxShadows: string[] = [];\n if (borderShadow) boxShadows.push(borderShadow);\n if (focusShadow) boxShadows.push(focusShadow);\n const combinedBoxShadow =\n boxShadows.length > 0 ? boxShadows.join(\", \") : \"none\";\n\n const buttonStyle: CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"2px\",\n padding: \"4px\",\n backgroundColor: loading ? \"transparent\" : colors.bg,\n color: colors.text,\n border: \"none\",\n borderWidth: \"0px\",\n borderRadius: `${borderRadius}px`,\n cursor: isDisabled ? \"not-allowed\" : \"pointer\",\n fontSize: `${fontSize}px`,\n fontWeight: 500,\n lineHeight: lineHeight,\n fontFamily: \"inherit\",\n transition:\n \"background-color 100ms ease-in-out, color 100ms ease-in-out, box-shadow 100ms ease-in-out\",\n outline: \"none\",\n boxShadow: combinedBoxShadow,\n opacity: isDisabled && !loading ? 0.6 : 1,\n };\n\n const contentStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"2px\",\n };\n\n const spinnerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"transparent\",\n height: lineHeight,\n };\n\n const computedAriaLabel =\n ariaLabel || (typeof children === \"string\" ? children : undefined);\n\n return (\n <button\n {...buttonProps}\n type={type}\n className={className}\n disabled={isDisabled}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onFocus={handleFocus}\n onBlur={handleBlur}\n aria-label={computedAriaLabel}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n tabIndex={tabIndex}\n style={buttonStyle}\n data-testid={testID || \"flex-button\"}\n >\n <span style={contentStyle}>\n {loading ? (\n <span style={spinnerStyle}>\n <Spinner size={spinnerSize} color={spinnerColor} />\n </span>\n ) : (\n <>\n {iconLeft && (\n <Icon size={iconSize} color={colors.text}>\n {iconLeft}\n </Icon>\n )}\n <span>{children}</span>\n {iconRight && (\n <Icon size={iconSize} color={colors.text}>\n {iconRight}\n </Icon>\n )}\n </>\n )}\n </span>\n </button>\n );\n};\n\nFlexButton.displayName = \"FlexButton\";\n","import React, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Spinner } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\ninterface AppButtonTokens {\n bg: string;\n bgHover: string;\n bgPress: string;\n border: string;\n borderHover: string;\n borderPress: string;\n text: string;\n textDisable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n sublabelFontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n labelIconSize: number;\n labelIconGap: number;\n}\n\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps,\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface AppButtonProps {\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Button content */\n children: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /** Icon to display on the left side */\n iconLeft?: React.ReactNode;\n /** Icon to display on the right side */\n iconRight?: React.ReactNode;\n /** Secondary text displayed inline with the main label */\n sublabel?: string;\n /** Alignment of the label text */\n labelAlignment?: \"left\" | \"center\";\n /** Small icon displayed directly next to the label text */\n labelIcon?: React.ReactNode;\n /** Custom content slot for badges, tags, or other elements */\n customContent?: React.ReactNode;\n /** Accessible label for screen readers */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Whether the button should stretch to fill the full width of its container */\n fullWidth?: boolean;\n}\n\n/**\n * AppButton - A prominent filled button for app-level actions.\n *\n * Uses the `control.appButton` theme tokens for styling.\n * Supports all the same layout features as Button (icons, sublabels, etc.).\n */\nexport const AppButton: React.FC<AppButtonProps> = ({\n size = \"md\",\n disabled = false,\n loading = false,\n children,\n onPress,\n iconLeft,\n iconRight,\n sublabel,\n labelAlignment = \"center\",\n labelIcon,\n customContent,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n fullWidth = false,\n}) => {\n const { theme } = useDesignSystem();\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n const tokens: AppButtonTokens = (theme?.colors?.control as any)\n ?.appButton || {\n bg: \"#34474b\",\n bgHover: \"#3d5256\",\n bgPress: \"#2b3b3e\",\n border: \"rgba(255, 255, 255, 0.12)\",\n borderHover: \"rgba(255, 255, 255, 0.18)\",\n borderPress: \"rgba(255, 255, 255, 0.12)\",\n text: \"#b7c5c8\",\n textDisable: \"#b3b3b3\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n let backgroundColor = tokens.bg;\n if (disabled) {\n backgroundColor = tokens.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = tokens.bgPress;\n }\n\n const borderColor = tokens.border;\n const textColor = disabled ? tokens.textDisable : tokens.text;\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\" &&\n borderColor !== \"rgba(0, 0, 0, 0)\" &&\n !borderColor.endsWith(\", 0)\")\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={fullWidth ? \"100%\" : undefined}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: tokens.bgHover,\n borderColor: tokens.borderHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: tokens.bgPress,\n borderColor: tokens.borderPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {iconLeft && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconLeft, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n\n <Box\n flex={fullWidth ? 1 : undefined}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent={labelAlignment === \"left\" ? \"flex-start\" : \"center\"}\n paddingHorizontal={sizeStyles.padding}\n height=\"100%\"\n gap={sizeStyles.labelIconGap}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n aria-hidden={loading ? true : undefined}\n >\n {labelIcon && (\n <Box aria-hidden={true}>\n {cloneIconWithDefaults(\n labelIcon,\n sizeStyles.labelIconSize,\n textColor\n )}\n </Box>\n )}\n\n <Text color={textColor} fontSize={sizeStyles.fontSize} fontWeight=\"500\">\n {children}\n </Text>\n\n {sublabel && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"500\"\n style={{ opacity: 0.4 }}\n >\n {sublabel}\n </Text>\n )}\n\n {customContent && <Box aria-hidden={true}>{customContent}</Box>}\n </Box>\n\n {iconRight && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconRight, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n </Box>\n );\n};\n\nAppButton.displayName = \"AppButton\";\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\n\nexport interface ButtonGroupProps {\n /**\n * Layout orientation of the buttons\n * @default 'horizontal'\n */\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Size of the button group, determines default gap between buttons\n * @default 'md'\n */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /**\n * Buttons to be grouped\n */\n children: React.ReactNode;\n /**\n * Optional description text below the buttons\n */\n description?: string;\n /**\n * Optional error message text below the buttons\n */\n error?: string;\n /**\n * Custom gap between buttons (in pixels). If not provided, uses size and orientation based default.\n */\n gap?: number;\n /**\n * Accessible label for the button group\n */\n \"aria-label\"?: string;\n /**\n * ID of element that labels this button group\n */\n \"aria-labelledby\"?: string;\n /**\n * ID of element that describes this button group\n */\n \"aria-describedby\"?: string;\n /**\n * HTML id attribute\n */\n id?: string;\n /**\n * Test ID for testing frameworks\n */\n testID?: string;\n}\n\n/**\n * ButtonGroup - A container for grouping related buttons\n *\n * Provides semantic grouping for related actions with proper accessibility support.\n *\n * ## Accessibility Features\n *\n * - **Semantic Grouping**: Uses `role=\"group\"` to indicate related buttons\n * - **Accessible Name**: Supports `aria-label` or `aria-labelledby` to describe the group's purpose\n * - **Error Announcements**: Errors are announced to screen readers via `aria-live`\n * - **Description Support**: Optional description text for additional context\n *\n */\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({\n orientation = \"horizontal\",\n size = \"md\",\n children,\n description,\n error,\n gap,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n testID,\n}) => {\n const { theme } = useDesignSystem();\n\n // Flatten children to handle fragments and get actual button elements\n const flattenChildren = (children: React.ReactNode): React.ReactNode[] => {\n const result: React.ReactNode[] = [];\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === React.Fragment) {\n result.push(...flattenChildren(child.props.children));\n } else if (child !== null && child !== undefined) {\n result.push(child);\n }\n });\n return result;\n };\n\n const flatChildren = flattenChildren(children);\n const childCount = flatChildren.length;\n\n // Check if we need space-between layout (horizontal with more than 2 buttons)\n const useSpaceBetween = orientation === \"horizontal\" && childCount > 2;\n\n // Size-based default gaps by orientation\n const verticalGapMap = {\n xl: 16,\n lg: 16,\n md: 12,\n sm: 8,\n xs: 4,\n };\n\n const horizontalGapMap = {\n xl: 16,\n lg: 16,\n md: 16,\n sm: 12,\n xs: 12,\n };\n\n // Use provided gap or fall back to orientation and size based default\n const computedGap =\n gap ??\n (orientation === \"vertical\"\n ? verticalGapMap[size]\n : horizontalGapMap[size]);\n\n // Generate IDs for description and error elements\n const descriptionId = id ? `${id}-description` : undefined;\n const errorId = id ? `${id}-error` : undefined;\n\n // Build aria-describedby value combining external and internal references\n const computedAriaDescribedBy =\n [\n ariaDescribedBy,\n error && errorId ? errorId : undefined,\n description && descriptionId ? descriptionId : undefined,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n // Apply fullWidth to children in vertical orientation for proper alignment\n const processChildren = (childrenToProcess: React.ReactNode[]) => {\n if (orientation === \"vertical\") {\n return childrenToProcess.map((child, index) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n ...child.props,\n fullWidth: true,\n key: child.key ?? index,\n });\n }\n return child;\n });\n }\n return childrenToProcess;\n };\n\n // Split children for space-between layout\n const renderChildren = () => {\n const processedChildren = processChildren(flatChildren);\n\n if (useSpaceBetween) {\n const firstChild = processedChildren[0];\n const restChildren = processedChildren.slice(1);\n\n return (\n <>\n {firstChild}\n <Box flexDirection=\"row\" gap={computedGap}>\n {restChildren}\n </Box>\n </>\n );\n }\n\n // For non-space-between layout, return processed children or original\n if (orientation === \"vertical\") {\n return processedChildren;\n }\n return children;\n };\n\n return (\n <Box flexDirection=\"column\" width=\"100%\" gap={8}>\n <Box\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={computedAriaDescribedBy}\n id={id}\n testID={testID}\n flexDirection={orientation === \"horizontal\" ? \"row\" : \"column\"}\n alignItems=\"stretch\"\n gap={computedGap}\n justifyContent={useSpaceBetween ? \"space-between\" : undefined}\n width=\"100%\"\n >\n {renderChildren()}\n </Box>\n\n {error && (\n <Box marginTop={4}>\n <Text\n id={errorId}\n role=\"alert\"\n aria-live=\"assertive\"\n color={theme.colors.content.alert.primary}\n fontSize={14}\n fontWeight=\"400\"\n style={\n orientation === \"vertical\" ? { textAlign: \"center\" } : undefined\n }\n >\n {error}\n </Text>\n </Box>\n )}\n\n {description && (\n <Box marginTop={4}>\n <Text\n id={descriptionId}\n color={theme.colors.content.tertiary}\n fontSize={14}\n fontWeight=\"400\"\n style={\n orientation === \"vertical\" ? { textAlign: \"center\" } : undefined\n }\n >\n {description}\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n\nButtonGroup.displayName = \"ButtonGroup\";\n"],"mappings":"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","names":["import_react","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","import_react_native","import_jsx_runtime","React","import_jsx_runtime","React","import_react","import_xui_core","import_jsx_runtime","cloneIconWithDefaults","React","import_react","import_xui_core","import_jsx_runtime","import_react","import_xui_core","import_jsx_runtime","cloneIconWithDefaults","React","import_react","import_xui_core","import_jsx_runtime","children","React"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/Button.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Spinner.tsx","../../../primitives-native/src/Icon.tsx","../../src/IconButton.tsx","../../src/FlexButton.tsx","../../src/AppButton.tsx","../../src/ButtonGroup.tsx"],"sourcesContent":["export * from \"./Button\";\nexport * from \"./IconButton\";\nexport * from \"./FlexButton\";\nexport * from \"./AppButton\";\nexport * from \"./ButtonGroup\";\n","import React, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Spinner } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\n// Local type definitions for button styling\ninterface ControlVariantStyles {\n bg: string;\n bgHover: string;\n bgPress: string;\n bgDisable?: string;\n border: string;\n borderHover: string;\n borderPress: string;\n borderDisable?: string;\n}\n\ninterface ControlTextStyles {\n primary: string;\n secondary: string;\n tertiary: string;\n ghost: string;\n disable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n sublabelFontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n labelIconSize: number;\n labelIconGap: number;\n}\n\n/**\n * Helper to clone an icon element with default props.\n * Only applies size/color if not already specified by the user.\n * This allows users to override the default size: <ArrowRight size={16} />\n */\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps, // Preserve existing props (including accessibility attributes)\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface ButtonProps extends ThemeOverrideProps {\n /** Visual variant of the button */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\";\n /** Color tone of the button */\n tone?: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Button content */\n children: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /**\n * Icon to display on the left side.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `iconLeft={<ArrowLeft size={16} />}`\n */\n iconLeft?: React.ReactNode;\n /**\n * Icon to display on the right side.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `iconRight={<ArrowRight size={16} />}`\n */\n iconRight?: React.ReactNode;\n /** Secondary text displayed inline with the main label (e.g., price), shown with 40% opacity */\n sublabel?: string;\n /** Alignment of the label text */\n labelAlignment?: \"left\" | \"center\";\n /**\n * Small icon displayed directly next to the label text.\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `labelIcon={<InfoIcon size={12} />}`\n */\n labelIcon?: React.ReactNode;\n /** Custom content slot for badges, tags, or other elements */\n customContent?: React.ReactNode;\n /** Accessible label for screen readers (use for icon-only buttons) */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Whether the button should stretch to fill the full width of its container */\n fullWidth?: boolean;\n}\n\n/**\n * Button - An accessible button component\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n * Supports various visual variants, sizes, and states including loading.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n *\n */\nexport const Button: React.FC<ButtonProps> = ({\n variant = \"primary\",\n tone = \"brand\",\n size = \"md\",\n disabled = false,\n loading = false,\n children,\n onPress,\n iconLeft,\n iconRight,\n sublabel,\n labelAlignment = \"center\",\n labelIcon,\n customContent,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n fullWidth = false,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n // Resolve Config from Theme - type assertion for extended sizing properties\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n // Type assertion for control variant styles - the JSON tokens include tertiary\n const controlTone = theme?.colors?.control?.[tone] as unknown as\n | (Record<string, ControlVariantStyles> & { text: ControlTextStyles })\n | undefined;\n\n const variantStyles: ControlVariantStyles = controlTone?.[variant] ||\n (\n theme?.colors?.control?.brand as unknown as Record<\n string,\n ControlVariantStyles\n >\n )?.primary || {\n bg: \"transparent\",\n bgHover: \"transparent\",\n bgPress: \"transparent\",\n bgDisable: \"transparent\",\n border: \"transparent\",\n borderHover: \"transparent\",\n borderPress: \"transparent\",\n borderDisable: \"transparent\",\n };\n\n // Text colors are at the tone level, mapped by variant name\n const textStyles: ControlTextStyles = controlTone?.text ||\n (theme?.colors?.control?.brand as unknown as { text: ControlTextStyles })\n ?.text || {\n primary: \"#000\",\n secondary: \"#fff\",\n tertiary: \"#888\",\n ghost: \"#000\",\n disable: \"#666\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Determine background color based on state\n let backgroundColor = variantStyles.bg;\n if (disabled) {\n backgroundColor = variantStyles.bgDisable || variantStyles.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = variantStyles.bgPress || variantStyles.bg;\n }\n\n const borderColor = disabled\n ? variantStyles.borderDisable || variantStyles.border\n : variantStyles.border;\n\n // Text color is determined by variant, with disable color for disabled state\n const textColor = disabled ? textStyles.disable : textStyles[variant];\n\n // Only use aria-label when explicitly provided\n // Text content provides accessible name naturally for buttons with visible text\n const computedAriaLabel = ariaLabel;\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={computedAriaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\"\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={fullWidth ? \"100%\" : undefined}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles?.bgHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles?.bgPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {/* Loading Spinner - Absolutely positioned in center */}\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {/* Left Icon Section - Square container matching button height */}\n {iconLeft && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconLeft, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n\n {/* Center Section: Content Area */}\n <Box\n flex={fullWidth ? 1 : undefined}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent={labelAlignment === \"left\" ? \"flex-start\" : \"center\"}\n paddingHorizontal={sizeStyles.padding}\n height=\"100%\"\n gap={sizeStyles.labelIconGap}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n aria-hidden={loading ? true : undefined}\n >\n {/* Label Icon (left of text) */}\n {labelIcon && (\n <Box aria-hidden={true}>\n {cloneIconWithDefaults(\n labelIcon,\n sizeStyles.labelIconSize,\n textColor\n )}\n </Box>\n )}\n\n {/* Label */}\n <Text color={textColor} fontSize={sizeStyles.fontSize} fontWeight=\"500\">\n {children}\n </Text>\n\n {/* Sublabel - inline with label, 40% opacity as per Figma */}\n {sublabel && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"500\"\n style={{ opacity: 0.4 }}\n >\n {sublabel}\n </Text>\n )}\n\n {/* Custom Content Slot */}\n {customContent && <Box aria-hidden={true}>{customContent}</Box>}\n </Box>\n\n {/* Right Icon Section - Square container matching button height */}\n {iconRight && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconRight, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n </Box>\n );\n};\n\nButton.displayName = \"Button\";\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 type React from \"react\";\nimport { ActivityIndicator, View } from \"react-native\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n color,\n size,\n role,\n \"aria-label\": ariaLabel,\n \"aria-live\": ariaLive,\n testID,\n}) => {\n return (\n <View\n accessible={true}\n accessibilityRole={role === \"status\" ? \"none\" : undefined}\n accessibilityLabel={ariaLabel}\n accessibilityLiveRegion={\n ariaLive === \"polite\"\n ? \"polite\"\n : ariaLive === \"assertive\"\n ? \"assertive\"\n : \"none\"\n }\n testID={testID}\n >\n <ActivityIndicator\n color={color}\n size={typeof size === \"number\" ? size : \"small\"}\n />\n </View>\n );\n};\n\nSpinner.displayName = \"Spinner\";\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, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Spinner } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\n// Local type definitions for button styling\ninterface ControlVariantStyles {\n bg: string;\n bgHover: string;\n bgPress: string;\n bgDisable?: string;\n border: string;\n borderHover: string;\n borderPress: string;\n borderDisable?: string;\n}\n\ninterface ControlTextStyles {\n primary: string;\n secondary: string;\n tertiary: string;\n ghost: string;\n disable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n}\n\n/**\n * Helper to clone an icon element with default props.\n * Only applies size/color if not already specified by the user.\n * This allows users to override the default size: <ArrowRight size={16} />\n */\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps, // Preserve existing props (including accessibility attributes)\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface IconButtonProps extends ThemeOverrideProps {\n /** Visual variant of the button */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\";\n /** Color tone of the button */\n tone?: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /**\n * Icon to display in the button (required).\n * Size and color are automatically set based on button size/state.\n * To override, specify size/color on the icon: `icon={<CloseIcon size={16} />}`\n */\n icon: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /**\n * Accessible label for screen readers (REQUIRED for icon-only buttons)\n * Since icon buttons have no visible text, this label is essential for accessibility.\n * @example aria-label=\"Close dialog\"\n * @example aria-label=\"Open settings menu\"\n */\n \"aria-label\": string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n}\n\n/**\n * IconButton - An accessible icon-only button component\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n * Supports various visual variants, sizes, and states including loading.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Required aria-label**: Ensures screen readers can announce the button's purpose\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n *\n * ## Usage\n *\n * ```tsx\n * // Basic usage - aria-label is required\n * <IconButton icon={<CloseIcon />} aria-label=\"Close dialog\" onPress={handleClose} />\n *\n * // Toggle button\n * <IconButton\n * icon={<MenuIcon />}\n * aria-label=\"Toggle menu\"\n * aria-expanded={isOpen}\n * aria-controls=\"menu-id\"\n * onPress={toggleMenu}\n * />\n *\n * // Loading state\n * <IconButton icon={<SaveIcon />} aria-label=\"Save changes\" loading />\n * ```\n */\nexport const IconButton: React.FC<IconButtonProps> = ({\n variant = \"primary\",\n tone = \"brand\",\n size = \"md\",\n disabled = false,\n loading = false,\n icon,\n onPress,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n // Type assertion for extended sizing properties\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n // Type assertion for control variant styles - the JSON tokens include tertiary\n const controlTone = theme?.colors?.control?.[tone] as unknown as\n | (Record<string, ControlVariantStyles> & { text: ControlTextStyles })\n | undefined;\n\n const variantStyles: ControlVariantStyles = controlTone?.[variant] ||\n (\n theme?.colors?.control?.brand as unknown as Record<\n string,\n ControlVariantStyles\n >\n )?.primary || {\n bg: \"transparent\",\n bgHover: \"transparent\",\n bgPress: \"transparent\",\n bgDisable: \"transparent\",\n border: \"transparent\",\n borderHover: \"transparent\",\n borderPress: \"transparent\",\n borderDisable: \"transparent\",\n };\n\n // Text colors are at the tone level, mapped by variant name\n const textStyles: ControlTextStyles = controlTone?.text ||\n (theme?.colors?.control?.brand as unknown as { text: ControlTextStyles })\n ?.text || {\n primary: \"#000\",\n secondary: \"#fff\",\n tertiary: \"#888\",\n ghost: \"#000\",\n disable: \"#666\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Determine background color based on state\n let backgroundColor = variantStyles.bg;\n if (disabled) {\n backgroundColor = variantStyles.bgDisable || variantStyles.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = variantStyles.bgPress || variantStyles.bg;\n }\n\n const borderColor = disabled\n ? variantStyles.borderDisable || variantStyles.border\n : variantStyles.border;\n\n // Text color is determined by variant, with disable color for disabled state\n const textColor = disabled ? textStyles.disable : textStyles[variant];\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\"\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={sizeStyles.height}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles.bgHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: variantStyles.bgPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {/* Loading Spinner - Absolutely positioned in center */}\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {/* Icon - Hidden when loading but maintains layout */}\n <Box\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(icon, sizeStyles.iconSize, textColor)}\n </Box>\n </Box>\n );\n};\n\nIconButton.displayName = \"IconButton\";\n","import React, {\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Spinner, Icon } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\nexport interface FlexButtonProps\n extends\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n ThemeOverrideProps {\n /** Button content */\n children: ReactNode;\n /** Visual variant of the button */\n variant?:\n | \"brand\"\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"brandExtra\"\n | \"inverse\";\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether to show background fill */\n background?: boolean;\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Icon to display on the left side */\n iconLeft?: ReactNode;\n /** Icon to display on the right side */\n iconRight?: ReactNode;\n /** Click handler */\n onPress?: () => void;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Accessible label for screen readers */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\ntype ButtonState = \"default\" | \"hover\" | \"press\";\n\nconst ICON_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nconst SPINNER_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nconst LINE_HEIGHTS: Record<NonNullable<FlexButtonProps[\"size\"]>, string> = {\n xs: \"14px\",\n sm: \"16px\",\n md: \"18px\",\n lg: \"20px\",\n xl: \"22px\",\n};\n\nconst FONT_SIZES: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xs: 12,\n sm: 14,\n md: 14,\n lg: 16,\n xl: 18,\n};\n\nconst BORDER_RADIUS: Record<NonNullable<FlexButtonProps[\"size\"]>, number> = {\n xl: 4,\n lg: 4,\n md: 2,\n sm: 2,\n xs: 2,\n};\n\n/**\n * FlexButton - A compact button component designed for use in modals and popups.\n *\n * Renders as a semantic `<button>` element with full ARIA support.\n *\n * ## Accessibility Features\n *\n * - **Semantic HTML**: Renders as a native `<button>` element\n * - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space\n * - **ARIA States**: Properly announces disabled and loading states\n * - **Focus Indicator**: Visible focus ring for keyboard navigation\n * - **Screen Reader Support**: Announces button label, state, and any associated descriptions\n */\nexport const FlexButton: React.FC<FlexButtonProps> = ({\n children,\n variant = \"brand\",\n size = \"md\",\n background = false,\n disabled = false,\n loading = false,\n iconLeft,\n iconRight,\n onPress,\n onClick,\n className,\n type = \"button\",\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n tabIndex = 0,\n themeMode,\n themeProductContext,\n ...buttonProps\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const [state, setState] = useState<ButtonState>(\"default\");\n const [isFocused, setIsFocused] = useState(false);\n const isMouseOverRef = useRef(false);\n\n const isDisabled = disabled || loading;\n\n const getVariantColors = (\n currentState: ButtonState\n ): { bg: string; text: string; border?: string } => {\n if (isDisabled) {\n return {\n bg: background ? theme.colors.overlay.mono : \"transparent\",\n text: theme.colors.control.text.disable,\n border: undefined,\n };\n }\n\n const effectiveBackground = loading ? false : background;\n\n switch (variant) {\n case \"brand\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.brand.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.brand.primary.bgHover\n : theme.colors.background.brand.primary,\n text: theme.colors.content.on.brand,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.background.brand.primary\n : currentState === \"hover\"\n ? theme.colors.overlay.brand\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.on.brand\n : theme.colors.content.brand.primary,\n border: undefined,\n };\n\n case \"primary\":\n if (effectiveBackground) {\n return {\n bg: theme.colors.background.primary,\n text: theme.colors.content.primary,\n border:\n currentState === \"press\"\n ? theme.colors.border.primary\n : undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text: theme.colors.content.primary,\n border:\n currentState === \"press\" ? theme.colors.border.primary : undefined,\n };\n\n case \"secondary\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.secondary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.secondary.bgHover\n : theme.colors.background.secondary,\n text: theme.colors.content.secondary,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.primary\n : currentState === \"hover\"\n ? theme.colors.content.secondary\n : theme.colors.content.secondary,\n border: undefined,\n };\n\n case \"tertiary\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.secondary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.secondary.bgHover\n : theme.colors.background.secondary,\n text: theme.colors.content.tertiary,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.secondary\n : currentState === \"hover\"\n ? theme.colors.content.tertiary\n : theme.colors.content.tertiary,\n border: undefined,\n };\n\n case \"brandExtra\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.brandExtra.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.brandExtra.primary.bgHover\n : theme.colors.background.brandExtra.primary,\n text: theme.colors.content.on.brandExtra,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.background.brandExtra.primary\n : currentState === \"hover\"\n ? theme.colors.overlay.brandExtra\n : \"transparent\",\n text:\n currentState === \"press\"\n ? theme.colors.content.on.brandExtra\n : theme.colors.content.brandExtra.secondary,\n border: undefined,\n };\n\n case \"inverse\":\n if (effectiveBackground) {\n return {\n bg:\n currentState === \"press\"\n ? theme.colors.control.mono.primary.bgPress\n : currentState === \"hover\"\n ? theme.colors.control.mono.primary.bgHover\n : theme.colors.background.inverse,\n text: theme.colors.content.inverse,\n border: undefined,\n };\n }\n return {\n bg:\n currentState === \"press\" || currentState === \"hover\"\n ? theme.colors.overlay.mono\n : \"transparent\",\n text: theme.colors.content.inverse,\n border: undefined,\n };\n\n default:\n return {\n bg: \"transparent\",\n text: theme.colors.content.primary,\n border: undefined,\n };\n }\n };\n\n const getFocusRingColor = (): string => {\n switch (variant) {\n case \"brand\":\n return theme.colors.overlay.brand;\n case \"brandExtra\":\n return theme.colors.overlay.brandExtra;\n case \"inverse\":\n return \"rgba(255, 255, 255, 0.3)\";\n default:\n return theme.colors.overlay.mono;\n }\n };\n\n const getSpinnerColor = (): string => {\n switch (variant) {\n case \"brand\":\n return theme.colors.content.brand.primary;\n case \"primary\":\n return theme.colors.content.primary;\n case \"secondary\":\n return theme.colors.content.secondary;\n case \"tertiary\":\n return theme.colors.content.tertiary;\n case \"brandExtra\":\n return theme.colors.content.brandExtra.secondary;\n case \"inverse\":\n return theme.colors.content.inverse;\n default:\n return theme.colors.content.brand.primary;\n }\n };\n\n const colors = getVariantColors(state);\n const focusRingColor = getFocusRingColor();\n const spinnerColor = getSpinnerColor();\n const iconSize = ICON_SIZES[size];\n const spinnerSize = SPINNER_SIZES[size];\n const fontSize = FONT_SIZES[size];\n const borderRadius = BORDER_RADIUS[size];\n const lineHeight = LINE_HEIGHTS[size];\n\n const handleMouseEnter = () => {\n if (!isDisabled) {\n isMouseOverRef.current = true;\n setState(\"hover\");\n }\n };\n\n const handleMouseLeave = () => {\n if (!isDisabled) {\n isMouseOverRef.current = false;\n setState(\"default\");\n }\n };\n\n const handleMouseDown = () => {\n if (!isDisabled) {\n setState(\"press\");\n }\n };\n\n const handleMouseUp = () => {\n if (!isDisabled) {\n setState(isMouseOverRef.current ? \"hover\" : \"default\");\n }\n };\n\n const handleFocus = () => {\n if (!isDisabled) {\n setIsFocused(true);\n }\n };\n\n const handleBlur = () => {\n setIsFocused(false);\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (onPress) {\n onPress();\n }\n if (onClick) {\n onClick(event);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n setState(\"press\");\n }\n };\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n setState(isMouseOverRef.current ? \"hover\" : \"default\");\n if (onPress) {\n onPress();\n }\n }\n };\n\n const borderShadow = colors.border\n ? `inset 0 0 0 1px ${colors.border}`\n : undefined;\n const focusShadow =\n isFocused && !isDisabled ? `0 0 0 2px ${focusRingColor}` : undefined;\n\n const boxShadows: string[] = [];\n if (borderShadow) boxShadows.push(borderShadow);\n if (focusShadow) boxShadows.push(focusShadow);\n const combinedBoxShadow =\n boxShadows.length > 0 ? boxShadows.join(\", \") : \"none\";\n\n const buttonStyle: CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"2px\",\n padding: \"4px\",\n backgroundColor: loading ? \"transparent\" : colors.bg,\n color: colors.text,\n border: \"none\",\n borderWidth: \"0px\",\n borderRadius: `${borderRadius}px`,\n cursor: isDisabled ? \"not-allowed\" : \"pointer\",\n fontSize: `${fontSize}px`,\n fontWeight: 500,\n lineHeight: lineHeight,\n fontFamily: \"inherit\",\n transition:\n \"background-color 100ms ease-in-out, color 100ms ease-in-out, box-shadow 100ms ease-in-out\",\n outline: \"none\",\n boxShadow: combinedBoxShadow,\n opacity: isDisabled && !loading ? 0.6 : 1,\n };\n\n const contentStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"2px\",\n };\n\n const spinnerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"transparent\",\n height: lineHeight,\n };\n\n const computedAriaLabel =\n ariaLabel || (typeof children === \"string\" ? children : undefined);\n\n return (\n <button\n {...buttonProps}\n type={type}\n className={className}\n disabled={isDisabled}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onFocus={handleFocus}\n onBlur={handleBlur}\n aria-label={computedAriaLabel}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n tabIndex={tabIndex}\n style={buttonStyle}\n data-testid={testID || \"flex-button\"}\n >\n <span style={contentStyle}>\n {loading ? (\n <span style={spinnerStyle}>\n <Spinner size={spinnerSize} color={spinnerColor} />\n </span>\n ) : (\n <>\n {iconLeft && (\n <Icon size={iconSize} color={colors.text}>\n {iconLeft}\n </Icon>\n )}\n <span>{children}</span>\n {iconRight && (\n <Icon size={iconSize} color={colors.text}>\n {iconRight}\n </Icon>\n )}\n </>\n )}\n </span>\n </button>\n );\n};\n\nFlexButton.displayName = \"FlexButton\";\n","import React, { useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Spinner } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\ninterface AppButtonTokens {\n bg: string;\n bgHover: string;\n bgPress: string;\n border: string;\n borderHover: string;\n borderPress: string;\n text: string;\n textDisable: string;\n}\n\ninterface ButtonSizeStyles {\n height: number;\n padding: number;\n fontSize: number;\n sublabelFontSize: number;\n spinnerSize: number;\n iconSize: number;\n iconContainerSize: number;\n iconPadding: number;\n loadingPadding: number;\n borderRadius: number;\n labelIconSize: number;\n labelIconGap: number;\n}\n\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<any>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps,\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nexport interface AppButtonProps extends ThemeOverrideProps {\n /** Size of the button */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is in a loading state */\n loading?: boolean;\n /** Button content */\n children: React.ReactNode;\n /** Click handler */\n onPress?: () => void;\n /** Icon to display on the left side */\n iconLeft?: React.ReactNode;\n /** Icon to display on the right side */\n iconRight?: React.ReactNode;\n /** Secondary text displayed inline with the main label */\n sublabel?: string;\n /** Alignment of the label text */\n labelAlignment?: \"left\" | \"center\";\n /** Small icon displayed directly next to the label text */\n labelIcon?: React.ReactNode;\n /** Custom content slot for badges, tags, or other elements */\n customContent?: React.ReactNode;\n /** Accessible label for screen readers */\n \"aria-label\"?: string;\n /** ID of element that describes this button */\n \"aria-describedby\"?: string;\n /** Indicates the button controls an expandable element */\n \"aria-expanded\"?: boolean;\n /** Indicates the type of popup triggered by the button */\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n /** Indicates the button is pressed (for toggle buttons) */\n \"aria-pressed\"?: boolean | \"mixed\";\n /** ID of the element this button controls */\n \"aria-controls\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n /** HTML id attribute */\n id?: string;\n /** HTML type attribute for the button */\n type?: \"button\" | \"submit\" | \"reset\";\n /** Whether the button should stretch to fill the full width of its container */\n fullWidth?: boolean;\n}\n\n/**\n * AppButton - A prominent filled button for app-level actions.\n *\n * Uses the `control.appButton` theme tokens for styling.\n * Supports all the same layout features as Button (icons, sublabels, etc.).\n */\nexport const AppButton: React.FC<AppButtonProps> = ({\n size = \"md\",\n disabled = false,\n loading = false,\n children,\n onPress,\n iconLeft,\n iconRight,\n sublabel,\n labelAlignment = \"center\",\n labelIcon,\n customContent,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n testID,\n id,\n type = \"button\",\n fullWidth = false,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);\n\n const isDisabled = disabled || loading;\n\n const sizeStyles = theme.sizing.button(size) as ButtonSizeStyles;\n\n const tokens: AppButtonTokens = (theme?.colors?.control as any)\n ?.appButton || {\n bg: \"#34474b\",\n bgHover: \"#3d5256\",\n bgPress: \"#2b3b3e\",\n border: \"rgba(255, 255, 255, 0.12)\",\n borderHover: \"rgba(255, 255, 255, 0.18)\",\n borderPress: \"rgba(255, 255, 255, 0.12)\",\n text: \"#b7c5c8\",\n textDisable: \"#b3b3b3\",\n };\n\n const handlePress = () => {\n if (!isDisabled && onPress) {\n onPress();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(true);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n if (isDisabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setIsKeyboardPressed(false);\n if (onPress) {\n onPress();\n }\n }\n };\n\n let backgroundColor = tokens.bg;\n if (disabled) {\n backgroundColor = tokens.bg;\n } else if (isKeyboardPressed) {\n backgroundColor = tokens.bgPress;\n }\n\n const borderColor = tokens.border;\n const textColor = disabled ? tokens.textDisable : tokens.text;\n\n return (\n <Box\n as=\"button\"\n type={type}\n id={id}\n onPress={handlePress}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n testID={testID}\n backgroundColor={backgroundColor}\n borderColor={borderColor}\n borderWidth={\n borderColor !== \"transparent\" &&\n borderColor !== \"rgba(255, 255, 255, 0)\" &&\n borderColor !== \"rgba(0, 0, 0, 0)\" &&\n !borderColor.endsWith(\", 0)\")\n ? 1\n : 0\n }\n borderRadius={sizeStyles.borderRadius}\n height={sizeStyles.height}\n width={fullWidth ? \"100%\" : undefined}\n padding={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n position=\"relative\"\n cursor={disabled ? \"not-allowed\" : loading ? \"wait\" : \"pointer\"}\n opacity={disabled ? 0.6 : 1}\n hoverStyle={\n !isDisabled\n ? {\n backgroundColor: tokens.bgHover,\n borderColor: tokens.borderHover,\n }\n : undefined\n }\n pressStyle={\n !isDisabled\n ? {\n backgroundColor: tokens.bgPress,\n borderColor: tokens.borderPress,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n }}\n >\n {loading && (\n <Box\n position=\"absolute\"\n top={0}\n left={0}\n right={0}\n bottom={0}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={1}\n >\n <Spinner\n color={textColor}\n size={sizeStyles.spinnerSize}\n aria-hidden={true}\n />\n </Box>\n )}\n\n {iconLeft && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconLeft, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n\n <Box\n flex={fullWidth ? 1 : undefined}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent={labelAlignment === \"left\" ? \"flex-start\" : \"center\"}\n paddingHorizontal={sizeStyles.padding}\n height=\"100%\"\n gap={sizeStyles.labelIconGap}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n aria-hidden={loading ? true : undefined}\n >\n {labelIcon && (\n <Box aria-hidden={true}>\n {cloneIconWithDefaults(\n labelIcon,\n sizeStyles.labelIconSize,\n textColor\n )}\n </Box>\n )}\n\n <Text color={textColor} fontSize={sizeStyles.fontSize} fontWeight=\"500\">\n {children}\n </Text>\n\n {sublabel && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"500\"\n style={{ opacity: 0.4 }}\n >\n {sublabel}\n </Text>\n )}\n\n {customContent && <Box aria-hidden={true}>{customContent}</Box>}\n </Box>\n\n {iconRight && (\n <Box\n width={sizeStyles.iconContainerSize}\n height={sizeStyles.iconContainerSize}\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n style={{\n opacity: loading ? 0 : 1,\n pointerEvents: loading ? \"none\" : \"auto\",\n }}\n >\n {cloneIconWithDefaults(iconRight, sizeStyles.iconSize, textColor)}\n </Box>\n )}\n </Box>\n );\n};\n\nAppButton.displayName = \"AppButton\";\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\nexport interface ButtonGroupProps extends ThemeOverrideProps {\n /**\n * Layout orientation of the buttons\n * @default 'horizontal'\n */\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Size of the button group, determines default gap between buttons\n * @default 'md'\n */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /**\n * Buttons to be grouped\n */\n children: React.ReactNode;\n /**\n * Optional description text below the buttons\n */\n description?: string;\n /**\n * Optional error message text below the buttons\n */\n error?: string;\n /**\n * Custom gap between buttons (in pixels). If not provided, uses size and orientation based default.\n */\n gap?: number;\n /**\n * Accessible label for the button group\n */\n \"aria-label\"?: string;\n /**\n * ID of element that labels this button group\n */\n \"aria-labelledby\"?: string;\n /**\n * ID of element that describes this button group\n */\n \"aria-describedby\"?: string;\n /**\n * HTML id attribute\n */\n id?: string;\n /**\n * Test ID for testing frameworks\n */\n testID?: string;\n}\n\n/**\n * ButtonGroup - A container for grouping related buttons\n *\n * Provides semantic grouping for related actions with proper accessibility support.\n *\n * ## Accessibility Features\n *\n * - **Semantic Grouping**: Uses `role=\"group\"` to indicate related buttons\n * - **Accessible Name**: Supports `aria-label` or `aria-labelledby` to describe the group's purpose\n * - **Error Announcements**: Errors are announced to screen readers via `aria-live`\n * - **Description Support**: Optional description text for additional context\n *\n */\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({\n orientation = \"horizontal\",\n size = \"md\",\n children,\n description,\n error,\n gap,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n id,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n // Flatten children to handle fragments and get actual button elements\n const flattenChildren = (children: React.ReactNode): React.ReactNode[] => {\n const result: React.ReactNode[] = [];\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === React.Fragment) {\n result.push(...flattenChildren(child.props.children));\n } else if (child !== null && child !== undefined) {\n result.push(child);\n }\n });\n return result;\n };\n\n const flatChildren = flattenChildren(children);\n const childCount = flatChildren.length;\n\n // Check if we need space-between layout (horizontal with more than 2 buttons)\n const useSpaceBetween = orientation === \"horizontal\" && childCount > 2;\n\n // Size-based default gaps by orientation\n const verticalGapMap = {\n xl: 16,\n lg: 16,\n md: 12,\n sm: 8,\n xs: 4,\n };\n\n const horizontalGapMap = {\n xl: 16,\n lg: 16,\n md: 16,\n sm: 12,\n xs: 12,\n };\n\n // Use provided gap or fall back to orientation and size based default\n const computedGap =\n gap ??\n (orientation === \"vertical\"\n ? verticalGapMap[size]\n : horizontalGapMap[size]);\n\n // Generate IDs for description and error elements\n const descriptionId = id ? `${id}-description` : undefined;\n const errorId = id ? `${id}-error` : undefined;\n\n // Build aria-describedby value combining external and internal references\n const computedAriaDescribedBy =\n [\n ariaDescribedBy,\n error && errorId ? errorId : undefined,\n description && descriptionId ? descriptionId : undefined,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n // Apply fullWidth to children in vertical orientation for proper alignment\n const processChildren = (childrenToProcess: React.ReactNode[]) => {\n if (orientation === \"vertical\") {\n return childrenToProcess.map((child, index) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n ...child.props,\n fullWidth: true,\n key: child.key ?? index,\n });\n }\n return child;\n });\n }\n return childrenToProcess;\n };\n\n // Split children for space-between layout\n const renderChildren = () => {\n const processedChildren = processChildren(flatChildren);\n\n if (useSpaceBetween) {\n const firstChild = processedChildren[0];\n const restChildren = processedChildren.slice(1);\n\n return (\n <>\n {firstChild}\n <Box flexDirection=\"row\" gap={computedGap}>\n {restChildren}\n </Box>\n </>\n );\n }\n\n // For non-space-between layout, return processed children or original\n if (orientation === \"vertical\") {\n return processedChildren;\n }\n return children;\n };\n\n return (\n <Box flexDirection=\"column\" width=\"100%\" gap={8}>\n <Box\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={computedAriaDescribedBy}\n id={id}\n testID={testID}\n flexDirection={orientation === \"horizontal\" ? \"row\" : \"column\"}\n alignItems=\"stretch\"\n gap={computedGap}\n justifyContent={useSpaceBetween ? \"space-between\" : undefined}\n width=\"100%\"\n >\n {renderChildren()}\n </Box>\n\n {error && (\n <Box marginTop={4}>\n <Text\n id={errorId}\n role=\"alert\"\n aria-live=\"assertive\"\n color={theme.colors.content.alert.primary}\n fontSize={14}\n fontWeight=\"400\"\n style={\n orientation === \"vertical\" ? { textAlign: \"center\" } : undefined\n }\n >\n {error}\n </Text>\n </Box>\n )}\n\n {description && (\n <Box marginTop={4}>\n <Text\n id={descriptionId}\n color={theme.colors.content.tertiary}\n fontSize={14}\n fontWeight=\"400\"\n style={\n orientation === \"vertical\" ? { textAlign: \"center\" } : undefined\n }\n >\n {description}\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n\nButtonGroup.displayName = \"ButtonGroup\";\n"],"mappings":"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","names":["import_react","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","import_react_native","import_jsx_runtime","React","import_jsx_runtime","React","import_react","import_xui_core","import_jsx_runtime","cloneIconWithDefaults","React","import_react","import_xui_core","import_jsx_runtime","import_react","import_xui_core","import_jsx_runtime","cloneIconWithDefaults","React","import_react","import_xui_core","import_jsx_runtime","children","React"]}
package/native/index.mjs CHANGED
@@ -48,6 +48,10 @@ var Box = ({
48
48
  left,
49
49
  right,
50
50
  width,
51
+ minWidth,
52
+ minHeight,
53
+ maxWidth,
54
+ maxHeight,
51
55
  flex,
52
56
  overflow,
53
57
  zIndex,
@@ -79,6 +83,10 @@ var Box = ({
79
83
  zIndex,
80
84
  height,
81
85
  width,
86
+ minWidth,
87
+ minHeight,
88
+ maxWidth,
89
+ maxHeight,
82
90
  padding,
83
91
  paddingHorizontal,
84
92
  paddingVertical,
@@ -210,7 +218,7 @@ var Text = ({
210
218
  }
211
219
  const incomingStyle = StyleSheet.flatten(styleProp);
212
220
  const baseStyle = {
213
- color,
221
+ color: color ?? incomingStyle?.color,
214
222
  fontSize: typeof fontSize === "number" ? fontSize : void 0,
215
223
  fontWeight,
216
224
  fontFamily: resolvedFontFamily,
@@ -293,7 +301,7 @@ var Icon = ({ children, color, size }) => {
293
301
  };
294
302
 
295
303
  // src/Button.tsx
296
- import { useDesignSystem } from "@xsolla/xui-core";
304
+ import { useResolvedTheme } from "@xsolla/xui-core";
297
305
  import { jsx as jsx5, jsxs } from "react/jsx-runtime";
298
306
  var cloneIconWithDefaults = (icon, defaultSize, defaultColor) => {
299
307
  if (!React2.isValidElement(icon)) return icon;
@@ -329,9 +337,11 @@ var Button = ({
329
337
  testID,
330
338
  id,
331
339
  type = "button",
332
- fullWidth = false
340
+ fullWidth = false,
341
+ themeMode,
342
+ themeProductContext
333
343
  }) => {
334
- const { theme } = useDesignSystem();
344
+ const { theme } = useResolvedTheme({ themeMode, themeProductContext });
335
345
  const [isKeyboardPressed, setIsKeyboardPressed] = useState(false);
336
346
  const isDisabled = disabled || loading;
337
347
  const sizeStyles = theme.sizing.button(size);
@@ -524,7 +534,7 @@ Button.displayName = "Button";
524
534
 
525
535
  // src/IconButton.tsx
526
536
  import React3, { useState as useState2 } from "react";
527
- import { useDesignSystem as useDesignSystem2 } from "@xsolla/xui-core";
537
+ import { useResolvedTheme as useResolvedTheme2 } from "@xsolla/xui-core";
528
538
  import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
529
539
  var cloneIconWithDefaults2 = (icon, defaultSize, defaultColor) => {
530
540
  if (!React3.isValidElement(icon)) return icon;
@@ -553,9 +563,11 @@ var IconButton = ({
553
563
  "aria-controls": ariaControls,
554
564
  testID,
555
565
  id,
556
- type = "button"
566
+ type = "button",
567
+ themeMode,
568
+ themeProductContext
557
569
  }) => {
558
- const { theme } = useDesignSystem2();
570
+ const { theme } = useResolvedTheme2({ themeMode, themeProductContext });
559
571
  const [isKeyboardPressed, setIsKeyboardPressed] = useState2(false);
560
572
  const isDisabled = disabled || loading;
561
573
  const sizeStyles = theme.sizing.button(size);
@@ -695,7 +707,7 @@ import {
695
707
  useRef,
696
708
  useState as useState3
697
709
  } from "react";
698
- import { useDesignSystem as useDesignSystem3 } from "@xsolla/xui-core";
710
+ import { useResolvedTheme as useResolvedTheme3 } from "@xsolla/xui-core";
699
711
  import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
700
712
  var ICON_SIZES = {
701
713
  xs: 12,
@@ -753,9 +765,11 @@ var FlexButton = ({
753
765
  "aria-controls": ariaControls,
754
766
  testID,
755
767
  tabIndex = 0,
768
+ themeMode,
769
+ themeProductContext,
756
770
  ...buttonProps
757
771
  }) => {
758
- const { theme } = useDesignSystem3();
772
+ const { theme } = useResolvedTheme3({ themeMode, themeProductContext });
759
773
  const [state, setState] = useState3("default");
760
774
  const [isFocused, setIsFocused] = useState3(false);
761
775
  const isMouseOverRef = useRef(false);
@@ -1030,7 +1044,7 @@ FlexButton.displayName = "FlexButton";
1030
1044
 
1031
1045
  // src/AppButton.tsx
1032
1046
  import React5, { useState as useState4 } from "react";
1033
- import { useDesignSystem as useDesignSystem4 } from "@xsolla/xui-core";
1047
+ import { useResolvedTheme as useResolvedTheme4 } from "@xsolla/xui-core";
1034
1048
  import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1035
1049
  var cloneIconWithDefaults3 = (icon, defaultSize, defaultColor) => {
1036
1050
  if (!React5.isValidElement(icon)) return icon;
@@ -1063,9 +1077,11 @@ var AppButton = ({
1063
1077
  testID,
1064
1078
  id,
1065
1079
  type = "button",
1066
- fullWidth = false
1080
+ fullWidth = false,
1081
+ themeMode,
1082
+ themeProductContext
1067
1083
  }) => {
1068
- const { theme } = useDesignSystem4();
1084
+ const { theme } = useResolvedTheme4({ themeMode, themeProductContext });
1069
1085
  const [isKeyboardPressed, setIsKeyboardPressed] = useState4(false);
1070
1086
  const isDisabled = disabled || loading;
1071
1087
  const sizeStyles = theme.sizing.button(size);
@@ -1251,7 +1267,7 @@ AppButton.displayName = "AppButton";
1251
1267
 
1252
1268
  // src/ButtonGroup.tsx
1253
1269
  import React6 from "react";
1254
- import { useDesignSystem as useDesignSystem5 } from "@xsolla/xui-core";
1270
+ import { useResolvedTheme as useResolvedTheme5 } from "@xsolla/xui-core";
1255
1271
  import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1256
1272
  var ButtonGroup = ({
1257
1273
  orientation = "horizontal",
@@ -1264,9 +1280,11 @@ var ButtonGroup = ({
1264
1280
  "aria-labelledby": ariaLabelledBy,
1265
1281
  "aria-describedby": ariaDescribedBy,
1266
1282
  id,
1267
- testID
1283
+ testID,
1284
+ themeMode,
1285
+ themeProductContext
1268
1286
  }) => {
1269
- const { theme } = useDesignSystem5();
1287
+ const { theme } = useResolvedTheme5({ themeMode, themeProductContext });
1270
1288
  const flattenChildren = (children2) => {
1271
1289
  const result = [];
1272
1290
  React6.Children.forEach(children2, (child) => {