@xsolla/xui-gdpr-banner 0.206.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/README.md +50 -0
- package/native/index.d.mts +199 -0
- package/native/index.d.ts +199 -0
- package/native/index.js +918 -0
- package/native/index.js.map +1 -0
- package/native/index.mjs +895 -0
- package/native/index.mjs.map +1 -0
- package/package.json +61 -0
- package/web/index.d.mts +199 -0
- package/web/index.d.ts +199 -0
- package/web/index.js +951 -0
- package/web/index.js.map +1 -0
- package/web/index.mjs +911 -0
- package/web/index.mjs.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/GdprBanner.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../../../foundation/primitives-native/src/Text.tsx","../../src/PrivacySettings.tsx","../../src/defaults.ts"],"sourcesContent":["export { GdprBanner } from \"./GdprBanner\";\nexport { PrivacySettings } from \"./PrivacySettings\";\nexport { DEFAULT_CATEGORIES, DEFAULT_LABELS } from \"./defaults\";\nexport type {\n GdprBannerProps,\n GdprBannerType,\n GdprBannerViewport,\n GdprBannerButtonsRow,\n GdprBannerAnchor,\n GdprBannerLabels,\n GdprCookieCategory,\n PrivacySettingsProps,\n} from \"./types\";\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, useId } from \"@xsolla/xui-core\";\nimport { Button, FlexButton } from \"@xsolla/xui-button\";\nimport { Remove } from \"@xsolla/xui-icons-base\";\nimport { PrivacySettings } from \"./PrivacySettings\";\nimport {\n CARD_WIDTH,\n CONTENT_GAP,\n DEFAULT_CATEGORIES,\n DEFAULT_LABELS,\n EDGE_OFFSET,\n} from \"./defaults\";\nimport type { GdprBannerProps } from \"./types\";\n\nconst FOCUSABLE_SELECTORS =\n 'button:not([disabled]), [href], input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nconst isElementVisible = (element: HTMLElement): boolean => {\n if (typeof window === \"undefined\") return true;\n const style = window.getComputedStyle(element);\n return style.visibility !== \"hidden\" && style.display !== \"none\";\n};\n\nconst getFocusableElements = (container: HTMLElement): HTMLElement[] =>\n Array.from(\n container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS)\n ).filter(isElementVisible);\n\n/**\n * GdprBanner - the Xsolla cookie-consent banner.\n *\n * Implements the Figma `GDPR-banner` component set. The four Figma variant\n * axes map to props: `Type` -> {@link GdprBannerProps.type}, `Fold` ->\n * {@link GdprBannerProps.expanded} (inverted - Figma's `Fold=On` is the\n * collapsed card), `Buttons row` -> {@link GdprBannerProps.buttonsRow},\n * `Viewport` -> {@link GdprBannerProps.viewport}.\n *\n * ## Layout\n *\n * - Desktop, collapsed - a card pinned to the bottom of the viewport with a\n * 20px inset, at either bottom corner (`anchor`).\n * - Desktop, expanded - a wider panel hosting the two-column Privacy settings.\n * - Mobile - always bottom-anchored and full width; actions stack.\n *\n * `Customize` and `Close` are borderless brand-tone text actions, matching the\n * Figma `Flex Button` with `Background=False`.\n *\n * ## Accessibility\n *\n * - `role=\"dialog\"` labelled by the visible heading.\n * - Focus moves into the banner when it mounts and when the panel expands.\n * - Tab and Shift+Tab cycle within the banner; Escape fires `onClose`.\n * - The close control carries an explicit `aria-label`.\n */\nexport const GdprBanner: React.FC<GdprBannerProps> = ({\n type = \"complex\",\n viewport = \"desktop\",\n buttonsRow = \"single\",\n anchor = \"bottom-left\",\n expanded,\n defaultExpanded = false,\n onExpandedChange,\n categories = DEFAULT_CATEGORIES,\n selectedCategoryIds,\n defaultSelectedCategoryIds,\n onSelectionChange,\n labels,\n cookiePolicyUrl,\n privacyPolicyUrl,\n onAcceptAll,\n onRejectAll,\n onCustomize,\n onConfirmSelection,\n onDismiss,\n onClose,\n showCloseButton = true,\n position = \"fixed\",\n offset = EDGE_OFFSET,\n testID = \"gdpr-banner\",\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const containerRef = useRef<HTMLDivElement>(null);\n\n const rawId = useId();\n const titleId = `gdpr-banner-title-${rawId.replace(/:/g, \"\")}`;\n\n const t = useMemo(() => ({ ...DEFAULT_LABELS, ...labels }), [labels]);\n\n const isMobile = viewport === \"mobile\";\n const isSimple = type === \"simple\";\n\n const allIds = useMemo(\n () => categories.map((category) => category.id),\n [categories]\n );\n const lockedIds = useMemo(\n () => categories.filter((category) => category.locked).map((c) => c.id),\n [categories]\n );\n\n const isExpandedControlled = expanded !== undefined;\n const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);\n // `simple` has no Privacy settings panel, so it can never be expanded.\n const isExpanded =\n !isSimple && (isExpandedControlled ? expanded : internalExpanded);\n\n const isSelectionControlled = selectedCategoryIds !== undefined;\n const [internalSelection, setInternalSelection] = useState<string[]>(\n defaultSelectedCategoryIds ?? allIds\n );\n const selection = isSelectionControlled\n ? selectedCategoryIds\n : internalSelection;\n\n const [activeCategoryId, setActiveCategoryId] = useState<string | null>(null);\n\n const setExpanded = useCallback(\n (next: boolean) => {\n if (!isExpandedControlled) setInternalExpanded(next);\n onExpandedChange?.(next);\n },\n [isExpandedControlled, onExpandedChange]\n );\n\n const setSelection = useCallback(\n (next: string[]) => {\n if (!isSelectionControlled) setInternalSelection(next);\n onSelectionChange?.(next);\n },\n [isSelectionControlled, onSelectionChange]\n );\n\n // Escape dismisses the banner outright, matching the close (X) control.\n useEffect(() => {\n if (!onClose || typeof document === \"undefined\") return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [onClose]);\n\n // Pull focus in on mount and whenever the panel expands or collapses, so the\n // newly revealed controls are reachable without hunting for them.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const [first] = getFocusableElements(container);\n first?.focus();\n }, [isExpanded]);\n\n const handleTabKey = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !containerRef.current) return;\n const focusable = getFocusableElements(containerRef.current);\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first) {\n event.preventDefault();\n return;\n }\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }, []);\n\n const handleToggleCategory = useCallback(\n (id: string) => {\n const category = categories.find((item) => item.id === id);\n if (!category || category.locked) return;\n const next = selection.includes(id)\n ? selection.filter((item) => item !== id)\n : [...selection, id];\n setSelection(next);\n },\n [categories, selection, setSelection]\n );\n\n const handleAcceptAll = useCallback(() => {\n setSelection(allIds);\n onAcceptAll?.();\n }, [allIds, onAcceptAll, setSelection]);\n\n const handleRejectAll = useCallback(() => {\n // Locked categories stay consented - they cannot be switched off.\n setSelection(lockedIds);\n onRejectAll?.();\n }, [lockedIds, onRejectAll, setSelection]);\n\n const handleCustomize = useCallback(() => {\n setExpanded(true);\n onCustomize?.();\n }, [onCustomize, setExpanded]);\n\n const handleCollapse = useCallback(() => {\n setExpanded(false);\n }, [setExpanded]);\n\n const handleConfirmSelection = useCallback(() => {\n onConfirmSelection?.(selection);\n }, [onConfirmSelection, selection]);\n\n const sizing = theme.sizing.modal();\n const titleToken = theme.typographyTokens.basic[\"body-lg\"];\n const bodyToken = theme.typographyTokens.basic[\"body-sm\"];\n\n /** Filled action (Reject All / Accept All / Confirm Selection / Dismiss). */\n const solidButton = (\n key: string,\n label: string,\n onPress: () => void,\n fullWidth: boolean\n ) => (\n <Button\n key={key}\n variant=\"secondary\"\n size=\"md\"\n fullWidth={fullWidth}\n onPress={onPress}\n testID={`${testID}__${key}`}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n >\n {label}\n </Button>\n );\n\n /**\n * Borderless text action (Customize / Close).\n *\n * `Button variant=\"ghost\"` cannot be used here: its border token is not\n * transparent in the light theme, so it renders a visible outline that the\n * Figma design does not have. `FlexButton` with the default\n * `background={false}` is the design-system's text-action primitive and is\n * what the Figma file instantiates (`Flex Button`, `Background=False`).\n */\n const textButton = (key: string, label: string, onPress: () => void) => (\n <FlexButton\n key={key}\n variant=\"brand\"\n size=\"lg\"\n onPress={onPress}\n testID={`${testID}__${key}`}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n >\n {label}\n </FlexButton>\n );\n\n const renderActions = () => {\n if (isSimple) {\n return (\n <Box\n width=\"100%\"\n flexDirection=\"row\"\n justifyContent={isMobile ? \"center\" : \"flex-end\"}\n >\n {solidButton(\"dismiss\", t.dismiss, () => onDismiss?.(), isMobile)}\n </Box>\n );\n }\n\n if (isExpanded) {\n const close = textButton(\"close\", t.close, handleCollapse);\n const reject = solidButton(\n \"reject-all\",\n t.rejectAll,\n handleRejectAll,\n isMobile\n );\n const confirm = solidButton(\n \"confirm-selection\",\n t.confirmSelection,\n handleConfirmSelection,\n isMobile\n );\n\n return isMobile ? (\n <Box width=\"100%\" gap={CONTENT_GAP} alignItems=\"center\">\n {[confirm, reject, close]}\n </Box>\n ) : (\n <Box\n width=\"100%\"\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"flex-end\"\n gap={CONTENT_GAP}\n >\n {[close, reject, confirm]}\n </Box>\n );\n }\n\n const customize = textButton(\"customize\", t.customize, handleCustomize);\n\n if (isMobile) {\n return (\n <Box width=\"100%\" gap={CONTENT_GAP} alignItems=\"center\">\n {solidButton(\"accept-all\", t.acceptAll, handleAcceptAll, true)}\n {solidButton(\"reject-all\", t.rejectAll, handleRejectAll, true)}\n {customize}\n </Box>\n );\n }\n\n if (buttonsRow === \"double\") {\n // Figma node 21855:20776 - Customize centred on its own row, then two\n // equal-width buttons filling the 250px content column with an 8px gap.\n return (\n <Box width=\"100%\" gap={CONTENT_GAP}>\n <Box flexDirection=\"row\" justifyContent=\"center\" width=\"100%\">\n {customize}\n </Box>\n <Box flexDirection=\"row\" gap={CONTENT_GAP} width=\"100%\">\n <Box flex={1}>\n {solidButton(\"reject-all\", t.rejectAll, handleRejectAll, true)}\n </Box>\n <Box flex={1}>\n {solidButton(\"accept-all\", t.acceptAll, handleAcceptAll, true)}\n </Box>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box\n width=\"100%\"\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"flex-end\"\n gap={CONTENT_GAP}\n >\n {customize}\n {solidButton(\"reject-all\", t.rejectAll, handleRejectAll, false)}\n {solidButton(\"accept-all\", t.acceptAll, handleAcceptAll, false)}\n </Box>\n );\n };\n\n const edge = isExpanded ? 0 : offset;\n const isFixed = position === \"fixed\";\n const spansFullWidth = isExpanded || isMobile;\n\n return (\n <Box\n ref={containerRef}\n testID={testID}\n role=\"dialog\"\n aria-labelledby={titleId}\n onKeyDown={handleTabKey}\n data-gdpr-banner-type={type}\n data-gdpr-banner-viewport={viewport}\n data-gdpr-banner-expanded={isExpanded ? \"true\" : \"false\"}\n position={isFixed ? \"fixed\" : \"relative\"}\n bottom={isFixed ? edge : undefined}\n left={isFixed && (spansFullWidth || anchor === \"bottom-left\") ? edge : undefined}\n right={\n isFixed && (spansFullWidth || anchor === \"bottom-right\") ? edge : undefined\n }\n zIndex={isFixed ? 1000 : undefined}\n width={spansFullWidth ? \"100%\" : CARD_WIDTH}\n maxWidth=\"100%\"\n backgroundColor={theme.colors.background.primary}\n borderRadius={isExpanded ? 0 : sizing.borderRadius}\n padding={isMobile ? 16 : 20}\n gap={CONTENT_GAP}\n >\n <Box\n flexDirection=\"row\"\n alignItems=\"flex-start\"\n justifyContent=\"space-between\"\n gap={12}\n width=\"100%\"\n >\n <Text\n id={titleId}\n color={theme.colors.content.primary}\n fontSize={titleToken.fontSize}\n lineHeight={titleToken.lineHeight}\n fontWeight={titleToken.accent?.fontWeight ?? 500}\n fontFamily={theme.fonts.body}\n >\n {isExpanded ? t.privacySettingsTitle : t.title}\n </Text>\n\n {showCloseButton && onClose && (\n <FlexButton\n variant=\"tertiary\"\n size=\"xs\"\n onPress={onClose}\n aria-label={t.closeButtonAriaLabel}\n testID={`${testID}__close-icon`}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n >\n <Remove variant=\"line\" />\n </FlexButton>\n )}\n </Box>\n\n {isExpanded ? (\n <PrivacySettings\n categories={categories}\n selectedCategoryIds={selection}\n onToggleCategory={handleToggleCategory}\n activeCategoryId={activeCategoryId}\n onActiveCategoryChange={setActiveCategoryId}\n viewport={viewport}\n labels={{\n generalInformation: t.generalInformation,\n generalInformationDescription: t.generalInformationDescription,\n cookiePolicy: t.cookiePolicy,\n privacyPolicy: t.privacyPolicy,\n }}\n cookiePolicyUrl={cookiePolicyUrl}\n privacyPolicyUrl={privacyPolicyUrl}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n testID={`${testID}__privacy-settings`}\n />\n ) : (\n <Text\n color={theme.colors.content.secondary}\n fontSize={bodyToken.fontSize}\n lineHeight={bodyToken.lineHeight}\n fontFamily={theme.fonts.body}\n testID={`${testID}__description`}\n >\n {isSimple ? t.simpleDescription : t.description}\n </Text>\n )}\n\n {renderActions()}\n </Box>\n );\n};\n\nGdprBanner.displayName = \"GdprBanner\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n AccessibilityRole,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nconst roleToAccessibilityRole: Record<string, AccessibilityRole> = {\n button: \"button\",\n link: \"link\",\n img: \"image\",\n image: \"image\",\n summary: \"summary\",\n switch: \"switch\",\n checkbox: \"checkbox\",\n radio: \"radio\",\n heading: \"header\",\n text: \"text\",\n search: \"search\",\n alert: \"alert\",\n none: \"none\",\n presentation: \"none\",\n progressbar: \"progressbar\",\n scrollbar: \"scrollbar\",\n adjustable: \"adjustable\",\n tab: \"tab\",\n menu: \"menu\",\n menuitem: \"menuitem\",\n list: \"list\",\n timer: \"timer\",\n};\n\n/** RN ViewStyle.gap is typed as number (Yoga gap), not DimensionValue. */\nconst toGapValue = (gap: number | string | undefined): number | undefined => {\n if (gap === undefined) return undefined;\n if (typeof gap === \"number\") return gap;\n const pxMatch = /^(\\d+(?:\\.\\d+)?)px$/.exec(gap);\n if (pxMatch) return Number(pxMatch[1]);\n const asNumber = Number(gap);\n return Number.isFinite(asNumber) ? asNumber : undefined;\n};\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 flexWrap,\n alignItems,\n justifyContent,\n alignSelf,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n flexShrink,\n gap,\n overflow,\n opacity,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n disabled,\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 opacity: opacity ?? (disabled ? 0.5 : undefined),\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 flexWrap,\n alignItems,\n justifyContent,\n alignSelf,\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 flexShrink,\n gap: toGapValue(gap),\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Map web a11y props; drop the rest of the web-only attributes before\n // spreading onto RN hosts (unknown props warn at runtime).\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 \"aria-busy\": ariaBusy,\n className,\n \"data-testid\": _dataTestId,\n cursor: _cursor,\n type: _type,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n const accessibilityRole =\n (typeof role === \"string\" && roleToAccessibilityRole[role]) ||\n (as === \"button\" ? \"button\" : undefined);\n const isDisabled = Boolean(disabled || ariaDisabled);\n const accessibilityState = {\n disabled: isDisabled || undefined,\n busy: Boolean(ariaBusy) || undefined,\n };\n const accessibilityLiveRegion =\n ariaLive === \"polite\" || ariaLive === \"assertive\" ? ariaLive : undefined;\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 accessibilityLabel={typeof ariaLabel === \"string\" ? ariaLabel : alt}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n // Prefer Pressable whenever the node is interactive or explicitly a button,\n // so disabled / aria-disabled controls stay in the a11y tree as buttons.\n if (onPress || as === \"button\") {\n return (\n <Pressable\n onPress={!isDisabled && onPress ? onPress : undefined}\n disabled={isDisabled}\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 accessibilityRole={accessibilityRole}\n accessibilityLabel={\n typeof ariaLabel === \"string\" ? ariaLabel : undefined\n }\n accessibilityState={accessibilityState}\n accessibilityLiveRegion={accessibilityLiveRegion}\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 accessibilityRole={accessibilityRole}\n accessibilityLabel={typeof ariaLabel === \"string\" ? ariaLabel : undefined}\n accessibilityState={accessibilityState}\n accessibilityLiveRegion={accessibilityLiveRegion}\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 testID,\n \"data-testid\": dataTestId,\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={dataTestId || testID || id}\n accessibilityRole={accessibilityRole}\n >\n {children}\n </RNText>\n );\n};\n","import React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box, Text } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme } from \"@xsolla/xui-core\";\nimport { Checkbox } from \"@xsolla/xui-checkbox\";\nimport { Link } from \"@xsolla/xui-link\";\nimport { InfoCr } from \"@xsolla/xui-icons-base\";\nimport type { PrivacySettingsProps } from \"./types\";\n\nconst PANE_RADIUS = 8;\nconst LIST_WIDTH = 280;\n\n/**\n * The expanded half of the GDPR banner: a category list on the left and the\n * selected category's explanation on the right (stacked on mobile, where the\n * explanation renders directly beneath the row it belongs to).\n *\n * Rendered by `GdprBanner` when the Privacy settings panel is open; exported\n * so consumers can embed the same panel inside their own settings screen.\n */\nexport const PrivacySettings: React.FC<PrivacySettingsProps> = ({\n categories,\n selectedCategoryIds,\n onToggleCategory,\n activeCategoryId,\n onActiveCategoryChange,\n viewport,\n labels,\n cookiePolicyUrl,\n privacyPolicyUrl,\n testID = \"gdpr-privacy-settings\",\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const isMobile = viewport === \"mobile\";\n const body = theme.typographyTokens.basic[\"body-sm\"];\n\n const activeDescription =\n activeCategoryId === null\n ? labels.generalInformationDescription\n : (categories.find((category) => category.id === activeCategoryId)\n ?.description ?? \"\");\n\n const descriptionPane = (\n <Box\n testID={`${testID}__description`}\n backgroundColor={theme.colors.control.faint.bg}\n borderRadius={PANE_RADIUS}\n padding={16}\n flex={isMobile ? undefined : 1}\n width={isMobile ? \"100%\" : undefined}\n aria-live=\"polite\"\n >\n <Text\n color={theme.colors.content.secondary}\n fontSize={body.fontSize}\n lineHeight={body.lineHeight}\n fontFamily={theme.fonts.body}\n >\n {activeDescription}\n </Text>\n </Box>\n );\n\n const focusStyle = {\n outlineColor: theme.colors.border.brand,\n outlineWidth: 2,\n outlineOffset: 2,\n outlineStyle: \"solid\",\n };\n\n const list = (\n <Box\n gap={12}\n width={isMobile ? \"100%\" : LIST_WIDTH}\n flexShrink={0}\n testID={`${testID}__categories`}\n >\n <Box gap={8}>\n <Box\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={8}\n role=\"button\"\n tabIndex={0}\n cursor=\"pointer\"\n aria-pressed={activeCategoryId === null}\n onPress={() => onActiveCategoryChange(null)}\n onKeyDown={(event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onActiveCategoryChange(null);\n }\n }}\n focusStyle={focusStyle}\n testID={`${testID}__general-information`}\n >\n <InfoCr\n variant=\"solid\"\n size={16}\n color={theme.colors.control.link.primary}\n />\n <Text\n color={theme.colors.content.primary}\n fontSize={body.fontSize}\n lineHeight={body.lineHeight}\n fontFamily={theme.fonts.body}\n >\n {labels.generalInformation}\n </Text>\n </Box>\n {isMobile && activeCategoryId === null && descriptionPane}\n </Box>\n\n {categories.map((category) => (\n <Box key={category.id} gap={8}>\n <Box onPress={() => onActiveCategoryChange(category.id)}>\n <Checkbox\n size=\"md\"\n checked={selectedCategoryIds.includes(category.id)}\n disabled={category.locked}\n onChange={() => onToggleCategory(category.id)}\n testID={`${testID}__category-${category.id}`}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n >\n {category.label}\n </Checkbox>\n </Box>\n {isMobile && activeCategoryId === category.id && descriptionPane}\n </Box>\n ))}\n </Box>\n );\n\n return (\n <Box testID={testID} gap={16} width=\"100%\">\n <Box\n flexDirection={isMobile ? \"column\" : \"row\"}\n gap={isMobile ? 12 : 24}\n alignItems=\"flex-start\"\n width=\"100%\"\n >\n {list}\n {!isMobile && descriptionPane}\n </Box>\n\n <Box\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={8}\n testID={`${testID}__policies`}\n >\n <Link\n size=\"sm\"\n href={cookiePolicyUrl}\n target=\"_blank\"\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n testID={`${testID}__cookie-policy`}\n >\n {labels.cookiePolicy}\n </Link>\n <Text\n color={theme.colors.content.tertiary}\n fontSize={body.fontSize}\n lineHeight={body.lineHeight}\n fontFamily={theme.fonts.body}\n aria-hidden={true}\n >\n {\"•\"}\n </Text>\n <Link\n size=\"sm\"\n href={privacyPolicyUrl}\n target=\"_blank\"\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n testID={`${testID}__privacy-policy`}\n >\n {labels.privacyPolicy}\n </Link>\n </Box>\n </Box>\n );\n};\n\nPrivacySettings.displayName = \"PrivacySettings\";\n","import type { GdprBannerLabels, GdprCookieCategory } from \"./types\";\n\n/**\n * The five categories shown in the Figma Privacy settings panel.\n *\n * `essential` is `locked`: it renders checked + disabled and is always part of\n * the reported selection, including after `Reject All`.\n */\nexport const DEFAULT_CATEGORIES: GdprCookieCategory[] = [\n {\n id: \"essential\",\n label: \"Essential cookies\",\n locked: true,\n description:\n \"These cookies are required for the Xsolla Ecosystem to function and cannot be disabled in our systems. They are often only set in response to activities taken by you that constitute a request for services, such as changing your privacy settings, logging in, contacting customer support, or filling out forms. You can set your browser to block or inform you about these cookies, but some aspects of the Xsolla Ecosystem will not function properly. These cookies do not contain personally identifying information.\",\n },\n {\n id: \"analytical\",\n label: \"Analytical and performance cookies\",\n description:\n \"These cookies let us count visits and traffic sources so we can measure and improve the performance of the Xsolla Ecosystem. They help us understand which pages are the most and least popular and see how visitors move around the service. All information these cookies collect is aggregated.\",\n },\n {\n id: \"functional\",\n label: \"Functional cookies\",\n description:\n \"These cookies enable the Xsolla Ecosystem to provide enhanced functionality and personalization, such as remembering your preferences and the region you are in. If you do not allow these cookies, some or all of these services may not function properly.\",\n },\n {\n id: \"targeting\",\n label: \"Targeting cookies\",\n description:\n \"These cookies may be set through the Xsolla Ecosystem by our advertising partners to build a profile of your interests and show you relevant offers on other sites. They do not store directly personal information but are based on uniquely identifying your browser and device.\",\n },\n];\n\nexport const DEFAULT_LABELS: Required<GdprBannerLabels> = {\n title: \"How we use cookies\",\n description:\n \"We use cookies to personalize your experience. If you reject the use of cookies, your experience will not be tailored to your preferences.\",\n simpleDescription:\n \"We only use essential cookies that allow us to run this service. Read our cookie policy to learn more.\",\n privacySettingsTitle: \"Privacy settings\",\n generalInformation: \"General information\",\n generalInformationDescription:\n \"We use cookies to personalize your experience, to run and secure the Xsolla Ecosystem, and to measure how it is used. Choose which categories you want to allow below. You can change your choice at any time.\",\n customize: \"Customize\",\n rejectAll: \"Reject All\",\n acceptAll: \"Accept All\",\n confirmSelection: \"Confirm Selection\",\n dismiss: \"Dismiss\",\n close: \"Close\",\n cookiePolicy: \"Cookie Policy\",\n privacyPolicy: \"Privacy Policy\",\n closeButtonAriaLabel: \"Close cookie banner\",\n};\n\n/** Collapsed desktop card width, from the Figma frame. */\nexport const CARD_WIDTH = 400;\n\n/** Default bottom / left / right inset of the collapsed banner, from Figma. */\nexport const EDGE_OFFSET = 20;\n\n/**\n * Vertical and horizontal gap between stacked content blocks and between\n * adjacent action buttons.\n *\n * 8px, measured on the Figma content column (`itemSpacing: 8` on the auto-\n * layout frame inside node 21855:20776).\n */\nexport const CONTENT_GAP = 8;\n"],"mappings":"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","names":["import_react_native","import_jsx_runtime","RNText","import_xui_core","import_xui_icons_base","import_jsx_runtime","import_jsx_runtime"]}
|