@xsolla/xui-tab-bar 0.102.0 → 0.104.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/TabBar.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx","../../src/TabBarItem.tsx"],"sourcesContent":["import React, { useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { TabBarItem } from \"./TabBarItem\";\nimport type { TabBarProps } from \"./types\";\n\n/**\n * TabBar - An accessible tab bar navigation component\n *\n * Implements WAI-ARIA Tabs pattern with proper keyboard navigation:\n * - Arrow Left/Right: Navigate between tabs\n * - Home: Jump to first tab\n * - End: Jump to last tab\n * - Enter/Space: Activate focused tab (when activateOnFocus is false)\n *\n * @example\n * ```tsx\n * <TabBar\n * state={navigationState}\n * descriptors={descriptors}\n * navigation={navigation}\n * aria-label=\"Main navigation\"\n * />\n * ```\n */\nexport const TabBar: React.FC<TabBarProps> = ({\n state,\n descriptors,\n navigation,\n labelPosition = \"below-icon\",\n backgroundColor,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n id,\n activateOnFocus = true,\n}) => {\n const { theme } = useDesignSystem();\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const tabCount = state.routes.length;\n\n /**\n * Focus a tab by its index\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n }\n }, []);\n\n /**\n * Navigate to a tab by index\n */\n const navigateToTab = useCallback(\n (index: number) => {\n const route = state.routes[index];\n if (route) {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n }\n },\n [state.routes, navigation]\n );\n\n /**\n * Handle keyboard navigation within the tab bar\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n let nextIndex: number | null = null;\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n nextIndex = currentIndex < tabCount - 1 ? currentIndex + 1 : 0;\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n nextIndex = currentIndex > 0 ? currentIndex - 1 : tabCount - 1;\n break;\n\n case \"Home\":\n e.preventDefault();\n nextIndex = 0;\n break;\n\n case \"End\":\n e.preventDefault();\n nextIndex = tabCount - 1;\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n navigateToTab(currentIndex);\n break;\n\n default:\n break;\n }\n\n if (nextIndex !== null) {\n focusTab(nextIndex);\n if (activateOnFocus) {\n navigateToTab(nextIndex);\n }\n }\n },\n [tabCount, focusTab, navigateToTab, activateOnFocus]\n );\n\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n aria-label={ariaLabel || \"Tab navigation\"}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n flexDirection=\"row\"\n backgroundColor={backgroundColor || theme.colors.background.primary}\n borderTopWidth={1}\n borderTopColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n height={60}\n width=\"100%\"\n testID={testID || \"tab-bar-container\"}\n id={id}\n >\n {state.routes.map((route, index) => {\n const { options } = descriptors[route.key];\n const label =\n options.tabBarShowLabel === false\n ? undefined\n : options.tabBarLabel !== undefined\n ? options.tabBarLabel\n : options.title !== undefined\n ? options.title\n : route.name;\n\n const isFocused = state.index === index;\n\n const onPress = () => {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!isFocused && !event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n };\n\n const onLongPress = () => {\n navigation.emit({\n type: \"tabLongPress\",\n target: route.key,\n });\n };\n\n const icon = options.tabBarIcon\n ? options.tabBarIcon({\n focused: isFocused,\n color: isFocused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary,\n size: 24,\n })\n : undefined;\n\n const badge = options.tabBarBadge;\n\n // Generate accessible label fallback\n const resolvedLabel =\n typeof label === \"function\"\n ? label({\n focused: isFocused,\n color: isFocused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary,\n position: labelPosition,\n })\n : label;\n\n // Use explicit accessibility label or fall back to text label\n const accessibilityLabel =\n options.tabBarAccessibilityLabel ||\n (typeof resolvedLabel === \"string\" ? resolvedLabel : route.name);\n\n // Generate unique tab ID\n const tabId = id ? `${id}-tab-${route.key}` : undefined;\n\n return (\n <TabBarItem\n key={route.key}\n id={tabId}\n label={resolvedLabel}\n icon={icon}\n badge={badge}\n focused={isFocused}\n onPress={onPress}\n onLongPress={onLongPress}\n labelPosition={labelPosition}\n accessibilityLabel={accessibilityLabel}\n testID={options.tabBarTestID}\n index={index}\n tabCount={tabCount}\n onKeyDown={handleKeyDown}\n tabRef={(el) => {\n tabRefs.current[index] = el;\n }}\n />\n );\n })}\n </Box>\n );\n};\n\nTabBar.displayName = \"TabBar\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, it's better to use the system font\n // to avoid rendering issues or missing text.\n if (resolvedFontFamily === \"Pilat Wide Bold\") {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n","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, { cloneElement, isValidElement, type ReactNode } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport type { TabBarItemProps } from \"./types\";\n\n/**\n * TabBarItem - An accessible tab item component\n *\n * Implements WAI-ARIA tab role with proper semantics:\n * - role=\"tab\" for tab semantics\n * - aria-selected to indicate active state\n * - tabIndex management for roving tabindex pattern\n * - Keyboard navigation support\n */\nexport const TabBarItem: React.FC<TabBarItemProps> = ({\n label,\n icon,\n badge,\n focused,\n onPress,\n onLongPress,\n labelPosition,\n accessibilityLabel,\n testID,\n id,\n index,\n onKeyDown,\n tabRef,\n}) => {\n const { theme } = useDesignSystem();\n\n const color = focused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary;\n\n const renderIcon = () => {\n if (!icon) return null;\n\n return (\n <Box\n position=\"relative\"\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n >\n <Icon size={24} color={color}>\n {isValidElement(icon)\n ? cloneElement(icon as React.ReactElement<any>, {\n size: 24,\n color: color,\n stroke: color,\n })\n : icon}\n </Icon>\n {badge !== undefined && badge !== null && (\n <Box position=\"absolute\" top={-5} right={-10} zIndex={1}>\n <Badge\n size=\"sm\"\n aria-label={\n typeof badge === \"number\"\n ? `${badge} notifications`\n : String(badge)\n }\n >\n {badge}\n </Badge>\n </Box>\n )}\n </Box>\n );\n };\n\n const renderLabel = () => {\n if (typeof label === \"string\") {\n return (\n <Text\n color={color}\n fontSize={12}\n fontWeight={focused ? \"600\" : \"400\"}\n numberOfLines={1}\n aria-hidden={true}\n >\n {label}\n </Text>\n );\n }\n return label as ReactNode;\n };\n\n /**\n * Handle keyboard events for this tab\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onKeyDown) {\n onKeyDown(e, index);\n }\n };\n\n return (\n <Box\n as=\"button\"\n role=\"tab\"\n id={id}\n aria-selected={focused}\n aria-label={accessibilityLabel}\n tabIndex={focused ? 0 : -1}\n ref={tabRef}\n flex={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n paddingVertical={8}\n cursor=\"pointer\"\n flexDirection={labelPosition === \"beside-icon\" ? \"row\" : \"column\"}\n gap={labelPosition === \"beside-icon\" ? 8 : 4}\n onPress={onPress}\n onLongPress={onLongPress}\n onKeyDown={handleKeyDown}\n testID={testID}\n hoverStyle={{\n backgroundColor: theme.colors.overlay.mono,\n }}\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n outlineStyle: \"solid\",\n }}\n >\n {renderIcon()}\n {renderLabel()}\n </Box>\n );\n};\n\nTabBarItem.displayName = \"TabBarItem\";\n"],"mappings":"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","names":["jsx","View","jsx","useDesignSystem","jsx","jsx","useDesignSystem"]}
1
+ {"version":3,"sources":["../../src/TabBar.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx","../../src/TabBarItem.tsx"],"sourcesContent":["import React, { useRef, useCallback, useState, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem, isWeb } from \"@xsolla/xui-core\";\nimport { TabBarItem } from \"./TabBarItem\";\nimport type { TabBarProps } from \"./types\";\n\n/**\n * TabBar - An accessible tab bar navigation component\n *\n * Implements WAI-ARIA Tabs pattern with proper keyboard navigation:\n * - Arrow Left/Right: Navigate between tabs\n * - Home: Jump to first tab\n * - End: Jump to last tab\n * - Enter/Space: Activate focused tab (when activateOnFocus is false)\n *\n * @example\n * ```tsx\n * <TabBar\n * state={navigationState}\n * descriptors={descriptors}\n * navigation={navigation}\n * aria-label=\"Main navigation\"\n * />\n * ```\n */\nexport const TabBar: React.FC<TabBarProps> = ({\n state,\n descriptors,\n navigation,\n labelPosition = \"below-icon\",\n backgroundColor,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n id,\n activateOnFocus = true,\n}) => {\n const { theme } = useDesignSystem();\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n const tabCount = state.routes.length;\n\n // Indicator position for sliding selection animation\n const [indicatorStyle, setIndicatorStyle] = useState<{\n left: number;\n width: number;\n initialized: boolean;\n }>({ left: 0, width: 0, initialized: false });\n\n // Update indicator position when active tab changes (web only)\n useEffect(() => {\n if (!isWeb) return;\n\n const activeIndex = state.index;\n const activeTabEl = tabRefs.current[activeIndex];\n const containerEl = containerRef.current;\n\n if (activeTabEl && containerEl) {\n const containerRect = containerEl.getBoundingClientRect();\n const tabRect = activeTabEl.getBoundingClientRect();\n\n setIndicatorStyle({\n left: tabRect.left - containerRect.left,\n width: tabRect.width,\n initialized: true,\n });\n }\n }, [state.index]);\n\n /**\n * Focus a tab by its index\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n }\n }, []);\n\n /**\n * Navigate to a tab by index\n */\n const navigateToTab = useCallback(\n (index: number) => {\n const route = state.routes[index];\n if (route) {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n }\n },\n [state.routes, navigation]\n );\n\n /**\n * Handle keyboard navigation within the tab bar\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n let nextIndex: number | null = null;\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n nextIndex = currentIndex < tabCount - 1 ? currentIndex + 1 : 0;\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n nextIndex = currentIndex > 0 ? currentIndex - 1 : tabCount - 1;\n break;\n\n case \"Home\":\n e.preventDefault();\n nextIndex = 0;\n break;\n\n case \"End\":\n e.preventDefault();\n nextIndex = tabCount - 1;\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n navigateToTab(currentIndex);\n break;\n\n default:\n break;\n }\n\n if (nextIndex !== null) {\n focusTab(nextIndex);\n if (activateOnFocus) {\n navigateToTab(nextIndex);\n }\n }\n },\n [tabCount, focusTab, navigateToTab, activateOnFocus]\n );\n\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n aria-label={ariaLabel || \"Tab navigation\"}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n backgroundColor={backgroundColor || theme.colors.background.primary}\n borderRadius={4}\n height={56}\n width=\"100%\"\n position=\"relative\"\n overflow=\"hidden\"\n testID={testID || \"tab-bar-container\"}\n id={id}\n >\n {/* Sliding selection indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height=\"100%\"\n backgroundColor={theme.colors.content.primary}\n borderRadius={4}\n style={{\n left: indicatorStyle.left,\n width: indicatorStyle.width,\n transition: \"left 200ms ease-out, width 200ms ease-out\",\n pointerEvents: \"none\",\n }}\n aria-hidden\n />\n )}\n {state.routes.map((route, index) => {\n const { options } = descriptors[route.key];\n const label =\n options.tabBarShowLabel === false\n ? undefined\n : options.tabBarLabel !== undefined\n ? options.tabBarLabel\n : options.title !== undefined\n ? options.title\n : route.name;\n\n const isFocused = state.index === index;\n\n const onPress = () => {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!isFocused && !event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n };\n\n const onLongPress = () => {\n navigation.emit({\n type: \"tabLongPress\",\n target: route.key,\n });\n };\n\n // Use inverse color (white) when selected for floating design\n const iconColor = isFocused\n ? theme.colors.content.inverse\n : theme.colors.content.primary;\n\n const icon = options.tabBarIcon\n ? options.tabBarIcon({\n focused: isFocused,\n color: iconColor,\n size: 24,\n })\n : undefined;\n\n const badge = options.tabBarBadge;\n\n // Generate accessible label fallback\n const resolvedLabel =\n typeof label === \"function\"\n ? label({\n focused: isFocused,\n color: iconColor,\n position: labelPosition,\n })\n : label;\n\n // Use explicit accessibility label or fall back to text label\n const accessibilityLabel =\n options.tabBarAccessibilityLabel ||\n (typeof resolvedLabel === \"string\" ? resolvedLabel : route.name);\n\n // Generate unique tab ID\n const tabId = id ? `${id}-tab-${route.key}` : undefined;\n\n return (\n <TabBarItem\n key={route.key}\n id={tabId}\n label={resolvedLabel}\n icon={icon}\n badge={badge}\n focused={isFocused}\n onPress={onPress}\n onLongPress={onLongPress}\n labelPosition={labelPosition}\n accessibilityLabel={accessibilityLabel}\n testID={options.tabBarTestID}\n index={index}\n tabCount={tabCount}\n onKeyDown={handleKeyDown}\n tabRef={(el) => {\n tabRefs.current[index] = el;\n }}\n />\n );\n })}\n </Box>\n );\n};\n\nTabBar.displayName = \"TabBar\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport { Text as RNText, TextStyle, AccessibilityRole } from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\n// Map web roles to React Native accessibility roles\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n id,\n role,\n ...props\n}) => {\n // Extract the first font name from a comma-separated list (e.g. for web-style font stacks)\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n // On native, if we don't have the custom font loaded, fall back to the system font\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const style: TextStyle = {\n color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n };\n\n // Map role to React Native accessibilityRole\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText style={style} testID={id} accessibilityRole={accessibilityRole}>\n {children}\n </RNText>\n );\n};\n","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, { cloneElement, isValidElement, type ReactNode } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport type { TabBarItemProps } from \"./types\";\n\n/**\n * TabBarItem - An accessible tab item component\n *\n * Implements WAI-ARIA tab role with proper semantics:\n * - role=\"tab\" for tab semantics\n * - aria-selected to indicate active state\n * - tabIndex management for roving tabindex pattern\n * - Keyboard navigation support\n */\nexport const TabBarItem: React.FC<TabBarItemProps> = ({\n label,\n icon,\n badge,\n focused,\n onPress,\n onLongPress,\n labelPosition,\n accessibilityLabel,\n testID,\n id,\n index,\n onKeyDown,\n tabRef,\n}) => {\n const { theme } = useDesignSystem();\n\n // Use inverse color (white) when focused for floating design\n const color = focused\n ? theme.colors.content.inverse\n : theme.colors.content.primary;\n\n const renderIcon = () => {\n if (!icon) return null;\n\n return (\n <Box\n position=\"relative\"\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n >\n <Icon size={24} color={color}>\n {isValidElement(icon)\n ? cloneElement(icon as React.ReactElement<any>, {\n size: 24,\n color: color,\n stroke: color,\n })\n : icon}\n </Icon>\n {badge !== undefined && badge !== null && (\n <Box position=\"absolute\" top={-5} right={-10} zIndex={1}>\n <Badge\n size=\"sm\"\n aria-label={\n typeof badge === \"number\"\n ? `${badge} notifications`\n : String(badge)\n }\n >\n {badge}\n </Badge>\n </Box>\n )}\n </Box>\n );\n };\n\n const renderLabel = () => {\n if (typeof label === \"string\") {\n return (\n <Text\n color={color}\n fontSize={10}\n lineHeight={10}\n fontWeight=\"400\"\n numberOfLines={1}\n aria-hidden={true}\n >\n {label}\n </Text>\n );\n }\n return label as ReactNode;\n };\n\n /**\n * Handle keyboard events for this tab\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onKeyDown) {\n onKeyDown(e, index);\n }\n };\n\n return (\n <Box\n as=\"button\"\n role=\"tab\"\n id={id}\n aria-selected={focused}\n aria-label={accessibilityLabel}\n tabIndex={focused ? 0 : -1}\n ref={tabRef}\n flex={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n paddingVertical={8}\n cursor=\"pointer\"\n flexDirection={labelPosition === \"beside-icon\" ? \"row\" : \"column\"}\n gap={labelPosition === \"beside-icon\" ? 8 : 8}\n position=\"relative\"\n zIndex={1}\n borderRadius={4}\n onPress={onPress}\n onLongPress={onLongPress}\n onKeyDown={handleKeyDown}\n testID={testID}\n hoverStyle={\n focused\n ? undefined\n : {\n backgroundColor: theme.colors.overlay.mono,\n }\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n outlineStyle: \"solid\",\n }}\n >\n {renderIcon()}\n {renderLabel()}\n </Box>\n );\n};\n\nTabBarItem.displayName = \"TabBarItem\";\n"],"mappings":"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","names":["jsx","View","jsx","useDesignSystem","jsx","jsx","jsxs","useDesignSystem"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-tab-bar",
3
- "version": "0.102.0",
3
+ "version": "0.104.0",
4
4
  "main": "./web/index.js",
5
5
  "module": "./web/index.mjs",
6
6
  "types": "./web/index.d.ts",
@@ -13,9 +13,9 @@
13
13
  "test:coverage": "vitest run --coverage"
14
14
  },
15
15
  "dependencies": {
16
- "@xsolla/xui-badge": "0.102.0",
17
- "@xsolla/xui-core": "0.102.0",
18
- "@xsolla/xui-primitives-core": "0.102.0"
16
+ "@xsolla/xui-badge": "0.104.0",
17
+ "@xsolla/xui-core": "0.104.0",
18
+ "@xsolla/xui-primitives-core": "0.104.0"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "react": ">=16.8.0"
package/web/index.js CHANGED
@@ -214,7 +214,7 @@ var StyledText = import_styled_components2.default.span`
214
214
  color: ${(props) => props.color || "inherit"};
215
215
  font-size: ${(props) => typeof props.fontSize === "number" ? `${props.fontSize}px` : props.fontSize || "inherit"};
216
216
  font-weight: ${(props) => props.fontWeight || "normal"};
217
- font-family: ${(props) => props.fontFamily || '"Pilat Wide Bold", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important'};
217
+ font-family: ${(props) => props.fontFamily || '"Aktiv Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif'};
218
218
  line-height: ${(props) => typeof props.lineHeight === "number" ? `${props.lineHeight}px` : props.lineHeight || "inherit"};
219
219
  white-space: ${(props) => props.whiteSpace || "normal"};
220
220
  text-align: ${(props) => props.textAlign || "inherit"};
@@ -285,7 +285,7 @@ var TabBarItem = ({
285
285
  tabRef
286
286
  }) => {
287
287
  const { theme } = (0, import_xui_core.useDesignSystem)();
288
- const color = focused ? theme.colors.content.brand.primary : theme.colors.content.primary;
288
+ const color = focused ? theme.colors.content.inverse : theme.colors.content.primary;
289
289
  const renderIcon = () => {
290
290
  if (!icon) return null;
291
291
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
@@ -319,8 +319,9 @@ var TabBarItem = ({
319
319
  Text,
320
320
  {
321
321
  color,
322
- fontSize: 12,
323
- fontWeight: focused ? "600" : "400",
322
+ fontSize: 10,
323
+ lineHeight: 10,
324
+ fontWeight: "400",
324
325
  numberOfLines: 1,
325
326
  "aria-hidden": true,
326
327
  children: label
@@ -350,12 +351,15 @@ var TabBarItem = ({
350
351
  paddingVertical: 8,
351
352
  cursor: "pointer",
352
353
  flexDirection: labelPosition === "beside-icon" ? "row" : "column",
353
- gap: labelPosition === "beside-icon" ? 8 : 4,
354
+ gap: labelPosition === "beside-icon" ? 8 : 8,
355
+ position: "relative",
356
+ zIndex: 1,
357
+ borderRadius: 4,
354
358
  onPress,
355
359
  onLongPress,
356
360
  onKeyDown: handleKeyDown,
357
361
  testID,
358
- hoverStyle: {
362
+ hoverStyle: focused ? void 0 : {
359
363
  backgroundColor: theme.colors.overlay.mono
360
364
  },
361
365
  focusStyle: {
@@ -389,7 +393,24 @@ var TabBar = ({
389
393
  }) => {
390
394
  const { theme } = (0, import_xui_core2.useDesignSystem)();
391
395
  const tabRefs = (0, import_react3.useRef)([]);
396
+ const containerRef = (0, import_react3.useRef)(null);
392
397
  const tabCount = state.routes.length;
398
+ const [indicatorStyle, setIndicatorStyle] = (0, import_react3.useState)({ left: 0, width: 0, initialized: false });
399
+ (0, import_react3.useEffect)(() => {
400
+ if (!import_xui_core2.isWeb) return;
401
+ const activeIndex = state.index;
402
+ const activeTabEl = tabRefs.current[activeIndex];
403
+ const containerEl = containerRef.current;
404
+ if (activeTabEl && containerEl) {
405
+ const containerRect = containerEl.getBoundingClientRect();
406
+ const tabRect = activeTabEl.getBoundingClientRect();
407
+ setIndicatorStyle({
408
+ left: tabRect.left - containerRect.left,
409
+ width: tabRect.width,
410
+ initialized: true
411
+ });
412
+ }
413
+ }, [state.index]);
393
414
  const focusTab = (0, import_react3.useCallback)((index) => {
394
415
  const tabElement = tabRefs.current[index];
395
416
  if (tabElement) {
@@ -451,7 +472,7 @@ var TabBar = ({
451
472
  },
452
473
  [tabCount, focusTab, navigateToTab, activateOnFocus]
453
474
  );
454
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
475
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
455
476
  Box,
456
477
  {
457
478
  as: "nav",
@@ -459,71 +480,94 @@ var TabBar = ({
459
480
  "aria-label": ariaLabel || "Tab navigation",
460
481
  "aria-labelledby": ariaLabelledBy,
461
482
  "aria-orientation": "horizontal",
483
+ ref: (el) => {
484
+ containerRef.current = el;
485
+ },
462
486
  flexDirection: "row",
463
487
  backgroundColor: backgroundColor || theme.colors.background.primary,
464
- borderTopWidth: 1,
465
- borderTopColor: theme.colors.border.secondary,
466
- borderStyle: "solid",
467
- height: 60,
488
+ borderRadius: 4,
489
+ height: 56,
468
490
  width: "100%",
491
+ position: "relative",
492
+ overflow: "hidden",
469
493
  testID: testID || "tab-bar-container",
470
494
  id,
471
- children: state.routes.map((route, index) => {
472
- const { options } = descriptors[route.key];
473
- const label = options.tabBarShowLabel === false ? void 0 : options.tabBarLabel !== void 0 ? options.tabBarLabel : options.title !== void 0 ? options.title : route.name;
474
- const isFocused = state.index === index;
475
- const onPress = () => {
476
- const event = navigation.emit({
477
- type: "tabPress",
478
- target: route.key,
479
- canPreventDefault: true
480
- });
481
- if (!isFocused && !event.defaultPrevented) {
482
- navigation.navigate(route.name, route.params);
483
- }
484
- };
485
- const onLongPress = () => {
486
- navigation.emit({
487
- type: "tabLongPress",
488
- target: route.key
489
- });
490
- };
491
- const icon = options.tabBarIcon ? options.tabBarIcon({
492
- focused: isFocused,
493
- color: isFocused ? theme.colors.content.brand.primary : theme.colors.content.primary,
494
- size: 24
495
- }) : void 0;
496
- const badge = options.tabBarBadge;
497
- const resolvedLabel = typeof label === "function" ? label({
498
- focused: isFocused,
499
- color: isFocused ? theme.colors.content.brand.primary : theme.colors.content.primary,
500
- position: labelPosition
501
- }) : label;
502
- const accessibilityLabel = options.tabBarAccessibilityLabel || (typeof resolvedLabel === "string" ? resolvedLabel : route.name);
503
- const tabId = id ? `${id}-tab-${route.key}` : void 0;
504
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
505
- TabBarItem,
495
+ children: [
496
+ import_xui_core2.isWeb && indicatorStyle.initialized && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
497
+ Box,
506
498
  {
507
- id: tabId,
508
- label: resolvedLabel,
509
- icon,
510
- badge,
511
- focused: isFocused,
512
- onPress,
513
- onLongPress,
514
- labelPosition,
515
- accessibilityLabel,
516
- testID: options.tabBarTestID,
517
- index,
518
- tabCount,
519
- onKeyDown: handleKeyDown,
520
- tabRef: (el) => {
521
- tabRefs.current[index] = el;
499
+ position: "absolute",
500
+ zIndex: 0,
501
+ height: "100%",
502
+ backgroundColor: theme.colors.content.primary,
503
+ borderRadius: 4,
504
+ style: {
505
+ left: indicatorStyle.left,
506
+ width: indicatorStyle.width,
507
+ transition: "left 200ms ease-out, width 200ms ease-out",
508
+ pointerEvents: "none"
509
+ },
510
+ "aria-hidden": true
511
+ }
512
+ ),
513
+ state.routes.map((route, index) => {
514
+ const { options } = descriptors[route.key];
515
+ const label = options.tabBarShowLabel === false ? void 0 : options.tabBarLabel !== void 0 ? options.tabBarLabel : options.title !== void 0 ? options.title : route.name;
516
+ const isFocused = state.index === index;
517
+ const onPress = () => {
518
+ const event = navigation.emit({
519
+ type: "tabPress",
520
+ target: route.key,
521
+ canPreventDefault: true
522
+ });
523
+ if (!isFocused && !event.defaultPrevented) {
524
+ navigation.navigate(route.name, route.params);
522
525
  }
523
- },
524
- route.key
525
- );
526
- })
526
+ };
527
+ const onLongPress = () => {
528
+ navigation.emit({
529
+ type: "tabLongPress",
530
+ target: route.key
531
+ });
532
+ };
533
+ const iconColor = isFocused ? theme.colors.content.inverse : theme.colors.content.primary;
534
+ const icon = options.tabBarIcon ? options.tabBarIcon({
535
+ focused: isFocused,
536
+ color: iconColor,
537
+ size: 24
538
+ }) : void 0;
539
+ const badge = options.tabBarBadge;
540
+ const resolvedLabel = typeof label === "function" ? label({
541
+ focused: isFocused,
542
+ color: iconColor,
543
+ position: labelPosition
544
+ }) : label;
545
+ const accessibilityLabel = options.tabBarAccessibilityLabel || (typeof resolvedLabel === "string" ? resolvedLabel : route.name);
546
+ const tabId = id ? `${id}-tab-${route.key}` : void 0;
547
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
548
+ TabBarItem,
549
+ {
550
+ id: tabId,
551
+ label: resolvedLabel,
552
+ icon,
553
+ badge,
554
+ focused: isFocused,
555
+ onPress,
556
+ onLongPress,
557
+ labelPosition,
558
+ accessibilityLabel,
559
+ testID: options.tabBarTestID,
560
+ index,
561
+ tabCount,
562
+ onKeyDown: handleKeyDown,
563
+ tabRef: (el) => {
564
+ tabRefs.current[index] = el;
565
+ }
566
+ },
567
+ route.key
568
+ );
569
+ })
570
+ ]
527
571
  }
528
572
  );
529
573
  };
package/web/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/TabBar.tsx","../../../primitives-web/src/Box.tsx","../../../primitives-web/src/Text.tsx","../../../primitives-web/src/Icon.tsx","../../src/TabBarItem.tsx"],"sourcesContent":["export * from \"./TabBar\";\nexport * from \"./TabBarItem\";\nexport * from \"./types\";\n","import React, { useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { TabBarItem } from \"./TabBarItem\";\nimport type { TabBarProps } from \"./types\";\n\n/**\n * TabBar - An accessible tab bar navigation component\n *\n * Implements WAI-ARIA Tabs pattern with proper keyboard navigation:\n * - Arrow Left/Right: Navigate between tabs\n * - Home: Jump to first tab\n * - End: Jump to last tab\n * - Enter/Space: Activate focused tab (when activateOnFocus is false)\n *\n * @example\n * ```tsx\n * <TabBar\n * state={navigationState}\n * descriptors={descriptors}\n * navigation={navigation}\n * aria-label=\"Main navigation\"\n * />\n * ```\n */\nexport const TabBar: React.FC<TabBarProps> = ({\n state,\n descriptors,\n navigation,\n labelPosition = \"below-icon\",\n backgroundColor,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n id,\n activateOnFocus = true,\n}) => {\n const { theme } = useDesignSystem();\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const tabCount = state.routes.length;\n\n /**\n * Focus a tab by its index\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n }\n }, []);\n\n /**\n * Navigate to a tab by index\n */\n const navigateToTab = useCallback(\n (index: number) => {\n const route = state.routes[index];\n if (route) {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n }\n },\n [state.routes, navigation]\n );\n\n /**\n * Handle keyboard navigation within the tab bar\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n let nextIndex: number | null = null;\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n nextIndex = currentIndex < tabCount - 1 ? currentIndex + 1 : 0;\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n nextIndex = currentIndex > 0 ? currentIndex - 1 : tabCount - 1;\n break;\n\n case \"Home\":\n e.preventDefault();\n nextIndex = 0;\n break;\n\n case \"End\":\n e.preventDefault();\n nextIndex = tabCount - 1;\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n navigateToTab(currentIndex);\n break;\n\n default:\n break;\n }\n\n if (nextIndex !== null) {\n focusTab(nextIndex);\n if (activateOnFocus) {\n navigateToTab(nextIndex);\n }\n }\n },\n [tabCount, focusTab, navigateToTab, activateOnFocus]\n );\n\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n aria-label={ariaLabel || \"Tab navigation\"}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n flexDirection=\"row\"\n backgroundColor={backgroundColor || theme.colors.background.primary}\n borderTopWidth={1}\n borderTopColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n height={60}\n width=\"100%\"\n testID={testID || \"tab-bar-container\"}\n id={id}\n >\n {state.routes.map((route, index) => {\n const { options } = descriptors[route.key];\n const label =\n options.tabBarShowLabel === false\n ? undefined\n : options.tabBarLabel !== undefined\n ? options.tabBarLabel\n : options.title !== undefined\n ? options.title\n : route.name;\n\n const isFocused = state.index === index;\n\n const onPress = () => {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!isFocused && !event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n };\n\n const onLongPress = () => {\n navigation.emit({\n type: \"tabLongPress\",\n target: route.key,\n });\n };\n\n const icon = options.tabBarIcon\n ? options.tabBarIcon({\n focused: isFocused,\n color: isFocused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary,\n size: 24,\n })\n : undefined;\n\n const badge = options.tabBarBadge;\n\n // Generate accessible label fallback\n const resolvedLabel =\n typeof label === \"function\"\n ? label({\n focused: isFocused,\n color: isFocused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary,\n position: labelPosition,\n })\n : label;\n\n // Use explicit accessibility label or fall back to text label\n const accessibilityLabel =\n options.tabBarAccessibilityLabel ||\n (typeof resolvedLabel === \"string\" ? resolvedLabel : route.name);\n\n // Generate unique tab ID\n const tabId = id ? `${id}-tab-${route.key}` : undefined;\n\n return (\n <TabBarItem\n key={route.key}\n id={tabId}\n label={resolvedLabel}\n icon={icon}\n badge={badge}\n focused={isFocused}\n onPress={onPress}\n onLongPress={onLongPress}\n labelPosition={labelPosition}\n accessibilityLabel={accessibilityLabel}\n testID={options.tabBarTestID}\n index={index}\n tabCount={tabCount}\n onKeyDown={handleKeyDown}\n tabRef={(el) => {\n tabRefs.current[index] = el;\n }}\n />\n );\n })}\n </Box>\n );\n};\n\nTabBar.displayName = \"TabBar\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledBox = styled.div<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n overflow: ${(props) => props.overflow || \"visible\"};\n overflow-x: ${(props) => props.overflowX || \"visible\"};\n overflow-y: ${(props) => props.overflowY || \"visible\"};\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) => (props.disabled ? 0.5 : 1)};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n &:hover {\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n type,\n disabled,\n id,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n as={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledText = styled.span<TextProps>`\n color: ${(props) => props.color || \"inherit\"};\n font-size: ${(props) =>\n typeof props.fontSize === \"number\"\n ? `${props.fontSize}px`\n : props.fontSize || \"inherit\"};\n font-weight: ${(props) => props.fontWeight || \"normal\"};\n font-family: ${(props) =>\n props.fontFamily ||\n '\"Pilat Wide Bold\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif !important'};\n line-height: ${(props) =>\n typeof props.lineHeight === \"number\"\n ? `${props.lineHeight}px`\n : props.lineHeight || \"inherit\"};\n white-space: ${(props) => props.whiteSpace || \"normal\"};\n text-align: ${(props) => props.textAlign || \"inherit\"};\n text-decoration: ${(props) => props.textDecoration || \"none\"};\n`;\n\nexport const Text: React.FC<TextProps> = ({\n style,\n className,\n id,\n role,\n ...props\n}) => {\n return (\n <StyledText\n {...props}\n style={style}\n className={className}\n id={id}\n role={role}\n />\n );\n};\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledIcon = styled.div<IconProps>`\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n height: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n color: ${(props) => props.color || \"currentColor\"};\n\n svg {\n width: 100%;\n height: 100%;\n fill: none;\n stroke: currentColor;\n }\n`;\n\nexport const Icon: React.FC<IconProps> = ({ children, ...props }) => {\n return <StyledIcon {...props}>{children}</StyledIcon>;\n};\n","import React, { cloneElement, isValidElement, type ReactNode } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport type { TabBarItemProps } from \"./types\";\n\n/**\n * TabBarItem - An accessible tab item component\n *\n * Implements WAI-ARIA tab role with proper semantics:\n * - role=\"tab\" for tab semantics\n * - aria-selected to indicate active state\n * - tabIndex management for roving tabindex pattern\n * - Keyboard navigation support\n */\nexport const TabBarItem: React.FC<TabBarItemProps> = ({\n label,\n icon,\n badge,\n focused,\n onPress,\n onLongPress,\n labelPosition,\n accessibilityLabel,\n testID,\n id,\n index,\n onKeyDown,\n tabRef,\n}) => {\n const { theme } = useDesignSystem();\n\n const color = focused\n ? theme.colors.content.brand.primary\n : theme.colors.content.primary;\n\n const renderIcon = () => {\n if (!icon) return null;\n\n return (\n <Box\n position=\"relative\"\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n >\n <Icon size={24} color={color}>\n {isValidElement(icon)\n ? cloneElement(icon as React.ReactElement<any>, {\n size: 24,\n color: color,\n stroke: color,\n })\n : icon}\n </Icon>\n {badge !== undefined && badge !== null && (\n <Box position=\"absolute\" top={-5} right={-10} zIndex={1}>\n <Badge\n size=\"sm\"\n aria-label={\n typeof badge === \"number\"\n ? `${badge} notifications`\n : String(badge)\n }\n >\n {badge}\n </Badge>\n </Box>\n )}\n </Box>\n );\n };\n\n const renderLabel = () => {\n if (typeof label === \"string\") {\n return (\n <Text\n color={color}\n fontSize={12}\n fontWeight={focused ? \"600\" : \"400\"}\n numberOfLines={1}\n aria-hidden={true}\n >\n {label}\n </Text>\n );\n }\n return label as ReactNode;\n };\n\n /**\n * Handle keyboard events for this tab\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onKeyDown) {\n onKeyDown(e, index);\n }\n };\n\n return (\n <Box\n as=\"button\"\n role=\"tab\"\n id={id}\n aria-selected={focused}\n aria-label={accessibilityLabel}\n tabIndex={focused ? 0 : -1}\n ref={tabRef}\n flex={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n paddingVertical={8}\n cursor=\"pointer\"\n flexDirection={labelPosition === \"beside-icon\" ? \"row\" : \"column\"}\n gap={labelPosition === \"beside-icon\" ? 8 : 4}\n onPress={onPress}\n onLongPress={onLongPress}\n onKeyDown={handleKeyDown}\n testID={testID}\n hoverStyle={{\n backgroundColor: theme.colors.overlay.mono,\n }}\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n outlineStyle: \"solid\",\n }}\n >\n {renderIcon()}\n {renderLabel()}\n </Box>\n );\n};\n\nTabBarItem.displayName = \"TabBarItem\";\n"],"mappings":"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","names":["import_react","styled","React","import_styled_components","import_jsx_runtime","styled","import_styled_components","import_jsx_runtime","styled","import_xui_core","import_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/TabBar.tsx","../../../primitives-web/src/Box.tsx","../../../primitives-web/src/Text.tsx","../../../primitives-web/src/Icon.tsx","../../src/TabBarItem.tsx"],"sourcesContent":["export * from \"./TabBar\";\nexport * from \"./TabBarItem\";\nexport * from \"./types\";\n","import React, { useRef, useCallback, useState, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem, isWeb } from \"@xsolla/xui-core\";\nimport { TabBarItem } from \"./TabBarItem\";\nimport type { TabBarProps } from \"./types\";\n\n/**\n * TabBar - An accessible tab bar navigation component\n *\n * Implements WAI-ARIA Tabs pattern with proper keyboard navigation:\n * - Arrow Left/Right: Navigate between tabs\n * - Home: Jump to first tab\n * - End: Jump to last tab\n * - Enter/Space: Activate focused tab (when activateOnFocus is false)\n *\n * @example\n * ```tsx\n * <TabBar\n * state={navigationState}\n * descriptors={descriptors}\n * navigation={navigation}\n * aria-label=\"Main navigation\"\n * />\n * ```\n */\nexport const TabBar: React.FC<TabBarProps> = ({\n state,\n descriptors,\n navigation,\n labelPosition = \"below-icon\",\n backgroundColor,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n id,\n activateOnFocus = true,\n}) => {\n const { theme } = useDesignSystem();\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n const tabCount = state.routes.length;\n\n // Indicator position for sliding selection animation\n const [indicatorStyle, setIndicatorStyle] = useState<{\n left: number;\n width: number;\n initialized: boolean;\n }>({ left: 0, width: 0, initialized: false });\n\n // Update indicator position when active tab changes (web only)\n useEffect(() => {\n if (!isWeb) return;\n\n const activeIndex = state.index;\n const activeTabEl = tabRefs.current[activeIndex];\n const containerEl = containerRef.current;\n\n if (activeTabEl && containerEl) {\n const containerRect = containerEl.getBoundingClientRect();\n const tabRect = activeTabEl.getBoundingClientRect();\n\n setIndicatorStyle({\n left: tabRect.left - containerRect.left,\n width: tabRect.width,\n initialized: true,\n });\n }\n }, [state.index]);\n\n /**\n * Focus a tab by its index\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n }\n }, []);\n\n /**\n * Navigate to a tab by index\n */\n const navigateToTab = useCallback(\n (index: number) => {\n const route = state.routes[index];\n if (route) {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n }\n },\n [state.routes, navigation]\n );\n\n /**\n * Handle keyboard navigation within the tab bar\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n let nextIndex: number | null = null;\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n nextIndex = currentIndex < tabCount - 1 ? currentIndex + 1 : 0;\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n nextIndex = currentIndex > 0 ? currentIndex - 1 : tabCount - 1;\n break;\n\n case \"Home\":\n e.preventDefault();\n nextIndex = 0;\n break;\n\n case \"End\":\n e.preventDefault();\n nextIndex = tabCount - 1;\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n navigateToTab(currentIndex);\n break;\n\n default:\n break;\n }\n\n if (nextIndex !== null) {\n focusTab(nextIndex);\n if (activateOnFocus) {\n navigateToTab(nextIndex);\n }\n }\n },\n [tabCount, focusTab, navigateToTab, activateOnFocus]\n );\n\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n aria-label={ariaLabel || \"Tab navigation\"}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n backgroundColor={backgroundColor || theme.colors.background.primary}\n borderRadius={4}\n height={56}\n width=\"100%\"\n position=\"relative\"\n overflow=\"hidden\"\n testID={testID || \"tab-bar-container\"}\n id={id}\n >\n {/* Sliding selection indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height=\"100%\"\n backgroundColor={theme.colors.content.primary}\n borderRadius={4}\n style={{\n left: indicatorStyle.left,\n width: indicatorStyle.width,\n transition: \"left 200ms ease-out, width 200ms ease-out\",\n pointerEvents: \"none\",\n }}\n aria-hidden\n />\n )}\n {state.routes.map((route, index) => {\n const { options } = descriptors[route.key];\n const label =\n options.tabBarShowLabel === false\n ? undefined\n : options.tabBarLabel !== undefined\n ? options.tabBarLabel\n : options.title !== undefined\n ? options.title\n : route.name;\n\n const isFocused = state.index === index;\n\n const onPress = () => {\n const event = navigation.emit({\n type: \"tabPress\",\n target: route.key,\n canPreventDefault: true,\n });\n\n if (!isFocused && !event.defaultPrevented) {\n navigation.navigate(route.name, route.params);\n }\n };\n\n const onLongPress = () => {\n navigation.emit({\n type: \"tabLongPress\",\n target: route.key,\n });\n };\n\n // Use inverse color (white) when selected for floating design\n const iconColor = isFocused\n ? theme.colors.content.inverse\n : theme.colors.content.primary;\n\n const icon = options.tabBarIcon\n ? options.tabBarIcon({\n focused: isFocused,\n color: iconColor,\n size: 24,\n })\n : undefined;\n\n const badge = options.tabBarBadge;\n\n // Generate accessible label fallback\n const resolvedLabel =\n typeof label === \"function\"\n ? label({\n focused: isFocused,\n color: iconColor,\n position: labelPosition,\n })\n : label;\n\n // Use explicit accessibility label or fall back to text label\n const accessibilityLabel =\n options.tabBarAccessibilityLabel ||\n (typeof resolvedLabel === \"string\" ? resolvedLabel : route.name);\n\n // Generate unique tab ID\n const tabId = id ? `${id}-tab-${route.key}` : undefined;\n\n return (\n <TabBarItem\n key={route.key}\n id={tabId}\n label={resolvedLabel}\n icon={icon}\n badge={badge}\n focused={isFocused}\n onPress={onPress}\n onLongPress={onLongPress}\n labelPosition={labelPosition}\n accessibilityLabel={accessibilityLabel}\n testID={options.tabBarTestID}\n index={index}\n tabCount={tabCount}\n onKeyDown={handleKeyDown}\n tabRef={(el) => {\n tabRefs.current[index] = el;\n }}\n />\n );\n })}\n </Box>\n );\n};\n\nTabBar.displayName = \"TabBar\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledBox = styled.div<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n overflow: ${(props) => props.overflow || \"visible\"};\n overflow-x: ${(props) => props.overflowX || \"visible\"};\n overflow-y: ${(props) => props.overflowY || \"visible\"};\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) => (props.disabled ? 0.5 : 1)};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n &:hover {\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n type,\n disabled,\n id,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n as={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledText = styled.span<TextProps>`\n color: ${(props) => props.color || \"inherit\"};\n font-size: ${(props) =>\n typeof props.fontSize === \"number\"\n ? `${props.fontSize}px`\n : props.fontSize || \"inherit\"};\n font-weight: ${(props) => props.fontWeight || \"normal\"};\n font-family: ${(props) =>\n props.fontFamily ||\n '\"Aktiv Grotesk\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif'};\n line-height: ${(props) =>\n typeof props.lineHeight === \"number\"\n ? `${props.lineHeight}px`\n : props.lineHeight || \"inherit\"};\n white-space: ${(props) => props.whiteSpace || \"normal\"};\n text-align: ${(props) => props.textAlign || \"inherit\"};\n text-decoration: ${(props) => props.textDecoration || \"none\"};\n`;\n\nexport const Text: React.FC<TextProps> = ({\n style,\n className,\n id,\n role,\n ...props\n}) => {\n return (\n <StyledText\n {...props}\n style={style}\n className={className}\n id={id}\n role={role}\n />\n );\n};\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nconst StyledIcon = styled.div<IconProps>`\n display: flex;\n align-items: center;\n justify-content: center;\n width: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n height: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n color: ${(props) => props.color || \"currentColor\"};\n\n svg {\n width: 100%;\n height: 100%;\n fill: none;\n stroke: currentColor;\n }\n`;\n\nexport const Icon: React.FC<IconProps> = ({ children, ...props }) => {\n return <StyledIcon {...props}>{children}</StyledIcon>;\n};\n","import React, { cloneElement, isValidElement, type ReactNode } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\nimport type { TabBarItemProps } from \"./types\";\n\n/**\n * TabBarItem - An accessible tab item component\n *\n * Implements WAI-ARIA tab role with proper semantics:\n * - role=\"tab\" for tab semantics\n * - aria-selected to indicate active state\n * - tabIndex management for roving tabindex pattern\n * - Keyboard navigation support\n */\nexport const TabBarItem: React.FC<TabBarItemProps> = ({\n label,\n icon,\n badge,\n focused,\n onPress,\n onLongPress,\n labelPosition,\n accessibilityLabel,\n testID,\n id,\n index,\n onKeyDown,\n tabRef,\n}) => {\n const { theme } = useDesignSystem();\n\n // Use inverse color (white) when focused for floating design\n const color = focused\n ? theme.colors.content.inverse\n : theme.colors.content.primary;\n\n const renderIcon = () => {\n if (!icon) return null;\n\n return (\n <Box\n position=\"relative\"\n alignItems=\"center\"\n justifyContent=\"center\"\n aria-hidden={true}\n >\n <Icon size={24} color={color}>\n {isValidElement(icon)\n ? cloneElement(icon as React.ReactElement<any>, {\n size: 24,\n color: color,\n stroke: color,\n })\n : icon}\n </Icon>\n {badge !== undefined && badge !== null && (\n <Box position=\"absolute\" top={-5} right={-10} zIndex={1}>\n <Badge\n size=\"sm\"\n aria-label={\n typeof badge === \"number\"\n ? `${badge} notifications`\n : String(badge)\n }\n >\n {badge}\n </Badge>\n </Box>\n )}\n </Box>\n );\n };\n\n const renderLabel = () => {\n if (typeof label === \"string\") {\n return (\n <Text\n color={color}\n fontSize={10}\n lineHeight={10}\n fontWeight=\"400\"\n numberOfLines={1}\n aria-hidden={true}\n >\n {label}\n </Text>\n );\n }\n return label as ReactNode;\n };\n\n /**\n * Handle keyboard events for this tab\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onKeyDown) {\n onKeyDown(e, index);\n }\n };\n\n return (\n <Box\n as=\"button\"\n role=\"tab\"\n id={id}\n aria-selected={focused}\n aria-label={accessibilityLabel}\n tabIndex={focused ? 0 : -1}\n ref={tabRef}\n flex={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n paddingVertical={8}\n cursor=\"pointer\"\n flexDirection={labelPosition === \"beside-icon\" ? \"row\" : \"column\"}\n gap={labelPosition === \"beside-icon\" ? 8 : 8}\n position=\"relative\"\n zIndex={1}\n borderRadius={4}\n onPress={onPress}\n onLongPress={onLongPress}\n onKeyDown={handleKeyDown}\n testID={testID}\n hoverStyle={\n focused\n ? undefined\n : {\n backgroundColor: theme.colors.overlay.mono,\n }\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n outlineStyle: \"solid\",\n }}\n >\n {renderIcon()}\n {renderLabel()}\n </Box>\n );\n};\n\nTabBarItem.displayName = \"TabBarItem\";\n"],"mappings":"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","names":["import_react","styled","React","import_styled_components","import_jsx_runtime","styled","import_styled_components","import_jsx_runtime","styled","import_xui_core","import_react","import_jsx_runtime","import_jsx_runtime"]}