@xsolla/xui-tabs 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,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { ThemeOverrideProps } from '@xsolla/xui-core';
2
3
 
3
4
  interface TabItemType {
4
5
  /** Unique identifier for the tab */
@@ -16,7 +17,7 @@ interface TabItemType {
16
17
  /** Accessible label for screen readers (defaults to label) */
17
18
  "aria-label"?: string;
18
19
  }
19
- interface TabsProps {
20
+ interface TabsProps extends ThemeOverrideProps {
20
21
  /** Array of tab items */
21
22
  tabs: TabItemType[];
22
23
  /** ID of the currently active tab */
package/native/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { ThemeOverrideProps } from '@xsolla/xui-core';
2
3
 
3
4
  interface TabItemType {
4
5
  /** Unique identifier for the tab */
@@ -16,7 +17,7 @@ interface TabItemType {
16
17
  /** Accessible label for screen readers (defaults to label) */
17
18
  "aria-label"?: string;
18
19
  }
19
- interface TabsProps {
20
+ interface TabsProps extends ThemeOverrideProps {
20
21
  /** Array of tab items */
21
22
  tabs: TabItemType[];
22
23
  /** ID of the currently active tab */
package/native/index.js CHANGED
@@ -81,6 +81,10 @@ var Box = ({
81
81
  left,
82
82
  right,
83
83
  width,
84
+ minWidth,
85
+ minHeight,
86
+ maxWidth,
87
+ maxHeight,
84
88
  flex,
85
89
  overflow,
86
90
  zIndex,
@@ -112,6 +116,10 @@ var Box = ({
112
116
  zIndex,
113
117
  height,
114
118
  width,
119
+ minWidth,
120
+ minHeight,
121
+ maxWidth,
122
+ maxHeight,
115
123
  padding,
116
124
  paddingHorizontal,
117
125
  paddingVertical,
@@ -240,7 +248,7 @@ var Text = ({
240
248
  }
241
249
  const incomingStyle = import_react_native2.StyleSheet.flatten(styleProp);
242
250
  const baseStyle = {
243
- color,
251
+ color: color ?? incomingStyle?.color,
244
252
  fontSize: typeof fontSize === "number" ? fontSize : void 0,
245
253
  fontWeight,
246
254
  fontFamily: resolvedFontFamily,
@@ -295,7 +303,6 @@ var Icon = ({ children, color, size }) => {
295
303
  var import_xui_core = require("@xsolla/xui-core");
296
304
  var import_xui_badge = require("@xsolla/xui-badge");
297
305
  var import_jsx_runtime4 = require("react/jsx-runtime");
298
- var isWeb = typeof document !== "undefined";
299
306
  var Tabs = ({
300
307
  tabs,
301
308
  activeTabId,
@@ -308,9 +315,11 @@ var Tabs = ({
308
315
  "aria-labelledby": ariaLabelledBy,
309
316
  activateOnFocus = true,
310
317
  id,
311
- testID
318
+ testID,
319
+ themeMode,
320
+ themeProductContext
312
321
  }) => {
313
- const { theme } = (0, import_xui_core.useDesignSystem)();
322
+ const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
314
323
  const isSegmented = variant === "segmented";
315
324
  const tabListId = id ? `${id}-tablist` : void 0;
316
325
  const [_focusedIndex, setFocusedIndex] = (0, import_react2.useState)(-1);
@@ -318,7 +327,7 @@ var Tabs = ({
318
327
  const containerRef = (0, import_react2.useRef)(null);
319
328
  const [indicatorStyle, setIndicatorStyle] = (0, import_react2.useState)({ left: 0, width: 0, initialized: false });
320
329
  (0, import_react2.useEffect)(() => {
321
- if (!isSegmented || !isWeb) return;
330
+ if (!isSegmented || !import_xui_core.isWeb) return;
322
331
  const activeIndex = tabs.findIndex((tab) => tab.id === activeTabId);
323
332
  const activeTabEl = tabRefs.current[activeIndex];
324
333
  const containerEl = containerRef.current;
@@ -336,7 +345,7 @@ var Tabs = ({
336
345
  const focusTab = (0, import_react2.useCallback)((index) => {
337
346
  const tabElement = tabRefs.current[index];
338
347
  if (tabElement) {
339
- tabElement.focus();
348
+ tabElement.focus?.();
340
349
  setFocusedIndex(index);
341
350
  }
342
351
  }, []);
@@ -418,14 +427,15 @@ var Tabs = ({
418
427
  alignItems: "center",
419
428
  flexShrink: 0,
420
429
  position: "relative",
421
- width: stretched ? "100%" : "fit-content",
430
+ width: stretched ? "100%" : import_xui_core.isWeb ? "fit-content" : void 0,
431
+ alignSelf: !stretched && !import_xui_core.isWeb ? "flex-start" : void 0,
422
432
  height: segmentedStyles.height,
423
433
  backgroundColor: theme.colors.control.segmented.bg,
424
434
  borderRadius: segmentedStyles.containerRadius,
425
435
  padding: segmentedStyles.containerPadding,
426
436
  overflow: "hidden",
427
437
  children: [
428
- isWeb && indicatorStyle.initialized && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
438
+ import_xui_core.isWeb && indicatorStyle.initialized && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
429
439
  Box,
430
440
  {
431
441
  position: "absolute",
@@ -485,7 +495,7 @@ var Tabs = ({
485
495
  alignItems: "center",
486
496
  justifyContent: "center",
487
497
  gap: segmentedStyles.gap,
488
- backgroundColor: !isWeb && isActive ? theme.colors.control.segmented.bgActive : "transparent",
498
+ backgroundColor: !import_xui_core.isWeb && isActive ? theme.colors.control.segmented.bgActive : "transparent",
489
499
  borderRadius: segmentedStyles.itemRadius,
490
500
  cursor: isDisabled ? "not-allowed" : "pointer",
491
501
  hoverStyle: !isDisabled && !isActive ? {
@@ -552,7 +562,8 @@ var Tabs = ({
552
562
  flexDirection: "row",
553
563
  alignItems: "flex-end",
554
564
  justifyContent: alignLeft ? "flex-start" : "center",
555
- width: stretched ? "100%" : "fit-content",
565
+ width: stretched ? "100%" : import_xui_core.isWeb ? "fit-content" : void 0,
566
+ alignSelf: !stretched && !import_xui_core.isWeb ? "flex-start" : void 0,
556
567
  height: lineStyles.height,
557
568
  borderBottomWidth: 1,
558
569
  borderBottomColor: theme.colors.border.secondary,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/Tabs.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx"],"sourcesContent":["export * from \"./Tabs\";\n","import React, { useState, useRef, useCallback, useEffect } 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\";\n\n// Platform detection without importing react-native directly\nconst isWeb = typeof document !== \"undefined\";\n\nexport interface TabItemType {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n /** Optional icon to display before the label */\n icon?: React.ReactNode;\n /** Optional counter to display after the label */\n counter?: string | number;\n /** Optional badge to display */\n badge?: boolean | string | number;\n /** Whether the tab is disabled */\n disabled?: boolean;\n /** Accessible label for screen readers (defaults to label) */\n \"aria-label\"?: string;\n}\n\nexport interface TabsProps {\n /** Array of tab items */\n tabs: TabItemType[];\n /** ID of the currently active tab */\n activeTabId?: string;\n /** Callback when a tab is selected */\n onChange?: (id: string) => void;\n /** Size variant of the tabs */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\";\n /** Visual variant of the tabs */\n variant?: \"line\" | \"segmented\";\n /** Whether to align tabs to the left (only for line variant) */\n alignLeft?: boolean;\n /** Whether the component should stretch to fill its container */\n stretched?: boolean;\n /** Accessible label for the tab list */\n \"aria-label\"?: string;\n /** ID of element that labels this tab list */\n \"aria-labelledby\"?: string;\n /** Whether keyboard navigation should automatically activate tabs */\n activateOnFocus?: boolean;\n /** HTML id attribute */\n id?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\n/**\n * Tabs - An accessible tabbed interface 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 * Variants:\n * - \"line\" (default): Traditional underlined tabs\n * - \"segmented\": Button-group style segmented control\n */\nexport const Tabs: React.FC<TabsProps> = ({\n tabs,\n activeTabId,\n onChange,\n size = \"md\",\n variant = \"line\",\n alignLeft = true,\n stretched = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n activateOnFocus = true,\n id,\n testID,\n}) => {\n const { theme } = useDesignSystem();\n const isSegmented = variant === \"segmented\";\n const tabListId = id ? `${id}-tablist` : undefined;\n\n // Track focused tab for keyboard navigation\n const [_focusedIndex, setFocusedIndex] = useState<number>(-1);\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n\n // Indicator position for segmented variant 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 (!isSegmented || !isWeb) return;\n\n const activeIndex = tabs.findIndex((tab) => tab.id === activeTabId);\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 }, [activeTabId, tabs, isSegmented]);\n\n const enabledIndices = tabs\n .map((tab, index) => (!tab.disabled ? index : -1))\n .filter((i) => i !== -1);\n\n /**\n * Focus a tab by its index in the full tabs array\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n setFocusedIndex(index);\n }\n }, []);\n\n /**\n * Handle keyboard navigation within the tab list\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n const currentEnabledIndex = enabledIndices.indexOf(currentIndex);\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n {\n const nextEnabledIndex =\n currentEnabledIndex < enabledIndices.length - 1\n ? enabledIndices[currentEnabledIndex + 1]\n : enabledIndices[0];\n focusTab(nextEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[nextEnabledIndex].id);\n }\n }\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n {\n const prevEnabledIndex =\n currentEnabledIndex > 0\n ? enabledIndices[currentEnabledIndex - 1]\n : enabledIndices[enabledIndices.length - 1];\n focusTab(prevEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[prevEnabledIndex].id);\n }\n }\n break;\n\n case \"Home\":\n e.preventDefault();\n {\n const firstEnabledIndex = enabledIndices[0];\n focusTab(firstEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[firstEnabledIndex].id);\n }\n }\n break;\n\n case \"End\":\n e.preventDefault();\n {\n const lastEnabledIndex = enabledIndices[enabledIndices.length - 1];\n focusTab(lastEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[lastEnabledIndex].id);\n }\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (!activateOnFocus && onChange) {\n onChange(tabs[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [enabledIndices, focusTab, activateOnFocus, onChange, tabs]\n );\n\n // Render segmented variant\n if (isSegmented) {\n const segmentedStyles = theme.sizing.tabsSegmented(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n alignItems=\"center\"\n flexShrink={0}\n position=\"relative\"\n width={stretched ? \"100%\" : \"fit-content\"}\n height={segmentedStyles.height}\n backgroundColor={theme.colors.control.segmented.bg}\n borderRadius={segmentedStyles.containerRadius}\n padding={segmentedStyles.containerPadding}\n overflow=\"hidden\"\n >\n {/* Sliding indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height={`calc(100% - ${segmentedStyles.containerPadding * 2}px)`}\n backgroundColor={theme.colors.control.segmented.bgActive}\n borderRadius={segmentedStyles.itemRadius}\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 {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = id ? `${id}-tab-${tab.id}` : undefined;\n const tabPanelId = id ? `${id}-tabpanel-${tab.id}` : undefined;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Text color: use segmented tokens for consistency\n const textColor = isDisabled\n ? theme.colors.control.segmented.textDisable\n : theme.colors.control.segmented.text;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled || undefined}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={stretched ? 1 : undefined}\n flexShrink={0}\n position=\"relative\"\n zIndex={1}\n height=\"100%\"\n paddingHorizontal={segmentedStyles.itemPaddingHorizontal}\n paddingVertical={segmentedStyles.itemPaddingVertical}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={segmentedStyles.gap}\n backgroundColor={\n !isWeb && isActive\n ? theme.colors.control.segmented.bgActive\n : \"transparent\"\n }\n borderRadius={segmentedStyles.itemRadius}\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.control.segmented.bgHover,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon\n size={segmentedStyles.iconSize}\n color={textColor}\n aria-hidden\n >\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n\n // Render line variant (default)\n const lineStyles = theme.sizing.tabs(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n flexDirection=\"row\"\n alignItems=\"flex-end\"\n justifyContent={alignLeft ? \"flex-start\" : \"center\"}\n width={stretched ? \"100%\" : \"fit-content\"}\n height={lineStyles.height}\n borderBottomWidth={1}\n borderBottomColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n >\n {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = `${id}-tab-${tab.id}`;\n const tabPanelId = `${id}-tabpanel-${tab.id}`;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Resolve colors based on state\n const textColor = isDisabled\n ? theme.colors.content.tertiary\n : isActive\n ? theme.colors.content.primary\n : theme.colors.content.tertiary;\n\n const borderBottomColor = isActive\n ? theme.colors.border.primary\n : \"transparent\";\n const borderBottomWidth = isActive ? 2 : 0;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n height={lineStyles.height}\n paddingHorizontal={lineStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={lineStyles.gap}\n position=\"relative\"\n borderBottomWidth={borderBottomWidth}\n borderBottomColor={borderBottomColor}\n borderStyle={isActive ? \"solid\" : \"none\"}\n marginBottom={-1} // Overlap the container's bottom border\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.overlay.mono,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon size={lineStyles.iconSize} color={textColor} aria-hidden>\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={lineStyles.fontSize}\n fontWeight={isActive ? \"600\" : \"500\"}\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={theme.colors.content.brand.primary}\n fontSize={lineStyles.fontSize}\n fontWeight=\"500\"\n aria-label={`${tab.counter} items`}\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nTabs.displayName = \"Tabs\";\n\n/**\n * TabPanel - Container for tab content with proper accessibility attributes\n *\n * @example\n * <TabPanel id=\"tab1\" tabsId=\"my-tabs\" hidden={activeTab !== 'tab1'}>\n * <p>Content for tab 1</p>\n * </TabPanel>\n */\nexport interface TabPanelProps {\n /** ID matching the tab's id */\n id: string;\n /** ID of the parent Tabs component */\n tabsId: string;\n /** Whether the panel is hidden */\n hidden?: boolean;\n /** Panel content */\n children: React.ReactNode;\n /** Accessible label for the panel */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const TabPanel: React.FC<TabPanelProps> = ({\n id,\n tabsId,\n hidden = false,\n children,\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const panelId = `${tabsId}-tabpanel-${id}`;\n const tabId = `${tabsId}-tab-${id}`;\n\n return (\n <Box\n as=\"section\"\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-label={ariaLabel}\n aria-hidden={hidden}\n tabIndex={hidden ? -1 : 0}\n testID={testID}\n style={{ display: hidden ? \"none\" : undefined }}\n >\n {children}\n </Box>\n );\n};\n\nTabPanel.displayName = \"TabPanel\";\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 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"],"mappings":"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","names":["import_react","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/Tabs.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx"],"sourcesContent":["export * from \"./Tabs\";\n","import React, { useState, useRef, useCallback, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport {\n useResolvedTheme,\n isWeb,\n type ThemeOverrideProps,\n} from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\n\nexport interface TabItemType {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n /** Optional icon to display before the label */\n icon?: React.ReactNode;\n /** Optional counter to display after the label */\n counter?: string | number;\n /** Optional badge to display */\n badge?: boolean | string | number;\n /** Whether the tab is disabled */\n disabled?: boolean;\n /** Accessible label for screen readers (defaults to label) */\n \"aria-label\"?: string;\n}\n\nexport interface TabsProps extends ThemeOverrideProps {\n /** Array of tab items */\n tabs: TabItemType[];\n /** ID of the currently active tab */\n activeTabId?: string;\n /** Callback when a tab is selected */\n onChange?: (id: string) => void;\n /** Size variant of the tabs */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\";\n /** Visual variant of the tabs */\n variant?: \"line\" | \"segmented\";\n /** Whether to align tabs to the left (only for line variant) */\n alignLeft?: boolean;\n /** Whether the component should stretch to fill its container */\n stretched?: boolean;\n /** Accessible label for the tab list */\n \"aria-label\"?: string;\n /** ID of element that labels this tab list */\n \"aria-labelledby\"?: string;\n /** Whether keyboard navigation should automatically activate tabs */\n activateOnFocus?: boolean;\n /** HTML id attribute */\n id?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\n/**\n * Tabs - An accessible tabbed interface 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 * Variants:\n * - \"line\" (default): Traditional underlined tabs\n * - \"segmented\": Button-group style segmented control\n */\nexport const Tabs: React.FC<TabsProps> = ({\n tabs,\n activeTabId,\n onChange,\n size = \"md\",\n variant = \"line\",\n alignLeft = true,\n stretched = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n activateOnFocus = true,\n id,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const isSegmented = variant === \"segmented\";\n const tabListId = id ? `${id}-tablist` : undefined;\n\n // Track focused tab for keyboard navigation\n const [_focusedIndex, setFocusedIndex] = useState<number>(-1);\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n\n // Indicator position for segmented variant 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 (!isSegmented || !isWeb) return;\n\n const activeIndex = tabs.findIndex((tab) => tab.id === activeTabId);\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 }, [activeTabId, tabs, isSegmented]);\n\n const enabledIndices = tabs\n .map((tab, index) => (!tab.disabled ? index : -1))\n .filter((i) => i !== -1);\n\n /**\n * Focus a tab by its index in the full tabs array\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus?.();\n setFocusedIndex(index);\n }\n }, []);\n\n /**\n * Handle keyboard navigation within the tab list\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n const currentEnabledIndex = enabledIndices.indexOf(currentIndex);\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n {\n const nextEnabledIndex =\n currentEnabledIndex < enabledIndices.length - 1\n ? enabledIndices[currentEnabledIndex + 1]\n : enabledIndices[0];\n focusTab(nextEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[nextEnabledIndex].id);\n }\n }\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n {\n const prevEnabledIndex =\n currentEnabledIndex > 0\n ? enabledIndices[currentEnabledIndex - 1]\n : enabledIndices[enabledIndices.length - 1];\n focusTab(prevEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[prevEnabledIndex].id);\n }\n }\n break;\n\n case \"Home\":\n e.preventDefault();\n {\n const firstEnabledIndex = enabledIndices[0];\n focusTab(firstEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[firstEnabledIndex].id);\n }\n }\n break;\n\n case \"End\":\n e.preventDefault();\n {\n const lastEnabledIndex = enabledIndices[enabledIndices.length - 1];\n focusTab(lastEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[lastEnabledIndex].id);\n }\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (!activateOnFocus && onChange) {\n onChange(tabs[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [enabledIndices, focusTab, activateOnFocus, onChange, tabs]\n );\n\n // Render segmented variant\n if (isSegmented) {\n const segmentedStyles = theme.sizing.tabsSegmented(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n alignItems=\"center\"\n flexShrink={0}\n position=\"relative\"\n width={stretched ? \"100%\" : isWeb ? \"fit-content\" : undefined}\n alignSelf={!stretched && !isWeb ? \"flex-start\" : undefined}\n height={segmentedStyles.height}\n backgroundColor={theme.colors.control.segmented.bg}\n borderRadius={segmentedStyles.containerRadius}\n padding={segmentedStyles.containerPadding}\n overflow=\"hidden\"\n >\n {/* Sliding indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height={`calc(100% - ${segmentedStyles.containerPadding * 2}px)`}\n backgroundColor={theme.colors.control.segmented.bgActive}\n borderRadius={segmentedStyles.itemRadius}\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 {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = id ? `${id}-tab-${tab.id}` : undefined;\n const tabPanelId = id ? `${id}-tabpanel-${tab.id}` : undefined;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Text color: use segmented tokens for consistency\n const textColor = isDisabled\n ? theme.colors.control.segmented.textDisable\n : theme.colors.control.segmented.text;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled || undefined}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={stretched ? 1 : undefined}\n flexShrink={0}\n position=\"relative\"\n zIndex={1}\n height=\"100%\"\n paddingHorizontal={segmentedStyles.itemPaddingHorizontal}\n paddingVertical={segmentedStyles.itemPaddingVertical}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={segmentedStyles.gap}\n backgroundColor={\n !isWeb && isActive\n ? theme.colors.control.segmented.bgActive\n : \"transparent\"\n }\n borderRadius={segmentedStyles.itemRadius}\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.control.segmented.bgHover,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon\n size={segmentedStyles.iconSize}\n color={textColor}\n aria-hidden\n >\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n\n // Render line variant (default)\n const lineStyles = theme.sizing.tabs(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n flexDirection=\"row\"\n alignItems=\"flex-end\"\n justifyContent={alignLeft ? \"flex-start\" : \"center\"}\n width={stretched ? \"100%\" : isWeb ? \"fit-content\" : undefined}\n alignSelf={!stretched && !isWeb ? \"flex-start\" : undefined}\n height={lineStyles.height}\n borderBottomWidth={1}\n borderBottomColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n >\n {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = `${id}-tab-${tab.id}`;\n const tabPanelId = `${id}-tabpanel-${tab.id}`;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Resolve colors based on state\n const textColor = isDisabled\n ? theme.colors.content.tertiary\n : isActive\n ? theme.colors.content.primary\n : theme.colors.content.tertiary;\n\n const borderBottomColor = isActive\n ? theme.colors.border.primary\n : \"transparent\";\n const borderBottomWidth = isActive ? 2 : 0;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n height={lineStyles.height}\n paddingHorizontal={lineStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={lineStyles.gap}\n position=\"relative\"\n borderBottomWidth={borderBottomWidth}\n borderBottomColor={borderBottomColor}\n borderStyle={isActive ? \"solid\" : \"none\"}\n marginBottom={-1} // Overlap the container's bottom border\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.overlay.mono,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon size={lineStyles.iconSize} color={textColor} aria-hidden>\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={lineStyles.fontSize}\n fontWeight={isActive ? \"600\" : \"500\"}\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={theme.colors.content.brand.primary}\n fontSize={lineStyles.fontSize}\n fontWeight=\"500\"\n aria-label={`${tab.counter} items`}\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nTabs.displayName = \"Tabs\";\n\n/**\n * TabPanel - Container for tab content with proper accessibility attributes\n *\n * @example\n * <TabPanel id=\"tab1\" tabsId=\"my-tabs\" hidden={activeTab !== 'tab1'}>\n * <p>Content for tab 1</p>\n * </TabPanel>\n */\nexport interface TabPanelProps {\n /** ID matching the tab's id */\n id: string;\n /** ID of the parent Tabs component */\n tabsId: string;\n /** Whether the panel is hidden */\n hidden?: boolean;\n /** Panel content */\n children: React.ReactNode;\n /** Accessible label for the panel */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const TabPanel: React.FC<TabPanelProps> = ({\n id,\n tabsId,\n hidden = false,\n children,\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const panelId = `${tabsId}-tabpanel-${id}`;\n const tabId = `${tabsId}-tab-${id}`;\n\n return (\n <Box\n as=\"section\"\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-label={ariaLabel}\n aria-hidden={hidden}\n tabIndex={hidden ? -1 : 0}\n testID={testID}\n style={{ display: hidden ? \"none\" : undefined }}\n >\n {children}\n </Box>\n );\n};\n\nTabPanel.displayName = \"TabPanel\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport {\n Text as RNText,\n TextStyle,\n AccessibilityRole,\n StyleSheet,\n} from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nconst parseNumericValue = (\n value: string | number | undefined\n): number | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = parseFloat(value);\n return isNaN(parsed) ? undefined : parsed;\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n textAlign,\n lineHeight,\n numberOfLines,\n id,\n role,\n style: styleProp,\n ...props\n}) => {\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const incomingStyle = StyleSheet.flatten(styleProp) as TextStyle | undefined;\n\n const baseStyle: TextStyle = {\n color: color ?? incomingStyle?.color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n textAlign: textAlign ?? incomingStyle?.textAlign,\n lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),\n marginTop: parseNumericValue(\n incomingStyle?.marginTop as number | string | undefined\n ),\n marginBottom: parseNumericValue(\n incomingStyle?.marginBottom as number | string | undefined\n ),\n };\n\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText\n style={baseStyle}\n numberOfLines={numberOfLines}\n testID={id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\nimport { View, ViewStyle } from \"react-native\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Icon: React.FC<IconProps> = ({ children, color, size }) => {\n const style: ViewStyle = {\n width: typeof size === \"number\" ? size : undefined,\n height: typeof size === \"number\" ? size : undefined,\n alignItems: \"center\",\n justifyContent: \"center\",\n };\n\n // On native, we try to pass the color down to children (like Text primitives)\n // to mimic the CSS inheritance behavior of the web version.\n const childrenWithProps = React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n color: child.props.color || color,\n // Also pass size if child seems to be an icon that needs it\n size: child.props.size || size,\n });\n }\n return child;\n });\n\n return <View style={style}>{childrenWithProps}</View>;\n};\n"],"mappings":"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","names":["import_react","import_react_native","import_jsx_runtime","RNText","import_react_native","import_jsx_runtime","React","import_jsx_runtime"]}
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,
@@ -262,10 +270,12 @@ var Icon = ({ children, color, size }) => {
262
270
  };
263
271
 
264
272
  // src/Tabs.tsx
265
- import { useDesignSystem } from "@xsolla/xui-core";
273
+ import {
274
+ useResolvedTheme,
275
+ isWeb
276
+ } from "@xsolla/xui-core";
266
277
  import { Badge } from "@xsolla/xui-badge";
267
278
  import { jsx as jsx4, jsxs } from "react/jsx-runtime";
268
- var isWeb = typeof document !== "undefined";
269
279
  var Tabs = ({
270
280
  tabs,
271
281
  activeTabId,
@@ -278,9 +288,11 @@ var Tabs = ({
278
288
  "aria-labelledby": ariaLabelledBy,
279
289
  activateOnFocus = true,
280
290
  id,
281
- testID
291
+ testID,
292
+ themeMode,
293
+ themeProductContext
282
294
  }) => {
283
- const { theme } = useDesignSystem();
295
+ const { theme } = useResolvedTheme({ themeMode, themeProductContext });
284
296
  const isSegmented = variant === "segmented";
285
297
  const tabListId = id ? `${id}-tablist` : void 0;
286
298
  const [_focusedIndex, setFocusedIndex] = useState(-1);
@@ -306,7 +318,7 @@ var Tabs = ({
306
318
  const focusTab = useCallback((index) => {
307
319
  const tabElement = tabRefs.current[index];
308
320
  if (tabElement) {
309
- tabElement.focus();
321
+ tabElement.focus?.();
310
322
  setFocusedIndex(index);
311
323
  }
312
324
  }, []);
@@ -388,7 +400,8 @@ var Tabs = ({
388
400
  alignItems: "center",
389
401
  flexShrink: 0,
390
402
  position: "relative",
391
- width: stretched ? "100%" : "fit-content",
403
+ width: stretched ? "100%" : isWeb ? "fit-content" : void 0,
404
+ alignSelf: !stretched && !isWeb ? "flex-start" : void 0,
392
405
  height: segmentedStyles.height,
393
406
  backgroundColor: theme.colors.control.segmented.bg,
394
407
  borderRadius: segmentedStyles.containerRadius,
@@ -522,7 +535,8 @@ var Tabs = ({
522
535
  flexDirection: "row",
523
536
  alignItems: "flex-end",
524
537
  justifyContent: alignLeft ? "flex-start" : "center",
525
- width: stretched ? "100%" : "fit-content",
538
+ width: stretched ? "100%" : isWeb ? "fit-content" : void 0,
539
+ alignSelf: !stretched && !isWeb ? "flex-start" : void 0,
526
540
  height: lineStyles.height,
527
541
  borderBottomWidth: 1,
528
542
  borderBottomColor: theme.colors.border.secondary,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Tabs.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useEffect } 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\";\n\n// Platform detection without importing react-native directly\nconst isWeb = typeof document !== \"undefined\";\n\nexport interface TabItemType {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n /** Optional icon to display before the label */\n icon?: React.ReactNode;\n /** Optional counter to display after the label */\n counter?: string | number;\n /** Optional badge to display */\n badge?: boolean | string | number;\n /** Whether the tab is disabled */\n disabled?: boolean;\n /** Accessible label for screen readers (defaults to label) */\n \"aria-label\"?: string;\n}\n\nexport interface TabsProps {\n /** Array of tab items */\n tabs: TabItemType[];\n /** ID of the currently active tab */\n activeTabId?: string;\n /** Callback when a tab is selected */\n onChange?: (id: string) => void;\n /** Size variant of the tabs */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\";\n /** Visual variant of the tabs */\n variant?: \"line\" | \"segmented\";\n /** Whether to align tabs to the left (only for line variant) */\n alignLeft?: boolean;\n /** Whether the component should stretch to fill its container */\n stretched?: boolean;\n /** Accessible label for the tab list */\n \"aria-label\"?: string;\n /** ID of element that labels this tab list */\n \"aria-labelledby\"?: string;\n /** Whether keyboard navigation should automatically activate tabs */\n activateOnFocus?: boolean;\n /** HTML id attribute */\n id?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\n/**\n * Tabs - An accessible tabbed interface 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 * Variants:\n * - \"line\" (default): Traditional underlined tabs\n * - \"segmented\": Button-group style segmented control\n */\nexport const Tabs: React.FC<TabsProps> = ({\n tabs,\n activeTabId,\n onChange,\n size = \"md\",\n variant = \"line\",\n alignLeft = true,\n stretched = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n activateOnFocus = true,\n id,\n testID,\n}) => {\n const { theme } = useDesignSystem();\n const isSegmented = variant === \"segmented\";\n const tabListId = id ? `${id}-tablist` : undefined;\n\n // Track focused tab for keyboard navigation\n const [_focusedIndex, setFocusedIndex] = useState<number>(-1);\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n\n // Indicator position for segmented variant 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 (!isSegmented || !isWeb) return;\n\n const activeIndex = tabs.findIndex((tab) => tab.id === activeTabId);\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 }, [activeTabId, tabs, isSegmented]);\n\n const enabledIndices = tabs\n .map((tab, index) => (!tab.disabled ? index : -1))\n .filter((i) => i !== -1);\n\n /**\n * Focus a tab by its index in the full tabs array\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus();\n setFocusedIndex(index);\n }\n }, []);\n\n /**\n * Handle keyboard navigation within the tab list\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n const currentEnabledIndex = enabledIndices.indexOf(currentIndex);\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n {\n const nextEnabledIndex =\n currentEnabledIndex < enabledIndices.length - 1\n ? enabledIndices[currentEnabledIndex + 1]\n : enabledIndices[0];\n focusTab(nextEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[nextEnabledIndex].id);\n }\n }\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n {\n const prevEnabledIndex =\n currentEnabledIndex > 0\n ? enabledIndices[currentEnabledIndex - 1]\n : enabledIndices[enabledIndices.length - 1];\n focusTab(prevEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[prevEnabledIndex].id);\n }\n }\n break;\n\n case \"Home\":\n e.preventDefault();\n {\n const firstEnabledIndex = enabledIndices[0];\n focusTab(firstEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[firstEnabledIndex].id);\n }\n }\n break;\n\n case \"End\":\n e.preventDefault();\n {\n const lastEnabledIndex = enabledIndices[enabledIndices.length - 1];\n focusTab(lastEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[lastEnabledIndex].id);\n }\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (!activateOnFocus && onChange) {\n onChange(tabs[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [enabledIndices, focusTab, activateOnFocus, onChange, tabs]\n );\n\n // Render segmented variant\n if (isSegmented) {\n const segmentedStyles = theme.sizing.tabsSegmented(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n alignItems=\"center\"\n flexShrink={0}\n position=\"relative\"\n width={stretched ? \"100%\" : \"fit-content\"}\n height={segmentedStyles.height}\n backgroundColor={theme.colors.control.segmented.bg}\n borderRadius={segmentedStyles.containerRadius}\n padding={segmentedStyles.containerPadding}\n overflow=\"hidden\"\n >\n {/* Sliding indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height={`calc(100% - ${segmentedStyles.containerPadding * 2}px)`}\n backgroundColor={theme.colors.control.segmented.bgActive}\n borderRadius={segmentedStyles.itemRadius}\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 {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = id ? `${id}-tab-${tab.id}` : undefined;\n const tabPanelId = id ? `${id}-tabpanel-${tab.id}` : undefined;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Text color: use segmented tokens for consistency\n const textColor = isDisabled\n ? theme.colors.control.segmented.textDisable\n : theme.colors.control.segmented.text;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled || undefined}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={stretched ? 1 : undefined}\n flexShrink={0}\n position=\"relative\"\n zIndex={1}\n height=\"100%\"\n paddingHorizontal={segmentedStyles.itemPaddingHorizontal}\n paddingVertical={segmentedStyles.itemPaddingVertical}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={segmentedStyles.gap}\n backgroundColor={\n !isWeb && isActive\n ? theme.colors.control.segmented.bgActive\n : \"transparent\"\n }\n borderRadius={segmentedStyles.itemRadius}\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.control.segmented.bgHover,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon\n size={segmentedStyles.iconSize}\n color={textColor}\n aria-hidden\n >\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n\n // Render line variant (default)\n const lineStyles = theme.sizing.tabs(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n flexDirection=\"row\"\n alignItems=\"flex-end\"\n justifyContent={alignLeft ? \"flex-start\" : \"center\"}\n width={stretched ? \"100%\" : \"fit-content\"}\n height={lineStyles.height}\n borderBottomWidth={1}\n borderBottomColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n >\n {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = `${id}-tab-${tab.id}`;\n const tabPanelId = `${id}-tabpanel-${tab.id}`;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Resolve colors based on state\n const textColor = isDisabled\n ? theme.colors.content.tertiary\n : isActive\n ? theme.colors.content.primary\n : theme.colors.content.tertiary;\n\n const borderBottomColor = isActive\n ? theme.colors.border.primary\n : \"transparent\";\n const borderBottomWidth = isActive ? 2 : 0;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n height={lineStyles.height}\n paddingHorizontal={lineStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={lineStyles.gap}\n position=\"relative\"\n borderBottomWidth={borderBottomWidth}\n borderBottomColor={borderBottomColor}\n borderStyle={isActive ? \"solid\" : \"none\"}\n marginBottom={-1} // Overlap the container's bottom border\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.overlay.mono,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon size={lineStyles.iconSize} color={textColor} aria-hidden>\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={lineStyles.fontSize}\n fontWeight={isActive ? \"600\" : \"500\"}\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={theme.colors.content.brand.primary}\n fontSize={lineStyles.fontSize}\n fontWeight=\"500\"\n aria-label={`${tab.counter} items`}\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nTabs.displayName = \"Tabs\";\n\n/**\n * TabPanel - Container for tab content with proper accessibility attributes\n *\n * @example\n * <TabPanel id=\"tab1\" tabsId=\"my-tabs\" hidden={activeTab !== 'tab1'}>\n * <p>Content for tab 1</p>\n * </TabPanel>\n */\nexport interface TabPanelProps {\n /** ID matching the tab's id */\n id: string;\n /** ID of the parent Tabs component */\n tabsId: string;\n /** Whether the panel is hidden */\n hidden?: boolean;\n /** Panel content */\n children: React.ReactNode;\n /** Accessible label for the panel */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const TabPanel: React.FC<TabPanelProps> = ({\n id,\n tabsId,\n hidden = false,\n children,\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const panelId = `${tabsId}-tabpanel-${id}`;\n const tabId = `${tabsId}-tab-${id}`;\n\n return (\n <Box\n as=\"section\"\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-label={ariaLabel}\n aria-hidden={hidden}\n tabIndex={hidden ? -1 : 0}\n testID={testID}\n style={{ display: hidden ? \"none\" : undefined }}\n >\n {children}\n </Box>\n );\n};\n\nTabPanel.displayName = \"TabPanel\";\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 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"],"mappings":"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","names":["jsx","View","jsx","jsx"]}
1
+ {"version":3,"sources":["../../src/Tabs.tsx","../../../primitives-native/src/Box.tsx","../../../primitives-native/src/Text.tsx","../../../primitives-native/src/Icon.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useEffect } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, Icon } from \"@xsolla/xui-primitives\";\nimport {\n useResolvedTheme,\n isWeb,\n type ThemeOverrideProps,\n} from \"@xsolla/xui-core\";\nimport { Badge } from \"@xsolla/xui-badge\";\n\nexport interface TabItemType {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n /** Optional icon to display before the label */\n icon?: React.ReactNode;\n /** Optional counter to display after the label */\n counter?: string | number;\n /** Optional badge to display */\n badge?: boolean | string | number;\n /** Whether the tab is disabled */\n disabled?: boolean;\n /** Accessible label for screen readers (defaults to label) */\n \"aria-label\"?: string;\n}\n\nexport interface TabsProps extends ThemeOverrideProps {\n /** Array of tab items */\n tabs: TabItemType[];\n /** ID of the currently active tab */\n activeTabId?: string;\n /** Callback when a tab is selected */\n onChange?: (id: string) => void;\n /** Size variant of the tabs */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\";\n /** Visual variant of the tabs */\n variant?: \"line\" | \"segmented\";\n /** Whether to align tabs to the left (only for line variant) */\n alignLeft?: boolean;\n /** Whether the component should stretch to fill its container */\n stretched?: boolean;\n /** Accessible label for the tab list */\n \"aria-label\"?: string;\n /** ID of element that labels this tab list */\n \"aria-labelledby\"?: string;\n /** Whether keyboard navigation should automatically activate tabs */\n activateOnFocus?: boolean;\n /** HTML id attribute */\n id?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\n/**\n * Tabs - An accessible tabbed interface 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 * Variants:\n * - \"line\" (default): Traditional underlined tabs\n * - \"segmented\": Button-group style segmented control\n */\nexport const Tabs: React.FC<TabsProps> = ({\n tabs,\n activeTabId,\n onChange,\n size = \"md\",\n variant = \"line\",\n alignLeft = true,\n stretched = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n activateOnFocus = true,\n id,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const isSegmented = variant === \"segmented\";\n const tabListId = id ? `${id}-tablist` : undefined;\n\n // Track focused tab for keyboard navigation\n const [_focusedIndex, setFocusedIndex] = useState<number>(-1);\n const tabRefs = useRef<(HTMLElement | null)[]>([]);\n const containerRef = useRef<HTMLElement | null>(null);\n\n // Indicator position for segmented variant 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 (!isSegmented || !isWeb) return;\n\n const activeIndex = tabs.findIndex((tab) => tab.id === activeTabId);\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 }, [activeTabId, tabs, isSegmented]);\n\n const enabledIndices = tabs\n .map((tab, index) => (!tab.disabled ? index : -1))\n .filter((i) => i !== -1);\n\n /**\n * Focus a tab by its index in the full tabs array\n */\n const focusTab = useCallback((index: number) => {\n const tabElement = tabRefs.current[index];\n if (tabElement) {\n tabElement.focus?.();\n setFocusedIndex(index);\n }\n }, []);\n\n /**\n * Handle keyboard navigation within the tab list\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n const currentEnabledIndex = enabledIndices.indexOf(currentIndex);\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n {\n const nextEnabledIndex =\n currentEnabledIndex < enabledIndices.length - 1\n ? enabledIndices[currentEnabledIndex + 1]\n : enabledIndices[0];\n focusTab(nextEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[nextEnabledIndex].id);\n }\n }\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n {\n const prevEnabledIndex =\n currentEnabledIndex > 0\n ? enabledIndices[currentEnabledIndex - 1]\n : enabledIndices[enabledIndices.length - 1];\n focusTab(prevEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[prevEnabledIndex].id);\n }\n }\n break;\n\n case \"Home\":\n e.preventDefault();\n {\n const firstEnabledIndex = enabledIndices[0];\n focusTab(firstEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[firstEnabledIndex].id);\n }\n }\n break;\n\n case \"End\":\n e.preventDefault();\n {\n const lastEnabledIndex = enabledIndices[enabledIndices.length - 1];\n focusTab(lastEnabledIndex);\n if (activateOnFocus && onChange) {\n onChange(tabs[lastEnabledIndex].id);\n }\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (!activateOnFocus && onChange) {\n onChange(tabs[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [enabledIndices, focusTab, activateOnFocus, onChange, tabs]\n );\n\n // Render segmented variant\n if (isSegmented) {\n const segmentedStyles = theme.sizing.tabsSegmented(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n ref={(el: HTMLElement | null) => {\n containerRef.current = el;\n }}\n flexDirection=\"row\"\n alignItems=\"center\"\n flexShrink={0}\n position=\"relative\"\n width={stretched ? \"100%\" : isWeb ? \"fit-content\" : undefined}\n alignSelf={!stretched && !isWeb ? \"flex-start\" : undefined}\n height={segmentedStyles.height}\n backgroundColor={theme.colors.control.segmented.bg}\n borderRadius={segmentedStyles.containerRadius}\n padding={segmentedStyles.containerPadding}\n overflow=\"hidden\"\n >\n {/* Sliding indicator (web only) */}\n {isWeb && indicatorStyle.initialized && (\n <Box\n position=\"absolute\"\n zIndex={0}\n height={`calc(100% - ${segmentedStyles.containerPadding * 2}px)`}\n backgroundColor={theme.colors.control.segmented.bgActive}\n borderRadius={segmentedStyles.itemRadius}\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 {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = id ? `${id}-tab-${tab.id}` : undefined;\n const tabPanelId = id ? `${id}-tabpanel-${tab.id}` : undefined;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Text color: use segmented tokens for consistency\n const textColor = isDisabled\n ? theme.colors.control.segmented.textDisable\n : theme.colors.control.segmented.text;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled || undefined}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={stretched ? 1 : undefined}\n flexShrink={0}\n position=\"relative\"\n zIndex={1}\n height=\"100%\"\n paddingHorizontal={segmentedStyles.itemPaddingHorizontal}\n paddingVertical={segmentedStyles.itemPaddingVertical}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={segmentedStyles.gap}\n backgroundColor={\n !isWeb && isActive\n ? theme.colors.control.segmented.bgActive\n : \"transparent\"\n }\n borderRadius={segmentedStyles.itemRadius}\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.control.segmented.bgHover,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon\n size={segmentedStyles.iconSize}\n color={textColor}\n aria-hidden\n >\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={textColor}\n fontSize={segmentedStyles.fontSize}\n fontWeight=\"400\"\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n }\n\n // Render line variant (default)\n const lineStyles = theme.sizing.tabs(size);\n return (\n <Box\n as=\"nav\"\n role=\"tablist\"\n id={tabListId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation=\"horizontal\"\n testID={testID}\n flexDirection=\"row\"\n alignItems=\"flex-end\"\n justifyContent={alignLeft ? \"flex-start\" : \"center\"}\n width={stretched ? \"100%\" : isWeb ? \"fit-content\" : undefined}\n alignSelf={!stretched && !isWeb ? \"flex-start\" : undefined}\n height={lineStyles.height}\n borderBottomWidth={1}\n borderBottomColor={theme.colors.border.secondary}\n borderStyle=\"solid\"\n >\n {tabs.map((tab, index) => {\n const isActive = tab.id === activeTabId;\n const isDisabled = tab.disabled;\n const tabId = `${id}-tab-${tab.id}`;\n const tabPanelId = `${id}-tabpanel-${tab.id}`;\n\n const handlePress = () => {\n if (!isDisabled && onChange) {\n onChange(tab.id);\n }\n };\n\n const handleFocus = () => {\n setFocusedIndex(index);\n };\n\n // Resolve colors based on state\n const textColor = isDisabled\n ? theme.colors.content.tertiary\n : isActive\n ? theme.colors.content.primary\n : theme.colors.content.tertiary;\n\n const borderBottomColor = isActive\n ? theme.colors.border.primary\n : \"transparent\";\n const borderBottomWidth = isActive ? 2 : 0;\n\n return (\n <Box\n key={tab.id}\n as=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-disabled={isDisabled}\n aria-controls={tabPanelId}\n aria-label={tab[\"aria-label\"]}\n tabIndex={isActive ? 0 : -1}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n tabRefs.current[index] = el;\n }}\n onPress={handlePress}\n onFocus={handleFocus}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n height={lineStyles.height}\n paddingHorizontal={lineStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={lineStyles.gap}\n position=\"relative\"\n borderBottomWidth={borderBottomWidth}\n borderBottomColor={borderBottomColor}\n borderStyle={isActive ? \"solid\" : \"none\"}\n marginBottom={-1} // Overlap the container's bottom border\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: theme.colors.overlay.mono,\n }\n : undefined\n }\n focusStyle={{\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: -2,\n }}\n >\n {tab.icon && (\n <Icon size={lineStyles.iconSize} color={textColor} aria-hidden>\n {tab.icon}\n </Icon>\n )}\n\n <Text\n color={textColor}\n fontSize={lineStyles.fontSize}\n fontWeight={isActive ? \"600\" : \"500\"}\n >\n {tab.label}\n </Text>\n\n {tab.counter !== undefined && (\n <Box marginLeft={2} aria-hidden>\n <Text\n color={theme.colors.content.brand.primary}\n fontSize={lineStyles.fontSize}\n fontWeight=\"500\"\n aria-label={`${tab.counter} items`}\n >\n {tab.counter}\n </Text>\n </Box>\n )}\n\n {tab.badge && (\n <Box marginLeft={2} aria-hidden>\n <Badge size=\"sm\">\n {typeof tab.badge === \"string\" ||\n typeof tab.badge === \"number\"\n ? tab.badge\n : undefined}\n </Badge>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nTabs.displayName = \"Tabs\";\n\n/**\n * TabPanel - Container for tab content with proper accessibility attributes\n *\n * @example\n * <TabPanel id=\"tab1\" tabsId=\"my-tabs\" hidden={activeTab !== 'tab1'}>\n * <p>Content for tab 1</p>\n * </TabPanel>\n */\nexport interface TabPanelProps {\n /** ID matching the tab's id */\n id: string;\n /** ID of the parent Tabs component */\n tabsId: string;\n /** Whether the panel is hidden */\n hidden?: boolean;\n /** Panel content */\n children: React.ReactNode;\n /** Accessible label for the panel */\n \"aria-label\"?: string;\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const TabPanel: React.FC<TabPanelProps> = ({\n id,\n tabsId,\n hidden = false,\n children,\n \"aria-label\": ariaLabel,\n testID,\n}) => {\n const panelId = `${tabsId}-tabpanel-${id}`;\n const tabId = `${tabsId}-tab-${id}`;\n\n return (\n <Box\n as=\"section\"\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={tabId}\n aria-label={ariaLabel}\n aria-hidden={hidden}\n tabIndex={hidden ? -1 : 0}\n testID={testID}\n style={{ display: hidden ? \"none\" : undefined }}\n >\n {children}\n </Box>\n );\n};\n\nTabPanel.displayName = \"TabPanel\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import React from \"react\";\nimport {\n Text as RNText,\n TextStyle,\n AccessibilityRole,\n StyleSheet,\n} from \"react-native\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleMap: Record<string, AccessibilityRole> = {\n alert: \"alert\",\n heading: \"header\",\n button: \"button\",\n link: \"link\",\n text: \"text\",\n};\n\nconst parseNumericValue = (\n value: string | number | undefined\n): number | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = parseFloat(value);\n return isNaN(parsed) ? undefined : parsed;\n};\n\nexport const Text: React.FC<TextProps> = ({\n children,\n color,\n fontSize,\n fontWeight,\n fontFamily,\n textAlign,\n lineHeight,\n numberOfLines,\n id,\n role,\n style: styleProp,\n ...props\n}) => {\n let resolvedFontFamily = fontFamily\n ? fontFamily.split(\",\")[0].replace(/['\"]/g, \"\").trim()\n : undefined;\n\n if (\n resolvedFontFamily === \"Pilat Wide\" ||\n resolvedFontFamily === \"Pilat Wide Bold\" ||\n resolvedFontFamily === \"Aktiv Grotesk\"\n ) {\n resolvedFontFamily = undefined;\n }\n\n const incomingStyle = StyleSheet.flatten(styleProp) as TextStyle | undefined;\n\n const baseStyle: TextStyle = {\n color: color ?? incomingStyle?.color,\n fontSize: typeof fontSize === \"number\" ? fontSize : undefined,\n fontWeight: fontWeight as TextStyle[\"fontWeight\"],\n fontFamily: resolvedFontFamily,\n textDecorationLine: props.textDecoration as TextStyle[\"textDecorationLine\"],\n textAlign: textAlign ?? incomingStyle?.textAlign,\n lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),\n marginTop: parseNumericValue(\n incomingStyle?.marginTop as number | string | undefined\n ),\n marginBottom: parseNumericValue(\n incomingStyle?.marginBottom as number | string | undefined\n ),\n };\n\n const accessibilityRole = role ? roleMap[role] : undefined;\n\n return (\n <RNText\n style={baseStyle}\n numberOfLines={numberOfLines}\n testID={id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\nimport { View, ViewStyle } from \"react-native\";\nimport { IconProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Icon: React.FC<IconProps> = ({ children, color, size }) => {\n const style: ViewStyle = {\n width: typeof size === \"number\" ? size : undefined,\n height: typeof size === \"number\" ? size : undefined,\n alignItems: \"center\",\n justifyContent: \"center\",\n };\n\n // On native, we try to pass the color down to children (like Text primitives)\n // to mimic the CSS inheritance behavior of the web version.\n const childrenWithProps = React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n color: child.props.color || color,\n // Also pass size if child seems to be an icon that needs it\n size: child.props.size || size,\n });\n }\n return child;\n });\n\n return <View style={style}>{childrenWithProps}</View>;\n};\n"],"mappings":"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","names":["jsx","View","jsx","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-tabs",
3
- "version": "0.128.0",
3
+ "version": "0.130.0",
4
4
  "main": "./web/index.js",
5
5
  "module": "./web/index.mjs",
6
6
  "types": "./web/index.d.ts",
@@ -12,9 +12,9 @@
12
12
  "test:watch": "vitest"
13
13
  },
14
14
  "dependencies": {
15
- "@xsolla/xui-badge": "0.128.0",
16
- "@xsolla/xui-core": "0.128.0",
17
- "@xsolla/xui-primitives-core": "0.128.0"
15
+ "@xsolla/xui-badge": "0.130.0",
16
+ "@xsolla/xui-core": "0.130.0",
17
+ "@xsolla/xui-primitives-core": "0.130.0"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "react": ">=16.8.0",