@xsolla/xui-toggle-button-group 0.216.1 → 0.217.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/web/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/ToggleButtonGroup.tsx","../../../../foundation/primitives-web/src/Box.tsx","../../../../foundation/primitives-web/src/filterDOMProps.ts","../../../../../node_modules/@emotion/memoize/dist/memoize.esm.js","../../../../../node_modules/@emotion/is-prop-valid/dist/is-prop-valid.esm.js","../../../../foundation/primitives-web/src/Text.tsx","../../../../foundation/primitives-web/src/textTruncation.ts","../../../../foundation/primitives-web/src/index.tsx"],"sourcesContent":["export { ToggleButtonGroup } from \"./ToggleButtonGroup\";\nexport type {\n ToggleButtonGroupProps,\n ToggleButtonGroupItem,\n ToggleButtonGroupItemTooltip,\n ToggleButtonGroupSize,\n ToggleButtonGroupAppearance,\n ToggleButtonGroupView,\n} from \"./types\";\n","import React, { useCallback, useRef, useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, isWeb } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme } from \"@xsolla/xui-core\";\nimport { Tooltip } from \"@xsolla/xui-tooltip\";\nimport type { ToggleButtonGroupProps } from \"./types\";\n\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<Record<string, unknown>>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps,\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nconst getUnitedItemCornerStyle = (\n index: number,\n total: number,\n borderRadius: number,\n isVertical: boolean\n): React.CSSProperties => {\n const isFirst = index === 0;\n const isLast = index === total - 1;\n if (!isFirst && !isLast) return {};\n\n const radius = `${borderRadius}px`;\n\n if (isVertical) {\n return {\n ...(isFirst && {\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n }),\n ...(isLast && {\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n }),\n };\n }\n\n return {\n ...(isFirst && {\n borderTopLeftRadius: radius,\n borderBottomLeftRadius: radius,\n }),\n ...(isLast && {\n borderTopRightRadius: radius,\n borderBottomRightRadius: radius,\n }),\n };\n};\n\n/**\n * ToggleButtonGroup - A control for picking one or several options from a set\n *\n * Used to pick one or several options from a linear set of closely related options.\n * Can be used to filter or to sort elements.\n *\n * ## Accessibility Features\n *\n * - **Role**: Uses `role=\"radiogroup\"` for single selection, `role=\"group\"` for multiple\n * - **Keyboard Navigation**: Arrow keys to navigate, Enter/Space to select\n * - **ARIA**: Proper aria-checked and aria-disabled states\n */\nexport const ToggleButtonGroup: React.FC<ToggleButtonGroupProps> = ({\n items,\n value,\n defaultValue,\n onChange,\n size = \"sm\",\n appearance = \"separated\",\n view = \"horizontal\",\n multiple = false,\n id,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n fullWidth = false,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizeStyles = theme.sizing.toggleButtonGroup(size);\n const itemRefs = useRef<(HTMLElement | null)[]>([]);\n\n const [internalValue, setInternalValue] = useState<string[]>(() => {\n if (defaultValue !== undefined) {\n return Array.isArray(defaultValue) ? defaultValue : [defaultValue];\n }\n return [];\n });\n\n const currentValue =\n value !== undefined\n ? Array.isArray(value)\n ? value\n : [value]\n : internalValue;\n\n const isItemActive = (itemId: string) => currentValue.includes(itemId);\n\n const enabledIndices = items\n .map((item, index) => (!item.disabled ? index : -1))\n .filter((i) => i !== -1);\n\n const focusItem = useCallback((index: number) => {\n const element = itemRefs.current[index];\n if (element) {\n element.focus();\n }\n }, []);\n\n const handleSelect = useCallback(\n (itemId: string) => {\n let newValue: string[];\n\n if (multiple) {\n if (currentValue.includes(itemId)) {\n newValue = currentValue.filter((v) => v !== itemId);\n } else {\n newValue = [...currentValue, itemId];\n }\n } else {\n newValue = [itemId];\n }\n\n if (value === undefined) {\n setInternalValue(newValue);\n }\n\n if (onChange) {\n if (multiple) {\n onChange(newValue);\n } else {\n onChange(newValue[0] || \"\");\n }\n }\n },\n [currentValue, multiple, value, onChange]\n );\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 focusItem(nextEnabledIndex);\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 focusItem(prevEnabledIndex);\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (!items[currentIndex].disabled) {\n handleSelect(items[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [enabledIndices, focusItem, handleSelect, items]\n );\n\n const isSeparated = appearance === \"separated\";\n const isVertical = view === \"vertical\";\n const containerGap = isSeparated ? sizeStyles.itemGap : 0;\n\n // Determine first active item for tabindex in single selection mode\n const firstActiveIndex = items.findIndex((item) =>\n currentValue.includes(item.id)\n );\n const firstEnabledIndex = enabledIndices[0] ?? 0;\n\n return (\n <Box\n id={id}\n role={multiple ? \"group\" : \"radiogroup\"}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n testID={testID}\n flexDirection={isVertical ? \"column\" : \"row\"}\n alignItems=\"stretch\"\n flexWrap={isSeparated && !isVertical ? \"wrap\" : \"nowrap\"}\n gap={containerGap}\n width={fullWidth ? \"100%\" : \"fit-content\"}\n {...(!isSeparated && {\n borderRadius: sizeStyles.borderRadius,\n overflow: \"hidden\",\n })}\n >\n {items.map((item, index) => {\n const isActive = isItemActive(item.id);\n const isDisabled = item.disabled;\n const itemId = id ? `${id}-item-${item.id}` : undefined;\n\n let tabIndex: number;\n if (isDisabled) {\n tabIndex = -1;\n } else if (multiple) {\n // In multiple mode, all enabled items are tabbable\n tabIndex = 0;\n } else {\n // In single mode, only the active item (or first enabled if none active) is tabbable\n tabIndex =\n isActive || (firstActiveIndex === -1 && index === firstEnabledIndex)\n ? 0\n : -1;\n }\n\n const handlePress = () => {\n if (!isDisabled) {\n handleSelect(item.id);\n }\n };\n\n const toggleColors = theme.colors.control.toggleButton;\n\n const bgColor = isDisabled\n ? toggleColors.bgDisable\n : isActive\n ? toggleColors.bgActive\n : toggleColors.bg;\n\n const textColor = isDisabled\n ? toggleColors.textDisable\n : isActive\n ? toggleColors.textActive\n : toggleColors.text;\n\n const borderColor = isDisabled\n ? toggleColors.borderDisable\n : isActive\n ? toggleColors.borderActive\n : toggleColors.border;\n\n const button = (\n <Box\n as=\"button\"\n role={multiple ? \"checkbox\" : \"radio\"}\n id={itemId}\n testID={item.testID}\n aria-checked={isActive}\n aria-disabled={isDisabled}\n aria-label={item[\"aria-label\"] || item.label}\n tabIndex={tabIndex}\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n itemRefs.current[index] = el;\n }}\n onPress={handlePress}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={fullWidth ? 1 : undefined}\n height={sizeStyles.height}\n paddingHorizontal={sizeStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={sizeStyles.gap}\n backgroundColor={bgColor}\n {...(isSeparated\n ? {\n borderWidth: theme.shape.toggleButtonGroup[size].borderWidth,\n borderColor: borderColor,\n borderStyle: \"solid\",\n borderRadius: sizeStyles.borderRadius,\n }\n : {\n borderWidth: theme.shape.toggleButtonGroup[size].borderWidth,\n borderColor: borderColor,\n borderStyle: \"solid\",\n })}\n cursor={isDisabled ? \"not-allowed\" : \"pointer\"}\n hoverStyle={\n !isDisabled && !isActive\n ? {\n backgroundColor: toggleColors.bgHover,\n borderColor: toggleColors.borderHover,\n }\n : undefined\n }\n style={{\n flexShrink: 0,\n ...(!isSeparated &&\n getUnitedItemCornerStyle(\n index,\n items.length,\n sizeStyles.borderRadius,\n isVertical\n )),\n ...(!isSeparated &&\n !isVertical &&\n index < items.length - 1 && { marginRight: -1 }),\n ...(!isSeparated &&\n isVertical &&\n index < items.length - 1 && { marginBottom: -1 }),\n }}\n >\n {item.iconLeft &&\n cloneIconWithDefaults(\n item.iconLeft,\n sizeStyles.iconSize,\n textColor\n )}\n {item.label && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n style={{\n lineHeight: `${sizeStyles.lineHeight}px`,\n }}\n >\n {item.label}\n </Text>\n )}\n {item.iconRight &&\n cloneIconWithDefaults(\n item.iconRight,\n sizeStyles.iconSize,\n textColor\n )}\n </Box>\n );\n\n if (!item.tooltip || !isWeb) {\n return <React.Fragment key={item.id}>{button}</React.Fragment>;\n }\n\n const defaultTooltipPlacement = isVertical ? \"right\" : \"top\";\n\n return (\n <Tooltip\n key={item.id}\n {...item.tooltip}\n placement={item.tooltip.placement ?? defaultTooltipPlacement}\n size={item.tooltip.size ?? sizeStyles.tooltipSize}\n style={\n fullWidth\n ? { flex: 1, ...item.tooltip.style }\n : item.tooltip.style\n }\n >\n {button}\n </Tooltip>\n );\n })}\n </Box>\n );\n};\n\nToggleButtonGroup.displayName = \"ToggleButtonGroup\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledBox = styled(FilteredDiv)<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n max-width: ${(props) =>\n typeof props.maxWidth === \"number\"\n ? `${props.maxWidth}px`\n : props.maxWidth || \"none\"};\n max-height: ${(props) =>\n typeof props.maxHeight === \"number\"\n ? `${props.maxHeight}px`\n : props.maxHeight || \"none\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n /* Only emit overflow-x/y when explicitly set. Defaulting them to\n visible after overflow would override the shorthand and break\n clipping (e.g. OtherCard bottom-right promo image). */\n overflow: ${(props) => props.overflow || \"visible\"};\n ${(props) =>\n props.overflowX != null ? `overflow-x: ${props.overflowX};` : \"\"}\n ${(props) =>\n props.overflowY != null ? `overflow-y: ${props.overflowY};` : \"\"}\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) =>\n props.opacity != null ? props.opacity : props.disabled ? 0.5 : 1};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n /* \\`background\\` is emitted before \\`background-color\\` so a caller passing\n both still gets backgroundColor as the winner. Use the shorthand for a\n layered fill (e.g. an overlay tint over a resting surface colour), which\n a single background-color cannot express. */\n &:hover {\n ${(props) =>\n props.hoverStyle?.background &&\n `background: ${props.hoverStyle.background};`}\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.background &&\n `background: ${props.pressStyle.background};`}\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n onError,\n onLoad,\n type,\n disabled,\n id,\n testID,\n \"data-testid\": dataTestId,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n onError={onError}\n onLoad={onLoad}\n data-testid={dataTestId || testID}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n ...props.style,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n elementType={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n data-testid={dataTestId || testID}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport isPropValid from \"@emotion/is-prop-valid\";\n\n// Props that @emotion/is-prop-valid incorrectly treats as valid HTML.\n// These are React Native or component-specific props that match\n// valid HTML patterns (on* event handlers, SVG attributes).\nexport const ADDITIONAL_BLOCKED_PROPS = new Set([\n // RN-only event handlers (pass isPropValid's on* pattern)\n \"onPress\",\n \"onChangeText\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n // SVG attributes that pass isPropValid\n \"strokeWidth\",\n // CSS properties that pass isPropValid but are used as component props\n \"overflow\",\n \"opacity\",\n \"cursor\",\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"textDecoration\",\n // Cross-platform layout prop that Text consumes as CSS, never as an\n // attribute. Pinned explicitly because it is now spread into the styled\n // component rather than destructured away before it can reach the DOM.\n \"numberOfLines\",\n]);\n\nfunction shouldForwardProp(key: string): boolean {\n if (ADDITIONAL_BLOCKED_PROPS.has(key)) return false;\n return isPropValid(key);\n}\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Uses @emotion/is-prop-valid (same library styled-components v4\n * uses internally) to automatically block invalid HTML attributes,\n * plus a small blocklist for false positives (RN on* handlers, SVG attrs).\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, Record<string, unknown>>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = (elementType as string) || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (shouldForwardProp(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(\n Tag,\n { ref, ...htmlProps },\n children as React.ReactNode\n );\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","function memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport default memoize;\n","import memoize from '@emotion/memoize';\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport default index;\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\nimport { truncationStyles } from \"./textTruncation\";\n\nconst FilteredSpan = createFilteredElement(\"span\");\n\nconst StyledText = styled(FilteredSpan)<TextProps>`\n color: ${(props) => props.color || \"inherit\"};\n font-size: ${(props) =>\n typeof props.fontSize === \"number\"\n ? `${props.fontSize}px`\n : props.fontSize || \"inherit\"};\n font-weight: ${(props) => props.fontWeight || \"normal\"};\n font-family: ${(props) =>\n props.fontFamily ||\n '\"Aktiv Grotesk\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif'};\n line-height: ${(props) =>\n typeof props.lineHeight === \"number\"\n ? `${props.lineHeight}px`\n : props.lineHeight || \"inherit\"};\n white-space: ${(props) => props.whiteSpace || \"normal\"};\n text-align: ${(props) => props.textAlign || \"inherit\"};\n text-decoration: ${(props) => props.textDecoration || \"none\"};\n\n /* Keep last: single-line truncation has to win over white-space above. */\n ${(props) => truncationStyles(props.numberOfLines)}\n`;\n\nexport const Text: React.FC<TextProps> = ({\n style,\n className,\n id,\n role,\n testID,\n \"data-testid\": dataTestId,\n ...props\n}) => {\n return (\n <StyledText\n {...props}\n style={style}\n className={className}\n id={id}\n role={role}\n data-testid={dataTestId || testID}\n />\n );\n};\n","/**\n * Web implementation of the cross-platform `numberOfLines` text prop.\n *\n * Native maps `numberOfLines` straight onto `RNText`. A web `<span>` has no\n * equivalent, so emit the CSS that produces the same result.\n *\n * Two details matter for the single-line case:\n * - `text-overflow` only takes effect on a block container, so the inline\n * `<span>` is promoted to `display: block` and capped at `max-width: 100%`.\n * - `min-width: 0` lets the text shrink below its own content width when it\n * sits in a flex row. Without it a `nowrap` label keeps its full intrinsic\n * width and pushes its siblings (icons, chevrons) out of a fixed-width field.\n *\n * Returns an empty string when there is nothing to clamp, so the declaration\n * block stays untouched for the majority of callers.\n */\nexport const truncationStyles = (numberOfLines?: number): string => {\n if (!numberOfLines || numberOfLines < 1) return \"\";\n\n if (numberOfLines === 1) {\n return `\n display: block;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n `;\n }\n\n return `\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ${numberOfLines};\n line-clamp: ${numberOfLines};\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n `;\n};\n","export * from \"./Box\";\nexport * from \"./Text\";\nexport * from \"./Spinner\";\nexport * from \"./Icon\";\nexport * from \"./Divider\";\nexport * from \"./Input\";\nexport * from \"./TextArea\";\nexport * from \"./LinearGradient\";\n\nexport const isWeb = true;\nexport const isNative = false;\n"],"mappings":"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","names":["import_react","import_react","React","styled","React","import_styled_components","import_jsx_runtime","styled","import_jsx_runtime","React","index"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/ToggleButtonGroup.tsx","../../../../foundation/primitives-web/src/Box.tsx","../../../../foundation/primitives-web/src/filterDOMProps.ts","../../../../../node_modules/@emotion/memoize/dist/memoize.esm.js","../../../../../node_modules/@emotion/is-prop-valid/dist/is-prop-valid.esm.js","../../../../foundation/primitives-web/src/Text.tsx","../../../../foundation/primitives-web/src/textTruncation.ts","../../../../foundation/primitives-web/src/index.tsx"],"sourcesContent":["export { ToggleButtonGroup } from \"./ToggleButtonGroup\";\nexport type {\n ToggleButtonGroupProps,\n ToggleButtonGroupItem,\n ToggleButtonGroupItemTooltip,\n ToggleButtonGroupSize,\n ToggleButtonGroupAppearance,\n ToggleButtonGroupView,\n} from \"./types\";\n","import React, { useCallback, useRef, useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text, isWeb } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme } from \"@xsolla/xui-core\";\nimport { Tooltip } from \"@xsolla/xui-tooltip\";\nimport type {\n ToggleButtonGroupItem,\n ToggleButtonGroupProps,\n} from \"./types\";\n\n/**\n * Opacity applied to a `locked` item while the theme carries no dedicated\n * locked tokens.\n *\n * A locked item keeps the *active* fill, text and border — so it still reads as\n * ON — and is dimmed as a whole to signal that it is not interactive. Dimming\n * the element (rather than swapping in the disable palette) preserves the\n * text-on-fill contrast ratio; only the contrast against the page drops, which\n * is the conventional treatment for a non-interactive control.\n *\n * Once design lands `bgActiveDisable` / `textActiveDisable` /\n * `borderActiveDisable` in `theme.colors.control.toggleButton`, those values\n * are used verbatim and this opacity is not applied — see `lockedColors` below.\n */\nconst LOCKED_OPACITY = 0.6;\n\n/** A locked item is selected and immutable; `locked` wins over `disabled`. */\nconst isItemLocked = (item: ToggleButtonGroupItem) => Boolean(item.locked);\n\n/** Disabled in the native sense: inert *and* not keyboard-reachable. */\nconst isItemDisabled = (item: ToggleButtonGroupItem) =>\n Boolean(item.disabled) && !isItemLocked(item);\n\n/** Can the item's selection be changed by the user? */\nconst isItemInteractive = (item: ToggleButtonGroupItem) =>\n !isItemDisabled(item) && !isItemLocked(item);\n\n/**\n * Can the item receive keyboard focus? Locked items can — that is how a\n * keyboard user reaches the tooltip explaining why the item is locked.\n */\nconst isItemFocusable = (item: ToggleButtonGroupItem) => !isItemDisabled(item);\n\nconst cloneIconWithDefaults = (\n icon: React.ReactNode,\n defaultSize: number,\n defaultColor: string\n): React.ReactNode => {\n if (!React.isValidElement(icon)) return icon;\n\n const iconElement = icon as React.ReactElement<Record<string, unknown>>;\n const existingProps = iconElement.props || {};\n\n return React.cloneElement(iconElement, {\n ...existingProps,\n size: existingProps.size ?? defaultSize,\n color: existingProps.color ?? defaultColor,\n });\n};\n\nconst getUnitedItemCornerStyle = (\n index: number,\n total: number,\n borderRadius: number,\n isVertical: boolean\n): React.CSSProperties => {\n const isFirst = index === 0;\n const isLast = index === total - 1;\n if (!isFirst && !isLast) return {};\n\n const radius = `${borderRadius}px`;\n\n if (isVertical) {\n return {\n ...(isFirst && {\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n }),\n ...(isLast && {\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n }),\n };\n }\n\n return {\n ...(isFirst && {\n borderTopLeftRadius: radius,\n borderBottomLeftRadius: radius,\n }),\n ...(isLast && {\n borderTopRightRadius: radius,\n borderBottomRightRadius: radius,\n }),\n };\n};\n\n/**\n * ToggleButtonGroup - A control for picking one or several options from a set\n *\n * Used to pick one or several options from a linear set of closely related options.\n * Can be used to filter or to sort elements.\n *\n * ## Item states\n *\n * - **Default / active** — selection driven by `value` / `defaultValue`.\n * - **`disabled`** — inert and not focusable; painted with the disable palette.\n * - **`locked`** — selected and immutable: painted with the *active* palette,\n * dimmed, inert, but still keyboard-focusable so its `tooltip` is reachable.\n *\n * ## Accessibility Features\n *\n * - **Role**: Uses `role=\"radiogroup\"` for single selection, `role=\"group\"` for multiple\n * - **Keyboard Navigation**: Arrow keys to navigate, Enter/Space to select\n * - **ARIA**: Proper aria-checked and aria-disabled states\n */\nexport const ToggleButtonGroup: React.FC<ToggleButtonGroupProps> = ({\n items,\n value,\n defaultValue,\n onChange,\n size = \"sm\",\n appearance = \"separated\",\n view = \"horizontal\",\n multiple = false,\n id,\n testID,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n fullWidth = false,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizeStyles = theme.sizing.toggleButtonGroup(size);\n const itemRefs = useRef<(HTMLElement | null)[]>([]);\n\n const toggleColors = theme.colors.control.toggleButton;\n\n /**\n * Locked-state tokens are not in the Figma token export yet. Read them\n * optionally so the component picks them up automatically once design adds\n * them to `control.toggleButton`, with no further code change.\n */\n const lockedColors = toggleColors as typeof toggleColors & {\n bgActiveDisable?: string;\n textActiveDisable?: string;\n borderActiveDisable?: string;\n };\n\n const hasLockedTokens = Boolean(\n lockedColors.bgActiveDisable ??\n lockedColors.textActiveDisable ??\n lockedColors.borderActiveDisable\n );\n\n const [internalValue, setInternalValue] = useState<string[]>(() => {\n if (defaultValue !== undefined) {\n return Array.isArray(defaultValue) ? defaultValue : [defaultValue];\n }\n return [];\n });\n\n const currentValue =\n value !== undefined\n ? Array.isArray(value)\n ? value\n : [value]\n : internalValue;\n\n const isItemActive = (item: ToggleButtonGroupItem) =>\n currentValue.includes(item.id) || isItemLocked(item);\n\n const focusableIndices = items\n .map((item, index) => (isItemFocusable(item) ? index : -1))\n .filter((i) => i !== -1);\n\n const focusItem = useCallback((index: number) => {\n const element = itemRefs.current[index];\n if (element) {\n element.focus();\n }\n }, []);\n\n const handleSelect = useCallback(\n (itemId: string) => {\n let newValue: string[];\n\n if (multiple) {\n if (currentValue.includes(itemId)) {\n newValue = currentValue.filter((v) => v !== itemId);\n } else {\n newValue = [...currentValue, itemId];\n }\n } else {\n newValue = [itemId];\n }\n\n if (value === undefined) {\n setInternalValue(newValue);\n }\n\n if (onChange) {\n if (multiple) {\n onChange(newValue);\n } else {\n onChange(newValue[0] || \"\");\n }\n }\n },\n [currentValue, multiple, value, onChange]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, currentIndex: number) => {\n const currentFocusableIndex = focusableIndices.indexOf(currentIndex);\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n {\n const nextFocusableIndex =\n currentFocusableIndex < focusableIndices.length - 1\n ? focusableIndices[currentFocusableIndex + 1]\n : focusableIndices[0];\n focusItem(nextFocusableIndex);\n }\n break;\n\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n {\n const prevFocusableIndex =\n currentFocusableIndex > 0\n ? focusableIndices[currentFocusableIndex - 1]\n : focusableIndices[focusableIndices.length - 1];\n focusItem(prevFocusableIndex);\n }\n break;\n\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (isItemInteractive(items[currentIndex])) {\n handleSelect(items[currentIndex].id);\n }\n break;\n\n default:\n break;\n }\n },\n [focusableIndices, focusItem, handleSelect, items]\n );\n\n const isSeparated = appearance === \"separated\";\n const isVertical = view === \"vertical\";\n const containerGap = isSeparated ? sizeStyles.itemGap : 0;\n\n // Determine first active item for tabindex in single selection mode\n const firstActiveIndex = items.findIndex((item) => isItemActive(item));\n const firstFocusableIndex = focusableIndices[0] ?? 0;\n\n return (\n <Box\n id={id}\n role={multiple ? \"group\" : \"radiogroup\"}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n testID={testID}\n flexDirection={isVertical ? \"column\" : \"row\"}\n alignItems=\"stretch\"\n flexWrap={isSeparated && !isVertical ? \"wrap\" : \"nowrap\"}\n gap={containerGap}\n width={fullWidth ? \"100%\" : \"fit-content\"}\n {...(!isSeparated && {\n borderRadius: sizeStyles.borderRadius,\n overflow: \"hidden\",\n })}\n >\n {items.map((item, index) => {\n const isLocked = isItemLocked(item);\n const isDisabled = isItemDisabled(item);\n const isInteractive = isItemInteractive(item);\n const isFocusable = isItemFocusable(item);\n const isActive = isItemActive(item);\n const itemId = id ? `${id}-item-${item.id}` : undefined;\n\n let tabIndex: number;\n if (!isFocusable) {\n tabIndex = -1;\n } else if (multiple) {\n // In multiple mode, all focusable items are tabbable\n tabIndex = 0;\n } else {\n // In single mode, only the active item (or first focusable if none active) is tabbable\n tabIndex =\n isActive ||\n (firstActiveIndex === -1 && index === firstFocusableIndex)\n ? 0\n : -1;\n }\n\n const handlePress = () => {\n if (isInteractive) {\n handleSelect(item.id);\n }\n };\n\n const bgColor = isLocked\n ? (lockedColors.bgActiveDisable ?? toggleColors.bgActive)\n : isDisabled\n ? toggleColors.bgDisable\n : isActive\n ? toggleColors.bgActive\n : toggleColors.bg;\n\n const textColor = isLocked\n ? (lockedColors.textActiveDisable ?? toggleColors.textActive)\n : isDisabled\n ? toggleColors.textDisable\n : isActive\n ? toggleColors.textActive\n : toggleColors.text;\n\n const borderColor = isLocked\n ? (lockedColors.borderActiveDisable ?? toggleColors.borderActive)\n : isDisabled\n ? toggleColors.borderDisable\n : isActive\n ? toggleColors.borderActive\n : toggleColors.border;\n\n const button = (\n <Box\n as=\"button\"\n role={multiple ? \"checkbox\" : \"radio\"}\n id={itemId}\n testID={item.testID}\n aria-checked={isActive}\n aria-disabled={isDisabled || isLocked}\n aria-label={item[\"aria-label\"] || item.label}\n tabIndex={tabIndex}\n // A locked item deliberately omits the native `disabled` attribute\n // so it stays focusable and its tooltip is reachable by keyboard.\n disabled={isDisabled}\n ref={(el: HTMLElement | null) => {\n itemRefs.current[index] = el;\n }}\n onPress={handlePress}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e, index)}\n flex={fullWidth ? 1 : undefined}\n height={sizeStyles.height}\n paddingHorizontal={sizeStyles.paddingHorizontal}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={sizeStyles.gap}\n backgroundColor={bgColor}\n {...(isSeparated\n ? {\n borderWidth: theme.shape.toggleButtonGroup[size].borderWidth,\n borderColor: borderColor,\n borderStyle: \"solid\",\n borderRadius: sizeStyles.borderRadius,\n }\n : {\n borderWidth: theme.shape.toggleButtonGroup[size].borderWidth,\n borderColor: borderColor,\n borderStyle: \"solid\",\n })}\n cursor={isInteractive ? \"pointer\" : \"not-allowed\"}\n hoverStyle={\n isInteractive && !isActive\n ? {\n backgroundColor: toggleColors.bgHover,\n borderColor: toggleColors.borderHover,\n }\n : undefined\n }\n style={{\n flexShrink: 0,\n ...(isLocked && !hasLockedTokens && { opacity: LOCKED_OPACITY }),\n ...(!isSeparated &&\n getUnitedItemCornerStyle(\n index,\n items.length,\n sizeStyles.borderRadius,\n isVertical\n )),\n ...(!isSeparated &&\n !isVertical &&\n index < items.length - 1 && { marginRight: -1 }),\n ...(!isSeparated &&\n isVertical &&\n index < items.length - 1 && { marginBottom: -1 }),\n }}\n >\n {item.iconLeft &&\n cloneIconWithDefaults(\n item.iconLeft,\n sizeStyles.iconSize,\n textColor\n )}\n {item.label && (\n <Text\n color={textColor}\n fontSize={sizeStyles.fontSize}\n fontWeight=\"400\"\n textAlign=\"center\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n style={{\n lineHeight: `${sizeStyles.lineHeight}px`,\n }}\n >\n {item.label}\n </Text>\n )}\n {item.iconRight &&\n cloneIconWithDefaults(\n item.iconRight,\n sizeStyles.iconSize,\n textColor\n )}\n </Box>\n );\n\n if (!item.tooltip || !isWeb) {\n return <React.Fragment key={item.id}>{button}</React.Fragment>;\n }\n\n const defaultTooltipPlacement = isVertical ? \"right\" : \"top\";\n\n return (\n <Tooltip\n key={item.id}\n {...item.tooltip}\n placement={item.tooltip.placement ?? defaultTooltipPlacement}\n size={item.tooltip.size ?? sizeStyles.tooltipSize}\n style={\n fullWidth\n ? { flex: 1, ...item.tooltip.style }\n : item.tooltip.style\n }\n >\n {button}\n </Tooltip>\n );\n })}\n </Box>\n );\n};\n\nToggleButtonGroup.displayName = \"ToggleButtonGroup\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledBox = styled(FilteredDiv)<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n max-width: ${(props) =>\n typeof props.maxWidth === \"number\"\n ? `${props.maxWidth}px`\n : props.maxWidth || \"none\"};\n max-height: ${(props) =>\n typeof props.maxHeight === \"number\"\n ? `${props.maxHeight}px`\n : props.maxHeight || \"none\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n /* Only emit overflow-x/y when explicitly set. Defaulting them to\n visible after overflow would override the shorthand and break\n clipping (e.g. OtherCard bottom-right promo image). */\n overflow: ${(props) => props.overflow || \"visible\"};\n ${(props) =>\n props.overflowX != null ? `overflow-x: ${props.overflowX};` : \"\"}\n ${(props) =>\n props.overflowY != null ? `overflow-y: ${props.overflowY};` : \"\"}\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) =>\n props.opacity != null ? props.opacity : props.disabled ? 0.5 : 1};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n /* \\`background\\` is emitted before \\`background-color\\` so a caller passing\n both still gets backgroundColor as the winner. Use the shorthand for a\n layered fill (e.g. an overlay tint over a resting surface colour), which\n a single background-color cannot express. */\n &:hover {\n ${(props) =>\n props.hoverStyle?.background &&\n `background: ${props.hoverStyle.background};`}\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.background &&\n `background: ${props.pressStyle.background};`}\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n onError,\n onLoad,\n type,\n disabled,\n id,\n testID,\n \"data-testid\": dataTestId,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n onError={onError}\n onLoad={onLoad}\n data-testid={dataTestId || testID}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n ...props.style,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n elementType={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n data-testid={dataTestId || testID}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport isPropValid from \"@emotion/is-prop-valid\";\n\n// Props that @emotion/is-prop-valid incorrectly treats as valid HTML.\n// These are React Native or component-specific props that match\n// valid HTML patterns (on* event handlers, SVG attributes).\nexport const ADDITIONAL_BLOCKED_PROPS = new Set([\n // RN-only event handlers (pass isPropValid's on* pattern)\n \"onPress\",\n \"onChangeText\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n // SVG attributes that pass isPropValid\n \"strokeWidth\",\n // CSS properties that pass isPropValid but are used as component props\n \"overflow\",\n \"opacity\",\n \"cursor\",\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"textDecoration\",\n // Cross-platform layout prop that Text consumes as CSS, never as an\n // attribute. Pinned explicitly because it is now spread into the styled\n // component rather than destructured away before it can reach the DOM.\n \"numberOfLines\",\n]);\n\nfunction shouldForwardProp(key: string): boolean {\n if (ADDITIONAL_BLOCKED_PROPS.has(key)) return false;\n return isPropValid(key);\n}\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Uses @emotion/is-prop-valid (same library styled-components v4\n * uses internally) to automatically block invalid HTML attributes,\n * plus a small blocklist for false positives (RN on* handlers, SVG attrs).\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, Record<string, unknown>>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = (elementType as string) || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (shouldForwardProp(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(\n Tag,\n { ref, ...htmlProps },\n children as React.ReactNode\n );\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","function memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport default memoize;\n","import memoize from '@emotion/memoize';\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport default index;\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { TextProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\nimport { truncationStyles } from \"./textTruncation\";\n\nconst FilteredSpan = createFilteredElement(\"span\");\n\nconst StyledText = styled(FilteredSpan)<TextProps>`\n color: ${(props) => props.color || \"inherit\"};\n font-size: ${(props) =>\n typeof props.fontSize === \"number\"\n ? `${props.fontSize}px`\n : props.fontSize || \"inherit\"};\n font-weight: ${(props) => props.fontWeight || \"normal\"};\n font-family: ${(props) =>\n props.fontFamily ||\n '\"Aktiv Grotesk\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif'};\n line-height: ${(props) =>\n typeof props.lineHeight === \"number\"\n ? `${props.lineHeight}px`\n : props.lineHeight || \"inherit\"};\n white-space: ${(props) => props.whiteSpace || \"normal\"};\n text-align: ${(props) => props.textAlign || \"inherit\"};\n text-decoration: ${(props) => props.textDecoration || \"none\"};\n\n /* Keep last: single-line truncation has to win over white-space above. */\n ${(props) => truncationStyles(props.numberOfLines)}\n`;\n\nexport const Text: React.FC<TextProps> = ({\n style,\n className,\n id,\n role,\n testID,\n \"data-testid\": dataTestId,\n ...props\n}) => {\n return (\n <StyledText\n {...props}\n style={style}\n className={className}\n id={id}\n role={role}\n data-testid={dataTestId || testID}\n />\n );\n};\n","/**\n * Web implementation of the cross-platform `numberOfLines` text prop.\n *\n * Native maps `numberOfLines` straight onto `RNText`. A web `<span>` has no\n * equivalent, so emit the CSS that produces the same result.\n *\n * Two details matter for the single-line case:\n * - `text-overflow` only takes effect on a block container, so the inline\n * `<span>` is promoted to `display: block` and capped at `max-width: 100%`.\n * - `min-width: 0` lets the text shrink below its own content width when it\n * sits in a flex row. Without it a `nowrap` label keeps its full intrinsic\n * width and pushes its siblings (icons, chevrons) out of a fixed-width field.\n *\n * Returns an empty string when there is nothing to clamp, so the declaration\n * block stays untouched for the majority of callers.\n */\nexport const truncationStyles = (numberOfLines?: number): string => {\n if (!numberOfLines || numberOfLines < 1) return \"\";\n\n if (numberOfLines === 1) {\n return `\n display: block;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n `;\n }\n\n return `\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: ${numberOfLines};\n line-clamp: ${numberOfLines};\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n `;\n};\n","export * from \"./Box\";\nexport * from \"./Text\";\nexport * from \"./Spinner\";\nexport * from \"./Icon\";\nexport * from \"./Divider\";\nexport * from \"./Input\";\nexport * from \"./TextArea\";\nexport * from \"./LinearGradient\";\n\nexport const isWeb = true;\nexport const isNative = false;\n"],"mappings":"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","names":["import_react","import_react","React","styled","React","import_styled_components","import_jsx_runtime","styled","import_jsx_runtime","React","index"]}
package/web/index.mjs CHANGED
@@ -339,6 +339,11 @@ var isWeb = true;
339
339
  import { useResolvedTheme } from "@xsolla/xui-core";
340
340
  import { Tooltip } from "@xsolla/xui-tooltip";
341
341
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
342
+ var LOCKED_OPACITY = 0.6;
343
+ var isItemLocked = (item) => Boolean(item.locked);
344
+ var isItemDisabled = (item) => Boolean(item.disabled) && !isItemLocked(item);
345
+ var isItemInteractive = (item) => !isItemDisabled(item) && !isItemLocked(item);
346
+ var isItemFocusable = (item) => !isItemDisabled(item);
342
347
  var cloneIconWithDefaults = (icon, defaultSize, defaultColor) => {
343
348
  if (!React3.isValidElement(icon)) return icon;
344
349
  const iconElement = icon;
@@ -397,6 +402,11 @@ var ToggleButtonGroup = ({
397
402
  const { theme } = useResolvedTheme({ themeMode, themeProductContext });
398
403
  const sizeStyles = theme.sizing.toggleButtonGroup(size);
399
404
  const itemRefs = useRef([]);
405
+ const toggleColors = theme.colors.control.toggleButton;
406
+ const lockedColors = toggleColors;
407
+ const hasLockedTokens = Boolean(
408
+ lockedColors.bgActiveDisable ?? lockedColors.textActiveDisable ?? lockedColors.borderActiveDisable
409
+ );
400
410
  const [internalValue, setInternalValue] = useState(() => {
401
411
  if (defaultValue !== void 0) {
402
412
  return Array.isArray(defaultValue) ? defaultValue : [defaultValue];
@@ -404,8 +414,8 @@ var ToggleButtonGroup = ({
404
414
  return [];
405
415
  });
406
416
  const currentValue = value !== void 0 ? Array.isArray(value) ? value : [value] : internalValue;
407
- const isItemActive = (itemId) => currentValue.includes(itemId);
408
- const enabledIndices = items.map((item, index2) => !item.disabled ? index2 : -1).filter((i) => i !== -1);
417
+ const isItemActive = (item) => currentValue.includes(item.id) || isItemLocked(item);
418
+ const focusableIndices = items.map((item, index2) => isItemFocusable(item) ? index2 : -1).filter((i) => i !== -1);
409
419
  const focusItem = useCallback((index2) => {
410
420
  const element = itemRefs.current[index2];
411
421
  if (element) {
@@ -439,28 +449,28 @@ var ToggleButtonGroup = ({
439
449
  );
440
450
  const handleKeyDown = useCallback(
441
451
  (e, currentIndex) => {
442
- const currentEnabledIndex = enabledIndices.indexOf(currentIndex);
452
+ const currentFocusableIndex = focusableIndices.indexOf(currentIndex);
443
453
  switch (e.key) {
444
454
  case "ArrowRight":
445
455
  case "ArrowDown":
446
456
  e.preventDefault();
447
457
  {
448
- const nextEnabledIndex = currentEnabledIndex < enabledIndices.length - 1 ? enabledIndices[currentEnabledIndex + 1] : enabledIndices[0];
449
- focusItem(nextEnabledIndex);
458
+ const nextFocusableIndex = currentFocusableIndex < focusableIndices.length - 1 ? focusableIndices[currentFocusableIndex + 1] : focusableIndices[0];
459
+ focusItem(nextFocusableIndex);
450
460
  }
451
461
  break;
452
462
  case "ArrowLeft":
453
463
  case "ArrowUp":
454
464
  e.preventDefault();
455
465
  {
456
- const prevEnabledIndex = currentEnabledIndex > 0 ? enabledIndices[currentEnabledIndex - 1] : enabledIndices[enabledIndices.length - 1];
457
- focusItem(prevEnabledIndex);
466
+ const prevFocusableIndex = currentFocusableIndex > 0 ? focusableIndices[currentFocusableIndex - 1] : focusableIndices[focusableIndices.length - 1];
467
+ focusItem(prevFocusableIndex);
458
468
  }
459
469
  break;
460
470
  case "Enter":
461
471
  case " ":
462
472
  e.preventDefault();
463
- if (!items[currentIndex].disabled) {
473
+ if (isItemInteractive(items[currentIndex])) {
464
474
  handleSelect(items[currentIndex].id);
465
475
  }
466
476
  break;
@@ -468,15 +478,13 @@ var ToggleButtonGroup = ({
468
478
  break;
469
479
  }
470
480
  },
471
- [enabledIndices, focusItem, handleSelect, items]
481
+ [focusableIndices, focusItem, handleSelect, items]
472
482
  );
473
483
  const isSeparated = appearance === "separated";
474
484
  const isVertical = view === "vertical";
475
485
  const containerGap = isSeparated ? sizeStyles.itemGap : 0;
476
- const firstActiveIndex = items.findIndex(
477
- (item) => currentValue.includes(item.id)
478
- );
479
- const firstEnabledIndex = enabledIndices[0] ?? 0;
486
+ const firstActiveIndex = items.findIndex((item) => isItemActive(item));
487
+ const firstFocusableIndex = focusableIndices[0] ?? 0;
480
488
  return /* @__PURE__ */ jsx3(
481
489
  Box,
482
490
  {
@@ -495,26 +503,28 @@ var ToggleButtonGroup = ({
495
503
  overflow: "hidden"
496
504
  },
497
505
  children: items.map((item, index2) => {
498
- const isActive = isItemActive(item.id);
499
- const isDisabled = item.disabled;
506
+ const isLocked = isItemLocked(item);
507
+ const isDisabled = isItemDisabled(item);
508
+ const isInteractive = isItemInteractive(item);
509
+ const isFocusable = isItemFocusable(item);
510
+ const isActive = isItemActive(item);
500
511
  const itemId = id ? `${id}-item-${item.id}` : void 0;
501
512
  let tabIndex;
502
- if (isDisabled) {
513
+ if (!isFocusable) {
503
514
  tabIndex = -1;
504
515
  } else if (multiple) {
505
516
  tabIndex = 0;
506
517
  } else {
507
- tabIndex = isActive || firstActiveIndex === -1 && index2 === firstEnabledIndex ? 0 : -1;
518
+ tabIndex = isActive || firstActiveIndex === -1 && index2 === firstFocusableIndex ? 0 : -1;
508
519
  }
509
520
  const handlePress = () => {
510
- if (!isDisabled) {
521
+ if (isInteractive) {
511
522
  handleSelect(item.id);
512
523
  }
513
524
  };
514
- const toggleColors = theme.colors.control.toggleButton;
515
- const bgColor = isDisabled ? toggleColors.bgDisable : isActive ? toggleColors.bgActive : toggleColors.bg;
516
- const textColor = isDisabled ? toggleColors.textDisable : isActive ? toggleColors.textActive : toggleColors.text;
517
- const borderColor = isDisabled ? toggleColors.borderDisable : isActive ? toggleColors.borderActive : toggleColors.border;
525
+ const bgColor = isLocked ? lockedColors.bgActiveDisable ?? toggleColors.bgActive : isDisabled ? toggleColors.bgDisable : isActive ? toggleColors.bgActive : toggleColors.bg;
526
+ const textColor = isLocked ? lockedColors.textActiveDisable ?? toggleColors.textActive : isDisabled ? toggleColors.textDisable : isActive ? toggleColors.textActive : toggleColors.text;
527
+ const borderColor = isLocked ? lockedColors.borderActiveDisable ?? toggleColors.borderActive : isDisabled ? toggleColors.borderDisable : isActive ? toggleColors.borderActive : toggleColors.border;
518
528
  const button = /* @__PURE__ */ jsxs(
519
529
  Box,
520
530
  {
@@ -523,7 +533,7 @@ var ToggleButtonGroup = ({
523
533
  id: itemId,
524
534
  testID: item.testID,
525
535
  "aria-checked": isActive,
526
- "aria-disabled": isDisabled,
536
+ "aria-disabled": isDisabled || isLocked,
527
537
  "aria-label": item["aria-label"] || item.label,
528
538
  tabIndex,
529
539
  disabled: isDisabled,
@@ -550,13 +560,14 @@ var ToggleButtonGroup = ({
550
560
  borderColor,
551
561
  borderStyle: "solid"
552
562
  },
553
- cursor: isDisabled ? "not-allowed" : "pointer",
554
- hoverStyle: !isDisabled && !isActive ? {
563
+ cursor: isInteractive ? "pointer" : "not-allowed",
564
+ hoverStyle: isInteractive && !isActive ? {
555
565
  backgroundColor: toggleColors.bgHover,
556
566
  borderColor: toggleColors.borderHover
557
567
  } : void 0,
558
568
  style: {
559
569
  flexShrink: 0,
570
+ ...isLocked && !hasLockedTokens && { opacity: LOCKED_OPACITY },
560
571
  ...!isSeparated && getUnitedItemCornerStyle(
561
572
  index2,
562
573
  items.length,