@gnome-ui/react-native 1.2.0 → 1.3.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/theme/tokens.generated.ts","../src/GnomeProvider/GnomeContext.ts","../src/theme/resolveTheme.ts","../src/GnomeProvider/resolveContext.ts","../src/GnomeProvider/GnomeProvider.tsx","../src/components/Text/Text.tsx","../src/components/ActionRow/ActionRow.tsx","../src/components/Icon/shared.ts","../src/components/Icon/Icon.tsx","../src/components/AnimatedIcon/AnimatedIcon.tsx","../src/components/Banner/Banner.tsx","../src/components/Separator/Separator.tsx","../src/components/BoxedList/BoxedList.tsx","../src/components/Button/Button.tsx","../src/components/Card/Card.tsx","../src/components/Checkbox/Checkbox.tsx","../src/components/Dialog/Dialog.tsx","../src/components/Dropdown/Dropdown.tsx","../src/components/HeaderBar/HeaderBar.tsx","../src/components/Link/Link.tsx","../src/components/PathBar/PathBar.tsx","../src/components/ProgressBar/ProgressBar.tsx","../src/components/RadioButton/RadioButton.tsx","../src/components/SearchBar/SearchBar.tsx","../src/components/Sidebar/filterUtils.ts","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/SidebarItem.tsx","../src/components/Sidebar/SidebarSection.tsx","../src/components/Skeleton/Skeleton.tsx","../src/components/Spinner/Spinner.tsx","../src/components/Switch/Switch.tsx","../src/components/Tabs/TabBar.tsx","../src/components/Tabs/TabItem.tsx","../src/components/Tabs/TabPanel.tsx","../src/components/TextField/TextField.tsx","../src/components/Toast/Toast.tsx","../src/components/Toast/Toaster.tsx","../src/components/Tooltip/Tooltip.tsx","../src/components/ViewSwitcher/ViewSwitcher.tsx","../src/components/ViewSwitcher/ViewSwitcherItem.tsx"],"sourcesContent":["/**\n * AUTO-GENERATED — do not edit by hand.\n * Run `npm run theme:generate` (from packages/react-native) to regenerate\n * from @gnome-ui/core's `src/tokens.css`.\n */\n\nexport interface GnomeThemeTokens {\n readonly accentBgColor: string;\n readonly accentColor: string;\n readonly accentFgColor: string;\n readonly activeOverlay: string;\n readonly blockquoteBorderWidth: number;\n readonly blue1: string;\n readonly blue2: string;\n readonly blue3: string;\n readonly blue4: string;\n readonly blue5: string;\n readonly borderSubtle: string;\n readonly brown1: string;\n readonly brown2: string;\n readonly brown3: string;\n readonly brown4: string;\n readonly brown5: string;\n readonly cardBgColor: string;\n readonly cardFgColor: string;\n readonly cardShadeColor: string;\n readonly dark1: string;\n readonly dark2: string;\n readonly dark3: string;\n readonly dark4: string;\n readonly dark5: string;\n readonly destructiveBgColor: string;\n readonly destructiveColor: string;\n readonly destructiveFgColor: string;\n readonly dialogBackdropBlur: number;\n readonly dialogBackdropColor: string;\n readonly dialogBgColor: string;\n readonly dialogFgColor: string;\n readonly dividerColor: string;\n readonly durationFast: number;\n readonly durationNormal: number;\n readonly durationSlow: number;\n readonly easingDefault: readonly number[];\n readonly errorBgColor: string;\n readonly errorColor: string;\n readonly errorFgColor: string;\n readonly focusRingColor: string;\n readonly focusRingOffset: number;\n readonly focusRingWidth: number;\n readonly fontFamily: string;\n readonly fontFamilyMono: string;\n readonly fontSizeBody: number;\n readonly fontSizeCaption: number;\n readonly fontSizeLargeTitle: number;\n readonly fontSizeTitle1: number;\n readonly fontSizeTitle2: number;\n readonly fontSizeTitle3: number;\n readonly fontSizeTitle4: number;\n readonly fontWeightBold: number;\n readonly fontWeightNormal: number;\n readonly fontWeightSemibold: number;\n readonly green1: string;\n readonly green2: string;\n readonly green3: string;\n readonly green4: string;\n readonly green5: string;\n readonly headerbarBgColor: string;\n readonly headerbarBorderColor: string;\n readonly headerbarFgColor: string;\n readonly headerbarShadeColor: string;\n readonly hoverOverlay: string;\n readonly layoutBreakpointMedium: number;\n readonly layoutBreakpointNarrow: number;\n readonly layoutBreakpointWide: number;\n readonly layoutContentPadding: number;\n readonly layoutContentPaddingCompact: number;\n readonly layoutContentPaddingSpacious: number;\n readonly layoutSidebarDefaultWidth: number;\n readonly layoutSidebarMaxWidth: number;\n readonly layoutSidebarMinWidth: number;\n readonly layoutSidebarRailWidth: number;\n readonly light1: string;\n readonly light2: string;\n readonly light3: string;\n readonly light4: string;\n readonly light5: string;\n readonly lineHeightBody: number;\n readonly lineHeightHeading: number;\n readonly lineHeightTitle: number;\n readonly newBgColor: string;\n readonly newColor: string;\n readonly newFgColor: string;\n readonly opacityBorder: number;\n readonly opacityDim: number;\n readonly opacityDisabled: number;\n readonly orange1: string;\n readonly orange2: string;\n readonly orange3: string;\n readonly orange4: string;\n readonly orange5: string;\n readonly popoverBgColor: string;\n readonly popoverFgColor: string;\n readonly purple1: string;\n readonly purple2: string;\n readonly purple3: string;\n readonly purple4: string;\n readonly purple5: string;\n readonly radiusLg: number;\n readonly radiusMd: number;\n readonly radiusPill: number;\n readonly radiusSm: number;\n readonly radiusXl: number;\n readonly red1: string;\n readonly red2: string;\n readonly red3: string;\n readonly red4: string;\n readonly red5: string;\n readonly sidebarBgColor: string;\n readonly sidebarFgColor: string;\n readonly skeletonBaseColor: string;\n readonly skeletonHighlightColor: string;\n readonly space1: number;\n readonly space2: number;\n readonly space3: number;\n readonly space4: number;\n readonly space5: number;\n readonly space6: number;\n readonly successBgColor: string;\n readonly successColor: string;\n readonly successFgColor: string;\n readonly viewBgColor: string;\n readonly viewFgColor: string;\n readonly warningBgColor: string;\n readonly warningColor: string;\n readonly warningFgColor: string;\n readonly windowBgColor: string;\n readonly windowFgColor: string;\n readonly yellow1: string;\n readonly yellow2: string;\n readonly yellow3: string;\n readonly yellow4: string;\n readonly yellow5: string;\n}\n\nexport const lightTheme: GnomeThemeTokens = {\n accentBgColor: '#3584e4',\n accentColor: '#3584e4',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(0, 0, 0, 0.12)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(0, 0, 0, 0.15)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#fff',\n cardFgColor: 'rgba(0, 0, 0, 0.8)',\n cardShadeColor: 'rgba(0, 0, 0, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#e01b24',\n destructiveColor: '#e01b24',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.5)',\n dialogBgColor: '#fafafa',\n dialogFgColor: 'rgba(0, 0, 0, 0.8)',\n dividerColor: 'rgba(0, 0, 0, 0.07)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#e01b24',\n errorColor: '#e01b24',\n errorFgColor: '#fff',\n focusRingColor: '#3584e4',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#ebebeb',\n headerbarBorderColor: 'rgba(0, 0, 0, 0.12)',\n headerbarFgColor: 'rgba(0, 0, 0, 0.8)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.12)',\n hoverOverlay: 'rgba(0, 0, 0, 0.06)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#9141ac',\n newColor: '#9141ac',\n newFgColor: '#fff',\n opacityBorder: 0.15,\n opacityDim: 0.55,\n opacityDisabled: 0.5,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#fff',\n popoverFgColor: 'rgba(0, 0, 0, 0.8)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#ebebeb',\n sidebarFgColor: 'rgba(0, 0, 0, 0.8)',\n skeletonBaseColor: 'rgba(0, 0, 0, 0.09)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.55)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#2ec27e',\n successColor: '#2ec27e',\n successFgColor: '#fff',\n viewBgColor: '#fff',\n viewFgColor: 'rgba(0, 0, 0, 0.8)',\n warningBgColor: '#f6d32d',\n warningColor: '#e5a50a',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#fafafa',\n windowFgColor: 'rgba(0, 0, 0, 0.8)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const darkTheme: GnomeThemeTokens = {\n accentBgColor: '#3584e4',\n accentColor: '#62a0ea',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(255, 255, 255, 0.14)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(255, 255, 255, 0.15)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#383838',\n cardFgColor: 'rgba(255, 255, 255, 0.87)',\n cardShadeColor: 'rgba(255, 255, 255, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#e01b24',\n destructiveColor: '#e01b24',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.65)',\n dialogBgColor: '#242424',\n dialogFgColor: 'rgba(255, 255, 255, 0.87)',\n dividerColor: 'rgba(255, 255, 255, 0.07)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#e01b24',\n errorColor: '#e01b24',\n errorFgColor: '#fff',\n focusRingColor: '#62a0ea',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#303030',\n headerbarBorderColor: 'rgba(255, 255, 255, 0.1)',\n headerbarFgColor: 'rgba(255, 255, 255, 0.87)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.36)',\n hoverOverlay: 'rgba(255, 255, 255, 0.08)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#9141ac',\n newColor: '#9141ac',\n newFgColor: '#fff',\n opacityBorder: 0.15,\n opacityDim: 0.55,\n opacityDisabled: 0.5,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#383838',\n popoverFgColor: 'rgba(255, 255, 255, 0.87)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#303030',\n sidebarFgColor: 'rgba(255, 255, 255, 0.87)',\n skeletonBaseColor: 'rgba(255, 255, 255, 0.12)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.18)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#2ec27e',\n successColor: '#2ec27e',\n successFgColor: '#fff',\n viewBgColor: '#1e1e1e',\n viewFgColor: 'rgba(255, 255, 255, 0.87)',\n warningBgColor: '#f6d32d',\n warningColor: '#e5a50a',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#242424',\n windowFgColor: 'rgba(255, 255, 255, 0.87)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const highContrastTheme: GnomeThemeTokens = {\n accentBgColor: '#1a5fb4',\n accentColor: '#1a5fb4',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(0, 0, 0, 0.22)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(0, 0, 0, 0.5)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#fff',\n cardFgColor: 'rgba(0, 0, 0, 0.8)',\n cardShadeColor: 'rgba(0, 0, 0, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#a51d2d',\n destructiveColor: '#a51d2d',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.5)',\n dialogBgColor: '#fafafa',\n dialogFgColor: 'rgba(0, 0, 0, 0.8)',\n dividerColor: 'rgba(0, 0, 0, 0.2)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#a51d2d',\n errorColor: '#a51d2d',\n errorFgColor: '#fff',\n focusRingColor: '#1a5fb4',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#ebebeb',\n headerbarBorderColor: 'rgba(0, 0, 0, 0.12)',\n headerbarFgColor: 'rgba(0, 0, 0, 0.8)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.12)',\n hoverOverlay: 'rgba(0, 0, 0, 0.12)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#613583',\n newColor: '#613583',\n newFgColor: '#fff',\n opacityBorder: 0.4,\n opacityDim: 0.7,\n opacityDisabled: 0.6,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#fff',\n popoverFgColor: 'rgba(0, 0, 0, 0.8)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#ebebeb',\n sidebarFgColor: 'rgba(0, 0, 0, 0.8)',\n skeletonBaseColor: 'rgba(0, 0, 0, 0.09)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.55)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#26a269',\n successColor: '#26a269',\n successFgColor: '#fff',\n viewBgColor: '#fff',\n viewFgColor: 'rgba(0, 0, 0, 0.8)',\n warningBgColor: '#e66100',\n warningColor: '#c64600',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#fafafa',\n windowFgColor: 'rgba(0, 0, 0, 0.8)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const highContrastDarkTheme: GnomeThemeTokens = {\n accentBgColor: '#62a0ea',\n accentColor: '#99c1f1',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(255, 255, 255, 0.22)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(255, 255, 255, 0.5)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#383838',\n cardFgColor: '#fff',\n cardShadeColor: 'rgba(255, 255, 255, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#ed333b',\n destructiveColor: '#f66151',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.65)',\n dialogBgColor: '#242424',\n dialogFgColor: '#fff',\n dividerColor: 'rgba(255, 255, 255, 0.2)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#ed333b',\n errorColor: '#f66151',\n errorFgColor: '#fff',\n focusRingColor: '#99c1f1',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#303030',\n headerbarBorderColor: 'rgba(255, 255, 255, 0.3)',\n headerbarFgColor: '#fff',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.36)',\n hoverOverlay: 'rgba(255, 255, 255, 0.12)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#c061cb',\n newColor: '#dc8add',\n newFgColor: '#fff',\n opacityBorder: 0.4,\n opacityDim: 0.7,\n opacityDisabled: 0.6,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#383838',\n popoverFgColor: '#fff',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#303030',\n sidebarFgColor: '#fff',\n skeletonBaseColor: 'rgba(255, 255, 255, 0.12)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.18)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#57e389',\n successColor: '#8ff0a4',\n successFgColor: '#fff',\n viewBgColor: '#1e1e1e',\n viewFgColor: '#fff',\n warningBgColor: '#f8e45c',\n warningColor: '#f9f06b',\n warningFgColor: 'rgba(0, 0, 0, 0.9)',\n windowBgColor: '#242424',\n windowFgColor: '#fff',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const lightRawTokens = {\n '--gnome-accent-bg-color': '#3584e4',\n '--gnome-accent-color': '#3584e4',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(0 0 0 / 0.12)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(0 0 0 / 0.15)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#fff',\n '--gnome-card-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-card-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#e01b24',\n '--gnome-destructive-color': '#e01b24',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.5)',\n '--gnome-dialog-bg-color': '#fafafa',\n '--gnome-dialog-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-divider-color': 'rgb(0 0 0 / 0.07)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#e01b24',\n '--gnome-error-color': '#e01b24',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#3584e4',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#ebebeb',\n '--gnome-headerbar-border-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-headerbar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-hover-overlay': 'rgb(0 0 0 / 0.06)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#9141ac',\n '--gnome-new-color': '#9141ac',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.15',\n '--gnome-opacity-dim': '0.55',\n '--gnome-opacity-disabled': '0.5',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#fff',\n '--gnome-popover-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#ebebeb',\n '--gnome-sidebar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-skeleton-base-color': 'rgb(0 0 0 / 0.09)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.55)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#2ec27e',\n '--gnome-success-color': '#2ec27e',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#fff',\n '--gnome-view-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-warning-bg-color': '#f6d32d',\n '--gnome-warning-color': '#e5a50a',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#fafafa',\n '--gnome-window-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const darkRawTokens = {\n '--gnome-accent-bg-color': '#3584e4',\n '--gnome-accent-color': '#62a0ea',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(255 255 255 / 0.14)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(255 255 255 / 0.15)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#383838',\n '--gnome-card-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-card-shade-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#e01b24',\n '--gnome-destructive-color': '#e01b24',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.65)',\n '--gnome-dialog-bg-color': '#242424',\n '--gnome-dialog-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-divider-color': 'rgb(255 255 255 / 0.07)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#e01b24',\n '--gnome-error-color': '#e01b24',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#62a0ea',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#303030',\n '--gnome-headerbar-border-color': 'rgb(255 255 255 / 0.1)',\n '--gnome-headerbar-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.36)',\n '--gnome-hover-overlay': 'rgb(255 255 255 / 0.08)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#9141ac',\n '--gnome-new-color': '#9141ac',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.15',\n '--gnome-opacity-dim': '0.55',\n '--gnome-opacity-disabled': '0.5',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#383838',\n '--gnome-popover-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#303030',\n '--gnome-sidebar-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-skeleton-base-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.18)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#2ec27e',\n '--gnome-success-color': '#2ec27e',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#1e1e1e',\n '--gnome-view-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-warning-bg-color': '#f6d32d',\n '--gnome-warning-color': '#e5a50a',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#242424',\n '--gnome-window-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const highContrastRawTokens = {\n '--gnome-accent-bg-color': '#1a5fb4',\n '--gnome-accent-color': '#1a5fb4',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(0 0 0 / 0.22)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(0 0 0 / 0.5)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#fff',\n '--gnome-card-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-card-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#a51d2d',\n '--gnome-destructive-color': '#a51d2d',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.5)',\n '--gnome-dialog-bg-color': '#fafafa',\n '--gnome-dialog-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-divider-color': 'rgb(0 0 0 / 0.2)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#a51d2d',\n '--gnome-error-color': '#a51d2d',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#1a5fb4',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#ebebeb',\n '--gnome-headerbar-border-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-headerbar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-hover-overlay': 'rgb(0 0 0 / 0.12)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#613583',\n '--gnome-new-color': '#613583',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.4',\n '--gnome-opacity-dim': '0.7',\n '--gnome-opacity-disabled': '0.6',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#fff',\n '--gnome-popover-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#ebebeb',\n '--gnome-sidebar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-skeleton-base-color': 'rgb(0 0 0 / 0.09)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.55)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#26a269',\n '--gnome-success-color': '#26a269',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#fff',\n '--gnome-view-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-warning-bg-color': '#e66100',\n '--gnome-warning-color': '#c64600',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#fafafa',\n '--gnome-window-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const highContrastDarkRawTokens = {\n '--gnome-accent-bg-color': '#62a0ea',\n '--gnome-accent-color': '#99c1f1',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(255 255 255 / 0.22)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(255 255 255 / 0.5)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#383838',\n '--gnome-card-fg-color': '#fff',\n '--gnome-card-shade-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#ed333b',\n '--gnome-destructive-color': '#f66151',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.65)',\n '--gnome-dialog-bg-color': '#242424',\n '--gnome-dialog-fg-color': '#fff',\n '--gnome-divider-color': 'rgb(255 255 255 / 0.2)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#ed333b',\n '--gnome-error-color': '#f66151',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#99c1f1',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#303030',\n '--gnome-headerbar-border-color': 'rgb(255 255 255 / 0.3)',\n '--gnome-headerbar-fg-color': '#fff',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.36)',\n '--gnome-hover-overlay': 'rgb(255 255 255 / 0.12)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#c061cb',\n '--gnome-new-color': '#dc8add',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.4',\n '--gnome-opacity-dim': '0.7',\n '--gnome-opacity-disabled': '0.6',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#383838',\n '--gnome-popover-fg-color': '#fff',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#303030',\n '--gnome-sidebar-fg-color': '#fff',\n '--gnome-skeleton-base-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.18)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#57e389',\n '--gnome-success-color': '#8ff0a4',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#1e1e1e',\n '--gnome-view-fg-color': '#fff',\n '--gnome-warning-bg-color': '#f8e45c',\n '--gnome-warning-color': '#f9f06b',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.9)',\n '--gnome-window-bg-color': '#242424',\n '--gnome-window-fg-color': '#fff',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n","import { createContext, useContext, useMemo } from 'react';\nimport type { GnomeResolvedColorScheme, GnomeResolvedContrast } from '@/theme/resolveTheme';\nimport type { GnomeThemeTokens } from '@/theme/tokens.generated';\nimport { lightTheme } from '@/theme/tokens.generated';\nimport type { GnomeAccentColor, GnomeColorScheme, GnomeContrast, GnomeDir } from './resolveContext';\n\nexport interface GnomeContextValue {\n locale: string | undefined;\n dir: GnomeDir;\n numberFormat: Intl.NumberFormatOptions | undefined;\n dateTimeFormat: Intl.DateTimeFormatOptions | undefined;\n colorScheme: GnomeColorScheme;\n resolvedColorScheme: GnomeResolvedColorScheme;\n contrast: GnomeContrast;\n resolvedContrast: GnomeResolvedContrast;\n accentColor: GnomeAccentColor;\n theme: GnomeThemeTokens;\n}\n\nexport const GnomeContext = createContext<GnomeContextValue>({\n locale: undefined,\n dir: 'ltr',\n numberFormat: undefined,\n dateTimeFormat: undefined,\n colorScheme: 'system',\n resolvedColorScheme: 'light',\n contrast: 'system',\n resolvedContrast: 'normal',\n accentColor: 'blue',\n theme: lightTheme,\n});\n\n/** Returns the locale set by the nearest `GnomeProvider`, or `undefined` to use the device locale. */\nexport function useLocale(): string | undefined {\n return useContext(GnomeContext).locale;\n}\n\n/** Returns the text direction set by the nearest `GnomeProvider`. Defaults to the app's `I18nManager.isRTL` state. */\nexport function useDir(): GnomeDir {\n return useContext(GnomeContext).dir;\n}\n\n/** Returns an `Intl.NumberFormat` configured from `GnomeProvider` defaults plus local overrides. */\nexport function useNumberFormatter(options?: Intl.NumberFormatOptions): Intl.NumberFormat {\n const { locale, numberFormat } = useContext(GnomeContext);\n\n return useMemo(\n () => new Intl.NumberFormat(locale, { ...numberFormat, ...options }),\n [locale, numberFormat, options],\n );\n}\n\n/** Returns an `Intl.DateTimeFormat` configured from `GnomeProvider` defaults plus local overrides. */\nexport function useDateTimeFormatter(options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const { locale, dateTimeFormat } = useContext(GnomeContext);\n\n return useMemo(\n () => new Intl.DateTimeFormat(locale, { ...dateTimeFormat, ...options }),\n [locale, dateTimeFormat, options],\n );\n}\n\n/** Returns the color scheme preference set by the nearest `GnomeProvider`. Defaults to `\"system\"`. */\nexport function useColorScheme(): GnomeColorScheme {\n return useContext(GnomeContext).colorScheme;\n}\n\n/** Returns the resolved color scheme (`\"light\"` or `\"dark\"`), accounting for the OS preference when `colorScheme` is `\"system\"`. */\nexport function useResolvedColorScheme(): GnomeResolvedColorScheme {\n return useContext(GnomeContext).resolvedColorScheme;\n}\n\n/** Returns the contrast preference set by the nearest `GnomeProvider`. Defaults to `\"system\"`. */\nexport function useContrast(): GnomeContrast {\n return useContext(GnomeContext).contrast;\n}\n\n/** Returns the resolved contrast (`\"normal\"` or `\"more\"`), accounting for the OS accessibility setting when `contrast` is `\"system\"`. */\nexport function useResolvedContrast(): GnomeResolvedContrast {\n return useContext(GnomeContext).resolvedContrast;\n}\n\n/** Returns the accent color set by the nearest `GnomeProvider`. Defaults to `\"blue\"`. */\nexport function useAccentColor(): GnomeAccentColor {\n return useContext(GnomeContext).accentColor;\n}\n\n/** Returns the fully-resolved theme tokens (colors, spacing, typography, …) for the nearest `GnomeProvider`, accent-adjusted. */\nexport function useGnomeTheme(): GnomeThemeTokens {\n return useContext(GnomeContext).theme;\n}\n","import type { GnomeThemeTokens } from './tokens.generated';\nimport {\n darkTheme,\n highContrastDarkTheme,\n highContrastTheme,\n lightTheme,\n} from './tokens.generated';\n\nexport type GnomeResolvedColorScheme = 'light' | 'dark';\nexport type GnomeResolvedContrast = 'normal' | 'more';\n\nexport interface ResolveGnomeThemeOptions {\n colorScheme: GnomeResolvedColorScheme;\n /** @default 'normal' */\n contrast?: GnomeResolvedContrast;\n}\n\nexport function resolveGnomeTheme({\n colorScheme,\n contrast = 'normal',\n}: ResolveGnomeThemeOptions): GnomeThemeTokens {\n if (contrast === 'more') {\n return colorScheme === 'dark' ? highContrastDarkTheme : highContrastTheme;\n }\n\n return colorScheme === 'dark' ? darkTheme : lightTheme;\n}\n","import type { GnomeResolvedColorScheme, GnomeResolvedContrast } from '@/theme/resolveTheme';\nimport type { GnomeThemeTokens } from '@/theme/tokens.generated';\n\nexport type GnomeColorScheme = GnomeResolvedColorScheme | 'system';\nexport type GnomeContrast = GnomeResolvedContrast | 'system';\nexport type GnomeDir = 'ltr' | 'rtl';\nexport type GnomeNamedAccentColor =\n | 'blue'\n | 'green'\n | 'yellow'\n | 'orange'\n | 'red'\n | 'purple'\n | 'brown';\nexport type GnomeAccentColor = GnomeNamedAccentColor | (string & {});\n\nexport const NAMED_ACCENT_COLORS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\n/**\n * Resolves a `'light' | 'dark' | 'system'` preference against the OS color\n * scheme. `systemColorScheme` is typed loosely (rather than as\n * `GnomeResolvedColorScheme`) so RN's `useColorScheme()` — which can also\n * report `'unspecified'` on Android, besides `null`/`undefined` — can be\n * passed straight through; anything other than `'dark'` resolves to light.\n */\nexport function resolveColorScheme(\n preference: GnomeColorScheme,\n systemColorScheme: string | null | undefined,\n): GnomeResolvedColorScheme {\n if (preference !== 'system') {\n return preference;\n }\n\n return systemColorScheme === 'dark' ? 'dark' : 'light';\n}\n\n/** Resolves a `'normal' | 'more' | 'system'` preference against the OS high-contrast setting. */\nexport function resolveContrast(\n preference: GnomeContrast,\n systemHighContrast: boolean,\n): GnomeResolvedContrast {\n if (preference !== 'system') {\n return preference;\n }\n\n return systemHighContrast ? 'more' : 'normal';\n}\n\n/**\n * Returns `theme` with `accentColor`/`accentBgColor` (and, outside\n * high-contrast, `focusRingColor`) overridden for a non-default accent.\n *\n * Named palette colors (`\"green\"`, `\"red\"`, …) resolve to the matching\n * Adwaita shade for the current color scheme, mirroring\n * `@gnome-ui/react`'s `GnomeProvider`. High-contrast variants keep their\n * own fixed, maximum-contrast focus ring regardless of accent — the same\n * behavior `tokens.css` encodes by not deriving it from `--gnome-accent-color`\n * under `prefers-contrast: more`.\n */\nexport function applyAccentColor(\n theme: GnomeThemeTokens,\n accentColor: GnomeAccentColor,\n resolvedColorScheme: GnomeResolvedColorScheme,\n resolvedContrast: GnomeResolvedContrast,\n): GnomeThemeTokens {\n if (accentColor === 'blue') {\n return theme;\n }\n\n const isNamed = NAMED_ACCENT_COLORS.has(accentColor as GnomeNamedAccentColor);\n const shade = resolvedColorScheme === 'dark' ? 2 : 3;\n const accent = isNamed\n ? (theme[`${accentColor}${shade}` as keyof GnomeThemeTokens] as string)\n : accentColor;\n const accentBg = isNamed\n ? (theme[`${accentColor}3` as keyof GnomeThemeTokens] as string)\n : accentColor;\n\n return {\n ...theme,\n accentColor: accent,\n accentBgColor: accentBg,\n ...(resolvedContrast === 'normal' ? { focusRingColor: accent } : {}),\n };\n}\n","import type { ReactNode } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n AccessibilityInfo,\n I18nManager,\n Platform,\n useColorScheme as useSystemColorScheme,\n} from 'react-native';\nimport { resolveGnomeTheme } from '@/theme/resolveTheme';\nimport { GnomeContext } from './GnomeContext';\nimport type { GnomeAccentColor, GnomeColorScheme, GnomeContrast, GnomeDir } from './resolveContext';\nimport { applyAccentColor, resolveColorScheme, resolveContrast } from './resolveContext';\n\nexport interface GnomeProviderProps {\n /** BCP 47 locale tag (e.g. `\"es-ES\"`, `\"de-DE\"`). When omitted, components fall back to the device locale. */\n locale?: string;\n /**\n * Text direction exposed via context for consumers to branch on (e.g.\n * mirroring icons or flipping a row's layout). Defaults to the app's\n * actual `I18nManager.isRTL` state.\n *\n * Unlike the web `GnomeProvider`, this does **not** call\n * `I18nManager.forceRTL()` — RN's layout direction is a single global\n * flag that requires an app reload to take effect and is normally set\n * once at app bootstrap, not scoped per provider tree.\n */\n dir?: GnomeDir;\n /**\n * Global defaults for number formatting.\n *\n * Use `{ notation: \"compact\", compactDisplay: \"short\" }` for compact\n * values such as `1K`; omit it or set `{ notation: \"standard\" }` for\n * full values such as `1,000`.\n */\n numberFormat?: Intl.NumberFormatOptions;\n /** Global defaults for date/time formatting. */\n dateTimeFormat?: Intl.DateTimeFormatOptions;\n /**\n * Color scheme preference. `\"system\"` (default) follows\n * `Appearance`/`useColorScheme()`. `\"light\"`/`\"dark\"` force that scheme\n * regardless of the OS setting.\n * @default 'system'\n */\n colorScheme?: GnomeColorScheme;\n /**\n * High-contrast preference. `\"system\"` (default) follows the OS\n * accessibility setting where one exists — Android's \"High text\n * contrast\" (`AccessibilityInfo.isHighTextContrastEnabled`) or iOS's\n * \"Increase Contrast\" (`AccessibilityInfo.isDarkerSystemColorsEnabled`)\n * — and falls back to `\"normal\"` where neither is available (e.g. web).\n * @default 'system'\n */\n contrast?: GnomeContrast;\n /**\n * Accent color. Accepts a named GNOME palette color (`\"blue\"`, `\"green\"`,\n * `\"yellow\"`, `\"orange\"`, `\"red\"`, `\"purple\"`, `\"brown\"`) or any RN color\n * string (e.g. `\"#ff0000\"`, `\"rgba(0, 0, 0, 0.5)\"`). Named colors are\n * theme-aware and use the correct shade for light/dark mode\n * automatically. Defaults to `\"blue\"`.\n */\n accentColor?: GnomeAccentColor;\n children: ReactNode;\n}\n\n/**\n * Subscribes to the OS high-contrast accessibility setting.\n *\n * Android exposes \"High text contrast\"; iOS exposes \"Increase Contrast\"\n * (surfaced through `AccessibilityInfo`'s \"darker system colors\" API,\n * which is what that setting maps to natively). Neither exists on other\n * platforms, so this resolves to `false` there.\n */\nfunction useSystemHighContrast(): boolean {\n const [enabled, setEnabled] = useState(false);\n\n useEffect(() => {\n const query =\n Platform.OS === 'android'\n ? AccessibilityInfo.isHighTextContrastEnabled\n : Platform.OS === 'ios'\n ? AccessibilityInfo.isDarkerSystemColorsEnabled\n : undefined;\n\n if (!query) {\n return;\n }\n\n let mounted = true;\n\n (async () => {\n const value = await query();\n\n if (mounted) {\n setEnabled(value);\n }\n })();\n\n const eventName =\n Platform.OS === 'android' ? 'highTextContrastChanged' : 'darkerSystemColorsChanged';\n const subscription = AccessibilityInfo.addEventListener(eventName, setEnabled);\n\n return () => {\n mounted = false;\n subscription.remove();\n };\n }, []);\n\n return enabled;\n}\n\n/**\n * Returns `true` when the OS \"Reduce Motion\" accessibility setting is on\n * (iOS Settings > Accessibility > Motion, Android Settings >\n * Accessibility > Remove animations), for components with a continuously\n * looping `Animated` value (e.g. `Spinner`) to slow down or skip that\n * animation. Unlike `contrast`/`colorScheme`, the web `GnomeProvider` has\n * no corresponding override prop — `prefers-reduced-motion` is a pure CSS\n * media query there, always OS-driven — so this hook mirrors that: it\n * reads `AccessibilityInfo` directly and isn't scoped to `GnomeProvider`'s\n * context, unlike every other hook in this package. `isReduceMotionEnabled`\n * / `reduceMotionChanged` are supported on both iOS and Android (unlike\n * the high-contrast APIs above, which are platform-specific), so no\n * `Platform.OS` branch is needed.\n */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useReducedMotion(): boolean {\n const [enabled, setEnabled] = useState(false);\n\n useEffect(() => {\n let mounted = true;\n\n (async () => {\n const value = await AccessibilityInfo.isReduceMotionEnabled();\n\n if (mounted) {\n setEnabled(value);\n }\n })();\n\n const subscription = AccessibilityInfo.addEventListener('reduceMotionChanged', setEnabled);\n\n return () => {\n mounted = false;\n subscription.remove();\n };\n }, []);\n\n return enabled;\n}\n\n/** Provides locale, text direction, color scheme, contrast, accent color, and resolved theme tokens to all descendant gnome-ui components. */\nexport const GnomeProvider = ({\n locale,\n dir,\n numberFormat,\n dateTimeFormat,\n colorScheme = 'system',\n contrast = 'system',\n accentColor = 'blue',\n children,\n}: GnomeProviderProps) => {\n const systemColorScheme = useSystemColorScheme();\n const systemHighContrast = useSystemHighContrast();\n\n const resolvedColorScheme = resolveColorScheme(colorScheme, systemColorScheme);\n const resolvedContrast = resolveContrast(contrast, systemHighContrast);\n const resolvedDir = dir ?? (I18nManager.isRTL ? 'rtl' : 'ltr');\n\n const value = useMemo(() => {\n const variantTheme = resolveGnomeTheme({\n colorScheme: resolvedColorScheme,\n contrast: resolvedContrast,\n });\n const theme = applyAccentColor(\n variantTheme,\n accentColor,\n resolvedColorScheme,\n resolvedContrast,\n );\n\n return {\n locale,\n dir: resolvedDir,\n numberFormat,\n dateTimeFormat,\n colorScheme,\n resolvedColorScheme,\n contrast,\n resolvedContrast,\n accentColor,\n theme,\n };\n }, [\n locale,\n resolvedDir,\n numberFormat,\n dateTimeFormat,\n colorScheme,\n resolvedColorScheme,\n contrast,\n resolvedContrast,\n accentColor,\n ]);\n\n return <GnomeContext.Provider value={value}>{children}</GnomeContext.Provider>;\n};\n","import { forwardRef } from 'react';\nimport type { AccessibilityRole, TextProps as RNTextProps, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type TextVariant =\n | 'large-title'\n | 'title-1'\n | 'title-2'\n | 'title-3'\n | 'title-4'\n | 'heading'\n | 'body'\n | 'document'\n | 'caption'\n | 'caption-heading'\n | 'monospace'\n | 'numeric';\n\nexport type TextColor =\n | 'default'\n | 'dim'\n | 'accent'\n | 'destructive'\n | 'success'\n | 'warning'\n | 'error';\n\n/**\n * Variants the web component renders as `<h1>`–`<h4>`. RN has no heading\n * elements, so they default to the `header` accessibility role instead —\n * the closest native equivalent, and what VoiceOver/TalkBack use to build\n * their heading rotor.\n */\nconst HEADING_VARIANTS: ReadonlySet<TextVariant> = new Set<TextVariant>([\n 'large-title',\n 'title-1',\n 'title-2',\n 'title-3',\n 'title-4',\n 'heading',\n]);\n\nexport interface TextProps extends RNTextProps {\n /** Typography style. Mirrors Adwaita / GNOME HIG text styles. */\n variant?: TextVariant;\n /** Semantic color. */\n color?: TextColor;\n children?: RNTextProps['children'];\n}\n\n/**\n * CSS `line-height` ratios and `letter-spacing` `em` values are relative;\n * RN wants absolute dp for both, so they're resolved against the variant's\n * own font size here.\n */\nfunction getVariantStyle(theme: GnomeThemeTokens, variant: TextVariant): TextStyle {\n const weight = (value: number) => String(value) as TextStyle['fontWeight'];\n\n switch (variant) {\n case 'large-title':\n return {\n fontSize: theme.fontSizeLargeTitle,\n fontWeight: weight(300),\n lineHeight: Math.round(theme.fontSizeLargeTitle * theme.lineHeightHeading),\n letterSpacing: theme.fontSizeLargeTitle * -0.02,\n };\n case 'title-1':\n return {\n fontSize: theme.fontSizeTitle1,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle1 * theme.lineHeightHeading),\n };\n case 'title-2':\n return {\n fontSize: theme.fontSizeTitle2,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle2 * theme.lineHeightHeading),\n };\n case 'title-3':\n return {\n fontSize: theme.fontSizeTitle3,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle3 * theme.lineHeightHeading),\n };\n case 'title-4':\n return {\n fontSize: theme.fontSizeTitle4,\n fontWeight: weight(theme.fontWeightSemibold),\n lineHeight: Math.round(theme.fontSizeTitle4 * theme.lineHeightHeading),\n };\n case 'heading':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightHeading),\n };\n case 'document':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * 1.65),\n };\n case 'caption':\n return {\n fontSize: theme.fontSizeCaption,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeCaption * theme.lineHeightBody),\n };\n case 'caption-heading':\n return {\n fontSize: theme.fontSizeCaption,\n fontWeight: weight(theme.fontWeightSemibold),\n lineHeight: Math.round(theme.fontSizeCaption * theme.lineHeightHeading),\n letterSpacing: theme.fontSizeCaption * 0.06,\n textTransform: 'uppercase',\n };\n case 'monospace':\n return {\n fontFamily: theme.fontFamilyMono,\n fontSize: 14,\n lineHeight: Math.round(14 * theme.lineHeightBody),\n };\n case 'numeric':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n fontVariant: ['tabular-nums'],\n };\n default:\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n };\n }\n}\n\n/**\n * `dim` is an opacity in the web stylesheet rather than a color, so it stays\n * an opacity here — that keeps it correct against any background, the same\n * way `.color-dim` does.\n */\nfunction getColorStyle(theme: GnomeThemeTokens, color: TextColor): TextStyle {\n switch (color) {\n case 'dim':\n return { color: theme.windowFgColor, opacity: theme.opacityDim };\n case 'accent':\n return { color: theme.accentColor };\n case 'destructive':\n return { color: theme.destructiveColor };\n case 'success':\n return { color: theme.successColor };\n case 'warning':\n return { color: theme.warningColor };\n case 'error':\n return { color: theme.errorColor };\n default:\n return { color: theme.windowFgColor };\n }\n}\n\n/**\n * Text component following GNOME Human Interface Guidelines typography styles.\n *\n * Variants map directly to Adwaita style classes:\n * `large-title`, `title-1`–`title-4`, `heading`, `body`, `document`,\n * `caption`, `caption-heading`, `monospace`, `numeric`.\n *\n * Rebuilt on RN's `Text` rather than ported from `@gnome-ui/react`'s DOM-based\n * JSX: there is no element to pick, so `@gnome-ui/react`'s `as` prop is\n * replaced by `accessibilityRole`, which the heading variants default to\n * `\"header\"`.\n *\n * @see https://developer.gnome.org/hig/guidelines/typography.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n */\nexport const Text = forwardRef<RNText, TextProps>(function Text(\n { variant = 'body', color = 'default', style, children, accessibilityRole, ...textProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const role: AccessibilityRole | undefined =\n accessibilityRole ?? (HEADING_VARIANTS.has(variant) ? 'header' : undefined);\n\n return (\n <RNText\n ref={ref}\n accessibilityRole={role}\n style={[\n { fontFamily: theme.fontFamily },\n getVariantStyle(theme, variant),\n getColorStyle(theme, color),\n style,\n ]}\n {...textProps}\n >\n {children}\n </RNText>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView, StyleSheet } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type ActionRowVariant = 'default' | 'property';\n\nexport interface ActionRowProps extends Omit<PressableProps, 'children' | 'style'> {\n /** Primary label. */\n title: string;\n /** Secondary line below the title. */\n subtitle?: string;\n /** Icon or image placed at the leading edge. Rendered as-is — size/color it yourself. */\n leading?: ReactNode;\n /**\n * Widget placed at the trailing edge (`Switch`, `Button`, `Text`…).\n * For interactive end widgets prefer a controlled component and stop\n * event propagation inside it so the row's own `onPress` isn't triggered.\n */\n trailing?: ReactNode;\n /**\n * When true the entire row becomes pressable (renders as `Pressable`\n * with `accessibilityRole=\"button\"`). Use for rows that navigate or\n * trigger an action.\n */\n interactive?: boolean;\n /**\n * `\"property\"` flips the visual hierarchy: the subtitle becomes the\n * prominent value and the title shrinks to a dim label above it.\n * Use for read-only property display (e.g. \"OS Version / GNOME 50\").\n * Mirrors the `.property` style class.\n */\n variant?: ActionRowVariant;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Standard settings row with title, optional subtitle, and end widget.\n *\n * Mirrors the Adwaita `AdwActionRow` pattern — the fundamental building\n * block inside a `BoxedList`.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s `<button>`/`<div>` — same `interactive` split as\n * `Card`: a pressed-state overlay tinted by `theme.activeOverlay` stands in\n * for the web's `:hover`/`:active` `background-color` transitions, since RN\n * has no hover state on touch devices and no `color-mix()`. `title`/\n * `subtitle` reuse the library's own `Text` component (`variant=\"body\"`/\n * `\"caption\"`, `color=\"dim\"`) instead of hand-rolled styles, with\n * `numberOfLines={1}` standing in for the web's CSS\n * `text-overflow: ellipsis` truncation.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ActionRow.html\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const ActionRow = forwardRef<View, ActionRowProps>(function ActionRow(\n {\n title,\n subtitle,\n leading,\n trailing,\n interactive = false,\n variant = 'default',\n style,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const property = variant === 'property';\n\n const baseStyle: ViewStyle = {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: theme.space2,\n paddingHorizontal: theme.space4,\n minHeight: 52,\n width: '100%',\n };\n\n const content = (\n <>\n {leading && <RNView style={{ flexShrink: 0 }}>{leading}</RNView>}\n\n <RNView style={{ flex: 1, gap: 2 }}>\n <Text\n variant={property ? 'caption' : 'body'}\n color={property ? 'dim' : 'default'}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {title}\n </Text>\n {subtitle && (\n <Text\n variant={property ? 'body' : 'caption'}\n color={property ? 'default' : 'dim'}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {subtitle}\n </Text>\n )}\n </RNView>\n\n {trailing && (\n <RNView\n style={{ flexShrink: 0, flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}\n >\n {trailing}\n </RNView>\n )}\n </>\n );\n\n if (!interactive) {\n return (\n <RNView ref={ref} style={[baseStyle, style]} {...pressableProps}>\n {content}\n </RNView>\n );\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={[\n baseStyle,\n { position: 'relative', opacity: disabled ? theme.opacityDisabled : 1 },\n style,\n ]}\n {...pressableProps}\n >\n {({ pressed }) => (\n <>\n {content}\n {pressed && !disabled ? (\n <RNView\n pointerEvents=\"none\"\n style={[StyleSheet.absoluteFill, { backgroundColor: theme.activeOverlay }]}\n />\n ) : null}\n </>\n )}\n </Pressable>\n );\n});\n","import type { useGnomeTheme } from '@/GnomeProvider';\nimport type { IconColor, IconSize } from './Icon';\n\n/**\n * Non-component helpers shared between `Icon` and `AnimatedIcon` — kept in\n * their own module (not exported from `Icon.tsx` itself) so both files stay\n * component-only for Fast Refresh, per the project's `react-refresh/\n * only-export-components` lint rule.\n */\n\nexport const ICON_SIZE_MAP: Record<IconSize, number> = { sm: 12, md: 16, lg: 20 };\n\nexport function resolveIconColor(\n theme: ReturnType<typeof useGnomeTheme>,\n color: IconColor | undefined,\n) {\n switch (color) {\n case 'blue':\n return theme.blue3;\n case 'green':\n return theme.green4;\n case 'yellow':\n return theme.yellow4;\n case 'orange':\n return theme.orange3;\n case 'red':\n return theme.red3;\n case 'purple':\n return theme.purple3;\n case 'brown':\n return theme.brown3;\n default:\n return theme.windowFgColor;\n }\n}\n\nexport function iconAccessibilityProps(label: string | undefined) {\n return label\n ? { accessible: true as const, accessibilityLabel: label, accessibilityRole: 'image' as const }\n : { accessible: false as const, accessibilityRole: 'none' as const };\n}\n","import type { AnyIconDefinition, IconDefinition } from '@gnome-ui/icons';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { Path, Svg, SvgXml } from 'react-native-svg';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { ICON_SIZE_MAP, iconAccessibilityProps, resolveIconColor } from './shared';\n\nexport type IconSize = 'sm' | 'md' | 'lg';\n\n/** Named GNOME palette color for the icon. `\"default\"` (or omitting the prop) resolves to the theme's default foreground color. */\nexport type IconColor =\n | 'default'\n | 'blue'\n | 'green'\n | 'yellow'\n | 'orange'\n | 'red'\n | 'purple'\n | 'brown';\n\nexport interface IconProps {\n /** Icon from `@gnome-ui/icons`, a `simple-icons` icon, or a raw `{ path }` object. */\n icon: AnyIconDefinition;\n /**\n * Rendered size.\n * - `sm` — 12 px\n * - `md` — 16 px (default)\n * - `lg` — 20 px\n *\n * Override with `width`/`height` for non-standard sizes.\n */\n size?: IconSize;\n width?: number;\n height?: number;\n /** Accessible label. Omit for decorative icons — they are hidden from screen readers. */\n label?: string;\n /**\n * Named GNOME palette color. Omit (or pass `\"default\"`) to use the\n * theme's default foreground color — RN has no `currentColor`\n * equivalent to inherit from a parent, unlike the web version.\n */\n color?: IconColor;\n /** Forwarded to the underlying `Svg` — useful for a `transform` (e.g. a rotated disclosure chevron) or `margin`. */\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * `icon.paths` present → `IconDefinition` with structured path data.\n * `icon.svg` present (and no `paths`) → `IconDefinition` carrying raw markup\n * (the `animated` icons — see `AnimatedIcon`).\n * Neither → `RawPathIconDefinition` (e.g. a `simple-icons` `SimpleIcon`,\n * which has its own unrelated `svg` field alongside `path` — checking\n * `path` is absent, not just that `svg` is a string, is what keeps those\n * correctly classified below instead of misread as an internal\n * `IconDefinition`). Duplicated from `@gnome-ui/react`'s `Icon.tsx` rather\n * than shared — see that component for the full reasoning.\n */\nfunction isIconDefinition(icon: AnyIconDefinition): icon is IconDefinition {\n if ('paths' in icon && Array.isArray((icon as IconDefinition).paths)) {\n return true;\n }\n\n return typeof (icon as IconDefinition).svg === 'string' && !('path' in icon);\n}\n\n/** `react-native-svg`'s `FillRule` has no `\"inherit\"` member (unlike `IconPath`'s, kept for CSS-source-of-truth completeness) — a leaf `<path>` has nothing to inherit from, so it maps to the SVG default (omitted attribute). */\nfunction fillRule(rule: 'nonzero' | 'evenodd' | 'inherit' | undefined) {\n return rule === 'nonzero' || rule === 'evenodd' ? rule : undefined;\n}\n\n/**\n * Renders an icon as an inline SVG, via `react-native-svg`.\n *\n * Accepts icons from `@gnome-ui/icons`, any `simple-icons` icon, or a plain\n * `{ path }` object — same `AnyIconDefinition` union as `@gnome-ui/react`'s\n * `Icon`. Pass `label` only when the icon conveys meaning on its own.\n *\n * `animated` icons (`Syncing`, `Recording`, …) carry raw `svg` markup\n * instead of `paths` — rendered here through `SvgXml`, which parses the\n * structural elements (`<g>`/`<path>`/`<circle>`) but has no CSS engine, so\n * the embedded `<style>`/`@keyframes` block is silently dropped and the\n * shapes render at their authored rest position. That happens to be exactly\n * the desired \"inert, static frame\" behavior for a plain `<Icon>` — no\n * special-casing needed here; wrap in `<AnimatedIcon>` to actually play the\n * motion (RN has to hand-build that with `Animated`, since there is no CSS\n * animation engine to interpret the markup's keyframes).\n *\n * @example\n * import { Search } from \"@gnome-ui/icons\";\n * <Icon icon={Search} label=\"Search\" />\n *\n * @example\n * import { siGithub } from \"simple-icons\";\n * <Icon icon={siGithub} label=\"GitHub\" />\n */\nexport const Icon = ({ icon, size = 'md', width, height, label, color, style }: IconProps) => {\n const theme = useGnomeTheme();\n const px = ICON_SIZE_MAP[size];\n const fill = resolveIconColor(theme, color);\n\n const resolvedViewBox = isIconDefinition(icon) ? icon.viewBox : (icon.viewBox ?? '0 0 24 24');\n const rawSvg = isIconDefinition(icon) ? icon.svg : undefined;\n const paths = isIconDefinition(icon)\n ? icon.svg\n ? undefined\n : icon.paths?.map((p, i) => (\n <Path\n key={i}\n d={p.d}\n fillRule={fillRule(p.fillRule)}\n clipRule={fillRule(p.clipRule)}\n transform={p.transform}\n />\n ))\n : [<Path key={0} d={icon.path} />];\n\n const accessibilityProps = iconAccessibilityProps(label);\n\n if (rawSvg) {\n return (\n <SvgXml\n xml={`<svg viewBox=\"${resolvedViewBox}\">${rawSvg}</svg>`}\n width={width ?? px}\n height={height ?? px}\n fill={fill}\n style={style}\n {...accessibilityProps}\n />\n );\n }\n\n return (\n <Svg\n viewBox={resolvedViewBox}\n width={width ?? px}\n height={height ?? px}\n fill={fill}\n style={style}\n {...accessibilityProps}\n >\n {paths}\n </Svg>\n );\n};\n","import { Connecting, Downloading, type IconDefinition, Recording, Syncing } from '@gnome-ui/icons';\nimport { type ComponentType, useEffect, useRef } from 'react';\nimport { Animated, Easing } from 'react-native';\nimport { Circle, G, Path, Svg } from 'react-native-svg';\nimport type { IconProps } from '@/components/Icon';\nimport { Icon } from '@/components/Icon';\nimport { ICON_SIZE_MAP, iconAccessibilityProps, resolveIconColor } from '@/components/Icon/shared';\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport interface AnimatedIconProps extends Omit<IconProps, 'icon'> {\n /** Animated icon from `@gnome-ui/icons` (`animated: true` — `Syncing`, `Recording`, `Downloading`, `Connecting`). */\n icon: IconDefinition;\n /**\n * Whether the animation plays. Defaults to `true`.\n *\n * Regardless of this prop, the animation is always paused when the OS\n * reduced-motion setting is on — callers don't need to check\n * `useReducedMotion()` themselves.\n */\n playing?: boolean;\n}\n\n/**\n * `Animated`'s style/prop interpolation only takes effect on `Animated.*`\n * host components — the same gotcha already documented on `Toast`/`Dialog`,\n * here applied to `react-native-svg`'s shape components instead of `View`/\n * `Pressable`. Hoisted to module scope so they aren't recreated per render.\n */\nconst AnimatedG = Animated.createAnimatedComponent(G);\nconst AnimatedPath = Animated.createAnimatedComponent(Path);\nconst AnimatedCircle = Animated.createAnimatedComponent(Circle);\n\ninterface MotionProps {\n fill: string;\n}\n\n/** Drives a `0 → 1` value on an infinite loop. Used wherever the whole motion can be expressed as one `interpolate()` off a single linear driver. */\nfunction useLoopingProgress(duration: number) {\n const value = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n const animation = Animated.loop(\n Animated.timing(value, {\n toValue: 1,\n duration,\n easing: Easing.linear,\n useNativeDriver: false,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [value, duration]);\n\n return value;\n}\n\n/** Same as `useLoopingProgress`, but the repeating loop only starts after an initial one-time `delay` — for staggering identical cycles (`Connecting`'s three dots) out of phase with each other. */\nfunction useDelayedLoopingProgress(duration: number, delay: number) {\n const value = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n const animation = Animated.sequence([\n Animated.delay(delay),\n Animated.loop(\n Animated.timing(value, {\n toValue: 1,\n duration,\n easing: Easing.linear,\n useNativeDriver: false,\n }),\n ),\n ]);\n\n animation.start();\n\n return () => animation.stop();\n }, [value, duration, delay]);\n\n return value;\n}\n\n/**\n * `emblem-synchronizing-symbolic` — rotates a full turn, 1.5s linear, mirroring\n * `@gnome-ui/icons`' `Syncing.svg` `@keyframes gicon-syncing-rotate`.\n * Reuses `Refresh`'s exact path data, same as the source icon.\n */\nconst SyncingMotion = ({ fill }: MotionProps) => {\n const progress = useLoopingProgress(1500);\n const transform = progress.interpolate({\n inputRange: [0, 1],\n outputRange: ['rotate(0, 8, 8)', 'rotate(360, 8, 8)'],\n });\n\n return (\n <AnimatedG transform={transform}>\n <Path\n fill={fill}\n fillRule=\"evenodd\"\n d=\"M8 2a6 6 0 0 0-6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1-4 4v-2L5 13l3 3v-2a6 6 0 0 0 6-6 6 6 0 0 0-6-6z\"\n />\n </AnimatedG>\n );\n};\n\n/**\n * `media-record-symbolic` — opacity pulse `1 → 0.35 → 1`, 1.2s ease-in-out,\n * mirroring `Recording.svg`'s `@keyframes gicon-recording-pulse`.\n */\nconst RecordingMotion = ({ fill }: MotionProps) => {\n const opacity = useRef(new Animated.Value(1)).current;\n\n useEffect(() => {\n const easing = Easing.inOut(Easing.ease);\n const animation = Animated.loop(\n Animated.sequence([\n Animated.timing(opacity, { toValue: 0.35, duration: 600, easing, useNativeDriver: false }),\n Animated.timing(opacity, { toValue: 1, duration: 600, easing, useNativeDriver: false }),\n ]),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [opacity]);\n\n return (\n <AnimatedPath\n fill={fill}\n opacity={opacity}\n d=\"m 15 8 c 0 3.867188 -3.132812 7 -7 7 s -7 -3.132812 -7 -7 s 3.132812 -7 7 -7 s 7 3.132812 7 7 z m 0 0\"\n />\n );\n};\n\n/**\n * Animated download indicator — static tray bar, arrow drops into it on a\n * loop (translateY + opacity), 1.4s, mirroring `Downloading.svg`'s\n * `@keyframes gicon-downloading-drop`. The five CSS keyframe stops\n * (`0%, 20%, 50%, 55%, 80%, 100%`) become one `interpolate()`'s\n * `inputRange` off a single linear `0 → 1` driver — good enough fidelity\n * for a decorative micro-interaction without chaining five separately-eased\n * `Animated.timing` segments.\n */\nconst DownloadingMotion = ({ fill }: MotionProps) => {\n const progress = useLoopingProgress(1400);\n const stops = [0, 0.2, 0.5, 0.55, 0.8, 1];\n const transform = progress.interpolate({\n inputRange: stops,\n outputRange: [\n 'translate(0, 0)',\n 'translate(0, 0)',\n 'translate(0, 3)',\n 'translate(0, -3)',\n 'translate(0, 0)',\n 'translate(0, 0)',\n ],\n });\n const opacity = progress.interpolate({ inputRange: stops, outputRange: [1, 1, 0, 0, 1, 1] });\n\n return (\n <>\n <Path fill={fill} d=\"M2 13h12v2H2z\" />\n <AnimatedG transform={transform} opacity={opacity}>\n <Path fill={fill} fillRule=\"evenodd\" d=\"m2.5 5 5.5 6 5.5-6z\" />\n </AnimatedG>\n </>\n );\n};\n\n/** `scale(s)` around an arbitrary `(cx, cy)` pivot, composed as SVG's own translate/scale/translate-back — `react-native-svg`'s dedicated `scale` prop takes a `NumberArray`, not a single animatable number, and its non-deprecated `scaleX`/`scaleY` still can't share one `Animated.Value` with `origin` cleanly, so a plain `transform` string is the most direct fit. */\nfunction scaleAround(cx: number, cy: number, scale: number) {\n return `translate(${cx}, ${cy}) scale(${scale}) translate(${-cx}, ${-cy})`;\n}\n\ninterface ConnectingDotProps {\n cx: number;\n cy: number;\n fill: string;\n delay: number;\n}\n\n/** One of `Connecting`'s three signal dots — opacity + scale pulse, 1.2s ease-in-out, staggered via `delay` so the three read as a left-to-right sweep, mirroring `Connecting.svg`'s `animation-delay: 0/0.15s/0.3s`. */\nconst ConnectingDot = ({ cx, cy, fill, delay }: ConnectingDotProps) => {\n const progress = useDelayedLoopingProgress(1200, delay);\n const stops = [0, 0.2, 0.4, 1];\n const opacity = progress.interpolate({ inputRange: stops, outputRange: [1, 0.3, 1, 1] });\n const transform = progress.interpolate({\n inputRange: stops,\n outputRange: [\n scaleAround(cx, cy, 1),\n scaleAround(cx, cy, 0.7),\n scaleAround(cx, cy, 1),\n scaleAround(cx, cy, 1),\n ],\n });\n\n return (\n <AnimatedCircle cx={cx} cy={cy} r={2} fill={fill} opacity={opacity} transform={transform} />\n );\n};\n\n/**\n * `network-wireless-acquiring-symbolic` — static device/arc path, three\n * signal dots pulsing in a staggered sweep, mirroring `Connecting.svg`.\n */\nconst ConnectingMotion = ({ fill }: MotionProps) => {\n return (\n <>\n <Path\n fill={fill}\n d=\"m 8 1.992188 c -2.617188 0 -5.238281 0.933593 -7.195312 2.808593 l -0.496094 0.480469 c -0.3984378 0.378906 -0.410156 1.011719 -0.03125 1.410156 c 0.003906 0.007813 0.011718 0.011719 0.019531 0.015625 c 0.480469 -1.011719 1.503906 -1.707031 2.703125 -1.707031 h 0.9375 c 2.480469 -1.292969 5.644531 -1.292969 8.125 0 h 0.9375 c 1.199219 0 2.222656 0.695312 2.707031 1.707031 c 0.003907 -0.007812 0.011719 -0.011719 0.015625 -0.015625 c 0.378906 -0.398437 0.367188 -1.03125 -0.03125 -1.410156 l -0.496094 -0.480469 c -1.957031 -1.875 -4.578124 -2.808593 -7.195312 -2.808593 z m -1.730469 9.007812 c -0.441406 0.765625 -0.339843 1.757812 0.316407 2.414062 c 0.78125 0.78125 2.046874 0.78125 2.828124 0 c 0.65625 -0.65625 0.757813 -1.648437 0.316407 -2.414062 z m 0 0\"\n />\n <ConnectingDot cx={3} cy={8} fill={fill} delay={0} />\n <ConnectingDot cx={8} cy={8} fill={fill} delay={150} />\n <ConnectingDot cx={13} cy={8} fill={fill} delay={300} />\n </>\n );\n};\n\n/**\n * Known animated icons, matched by referential identity against\n * `@gnome-ui/icons`' own exports. There is no generic way to interpret an\n * arbitrary icon's `svg`-embedded CSS `@keyframes` in RN (no CSS engine),\n * so each recipe is hand-built — this registry only covers the 4 icons\n * `@gnome-ui/icons` currently ships as `animated: true`. An icon that isn't\n * in it (a future 5th animated icon, or a consumer-authored one) falls back\n * to the static `<Icon>` frame — `playing` silently has no visible effect\n * rather than throwing.\n */\nconst RECIPES = new Map<IconDefinition, ComponentType<MotionProps>>([\n [Syncing, SyncingMotion],\n [Recording, RecordingMotion],\n [Downloading, DownloadingMotion],\n [Connecting, ConnectingMotion],\n]);\n\n/**\n * Plays the motion for a known `animated` icon from `@gnome-ui/icons`\n * (`Syncing`, `Recording`, `Downloading`, `Connecting`) — rendered through\n * plain `<Icon>`, these show a static frame instead.\n *\n * Unlike `@gnome-ui/react`'s `AnimatedIcon` (which plays a CSS animation\n * embedded in the icon's raw `svg` markup via a `--gnome-icon-play-state`\n * custom property), RN has no CSS engine to interpret `@keyframes` at all —\n * `<Icon>` already drops the `<style>` block silently (see its own doc\n * comment), and this component instead hand-builds each of the 4 known\n * icons' exact motion with `Animated`, matched against `RECIPES` by\n * reference. When playing and reduced motion is off, it renders its own\n * `<Svg>` with the matching `*Motion` recipe as children; otherwise (not\n * playing, reduced motion on, or an icon `RECIPES` doesn't recognize) it\n * defers straight to `<Icon>`.\n *\n * Useful for progress, sync, recording, download, and connection states, or\n * cross-fading between icons by swapping `icon` while `playing` stays true.\n *\n * @example\n * import { Syncing } from \"@gnome-ui/icons\";\n * <AnimatedIcon icon={Syncing} playing={isSyncing} label=\"Syncing\" />\n */\nexport const AnimatedIcon = ({\n icon,\n playing = true,\n size = 'md',\n width,\n height,\n label,\n color,\n}: AnimatedIconProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n const isPlaying = playing && !reducedMotion;\n const Motion = isPlaying ? RECIPES.get(icon) : undefined;\n\n if (!Motion) {\n return (\n <Icon icon={icon} size={size} width={width} height={height} label={label} color={color} />\n );\n }\n\n const px = ICON_SIZE_MAP[size];\n const fill = resolveIconColor(theme, color);\n const accessibilityProps = iconAccessibilityProps(label);\n\n return (\n <Svg viewBox={icon.viewBox} width={width ?? px} height={height ?? px} {...accessibilityProps}>\n <Motion fill={fill} />\n </Svg>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type BannerVariant = 'info' | 'warning' | 'error' | 'success';\n\nexport interface BannerProps extends Omit<ViewProps, 'style'> {\n /**\n * Visual emphasis level.\n * - `info` (default) — neutral, accent-colored. Use for tips and notices.\n * - `warning` — yellow. Use for recoverable problems.\n * - `error` — red. Use for failures that need attention.\n * - `success` — green. Use for confirmations.\n */\n variant?: BannerVariant;\n /** The message text. Keep it short — one or two sentences. */\n children: ReactNode;\n /**\n * Label for the optional action button placed at the trailing end.\n * When provided, `onAction` should also be supplied.\n */\n actionLabel?: string;\n /** Called when the user presses the action button. */\n onAction?: () => void;\n /**\n * When true a dismiss (×) button is shown at the trailing edge.\n * Provide `onDismiss` to handle removal from the list.\n */\n dismissible?: boolean;\n /** Called when the user presses the dismiss button. */\n onDismiss?: () => void;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Persistent message strip displayed at the top of a view, following the\n * Adwaita `AdwBanner` pattern. Use for important information that persists\n * until the user acts or explicitly dismisses it — unlike `Toast`, it never\n * auto-dismisses.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"alert\"` is the closest available role, paired with\n * `accessibilityLiveRegion=\"polite\"` (Android's live-region API) as the\n * nearest match to `aria-live=\"polite\"` — the same substitution `Toast`\n * already established for the identical web role pair. Since the banner\n * itself is a plain `View` (not `Pressable` — only its buttons are\n * interactive), `accessible` is set explicitly alongside `accessibilityRole`,\n * per the `BoxedList` lesson that a bare `View` isn't an accessibility\n * element by default.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Banner.html\n * @see https://developer.gnome.org/hig/patterns/feedback/banners.html\n */\nexport const Banner = ({\n variant = 'info',\n children,\n actionLabel,\n onAction,\n dismissible = false,\n onDismiss,\n style,\n ...viewProps\n}: BannerProps) => {\n const theme = useGnomeTheme();\n\n const colors = {\n info: { bg: theme.accentBgColor, fg: theme.accentFgColor },\n warning: { bg: theme.warningBgColor, fg: theme.warningFgColor },\n error: { bg: theme.errorBgColor, fg: theme.errorFgColor },\n success: { bg: theme.successBgColor, fg: theme.successFgColor },\n }[variant];\n\n // Mirrors the source CSS's per-variant :active overlay: a light overlay on\n // the darker info/error/success backgrounds, a dark one on the light\n // warning background.\n const pressedOverlay =\n variant === 'warning' ? 'rgba(0, 0, 0, 0.14)' : 'rgba(255, 255, 255, 0.25)';\n\n return (\n <View\n accessible\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 10,\n paddingHorizontal: theme.space4,\n minHeight: 44,\n width: '100%',\n backgroundColor: colors.bg,\n },\n style,\n ]}\n {...viewProps}\n >\n <Text variant=\"body\" style={{ flex: 1, minWidth: 0, color: colors.fg }}>\n {children}\n </Text>\n\n {(actionLabel || dismissible) && (\n <View\n style={{ flexDirection: 'row', alignItems: 'center', gap: theme.space1, flexShrink: 0 }}\n >\n {actionLabel && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={actionLabel}\n onPress={onAction}\n style={({ pressed }) => ({\n paddingVertical: 4,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusMd,\n backgroundColor: pressed ? pressedOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: colors.fg,\n }}\n >\n {actionLabel}\n </RNText>\n </Pressable>\n )}\n\n {dismissible && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={4}\n onPress={onDismiss}\n style={({ pressed }) => ({\n width: 28,\n height: 28,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusMd,\n opacity: pressed ? 1 : 0.6,\n backgroundColor: pressed ? pressedOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: colors.fg }}>{'×'}</RNText>\n </Pressable>\n )}\n </View>\n )}\n </View>\n );\n};\n","import { forwardRef } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type SeparatorOrientation = 'horizontal' | 'vertical';\n\nexport interface SeparatorProps extends Omit<ViewProps, 'style'> {\n /** Direction of the dividing line. Defaults to `\"horizontal\"`. */\n orientation?: SeparatorOrientation;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Thin dividing line that separates groups of content.\n *\n * Color is driven entirely by `theme.cardShadeColor`, which already\n * resolves correctly per color scheme, so — unlike `Switch`/`Checkbox`/\n * `RadioButton` — there's no `useResolvedColorScheme()` branching needed\n * here.\n *\n * Rebuilt as a plain `View` rather than ported from `@gnome-ui/react`'s\n * `<hr>`/`<div role=\"separator\">`: RN's `AccessibilityRole` union has no\n * `\"separator\"` value, so — since a divider carries no information a\n * screen reader user needs — it's excluded from the accessibility tree\n * entirely with `accessible={false}`, the RN-idiomatic way to mark a\n * purely decorative element, rather than reaching for a role that doesn't\n * exist.\n *\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const Separator = forwardRef<View, SeparatorProps>(function Separator(\n { orientation = 'horizontal', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n ref={ref}\n accessible={false}\n style={[\n { backgroundColor: theme.cardShadeColor, flexShrink: 0 },\n orientation === 'vertical'\n ? { width: 1, height: '100%', alignSelf: 'stretch' }\n : { width: '100%', height: 1 },\n style,\n ]}\n {...viewProps}\n />\n );\n});\n","import { Children, forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { Separator } from '@/components/Separator';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type BoxedListVariant = 'default' | 'separate';\n\nexport interface BoxedListProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /**\n * `\"separate\"` renders each child as its own standalone rounded card\n * instead of a single joined list — mirrors `.boxed-list-separate`.\n * Use when rows are independent items rather than a continuous group.\n */\n variant?: BoxedListVariant;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Rounded bordered list — the most common container pattern in GNOME apps.\n *\n * Mirrors the Adwaita `.boxed-list` style applied to a `GtkListBox`.\n * Separators between rows are inserted automatically. Pair with `ActionRow`\n * or any row-shaped element.\n *\n * Rebuilt with `View` rather than ported from `@gnome-ui/react`'s\n * `<ul>`/`<li>` — RN has no list-semantics elements, so the outer `View`\n * gets `accessibilityRole=\"list\"` (there's no RN equivalent of `listitem`\n * for rows), paired with `accessible` — a plain `View` isn't an\n * accessibility element by default, so without it screen readers (and\n * `@testing-library/react-native`'s `getByRole`) would skip over the role\n * entirely. The web version applies `border-radius` directly to each\n * first/last child via a `:first-child > *` CSS selector, since its `<ul>`\n * has no `overflow: hidden` of its own; RN's `overflow: 'hidden'` on the\n * outer `View` clips every row to the container's rounded corners\n * uniformly, so that per-child trick isn't needed here.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html#boxed-lists-cards\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const BoxedList = forwardRef<View, BoxedListProps>(function BoxedList(\n { children, variant = 'default', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const items = Children.toArray(children).filter(Boolean);\n\n if (variant === 'separate') {\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"list\"\n style={[{ gap: theme.space2 }, style]}\n {...viewProps}\n >\n {items.map((child, i) => (\n <RNView\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n key={i}\n style={{\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.dividerColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n }}\n >\n {child}\n </RNView>\n ))}\n </RNView>\n );\n }\n\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"list\"\n style={[\n {\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.dividerColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n },\n style,\n ]}\n {...viewProps}\n >\n {items.map((child, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n <RNView key={i}>\n {i > 0 && <Separator testID=\"boxed-list-separator\" />}\n {child}\n </RNView>\n ))}\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Pressable, Text } from 'react-native';\n\nimport { useGnomeTheme, useResolvedContrast } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type ButtonVariant = 'default' | 'suggested' | 'destructive' | 'flat' | 'raised';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonShape = 'default' | 'pill' | 'circular';\n\nexport interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {\n /** Visual style of the button. Follows GNOME HIG button types. */\n variant?: ButtonVariant;\n /** Size of the button. */\n size?: ButtonSize;\n /** Shape of the button. \"pill\" for primary actions in open space, \"circular\" for icon-only buttons. */\n shape?: ButtonShape;\n /**\n * Dark semi-transparent overlay style for buttons placed on top of media\n * or images — mirrors `@gnome-ui/react`'s `osd` prop.\n */\n osd?: boolean;\n /**\n * Icon placed before the label. Rendered as-is — RN has no CSS\n * `currentColor` equivalent, so size and color it yourself (`theme.*FgColor`\n * from `useGnomeTheme()` matches the resolved label color for each variant).\n */\n leadingIcon?: ReactNode;\n /** Icon placed after the label. See `leadingIcon` for color/size notes. */\n trailingIcon?: ReactNode;\n /** String children render as a themed `Text` label; other nodes render as-is. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n /** Style applied to the label `Text` when `children` is a string. */\n textStyle?: StyleProp<TextStyle>;\n}\n\ninterface SizeMetrics {\n minHeight: number;\n minWidth: number;\n paddingVertical: number;\n paddingHorizontal: number;\n fontSize: number;\n}\n\nfunction getSizeMetrics(theme: GnomeThemeTokens, size: ButtonSize): SizeMetrics {\n switch (size) {\n case 'sm':\n return {\n minHeight: 28,\n minWidth: 64,\n paddingVertical: 4,\n paddingHorizontal: theme.space1,\n fontSize: theme.fontSizeCaption,\n };\n case 'lg':\n return {\n minHeight: 42,\n minWidth: 88,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space3,\n fontSize: theme.fontSizeTitle4,\n };\n default:\n return {\n minHeight: 34,\n minWidth: 88,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space2,\n fontSize: theme.fontSizeBody,\n };\n }\n}\n\nfunction getCircularSize(size: ButtonSize): number {\n switch (size) {\n case 'sm':\n return 28;\n case 'lg':\n return 42;\n default:\n return 34;\n }\n}\n\ninterface VariantColors {\n backgroundColor: string;\n borderColor: string;\n color: string;\n}\n\nfunction getVariantColors(\n theme: GnomeThemeTokens,\n variant: ButtonVariant,\n pressed: boolean,\n osd: boolean,\n): VariantColors {\n if (osd) {\n return {\n backgroundColor: pressed ? 'rgba(0, 0, 0, 0.85)' : 'rgba(0, 0, 0, 0.65)',\n borderColor: 'rgba(255, 255, 255, 0.12)',\n color: 'rgba(255, 255, 255, 0.95)',\n };\n }\n\n switch (variant) {\n case 'suggested':\n return {\n backgroundColor: theme.accentBgColor,\n borderColor: 'transparent',\n color: theme.accentFgColor,\n };\n case 'destructive':\n return {\n backgroundColor: theme.destructiveBgColor,\n borderColor: 'transparent',\n color: theme.destructiveFgColor,\n };\n case 'flat':\n return {\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n borderColor: 'transparent',\n color: theme.windowFgColor,\n };\n default:\n return {\n backgroundColor: pressed ? theme.light3 : theme.cardBgColor,\n borderColor: theme.light3,\n color: theme.windowFgColor,\n };\n }\n}\n\n/**\n * Button component following GNOME Human Interface Guidelines.\n *\n * Variants:\n * - `default` — Standard action, flat appearance with subtle border.\n * - `suggested` — Affirmative/primary action (accent color). Use at most once per view.\n * - `destructive` — Dangerous or irreversible action (red). Use sparingly.\n * - `flat` — No border or background; ideal for header bars and toolbars.\n * - `raised` — Explicit raised look inside flat/toolbar contexts.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s DOM-based JSX, but mirrors its prop API.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/buttons.html\n */\nexport const Button = forwardRef<View, ButtonProps>(function Button(\n {\n variant = 'default',\n size = 'md',\n shape = 'default',\n osd = false,\n leadingIcon,\n trailingIcon,\n children,\n style,\n textStyle,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const contrast = useResolvedContrast();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={({ pressed }) => {\n const { backgroundColor, borderColor } = getVariantColors(theme, variant, pressed, osd);\n const solidVariant = !osd && (variant === 'suggested' || variant === 'destructive');\n const circularSize = shape === 'circular' ? getCircularSize(size) : undefined;\n const { minHeight, minWidth, paddingVertical, paddingHorizontal } = getSizeMetrics(\n theme,\n size,\n );\n\n return [\n {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.space1,\n minHeight: circularSize ?? minHeight,\n minWidth: circularSize ?? (shape === 'pill' ? undefined : minWidth),\n width: circularSize,\n height: circularSize,\n paddingVertical: circularSize ? theme.space1 : paddingVertical,\n paddingHorizontal: circularSize\n ? theme.space1\n : shape === 'pill'\n ? theme.space3\n : paddingHorizontal,\n borderRadius: shape === 'default' ? theme.radiusMd : theme.radiusPill,\n borderWidth: variant === 'default' && contrast === 'more' ? 2 : 1,\n borderColor,\n backgroundColor,\n opacity: disabled ? theme.opacityDisabled : pressed && solidVariant ? 0.85 : 1,\n } satisfies ViewStyle,\n style,\n ];\n }}\n {...pressableProps}\n >\n {({ pressed }) => {\n const { fontSize } = getSizeMetrics(theme, size);\n const { color } = getVariantColors(theme, variant, pressed, osd);\n\n return (\n <>\n {leadingIcon}\n {typeof children === 'string' ? (\n <Text\n style={[\n {\n fontFamily: theme.fontFamily,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n fontSize,\n color,\n },\n textStyle,\n ]}\n >\n {children}\n </Text>\n ) : (\n children\n )}\n {trailingIcon}\n </>\n );\n }}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView, StyleSheet } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg';\n\nexport interface CardProps extends Omit<PressableProps, 'style' | 'children'> {\n /**\n * When true the card becomes pressable (Adwaita `.activatable`).\n * Renders as `Pressable` with `accessibilityRole=\"button\"`; a plain\n * `View` otherwise. `onPress`/`onLongPress`/etc. only take effect when\n * `interactive` is true — RN's `View` has no touch handling of its own,\n * unlike a DOM `<div>`'s `onClick`.\n */\n interactive?: boolean;\n /** Internal spacing. Defaults to `\"md\"`. */\n padding?: CardPadding;\n style?: StyleProp<ViewStyle>;\n children?: ReactNode;\n}\n\nfunction getPadding(theme: GnomeThemeTokens, padding: CardPadding): number {\n switch (padding) {\n case 'none':\n return 0;\n case 'sm':\n return theme.space2;\n case 'lg':\n return theme.space5;\n default:\n return theme.space4;\n }\n}\n\n/**\n * Card component following the GNOME HIG and Adwaita `.card` style class.\n *\n * Use for grouping related content on an elevated surface. Set\n * `interactive` for clickable cards (e.g. grid item, settings shortcut).\n *\n * Rebuilt with `Pressable`/`View` rather than ported from `@gnome-ui/react`'s\n * DOM-based `<button>`/`<div>` + `as` prop — RN has no polymorphic-element\n * equivalent, so `as` is dropped. The web version's `:hover`/`:active`\n * `color-mix()` darken/lighten is reproduced with an absolutely-positioned\n * overlay `View` tinted by `theme.activeOverlay` while pressed, since RN\n * has no `color-mix()` to blend two flat colors directly.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const Card = forwardRef<View, CardProps>(function Card(\n { interactive = false, padding = 'md', style, children, disabled, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n const baseStyle: ViewStyle = {\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n padding: getPadding(theme, padding),\n };\n\n if (!interactive) {\n return (\n <RNView ref={ref} style={[baseStyle, style]} {...(pressableProps as ViewProps)}>\n {children}\n </RNView>\n );\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={[\n baseStyle,\n { position: 'relative', opacity: disabled ? theme.opacityDisabled : 1 },\n style,\n ]}\n {...pressableProps}\n >\n {({ pressed }) => (\n <>\n {children}\n {pressed && !disabled ? (\n <RNView\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n { backgroundColor: theme.activeOverlay, borderRadius: theme.radiusLg },\n ]}\n />\n ) : null}\n </>\n )}\n </Pressable>\n );\n});\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface CheckboxProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether the checkbox is checked. */\n value: boolean;\n /**\n * Indeterminate state — shown when only some items in a group are\n * checked. Takes visual precedence over `value`.\n */\n indeterminate?: boolean;\n /** Called with the next value when the checkbox is pressed. */\n onValueChange?: (value: boolean) => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst SIZE = 18;\n\n/**\n * Checkbox for multi-selection, following the GNOME HIG and Adwaita style.\n *\n * Supports three states: unchecked, checked, and indeterminate (mixed).\n * Use `indeterminate` for \"select all\" controls when only some items are\n * selected.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"checkbox\">`: RN has no `indeterminate`\n * DOM property to set imperatively (the web version's whole reason for a\n * ref + effect), so it's just a rendering branch here — `indeterminate`\n * draws a short bar, otherwise a checkmark, both fading in via the same\n * `Animated.Value` used for the border/background transition. The\n * checkmark itself is a `✓` glyph in a plain (non-themed) `Text` rather\n * than the web version's `clip-path` polygon — this package has no SVG\n * dependency to draw one exactly, and `Link`'s external-link indicator\n * already established a Unicode glyph as this codebase's fallback for a\n * small decorative mark with no icon library available.\n *\n * `value`/`onValueChange` mirror the same convention as `Switch`, RN's own\n * toggle-control shape, rather than the web version's `checked`/`onChange`.\n * The idle border color is another `Switch`-style case where the source\n * CSS hardcodes a palette swatch per color scheme instead of a token that\n * already resolves per theme, so it branches on `useResolvedColorScheme()`\n * the same way.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/checkboxes.html\n */\nexport const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox(\n { value, indeterminate = false, onValueChange, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const marked = value || indeterminate;\n const progress = useRef(new Animated.Value(marked ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `marked` — skip\n // animating into a state the checkbox is already rendering, so it\n // never plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: marked ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [marked, progress, theme.durationFast, theme.easingDefault]);\n\n const idleBorderColor =\n contrast === 'more' ? theme.windowFgColor : colorScheme === 'dark' ? theme.dark1 : theme.light4;\n\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [idleBorderColor, theme.accentBgColor],\n });\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.cardBgColor, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"checkbox\"\n accessibilityState={{ checked: indeterminate ? 'mixed' : value, disabled: !!disabled }}\n onPress={() => onValueChange?.(!value)}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: SIZE,\n height: SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n borderWidth: contrast === 'more' ? 2 : 1.5,\n borderColor,\n backgroundColor,\n }}\n >\n {indeterminate ? (\n <Animated.View\n style={{\n width: 10,\n height: 2,\n borderRadius: 1,\n backgroundColor: '#fff',\n opacity: progress,\n }}\n />\n ) : (\n <Animated.Text\n style={{\n opacity: progress,\n color: '#fff',\n fontSize: 13,\n fontWeight: 'bold',\n lineHeight: 13,\n }}\n >\n {'✓'}\n </Animated.Text>\n )}\n </Animated.View>\n </Pressable>\n );\n});\n","import { type ReactNode, useEffect, useRef } from 'react';\nimport type { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Animated, BackHandler, Easing, Modal, Pressable, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\n/**\n * `Animated`'s style interpolation only takes effect on `Animated.*` host\n * components — a plain `Pressable` would silently ignore the animated\n * `opacity` in its style, the same gotcha already documented on `Toast`.\n * Hoisted to module scope so it isn't recreated on every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nexport type DialogButtonVariant = 'default' | 'suggested' | 'destructive';\n\nexport interface DialogButton {\n /** Button label. */\n label: string;\n /** Visual variant. Defaults to `\"default\"`. */\n variant?: DialogButtonVariant;\n /** Called when the button is pressed. */\n onPress: () => void;\n /** Whether the button is disabled. */\n disabled?: boolean;\n}\n\nexport type AlertDialogResponseVariant = DialogButtonVariant;\n\nexport interface AlertDialogResponse {\n /**\n * Unique identifier returned via `onResponse`.\n * Use `\"cancel\"` by convention for the dismissive action.\n */\n id: string;\n /** Button label. */\n label: string;\n /** Visual emphasis. Defaults to `\"default\"`. */\n variant?: AlertDialogResponseVariant;\n /** Disables the button. */\n disabled?: boolean;\n}\n\nexport interface DialogProps {\n /** Whether the dialog is visible. */\n open: boolean;\n\n // ── Standard dialog ────────────────────────────────────────────────────\n\n /** Dialog heading. */\n title?: ReactNode;\n /** Body content. */\n children?: ReactNode;\n /** Action buttons (standard dialog API). */\n buttons?: DialogButton[];\n /** Called on Android back button / backdrop press. */\n onClose?: () => void;\n /** Whether pressing the backdrop closes the dialog. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n\n // ── AlertDialog extension ───────────────────────────────────────────────\n\n /**\n * Use `\"alertdialog\"` for confirmations and destructive warnings — screen\n * readers announce it immediately. Defaults to `\"dialog\"`.\n *\n * When using `role=\"alertdialog\"`, prefer the `responses`/`onResponse` API\n * over `buttons`/`onPress` for semantic clarity.\n */\n role?: 'dialog' | 'alertdialog';\n\n /**\n * Response buttons (AlertDialog API). Alternative to `buttons` — each\n * response has a semantic `id` returned via `onResponse`. The Android back\n * button and backdrop press fire the first non-destructive response.\n */\n responses?: AlertDialogResponse[];\n\n /**\n * Called with the `id` of the response button pressed.\n * Required when `responses` is provided.\n */\n onResponse?: (id: string) => void;\n\n style?: StyleProp<ViewStyle>;\n /** Forwarded to the backdrop — useful for testing. */\n testID?: string;\n}\n\n/**\n * Blocking modal dialog following the Adwaita pattern.\n *\n * **Standard** — `title` + `children` + `buttons[]`.\n *\n * **Alert** — add `role=\"alertdialog\"` + `responses[]` + `onResponse`.\n * Uses a semantic response id instead of per-button `onPress`. The Android\n * back button / backdrop press fire the first non-destructive response.\n * Mirrors `AdwAlertDialog`.\n *\n * Built on RN's own `Modal` rather than `@gnome-ui/react`'s DOM `Portal` +\n * manual focus trap: `Modal` already floats above everything with no portal\n * target needed, already blocks interaction with the screen behind it (no\n * `useBodyScrollLock` equivalent needed), and its `onRequestClose` fires on\n * the Android hardware back button — the direct analog of the web version's\n * document-level Escape listener. Focus-trapping (`Tab`/`Shift+Tab` cycling)\n * has no port: there is no keyboard `Tab` concept in RN's touch-first model,\n * the same reasoning that already dropped `TabBar`'s roving-tabindex arrow\n * keys.\n *\n * `role` is passed straight through as RN's own `role` prop (not\n * `accessibilityRole`) — RN's newer, web-aligned `Role` union has real\n * `\"dialog\"`/`\"alertdialog\"` values, unlike the older `AccessibilityRole`\n * enum `Toast`/`Banner` had to substitute `\"alert\"` into for the web's\n * `role=\"status\"`. `accessibilityViewIsModal` (iOS) is the closest match to\n * `aria-modal=\"true\"`, restricting VoiceOver to the dialog's subtree.\n *\n * There is no exit animation on either platform — the source CSS only\n * defines entrance keyframes, and `Modal`'s `visible={false}` unmounts\n * immediately, matching the web version returning `null` outright when\n * `!open`. Entrance is an `Animated.timing` fading + scaling + sliding the\n * card in (mirrors `@keyframes dialog-in`) alongside a plain backdrop fade\n * (`@keyframes backdrop-in`), replayed via a `useEffect` keyed on `open`\n * since — unlike `Toast`, which mounts once per instance — the same\n * `Dialog` element toggles `open` repeatedly while `Modal` itself\n * mounts/unmounts internally. `useReducedMotion()` skips straight to the\n * settled state.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Dialog.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.AlertDialog.html\n */\nexport const Dialog = ({\n open,\n title,\n children,\n buttons = [],\n onClose,\n closeOnBackdrop = true,\n role = 'dialog',\n responses,\n onResponse,\n style,\n testID,\n}: DialogProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n const progress = useRef(new Animated.Value(reducedMotion ? 1 : 0)).current;\n\n const isAlert = !!responses;\n\n const dismissAlert = () => {\n const cancel = responses?.find((r) => r.variant !== 'destructive' && !r.disabled);\n\n if (cancel) {\n onResponse?.(cancel.id);\n }\n };\n\n const handleEscape = () => {\n if (isAlert) {\n dismissAlert();\n } else {\n onClose?.();\n }\n };\n\n const handleBackdropPress = isAlert ? dismissAlert : closeOnBackdrop ? onClose : undefined;\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [open, reducedMotion, progress, theme.durationNormal, theme.easingDefault]);\n\n // Only the topmost dialog reacts to the Android back button, mirroring\n // the web version's \"topmost modal only\" Escape behavior for stacked\n // dialogs.\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n handleEscape();\n\n return true;\n });\n\n return () => subscription.remove();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, isAlert, responses, onResponse, onClose]);\n\n const renderButtons = () => {\n const rows = isAlert && responses ? responses : buttons;\n\n if (rows.length === 0) {\n return null;\n }\n\n return (\n <View style={{ borderTopWidth: 1, borderTopColor: theme.cardShadeColor }}>\n {rows.map((row, index) => {\n const variant = row.variant ?? 'default';\n const color = variant === 'destructive' ? theme.destructiveColor : theme.accentColor;\n const onPress = isAlert\n ? () => onResponse?.((row as AlertDialogResponse).id)\n : (row as DialogButton).onPress;\n\n return (\n <Pressable\n key={isAlert ? (row as AlertDialogResponse).id : row.label}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: row.disabled }}\n disabled={row.disabled}\n onPress={onPress}\n style={({ pressed }) => ({\n paddingVertical: 14,\n paddingHorizontal: theme.space4,\n borderBottomWidth: index < rows.length - 1 ? 1 : 0,\n borderBottomColor: theme.cardShadeColor,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n opacity: row.disabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text\n variant=\"body\"\n style={{\n textAlign: 'center',\n color,\n fontWeight:\n variant === 'suggested'\n ? (String(theme.fontWeightSemibold) as TextStyle['fontWeight'])\n : undefined,\n }}\n >\n {row.label}\n </Text>\n </Pressable>\n );\n })}\n </View>\n );\n };\n\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.5, shadowRadius: 32, elevation: 12 }\n : { shadowOpacity: 0.25, shadowRadius: 32, elevation: 8 };\n\n return (\n <Modal\n visible={open}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={handleEscape}\n >\n <AnimatedPressable\n testID={testID}\n onPress={handleBackdropPress}\n style={{\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 24,\n backgroundColor: theme.dialogBackdropColor,\n opacity: progress,\n }}\n >\n <Pressable onPress={() => {}} accessible={false} style={{ width: '100%', maxWidth: 480 }}>\n <Animated.View\n accessible\n role={role}\n accessibilityViewIsModal\n style={[\n {\n backgroundColor: theme.dialogBgColor,\n borderRadius: theme.radiusXl,\n overflow: 'hidden',\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 8 },\n ...shadow,\n opacity: progress,\n transform: [\n {\n translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }),\n },\n { scale: progress.interpolate({ inputRange: [0, 1], outputRange: [0.92, 1] }) },\n ],\n },\n style,\n ]}\n >\n {title && (\n <Text\n variant=\"title-4\"\n style={{\n padding: theme.space4,\n paddingBottom: children ? 0 : theme.space4,\n textAlign: 'center',\n fontWeight: String(theme.fontWeightBold) as TextStyle['fontWeight'],\n }}\n >\n {title}\n </Text>\n )}\n\n {children && (\n <View style={{ paddingVertical: theme.space2, paddingHorizontal: theme.space4 }}>\n {typeof children === 'string' ? (\n <Text variant=\"body\" style={{ textAlign: 'center', opacity: theme.opacityDim }}>\n {children}\n </Text>\n ) : (\n children\n )}\n </View>\n )}\n\n {renderButtons()}\n </Animated.View>\n </Pressable>\n </AnimatedPressable>\n </Modal>\n );\n};\n","import { Check, PanDown } from '@gnome-ui/icons';\nimport { useEffect, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Animated, Dimensions, Modal, Pressable, ScrollView, View } from 'react-native';\n\nimport { Icon } from '@/components/Icon';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport interface DropdownOption<V extends string = string> {\n /** The value submitted / returned on selection. */\n value: V;\n /** Display label shown in the list and trigger. */\n label: string;\n /** Optional descriptive text shown below the label. */\n description?: string;\n /** Whether the option is selectable. */\n disabled?: boolean;\n}\n\nexport interface DropdownProps<V extends string = string> {\n /** The list of selectable options. */\n options: DropdownOption<V>[];\n /** The currently selected value. */\n value?: V;\n /** Called when the user selects an option. */\n onChange?: (value: V) => void;\n /** Placeholder shown when no option is selected. */\n placeholder?: string;\n /** Accessible label for the control. */\n accessibilityLabel?: string;\n /** Disables the entire control. */\n disabled?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n width: number;\n flipUp: boolean;\n}\n\nconst GAP = 4;\nconst MARGIN = 8;\nconst MAX_LIST_HEIGHT = 280;\n\nfunction computePosition(trigger: Rect, panelHeight: number): Position {\n const { height: vh } = Dimensions.get('window');\n const spaceBelow = vh - (trigger.y + trigger.height);\n const flipUp = spaceBelow < panelHeight && trigger.y > panelHeight;\n const top = flipUp ? trigger.y - panelHeight - GAP : trigger.y + trigger.height + GAP;\n\n return {\n top: Math.max(MARGIN, Math.min(top, vh - panelHeight - MARGIN)),\n left: trigger.x,\n width: trigger.width,\n flipUp,\n };\n}\n\n/**\n * Expandable option list following the Adwaita combo-row / drop-down\n * pattern, mirroring `@gnome-ui/react`'s `Dropdown`.\n *\n * Built on RN's own `Modal` (transparent) — the same portal-substitute\n * `Dialog`/`Tooltip` already use — with a full-screen backdrop `Pressable`\n * (not `pointerEvents=\"box-none\"` like `Tooltip`'s: unlike a tooltip, this\n * panel is meant to catch and close on an outside tap, the RN analog of the\n * web version's document-level \"click outside\" listener). `open` flips\n * synchronously on trigger press; the trigger's on-screen rect\n * (`measureInWindow`) and the panel's own rendered height (`onLayout`) each\n * resolve independently into state, combined by a separate effect into the\n * final `top`/`left`/`width`/`flipUp` — the same two-independent-\n * async-measurements pattern `Tooltip` established (and for the same\n * reason: gating `open` itself on the native measurement callback would\n * make the component untestable in this package's Jest environment, where\n * `measureInWindow` never calls back).\n *\n * Keyboard navigation (↑/↓ roving highlight, Home/End, type-ahead) has no\n * port — RN's touch-first model has no keyboard focus to drive it, the\n * same reasoning that already dropped `TabBar`'s roving-tabindex arrow\n * keys. Selection is by direct tap only.\n *\n * `role=\"combobox\"` on the trigger ports 1:1. RN's `Role` union has no\n * `\"listbox\"` value (unlike `\"option\"`, which does exist) — the panel uses\n * `role=\"list\"` instead, the same closest-available substitution `BoxedList`\n * already established for a plain list container.\n */\nexport const Dropdown = <V extends string = string>({\n options,\n value,\n onChange,\n placeholder = 'Select an option',\n accessibilityLabel,\n disabled,\n style,\n testID,\n}: DropdownProps<V>) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const [open, setOpen] = useState(false);\n const [triggerRect, setTriggerRect] = useState<Rect | null>(null);\n const [panelHeight, setPanelHeight] = useState<number | null>(null);\n const [pos, setPos] = useState<Position | null>(null);\n\n const triggerRef = useRef<View>(null);\n const progress = useRef(new Animated.Value(0)).current;\n\n const selected = options.find((o) => o.value === value);\n\n const openList = () => {\n if (disabled) {\n return;\n }\n\n setOpen(true);\n };\n\n const closeList = () => setOpen(false);\n\n const selectOption = (opt: DropdownOption<V>) => {\n if (opt.disabled) {\n return;\n }\n\n onChange?.(opt.value);\n closeList();\n };\n\n useEffect(() => {\n if (!open) {\n setTriggerRect(null);\n setPanelHeight(null);\n setPos(null);\n\n return;\n }\n\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerRect({ x, y, width, height });\n });\n }, [open]);\n\n useEffect(() => {\n if (triggerRect === null || panelHeight === null) {\n return;\n }\n\n setPos(computePosition(triggerRect, panelHeight));\n }, [triggerRect, panelHeight]);\n\n useEffect(() => {\n if (!pos) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationFast,\n useNativeDriver: true,\n }).start();\n }, [pos, reducedMotion, progress, theme.durationFast]);\n\n const handlePanelLayout = (e: LayoutChangeEvent) => {\n setPanelHeight(Math.min(e.nativeEvent.layout.height, MAX_LIST_HEIGHT));\n };\n\n return (\n <View style={style}>\n <Pressable\n ref={triggerRef}\n testID={testID}\n role=\"combobox\"\n accessibilityLabel={accessibilityLabel}\n accessibilityState={{ expanded: open, disabled: !!disabled }}\n disabled={disabled}\n onPress={() => (open ? closeList() : openList())}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: theme.space1,\n minHeight: 36,\n minWidth: 160,\n paddingVertical: 7,\n paddingHorizontal: theme.space2,\n backgroundColor: pressed ? theme.activeOverlay : theme.cardBgColor,\n borderWidth: 1,\n borderColor: open ? theme.accentColor : theme.cardShadeColor,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text\n numberOfLines={1}\n style={{\n flex: 1,\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n opacity: selected ? 1 : theme.opacityDim,\n }}\n >\n {selected?.label ?? placeholder}\n </Text>\n <Icon\n icon={PanDown}\n size=\"md\"\n color=\"default\"\n style={{ transform: [{ rotate: open ? '180deg' : '0deg' }] }}\n />\n </Pressable>\n\n <Modal visible={open} transparent animationType=\"none\" statusBarTranslucent>\n <Pressable\n onPress={closeList}\n accessible={false}\n style={{ flex: 1 }}\n testID={testID ? `${testID}-backdrop` : undefined}\n >\n <Animated.View\n onLayout={handlePanelLayout}\n role=\"list\"\n accessible\n style={[\n {\n position: 'absolute',\n maxHeight: MAX_LIST_HEIGHT,\n backgroundColor: theme.popoverBgColor,\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusMd,\n paddingVertical: 4,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.15,\n shadowRadius: 12,\n elevation: 6,\n },\n pos\n ? { top: pos.top, left: pos.left, width: pos.width, opacity: progress }\n : { top: -9999, left: -9999, width: 200, opacity: 0 },\n ]}\n >\n <ScrollView bounces={false}>\n {options.map((opt) => {\n const isSelected = opt.value === value;\n\n return (\n <Pressable\n key={opt.value}\n role=\"option\"\n accessibilityState={{ selected: isSelected, disabled: !!opt.disabled }}\n disabled={opt.disabled}\n onPress={() => selectOption(opt)}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n minHeight: 40,\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n opacity: opt.disabled ? theme.opacityDisabled : 1,\n })}\n >\n <View style={{ flex: 1, gap: 1 }}>\n <Text\n numberOfLines={1}\n style={{\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n fontWeight: isSelected\n ? (String(theme.fontWeightSemibold) as TextStyle['fontWeight'])\n : undefined,\n }}\n >\n {opt.label}\n </Text>\n {opt.description && (\n <Text\n numberOfLines={1}\n style={{\n fontSize: theme.fontSizeCaption,\n color: theme.windowFgColor,\n opacity: theme.opacityDim,\n }}\n >\n {opt.description}\n </Text>\n )}\n </View>\n {isSelected && <Icon icon={Check} size=\"md\" color=\"blue\" />}\n </Pressable>\n );\n })}\n </ScrollView>\n </Animated.View>\n </Pressable>\n </Modal>\n </View>\n );\n};\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, TextStyle, View, ViewProps, ViewStyle } from 'react-native';\nimport { Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface HeaderBarProps extends Omit<ViewProps, 'style'> {\n /** Centered title. Pass a string or a custom element. */\n title?: ReactNode;\n /** Controls placed at the leading (left) edge — back button, menu, etc. */\n start?: ReactNode;\n /** Controls placed at the trailing (right) edge — actions, overflow menu, etc. */\n end?: ReactNode;\n /**\n * When true the header bar blends into the window chrome (no bottom\n * border). Use for the topmost bar of a full-window layout.\n */\n flat?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Title bar with centered title and leading/trailing action slots.\n *\n * Mirrors the Adwaita `AdwHeaderBar` pattern. Use `flat` buttons\n * (`<Button variant=\"flat\">`) inside the header bar per GNOME HIG.\n *\n * Rebuilt with flexbox rather than ported from `@gnome-ui/react`'s CSS\n * Grid (`1fr auto 1fr`) — RN has no grid layout, but the same true-centering\n * effect (the title stays centered in the full width regardless of how\n * wide `start`/`end` are, rather than centering only in the leftover gap\n * between them) comes from giving both side slots `flex: 1` with the title\n * left unflexed in between, since both sides then always claim equal\n * leftover space. The web version's `<header>` element has no RN\n * equivalent; `accessibilityRole=\"header\"` is deliberately *not* applied to\n * the outer `View` since that role means \"text heading\" in RN's\n * accessibility tree (see `Text`'s heading variants), not \"landmark\n * container\" the way HTML's `<header>` does.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.HeaderBar.html\n * @see https://developer.gnome.org/hig/patterns/containers/header-bars.html\n */\nexport const HeaderBar = forwardRef<View, HeaderBarProps>(function HeaderBar(\n { title, start, end, flat = false, style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n ref={ref}\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space2,\n minHeight: 47,\n backgroundColor: theme.headerbarBgColor,\n borderBottomWidth: flat ? 0 : 1,\n borderBottomColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <RNView style={{ flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}>\n {start}\n </RNView>\n\n <RNView\n accessibilityLiveRegion=\"polite\"\n style={{ alignItems: 'center', justifyContent: 'center', paddingHorizontal: theme.space1 }}\n >\n {typeof title === 'string' ? (\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightHeading),\n color: theme.headerbarFgColor,\n }}\n >\n {title}\n </RNText>\n ) : (\n title\n )}\n </RNView>\n\n <RNView\n style={{\n flex: 1,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: theme.space1,\n }}\n >\n {end}\n </RNView>\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Linking, Pressable, Text as RNText } from 'react-native';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface LinkProps extends Omit<PressableProps, 'children' | 'style'> {\n /**\n * Target URL. Passed to `Linking.openURL` when pressed, unless a custom\n * `onPress` is supplied (e.g. to hand internal links to a router like\n * React Navigation instead of the device browser).\n */\n href: string;\n /**\n * When true the link is treated as external: appends a trailing ↗\n * indicator and an \"Opens in browser\" accessibility hint. RN has no tab\n * concept, so unlike the web `Link` this doesn't change navigation\n * behaviour — `href` always opens via `Linking.openURL` regardless.\n */\n external?: boolean;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n /** Style applied to the label `Text`. */\n textStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Inline hyperlink following GNOME HIG.\n *\n * Rebuilt on `Pressable`/themed `Text` rather than ported from\n * `@gnome-ui/react`'s `<a>`: touch devices have no `:hover`, so the\n * underline that the web version reveals on hover instead reveals on\n * press — the closest native equivalent — alongside the same `0.7`\n * press-opacity dip as `@gnome-ui/react`'s `:active` state.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/links.html\n */\nexport const Link = forwardRef<View, LinkProps>(function Link(\n { href, external = false, children, style, textStyle, onPress, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n accessibilityRole=\"link\"\n accessibilityHint={external ? 'Opens in browser' : undefined}\n onPress={onPress ?? (() => Linking.openURL(href))}\n style={style}\n {...pressableProps}\n >\n {({ pressed }) => (\n <Text\n style={[\n {\n color: theme.accentColor,\n textDecorationLine: pressed ? 'underline' : 'none',\n opacity: pressed ? 0.7 : 1,\n },\n textStyle,\n ]}\n >\n {children}\n {external && (\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{ fontSize: 12 }}\n >\n {' ↗'}\n </RNText>\n )}\n </Text>\n )}\n </Pressable>\n );\n});\n","import type { ReactNode } from 'react';\nimport { Fragment } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface PathBarSegment {\n /** Display label for this path segment. */\n label: string;\n /** Opaque path value passed to `onNavigate` when the segment is pressed. */\n path: string;\n /** Optional icon placed before the label (e.g. a folder icon). Rendered as-is. */\n icon?: ReactNode;\n}\n\nexport interface PathBarProps extends Omit<ViewProps, 'style'> {\n /**\n * Ordered path segments from root to current location. The last segment\n * is the current folder and is rendered non-interactive.\n */\n segments: PathBarSegment[];\n /**\n * Called when the user presses a non-current segment. Receives the\n * `path` and zero-based `index` of the pressed segment.\n */\n onNavigate?: (path: string, index: number) => void;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Breadcrumb path bar for navigating a hierarchical location.\n *\n * Mirrors the location bar in GNOME Files (Nautilus). Segments are\n * separated by chevron dividers. All segments except the last are\n * interactive — pressing them calls `onNavigate`. The last segment\n * represents the current location and renders as a static, bold label.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s `<nav><ol><li>`: RN's `AccessibilityRole` union has\n * neither a \"navigation\" landmark nor a breadcrumb-list role (the same gap\n * that dropped `Sidebar`'s `<nav>` role), so those are dropped rather than\n * faked — each interactive segment still gets its own\n * `accessibilityRole=\"button\"` and `accessibilityLabel`. The separator\n * chevron is a Unicode `›` glyph instead of the web version's inline SVG\n * path, matching this package's established no-SVG-dependency convention.\n *\n * @see https://developer.gnome.org/hig/patterns/nav/search.html\n */\nexport const PathBar = ({ segments, onNavigate, style, ...viewProps }: PathBarProps) => {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n style={[{ flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center' }, style]}\n {...viewProps}\n >\n {segments.map((segment, index) => {\n const isCurrent = index === segments.length - 1;\n\n return (\n <Fragment key={segment.path}>\n {index > 0 && (\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n color: theme.windowFgColor,\n opacity: 0.5,\n marginHorizontal: 1,\n fontSize: theme.fontSizeBody,\n }}\n >\n {'›'}\n </RNText>\n )}\n\n {isCurrent ? (\n <RNView\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n paddingVertical: 2,\n paddingHorizontal: theme.space1,\n maxWidth: 200,\n }}\n >\n {segment.icon && <RNView style={{ flexShrink: 0 }}>{segment.icon}</RNView>}\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: theme.windowFgColor,\n }}\n >\n {segment.label}\n </RNText>\n </RNView>\n ) : (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={segment.label}\n onPress={() => onNavigate?.(segment.path, index)}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n paddingVertical: 2,\n paddingHorizontal: theme.space1,\n maxWidth: 160,\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n {segment.icon && <RNView style={{ flexShrink: 0 }}>{segment.icon}</RNView>}\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n }}\n >\n {segment.label}\n </RNText>\n </Pressable>\n )}\n </Fragment>\n );\n })}\n </RNView>\n );\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type ProgressBarVariant = 'accent' | 'success' | 'warning' | 'error';\n\nexport interface ProgressBarProps extends Omit<ViewProps, 'style'> {\n /**\n * Current progress value between `0` and `1` (e.g. `0.6` = 60%). Omit\n * or set to `undefined` for the indeterminate (pulsing) state.\n */\n value?: number;\n /**\n * Fill color of the progress indicator.\n * - `\"accent\"` (default) — blue, general-purpose progress.\n * - `\"success\"` — green, completed or healthy state.\n * - `\"warning\"` — yellow, approaching a limit.\n * - `\"error\"` — red, failed or critical state.\n */\n variant?: ProgressBarVariant;\n /** Accessible label describing what is loading. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Determinate and indeterminate progress bar following the Adwaita style.\n *\n * - **Determinate** — pass `value` (0–1) to show exact progress; the fill\n * width animates on every change, matching the web version's\n * `transition: width`.\n * - **Indeterminate** — omit `value` for a 40%-wide bar that slides left\n * to right on an `Animated.loop`, matching the web version's CSS\n * `@keyframes pulse`.\n *\n * `useReducedMotion()` is honored per the *source CSS's own* per-state\n * behavior rather than one uniform rule: determinate width changes simply\n * skip the transition (duration `0`, still an immediate jump like the CSS\n * `transition: none`), while the indeterminate pulse stops entirely and\n * freezes as a static, full-width, 50%-opacity bar — exactly what\n * `@media (prefers-reduced-motion: reduce) { .indeterminate { animation:\n * none; left: 0; width: 100%; opacity: 0.5 } }` does. This differs from\n * `Spinner`, whose reduced-motion behavior *slows* its animation instead\n * of stopping it — each component mirrors its own source CSS rather than\n * applying a single reduced-motion policy across the package.\n *\n * Both animated states are driven entirely by `transform` rather than by\n * layout properties (`width`/`left`), so both can run\n * `useNativeDriver: true`: RN's native animation driver can only animate\n * transforms, and a JS-driven (`useNativeDriver: false`) `Animated.timing`\n * or `Animated.loop` schedules its next frame via a plain `setTimeout` —\n * one that routinely fires a tick after a test's `render()` returns but\n * before unmount, outside any `act()` boundary, producing a real (if\n * harmless) \"update not wrapped in act()\" warning under\n * `@testing-library/react-native` on every render of this component. The\n * determinate fill stays a constant `width: '100%'` and instead animates\n * `transform: [{ scaleX }]` with `transformOrigin: 'left'` (so it grows\n * from the left edge, not from center); the indeterminate pulse similarly\n * animates `transform: [{ translateX }]` from `-0.4 * trackWidth` to\n * `trackWidth` (measured via `onLayout`, since a transform's `translateX`\n * needs a pixel offset, not a percentage) rather than animating `left`.\n * Both reproduce the exact same visual motion as the source CSS's\n * `width`/`left` transitions while running fully off the JS thread, which\n * eliminates the warning at its root rather than suppressing it.\n *\n * `role=\"progressbar\"` maps directly to RN's own `accessibilityRole`\n * (unlike `Spinner`, which had to substitute for the web's `role=\"status\"`\n * — `ProgressBar`'s web role already has a 1:1 RN equivalent).\n * `accessibilityValue` carries `now`/`min`/`max` for the determinate case;\n * the indeterminate case omits all three, RN's equivalent of the web\n * version omitting `aria-valuenow`/`aria-valuemin`/`aria-valuemax`. Web's\n * `aria-labelledby` (an id-relationship prop) has no RN equivalent — RN\n * has no DOM ids — so only `aria-label` (`accessibilityLabel`) is ported.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/progress.html\n */\nexport const ProgressBar = ({\n value,\n variant = 'accent',\n accessibilityLabel,\n style,\n onLayout,\n ...viewProps\n}: ProgressBarProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const isIndeterminate = value === undefined || value === null;\n const clamped = isIndeterminate ? undefined : Math.min(1, Math.max(0, value));\n const percent = clamped !== undefined ? clamped * 100 : undefined;\n\n const width = useRef(new Animated.Value(clamped ?? 0)).current;\n const pulse = useRef(new Animated.Value(0)).current;\n const [trackWidth, setTrackWidth] = useState(0);\n\n const handleTrackLayout = (event: LayoutChangeEvent) => {\n setTrackWidth(event.nativeEvent.layout.width);\n onLayout?.(event);\n };\n\n useEffect(() => {\n if (isIndeterminate) {\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(width, {\n toValue: clamped ?? 0,\n duration: reducedMotion ? 0 : theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [clamped, isIndeterminate, reducedMotion, width, theme.durationNormal, theme.easingDefault]);\n\n useEffect(() => {\n if (!isIndeterminate || reducedMotion) {\n return;\n }\n\n pulse.setValue(0);\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n const animation = Animated.loop(\n Animated.timing(pulse, {\n toValue: 1,\n duration: 1400,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [isIndeterminate, reducedMotion, pulse, theme.easingDefault]);\n\n const trackColor = scheme === 'dark' ? theme.dark2 : theme.light3;\n const variantColor: Record<ProgressBarVariant, string> = {\n accent: theme.accentBgColor,\n success: theme.successBgColor,\n warning: theme.warningBgColor,\n error: theme.errorBgColor,\n };\n\n const fillStyle = isIndeterminate\n ? reducedMotion\n ? { left: 0, width: '100%', opacity: 0.5 }\n : {\n left: 0,\n width: '40%',\n transform: [\n {\n translateX: pulse.interpolate({\n inputRange: [0, 1],\n outputRange: [-0.4 * trackWidth, trackWidth],\n }),\n },\n ],\n }\n : {\n width: '100%',\n transformOrigin: 'left',\n transform: [{ scaleX: width }],\n };\n\n return (\n <Animated.View\n accessible\n accessibilityRole=\"progressbar\"\n accessibilityLabel={accessibilityLabel}\n accessibilityValue={\n clamped !== undefined ? { min: 0, max: 100, now: Math.round(percent as number) } : undefined\n }\n onLayout={handleTrackLayout}\n style={[\n {\n width: '100%',\n height: 6,\n borderRadius: theme.radiusPill,\n backgroundColor: trackColor,\n overflow: 'hidden',\n },\n style,\n ]}\n {...viewProps}\n >\n <Animated.View\n style={[\n {\n position: isIndeterminate ? 'absolute' : 'relative',\n top: 0,\n height: '100%',\n borderRadius: theme.radiusPill,\n backgroundColor: variantColor[variant],\n },\n fillStyle as ViewStyle,\n ]}\n />\n </Animated.View>\n );\n};\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface RadioButtonProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether this radio button is the selected one in its group. */\n value: boolean;\n /**\n * Called when pressed while unselected. RN has no `name`-attribute\n * grouping like the web `<input type=\"radio\">`, so mutual exclusivity\n * within a group is the consumer's responsibility — render one\n * `RadioButton` per option and drive `value` from shared selection\n * state, flipping it in `onSelect`.\n */\n onSelect?: () => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst SIZE = 18;\nconst DOT_SIZE = 6;\n\n/**\n * Single-selection radio button following the GNOME HIG and Adwaita style.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"radio\">`: reuses `Checkbox`'s exact\n * border/background transition technique (same `Animated.Value`, same\n * mount-skip guard so it never animates before the user touches it, same\n * `useResolvedColorScheme()`/`useResolvedContrast()` branching for the\n * idle border color, since the source CSS hardcodes those the same way\n * `Checkbox.module.css` does) — just circular, with a filled dot instead\n * of a checkmark, and no indeterminate state.\n *\n * The web version's `name`-attribute grouping has no RN equivalent, so\n * grouping is fully manual here: render one `RadioButton` per option and\n * manage the selected option in the parent, same as any other controlled\n * list of options.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/radio-buttons.html\n */\nexport const RadioButton = forwardRef<View, RadioButtonProps>(function RadioButton(\n { value, onSelect, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const progress = useRef(new Animated.Value(value ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `value` — skip\n // animating into a state the radio button is already rendering, so it\n // never plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: value ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [value, progress, theme.durationFast, theme.easingDefault]);\n\n const idleBorderColor =\n contrast === 'more' ? theme.windowFgColor : colorScheme === 'dark' ? theme.dark1 : theme.light4;\n\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [idleBorderColor, theme.accentBgColor],\n });\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.cardBgColor, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"radio\"\n accessibilityState={{ checked: value, disabled: !!disabled }}\n onPress={() => {\n if (!value) {\n onSelect?.();\n }\n }}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: SIZE,\n height: SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusPill,\n borderWidth: contrast === 'more' ? 2 : 1.5,\n borderColor,\n backgroundColor,\n }}\n >\n <Animated.View\n style={{\n width: DOT_SIZE,\n height: DOT_SIZE,\n borderRadius: theme.radiusPill,\n backgroundColor: '#fff',\n opacity: progress,\n }}\n />\n </Animated.View>\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode, useEffect, useImperativeHandle, useRef } from 'react';\nimport type { StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, TextInput as RNTextInput, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface SearchBarProps extends Omit<TextInputProps, 'style'> {\n /** Whether the search bar is rendered. `false` renders nothing. */\n open: boolean;\n /**\n * Renders a trailing \"Cancel\" button (the RN-idiomatic stand-in for the\n * web version's Escape-to-close — touch keyboards have no reliable\n * Escape key) and calls this when it's pressed.\n */\n onClose?: () => void;\n /** Called when the clear (×) button is pressed. Also clears the input value. */\n onClear?: () => void;\n /**\n * Content rendered below the bar (e.g. filter chips). Only rendered\n * while `open` is true.\n */\n children?: ReactNode;\n /** Removes the header-bar background so the bar blends into any surface. */\n inline?: boolean;\n /** Accessible label for the close button. Defaults to `\"Cancel\"`. */\n closeLabel?: string;\n /** Style applied to the wrapping `View`. */\n style?: StyleProp<ViewStyle>;\n /** Style applied to the `TextInput` itself. */\n inputStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Multiplies an `rgba(r, g, b, a)` token's alpha channel. Duplicated from\n * `TextField` rather than shared — see that component for the full\n * rationale; it's small and self-contained enough that a shared module\n * isn't worth it for two call sites.\n */\nfunction dimColor(color: string, factor: number): string {\n const match = color.match(/^rgba?\\(([^,]+),([^,]+),([^,]+),?([^)]+)?\\)$/);\n\n if (!match) {\n return color;\n }\n\n const [, r, g, b, a] = match;\n const alpha = (a ? Number.parseFloat(a) : 1) * factor;\n\n return `rgba(${r.trim()}, ${g.trim()}, ${b.trim()}, ${alpha})`;\n}\n\n/**\n * Collapsible search input following the Adwaita `AdwSearchBar` pattern.\n *\n * Rebuilt on RN's `TextInput` rather than ported from `@gnome-ui/react`'s\n * `<input type=\"search\">`: `open` no longer drives a CSS height/opacity\n * transition (no established animated-height pattern exists yet in this\n * package — same trade-off `SidebarSection` made for its collapsible body)\n * — `open={false}` renders nothing at all, and mounting on `open={true}`\n * auto-focuses the input, standing in for the web version's\n * `requestAnimationFrame`-on-open focus effect.\n *\n * Dropped relative to `@gnome-ui/react`'s `SearchBar`: the `suggestions` /\n * `onSuggestionSelect` / `loadingSuggestions` / `renderSuggestion` /\n * `suggestionsLabel` autocomplete popover — it depends on a portal +\n * viewport-anchored positioning primitive (`createPortal` +\n * `getBoundingClientRect`) this package doesn't have yet, the same gap\n * that dropped `SidebarItem`'s `menuItems` context menu — and a `Spinner`\n * component, not yet ported. The search/clear icons are Unicode glyphs\n * (`🔍`/`×`) rather than `@gnome-ui/icons`, matching every other\n * no-SVG-dependency component in this package.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.SearchBar.html\n */\nexport const SearchBar = forwardRef<TextInput, SearchBarProps>(function SearchBar(\n {\n open,\n onClose,\n onClear,\n children,\n value,\n placeholder = 'Search…',\n editable = true,\n inline = false,\n closeLabel = 'Cancel',\n style,\n inputStyle,\n ...inputProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const inputRef = useRef<TextInput>(null);\n\n useImperativeHandle(ref, () => inputRef.current as TextInput, []);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const id = requestAnimationFrame(() => inputRef.current?.focus());\n\n return () => cancelAnimationFrame(id);\n }, [open]);\n\n if (!open) {\n return null;\n }\n\n const disabled = !editable;\n const hasValue = typeof value === 'string' && value.length > 0;\n\n const barBg = inline ? 'transparent' : theme.headerbarBgColor;\n const barBorder = inline ? 'transparent' : theme.headerbarShadeColor;\n\n return (\n <RNView style={style}>\n <RNView style={{ flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}>\n <RNView\n style={{\n flex: 1,\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space2,\n backgroundColor: barBg,\n borderBottomWidth: 1,\n borderBottomColor: barBorder,\n opacity: disabled ? theme.opacityDisabled : 1,\n }}\n >\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{ opacity: theme.opacityDim, fontSize: theme.fontSizeBody }}\n >\n {'🔍'}\n </RNText>\n\n <RNTextInput\n ref={inputRef}\n editable={editable}\n value={value}\n placeholder={placeholder}\n placeholderTextColor={dimColor(theme.windowFgColor, theme.opacityDim)}\n style={[\n {\n flex: 1,\n padding: 0,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n color: theme.windowFgColor,\n } satisfies TextStyle,\n inputStyle,\n ]}\n {...inputProps}\n />\n\n {hasValue && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Clear search\"\n disabled={disabled}\n hitSlop={8}\n onPress={() => {\n onClear?.();\n inputRef.current?.focus();\n }}\n style={({ pressed }) => ({\n width: 24,\n height: 24,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: theme.windowFgColor }}>\n {'×'}\n </RNText>\n </Pressable>\n )}\n </RNView>\n\n {onClose && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={closeLabel}\n onPress={onClose}\n hitSlop={8}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n color: theme.accentColor,\n }}\n >\n {closeLabel}\n </RNText>\n </Pressable>\n )}\n </RNView>\n\n {children && (\n <RNView\n style={{\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: theme.space1,\n padding: theme.space1,\n paddingHorizontal: theme.space2,\n backgroundColor: barBg,\n borderBottomWidth: 1,\n borderBottomColor: barBorder,\n }}\n >\n {children}\n </RNView>\n )}\n </RNView>\n );\n});\n","import { Children, isValidElement, type ReactNode } from 'react';\n\n/** Recursively count items whose `label` prop matches `filter` (case-insensitive). */\nexport function countMatchingItems(children: ReactNode, filter: string): number {\n let count = 0;\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n return;\n }\n\n const props = child.props as Record<string, unknown>;\n\n if (typeof props.label === 'string') {\n if (props.label.toLowerCase().includes(filter.toLowerCase())) {\n count++;\n }\n } else if (props.children) {\n count += countMatchingItems(props.children as ReactNode, filter);\n }\n });\n\n return count;\n}\n\n/**\n * Whether a single top-level `Sidebar` child would render something under\n * `filter` — a bare `SidebarItem` if its own `label` matches, a\n * `SidebarSection` (or anything else with `children`) if any descendant\n * matches. Used to decide which children get a `Separator` between them, so\n * a filtered-out (null-rendering) item doesn't still claim a divider slot.\n */\nexport function isChildVisible(child: ReactNode, filter: string): boolean {\n if (!filter) {\n return true;\n }\n\n if (!isValidElement(child)) {\n return true;\n }\n\n const props = child.props as Record<string, unknown>;\n\n if (typeof props.label === 'string') {\n return props.label.toLowerCase().includes(filter.toLowerCase());\n }\n\n if (props.children) {\n return countMatchingItems(props.children as ReactNode, filter) > 0;\n }\n\n return true;\n}\n","import { Children, createContext, Fragment, forwardRef, type ReactNode, useContext } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView, ScrollView } from 'react-native';\n\nimport { Separator } from '@/components/Separator';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { isChildVisible } from './filterUtils';\n\n// ─── Contexts ───────────────────────────────────────────────────────────────\n\n/** Provides the collapsed state to all descendant `SidebarSection`/`SidebarItem`. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport const SidebarCollapsedContext = createContext(false);\n\n/** Returns `true` when the nearest `Sidebar` is in collapsed (icon-only/rail) mode. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useSidebarCollapsed() {\n return useContext(SidebarCollapsedContext);\n}\n\n/** Provides the active filter string to all descendant `SidebarItem`/`SidebarSection`. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport const SidebarFilterContext = createContext('');\n\n// ─── Props ──────────────────────────────────────────────────────────────────\n\nexport interface SidebarProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /**\n * When `true`, collapses the sidebar to icon-only (rail) mode. Labels and\n * section titles are hidden.\n */\n collapsed?: boolean;\n /**\n * Controlled filter string. `SidebarItem`s whose `label` does not match\n * (case-insensitive substring) are hidden, and empty `SidebarSection`s are\n * hidden entirely. Unlike the web version this never renders a search\n * input itself — pair it with your own `TextField` (or the future\n * `SearchBar` port) and drive this prop from its value.\n */\n filter?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Lateral navigation panel following the Adwaita `.navigation-sidebar` style.\n *\n * Compose with `SidebarSection` (named groups) and `SidebarItem` (rows).\n * Consecutive top-level children get a `Separator` inserted between them —\n * same divider-on-index-boundary technique `BoxedList` uses for its rows —\n * standing in for the web version's `.section + .section` adjacent-sibling\n * CSS rule, which RN has no equivalent of.\n *\n * Dropped relative to `@gnome-ui/react`'s `Sidebar`: `searchable` (would\n * pull in a `SearchBar`, not yet ported to this package — use `filter` with\n * your own input instead), `mode`/auto page-layout switch (depends on the\n * web-only `useBreakpoint` hook), `variant` (tinted/blurred backgrounds —\n * the blurred variant needs a native blur view this package doesn't depend\n * on), and the `<nav>` landmark role (RN's `AccessibilityRole` union has no\n * \"navigation\" value).\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const Sidebar = forwardRef<View, SidebarProps>(function Sidebar(\n { children, collapsed = false, filter = '', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const isFilterActive = filter.length > 0;\n const items = Children.toArray(children)\n .filter(Boolean)\n .filter((child) => isChildVisible(child, filter));\n\n const hasMatches = !isFilterActive || items.length > 0;\n\n return (\n <SidebarCollapsedContext.Provider value={collapsed}>\n <SidebarFilterContext.Provider value={filter}>\n <RNView\n ref={ref}\n style={[\n {\n flexShrink: 0,\n width: collapsed ? theme.layoutSidebarRailWidth : theme.layoutSidebarDefaultWidth,\n backgroundColor: theme.sidebarBgColor,\n borderRightWidth: 1,\n borderRightColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <ScrollView contentContainerStyle={{ padding: theme.space1 }}>\n {isFilterActive && !hasMatches ? (\n <Text\n variant=\"caption\"\n color=\"dim\"\n style={{ textAlign: 'center', padding: theme.space4 }}\n >\n No items match your search.\n </Text>\n ) : (\n items.map((child, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n <Fragment key={i}>\n {i > 0 && (\n <Separator\n testID=\"sidebar-separator\"\n style={{ marginVertical: theme.space1 }}\n />\n )}\n {child}\n </Fragment>\n ))\n )}\n </ScrollView>\n </RNView>\n </SidebarFilterContext.Provider>\n </SidebarCollapsedContext.Provider>\n );\n});\n","import { forwardRef, type ReactNode, useContext } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { SidebarFilterContext, useSidebarCollapsed } from './Sidebar';\n\nexport interface SidebarItemProps extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Primary label. */\n label: string;\n /**\n * Icon placed at the leading edge. Rendered as-is — size/color it\n * yourself. Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`;\n * this package has no SVG icon system, so it's a plain `ReactNode` here,\n * same as `ActionRow`'s `leading` and `TabItem`'s `icon`.\n */\n icon?: ReactNode;\n /** Marks this item as the currently active view. */\n active?: boolean;\n /** Trailing widget — badge, count, button, icon… */\n suffix?: ReactNode;\n disabled?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Individual navigation row inside a `Sidebar` or `SidebarSection`.\n *\n * Automatically hidden (renders nothing) when the nearest `Sidebar`'s\n * `filter` is active and `label` doesn't match. In collapsed (rail) mode\n * the label and suffix are hidden and the icon centers — `label` still\n * reaches screen readers via `accessibilityLabel`.\n *\n * Dropped relative to `@gnome-ui/react`'s `SidebarItem`: `tooltip` (no\n * `Tooltip` port yet, and RN's touch-first model has no hover to trigger\n * one from), `menuItems` (context menu — no portal/positioning primitive\n * exists in this package yet), and `onDrop`/`acceptTypes` (HTML5\n * drag-and-drop has no RN equivalent without a gesture-handler dependency\n * this package doesn't have).\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const SidebarItem = forwardRef<View, SidebarItemProps>(function SidebarItem(\n { label, icon, active = false, suffix, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const collapsed = useSidebarCollapsed();\n const filterValue = useContext(SidebarFilterContext);\n\n const isFiltered =\n filterValue.length > 0 && !label.toLowerCase().includes(filterValue.toLowerCase());\n\n if (isFiltered) {\n return null;\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => [\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: active\n ? theme.accentBgColor\n : pressed\n ? theme.hoverOverlay\n : 'transparent',\n },\n collapsed && { justifyContent: 'center', paddingHorizontal: 0 },\n style,\n ]}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0, opacity: active ? 1 : 0.85 }}>{icon}</RNView>}\n\n {!collapsed && (\n <Text\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n flex: 1,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: active ? theme.accentFgColor : theme.sidebarFgColor,\n }}\n >\n {label}\n </Text>\n )}\n\n {!collapsed && suffix && <RNView style={{ flexShrink: 0 }}>{suffix}</RNView>}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode, useContext, useImperativeHandle, useState } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport { countMatchingItems } from './filterUtils';\nimport { SidebarFilterContext, useSidebarCollapsed } from './Sidebar';\n\nexport interface SidebarSectionHandle {\n expand: () => void;\n collapse: () => void;\n toggle: () => void;\n}\n\nexport interface SidebarSectionProps extends Omit<ViewProps, 'style'> {\n /** Section heading. Omit for an untitled section (e.g. the first group in a sidebar). */\n title?: string;\n /** Icon rendered left of the title. Rendered as-is — size/color it yourself. */\n icon?: ReactNode;\n /** Whether the section body can be toggled open/closed. Defaults to `false`. */\n collapsible?: boolean;\n /** Initial open state when `collapsible` is true. Defaults to `true`. */\n defaultOpen?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Named group of `SidebarItem` entries inside a `Sidebar`.\n *\n * When `collapsible`, the body toggles via the header `Pressable` or\n * imperatively via a `ref` (`expand`/`collapse`/`toggle`) — same\n * `useImperativeHandle` shape as the web version's `SidebarSectionHandle`.\n * The body stays mounted and toggles `display: 'none'` rather than\n * unmounting, the same \"stays mounted but hidden\" approach `TabPanel` uses,\n * instead of porting the web version's animated CSS-grid collapse (no\n * established animated-height pattern exists yet in this package).\n *\n * In rail (`collapsed`) mode the header — and with it the collapse toggle —\n * is hidden and the body is always shown, matching the web version's rail\n * behavior. When a `Sidebar` filter is active and no descendant matches,\n * the whole section renders nothing.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const SidebarSection = forwardRef<SidebarSectionHandle, SidebarSectionProps>(\n function SidebarSection(\n {\n title,\n icon,\n collapsible = false,\n defaultOpen = true,\n open: controlledOpen,\n onOpenChange,\n children,\n style,\n ...viewProps\n },\n ref,\n ) {\n const theme = useGnomeTheme();\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n\n const collapsed = useSidebarCollapsed();\n const filterValue = useContext(SidebarFilterContext);\n\n const setAndNotify = (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n\n onOpenChange?.(next);\n };\n\n useImperativeHandle(ref, () => ({\n expand: () => setAndNotify(true),\n collapse: () => setAndNotify(false),\n toggle: () => setAndNotify(!open),\n }));\n\n const hasVisibleChildren =\n filterValue.length === 0 || countMatchingItems(children, filterValue) > 0;\n\n if (!hasVisibleChildren) {\n return null;\n }\n\n const isOpen = collapsed ? true : open;\n const showHeader = !collapsed && !!(title || icon);\n\n const header = (title || icon) && (\n <RNView\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space1,\n paddingVertical: 2,\n marginTop: 4,\n marginBottom: 2,\n }}\n >\n {icon && <RNView style={{ flexShrink: 0, opacity: 0.7 }}>{icon}</RNView>}\n {title && (\n <Text variant=\"caption-heading\" color=\"dim\" style={{ flex: 1 }} numberOfLines={1}>\n {title}\n </Text>\n )}\n {collapsible && (\n <Text variant=\"caption\" color=\"dim\" style={{ flexShrink: 0 }}>\n {open ? '▾' : '▸'}\n </Text>\n )}\n </RNView>\n );\n\n return (\n <RNView style={style} {...viewProps}>\n {showHeader &&\n (collapsible ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ expanded: open }}\n accessibilityLabel={title}\n onPress={() => setAndNotify(!open)}\n >\n {header}\n </Pressable>\n ) : (\n header\n ))}\n\n <RNView\n accessible\n accessibilityRole=\"list\"\n style={{ display: isOpen ? 'flex' : 'none', gap: 2 }}\n >\n {children}\n </RNView>\n </RNView>\n );\n },\n);\n","import { useEffect, useRef } from 'react';\nimport type { DimensionValue, StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing, View as RNView } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport type SkeletonVariant = 'rect' | 'circle' | 'text';\n\nexport interface SkeletonProps extends Omit<ViewProps, 'style'> {\n /** Shape of the placeholder. Defaults to `\"rect\"`. */\n variant?: SkeletonVariant;\n /** Width for rectangular placeholders. Defaults to `\"100%\"`. */\n width?: DimensionValue;\n /** Height for rectangular placeholders. Defaults to `16`. */\n height?: DimensionValue;\n /** Diameter for circular placeholders. Defaults to `40`. */\n size?: number;\n /** Number of rows for text placeholders. Defaults to `3`. */\n lines?: number;\n /** Enables the pulse animation. Respects `useReducedMotion()`. Defaults to `true`. */\n animated?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Loading placeholder for content-shaped skeleton screens.\n *\n * GNOME HIG recommends `Spinner` or `ProgressBar` for loading states; this\n * is a pragmatic web-style extension for layouts that benefit from\n * placeholder shape, ported as-is from `@gnome-ui/react`.\n *\n * The web version's shimmer is a `linear-gradient` swept across the shape\n * via `transform: translateX()`; this package has no gradient dependency\n * (no `expo-linear-gradient`/`react-native-linear-gradient` in its\n * dependency tree, and adding one for a single component would be scope\n * creep), so the animation is a plain opacity pulse instead — animating\n * `theme.skeletonBaseColor`'s own opacity between `1` and `0.5` on a\n * 1.4s round trip, the same cycle length as the web shimmer. This is a\n * common RN-idiomatic substitute for a CSS shimmer (compare Tailwind's own\n * `animate-pulse` utility, which uses the identical technique). Unlike\n * `Spinner` (slows) and `ProgressBar` (stops one state, slows the other),\n * `useReducedMotion()` here fully disables the pulse and shows a static\n * base color — mirroring the source CSS's own\n * `@media (prefers-reduced-motion: reduce) { animation: none }`, which has\n * no partial-motion in-between state to preserve.\n *\n * `theme.skeletonBaseColor` already resolves correctly per color scheme\n * (unlike `Spinner`'s track color, which the source CSS never actually\n * tokenizes), so no `useResolvedColorScheme()` branching is needed here.\n *\n * `accessible={false}` mirrors the web version's `aria-hidden=\"true\"` — a\n * loading placeholder carries no information a screen reader user needs,\n * same reasoning `Separator` already established for a purely decorative\n * element.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/progress.html\n */\nexport const Skeleton = ({\n variant = 'rect',\n width = '100%',\n height = 16,\n size = 40,\n lines = 3,\n animated = true,\n style,\n ...viewProps\n}: SkeletonProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n const pulse = useRef(new Animated.Value(1)).current;\n\n const isPulsing = animated && !reducedMotion;\n\n useEffect(() => {\n if (!isPulsing) {\n pulse.setValue(1);\n\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n const easing = Easing.bezier(x1, y1, x2, y2);\n\n const animation = Animated.loop(\n Animated.sequence([\n Animated.timing(pulse, { toValue: 0.5, duration: 700, easing, useNativeDriver: true }),\n Animated.timing(pulse, { toValue: 1, duration: 700, easing, useNativeDriver: true }),\n ]),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [isPulsing, pulse, theme.easingDefault]);\n\n if (variant === 'text') {\n const lineCount = Math.max(1, Math.floor(lines));\n\n return (\n <RNView accessible={false} style={[{ gap: 8 }, style]} {...viewProps}>\n {Array.from({ length: lineCount }, (_, index) => (\n <Animated.View\n // biome-ignore lint/suspicious/noArrayIndexKey: lines have no natural stable id\n key={index}\n style={{\n width: index === lineCount - 1 ? '60%' : '100%',\n height: 12,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.skeletonBaseColor,\n opacity: pulse,\n }}\n />\n ))}\n </RNView>\n );\n }\n\n const shapeStyle: ViewStyle =\n variant === 'circle'\n ? { width: size, height: size, borderRadius: size / 2 }\n : { width, height, borderRadius: theme.radiusMd };\n\n return (\n <Animated.View\n accessible={false}\n style={[shapeStyle, { backgroundColor: theme.skeletonBaseColor, opacity: pulse }, style]}\n {...viewProps}\n />\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\n\nconst SIZES: Record<SpinnerSize, { dimension: number; borderWidth: number }> = {\n sm: { dimension: 16, borderWidth: 2 },\n md: { dimension: 24, borderWidth: 2.5 },\n lg: { dimension: 36, borderWidth: 3 },\n};\n\nexport interface SpinnerProps extends Omit<ViewProps, 'style'> {\n /** Size of the spinner. Defaults to `\"md\"`. */\n size?: SpinnerSize;\n /**\n * Accessible label announced by screen readers. Defaults to\n * `\"Loading…\"`. Set to `\"\"` to silence if a sibling label is present.\n */\n label?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Indeterminate loading indicator following the Adwaita spinner style.\n *\n * Rebuilt on `Animated.View` rather than ported from `@gnome-ui/react`'s\n * pure-CSS `@keyframes spin` animation: the ring itself reuses the same\n * per-side-border trick the CSS does (`borderColor` for the track,\n * `borderTopColor` for the accent-colored \"head\" of the spinner, on a\n * `borderRadius: 50%` circle) — that part translates directly, since RN's\n * `View` supports independent per-side border colors too. The rotation\n * itself is an `Animated.loop`d `Animated.timing` driving a `rotate`\n * transform, `useNativeDriver: true` since only a transform is animated.\n *\n * `useReducedMotion()` mirrors the source CSS's own\n * `@media (prefers-reduced-motion: reduce) { animation-duration: 2s }` —\n * slowed to 2s, not stopped outright, exactly matching the web behavior\n * rather than dropping the animation entirely.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"progressbar\"` is the closest match for an\n * indeterminate loading indicator and is what's used here — omitting\n * `accessibilityValue` is RN's equivalent of omitting `aria-valuenow` for\n * an indeterminate progress bar. `@gnome-ui/react`'s two hardcoded\n * per-color-scheme track colors (the `--gnome-spinner-track-color` CSS\n * variable is referenced but never actually defined in `@gnome-ui/core`'s\n * tokens, so the CSS fallback value is always what renders) are ported as\n * the same hardcoded `rgba()` pair, branched on `useResolvedColorScheme()`\n * — the same pattern `Switch`/`Checkbox`/`RadioButton` already use for\n * colors the source CSS hardcodes rather than tokenizes.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n */\nexport const Spinner = ({ size = 'md', label = 'Loading…', style, ...viewProps }: SpinnerProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const spin = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n spin.setValue(0);\n\n const animation = Animated.loop(\n Animated.timing(spin, {\n toValue: 1,\n duration: reducedMotion ? 2000 : 750,\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [spin, reducedMotion]);\n\n const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'] });\n const { dimension, borderWidth } = SIZES[size];\n const trackColor = scheme === 'dark' ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)';\n\n return (\n <Animated.View\n accessible\n accessibilityRole=\"progressbar\"\n accessibilityLabel={label || undefined}\n accessibilityElementsHidden={label === ''}\n importantForAccessibility={label === '' ? 'no-hide-descendants' : 'yes'}\n style={[\n {\n width: dimension,\n height: dimension,\n borderRadius: dimension / 2,\n borderWidth,\n borderColor: trackColor,\n borderTopColor: theme.accentColor,\n transform: [{ rotate }],\n },\n style,\n ]}\n {...viewProps}\n />\n );\n};\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface SwitchProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether the switch is on. */\n value: boolean;\n /** Called with the next value when the switch is pressed. */\n onValueChange?: (value: boolean) => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst TRACK_WIDTH = 56;\nconst TRACK_HEIGHT = 28;\nconst THUMB_SIZE = 20;\nconst THUMB_INSET = 3;\n/** Matches `@gnome-ui/react`'s `.switch:checked::before { transform: translateX(28px) }`. */\nconst THUMB_TRAVEL = 28;\n\n/**\n * On/off toggle following the Adwaita switch style.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"checkbox\" role=\"switch\">`: RN has no\n * checkbox primitive to style, and the platform-supplied `Switch` can't be\n * skinned to match Adwaita, so the track and thumb are drawn by hand.\n * `value`/`onValueChange` (not `checked`/`onChange`) mirror RN's own\n * `Switch` API, which is the ecosystem convention this component overlaps\n * with — it's fully controlled, with no `defaultValue` escape hatch.\n *\n * Two of `Switch.module.css`'s colors are hardcoded per color scheme\n * inside a component-level `@media (prefers-color-scheme: dark)` block\n * rather than driven by a semantic token, so — unlike `Button`/`Link`/\n * `TextField`, which read a single token that already resolves correctly\n * per theme — the unchecked track/thumb colors here branch explicitly on\n * `useResolvedColorScheme()` to match. Track background/border color\n * animate (mirroring the CSS `transition` on `.switch`); the thumb's own\n * fill color does not, since the source CSS only transitions its\n * `transform`, not its `background-color`.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/switches.html\n */\nexport const Switch = forwardRef<View, SwitchProps>(function Switch(\n { value, onValueChange, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const progress = useRef(new Animated.Value(value ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `value` — skip\n // animating into a state the switch is already rendering, so it never\n // plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: value ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [value, progress, theme.durationFast, theme.easingDefault]);\n\n const trackColorOff = colorScheme === 'dark' ? theme.dark2 : theme.light4;\n const thumbColorOff = colorScheme === 'dark' ? theme.light3 : '#fff';\n\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [trackColorOff, theme.accentBgColor],\n });\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.borderSubtle, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: value, disabled: !!disabled }}\n onPress={() => onValueChange?.(!value)}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: TRACK_WIDTH,\n height: TRACK_HEIGHT,\n borderRadius: theme.radiusPill,\n borderWidth: contrast === 'more' ? 2 : 1,\n borderColor,\n backgroundColor,\n }}\n >\n <Animated.View\n style={[\n {\n position: 'absolute',\n top: THUMB_INSET,\n left: THUMB_INSET,\n width: THUMB_SIZE,\n height: THUMB_SIZE,\n borderRadius: theme.radiusPill,\n backgroundColor: value ? '#fff' : thumbColorOff,\n transform: [\n {\n translateX: progress.interpolate({\n inputRange: [0, 1],\n outputRange: [0, THUMB_TRAVEL],\n }),\n },\n ],\n },\n contrast !== 'more' && {\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 1 },\n shadowOpacity: 0.25,\n shadowRadius: 3,\n elevation: 2,\n },\n ]}\n />\n </Animated.View>\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { ScrollView, ScrollViewProps, StyleProp, ViewStyle } from 'react-native';\nimport { ScrollView as RNScrollView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface TabBarProps extends Omit<ScrollViewProps, 'style' | 'horizontal' | 'children'> {\n children?: ReactNode;\n /** Accessible label for the tab list. */\n accessibilityLabel?: string;\n /**\n * Removes the header-bar background so the tab bar blends into any surface.\n * Use when placing the bar inside a card, content area, or custom container.\n * Mirrors the `.inline` style class.\n */\n inline?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Horizontal, horizontally-scrollable tab bar that holds `TabItem` elements.\n *\n * Rebuilt on a horizontal `ScrollView` rather than ported from\n * `@gnome-ui/react`'s `overflow-x: auto` `<div role=\"tablist\">` — RN's\n * `AccessibilityRole` union does include `\"tablist\"`, so that semantic\n * carries over directly, but the web version's roving-tabindex ← → / Home /\n * End keyboard navigation doesn't: RN's touch-first focus model has no\n * per-app arrow-key convention to port, so it's dropped here rather than\n * faking it.\n *\n * `style={{ flexGrow: 0 }}` on the `ScrollView` is deliberate, not\n * decorative — a horizontal `ScrollView` with no explicit `flexGrow` can\n * stretch to fill the cross-axis of whatever flex column it's placed in\n * (confirmed the hard way debugging the example app's own tab-like\n * `ControlsBar`), so it's baked in here once rather than left for every\n * consumer to rediscover.\n *\n * @see https://developer.gnome.org/hig/patterns/nav/tabs.html\n */\nexport const TabBar = forwardRef<ScrollView, TabBarProps>(function TabBar(\n { children, inline = false, accessibilityLabel = 'Tabs', style, ...scrollViewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNScrollView\n ref={ref}\n horizontal\n showsHorizontalScrollIndicator={false}\n contentInsetAdjustmentBehavior=\"never\"\n accessible\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n style={[\n {\n flexGrow: 0,\n backgroundColor: inline ? 'transparent' : theme.headerbarBgColor,\n borderBottomWidth: inline ? 0 : 1,\n borderBottomColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n contentContainerStyle={{\n flexDirection: 'row',\n alignItems: 'stretch',\n paddingHorizontal: theme.space1,\n gap: 2,\n minHeight: 40,\n }}\n {...scrollViewProps}\n >\n {children}\n </RNScrollView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, TextStyle, View } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface TabItemProps extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Tab label. */\n label: string;\n /**\n * Icon placed before the label. Rendered as-is — size/color it yourself.\n * Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`; this package\n * has no SVG icon system (see [[react-native-port-status]]), so it's a\n * plain `ReactNode` here instead, same as `ActionRow`'s `leading`.\n */\n icon?: ReactNode;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user taps the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n /** Optional count shown as a small badge next to the label. Values above 99 render as \"99+\". */\n count?: number;\n disabled?: boolean;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n *\n * Web's `panelId` (which sets `aria-controls`) is dropped — RN has no ARIA\n * relationship attributes, so there's nothing for it to wire up; keep the\n * tab ↔ panel link in your own state instead. The count badge is a small\n * inline pill rather than the web version's separate `Badge` component,\n * since `Badge` hasn't been ported to this package yet and pulling in a\n * whole new component just for this one pill would be scope creep.\n *\n * The close button is a nested `Pressable` inside the tab's own\n * `Pressable` — unlike the web version, no explicit \"stop propagation\" is\n * needed: RN's touch responder system grants an in-progress touch to the\n * innermost view that claims it, so pressing the close button never also\n * fires the outer tab's `onPress`. It also gets a `hitSlop` the web\n * version has no equivalent of, since its 18×18 visual size is well under\n * the ~44pt touch target guidance both major mobile platforms recommend.\n *\n * The label `Text` deliberately has no `flex: 1` (unlike the web version's\n * `.tabLabel`) — the outer `Pressable`'s width here is content-driven\n * (`minWidth`/`maxWidth`, not a definite width), and giving a `flex: 1`\n * child to a row whose own width isn't definite collapses that child to a\n * near-zero width in Yoga (confirmed visually: every label truncated to\n * 3-4 characters despite ample room). CSS flexbox resolves this fine\n * because browsers can grow a flex child within an intrinsically-sized\n * container; Yoga can't. `numberOfLines`/`ellipsizeMode` alone are enough\n * to truncate genuinely-too-long labels against `maxWidth`.\n */\nexport const TabItem = forwardRef<View, TabItemProps>(function TabItem(\n {\n label,\n icon,\n active = false,\n onClose,\n closeLabel = 'Close tab',\n count,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => ({\n position: 'relative',\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space2,\n minWidth: 80,\n maxWidth: 200,\n minHeight: 40,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : active ? 1 : 0.7,\n backgroundColor: active\n ? theme.activeOverlay\n : pressed\n ? theme.hoverOverlay\n : 'transparent',\n })}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0 }}>{icon}</RNView>}\n\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: theme.headerbarFgColor,\n }}\n >\n {label}\n </RNText>\n\n {count !== undefined && (\n <RNView\n style={{\n flexShrink: 0,\n minWidth: 18,\n height: 18,\n paddingHorizontal: 5,\n borderRadius: 9,\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: theme.accentBgColor,\n }}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: 11,\n fontWeight: '600' as TextStyle['fontWeight'],\n color: theme.accentFgColor,\n }}\n >\n {count > 99 ? '99+' : count}\n </RNText>\n </RNView>\n )}\n\n {onClose && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={closeLabel}\n hitSlop={8}\n onPress={onClose}\n style={({ pressed }) => ({\n flexShrink: 0,\n width: 18,\n height: 18,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: 15,\n lineHeight: 16,\n color: theme.headerbarFgColor,\n }}\n >\n {'×'}\n </RNText>\n </Pressable>\n )}\n\n {active && (\n <RNView\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n bottom: 0,\n left: theme.space2,\n right: theme.space2,\n height: 2,\n borderRadius: 1,\n backgroundColor: theme.accentBgColor,\n }}\n />\n )}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nexport interface TabPanelProps extends Omit<ViewProps, 'style'> {\n /** Controls whether this panel is visible. */\n active?: boolean;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Content panel associated with a `TabItem`.\n *\n * Web's `id` (paired with `TabItem`'s `panelId`, together wiring up\n * `aria-controls`) is dropped on both sides here — RN has no ARIA\n * relationship attributes for it to drive, so track which tab is active in\n * your own state (index, key, whatever) and pass the matching panel\n * `active={true}` directly, rather than reaching for an id-matching\n * convention with nothing underneath it.\n *\n * Hidden panels stay mounted with `display: 'none'` rather than being\n * conditionally unmounted — same as the web version keeping them in the\n * DOM via the `hidden` attribute — so a panel's internal state (scroll\n * position, form input, etc.) survives switching tabs away and back. RN\n * has no `\"tabpanel\"` value in its `AccessibilityRole` union (unlike\n * `TabBar`'s `\"tablist\"` and `TabItem`'s `\"tab\"`, both of which do exist),\n * so no role is set here — same reasoning as `Separator` dropping a role\n * RN doesn't have rather than reaching for an inaccurate substitute.\n */\nexport const TabPanel = forwardRef<View, TabPanelProps>(function TabPanel(\n { active = false, style, children, ...viewProps },\n ref,\n) {\n return (\n <RNView ref={ref} style={[{ display: active ? 'flex' : 'none' }, style]} {...viewProps}>\n {children}\n </RNView>\n );\n});\n","import { forwardRef, useState } from 'react';\nimport type { StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport { TextInput as RNTextInput, View } from 'react-native';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface TextFieldProps extends Omit<TextInputProps, 'style'> {\n /** Visible label rendered above the input. */\n label?: string;\n /** Helper text rendered below the input. Hidden when `error` is set. */\n helperText?: string;\n /**\n * Error message rendered below the input in place of `helperText`.\n * Also applies the error visual state to the input border.\n */\n error?: string;\n /** Style applied to the wrapping `View`. */\n style?: StyleProp<ViewStyle>;\n /** Style applied to the `TextInput` itself. */\n inputStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Multiplies an `rgba(r, g, b, a)` token's alpha channel. Tokens that\n * aren't `rgba()` (e.g. `windowFgColor` in some variants resolves to a flat\n * hex) are returned unchanged — good enough here since this is only ever\n * used to dim `windowFgColor`, which the generated theme always emits as\n * `rgba()`.\n */\nfunction dimColor(color: string, factor: number): string {\n const match = color.match(/^rgba?\\(([^,]+),([^,]+),([^,]+),?([^)]+)?\\)$/);\n\n if (!match) {\n return color;\n }\n\n const [, r, g, b, a] = match;\n const alpha = (a ? Number.parseFloat(a) : 1) * factor;\n\n return `rgba(${r.trim()}, ${g.trim()}, ${b.trim()}, ${alpha})`;\n}\n\n/**\n * Single-line text input with label, helper text, and error state.\n *\n * Follows the Adwaita `GtkEntry` / `.entry` style class.\n *\n * Rebuilt on RN's `TextInput` rather than ported from `@gnome-ui/react`'s\n * `<input>`: there's no `<label htmlFor>`/`aria-describedby` pairing on RN,\n * so `label` doubles as `accessibilityLabel` and `error`/`helperText`\n * double as `accessibilityHint` — announced together with the input the\n * same way `aria-describedby` reads them on the web. `:focus-visible`'s\n * accent border becomes plain `onFocus`/`onBlur` state — RN has no\n * hover/keyboard-vs-pointer focus distinction to mirror, and no outer\n * `box-shadow` ring, so focus is just a border-color change rather than a\n * grown ring. The web version's `disabled` prop is RN's own\n * `editable={false}` — mirrored here as a dimmed wrapper the same way\n * `@gnome-ui/react`'s `.disabled` class dims the label and hint alongside\n * the input.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/text-fields.html\n */\nexport const TextField = forwardRef<TextInput, TextFieldProps>(function TextField(\n {\n label,\n helperText,\n error,\n style,\n inputStyle,\n editable = true,\n onFocus,\n onBlur,\n accessibilityLabel,\n accessibilityHint,\n ...inputProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const contrast = useResolvedContrast();\n const [focused, setFocused] = useState(false);\n const disabled = !editable;\n const hint = error ?? helperText;\n\n const borderColor = error ? theme.errorColor : focused ? theme.accentColor : theme.borderSubtle;\n\n return (\n <View style={[{ gap: theme.space1, opacity: disabled ? theme.opacityDisabled : 1 }, style]}>\n {label && (\n <Text\n variant=\"body\"\n style={{ fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'] }}\n >\n {label}\n </Text>\n )}\n\n <RNTextInput\n ref={ref}\n editable={editable}\n accessibilityLabel={accessibilityLabel ?? label}\n accessibilityHint={accessibilityHint ?? hint}\n placeholderTextColor={dimColor(theme.windowFgColor, theme.opacityDim)}\n onFocus={(event) => {\n setFocused(true);\n onFocus?.(event);\n }}\n onBlur={(event) => {\n setFocused(false);\n onBlur?.(event);\n }}\n style={[\n {\n width: '100%',\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n color: theme.viewFgColor,\n backgroundColor: theme.viewBgColor,\n borderRadius: theme.radiusMd,\n borderWidth: contrast === 'more' ? 2 : 1,\n borderColor,\n } satisfies TextStyle,\n inputStyle,\n ]}\n {...inputProps}\n />\n\n {hint && (\n <Text\n variant=\"caption\"\n style={{\n color: error ? theme.errorColor : theme.windowFgColor,\n opacity: error ? 1 : theme.opacityDim,\n }}\n >\n {hint}\n </Text>\n )}\n </View>\n );\n});\n","import { type ReactNode, useCallback, useEffect, useRef } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable, Text as RNText } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\n/**\n * `Animated`'s style interpolation only takes effect on `Animated.*`\n * host components — a plain `Pressable` would silently ignore the\n * animated `opacity`/`transform` in its style. Hoisted to module scope so\n * it isn't recreated on every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nexport interface ToastProps extends Omit<ViewProps, 'style'> {\n /** The notification message. Keep it short — one sentence. */\n title: ReactNode;\n /**\n * Auto-dismiss timeout in milliseconds.\n * - Set to `0` to disable auto-dismiss (user must press action or dismiss).\n * - Defaults to `3000`.\n */\n duration?: number;\n /** Called when the toast should be removed — after timeout or user action. */\n onDismiss?: () => void;\n /** Label for the optional action button. */\n actionLabel?: string;\n /** Called when the user presses the action button. */\n onAction?: () => void;\n /** Whether to show a manual dismiss (×) button. */\n dismissible?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Non-blocking temporary notification following the Adwaita `AdwToast`\n * pattern. Auto-dismisses after `duration` ms (default 3s, `0` disables\n * it); the timer pauses while the toast is pressed and held. Use inside\n * `Toaster` for correct positioning and stacking.\n *\n * The auto-dismiss/pause timer logic (`timerRef`/`remainingRef`/\n * `startedAtRef`) is ported verbatim from `@gnome-ui/react` — it's plain\n * `setTimeout`/`Date.now()` bookkeeping, no DOM API involved, so nothing\n * platform-specific to change. The pause trigger is: RN has no hover, so\n * `onPressIn`/`onPressOut` (touch-down/touch-up) stand in for the web\n * version's `onMouseEnter`/`onMouseLeave` — pausing while the user is\n * actively touching the toast, the closest RN analog to \"giving the user\n * time to read it.\" `onFocus`/`onBlur`-triggered pausing (keyboard\n * accessibility on web) has no port here — the outer card itself isn't a\n * focusable element in RN's touch-first model, only its action/dismiss\n * buttons are, and RN has no \"focus-within\" primitive to detect that\n * without an extra dependency.\n *\n * The entrance is an `Animated.timing` fading + sliding + scaling in\n * (`opacity`/`translateY`/`scale`, all transform-safe for\n * `useNativeDriver: true`), matching the web version's `@keyframes\n * toast-in`; `useReducedMotion()` skips straight to the settled state,\n * matching the source CSS's `animation: none`. There's no exit animation\n * to port either — the web version doesn't define one, removal is\n * immediate once the consumer drops the `Toast` from its list.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"alert\"` is the closest available role for content\n * that should interrupt and be announced, paired with\n * `accessibilityLiveRegion=\"polite\"` (Android's live-region API) as the\n * nearest match to the web's `aria-live=\"polite\"` — deliberately not\n * `\"assertive\"`, matching the same politeness level the source chose.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Toast.html\n */\nexport const Toast = ({\n title,\n duration = 3000,\n onDismiss,\n actionLabel,\n onAction,\n dismissible = false,\n style,\n ...viewProps\n}: ToastProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const remainingRef = useRef(duration);\n const startedAtRef = useRef(0);\n const progress = useRef(new Animated.Value(reducedMotion ? 1 : 0)).current;\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const startTimer = useCallback(\n (ms: number) => {\n if (ms <= 0 || !onDismiss) {\n return;\n }\n\n clearTimer();\n startedAtRef.current = Date.now();\n timerRef.current = setTimeout(() => onDismiss(), ms);\n },\n [onDismiss, clearTimer],\n );\n\n useEffect(() => {\n if (duration > 0) {\n remainingRef.current = duration;\n startTimer(duration);\n }\n\n return clearTimer;\n }, [duration, startTimer, clearTimer]);\n\n useEffect(() => {\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [reducedMotion, progress, theme.durationNormal, theme.easingDefault]);\n\n const handlePressIn = () => {\n if (timerRef.current) {\n const elapsed = Date.now() - startedAtRef.current;\n\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\n clearTimer();\n }\n };\n\n const handlePressOut = () => {\n startTimer(remainingRef.current);\n };\n\n const handleAction = () => {\n clearTimer();\n onAction?.();\n onDismiss?.();\n };\n\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.4, shadowRadius: 12, elevation: 6 }\n : { shadowOpacity: 0.15, shadowRadius: 8, elevation: 4 };\n\n return (\n <AnimatedPressable\n accessible\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 10,\n paddingRight: theme.space2,\n paddingLeft: theme.space3,\n minHeight: 44,\n maxWidth: 480,\n minWidth: 240,\n backgroundColor: theme.cardBgColor,\n borderRadius: theme.radiusLg,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n opacity: progress,\n transform: [\n {\n translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [12, 0] }),\n },\n { scale: progress.interpolate({ inputRange: [0, 1], outputRange: [0.96, 1] }) },\n ],\n ...shadow,\n },\n style,\n ]}\n {...viewProps}\n >\n <Text\n variant=\"body\"\n style={{ flex: 1, minWidth: 0 }}\n numberOfLines={typeof title === 'string' ? 2 : undefined}\n >\n {title}\n </Text>\n\n {(actionLabel || dismissible) && (\n <>\n {actionLabel && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={actionLabel}\n onPress={handleAction}\n style={({ pressed }) => ({\n paddingVertical: 4,\n paddingHorizontal: theme.space1,\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: theme.accentColor,\n }}\n >\n {actionLabel}\n </RNText>\n </Pressable>\n )}\n\n {dismissible && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={4}\n onPress={() => {\n clearTimer();\n onDismiss?.();\n }}\n style={({ pressed }) => ({\n width: 28,\n height: 28,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n opacity: pressed ? 1 : 0.55,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: theme.windowFgColor }}>\n {'×'}\n </RNText>\n </Pressable>\n )}\n </>\n )}\n </AnimatedPressable>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface ToasterProps extends Omit<ViewProps, 'style'> {\n /**\n * Where to position the toast stack within its container.\n * - `\"bottom\"` (default) — bottom-center, following the GNOME HIG.\n * - `\"top\"` — top-center.\n */\n position?: 'bottom' | 'top';\n /** `Toast` elements to display. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Absolutely-positioned container that stacks `Toast` notifications.\n *\n * RN has no `document.body`/portal target to render into the way the web\n * version's `createPortal(node, container ?? document.body)` does, so\n * there's no `container` prop here — mount `Toaster` yourself as the\n * **last** child of your app's root-level `View` (so it paints on top of\n * everything else) with that root `View` given `position: 'relative'` (or\n * left as the default relative positioning). `Toaster` then positions\n * itself with `position: 'absolute'`, spanning the full width and\n * anchored to `top`/`bottom` by `position`.\n *\n * `pointerEvents=\"box-none\"` is RN's equivalent of the web version's\n * `pointer-events: none` on the container — the empty space around the\n * toast stack doesn't intercept touches, but each `Toast` inside (a\n * `Pressable`) still handles its own.\n *\n * @example\n * ```tsx\n * <View style={{ flex: 1 }}>\n * <YourAppContent />\n * <Toaster>\n * {toasts.map((t) => (\n * <Toast key={t.id} title={t.message} onDismiss={() => remove(t.id)} />\n * ))}\n * </Toaster>\n * </View>\n * ```\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Toast.html\n */\nexport const Toaster = ({ position = 'bottom', children, style, ...viewProps }: ToasterProps) => {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n pointerEvents=\"box-none\"\n accessibilityLabel=\"Notifications\"\n style={[\n {\n position: 'absolute',\n left: 0,\n right: 0,\n alignItems: 'center',\n gap: theme.space1,\n zIndex: 9999,\n },\n position === 'top' ? { top: theme.space4 } : { bottom: theme.space4 },\n style,\n ]}\n {...viewProps}\n >\n {children}\n </RNView>\n );\n};\n","import {\n cloneElement,\n type ReactElement,\n type Ref,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n GestureResponderEvent,\n LayoutChangeEvent,\n MouseEvent,\n NativeSyntheticEvent,\n PressableProps,\n TargetedEvent,\n TextStyle,\n} from 'react-native';\nimport { Animated, Dimensions, Modal, StyleSheet, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface TooltipProps {\n /**\n * The tooltip label. Keep it short — a noun phrase or brief description.\n * Do not duplicate information already visible on screen.\n */\n label: string;\n /**\n * Preferred placement relative to the trigger.\n * The tooltip flips automatically if there is not enough space.\n * Defaults to `\"top\"`.\n */\n placement?: TooltipPlacement;\n /**\n * Delay in milliseconds before the tooltip appears, on both the\n * long-press and hover/focus triggers. Defaults to `500`. Set to `0` for\n * instant.\n */\n delay?: number;\n /**\n * The element that triggers the tooltip.\n * Must be a single element built on `Pressable` (e.g. `Button`, `Card`)\n * that forwards its `ref` to the underlying `View`.\n */\n children: ReactElement<PressableProps & { ref?: Ref<View> }>;\n}\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface Size {\n width: number;\n height: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n placement: TooltipPlacement;\n}\n\nconst GAP = 6;\nconst MARGIN = 8;\nconst ARROW = 5;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (!ref) {\n return;\n }\n\n if (typeof ref === 'function') {\n ref(value);\n\n return;\n }\n\n (ref as { current: T | null }).current = value;\n}\n\nfunction placementRect(trigger: Rect, tooltip: Size, placement: TooltipPlacement) {\n switch (placement) {\n case 'top':\n return {\n top: trigger.y - tooltip.height - GAP,\n left: trigger.x + trigger.width / 2 - tooltip.width / 2,\n };\n case 'bottom':\n return {\n top: trigger.y + trigger.height + GAP,\n left: trigger.x + trigger.width / 2 - tooltip.width / 2,\n };\n case 'left':\n return {\n top: trigger.y + trigger.height / 2 - tooltip.height / 2,\n left: trigger.x - tooltip.width - GAP,\n };\n case 'right':\n return {\n top: trigger.y + trigger.height / 2 - tooltip.height / 2,\n left: trigger.x + trigger.width + GAP,\n };\n }\n}\n\nfunction computePosition(trigger: Rect, tooltip: Size, preferred: TooltipPlacement): Position {\n const { width: vw, height: vh } = Dimensions.get('window');\n\n const opposite: TooltipPlacement =\n preferred === 'top'\n ? 'bottom'\n : preferred === 'bottom'\n ? 'top'\n : preferred === 'left'\n ? 'right'\n : 'left';\n const placements: TooltipPlacement[] = [preferred, opposite, 'top', 'bottom', 'left', 'right'];\n\n for (const p of placements) {\n const { top, left } = placementRect(trigger, tooltip, p);\n const fitsH = left >= MARGIN && left + tooltip.width <= vw - MARGIN;\n const fitsV = top >= MARGIN && top + tooltip.height <= vh - MARGIN;\n\n if (fitsH && fitsV) {\n return {\n top: Math.max(MARGIN, Math.min(top, vh - tooltip.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - tooltip.width - MARGIN)),\n placement: p,\n };\n }\n }\n\n const { top, left } = placementRect(trigger, tooltip, preferred);\n\n return {\n top: Math.max(MARGIN, Math.min(top, vh - tooltip.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - tooltip.width - MARGIN)),\n placement: preferred,\n };\n}\n\n/**\n * Informational tooltip following the Adwaita / GNOME HIG pattern.\n *\n * Wraps a single trigger element and shows a floating label. Positioned\n * automatically and flips if there is not enough space, mirroring\n * `@gnome-ui/react`'s `Tooltip`.\n *\n * **Trigger differs from the web version by necessity**: the web `Tooltip`\n * shows only on mouse hover / keyboard focus — touch has no hover state, so\n * it explicitly never shows on touch. RN is touch-first, so the primary\n * trigger here is long-press (`delayLongPress={delay}`, released via\n * `onPressOut`) — the standard mobile \"peek\" idiom. `onHoverIn`/`onHoverOut`\n * are also wired for hover-capable input (trackpad/mouse on iPad or a\n * pointer-driven RN target) and `onFocus`/`onBlur` for external-keyboard\n * accessibility, both delayed the same way the web version delays hover.\n *\n * Built on RN's own `Modal` (transparent, `pointerEvents=\"box-none\"`), the\n * same portal-substitute `Dialog` uses — no DOM `Portal` equivalent exists.\n * Unlike `Dialog`, `visible` is set synchronously on trigger (not gated on\n * the async `measureInWindow` result): the trigger's on-screen rect and the\n * tooltip's own rendered size each resolve independently into state, and a\n * separate effect computes the final position only once both have arrived.\n * Gating `visible` itself on `measureInWindow`'s callback was tried first\n * and dropped — that callback never fires in this package's Jest\n * environment (no real native view to measure), which would make the\n * component untestable, and in production it would also lose a real\n * quick-tap-then-release press if the callback resolved after `onPressOut`\n * had already fired.\n *\n * `role=\"tooltip\"` ports 1:1 — RN's newer web-aligned `Role` union (the\n * same one `Dialog` uses for `role=\"dialog\"`) already has a `\"tooltip\"`\n * value, no substitution needed. `aria-describedby` has no RN equivalent\n * (no cross-platform description-relationship prop exists), so the label is\n * set as the trigger's `accessibilityHint` instead — read after the\n * trigger's own label by VoiceOver/TalkBack, the nearest analog. The CSS\n * arrow reuses the same zero-size / transparent-border-on-three-sides\n * triangle trick as the web version — RN Views support per-side\n * `border*Color` just like CSS, the same technique `Spinner`'s ring\n * already relies on, applied here to a triangle instead of an arc.\n *\n * Not ported: repositioning on scroll/resize while visible (the web\n * version listens for both) — RN has no global scroll event, and a\n * long-press is naturally cancelled by a scroll gesture starting, so the\n * window to go stale is negligible for the touch trigger; orientation\n * change mid-hover is an accepted edge case for a component this transient.\n * `tooltipBgColor`/`tooltipFgColor` are not real `@gnome-ui/core` tokens\n * (only referenced as CSS var fallbacks, never defined) — hardcoded to the\n * same literal light/dark values as the web fallback, the same workaround\n * `Spinner`'s track color already established for this class of gap.\n *\n * @example\n * <Tooltip label=\"Save file\">\n * <Button accessibilityLabel=\"Save\"><Icon icon={Save} /></Button>\n * </Tooltip>\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/tooltips.html\n */\nexport const Tooltip = ({\n label,\n placement: preferredPlacement = 'top',\n delay = 500,\n children,\n}: TooltipProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const [visible, setVisible] = useState(false);\n const [triggerRect, setTriggerRect] = useState<Rect | null>(null);\n const [tooltipSize, setTooltipSize] = useState<Size | null>(null);\n const [pos, setPos] = useState<Position | null>(null);\n\n const triggerRef = useRef<View>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const progress = useRef(new Animated.Value(0)).current;\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const open = useCallback(() => {\n clearTimer();\n setVisible(true);\n }, [clearTimer]);\n\n const openDelayed = useCallback(() => {\n clearTimer();\n timerRef.current = setTimeout(open, delay);\n }, [clearTimer, open, delay]);\n\n const close = useCallback(() => {\n clearTimer();\n setVisible(false);\n }, [clearTimer]);\n\n // Measure the trigger's on-screen rect as soon as it's asked to show.\n useEffect(() => {\n if (!visible) {\n setTriggerRect(null);\n setTooltipSize(null);\n setPos(null);\n\n return;\n }\n\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerRect({ x, y, width, height });\n });\n }, [visible]);\n\n // Resolve the final position once both the trigger's rect and the\n // tooltip's own rendered size are known.\n useEffect(() => {\n if (!triggerRect || !tooltipSize) {\n return;\n }\n\n setPos(computePosition(triggerRect, tooltipSize, preferredPlacement));\n }, [triggerRect, tooltipSize, preferredPlacement]);\n\n useEffect(() => {\n if (!pos) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationFast,\n useNativeDriver: true,\n }).start();\n }, [pos, reducedMotion, progress, theme.durationFast]);\n\n useEffect(() => clearTimer, [clearTimer]);\n\n const handleTooltipLayout = (e: LayoutChangeEvent) => {\n const { width, height } = e.nativeEvent.layout;\n\n setTooltipSize({ width, height });\n };\n\n const bg = scheme === 'dark' ? '#c0bfbc' : '#3d3d3d';\n const fg = scheme === 'dark' ? 'rgba(0, 0, 0, 0.8)' : '#fff';\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.4, shadowRadius: 8, elevation: 6 }\n : { shadowOpacity: 0.2, shadowRadius: 8, elevation: 4 };\n\n const arrowBase = {\n position: 'absolute' as const,\n width: 0,\n height: 0,\n borderWidth: ARROW,\n borderColor: 'transparent',\n };\n\n const arrowStyle = (() => {\n switch (pos?.placement) {\n case 'top':\n return {\n ...arrowBase,\n top: '100%' as const,\n left: '50%' as const,\n marginLeft: -ARROW,\n borderTopColor: bg,\n };\n case 'bottom':\n return {\n ...arrowBase,\n bottom: '100%' as const,\n left: '50%' as const,\n marginLeft: -ARROW,\n borderBottomColor: bg,\n };\n case 'left':\n return {\n ...arrowBase,\n left: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderLeftColor: bg,\n };\n case 'right':\n return {\n ...arrowBase,\n right: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderRightColor: bg,\n };\n default:\n return null;\n }\n })();\n\n const existingRef = (children.props as { ref?: Ref<View> }).ref;\n\n const child = cloneElement(children, {\n ref: (node: View | null) => {\n (triggerRef as { current: View | null }).current = node;\n assignRef(existingRef, node);\n },\n delayLongPress: delay,\n accessibilityHint: children.props.accessibilityHint ?? label,\n onLongPress: (e: GestureResponderEvent) => {\n open();\n children.props.onLongPress?.(e);\n },\n onPressOut: (e: GestureResponderEvent) => {\n close();\n children.props.onPressOut?.(e);\n },\n onHoverIn: (e: MouseEvent) => {\n openDelayed();\n children.props.onHoverIn?.(e);\n },\n onHoverOut: (e: MouseEvent) => {\n close();\n children.props.onHoverOut?.(e);\n },\n onFocus: (e: NativeSyntheticEvent<TargetedEvent>) => {\n openDelayed();\n children.props.onFocus?.(e);\n },\n onBlur: (e: NativeSyntheticEvent<TargetedEvent>) => {\n close();\n children.props.onBlur?.(e);\n },\n });\n\n return (\n <>\n {child}\n <Modal visible={visible} transparent animationType=\"none\" statusBarTranslucent>\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n <Animated.View\n onLayout={handleTooltipLayout}\n accessible\n role=\"tooltip\"\n style={[\n {\n position: 'absolute',\n maxWidth: 240,\n paddingVertical: 4,\n paddingHorizontal: theme.space2,\n backgroundColor: bg,\n borderRadius: theme.radiusSm,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n ...shadow,\n },\n pos\n ? { top: pos.top, left: pos.left, opacity: progress }\n : { top: -9999, left: -9999, opacity: 0 },\n ]}\n >\n <Text\n style={{\n color: fg,\n fontSize: theme.fontSizeCaption,\n fontWeight: String(theme.fontWeightNormal) as TextStyle['fontWeight'],\n lineHeight: theme.fontSizeCaption * theme.lineHeightBody,\n textAlign: 'center',\n }}\n >\n {label}\n </Text>\n {arrowStyle && <View style={arrowStyle} />}\n </Animated.View>\n </View>\n </Modal>\n </>\n );\n};\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView, StyleSheet } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport interface ViewSwitcherProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /** Accessible label for the group. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Segmented control for switching between major views.\n *\n * Mirrors the Adwaita `AdwViewSwitcher` pattern. Place as a `HeaderBar`'s\n * `title` for the canonical GNOME layout. Compose with `ViewSwitcherItem`\n * for each option.\n *\n * The web version's pill background is `color-mix(in srgb,\n * var(--gnome-headerbar-bg-color) 75%, black 25%)` (70/30 in dark mode) —\n * RN has no `color-mix()`, but alpha-compositing a flat semi-transparent\n * black `View` over an opaque background produces the exact same math\n * (`background × (1 − alpha) + black × alpha`), so that's what's layered\n * here instead, matching `Card`'s established color-mix-avoidance pattern.\n * `useResolvedColorScheme()` picks the 25%/30% split to match the web\n * value exactly rather than reusing a nearby overlay token.\n *\n * Roving-tabindex ← → / Home / End keyboard navigation isn't ported —\n * same reasoning as `TabBar`: no per-app arrow-key convention exists in\n * RN's touch-first focus model to port it to.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ViewSwitcher.html\n * @see https://developer.gnome.org/hig/patterns/nav/view-switchers.html\n */\nexport const ViewSwitcher = forwardRef<View, ViewSwitcherProps>(function ViewSwitcher(\n { children, accessibilityLabel = 'View switcher', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"radiogroup\"\n accessibilityLabel={accessibilityLabel}\n style={[\n {\n alignSelf: 'flex-start',\n borderRadius: theme.radiusPill,\n overflow: 'hidden',\n backgroundColor: theme.headerbarBgColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <RNView\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n { backgroundColor: scheme === 'dark' ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.25)' },\n ]}\n />\n <RNView style={{ flexDirection: 'row', alignItems: 'center', gap: 2, padding: 3 }}>\n {children}\n </RNView>\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, TextStyle, View } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface ViewSwitcherItemProps\n extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Display label. */\n label: string;\n /**\n * Icon placed before the label. Rendered as-is — size/color it yourself.\n * Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`; this package\n * has no SVG icon system, so it's a plain `ReactNode` here, same as\n * `TabItem`'s `icon`.\n */\n icon?: ReactNode;\n /** Marks this item as the currently active view. */\n active?: boolean;\n disabled?: boolean;\n}\n\n/**\n * Individual option inside a `ViewSwitcher`.\n *\n * Renders with `accessibilityRole=\"radio\"` so the group reads as a proper\n * radio group. The pressed-state tint on non-active items\n * (`theme.activeOverlay`) isn't a stand-in approximation here — its light\n * (`rgba(0, 0, 0, 0.12)`) and dark (`rgba(255, 255, 255, 0.14)`) values\n * happen to match the web version's `:active` colors exactly, so it's\n * reused directly rather than hand-rolled.\n */\nexport const ViewSwitcherItem = forwardRef<View, ViewSwitcherItemProps>(function ViewSwitcherItem(\n { label, icon, active = false, disabled, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"radio\"\n accessibilityState={{ checked: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.space1,\n paddingVertical: 5,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusPill - 3,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: active\n ? theme.headerbarBgColor\n : pressed\n ? theme.activeOverlay\n : 'transparent',\n })}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0 }}>{icon}</RNView>}\n\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: theme.headerbarFgColor,\n }}\n >\n {label}\n </RNText>\n </Pressable>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/theme/tokens.generated.ts","../src/GnomeProvider/GnomeContext.ts","../src/theme/resolveTheme.ts","../src/GnomeProvider/resolveContext.ts","../src/GnomeProvider/GnomeProvider.tsx","../src/components/Text/Text.tsx","../src/components/ActionRow/ActionRow.tsx","../src/components/Icon/shared.ts","../src/components/Icon/Icon.tsx","../src/components/AnimatedIcon/AnimatedIcon.tsx","../src/components/Banner/Banner.tsx","../src/components/Separator/Separator.tsx","../src/components/BoxedList/BoxedList.tsx","../src/components/Button/Button.tsx","../src/components/Card/Card.tsx","../src/components/Checkbox/Checkbox.tsx","../src/components/Dialog/Dialog.tsx","../src/components/Dropdown/Dropdown.tsx","../src/components/HeaderBar/HeaderBar.tsx","../src/components/Link/Link.tsx","../src/components/PathBar/PathBar.tsx","../src/components/ProgressBar/ProgressBar.tsx","../src/components/RadioButton/RadioButton.tsx","../src/components/SearchBar/SearchBar.tsx","../src/components/Sidebar/filterUtils.ts","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/SidebarItem.tsx","../src/components/Sidebar/SidebarSection.tsx","../src/components/Skeleton/Skeleton.tsx","../src/components/Slider/Slider.tsx","../src/components/Spinner/Spinner.tsx","../src/components/Switch/Switch.tsx","../src/components/Tabs/TabBar.tsx","../src/components/Tabs/TabItem.tsx","../src/components/Tabs/TabPanel.tsx","../src/components/TextField/TextField.tsx","../src/components/Toast/Toast.tsx","../src/components/Toast/Toaster.tsx","../src/components/Tooltip/Tooltip.tsx","../src/components/ViewSwitcher/ViewSwitcher.tsx","../src/components/ViewSwitcher/ViewSwitcherItem.tsx"],"sourcesContent":["/**\n * AUTO-GENERATED — do not edit by hand.\n * Run `npm run theme:generate` (from packages/react-native) to regenerate\n * from @gnome-ui/core's `src/tokens.css`.\n */\n\nexport interface GnomeThemeTokens {\n readonly accentBgColor: string;\n readonly accentColor: string;\n readonly accentFgColor: string;\n readonly activeOverlay: string;\n readonly blockquoteBorderWidth: number;\n readonly blue1: string;\n readonly blue2: string;\n readonly blue3: string;\n readonly blue4: string;\n readonly blue5: string;\n readonly borderSubtle: string;\n readonly brown1: string;\n readonly brown2: string;\n readonly brown3: string;\n readonly brown4: string;\n readonly brown5: string;\n readonly cardBgColor: string;\n readonly cardFgColor: string;\n readonly cardShadeColor: string;\n readonly dark1: string;\n readonly dark2: string;\n readonly dark3: string;\n readonly dark4: string;\n readonly dark5: string;\n readonly destructiveBgColor: string;\n readonly destructiveColor: string;\n readonly destructiveFgColor: string;\n readonly dialogBackdropBlur: number;\n readonly dialogBackdropColor: string;\n readonly dialogBgColor: string;\n readonly dialogFgColor: string;\n readonly dividerColor: string;\n readonly durationFast: number;\n readonly durationNormal: number;\n readonly durationSlow: number;\n readonly easingDefault: readonly number[];\n readonly errorBgColor: string;\n readonly errorColor: string;\n readonly errorFgColor: string;\n readonly focusRingColor: string;\n readonly focusRingOffset: number;\n readonly focusRingWidth: number;\n readonly fontFamily: string;\n readonly fontFamilyMono: string;\n readonly fontSizeBody: number;\n readonly fontSizeCaption: number;\n readonly fontSizeLargeTitle: number;\n readonly fontSizeTitle1: number;\n readonly fontSizeTitle2: number;\n readonly fontSizeTitle3: number;\n readonly fontSizeTitle4: number;\n readonly fontWeightBold: number;\n readonly fontWeightNormal: number;\n readonly fontWeightSemibold: number;\n readonly green1: string;\n readonly green2: string;\n readonly green3: string;\n readonly green4: string;\n readonly green5: string;\n readonly headerbarBgColor: string;\n readonly headerbarBorderColor: string;\n readonly headerbarFgColor: string;\n readonly headerbarShadeColor: string;\n readonly hoverOverlay: string;\n readonly layoutBreakpointMedium: number;\n readonly layoutBreakpointNarrow: number;\n readonly layoutBreakpointWide: number;\n readonly layoutContentPadding: number;\n readonly layoutContentPaddingCompact: number;\n readonly layoutContentPaddingSpacious: number;\n readonly layoutSidebarDefaultWidth: number;\n readonly layoutSidebarMaxWidth: number;\n readonly layoutSidebarMinWidth: number;\n readonly layoutSidebarRailWidth: number;\n readonly light1: string;\n readonly light2: string;\n readonly light3: string;\n readonly light4: string;\n readonly light5: string;\n readonly lineHeightBody: number;\n readonly lineHeightHeading: number;\n readonly lineHeightTitle: number;\n readonly newBgColor: string;\n readonly newColor: string;\n readonly newFgColor: string;\n readonly opacityBorder: number;\n readonly opacityDim: number;\n readonly opacityDisabled: number;\n readonly orange1: string;\n readonly orange2: string;\n readonly orange3: string;\n readonly orange4: string;\n readonly orange5: string;\n readonly popoverBgColor: string;\n readonly popoverFgColor: string;\n readonly purple1: string;\n readonly purple2: string;\n readonly purple3: string;\n readonly purple4: string;\n readonly purple5: string;\n readonly radiusLg: number;\n readonly radiusMd: number;\n readonly radiusPill: number;\n readonly radiusSm: number;\n readonly radiusXl: number;\n readonly red1: string;\n readonly red2: string;\n readonly red3: string;\n readonly red4: string;\n readonly red5: string;\n readonly sidebarBgColor: string;\n readonly sidebarFgColor: string;\n readonly skeletonBaseColor: string;\n readonly skeletonHighlightColor: string;\n readonly space1: number;\n readonly space2: number;\n readonly space3: number;\n readonly space4: number;\n readonly space5: number;\n readonly space6: number;\n readonly successBgColor: string;\n readonly successColor: string;\n readonly successFgColor: string;\n readonly viewBgColor: string;\n readonly viewFgColor: string;\n readonly warningBgColor: string;\n readonly warningColor: string;\n readonly warningFgColor: string;\n readonly windowBgColor: string;\n readonly windowFgColor: string;\n readonly yellow1: string;\n readonly yellow2: string;\n readonly yellow3: string;\n readonly yellow4: string;\n readonly yellow5: string;\n}\n\nexport const lightTheme: GnomeThemeTokens = {\n accentBgColor: '#3584e4',\n accentColor: '#3584e4',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(0, 0, 0, 0.12)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(0, 0, 0, 0.15)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#fff',\n cardFgColor: 'rgba(0, 0, 0, 0.8)',\n cardShadeColor: 'rgba(0, 0, 0, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#e01b24',\n destructiveColor: '#e01b24',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.5)',\n dialogBgColor: '#fafafa',\n dialogFgColor: 'rgba(0, 0, 0, 0.8)',\n dividerColor: 'rgba(0, 0, 0, 0.07)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#e01b24',\n errorColor: '#e01b24',\n errorFgColor: '#fff',\n focusRingColor: '#3584e4',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#ebebeb',\n headerbarBorderColor: 'rgba(0, 0, 0, 0.12)',\n headerbarFgColor: 'rgba(0, 0, 0, 0.8)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.12)',\n hoverOverlay: 'rgba(0, 0, 0, 0.06)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#9141ac',\n newColor: '#9141ac',\n newFgColor: '#fff',\n opacityBorder: 0.15,\n opacityDim: 0.55,\n opacityDisabled: 0.5,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#fff',\n popoverFgColor: 'rgba(0, 0, 0, 0.8)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#ebebeb',\n sidebarFgColor: 'rgba(0, 0, 0, 0.8)',\n skeletonBaseColor: 'rgba(0, 0, 0, 0.09)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.55)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#2ec27e',\n successColor: '#2ec27e',\n successFgColor: '#fff',\n viewBgColor: '#fff',\n viewFgColor: 'rgba(0, 0, 0, 0.8)',\n warningBgColor: '#f6d32d',\n warningColor: '#e5a50a',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#fafafa',\n windowFgColor: 'rgba(0, 0, 0, 0.8)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const darkTheme: GnomeThemeTokens = {\n accentBgColor: '#3584e4',\n accentColor: '#62a0ea',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(255, 255, 255, 0.14)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(255, 255, 255, 0.15)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#383838',\n cardFgColor: 'rgba(255, 255, 255, 0.87)',\n cardShadeColor: 'rgba(255, 255, 255, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#e01b24',\n destructiveColor: '#e01b24',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.65)',\n dialogBgColor: '#242424',\n dialogFgColor: 'rgba(255, 255, 255, 0.87)',\n dividerColor: 'rgba(255, 255, 255, 0.07)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#e01b24',\n errorColor: '#e01b24',\n errorFgColor: '#fff',\n focusRingColor: '#62a0ea',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#303030',\n headerbarBorderColor: 'rgba(255, 255, 255, 0.1)',\n headerbarFgColor: 'rgba(255, 255, 255, 0.87)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.36)',\n hoverOverlay: 'rgba(255, 255, 255, 0.08)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#9141ac',\n newColor: '#9141ac',\n newFgColor: '#fff',\n opacityBorder: 0.15,\n opacityDim: 0.55,\n opacityDisabled: 0.5,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#383838',\n popoverFgColor: 'rgba(255, 255, 255, 0.87)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#303030',\n sidebarFgColor: 'rgba(255, 255, 255, 0.87)',\n skeletonBaseColor: 'rgba(255, 255, 255, 0.12)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.18)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#2ec27e',\n successColor: '#2ec27e',\n successFgColor: '#fff',\n viewBgColor: '#1e1e1e',\n viewFgColor: 'rgba(255, 255, 255, 0.87)',\n warningBgColor: '#f6d32d',\n warningColor: '#e5a50a',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#242424',\n windowFgColor: 'rgba(255, 255, 255, 0.87)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const highContrastTheme: GnomeThemeTokens = {\n accentBgColor: '#1a5fb4',\n accentColor: '#1a5fb4',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(0, 0, 0, 0.22)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(0, 0, 0, 0.5)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#fff',\n cardFgColor: 'rgba(0, 0, 0, 0.8)',\n cardShadeColor: 'rgba(0, 0, 0, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#a51d2d',\n destructiveColor: '#a51d2d',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.5)',\n dialogBgColor: '#fafafa',\n dialogFgColor: 'rgba(0, 0, 0, 0.8)',\n dividerColor: 'rgba(0, 0, 0, 0.2)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#a51d2d',\n errorColor: '#a51d2d',\n errorFgColor: '#fff',\n focusRingColor: '#1a5fb4',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#ebebeb',\n headerbarBorderColor: 'rgba(0, 0, 0, 0.12)',\n headerbarFgColor: 'rgba(0, 0, 0, 0.8)',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.12)',\n hoverOverlay: 'rgba(0, 0, 0, 0.12)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#613583',\n newColor: '#613583',\n newFgColor: '#fff',\n opacityBorder: 0.4,\n opacityDim: 0.7,\n opacityDisabled: 0.6,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#fff',\n popoverFgColor: 'rgba(0, 0, 0, 0.8)',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#ebebeb',\n sidebarFgColor: 'rgba(0, 0, 0, 0.8)',\n skeletonBaseColor: 'rgba(0, 0, 0, 0.09)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.55)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#26a269',\n successColor: '#26a269',\n successFgColor: '#fff',\n viewBgColor: '#fff',\n viewFgColor: 'rgba(0, 0, 0, 0.8)',\n warningBgColor: '#e66100',\n warningColor: '#c64600',\n warningFgColor: 'rgba(0, 0, 0, 0.8)',\n windowBgColor: '#fafafa',\n windowFgColor: 'rgba(0, 0, 0, 0.8)',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const highContrastDarkTheme: GnomeThemeTokens = {\n accentBgColor: '#62a0ea',\n accentColor: '#99c1f1',\n accentFgColor: '#fff',\n activeOverlay: 'rgba(255, 255, 255, 0.22)',\n blockquoteBorderWidth: 3,\n blue1: '#99c1f1',\n blue2: '#62a0ea',\n blue3: '#3584e4',\n blue4: '#1c71d8',\n blue5: '#1a5fb4',\n borderSubtle: 'rgba(255, 255, 255, 0.5)',\n brown1: '#cdab8f',\n brown2: '#b5835a',\n brown3: '#986a44',\n brown4: '#865e3c',\n brown5: '#63452c',\n cardBgColor: '#383838',\n cardFgColor: '#fff',\n cardShadeColor: 'rgba(255, 255, 255, 0.12)',\n dark1: '#77767b',\n dark2: '#5e5c64',\n dark3: '#3d3846',\n dark4: '#241f31',\n dark5: '#000',\n destructiveBgColor: '#ed333b',\n destructiveColor: '#f66151',\n destructiveFgColor: '#fff',\n dialogBackdropBlur: 4,\n dialogBackdropColor: 'rgba(0, 0, 0, 0.65)',\n dialogBgColor: '#242424',\n dialogFgColor: '#fff',\n dividerColor: 'rgba(255, 255, 255, 0.2)',\n durationFast: 100,\n durationNormal: 200,\n durationSlow: 400,\n easingDefault: [0.25, 0.46, 0.45, 0.94],\n errorBgColor: '#ed333b',\n errorColor: '#f66151',\n errorFgColor: '#fff',\n focusRingColor: '#99c1f1',\n focusRingOffset: 2,\n focusRingWidth: 3,\n fontFamily: 'Adwaita Sans',\n fontFamilyMono: 'Adwaita Mono',\n fontSizeBody: 16,\n fontSizeCaption: 12,\n fontSizeLargeTitle: 36,\n fontSizeTitle1: 30,\n fontSizeTitle2: 24,\n fontSizeTitle3: 20,\n fontSizeTitle4: 18,\n fontWeightBold: 700,\n fontWeightNormal: 400,\n fontWeightSemibold: 600,\n green1: '#8ff0a4',\n green2: '#57e389',\n green3: '#33d17a',\n green4: '#2ec27e',\n green5: '#26a269',\n headerbarBgColor: '#303030',\n headerbarBorderColor: 'rgba(255, 255, 255, 0.3)',\n headerbarFgColor: '#fff',\n headerbarShadeColor: 'rgba(0, 0, 0, 0.36)',\n hoverOverlay: 'rgba(255, 255, 255, 0.12)',\n layoutBreakpointMedium: 550,\n layoutBreakpointNarrow: 400,\n layoutBreakpointWide: 860,\n layoutContentPadding: 24,\n layoutContentPaddingCompact: 12,\n layoutContentPaddingSpacious: 36,\n layoutSidebarDefaultWidth: 240,\n layoutSidebarMaxWidth: 280,\n layoutSidebarMinWidth: 180,\n layoutSidebarRailWidth: 56,\n light1: '#fff',\n light2: '#f6f5f4',\n light3: '#deddda',\n light4: '#c0bfbc',\n light5: '#9a9996',\n lineHeightBody: 1.5,\n lineHeightHeading: 1.2,\n lineHeightTitle: 1.2,\n newBgColor: '#c061cb',\n newColor: '#dc8add',\n newFgColor: '#fff',\n opacityBorder: 0.4,\n opacityDim: 0.7,\n opacityDisabled: 0.6,\n orange1: '#ffbe6f',\n orange2: '#ffa348',\n orange3: '#ff7800',\n orange4: '#e66100',\n orange5: '#c64600',\n popoverBgColor: '#383838',\n popoverFgColor: '#fff',\n purple1: '#dc8add',\n purple2: '#c061cb',\n purple3: '#9141ac',\n purple4: '#813d9c',\n purple5: '#613583',\n radiusLg: 12,\n radiusMd: 8,\n radiusPill: 9999,\n radiusSm: 4,\n radiusXl: 15,\n red1: '#f66151',\n red2: '#ed333b',\n red3: '#e01b24',\n red4: '#c01c28',\n red5: '#a51d2d',\n sidebarBgColor: '#303030',\n sidebarFgColor: '#fff',\n skeletonBaseColor: 'rgba(255, 255, 255, 0.12)',\n skeletonHighlightColor: 'rgba(255, 255, 255, 0.18)',\n space1: 6,\n space2: 12,\n space3: 18,\n space4: 24,\n space5: 36,\n space6: 48,\n successBgColor: '#57e389',\n successColor: '#8ff0a4',\n successFgColor: '#fff',\n viewBgColor: '#1e1e1e',\n viewFgColor: '#fff',\n warningBgColor: '#f8e45c',\n warningColor: '#f9f06b',\n warningFgColor: 'rgba(0, 0, 0, 0.9)',\n windowBgColor: '#242424',\n windowFgColor: '#fff',\n yellow1: '#f9f06b',\n yellow2: '#f8e45c',\n yellow3: '#f6d32d',\n yellow4: '#f5c211',\n yellow5: '#e5a50a',\n} as const;\n\nexport const lightRawTokens = {\n '--gnome-accent-bg-color': '#3584e4',\n '--gnome-accent-color': '#3584e4',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(0 0 0 / 0.12)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(0 0 0 / 0.15)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#fff',\n '--gnome-card-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-card-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#e01b24',\n '--gnome-destructive-color': '#e01b24',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.5)',\n '--gnome-dialog-bg-color': '#fafafa',\n '--gnome-dialog-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-divider-color': 'rgb(0 0 0 / 0.07)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#e01b24',\n '--gnome-error-color': '#e01b24',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#3584e4',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#ebebeb',\n '--gnome-headerbar-border-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-headerbar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-hover-overlay': 'rgb(0 0 0 / 0.06)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#9141ac',\n '--gnome-new-color': '#9141ac',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.15',\n '--gnome-opacity-dim': '0.55',\n '--gnome-opacity-disabled': '0.5',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#fff',\n '--gnome-popover-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#ebebeb',\n '--gnome-sidebar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-skeleton-base-color': 'rgb(0 0 0 / 0.09)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.55)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#2ec27e',\n '--gnome-success-color': '#2ec27e',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#fff',\n '--gnome-view-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-warning-bg-color': '#f6d32d',\n '--gnome-warning-color': '#e5a50a',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#fafafa',\n '--gnome-window-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const darkRawTokens = {\n '--gnome-accent-bg-color': '#3584e4',\n '--gnome-accent-color': '#62a0ea',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(255 255 255 / 0.14)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(255 255 255 / 0.15)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#383838',\n '--gnome-card-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-card-shade-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#e01b24',\n '--gnome-destructive-color': '#e01b24',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.65)',\n '--gnome-dialog-bg-color': '#242424',\n '--gnome-dialog-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-divider-color': 'rgb(255 255 255 / 0.07)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#e01b24',\n '--gnome-error-color': '#e01b24',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#62a0ea',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#303030',\n '--gnome-headerbar-border-color': 'rgb(255 255 255 / 0.1)',\n '--gnome-headerbar-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.36)',\n '--gnome-hover-overlay': 'rgb(255 255 255 / 0.08)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#9141ac',\n '--gnome-new-color': '#9141ac',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.15',\n '--gnome-opacity-dim': '0.55',\n '--gnome-opacity-disabled': '0.5',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#383838',\n '--gnome-popover-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#303030',\n '--gnome-sidebar-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-skeleton-base-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.18)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#2ec27e',\n '--gnome-success-color': '#2ec27e',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#1e1e1e',\n '--gnome-view-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-warning-bg-color': '#f6d32d',\n '--gnome-warning-color': '#e5a50a',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#242424',\n '--gnome-window-fg-color': 'rgb(255 255 255 / 0.87)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const highContrastRawTokens = {\n '--gnome-accent-bg-color': '#1a5fb4',\n '--gnome-accent-color': '#1a5fb4',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(0 0 0 / 0.22)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(0 0 0 / 0.5)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#fff',\n '--gnome-card-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-card-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#a51d2d',\n '--gnome-destructive-color': '#a51d2d',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.5)',\n '--gnome-dialog-bg-color': '#fafafa',\n '--gnome-dialog-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-divider-color': 'rgb(0 0 0 / 0.2)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#a51d2d',\n '--gnome-error-color': '#a51d2d',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#1a5fb4',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#ebebeb',\n '--gnome-headerbar-border-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-headerbar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.12)',\n '--gnome-hover-overlay': 'rgb(0 0 0 / 0.12)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#613583',\n '--gnome-new-color': '#613583',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.4',\n '--gnome-opacity-dim': '0.7',\n '--gnome-opacity-disabled': '0.6',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#fff',\n '--gnome-popover-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#ebebeb',\n '--gnome-sidebar-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-skeleton-base-color': 'rgb(0 0 0 / 0.09)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.55)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#26a269',\n '--gnome-success-color': '#26a269',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#fff',\n '--gnome-view-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-warning-bg-color': '#e66100',\n '--gnome-warning-color': '#c64600',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-window-bg-color': '#fafafa',\n '--gnome-window-fg-color': 'rgb(0 0 0 / 0.8)',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n\nexport const highContrastDarkRawTokens = {\n '--gnome-accent-bg-color': '#62a0ea',\n '--gnome-accent-color': '#99c1f1',\n '--gnome-accent-fg-color': '#fff',\n '--gnome-active-overlay': 'rgb(255 255 255 / 0.22)',\n '--gnome-blockquote-border-width': '3px',\n '--gnome-blue-1': '#99c1f1',\n '--gnome-blue-2': '#62a0ea',\n '--gnome-blue-3': '#3584e4',\n '--gnome-blue-4': '#1c71d8',\n '--gnome-blue-5': '#1a5fb4',\n '--gnome-border-subtle': 'rgb(255 255 255 / 0.5)',\n '--gnome-brown-1': '#cdab8f',\n '--gnome-brown-2': '#b5835a',\n '--gnome-brown-3': '#986a44',\n '--gnome-brown-4': '#865e3c',\n '--gnome-brown-5': '#63452c',\n '--gnome-card-bg-color': '#383838',\n '--gnome-card-fg-color': '#fff',\n '--gnome-card-shade-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-dark-1': '#77767b',\n '--gnome-dark-2': '#5e5c64',\n '--gnome-dark-3': '#3d3846',\n '--gnome-dark-4': '#241f31',\n '--gnome-dark-5': '#000',\n '--gnome-destructive-bg-color': '#ed333b',\n '--gnome-destructive-color': '#f66151',\n '--gnome-destructive-fg-color': '#fff',\n '--gnome-dialog-backdrop-blur': '4px',\n '--gnome-dialog-backdrop-color': 'rgb(0 0 0 / 0.65)',\n '--gnome-dialog-bg-color': '#242424',\n '--gnome-dialog-fg-color': '#fff',\n '--gnome-divider-color': 'rgb(255 255 255 / 0.2)',\n '--gnome-duration-fast': '100ms',\n '--gnome-duration-normal': '200ms',\n '--gnome-duration-slow': '400ms',\n '--gnome-easing-default': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n '--gnome-error-bg-color': '#ed333b',\n '--gnome-error-color': '#f66151',\n '--gnome-error-fg-color': '#fff',\n '--gnome-focus-ring-color': '#99c1f1',\n '--gnome-focus-ring-offset': '2px',\n '--gnome-focus-ring-width': '3px',\n '--gnome-font-family': '\"Adwaita Sans\", cantarell, \"Inter\", system-ui, sans-serif',\n '--gnome-font-family-mono': '\"Adwaita Mono\", \"Source Code Pro\", monospace',\n '--gnome-font-size-body': '1rem',\n '--gnome-font-size-caption': '0.75rem',\n '--gnome-font-size-large-title': '2.25rem',\n '--gnome-font-size-title-1': '1.875rem',\n '--gnome-font-size-title-2': '1.5rem',\n '--gnome-font-size-title-3': '1.25rem',\n '--gnome-font-size-title-4': '1.125rem',\n '--gnome-font-weight-bold': '700',\n '--gnome-font-weight-normal': '400',\n '--gnome-font-weight-semibold': '600',\n '--gnome-green-1': '#8ff0a4',\n '--gnome-green-2': '#57e389',\n '--gnome-green-3': '#33d17a',\n '--gnome-green-4': '#2ec27e',\n '--gnome-green-5': '#26a269',\n '--gnome-headerbar-bg-color': '#303030',\n '--gnome-headerbar-border-color': 'rgb(255 255 255 / 0.3)',\n '--gnome-headerbar-fg-color': '#fff',\n '--gnome-headerbar-shade-color': 'rgb(0 0 0 / 0.36)',\n '--gnome-hover-overlay': 'rgb(255 255 255 / 0.12)',\n '--gnome-layout-breakpoint-medium': '550px',\n '--gnome-layout-breakpoint-narrow': '400px',\n '--gnome-layout-breakpoint-wide': '860px',\n '--gnome-layout-content-padding': '24px',\n '--gnome-layout-content-padding-compact': '12px',\n '--gnome-layout-content-padding-spacious': '36px',\n '--gnome-layout-sidebar-default-width': '240px',\n '--gnome-layout-sidebar-max-width': '280px',\n '--gnome-layout-sidebar-min-width': '180px',\n '--gnome-layout-sidebar-overlay-width': 'clamp( 180px, 75%, 280px )',\n '--gnome-layout-sidebar-rail-width': '56px',\n '--gnome-layout-sidebar-width': 'clamp( 180px, 25%, 280px )',\n '--gnome-light-1': '#fff',\n '--gnome-light-2': '#f6f5f4',\n '--gnome-light-3': '#deddda',\n '--gnome-light-4': '#c0bfbc',\n '--gnome-light-5': '#9a9996',\n '--gnome-line-height-body': '1.5',\n '--gnome-line-height-heading': '1.2',\n '--gnome-line-height-title': '1.2',\n '--gnome-new-bg-color': '#c061cb',\n '--gnome-new-color': '#dc8add',\n '--gnome-new-fg-color': '#fff',\n '--gnome-opacity-border': '0.4',\n '--gnome-opacity-dim': '0.7',\n '--gnome-opacity-disabled': '0.6',\n '--gnome-orange-1': '#ffbe6f',\n '--gnome-orange-2': '#ffa348',\n '--gnome-orange-3': '#ff7800',\n '--gnome-orange-4': '#e66100',\n '--gnome-orange-5': '#c64600',\n '--gnome-popover-bg-color': '#383838',\n '--gnome-popover-fg-color': '#fff',\n '--gnome-purple-1': '#dc8add',\n '--gnome-purple-2': '#c061cb',\n '--gnome-purple-3': '#9141ac',\n '--gnome-purple-4': '#813d9c',\n '--gnome-purple-5': '#613583',\n '--gnome-radius-lg': '12px',\n '--gnome-radius-md': '8px',\n '--gnome-radius-pill': '9999px',\n '--gnome-radius-sm': '4px',\n '--gnome-radius-xl': '15px',\n '--gnome-red-1': '#f66151',\n '--gnome-red-2': '#ed333b',\n '--gnome-red-3': '#e01b24',\n '--gnome-red-4': '#c01c28',\n '--gnome-red-5': '#a51d2d',\n '--gnome-shadow-lg':\n '0 3px 9px 1px rgb(0 0 0 / 0.1), 0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(28 31 31 / 0.9)',\n '--gnome-shadow-md': '0 2px 6px 2px rgb(0 0 0 / 0.2), 0 0 0 1px rgb(0 0 0 / 0.08)',\n '--gnome-shadow-sm': '0 1px 2px rgb(0 0 0 / 0.12)',\n '--gnome-sidebar-bg-color': '#303030',\n '--gnome-sidebar-fg-color': '#fff',\n '--gnome-skeleton-base-color': 'rgb(255 255 255 / 0.12)',\n '--gnome-skeleton-highlight-color': 'rgb(255 255 255 / 0.18)',\n '--gnome-space-1': '6px',\n '--gnome-space-2': '12px',\n '--gnome-space-3': '18px',\n '--gnome-space-4': '24px',\n '--gnome-space-5': '36px',\n '--gnome-space-6': '48px',\n '--gnome-success-bg-color': '#57e389',\n '--gnome-success-color': '#8ff0a4',\n '--gnome-success-fg-color': '#fff',\n '--gnome-view-bg-color': '#1e1e1e',\n '--gnome-view-fg-color': '#fff',\n '--gnome-warning-bg-color': '#f8e45c',\n '--gnome-warning-color': '#f9f06b',\n '--gnome-warning-fg-color': 'rgb(0 0 0 / 0.9)',\n '--gnome-window-bg-color': '#242424',\n '--gnome-window-fg-color': '#fff',\n '--gnome-yellow-1': '#f9f06b',\n '--gnome-yellow-2': '#f8e45c',\n '--gnome-yellow-3': '#f6d32d',\n '--gnome-yellow-4': '#f5c211',\n '--gnome-yellow-5': '#e5a50a',\n} as const;\n","import { createContext, useContext, useMemo } from 'react';\nimport type { GnomeResolvedColorScheme, GnomeResolvedContrast } from '@/theme/resolveTheme';\nimport type { GnomeThemeTokens } from '@/theme/tokens.generated';\nimport { lightTheme } from '@/theme/tokens.generated';\nimport type { GnomeAccentColor, GnomeColorScheme, GnomeContrast, GnomeDir } from './resolveContext';\n\nexport interface GnomeContextValue {\n locale: string | undefined;\n dir: GnomeDir;\n numberFormat: Intl.NumberFormatOptions | undefined;\n dateTimeFormat: Intl.DateTimeFormatOptions | undefined;\n colorScheme: GnomeColorScheme;\n resolvedColorScheme: GnomeResolvedColorScheme;\n contrast: GnomeContrast;\n resolvedContrast: GnomeResolvedContrast;\n accentColor: GnomeAccentColor;\n theme: GnomeThemeTokens;\n}\n\nexport const GnomeContext = createContext<GnomeContextValue>({\n locale: undefined,\n dir: 'ltr',\n numberFormat: undefined,\n dateTimeFormat: undefined,\n colorScheme: 'system',\n resolvedColorScheme: 'light',\n contrast: 'system',\n resolvedContrast: 'normal',\n accentColor: 'blue',\n theme: lightTheme,\n});\n\n/** Returns the locale set by the nearest `GnomeProvider`, or `undefined` to use the device locale. */\nexport function useLocale(): string | undefined {\n return useContext(GnomeContext).locale;\n}\n\n/** Returns the text direction set by the nearest `GnomeProvider`. Defaults to the app's `I18nManager.isRTL` state. */\nexport function useDir(): GnomeDir {\n return useContext(GnomeContext).dir;\n}\n\n/** Returns an `Intl.NumberFormat` configured from `GnomeProvider` defaults plus local overrides. */\nexport function useNumberFormatter(options?: Intl.NumberFormatOptions): Intl.NumberFormat {\n const { locale, numberFormat } = useContext(GnomeContext);\n\n return useMemo(\n () => new Intl.NumberFormat(locale, { ...numberFormat, ...options }),\n [locale, numberFormat, options],\n );\n}\n\n/** Returns an `Intl.DateTimeFormat` configured from `GnomeProvider` defaults plus local overrides. */\nexport function useDateTimeFormatter(options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const { locale, dateTimeFormat } = useContext(GnomeContext);\n\n return useMemo(\n () => new Intl.DateTimeFormat(locale, { ...dateTimeFormat, ...options }),\n [locale, dateTimeFormat, options],\n );\n}\n\n/** Returns the color scheme preference set by the nearest `GnomeProvider`. Defaults to `\"system\"`. */\nexport function useColorScheme(): GnomeColorScheme {\n return useContext(GnomeContext).colorScheme;\n}\n\n/** Returns the resolved color scheme (`\"light\"` or `\"dark\"`), accounting for the OS preference when `colorScheme` is `\"system\"`. */\nexport function useResolvedColorScheme(): GnomeResolvedColorScheme {\n return useContext(GnomeContext).resolvedColorScheme;\n}\n\n/** Returns the contrast preference set by the nearest `GnomeProvider`. Defaults to `\"system\"`. */\nexport function useContrast(): GnomeContrast {\n return useContext(GnomeContext).contrast;\n}\n\n/** Returns the resolved contrast (`\"normal\"` or `\"more\"`), accounting for the OS accessibility setting when `contrast` is `\"system\"`. */\nexport function useResolvedContrast(): GnomeResolvedContrast {\n return useContext(GnomeContext).resolvedContrast;\n}\n\n/** Returns the accent color set by the nearest `GnomeProvider`. Defaults to `\"blue\"`. */\nexport function useAccentColor(): GnomeAccentColor {\n return useContext(GnomeContext).accentColor;\n}\n\n/** Returns the fully-resolved theme tokens (colors, spacing, typography, …) for the nearest `GnomeProvider`, accent-adjusted. */\nexport function useGnomeTheme(): GnomeThemeTokens {\n return useContext(GnomeContext).theme;\n}\n","import type { GnomeThemeTokens } from './tokens.generated';\nimport {\n darkTheme,\n highContrastDarkTheme,\n highContrastTheme,\n lightTheme,\n} from './tokens.generated';\n\nexport type GnomeResolvedColorScheme = 'light' | 'dark';\nexport type GnomeResolvedContrast = 'normal' | 'more';\n\nexport interface ResolveGnomeThemeOptions {\n colorScheme: GnomeResolvedColorScheme;\n /** @default 'normal' */\n contrast?: GnomeResolvedContrast;\n}\n\nexport function resolveGnomeTheme({\n colorScheme,\n contrast = 'normal',\n}: ResolveGnomeThemeOptions): GnomeThemeTokens {\n if (contrast === 'more') {\n return colorScheme === 'dark' ? highContrastDarkTheme : highContrastTheme;\n }\n\n return colorScheme === 'dark' ? darkTheme : lightTheme;\n}\n","import type { GnomeResolvedColorScheme, GnomeResolvedContrast } from '@/theme/resolveTheme';\nimport type { GnomeThemeTokens } from '@/theme/tokens.generated';\n\nexport type GnomeColorScheme = GnomeResolvedColorScheme | 'system';\nexport type GnomeContrast = GnomeResolvedContrast | 'system';\nexport type GnomeDir = 'ltr' | 'rtl';\nexport type GnomeNamedAccentColor =\n | 'blue'\n | 'green'\n | 'yellow'\n | 'orange'\n | 'red'\n | 'purple'\n | 'brown';\nexport type GnomeAccentColor = GnomeNamedAccentColor | (string & {});\n\nexport const NAMED_ACCENT_COLORS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\n/**\n * Resolves a `'light' | 'dark' | 'system'` preference against the OS color\n * scheme. `systemColorScheme` is typed loosely (rather than as\n * `GnomeResolvedColorScheme`) so RN's `useColorScheme()` — which can also\n * report `'unspecified'` on Android, besides `null`/`undefined` — can be\n * passed straight through; anything other than `'dark'` resolves to light.\n */\nexport function resolveColorScheme(\n preference: GnomeColorScheme,\n systemColorScheme: string | null | undefined,\n): GnomeResolvedColorScheme {\n if (preference !== 'system') {\n return preference;\n }\n\n return systemColorScheme === 'dark' ? 'dark' : 'light';\n}\n\n/** Resolves a `'normal' | 'more' | 'system'` preference against the OS high-contrast setting. */\nexport function resolveContrast(\n preference: GnomeContrast,\n systemHighContrast: boolean,\n): GnomeResolvedContrast {\n if (preference !== 'system') {\n return preference;\n }\n\n return systemHighContrast ? 'more' : 'normal';\n}\n\n/**\n * Returns `theme` with `accentColor`/`accentBgColor` (and, outside\n * high-contrast, `focusRingColor`) overridden for a non-default accent.\n *\n * Named palette colors (`\"green\"`, `\"red\"`, …) resolve to the matching\n * Adwaita shade for the current color scheme, mirroring\n * `@gnome-ui/react`'s `GnomeProvider`. High-contrast variants keep their\n * own fixed, maximum-contrast focus ring regardless of accent — the same\n * behavior `tokens.css` encodes by not deriving it from `--gnome-accent-color`\n * under `prefers-contrast: more`.\n */\nexport function applyAccentColor(\n theme: GnomeThemeTokens,\n accentColor: GnomeAccentColor,\n resolvedColorScheme: GnomeResolvedColorScheme,\n resolvedContrast: GnomeResolvedContrast,\n): GnomeThemeTokens {\n if (accentColor === 'blue') {\n return theme;\n }\n\n const isNamed = NAMED_ACCENT_COLORS.has(accentColor as GnomeNamedAccentColor);\n const shade = resolvedColorScheme === 'dark' ? 2 : 3;\n const accent = isNamed\n ? (theme[`${accentColor}${shade}` as keyof GnomeThemeTokens] as string)\n : accentColor;\n const accentBg = isNamed\n ? (theme[`${accentColor}3` as keyof GnomeThemeTokens] as string)\n : accentColor;\n\n return {\n ...theme,\n accentColor: accent,\n accentBgColor: accentBg,\n ...(resolvedContrast === 'normal' ? { focusRingColor: accent } : {}),\n };\n}\n","import type { ReactNode } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n AccessibilityInfo,\n I18nManager,\n Platform,\n useColorScheme as useSystemColorScheme,\n} from 'react-native';\nimport { resolveGnomeTheme } from '@/theme/resolveTheme';\nimport { GnomeContext } from './GnomeContext';\nimport type { GnomeAccentColor, GnomeColorScheme, GnomeContrast, GnomeDir } from './resolveContext';\nimport { applyAccentColor, resolveColorScheme, resolveContrast } from './resolveContext';\n\nexport interface GnomeProviderProps {\n /** BCP 47 locale tag (e.g. `\"es-ES\"`, `\"de-DE\"`). When omitted, components fall back to the device locale. */\n locale?: string;\n /**\n * Text direction exposed via context for consumers to branch on (e.g.\n * mirroring icons or flipping a row's layout). Defaults to the app's\n * actual `I18nManager.isRTL` state.\n *\n * Unlike the web `GnomeProvider`, this does **not** call\n * `I18nManager.forceRTL()` — RN's layout direction is a single global\n * flag that requires an app reload to take effect and is normally set\n * once at app bootstrap, not scoped per provider tree.\n */\n dir?: GnomeDir;\n /**\n * Global defaults for number formatting.\n *\n * Use `{ notation: \"compact\", compactDisplay: \"short\" }` for compact\n * values such as `1K`; omit it or set `{ notation: \"standard\" }` for\n * full values such as `1,000`.\n */\n numberFormat?: Intl.NumberFormatOptions;\n /** Global defaults for date/time formatting. */\n dateTimeFormat?: Intl.DateTimeFormatOptions;\n /**\n * Color scheme preference. `\"system\"` (default) follows\n * `Appearance`/`useColorScheme()`. `\"light\"`/`\"dark\"` force that scheme\n * regardless of the OS setting.\n * @default 'system'\n */\n colorScheme?: GnomeColorScheme;\n /**\n * High-contrast preference. `\"system\"` (default) follows the OS\n * accessibility setting where one exists — Android's \"High text\n * contrast\" (`AccessibilityInfo.isHighTextContrastEnabled`) or iOS's\n * \"Increase Contrast\" (`AccessibilityInfo.isDarkerSystemColorsEnabled`)\n * — and falls back to `\"normal\"` where neither is available (e.g. web).\n * @default 'system'\n */\n contrast?: GnomeContrast;\n /**\n * Accent color. Accepts a named GNOME palette color (`\"blue\"`, `\"green\"`,\n * `\"yellow\"`, `\"orange\"`, `\"red\"`, `\"purple\"`, `\"brown\"`) or any RN color\n * string (e.g. `\"#ff0000\"`, `\"rgba(0, 0, 0, 0.5)\"`). Named colors are\n * theme-aware and use the correct shade for light/dark mode\n * automatically. Defaults to `\"blue\"`.\n */\n accentColor?: GnomeAccentColor;\n children: ReactNode;\n}\n\n/**\n * Subscribes to the OS high-contrast accessibility setting.\n *\n * Android exposes \"High text contrast\"; iOS exposes \"Increase Contrast\"\n * (surfaced through `AccessibilityInfo`'s \"darker system colors\" API,\n * which is what that setting maps to natively). Neither exists on other\n * platforms, so this resolves to `false` there.\n */\nfunction useSystemHighContrast(): boolean {\n const [enabled, setEnabled] = useState(false);\n\n useEffect(() => {\n const query =\n Platform.OS === 'android'\n ? AccessibilityInfo.isHighTextContrastEnabled\n : Platform.OS === 'ios'\n ? AccessibilityInfo.isDarkerSystemColorsEnabled\n : undefined;\n\n if (!query) {\n return;\n }\n\n let mounted = true;\n\n (async () => {\n const value = await query();\n\n if (mounted) {\n setEnabled(value);\n }\n })();\n\n const eventName =\n Platform.OS === 'android' ? 'highTextContrastChanged' : 'darkerSystemColorsChanged';\n const subscription = AccessibilityInfo.addEventListener(eventName, setEnabled);\n\n return () => {\n mounted = false;\n subscription.remove();\n };\n }, []);\n\n return enabled;\n}\n\n/**\n * Returns `true` when the OS \"Reduce Motion\" accessibility setting is on\n * (iOS Settings > Accessibility > Motion, Android Settings >\n * Accessibility > Remove animations), for components with a continuously\n * looping `Animated` value (e.g. `Spinner`) to slow down or skip that\n * animation. Unlike `contrast`/`colorScheme`, the web `GnomeProvider` has\n * no corresponding override prop — `prefers-reduced-motion` is a pure CSS\n * media query there, always OS-driven — so this hook mirrors that: it\n * reads `AccessibilityInfo` directly and isn't scoped to `GnomeProvider`'s\n * context, unlike every other hook in this package. `isReduceMotionEnabled`\n * / `reduceMotionChanged` are supported on both iOS and Android (unlike\n * the high-contrast APIs above, which are platform-specific), so no\n * `Platform.OS` branch is needed.\n */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useReducedMotion(): boolean {\n const [enabled, setEnabled] = useState(false);\n\n useEffect(() => {\n let mounted = true;\n\n (async () => {\n const value = await AccessibilityInfo.isReduceMotionEnabled();\n\n if (mounted) {\n setEnabled(value);\n }\n })();\n\n const subscription = AccessibilityInfo.addEventListener('reduceMotionChanged', setEnabled);\n\n return () => {\n mounted = false;\n subscription.remove();\n };\n }, []);\n\n return enabled;\n}\n\n/** Provides locale, text direction, color scheme, contrast, accent color, and resolved theme tokens to all descendant gnome-ui components. */\nexport const GnomeProvider = ({\n locale,\n dir,\n numberFormat,\n dateTimeFormat,\n colorScheme = 'system',\n contrast = 'system',\n accentColor = 'blue',\n children,\n}: GnomeProviderProps) => {\n const systemColorScheme = useSystemColorScheme();\n const systemHighContrast = useSystemHighContrast();\n\n const resolvedColorScheme = resolveColorScheme(colorScheme, systemColorScheme);\n const resolvedContrast = resolveContrast(contrast, systemHighContrast);\n const resolvedDir = dir ?? (I18nManager.isRTL ? 'rtl' : 'ltr');\n\n const value = useMemo(() => {\n const variantTheme = resolveGnomeTheme({\n colorScheme: resolvedColorScheme,\n contrast: resolvedContrast,\n });\n const theme = applyAccentColor(\n variantTheme,\n accentColor,\n resolvedColorScheme,\n resolvedContrast,\n );\n\n return {\n locale,\n dir: resolvedDir,\n numberFormat,\n dateTimeFormat,\n colorScheme,\n resolvedColorScheme,\n contrast,\n resolvedContrast,\n accentColor,\n theme,\n };\n }, [\n locale,\n resolvedDir,\n numberFormat,\n dateTimeFormat,\n colorScheme,\n resolvedColorScheme,\n contrast,\n resolvedContrast,\n accentColor,\n ]);\n\n return <GnomeContext.Provider value={value}>{children}</GnomeContext.Provider>;\n};\n","import { forwardRef } from 'react';\nimport type { AccessibilityRole, TextProps as RNTextProps, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type TextVariant =\n | 'large-title'\n | 'title-1'\n | 'title-2'\n | 'title-3'\n | 'title-4'\n | 'heading'\n | 'body'\n | 'document'\n | 'caption'\n | 'caption-heading'\n | 'monospace'\n | 'numeric';\n\nexport type TextColor =\n | 'default'\n | 'dim'\n | 'accent'\n | 'destructive'\n | 'success'\n | 'warning'\n | 'error';\n\n/**\n * Variants the web component renders as `<h1>`–`<h4>`. RN has no heading\n * elements, so they default to the `header` accessibility role instead —\n * the closest native equivalent, and what VoiceOver/TalkBack use to build\n * their heading rotor.\n */\nconst HEADING_VARIANTS: ReadonlySet<TextVariant> = new Set<TextVariant>([\n 'large-title',\n 'title-1',\n 'title-2',\n 'title-3',\n 'title-4',\n 'heading',\n]);\n\nexport interface TextProps extends RNTextProps {\n /** Typography style. Mirrors Adwaita / GNOME HIG text styles. */\n variant?: TextVariant;\n /** Semantic color. */\n color?: TextColor;\n children?: RNTextProps['children'];\n}\n\n/**\n * CSS `line-height` ratios and `letter-spacing` `em` values are relative;\n * RN wants absolute dp for both, so they're resolved against the variant's\n * own font size here.\n */\nfunction getVariantStyle(theme: GnomeThemeTokens, variant: TextVariant): TextStyle {\n const weight = (value: number) => String(value) as TextStyle['fontWeight'];\n\n switch (variant) {\n case 'large-title':\n return {\n fontSize: theme.fontSizeLargeTitle,\n fontWeight: weight(300),\n lineHeight: Math.round(theme.fontSizeLargeTitle * theme.lineHeightHeading),\n letterSpacing: theme.fontSizeLargeTitle * -0.02,\n };\n case 'title-1':\n return {\n fontSize: theme.fontSizeTitle1,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle1 * theme.lineHeightHeading),\n };\n case 'title-2':\n return {\n fontSize: theme.fontSizeTitle2,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle2 * theme.lineHeightHeading),\n };\n case 'title-3':\n return {\n fontSize: theme.fontSizeTitle3,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeTitle3 * theme.lineHeightHeading),\n };\n case 'title-4':\n return {\n fontSize: theme.fontSizeTitle4,\n fontWeight: weight(theme.fontWeightSemibold),\n lineHeight: Math.round(theme.fontSizeTitle4 * theme.lineHeightHeading),\n };\n case 'heading':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightBold),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightHeading),\n };\n case 'document':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * 1.65),\n };\n case 'caption':\n return {\n fontSize: theme.fontSizeCaption,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeCaption * theme.lineHeightBody),\n };\n case 'caption-heading':\n return {\n fontSize: theme.fontSizeCaption,\n fontWeight: weight(theme.fontWeightSemibold),\n lineHeight: Math.round(theme.fontSizeCaption * theme.lineHeightHeading),\n letterSpacing: theme.fontSizeCaption * 0.06,\n textTransform: 'uppercase',\n };\n case 'monospace':\n return {\n fontFamily: theme.fontFamilyMono,\n fontSize: 14,\n lineHeight: Math.round(14 * theme.lineHeightBody),\n };\n case 'numeric':\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n fontVariant: ['tabular-nums'],\n };\n default:\n return {\n fontSize: theme.fontSizeBody,\n fontWeight: weight(theme.fontWeightNormal),\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n };\n }\n}\n\n/**\n * `dim` is an opacity in the web stylesheet rather than a color, so it stays\n * an opacity here — that keeps it correct against any background, the same\n * way `.color-dim` does.\n */\nfunction getColorStyle(theme: GnomeThemeTokens, color: TextColor): TextStyle {\n switch (color) {\n case 'dim':\n return { color: theme.windowFgColor, opacity: theme.opacityDim };\n case 'accent':\n return { color: theme.accentColor };\n case 'destructive':\n return { color: theme.destructiveColor };\n case 'success':\n return { color: theme.successColor };\n case 'warning':\n return { color: theme.warningColor };\n case 'error':\n return { color: theme.errorColor };\n default:\n return { color: theme.windowFgColor };\n }\n}\n\n/**\n * Text component following GNOME Human Interface Guidelines typography styles.\n *\n * Variants map directly to Adwaita style classes:\n * `large-title`, `title-1`–`title-4`, `heading`, `body`, `document`,\n * `caption`, `caption-heading`, `monospace`, `numeric`.\n *\n * Rebuilt on RN's `Text` rather than ported from `@gnome-ui/react`'s DOM-based\n * JSX: there is no element to pick, so `@gnome-ui/react`'s `as` prop is\n * replaced by `accessibilityRole`, which the heading variants default to\n * `\"header\"`.\n *\n * @see https://developer.gnome.org/hig/guidelines/typography.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n */\nexport const Text = forwardRef<RNText, TextProps>(function Text(\n { variant = 'body', color = 'default', style, children, accessibilityRole, ...textProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const role: AccessibilityRole | undefined =\n accessibilityRole ?? (HEADING_VARIANTS.has(variant) ? 'header' : undefined);\n\n return (\n <RNText\n ref={ref}\n accessibilityRole={role}\n style={[\n { fontFamily: theme.fontFamily },\n getVariantStyle(theme, variant),\n getColorStyle(theme, color),\n style,\n ]}\n {...textProps}\n >\n {children}\n </RNText>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView, StyleSheet } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type ActionRowVariant = 'default' | 'property';\n\nexport interface ActionRowProps extends Omit<PressableProps, 'children' | 'style'> {\n /** Primary label. */\n title: string;\n /** Secondary line below the title. */\n subtitle?: string;\n /** Icon or image placed at the leading edge. Rendered as-is — size/color it yourself. */\n leading?: ReactNode;\n /**\n * Widget placed at the trailing edge (`Switch`, `Button`, `Text`…).\n * For interactive end widgets prefer a controlled component and stop\n * event propagation inside it so the row's own `onPress` isn't triggered.\n */\n trailing?: ReactNode;\n /**\n * When true the entire row becomes pressable (renders as `Pressable`\n * with `accessibilityRole=\"button\"`). Use for rows that navigate or\n * trigger an action.\n */\n interactive?: boolean;\n /**\n * `\"property\"` flips the visual hierarchy: the subtitle becomes the\n * prominent value and the title shrinks to a dim label above it.\n * Use for read-only property display (e.g. \"OS Version / GNOME 50\").\n * Mirrors the `.property` style class.\n */\n variant?: ActionRowVariant;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Standard settings row with title, optional subtitle, and end widget.\n *\n * Mirrors the Adwaita `AdwActionRow` pattern — the fundamental building\n * block inside a `BoxedList`.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s `<button>`/`<div>` — same `interactive` split as\n * `Card`: a pressed-state overlay tinted by `theme.activeOverlay` stands in\n * for the web's `:hover`/`:active` `background-color` transitions, since RN\n * has no hover state on touch devices and no `color-mix()`. `title`/\n * `subtitle` reuse the library's own `Text` component (`variant=\"body\"`/\n * `\"caption\"`, `color=\"dim\"`) instead of hand-rolled styles, with\n * `numberOfLines={1}` standing in for the web's CSS\n * `text-overflow: ellipsis` truncation.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ActionRow.html\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const ActionRow = forwardRef<View, ActionRowProps>(function ActionRow(\n {\n title,\n subtitle,\n leading,\n trailing,\n interactive = false,\n variant = 'default',\n style,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const property = variant === 'property';\n\n const baseStyle: ViewStyle = {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: theme.space2,\n paddingHorizontal: theme.space4,\n minHeight: 52,\n width: '100%',\n };\n\n const content = (\n <>\n {leading && <RNView style={{ flexShrink: 0 }}>{leading}</RNView>}\n\n <RNView style={{ flex: 1, gap: 2 }}>\n <Text\n variant={property ? 'caption' : 'body'}\n color={property ? 'dim' : 'default'}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {title}\n </Text>\n {subtitle && (\n <Text\n variant={property ? 'body' : 'caption'}\n color={property ? 'default' : 'dim'}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {subtitle}\n </Text>\n )}\n </RNView>\n\n {trailing && (\n <RNView\n style={{ flexShrink: 0, flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}\n >\n {trailing}\n </RNView>\n )}\n </>\n );\n\n if (!interactive) {\n return (\n <RNView ref={ref} style={[baseStyle, style]} {...pressableProps}>\n {content}\n </RNView>\n );\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={[\n baseStyle,\n { position: 'relative', opacity: disabled ? theme.opacityDisabled : 1 },\n style,\n ]}\n {...pressableProps}\n >\n {({ pressed }) => (\n <>\n {content}\n {pressed && !disabled ? (\n <RNView\n pointerEvents=\"none\"\n style={[StyleSheet.absoluteFill, { backgroundColor: theme.activeOverlay }]}\n />\n ) : null}\n </>\n )}\n </Pressable>\n );\n});\n","import type { useGnomeTheme } from '@/GnomeProvider';\nimport type { IconColor, IconSize } from './Icon';\n\n/**\n * Non-component helpers shared between `Icon` and `AnimatedIcon` — kept in\n * their own module (not exported from `Icon.tsx` itself) so both files stay\n * component-only for Fast Refresh, per the project's `react-refresh/\n * only-export-components` lint rule.\n */\n\nexport const ICON_SIZE_MAP: Record<IconSize, number> = { sm: 12, md: 16, lg: 20 };\n\nexport function resolveIconColor(\n theme: ReturnType<typeof useGnomeTheme>,\n color: IconColor | undefined,\n) {\n switch (color) {\n case 'blue':\n return theme.blue3;\n case 'green':\n return theme.green4;\n case 'yellow':\n return theme.yellow4;\n case 'orange':\n return theme.orange3;\n case 'red':\n return theme.red3;\n case 'purple':\n return theme.purple3;\n case 'brown':\n return theme.brown3;\n default:\n return theme.windowFgColor;\n }\n}\n\nexport function iconAccessibilityProps(label: string | undefined) {\n return label\n ? { accessible: true as const, accessibilityLabel: label, accessibilityRole: 'image' as const }\n : { accessible: false as const, accessibilityRole: 'none' as const };\n}\n","import type { AnyIconDefinition, IconDefinition } from '@gnome-ui/icons';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { Path, Svg, SvgXml } from 'react-native-svg';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { ICON_SIZE_MAP, iconAccessibilityProps, resolveIconColor } from './shared';\n\nexport type IconSize = 'sm' | 'md' | 'lg';\n\n/** Named GNOME palette color for the icon. `\"default\"` (or omitting the prop) resolves to the theme's default foreground color. */\nexport type IconColor =\n | 'default'\n | 'blue'\n | 'green'\n | 'yellow'\n | 'orange'\n | 'red'\n | 'purple'\n | 'brown';\n\nexport interface IconProps {\n /** Icon from `@gnome-ui/icons`, a `simple-icons` icon, or a raw `{ path }` object. */\n icon: AnyIconDefinition;\n /**\n * Rendered size.\n * - `sm` — 12 px\n * - `md` — 16 px (default)\n * - `lg` — 20 px\n *\n * Override with `width`/`height` for non-standard sizes.\n */\n size?: IconSize;\n width?: number;\n height?: number;\n /** Accessible label. Omit for decorative icons — they are hidden from screen readers. */\n label?: string;\n /**\n * Named GNOME palette color. Omit (or pass `\"default\"`) to use the\n * theme's default foreground color — RN has no `currentColor`\n * equivalent to inherit from a parent, unlike the web version.\n */\n color?: IconColor;\n /** Forwarded to the underlying `Svg` — useful for a `transform` (e.g. a rotated disclosure chevron) or `margin`. */\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * `icon.paths` present → `IconDefinition` with structured path data.\n * `icon.svg` present (and no `paths`) → `IconDefinition` carrying raw markup\n * (the `animated` icons — see `AnimatedIcon`).\n * Neither → `RawPathIconDefinition` (e.g. a `simple-icons` `SimpleIcon`,\n * which has its own unrelated `svg` field alongside `path` — checking\n * `path` is absent, not just that `svg` is a string, is what keeps those\n * correctly classified below instead of misread as an internal\n * `IconDefinition`). Duplicated from `@gnome-ui/react`'s `Icon.tsx` rather\n * than shared — see that component for the full reasoning.\n */\nfunction isIconDefinition(icon: AnyIconDefinition): icon is IconDefinition {\n if ('paths' in icon && Array.isArray((icon as IconDefinition).paths)) {\n return true;\n }\n\n return typeof (icon as IconDefinition).svg === 'string' && !('path' in icon);\n}\n\n/** `react-native-svg`'s `FillRule` has no `\"inherit\"` member (unlike `IconPath`'s, kept for CSS-source-of-truth completeness) — a leaf `<path>` has nothing to inherit from, so it maps to the SVG default (omitted attribute). */\nfunction fillRule(rule: 'nonzero' | 'evenodd' | 'inherit' | undefined) {\n return rule === 'nonzero' || rule === 'evenodd' ? rule : undefined;\n}\n\n/**\n * Renders an icon as an inline SVG, via `react-native-svg`.\n *\n * Accepts icons from `@gnome-ui/icons`, any `simple-icons` icon, or a plain\n * `{ path }` object — same `AnyIconDefinition` union as `@gnome-ui/react`'s\n * `Icon`. Pass `label` only when the icon conveys meaning on its own.\n *\n * `animated` icons (`Syncing`, `Recording`, …) carry raw `svg` markup\n * instead of `paths` — rendered here through `SvgXml`, which parses the\n * structural elements (`<g>`/`<path>`/`<circle>`) but has no CSS engine, so\n * the embedded `<style>`/`@keyframes` block is silently dropped and the\n * shapes render at their authored rest position. That happens to be exactly\n * the desired \"inert, static frame\" behavior for a plain `<Icon>` — no\n * special-casing needed here; wrap in `<AnimatedIcon>` to actually play the\n * motion (RN has to hand-build that with `Animated`, since there is no CSS\n * animation engine to interpret the markup's keyframes).\n *\n * @example\n * import { Search } from \"@gnome-ui/icons\";\n * <Icon icon={Search} label=\"Search\" />\n *\n * @example\n * import { siGithub } from \"simple-icons\";\n * <Icon icon={siGithub} label=\"GitHub\" />\n */\nexport const Icon = ({ icon, size = 'md', width, height, label, color, style }: IconProps) => {\n const theme = useGnomeTheme();\n const px = ICON_SIZE_MAP[size];\n const fill = resolveIconColor(theme, color);\n\n const resolvedViewBox = isIconDefinition(icon) ? icon.viewBox : (icon.viewBox ?? '0 0 24 24');\n const rawSvg = isIconDefinition(icon) ? icon.svg : undefined;\n const paths = isIconDefinition(icon)\n ? icon.svg\n ? undefined\n : icon.paths?.map((p, i) => (\n <Path\n key={i}\n d={p.d}\n fillRule={fillRule(p.fillRule)}\n clipRule={fillRule(p.clipRule)}\n transform={p.transform}\n />\n ))\n : [<Path key={0} d={icon.path} />];\n\n const accessibilityProps = iconAccessibilityProps(label);\n\n if (rawSvg) {\n return (\n <SvgXml\n xml={`<svg viewBox=\"${resolvedViewBox}\">${rawSvg}</svg>`}\n width={width ?? px}\n height={height ?? px}\n fill={fill}\n style={style}\n {...accessibilityProps}\n />\n );\n }\n\n return (\n <Svg\n viewBox={resolvedViewBox}\n width={width ?? px}\n height={height ?? px}\n fill={fill}\n style={style}\n {...accessibilityProps}\n >\n {paths}\n </Svg>\n );\n};\n","import { Connecting, Downloading, type IconDefinition, Recording, Syncing } from '@gnome-ui/icons';\nimport { type ComponentType, useEffect, useRef } from 'react';\nimport { Animated, Easing } from 'react-native';\nimport { Circle, G, Path, Svg } from 'react-native-svg';\nimport type { IconProps } from '@/components/Icon';\nimport { Icon } from '@/components/Icon';\nimport { ICON_SIZE_MAP, iconAccessibilityProps, resolveIconColor } from '@/components/Icon/shared';\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport interface AnimatedIconProps extends Omit<IconProps, 'icon'> {\n /** Animated icon from `@gnome-ui/icons` (`animated: true` — `Syncing`, `Recording`, `Downloading`, `Connecting`). */\n icon: IconDefinition;\n /**\n * Whether the animation plays. Defaults to `true`.\n *\n * Regardless of this prop, the animation is always paused when the OS\n * reduced-motion setting is on — callers don't need to check\n * `useReducedMotion()` themselves.\n */\n playing?: boolean;\n}\n\n/**\n * `Animated`'s style/prop interpolation only takes effect on `Animated.*`\n * host components — the same gotcha already documented on `Toast`/`Dialog`,\n * here applied to `react-native-svg`'s shape components instead of `View`/\n * `Pressable`. Hoisted to module scope so they aren't recreated per render.\n */\nconst AnimatedG = Animated.createAnimatedComponent(G);\nconst AnimatedPath = Animated.createAnimatedComponent(Path);\nconst AnimatedCircle = Animated.createAnimatedComponent(Circle);\n\ninterface MotionProps {\n fill: string;\n}\n\n/** Drives a `0 → 1` value on an infinite loop. Used wherever the whole motion can be expressed as one `interpolate()` off a single linear driver. */\nfunction useLoopingProgress(duration: number) {\n const value = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n const animation = Animated.loop(\n Animated.timing(value, {\n toValue: 1,\n duration,\n easing: Easing.linear,\n useNativeDriver: false,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [value, duration]);\n\n return value;\n}\n\n/** Same as `useLoopingProgress`, but the repeating loop only starts after an initial one-time `delay` — for staggering identical cycles (`Connecting`'s three dots) out of phase with each other. */\nfunction useDelayedLoopingProgress(duration: number, delay: number) {\n const value = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n const animation = Animated.sequence([\n Animated.delay(delay),\n Animated.loop(\n Animated.timing(value, {\n toValue: 1,\n duration,\n easing: Easing.linear,\n useNativeDriver: false,\n }),\n ),\n ]);\n\n animation.start();\n\n return () => animation.stop();\n }, [value, duration, delay]);\n\n return value;\n}\n\n/**\n * `emblem-synchronizing-symbolic` — rotates a full turn, 1.5s linear, mirroring\n * `@gnome-ui/icons`' `Syncing.svg` `@keyframes gicon-syncing-rotate`.\n * Reuses `Refresh`'s exact path data, same as the source icon.\n */\nconst SyncingMotion = ({ fill }: MotionProps) => {\n const progress = useLoopingProgress(1500);\n const transform = progress.interpolate({\n inputRange: [0, 1],\n outputRange: ['rotate(0, 8, 8)', 'rotate(360, 8, 8)'],\n });\n\n return (\n <AnimatedG transform={transform}>\n <Path\n fill={fill}\n fillRule=\"evenodd\"\n d=\"M8 2a6 6 0 0 0-6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1-4 4v-2L5 13l3 3v-2a6 6 0 0 0 6-6 6 6 0 0 0-6-6z\"\n />\n </AnimatedG>\n );\n};\n\n/**\n * `media-record-symbolic` — opacity pulse `1 → 0.35 → 1`, 1.2s ease-in-out,\n * mirroring `Recording.svg`'s `@keyframes gicon-recording-pulse`.\n */\nconst RecordingMotion = ({ fill }: MotionProps) => {\n const opacity = useRef(new Animated.Value(1)).current;\n\n useEffect(() => {\n const easing = Easing.inOut(Easing.ease);\n const animation = Animated.loop(\n Animated.sequence([\n Animated.timing(opacity, { toValue: 0.35, duration: 600, easing, useNativeDriver: false }),\n Animated.timing(opacity, { toValue: 1, duration: 600, easing, useNativeDriver: false }),\n ]),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [opacity]);\n\n return (\n <AnimatedPath\n fill={fill}\n opacity={opacity}\n d=\"m 15 8 c 0 3.867188 -3.132812 7 -7 7 s -7 -3.132812 -7 -7 s 3.132812 -7 7 -7 s 7 3.132812 7 7 z m 0 0\"\n />\n );\n};\n\n/**\n * Animated download indicator — static tray bar, arrow drops into it on a\n * loop (translateY + opacity), 1.4s, mirroring `Downloading.svg`'s\n * `@keyframes gicon-downloading-drop`. The five CSS keyframe stops\n * (`0%, 20%, 50%, 55%, 80%, 100%`) become one `interpolate()`'s\n * `inputRange` off a single linear `0 → 1` driver — good enough fidelity\n * for a decorative micro-interaction without chaining five separately-eased\n * `Animated.timing` segments.\n */\nconst DownloadingMotion = ({ fill }: MotionProps) => {\n const progress = useLoopingProgress(1400);\n const stops = [0, 0.2, 0.5, 0.55, 0.8, 1];\n const transform = progress.interpolate({\n inputRange: stops,\n outputRange: [\n 'translate(0, 0)',\n 'translate(0, 0)',\n 'translate(0, 3)',\n 'translate(0, -3)',\n 'translate(0, 0)',\n 'translate(0, 0)',\n ],\n });\n const opacity = progress.interpolate({ inputRange: stops, outputRange: [1, 1, 0, 0, 1, 1] });\n\n return (\n <>\n <Path fill={fill} d=\"M2 13h12v2H2z\" />\n <AnimatedG transform={transform} opacity={opacity}>\n <Path fill={fill} fillRule=\"evenodd\" d=\"m2.5 5 5.5 6 5.5-6z\" />\n </AnimatedG>\n </>\n );\n};\n\n/** `scale(s)` around an arbitrary `(cx, cy)` pivot, composed as SVG's own translate/scale/translate-back — `react-native-svg`'s dedicated `scale` prop takes a `NumberArray`, not a single animatable number, and its non-deprecated `scaleX`/`scaleY` still can't share one `Animated.Value` with `origin` cleanly, so a plain `transform` string is the most direct fit. */\nfunction scaleAround(cx: number, cy: number, scale: number) {\n return `translate(${cx}, ${cy}) scale(${scale}) translate(${-cx}, ${-cy})`;\n}\n\ninterface ConnectingDotProps {\n cx: number;\n cy: number;\n fill: string;\n delay: number;\n}\n\n/** One of `Connecting`'s three signal dots — opacity + scale pulse, 1.2s ease-in-out, staggered via `delay` so the three read as a left-to-right sweep, mirroring `Connecting.svg`'s `animation-delay: 0/0.15s/0.3s`. */\nconst ConnectingDot = ({ cx, cy, fill, delay }: ConnectingDotProps) => {\n const progress = useDelayedLoopingProgress(1200, delay);\n const stops = [0, 0.2, 0.4, 1];\n const opacity = progress.interpolate({ inputRange: stops, outputRange: [1, 0.3, 1, 1] });\n const transform = progress.interpolate({\n inputRange: stops,\n outputRange: [\n scaleAround(cx, cy, 1),\n scaleAround(cx, cy, 0.7),\n scaleAround(cx, cy, 1),\n scaleAround(cx, cy, 1),\n ],\n });\n\n return (\n <AnimatedCircle cx={cx} cy={cy} r={2} fill={fill} opacity={opacity} transform={transform} />\n );\n};\n\n/**\n * `network-wireless-acquiring-symbolic` — static device/arc path, three\n * signal dots pulsing in a staggered sweep, mirroring `Connecting.svg`.\n */\nconst ConnectingMotion = ({ fill }: MotionProps) => {\n return (\n <>\n <Path\n fill={fill}\n d=\"m 8 1.992188 c -2.617188 0 -5.238281 0.933593 -7.195312 2.808593 l -0.496094 0.480469 c -0.3984378 0.378906 -0.410156 1.011719 -0.03125 1.410156 c 0.003906 0.007813 0.011718 0.011719 0.019531 0.015625 c 0.480469 -1.011719 1.503906 -1.707031 2.703125 -1.707031 h 0.9375 c 2.480469 -1.292969 5.644531 -1.292969 8.125 0 h 0.9375 c 1.199219 0 2.222656 0.695312 2.707031 1.707031 c 0.003907 -0.007812 0.011719 -0.011719 0.015625 -0.015625 c 0.378906 -0.398437 0.367188 -1.03125 -0.03125 -1.410156 l -0.496094 -0.480469 c -1.957031 -1.875 -4.578124 -2.808593 -7.195312 -2.808593 z m -1.730469 9.007812 c -0.441406 0.765625 -0.339843 1.757812 0.316407 2.414062 c 0.78125 0.78125 2.046874 0.78125 2.828124 0 c 0.65625 -0.65625 0.757813 -1.648437 0.316407 -2.414062 z m 0 0\"\n />\n <ConnectingDot cx={3} cy={8} fill={fill} delay={0} />\n <ConnectingDot cx={8} cy={8} fill={fill} delay={150} />\n <ConnectingDot cx={13} cy={8} fill={fill} delay={300} />\n </>\n );\n};\n\n/**\n * Known animated icons, matched by referential identity against\n * `@gnome-ui/icons`' own exports. There is no generic way to interpret an\n * arbitrary icon's `svg`-embedded CSS `@keyframes` in RN (no CSS engine),\n * so each recipe is hand-built — this registry only covers the 4 icons\n * `@gnome-ui/icons` currently ships as `animated: true`. An icon that isn't\n * in it (a future 5th animated icon, or a consumer-authored one) falls back\n * to the static `<Icon>` frame — `playing` silently has no visible effect\n * rather than throwing.\n */\nconst RECIPES = new Map<IconDefinition, ComponentType<MotionProps>>([\n [Syncing, SyncingMotion],\n [Recording, RecordingMotion],\n [Downloading, DownloadingMotion],\n [Connecting, ConnectingMotion],\n]);\n\n/**\n * Plays the motion for a known `animated` icon from `@gnome-ui/icons`\n * (`Syncing`, `Recording`, `Downloading`, `Connecting`) — rendered through\n * plain `<Icon>`, these show a static frame instead.\n *\n * Unlike `@gnome-ui/react`'s `AnimatedIcon` (which plays a CSS animation\n * embedded in the icon's raw `svg` markup via a `--gnome-icon-play-state`\n * custom property), RN has no CSS engine to interpret `@keyframes` at all —\n * `<Icon>` already drops the `<style>` block silently (see its own doc\n * comment), and this component instead hand-builds each of the 4 known\n * icons' exact motion with `Animated`, matched against `RECIPES` by\n * reference. When playing and reduced motion is off, it renders its own\n * `<Svg>` with the matching `*Motion` recipe as children; otherwise (not\n * playing, reduced motion on, or an icon `RECIPES` doesn't recognize) it\n * defers straight to `<Icon>`.\n *\n * Useful for progress, sync, recording, download, and connection states, or\n * cross-fading between icons by swapping `icon` while `playing` stays true.\n *\n * @example\n * import { Syncing } from \"@gnome-ui/icons\";\n * <AnimatedIcon icon={Syncing} playing={isSyncing} label=\"Syncing\" />\n */\nexport const AnimatedIcon = ({\n icon,\n playing = true,\n size = 'md',\n width,\n height,\n label,\n color,\n}: AnimatedIconProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n const isPlaying = playing && !reducedMotion;\n const Motion = isPlaying ? RECIPES.get(icon) : undefined;\n\n if (!Motion) {\n return (\n <Icon icon={icon} size={size} width={width} height={height} label={label} color={color} />\n );\n }\n\n const px = ICON_SIZE_MAP[size];\n const fill = resolveIconColor(theme, color);\n const accessibilityProps = iconAccessibilityProps(label);\n\n return (\n <Svg viewBox={icon.viewBox} width={width ?? px} height={height ?? px} {...accessibilityProps}>\n <Motion fill={fill} />\n </Svg>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type BannerVariant = 'info' | 'warning' | 'error' | 'success';\n\nexport interface BannerProps extends Omit<ViewProps, 'style'> {\n /**\n * Visual emphasis level.\n * - `info` (default) — neutral, accent-colored. Use for tips and notices.\n * - `warning` — yellow. Use for recoverable problems.\n * - `error` — red. Use for failures that need attention.\n * - `success` — green. Use for confirmations.\n */\n variant?: BannerVariant;\n /** The message text. Keep it short — one or two sentences. */\n children: ReactNode;\n /**\n * Label for the optional action button placed at the trailing end.\n * When provided, `onAction` should also be supplied.\n */\n actionLabel?: string;\n /** Called when the user presses the action button. */\n onAction?: () => void;\n /**\n * When true a dismiss (×) button is shown at the trailing edge.\n * Provide `onDismiss` to handle removal from the list.\n */\n dismissible?: boolean;\n /** Called when the user presses the dismiss button. */\n onDismiss?: () => void;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Persistent message strip displayed at the top of a view, following the\n * Adwaita `AdwBanner` pattern. Use for important information that persists\n * until the user acts or explicitly dismisses it — unlike `Toast`, it never\n * auto-dismisses.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"alert\"` is the closest available role, paired with\n * `accessibilityLiveRegion=\"polite\"` (Android's live-region API) as the\n * nearest match to `aria-live=\"polite\"` — the same substitution `Toast`\n * already established for the identical web role pair. Since the banner\n * itself is a plain `View` (not `Pressable` — only its buttons are\n * interactive), `accessible` is set explicitly alongside `accessibilityRole`,\n * per the `BoxedList` lesson that a bare `View` isn't an accessibility\n * element by default.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Banner.html\n * @see https://developer.gnome.org/hig/patterns/feedback/banners.html\n */\nexport const Banner = ({\n variant = 'info',\n children,\n actionLabel,\n onAction,\n dismissible = false,\n onDismiss,\n style,\n ...viewProps\n}: BannerProps) => {\n const theme = useGnomeTheme();\n\n const colors = {\n info: { bg: theme.accentBgColor, fg: theme.accentFgColor },\n warning: { bg: theme.warningBgColor, fg: theme.warningFgColor },\n error: { bg: theme.errorBgColor, fg: theme.errorFgColor },\n success: { bg: theme.successBgColor, fg: theme.successFgColor },\n }[variant];\n\n // Mirrors the source CSS's per-variant :active overlay: a light overlay on\n // the darker info/error/success backgrounds, a dark one on the light\n // warning background.\n const pressedOverlay =\n variant === 'warning' ? 'rgba(0, 0, 0, 0.14)' : 'rgba(255, 255, 255, 0.25)';\n\n return (\n <View\n accessible\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 10,\n paddingHorizontal: theme.space4,\n minHeight: 44,\n width: '100%',\n backgroundColor: colors.bg,\n },\n style,\n ]}\n {...viewProps}\n >\n <Text variant=\"body\" style={{ flex: 1, minWidth: 0, color: colors.fg }}>\n {children}\n </Text>\n\n {(actionLabel || dismissible) && (\n <View\n style={{ flexDirection: 'row', alignItems: 'center', gap: theme.space1, flexShrink: 0 }}\n >\n {actionLabel && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={actionLabel}\n onPress={onAction}\n style={({ pressed }) => ({\n paddingVertical: 4,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusMd,\n backgroundColor: pressed ? pressedOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: colors.fg,\n }}\n >\n {actionLabel}\n </RNText>\n </Pressable>\n )}\n\n {dismissible && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={4}\n onPress={onDismiss}\n style={({ pressed }) => ({\n width: 28,\n height: 28,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusMd,\n opacity: pressed ? 1 : 0.6,\n backgroundColor: pressed ? pressedOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: colors.fg }}>{'×'}</RNText>\n </Pressable>\n )}\n </View>\n )}\n </View>\n );\n};\n","import { forwardRef } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type SeparatorOrientation = 'horizontal' | 'vertical';\n\nexport interface SeparatorProps extends Omit<ViewProps, 'style'> {\n /** Direction of the dividing line. Defaults to `\"horizontal\"`. */\n orientation?: SeparatorOrientation;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Thin dividing line that separates groups of content.\n *\n * Color is driven entirely by `theme.cardShadeColor`, which already\n * resolves correctly per color scheme, so — unlike `Switch`/`Checkbox`/\n * `RadioButton` — there's no `useResolvedColorScheme()` branching needed\n * here.\n *\n * Rebuilt as a plain `View` rather than ported from `@gnome-ui/react`'s\n * `<hr>`/`<div role=\"separator\">`: RN's `AccessibilityRole` union has no\n * `\"separator\"` value, so — since a divider carries no information a\n * screen reader user needs — it's excluded from the accessibility tree\n * entirely with `accessible={false}`, the RN-idiomatic way to mark a\n * purely decorative element, rather than reaching for a role that doesn't\n * exist.\n *\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const Separator = forwardRef<View, SeparatorProps>(function Separator(\n { orientation = 'horizontal', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n ref={ref}\n accessible={false}\n style={[\n { backgroundColor: theme.cardShadeColor, flexShrink: 0 },\n orientation === 'vertical'\n ? { width: 1, height: '100%', alignSelf: 'stretch' }\n : { width: '100%', height: 1 },\n style,\n ]}\n {...viewProps}\n />\n );\n});\n","import { Children, forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { Separator } from '@/components/Separator';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport type BoxedListVariant = 'default' | 'separate';\n\nexport interface BoxedListProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /**\n * `\"separate\"` renders each child as its own standalone rounded card\n * instead of a single joined list — mirrors `.boxed-list-separate`.\n * Use when rows are independent items rather than a continuous group.\n */\n variant?: BoxedListVariant;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Rounded bordered list — the most common container pattern in GNOME apps.\n *\n * Mirrors the Adwaita `.boxed-list` style applied to a `GtkListBox`.\n * Separators between rows are inserted automatically. Pair with `ActionRow`\n * or any row-shaped element.\n *\n * Rebuilt with `View` rather than ported from `@gnome-ui/react`'s\n * `<ul>`/`<li>` — RN has no list-semantics elements, so the outer `View`\n * gets `accessibilityRole=\"list\"` (there's no RN equivalent of `listitem`\n * for rows), paired with `accessible` — a plain `View` isn't an\n * accessibility element by default, so without it screen readers (and\n * `@testing-library/react-native`'s `getByRole`) would skip over the role\n * entirely. The web version applies `border-radius` directly to each\n * first/last child via a `:first-child > *` CSS selector, since its `<ul>`\n * has no `overflow: hidden` of its own; RN's `overflow: 'hidden'` on the\n * outer `View` clips every row to the container's rounded corners\n * uniformly, so that per-child trick isn't needed here.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html#boxed-lists-cards\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const BoxedList = forwardRef<View, BoxedListProps>(function BoxedList(\n { children, variant = 'default', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const items = Children.toArray(children).filter(Boolean);\n\n if (variant === 'separate') {\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"list\"\n style={[{ gap: theme.space2 }, style]}\n {...viewProps}\n >\n {items.map((child, i) => (\n <RNView\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n key={i}\n style={{\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.dividerColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n }}\n >\n {child}\n </RNView>\n ))}\n </RNView>\n );\n }\n\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"list\"\n style={[\n {\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.dividerColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n },\n style,\n ]}\n {...viewProps}\n >\n {items.map((child, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n <RNView key={i}>\n {i > 0 && <Separator testID=\"boxed-list-separator\" />}\n {child}\n </RNView>\n ))}\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Pressable, Text } from 'react-native';\n\nimport { useGnomeTheme, useResolvedContrast } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type ButtonVariant = 'default' | 'suggested' | 'destructive' | 'flat' | 'raised';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonShape = 'default' | 'pill' | 'circular';\n\nexport interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {\n /** Visual style of the button. Follows GNOME HIG button types. */\n variant?: ButtonVariant;\n /** Size of the button. */\n size?: ButtonSize;\n /** Shape of the button. \"pill\" for primary actions in open space, \"circular\" for icon-only buttons. */\n shape?: ButtonShape;\n /**\n * Dark semi-transparent overlay style for buttons placed on top of media\n * or images — mirrors `@gnome-ui/react`'s `osd` prop.\n */\n osd?: boolean;\n /**\n * Icon placed before the label. Rendered as-is — RN has no CSS\n * `currentColor` equivalent, so size and color it yourself (`theme.*FgColor`\n * from `useGnomeTheme()` matches the resolved label color for each variant).\n */\n leadingIcon?: ReactNode;\n /** Icon placed after the label. See `leadingIcon` for color/size notes. */\n trailingIcon?: ReactNode;\n /** String children render as a themed `Text` label; other nodes render as-is. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n /** Style applied to the label `Text` when `children` is a string. */\n textStyle?: StyleProp<TextStyle>;\n}\n\ninterface SizeMetrics {\n minHeight: number;\n minWidth: number;\n paddingVertical: number;\n paddingHorizontal: number;\n fontSize: number;\n}\n\nfunction getSizeMetrics(theme: GnomeThemeTokens, size: ButtonSize): SizeMetrics {\n switch (size) {\n case 'sm':\n return {\n minHeight: 28,\n minWidth: 64,\n paddingVertical: 4,\n paddingHorizontal: theme.space1,\n fontSize: theme.fontSizeCaption,\n };\n case 'lg':\n return {\n minHeight: 42,\n minWidth: 88,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space3,\n fontSize: theme.fontSizeTitle4,\n };\n default:\n return {\n minHeight: 34,\n minWidth: 88,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space2,\n fontSize: theme.fontSizeBody,\n };\n }\n}\n\nfunction getCircularSize(size: ButtonSize): number {\n switch (size) {\n case 'sm':\n return 28;\n case 'lg':\n return 42;\n default:\n return 34;\n }\n}\n\ninterface VariantColors {\n backgroundColor: string;\n borderColor: string;\n color: string;\n}\n\nfunction getVariantColors(\n theme: GnomeThemeTokens,\n variant: ButtonVariant,\n pressed: boolean,\n osd: boolean,\n): VariantColors {\n if (osd) {\n return {\n backgroundColor: pressed ? 'rgba(0, 0, 0, 0.85)' : 'rgba(0, 0, 0, 0.65)',\n borderColor: 'rgba(255, 255, 255, 0.12)',\n color: 'rgba(255, 255, 255, 0.95)',\n };\n }\n\n switch (variant) {\n case 'suggested':\n return {\n backgroundColor: theme.accentBgColor,\n borderColor: 'transparent',\n color: theme.accentFgColor,\n };\n case 'destructive':\n return {\n backgroundColor: theme.destructiveBgColor,\n borderColor: 'transparent',\n color: theme.destructiveFgColor,\n };\n case 'flat':\n return {\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n borderColor: 'transparent',\n color: theme.windowFgColor,\n };\n default:\n return {\n backgroundColor: pressed ? theme.light3 : theme.cardBgColor,\n borderColor: theme.light3,\n color: theme.windowFgColor,\n };\n }\n}\n\n/**\n * Button component following GNOME Human Interface Guidelines.\n *\n * Variants:\n * - `default` — Standard action, flat appearance with subtle border.\n * - `suggested` — Affirmative/primary action (accent color). Use at most once per view.\n * - `destructive` — Dangerous or irreversible action (red). Use sparingly.\n * - `flat` — No border or background; ideal for header bars and toolbars.\n * - `raised` — Explicit raised look inside flat/toolbar contexts.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s DOM-based JSX, but mirrors its prop API.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/buttons.html\n */\nexport const Button = forwardRef<View, ButtonProps>(function Button(\n {\n variant = 'default',\n size = 'md',\n shape = 'default',\n osd = false,\n leadingIcon,\n trailingIcon,\n children,\n style,\n textStyle,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const contrast = useResolvedContrast();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={({ pressed }) => {\n const { backgroundColor, borderColor } = getVariantColors(theme, variant, pressed, osd);\n const solidVariant = !osd && (variant === 'suggested' || variant === 'destructive');\n const circularSize = shape === 'circular' ? getCircularSize(size) : undefined;\n const { minHeight, minWidth, paddingVertical, paddingHorizontal } = getSizeMetrics(\n theme,\n size,\n );\n\n return [\n {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.space1,\n minHeight: circularSize ?? minHeight,\n minWidth: circularSize ?? (shape === 'pill' ? undefined : minWidth),\n width: circularSize,\n height: circularSize,\n paddingVertical: circularSize ? theme.space1 : paddingVertical,\n paddingHorizontal: circularSize\n ? theme.space1\n : shape === 'pill'\n ? theme.space3\n : paddingHorizontal,\n borderRadius: shape === 'default' ? theme.radiusMd : theme.radiusPill,\n borderWidth: variant === 'default' && contrast === 'more' ? 2 : 1,\n borderColor,\n backgroundColor,\n opacity: disabled ? theme.opacityDisabled : pressed && solidVariant ? 0.85 : 1,\n } satisfies ViewStyle,\n style,\n ];\n }}\n {...pressableProps}\n >\n {({ pressed }) => {\n const { fontSize } = getSizeMetrics(theme, size);\n const { color } = getVariantColors(theme, variant, pressed, osd);\n\n return (\n <>\n {leadingIcon}\n {typeof children === 'string' ? (\n <Text\n style={[\n {\n fontFamily: theme.fontFamily,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n fontSize,\n color,\n },\n textStyle,\n ]}\n >\n {children}\n </Text>\n ) : (\n children\n )}\n {trailingIcon}\n </>\n );\n }}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView, StyleSheet } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg';\n\nexport interface CardProps extends Omit<PressableProps, 'style' | 'children'> {\n /**\n * When true the card becomes pressable (Adwaita `.activatable`).\n * Renders as `Pressable` with `accessibilityRole=\"button\"`; a plain\n * `View` otherwise. `onPress`/`onLongPress`/etc. only take effect when\n * `interactive` is true — RN's `View` has no touch handling of its own,\n * unlike a DOM `<div>`'s `onClick`.\n */\n interactive?: boolean;\n /** Internal spacing. Defaults to `\"md\"`. */\n padding?: CardPadding;\n style?: StyleProp<ViewStyle>;\n children?: ReactNode;\n}\n\nfunction getPadding(theme: GnomeThemeTokens, padding: CardPadding): number {\n switch (padding) {\n case 'none':\n return 0;\n case 'sm':\n return theme.space2;\n case 'lg':\n return theme.space5;\n default:\n return theme.space4;\n }\n}\n\n/**\n * Card component following the GNOME HIG and Adwaita `.card` style class.\n *\n * Use for grouping related content on an elevated surface. Set\n * `interactive` for clickable cards (e.g. grid item, settings shortcut).\n *\n * Rebuilt with `Pressable`/`View` rather than ported from `@gnome-ui/react`'s\n * DOM-based `<button>`/`<div>` + `as` prop — RN has no polymorphic-element\n * equivalent, so `as` is dropped. The web version's `:hover`/`:active`\n * `color-mix()` darken/lighten is reproduced with an absolutely-positioned\n * overlay `View` tinted by `theme.activeOverlay` while pressed, since RN\n * has no `color-mix()` to blend two flat colors directly.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const Card = forwardRef<View, CardProps>(function Card(\n { interactive = false, padding = 'md', style, children, disabled, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n const baseStyle: ViewStyle = {\n backgroundColor: theme.cardBgColor,\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusLg,\n overflow: 'hidden',\n padding: getPadding(theme, padding),\n };\n\n if (!interactive) {\n return (\n <RNView ref={ref} style={[baseStyle, style]} {...(pressableProps as ViewProps)}>\n {children}\n </RNView>\n );\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: !!disabled }}\n style={[\n baseStyle,\n { position: 'relative', opacity: disabled ? theme.opacityDisabled : 1 },\n style,\n ]}\n {...pressableProps}\n >\n {({ pressed }) => (\n <>\n {children}\n {pressed && !disabled ? (\n <RNView\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n { backgroundColor: theme.activeOverlay, borderRadius: theme.radiusLg },\n ]}\n />\n ) : null}\n </>\n )}\n </Pressable>\n );\n});\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface CheckboxProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether the checkbox is checked. */\n value: boolean;\n /**\n * Indeterminate state — shown when only some items in a group are\n * checked. Takes visual precedence over `value`.\n */\n indeterminate?: boolean;\n /** Called with the next value when the checkbox is pressed. */\n onValueChange?: (value: boolean) => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst SIZE = 18;\n\n/**\n * Checkbox for multi-selection, following the GNOME HIG and Adwaita style.\n *\n * Supports three states: unchecked, checked, and indeterminate (mixed).\n * Use `indeterminate` for \"select all\" controls when only some items are\n * selected.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"checkbox\">`: RN has no `indeterminate`\n * DOM property to set imperatively (the web version's whole reason for a\n * ref + effect), so it's just a rendering branch here — `indeterminate`\n * draws a short bar, otherwise a checkmark, both fading in via the same\n * `Animated.Value` used for the border/background transition. The\n * checkmark itself is a `✓` glyph in a plain (non-themed) `Text` rather\n * than the web version's `clip-path` polygon — this package has no SVG\n * dependency to draw one exactly, and `Link`'s external-link indicator\n * already established a Unicode glyph as this codebase's fallback for a\n * small decorative mark with no icon library available.\n *\n * `value`/`onValueChange` mirror the same convention as `Switch`, RN's own\n * toggle-control shape, rather than the web version's `checked`/`onChange`.\n * The idle border color is another `Switch`-style case where the source\n * CSS hardcodes a palette swatch per color scheme instead of a token that\n * already resolves per theme, so it branches on `useResolvedColorScheme()`\n * the same way.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/checkboxes.html\n */\nexport const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox(\n { value, indeterminate = false, onValueChange, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const marked = value || indeterminate;\n const progress = useRef(new Animated.Value(marked ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `marked` — skip\n // animating into a state the checkbox is already rendering, so it\n // never plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: marked ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [marked, progress, theme.durationFast, theme.easingDefault]);\n\n const idleBorderColor =\n contrast === 'more' ? theme.windowFgColor : colorScheme === 'dark' ? theme.dark1 : theme.light4;\n\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [idleBorderColor, theme.accentBgColor],\n });\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.cardBgColor, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"checkbox\"\n accessibilityState={{ checked: indeterminate ? 'mixed' : value, disabled: !!disabled }}\n onPress={() => onValueChange?.(!value)}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: SIZE,\n height: SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n borderWidth: contrast === 'more' ? 2 : 1.5,\n borderColor,\n backgroundColor,\n }}\n >\n {indeterminate ? (\n <Animated.View\n style={{\n width: 10,\n height: 2,\n borderRadius: 1,\n backgroundColor: '#fff',\n opacity: progress,\n }}\n />\n ) : (\n <Animated.Text\n style={{\n opacity: progress,\n color: '#fff',\n fontSize: 13,\n fontWeight: 'bold',\n lineHeight: 13,\n }}\n >\n {'✓'}\n </Animated.Text>\n )}\n </Animated.View>\n </Pressable>\n );\n});\n","import { type ReactNode, useEffect, useRef } from 'react';\nimport type { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Animated, BackHandler, Easing, Modal, Pressable, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\n/**\n * `Animated`'s style interpolation only takes effect on `Animated.*` host\n * components — a plain `Pressable` would silently ignore the animated\n * `opacity` in its style, the same gotcha already documented on `Toast`.\n * Hoisted to module scope so it isn't recreated on every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nexport type DialogButtonVariant = 'default' | 'suggested' | 'destructive';\n\nexport interface DialogButton {\n /** Button label. */\n label: string;\n /** Visual variant. Defaults to `\"default\"`. */\n variant?: DialogButtonVariant;\n /** Called when the button is pressed. */\n onPress: () => void;\n /** Whether the button is disabled. */\n disabled?: boolean;\n}\n\nexport type AlertDialogResponseVariant = DialogButtonVariant;\n\nexport interface AlertDialogResponse {\n /**\n * Unique identifier returned via `onResponse`.\n * Use `\"cancel\"` by convention for the dismissive action.\n */\n id: string;\n /** Button label. */\n label: string;\n /** Visual emphasis. Defaults to `\"default\"`. */\n variant?: AlertDialogResponseVariant;\n /** Disables the button. */\n disabled?: boolean;\n}\n\nexport interface DialogProps {\n /** Whether the dialog is visible. */\n open: boolean;\n\n // ── Standard dialog ────────────────────────────────────────────────────\n\n /** Dialog heading. */\n title?: ReactNode;\n /** Body content. */\n children?: ReactNode;\n /** Action buttons (standard dialog API). */\n buttons?: DialogButton[];\n /** Called on Android back button / backdrop press. */\n onClose?: () => void;\n /** Whether pressing the backdrop closes the dialog. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n\n // ── AlertDialog extension ───────────────────────────────────────────────\n\n /**\n * Use `\"alertdialog\"` for confirmations and destructive warnings — screen\n * readers announce it immediately. Defaults to `\"dialog\"`.\n *\n * When using `role=\"alertdialog\"`, prefer the `responses`/`onResponse` API\n * over `buttons`/`onPress` for semantic clarity.\n */\n role?: 'dialog' | 'alertdialog';\n\n /**\n * Response buttons (AlertDialog API). Alternative to `buttons` — each\n * response has a semantic `id` returned via `onResponse`. The Android back\n * button and backdrop press fire the first non-destructive response.\n */\n responses?: AlertDialogResponse[];\n\n /**\n * Called with the `id` of the response button pressed.\n * Required when `responses` is provided.\n */\n onResponse?: (id: string) => void;\n\n style?: StyleProp<ViewStyle>;\n /** Forwarded to the backdrop — useful for testing. */\n testID?: string;\n}\n\n/**\n * Blocking modal dialog following the Adwaita pattern.\n *\n * **Standard** — `title` + `children` + `buttons[]`.\n *\n * **Alert** — add `role=\"alertdialog\"` + `responses[]` + `onResponse`.\n * Uses a semantic response id instead of per-button `onPress`. The Android\n * back button / backdrop press fire the first non-destructive response.\n * Mirrors `AdwAlertDialog`.\n *\n * Built on RN's own `Modal` rather than `@gnome-ui/react`'s DOM `Portal` +\n * manual focus trap: `Modal` already floats above everything with no portal\n * target needed, already blocks interaction with the screen behind it (no\n * `useBodyScrollLock` equivalent needed), and its `onRequestClose` fires on\n * the Android hardware back button — the direct analog of the web version's\n * document-level Escape listener. Focus-trapping (`Tab`/`Shift+Tab` cycling)\n * has no port: there is no keyboard `Tab` concept in RN's touch-first model,\n * the same reasoning that already dropped `TabBar`'s roving-tabindex arrow\n * keys.\n *\n * `role` is passed straight through as RN's own `role` prop (not\n * `accessibilityRole`) — RN's newer, web-aligned `Role` union has real\n * `\"dialog\"`/`\"alertdialog\"` values, unlike the older `AccessibilityRole`\n * enum `Toast`/`Banner` had to substitute `\"alert\"` into for the web's\n * `role=\"status\"`. `accessibilityViewIsModal` (iOS) is the closest match to\n * `aria-modal=\"true\"`, restricting VoiceOver to the dialog's subtree.\n *\n * There is no exit animation on either platform — the source CSS only\n * defines entrance keyframes, and `Modal`'s `visible={false}` unmounts\n * immediately, matching the web version returning `null` outright when\n * `!open`. Entrance is an `Animated.timing` fading + scaling + sliding the\n * card in (mirrors `@keyframes dialog-in`) alongside a plain backdrop fade\n * (`@keyframes backdrop-in`), replayed via a `useEffect` keyed on `open`\n * since — unlike `Toast`, which mounts once per instance — the same\n * `Dialog` element toggles `open` repeatedly while `Modal` itself\n * mounts/unmounts internally. `useReducedMotion()` skips straight to the\n * settled state.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Dialog.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.AlertDialog.html\n */\nexport const Dialog = ({\n open,\n title,\n children,\n buttons = [],\n onClose,\n closeOnBackdrop = true,\n role = 'dialog',\n responses,\n onResponse,\n style,\n testID,\n}: DialogProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n const progress = useRef(new Animated.Value(reducedMotion ? 1 : 0)).current;\n\n const isAlert = !!responses;\n\n const dismissAlert = () => {\n const cancel = responses?.find((r) => r.variant !== 'destructive' && !r.disabled);\n\n if (cancel) {\n onResponse?.(cancel.id);\n }\n };\n\n const handleEscape = () => {\n if (isAlert) {\n dismissAlert();\n } else {\n onClose?.();\n }\n };\n\n const handleBackdropPress = isAlert ? dismissAlert : closeOnBackdrop ? onClose : undefined;\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [open, reducedMotion, progress, theme.durationNormal, theme.easingDefault]);\n\n // Only the topmost dialog reacts to the Android back button, mirroring\n // the web version's \"topmost modal only\" Escape behavior for stacked\n // dialogs.\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n handleEscape();\n\n return true;\n });\n\n return () => subscription.remove();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, isAlert, responses, onResponse, onClose]);\n\n const renderButtons = () => {\n const rows = isAlert && responses ? responses : buttons;\n\n if (rows.length === 0) {\n return null;\n }\n\n return (\n <View style={{ borderTopWidth: 1, borderTopColor: theme.cardShadeColor }}>\n {rows.map((row, index) => {\n const variant = row.variant ?? 'default';\n const color = variant === 'destructive' ? theme.destructiveColor : theme.accentColor;\n const onPress = isAlert\n ? () => onResponse?.((row as AlertDialogResponse).id)\n : (row as DialogButton).onPress;\n\n return (\n <Pressable\n key={isAlert ? (row as AlertDialogResponse).id : row.label}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: row.disabled }}\n disabled={row.disabled}\n onPress={onPress}\n style={({ pressed }) => ({\n paddingVertical: 14,\n paddingHorizontal: theme.space4,\n borderBottomWidth: index < rows.length - 1 ? 1 : 0,\n borderBottomColor: theme.cardShadeColor,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n opacity: row.disabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text\n variant=\"body\"\n style={{\n textAlign: 'center',\n color,\n fontWeight:\n variant === 'suggested'\n ? (String(theme.fontWeightSemibold) as TextStyle['fontWeight'])\n : undefined,\n }}\n >\n {row.label}\n </Text>\n </Pressable>\n );\n })}\n </View>\n );\n };\n\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.5, shadowRadius: 32, elevation: 12 }\n : { shadowOpacity: 0.25, shadowRadius: 32, elevation: 8 };\n\n return (\n <Modal\n visible={open}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={handleEscape}\n >\n <AnimatedPressable\n testID={testID}\n onPress={handleBackdropPress}\n style={{\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 24,\n backgroundColor: theme.dialogBackdropColor,\n opacity: progress,\n }}\n >\n <Pressable onPress={() => {}} accessible={false} style={{ width: '100%', maxWidth: 480 }}>\n <Animated.View\n accessible\n role={role}\n accessibilityViewIsModal\n style={[\n {\n backgroundColor: theme.dialogBgColor,\n borderRadius: theme.radiusXl,\n overflow: 'hidden',\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 8 },\n ...shadow,\n opacity: progress,\n transform: [\n {\n translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }),\n },\n { scale: progress.interpolate({ inputRange: [0, 1], outputRange: [0.92, 1] }) },\n ],\n },\n style,\n ]}\n >\n {title && (\n <Text\n variant=\"title-4\"\n style={{\n padding: theme.space4,\n paddingBottom: children ? 0 : theme.space4,\n textAlign: 'center',\n fontWeight: String(theme.fontWeightBold) as TextStyle['fontWeight'],\n }}\n >\n {title}\n </Text>\n )}\n\n {children && (\n <View style={{ paddingVertical: theme.space2, paddingHorizontal: theme.space4 }}>\n {typeof children === 'string' ? (\n <Text variant=\"body\" style={{ textAlign: 'center', opacity: theme.opacityDim }}>\n {children}\n </Text>\n ) : (\n children\n )}\n </View>\n )}\n\n {renderButtons()}\n </Animated.View>\n </Pressable>\n </AnimatedPressable>\n </Modal>\n );\n};\n","import { Check, PanDown } from '@gnome-ui/icons';\nimport { useEffect, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Animated, Dimensions, Modal, Pressable, ScrollView, View } from 'react-native';\n\nimport { Icon } from '@/components/Icon';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport interface DropdownOption<V extends string = string> {\n /** The value submitted / returned on selection. */\n value: V;\n /** Display label shown in the list and trigger. */\n label: string;\n /** Optional descriptive text shown below the label. */\n description?: string;\n /** Whether the option is selectable. */\n disabled?: boolean;\n}\n\nexport interface DropdownProps<V extends string = string> {\n /** The list of selectable options. */\n options: DropdownOption<V>[];\n /** The currently selected value. */\n value?: V;\n /** Called when the user selects an option. */\n onChange?: (value: V) => void;\n /** Placeholder shown when no option is selected. */\n placeholder?: string;\n /** Accessible label for the control. */\n accessibilityLabel?: string;\n /** Disables the entire control. */\n disabled?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n width: number;\n flipUp: boolean;\n}\n\nconst GAP = 4;\nconst MARGIN = 8;\nconst MAX_LIST_HEIGHT = 280;\n\nfunction computePosition(trigger: Rect, panelHeight: number): Position {\n const { height: vh } = Dimensions.get('window');\n const spaceBelow = vh - (trigger.y + trigger.height);\n const flipUp = spaceBelow < panelHeight && trigger.y > panelHeight;\n const top = flipUp ? trigger.y - panelHeight - GAP : trigger.y + trigger.height + GAP;\n\n return {\n top: Math.max(MARGIN, Math.min(top, vh - panelHeight - MARGIN)),\n left: trigger.x,\n width: trigger.width,\n flipUp,\n };\n}\n\n/**\n * Expandable option list following the Adwaita combo-row / drop-down\n * pattern, mirroring `@gnome-ui/react`'s `Dropdown`.\n *\n * Built on RN's own `Modal` (transparent) — the same portal-substitute\n * `Dialog`/`Tooltip` already use — with a full-screen backdrop `Pressable`\n * (not `pointerEvents=\"box-none\"` like `Tooltip`'s: unlike a tooltip, this\n * panel is meant to catch and close on an outside tap, the RN analog of the\n * web version's document-level \"click outside\" listener). `open` flips\n * synchronously on trigger press; the trigger's on-screen rect\n * (`measureInWindow`) and the panel's own rendered height (`onLayout`) each\n * resolve independently into state, combined by a separate effect into the\n * final `top`/`left`/`width`/`flipUp` — the same two-independent-\n * async-measurements pattern `Tooltip` established (and for the same\n * reason: gating `open` itself on the native measurement callback would\n * make the component untestable in this package's Jest environment, where\n * `measureInWindow` never calls back).\n *\n * Keyboard navigation (↑/↓ roving highlight, Home/End, type-ahead) has no\n * port — RN's touch-first model has no keyboard focus to drive it, the\n * same reasoning that already dropped `TabBar`'s roving-tabindex arrow\n * keys. Selection is by direct tap only.\n *\n * `role=\"combobox\"` on the trigger ports 1:1. RN's `Role` union has no\n * `\"listbox\"` value (unlike `\"option\"`, which does exist) — the panel uses\n * `role=\"list\"` instead, the same closest-available substitution `BoxedList`\n * already established for a plain list container.\n */\nexport const Dropdown = <V extends string = string>({\n options,\n value,\n onChange,\n placeholder = 'Select an option',\n accessibilityLabel,\n disabled,\n style,\n testID,\n}: DropdownProps<V>) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const [open, setOpen] = useState(false);\n const [triggerRect, setTriggerRect] = useState<Rect | null>(null);\n const [panelHeight, setPanelHeight] = useState<number | null>(null);\n const [pos, setPos] = useState<Position | null>(null);\n\n const triggerRef = useRef<View>(null);\n const progress = useRef(new Animated.Value(0)).current;\n\n const selected = options.find((o) => o.value === value);\n\n const openList = () => {\n if (disabled) {\n return;\n }\n\n setOpen(true);\n };\n\n const closeList = () => setOpen(false);\n\n const selectOption = (opt: DropdownOption<V>) => {\n if (opt.disabled) {\n return;\n }\n\n onChange?.(opt.value);\n closeList();\n };\n\n useEffect(() => {\n if (!open) {\n setTriggerRect(null);\n setPanelHeight(null);\n setPos(null);\n\n return;\n }\n\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerRect({ x, y, width, height });\n });\n }, [open]);\n\n useEffect(() => {\n if (triggerRect === null || panelHeight === null) {\n return;\n }\n\n setPos(computePosition(triggerRect, panelHeight));\n }, [triggerRect, panelHeight]);\n\n useEffect(() => {\n if (!pos) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationFast,\n useNativeDriver: true,\n }).start();\n }, [pos, reducedMotion, progress, theme.durationFast]);\n\n const handlePanelLayout = (e: LayoutChangeEvent) => {\n setPanelHeight(Math.min(e.nativeEvent.layout.height, MAX_LIST_HEIGHT));\n };\n\n return (\n <View style={style}>\n <Pressable\n ref={triggerRef}\n testID={testID}\n role=\"combobox\"\n accessibilityLabel={accessibilityLabel}\n accessibilityState={{ expanded: open, disabled: !!disabled }}\n disabled={disabled}\n onPress={() => (open ? closeList() : openList())}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: theme.space1,\n minHeight: 36,\n minWidth: 160,\n paddingVertical: 7,\n paddingHorizontal: theme.space2,\n backgroundColor: pressed ? theme.activeOverlay : theme.cardBgColor,\n borderWidth: 1,\n borderColor: open ? theme.accentColor : theme.cardShadeColor,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text\n numberOfLines={1}\n style={{\n flex: 1,\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n opacity: selected ? 1 : theme.opacityDim,\n }}\n >\n {selected?.label ?? placeholder}\n </Text>\n <Icon\n icon={PanDown}\n size=\"md\"\n color=\"default\"\n style={{ transform: [{ rotate: open ? '180deg' : '0deg' }] }}\n />\n </Pressable>\n\n <Modal visible={open} transparent animationType=\"none\" statusBarTranslucent>\n <Pressable\n onPress={closeList}\n accessible={false}\n style={{ flex: 1 }}\n testID={testID ? `${testID}-backdrop` : undefined}\n >\n <Animated.View\n onLayout={handlePanelLayout}\n role=\"list\"\n accessible\n style={[\n {\n position: 'absolute',\n maxHeight: MAX_LIST_HEIGHT,\n backgroundColor: theme.popoverBgColor,\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusMd,\n paddingVertical: 4,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.15,\n shadowRadius: 12,\n elevation: 6,\n },\n pos\n ? { top: pos.top, left: pos.left, width: pos.width, opacity: progress }\n : { top: -9999, left: -9999, width: 200, opacity: 0 },\n ]}\n >\n <ScrollView bounces={false}>\n {options.map((opt) => {\n const isSelected = opt.value === value;\n\n return (\n <Pressable\n key={opt.value}\n role=\"option\"\n accessibilityState={{ selected: isSelected, disabled: !!opt.disabled }}\n disabled={opt.disabled}\n onPress={() => selectOption(opt)}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n minHeight: 40,\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n opacity: opt.disabled ? theme.opacityDisabled : 1,\n })}\n >\n <View style={{ flex: 1, gap: 1 }}>\n <Text\n numberOfLines={1}\n style={{\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n fontWeight: isSelected\n ? (String(theme.fontWeightSemibold) as TextStyle['fontWeight'])\n : undefined,\n }}\n >\n {opt.label}\n </Text>\n {opt.description && (\n <Text\n numberOfLines={1}\n style={{\n fontSize: theme.fontSizeCaption,\n color: theme.windowFgColor,\n opacity: theme.opacityDim,\n }}\n >\n {opt.description}\n </Text>\n )}\n </View>\n {isSelected && <Icon icon={Check} size=\"md\" color=\"blue\" />}\n </Pressable>\n );\n })}\n </ScrollView>\n </Animated.View>\n </Pressable>\n </Modal>\n </View>\n );\n};\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, TextStyle, View, ViewProps, ViewStyle } from 'react-native';\nimport { Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface HeaderBarProps extends Omit<ViewProps, 'style'> {\n /** Centered title. Pass a string or a custom element. */\n title?: ReactNode;\n /** Controls placed at the leading (left) edge — back button, menu, etc. */\n start?: ReactNode;\n /** Controls placed at the trailing (right) edge — actions, overflow menu, etc. */\n end?: ReactNode;\n /**\n * When true the header bar blends into the window chrome (no bottom\n * border). Use for the topmost bar of a full-window layout.\n */\n flat?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Title bar with centered title and leading/trailing action slots.\n *\n * Mirrors the Adwaita `AdwHeaderBar` pattern. Use `flat` buttons\n * (`<Button variant=\"flat\">`) inside the header bar per GNOME HIG.\n *\n * Rebuilt with flexbox rather than ported from `@gnome-ui/react`'s CSS\n * Grid (`1fr auto 1fr`) — RN has no grid layout, but the same true-centering\n * effect (the title stays centered in the full width regardless of how\n * wide `start`/`end` are, rather than centering only in the leftover gap\n * between them) comes from giving both side slots `flex: 1` with the title\n * left unflexed in between, since both sides then always claim equal\n * leftover space. The web version's `<header>` element has no RN\n * equivalent; `accessibilityRole=\"header\"` is deliberately *not* applied to\n * the outer `View` since that role means \"text heading\" in RN's\n * accessibility tree (see `Text`'s heading variants), not \"landmark\n * container\" the way HTML's `<header>` does.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.HeaderBar.html\n * @see https://developer.gnome.org/hig/patterns/containers/header-bars.html\n */\nexport const HeaderBar = forwardRef<View, HeaderBarProps>(function HeaderBar(\n { title, start, end, flat = false, style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n ref={ref}\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space2,\n minHeight: 47,\n backgroundColor: theme.headerbarBgColor,\n borderBottomWidth: flat ? 0 : 1,\n borderBottomColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <RNView style={{ flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}>\n {start}\n </RNView>\n\n <RNView\n accessibilityLiveRegion=\"polite\"\n style={{ alignItems: 'center', justifyContent: 'center', paddingHorizontal: theme.space1 }}\n >\n {typeof title === 'string' ? (\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightHeading),\n color: theme.headerbarFgColor,\n }}\n >\n {title}\n </RNText>\n ) : (\n title\n )}\n </RNView>\n\n <RNView\n style={{\n flex: 1,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: theme.space1,\n }}\n >\n {end}\n </RNView>\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Linking, Pressable, Text as RNText } from 'react-native';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface LinkProps extends Omit<PressableProps, 'children' | 'style'> {\n /**\n * Target URL. Passed to `Linking.openURL` when pressed, unless a custom\n * `onPress` is supplied (e.g. to hand internal links to a router like\n * React Navigation instead of the device browser).\n */\n href: string;\n /**\n * When true the link is treated as external: appends a trailing ↗\n * indicator and an \"Opens in browser\" accessibility hint. RN has no tab\n * concept, so unlike the web `Link` this doesn't change navigation\n * behaviour — `href` always opens via `Linking.openURL` regardless.\n */\n external?: boolean;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n /** Style applied to the label `Text`. */\n textStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Inline hyperlink following GNOME HIG.\n *\n * Rebuilt on `Pressable`/themed `Text` rather than ported from\n * `@gnome-ui/react`'s `<a>`: touch devices have no `:hover`, so the\n * underline that the web version reveals on hover instead reveals on\n * press — the closest native equivalent — alongside the same `0.7`\n * press-opacity dip as `@gnome-ui/react`'s `:active` state.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/links.html\n */\nexport const Link = forwardRef<View, LinkProps>(function Link(\n { href, external = false, children, style, textStyle, onPress, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n accessibilityRole=\"link\"\n accessibilityHint={external ? 'Opens in browser' : undefined}\n onPress={onPress ?? (() => Linking.openURL(href))}\n style={style}\n {...pressableProps}\n >\n {({ pressed }) => (\n <Text\n style={[\n {\n color: theme.accentColor,\n textDecorationLine: pressed ? 'underline' : 'none',\n opacity: pressed ? 0.7 : 1,\n },\n textStyle,\n ]}\n >\n {children}\n {external && (\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{ fontSize: 12 }}\n >\n {' ↗'}\n </RNText>\n )}\n </Text>\n )}\n </Pressable>\n );\n});\n","import type { ReactNode } from 'react';\nimport { Fragment } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface PathBarSegment {\n /** Display label for this path segment. */\n label: string;\n /** Opaque path value passed to `onNavigate` when the segment is pressed. */\n path: string;\n /** Optional icon placed before the label (e.g. a folder icon). Rendered as-is. */\n icon?: ReactNode;\n}\n\nexport interface PathBarProps extends Omit<ViewProps, 'style'> {\n /**\n * Ordered path segments from root to current location. The last segment\n * is the current folder and is rendered non-interactive.\n */\n segments: PathBarSegment[];\n /**\n * Called when the user presses a non-current segment. Receives the\n * `path` and zero-based `index` of the pressed segment.\n */\n onNavigate?: (path: string, index: number) => void;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Breadcrumb path bar for navigating a hierarchical location.\n *\n * Mirrors the location bar in GNOME Files (Nautilus). Segments are\n * separated by chevron dividers. All segments except the last are\n * interactive — pressing them calls `onNavigate`. The last segment\n * represents the current location and renders as a static, bold label.\n *\n * Rebuilt with `Pressable`/`View`/`Text` rather than ported from\n * `@gnome-ui/react`'s `<nav><ol><li>`: RN's `AccessibilityRole` union has\n * neither a \"navigation\" landmark nor a breadcrumb-list role (the same gap\n * that dropped `Sidebar`'s `<nav>` role), so those are dropped rather than\n * faked — each interactive segment still gets its own\n * `accessibilityRole=\"button\"` and `accessibilityLabel`. The separator\n * chevron is a Unicode `›` glyph instead of the web version's inline SVG\n * path, matching this package's established no-SVG-dependency convention.\n *\n * @see https://developer.gnome.org/hig/patterns/nav/search.html\n */\nexport const PathBar = ({ segments, onNavigate, style, ...viewProps }: PathBarProps) => {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n style={[{ flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center' }, style]}\n {...viewProps}\n >\n {segments.map((segment, index) => {\n const isCurrent = index === segments.length - 1;\n\n return (\n <Fragment key={segment.path}>\n {index > 0 && (\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n color: theme.windowFgColor,\n opacity: 0.5,\n marginHorizontal: 1,\n fontSize: theme.fontSizeBody,\n }}\n >\n {'›'}\n </RNText>\n )}\n\n {isCurrent ? (\n <RNView\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n paddingVertical: 2,\n paddingHorizontal: theme.space1,\n maxWidth: 200,\n }}\n >\n {segment.icon && <RNView style={{ flexShrink: 0 }}>{segment.icon}</RNView>}\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: theme.windowFgColor,\n }}\n >\n {segment.label}\n </RNText>\n </RNView>\n ) : (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={segment.label}\n onPress={() => onNavigate?.(segment.path, index)}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n paddingVertical: 2,\n paddingHorizontal: theme.space1,\n maxWidth: 160,\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n {segment.icon && <RNView style={{ flexShrink: 0 }}>{segment.icon}</RNView>}\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n color: theme.windowFgColor,\n }}\n >\n {segment.label}\n </RNText>\n </Pressable>\n )}\n </Fragment>\n );\n })}\n </RNView>\n );\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type ProgressBarVariant = 'accent' | 'success' | 'warning' | 'error';\n\nexport interface ProgressBarProps extends Omit<ViewProps, 'style'> {\n /**\n * Current progress value between `0` and `1` (e.g. `0.6` = 60%). Omit\n * or set to `undefined` for the indeterminate (pulsing) state.\n */\n value?: number;\n /**\n * Fill color of the progress indicator.\n * - `\"accent\"` (default) — blue, general-purpose progress.\n * - `\"success\"` — green, completed or healthy state.\n * - `\"warning\"` — yellow, approaching a limit.\n * - `\"error\"` — red, failed or critical state.\n */\n variant?: ProgressBarVariant;\n /** Accessible label describing what is loading. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Determinate and indeterminate progress bar following the Adwaita style.\n *\n * - **Determinate** — pass `value` (0–1) to show exact progress; the fill\n * width animates on every change, matching the web version's\n * `transition: width`.\n * - **Indeterminate** — omit `value` for a 40%-wide bar that slides left\n * to right on an `Animated.loop`, matching the web version's CSS\n * `@keyframes pulse`.\n *\n * `useReducedMotion()` is honored per the *source CSS's own* per-state\n * behavior rather than one uniform rule: determinate width changes simply\n * skip the transition (duration `0`, still an immediate jump like the CSS\n * `transition: none`), while the indeterminate pulse stops entirely and\n * freezes as a static, full-width, 50%-opacity bar — exactly what\n * `@media (prefers-reduced-motion: reduce) { .indeterminate { animation:\n * none; left: 0; width: 100%; opacity: 0.5 } }` does. This differs from\n * `Spinner`, whose reduced-motion behavior *slows* its animation instead\n * of stopping it — each component mirrors its own source CSS rather than\n * applying a single reduced-motion policy across the package.\n *\n * Both animated states are driven entirely by `transform` rather than by\n * layout properties (`width`/`left`), so both can run\n * `useNativeDriver: true`: RN's native animation driver can only animate\n * transforms, and a JS-driven (`useNativeDriver: false`) `Animated.timing`\n * or `Animated.loop` schedules its next frame via a plain `setTimeout` —\n * one that routinely fires a tick after a test's `render()` returns but\n * before unmount, outside any `act()` boundary, producing a real (if\n * harmless) \"update not wrapped in act()\" warning under\n * `@testing-library/react-native` on every render of this component. The\n * determinate fill stays a constant `width: '100%'` and instead animates\n * `transform: [{ scaleX }]` with `transformOrigin: 'left'` (so it grows\n * from the left edge, not from center); the indeterminate pulse similarly\n * animates `transform: [{ translateX }]` from `-0.4 * trackWidth` to\n * `trackWidth` (measured via `onLayout`, since a transform's `translateX`\n * needs a pixel offset, not a percentage) rather than animating `left`.\n * Both reproduce the exact same visual motion as the source CSS's\n * `width`/`left` transitions while running fully off the JS thread, which\n * eliminates the warning at its root rather than suppressing it.\n *\n * `role=\"progressbar\"` maps directly to RN's own `accessibilityRole`\n * (unlike `Spinner`, which had to substitute for the web's `role=\"status\"`\n * — `ProgressBar`'s web role already has a 1:1 RN equivalent).\n * `accessibilityValue` carries `now`/`min`/`max` for the determinate case;\n * the indeterminate case omits all three, RN's equivalent of the web\n * version omitting `aria-valuenow`/`aria-valuemin`/`aria-valuemax`. Web's\n * `aria-labelledby` (an id-relationship prop) has no RN equivalent — RN\n * has no DOM ids — so only `aria-label` (`accessibilityLabel`) is ported.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/progress.html\n */\nexport const ProgressBar = ({\n value,\n variant = 'accent',\n accessibilityLabel,\n style,\n onLayout,\n ...viewProps\n}: ProgressBarProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const isIndeterminate = value === undefined || value === null;\n const clamped = isIndeterminate ? undefined : Math.min(1, Math.max(0, value));\n const percent = clamped !== undefined ? clamped * 100 : undefined;\n\n const width = useRef(new Animated.Value(clamped ?? 0)).current;\n const pulse = useRef(new Animated.Value(0)).current;\n const [trackWidth, setTrackWidth] = useState(0);\n\n const handleTrackLayout = (event: LayoutChangeEvent) => {\n setTrackWidth(event.nativeEvent.layout.width);\n onLayout?.(event);\n };\n\n useEffect(() => {\n if (isIndeterminate) {\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(width, {\n toValue: clamped ?? 0,\n duration: reducedMotion ? 0 : theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [clamped, isIndeterminate, reducedMotion, width, theme.durationNormal, theme.easingDefault]);\n\n useEffect(() => {\n if (!isIndeterminate || reducedMotion) {\n return;\n }\n\n pulse.setValue(0);\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n const animation = Animated.loop(\n Animated.timing(pulse, {\n toValue: 1,\n duration: 1400,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [isIndeterminate, reducedMotion, pulse, theme.easingDefault]);\n\n const trackColor = scheme === 'dark' ? theme.dark2 : theme.light3;\n const variantColor: Record<ProgressBarVariant, string> = {\n accent: theme.accentBgColor,\n success: theme.successBgColor,\n warning: theme.warningBgColor,\n error: theme.errorBgColor,\n };\n\n const fillStyle = isIndeterminate\n ? reducedMotion\n ? { left: 0, width: '100%', opacity: 0.5 }\n : {\n left: 0,\n width: '40%',\n transform: [\n {\n translateX: pulse.interpolate({\n inputRange: [0, 1],\n outputRange: [-0.4 * trackWidth, trackWidth],\n }),\n },\n ],\n }\n : {\n width: '100%',\n transformOrigin: 'left',\n transform: [{ scaleX: width }],\n };\n\n return (\n <Animated.View\n accessible\n accessibilityRole=\"progressbar\"\n accessibilityLabel={accessibilityLabel}\n accessibilityValue={\n clamped !== undefined ? { min: 0, max: 100, now: Math.round(percent as number) } : undefined\n }\n onLayout={handleTrackLayout}\n style={[\n {\n width: '100%',\n height: 6,\n borderRadius: theme.radiusPill,\n backgroundColor: trackColor,\n overflow: 'hidden',\n },\n style,\n ]}\n {...viewProps}\n >\n <Animated.View\n style={[\n {\n position: isIndeterminate ? 'absolute' : 'relative',\n top: 0,\n height: '100%',\n borderRadius: theme.radiusPill,\n backgroundColor: variantColor[variant],\n },\n fillStyle as ViewStyle,\n ]}\n />\n </Animated.View>\n );\n};\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface RadioButtonProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether this radio button is the selected one in its group. */\n value: boolean;\n /**\n * Called when pressed while unselected. RN has no `name`-attribute\n * grouping like the web `<input type=\"radio\">`, so mutual exclusivity\n * within a group is the consumer's responsibility — render one\n * `RadioButton` per option and drive `value` from shared selection\n * state, flipping it in `onSelect`.\n */\n onSelect?: () => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst SIZE = 18;\nconst DOT_SIZE = 6;\n\n/**\n * Single-selection radio button following the GNOME HIG and Adwaita style.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"radio\">`: reuses `Checkbox`'s exact\n * border/background transition technique (same `Animated.Value`, same\n * mount-skip guard so it never animates before the user touches it, same\n * `useResolvedColorScheme()`/`useResolvedContrast()` branching for the\n * idle border color, since the source CSS hardcodes those the same way\n * `Checkbox.module.css` does) — just circular, with a filled dot instead\n * of a checkmark, and no indeterminate state.\n *\n * The web version's `name`-attribute grouping has no RN equivalent, so\n * grouping is fully manual here: render one `RadioButton` per option and\n * manage the selected option in the parent, same as any other controlled\n * list of options.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/radio-buttons.html\n */\nexport const RadioButton = forwardRef<View, RadioButtonProps>(function RadioButton(\n { value, onSelect, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const progress = useRef(new Animated.Value(value ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `value` — skip\n // animating into a state the radio button is already rendering, so it\n // never plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: value ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [value, progress, theme.durationFast, theme.easingDefault]);\n\n const idleBorderColor =\n contrast === 'more' ? theme.windowFgColor : colorScheme === 'dark' ? theme.dark1 : theme.light4;\n\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [idleBorderColor, theme.accentBgColor],\n });\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.cardBgColor, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"radio\"\n accessibilityState={{ checked: value, disabled: !!disabled }}\n onPress={() => {\n if (!value) {\n onSelect?.();\n }\n }}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: SIZE,\n height: SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusPill,\n borderWidth: contrast === 'more' ? 2 : 1.5,\n borderColor,\n backgroundColor,\n }}\n >\n <Animated.View\n style={{\n width: DOT_SIZE,\n height: DOT_SIZE,\n borderRadius: theme.radiusPill,\n backgroundColor: '#fff',\n opacity: progress,\n }}\n />\n </Animated.View>\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode, useEffect, useImperativeHandle, useRef } from 'react';\nimport type { StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport { Pressable, Text as RNText, TextInput as RNTextInput, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface SearchBarProps extends Omit<TextInputProps, 'style'> {\n /** Whether the search bar is rendered. `false` renders nothing. */\n open: boolean;\n /**\n * Renders a trailing \"Cancel\" button (the RN-idiomatic stand-in for the\n * web version's Escape-to-close — touch keyboards have no reliable\n * Escape key) and calls this when it's pressed.\n */\n onClose?: () => void;\n /** Called when the clear (×) button is pressed. Also clears the input value. */\n onClear?: () => void;\n /**\n * Content rendered below the bar (e.g. filter chips). Only rendered\n * while `open` is true.\n */\n children?: ReactNode;\n /** Removes the header-bar background so the bar blends into any surface. */\n inline?: boolean;\n /** Accessible label for the close button. Defaults to `\"Cancel\"`. */\n closeLabel?: string;\n /** Style applied to the wrapping `View`. */\n style?: StyleProp<ViewStyle>;\n /** Style applied to the `TextInput` itself. */\n inputStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Multiplies an `rgba(r, g, b, a)` token's alpha channel. Duplicated from\n * `TextField` rather than shared — see that component for the full\n * rationale; it's small and self-contained enough that a shared module\n * isn't worth it for two call sites.\n */\nfunction dimColor(color: string, factor: number): string {\n const match = color.match(/^rgba?\\(([^,]+),([^,]+),([^,]+),?([^)]+)?\\)$/);\n\n if (!match) {\n return color;\n }\n\n const [, r, g, b, a] = match;\n const alpha = (a ? Number.parseFloat(a) : 1) * factor;\n\n return `rgba(${r.trim()}, ${g.trim()}, ${b.trim()}, ${alpha})`;\n}\n\n/**\n * Collapsible search input following the Adwaita `AdwSearchBar` pattern.\n *\n * Rebuilt on RN's `TextInput` rather than ported from `@gnome-ui/react`'s\n * `<input type=\"search\">`: `open` no longer drives a CSS height/opacity\n * transition (no established animated-height pattern exists yet in this\n * package — same trade-off `SidebarSection` made for its collapsible body)\n * — `open={false}` renders nothing at all, and mounting on `open={true}`\n * auto-focuses the input, standing in for the web version's\n * `requestAnimationFrame`-on-open focus effect.\n *\n * Dropped relative to `@gnome-ui/react`'s `SearchBar`: the `suggestions` /\n * `onSuggestionSelect` / `loadingSuggestions` / `renderSuggestion` /\n * `suggestionsLabel` autocomplete popover — it depends on a portal +\n * viewport-anchored positioning primitive (`createPortal` +\n * `getBoundingClientRect`) this package doesn't have yet, the same gap\n * that dropped `SidebarItem`'s `menuItems` context menu — and a `Spinner`\n * component, not yet ported. The search/clear icons are Unicode glyphs\n * (`🔍`/`×`) rather than `@gnome-ui/icons`, matching every other\n * no-SVG-dependency component in this package.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.SearchBar.html\n */\nexport const SearchBar = forwardRef<TextInput, SearchBarProps>(function SearchBar(\n {\n open,\n onClose,\n onClear,\n children,\n value,\n placeholder = 'Search…',\n editable = true,\n inline = false,\n closeLabel = 'Cancel',\n style,\n inputStyle,\n ...inputProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const inputRef = useRef<TextInput>(null);\n\n useImperativeHandle(ref, () => inputRef.current as TextInput, []);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const id = requestAnimationFrame(() => inputRef.current?.focus());\n\n return () => cancelAnimationFrame(id);\n }, [open]);\n\n if (!open) {\n return null;\n }\n\n const disabled = !editable;\n const hasValue = typeof value === 'string' && value.length > 0;\n\n const barBg = inline ? 'transparent' : theme.headerbarBgColor;\n const barBorder = inline ? 'transparent' : theme.headerbarShadeColor;\n\n return (\n <RNView style={style}>\n <RNView style={{ flexDirection: 'row', alignItems: 'center', gap: theme.space1 }}>\n <RNView\n style={{\n flex: 1,\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingVertical: theme.space1,\n paddingHorizontal: theme.space2,\n backgroundColor: barBg,\n borderBottomWidth: 1,\n borderBottomColor: barBorder,\n opacity: disabled ? theme.opacityDisabled : 1,\n }}\n >\n <RNText\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{ opacity: theme.opacityDim, fontSize: theme.fontSizeBody }}\n >\n {'🔍'}\n </RNText>\n\n <RNTextInput\n ref={inputRef}\n editable={editable}\n value={value}\n placeholder={placeholder}\n placeholderTextColor={dimColor(theme.windowFgColor, theme.opacityDim)}\n style={[\n {\n flex: 1,\n padding: 0,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n color: theme.windowFgColor,\n } satisfies TextStyle,\n inputStyle,\n ]}\n {...inputProps}\n />\n\n {hasValue && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Clear search\"\n disabled={disabled}\n hitSlop={8}\n onPress={() => {\n onClear?.();\n inputRef.current?.focus();\n }}\n style={({ pressed }) => ({\n width: 24,\n height: 24,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: theme.windowFgColor }}>\n {'×'}\n </RNText>\n </Pressable>\n )}\n </RNView>\n\n {onClose && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={closeLabel}\n onPress={onClose}\n hitSlop={8}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n color: theme.accentColor,\n }}\n >\n {closeLabel}\n </RNText>\n </Pressable>\n )}\n </RNView>\n\n {children && (\n <RNView\n style={{\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: theme.space1,\n padding: theme.space1,\n paddingHorizontal: theme.space2,\n backgroundColor: barBg,\n borderBottomWidth: 1,\n borderBottomColor: barBorder,\n }}\n >\n {children}\n </RNView>\n )}\n </RNView>\n );\n});\n","import { Children, isValidElement, type ReactNode } from 'react';\n\n/** Recursively count items whose `label` prop matches `filter` (case-insensitive). */\nexport function countMatchingItems(children: ReactNode, filter: string): number {\n let count = 0;\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n return;\n }\n\n const props = child.props as Record<string, unknown>;\n\n if (typeof props.label === 'string') {\n if (props.label.toLowerCase().includes(filter.toLowerCase())) {\n count++;\n }\n } else if (props.children) {\n count += countMatchingItems(props.children as ReactNode, filter);\n }\n });\n\n return count;\n}\n\n/**\n * Whether a single top-level `Sidebar` child would render something under\n * `filter` — a bare `SidebarItem` if its own `label` matches, a\n * `SidebarSection` (or anything else with `children`) if any descendant\n * matches. Used to decide which children get a `Separator` between them, so\n * a filtered-out (null-rendering) item doesn't still claim a divider slot.\n */\nexport function isChildVisible(child: ReactNode, filter: string): boolean {\n if (!filter) {\n return true;\n }\n\n if (!isValidElement(child)) {\n return true;\n }\n\n const props = child.props as Record<string, unknown>;\n\n if (typeof props.label === 'string') {\n return props.label.toLowerCase().includes(filter.toLowerCase());\n }\n\n if (props.children) {\n return countMatchingItems(props.children as ReactNode, filter) > 0;\n }\n\n return true;\n}\n","import { Children, createContext, Fragment, forwardRef, type ReactNode, useContext } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView, ScrollView } from 'react-native';\n\nimport { Separator } from '@/components/Separator';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { isChildVisible } from './filterUtils';\n\n// ─── Contexts ───────────────────────────────────────────────────────────────\n\n/** Provides the collapsed state to all descendant `SidebarSection`/`SidebarItem`. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport const SidebarCollapsedContext = createContext(false);\n\n/** Returns `true` when the nearest `Sidebar` is in collapsed (icon-only/rail) mode. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useSidebarCollapsed() {\n return useContext(SidebarCollapsedContext);\n}\n\n/** Provides the active filter string to all descendant `SidebarItem`/`SidebarSection`. */\n// eslint-disable-next-line react-refresh/only-export-components\nexport const SidebarFilterContext = createContext('');\n\n// ─── Props ──────────────────────────────────────────────────────────────────\n\nexport interface SidebarProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /**\n * When `true`, collapses the sidebar to icon-only (rail) mode. Labels and\n * section titles are hidden.\n */\n collapsed?: boolean;\n /**\n * Controlled filter string. `SidebarItem`s whose `label` does not match\n * (case-insensitive substring) are hidden, and empty `SidebarSection`s are\n * hidden entirely. Unlike the web version this never renders a search\n * input itself — pair it with your own `TextField` (or the future\n * `SearchBar` port) and drive this prop from its value.\n */\n filter?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Lateral navigation panel following the Adwaita `.navigation-sidebar` style.\n *\n * Compose with `SidebarSection` (named groups) and `SidebarItem` (rows).\n * Consecutive top-level children get a `Separator` inserted between them —\n * same divider-on-index-boundary technique `BoxedList` uses for its rows —\n * standing in for the web version's `.section + .section` adjacent-sibling\n * CSS rule, which RN has no equivalent of.\n *\n * Dropped relative to `@gnome-ui/react`'s `Sidebar`: `searchable` (would\n * pull in a `SearchBar`, not yet ported to this package — use `filter` with\n * your own input instead), `mode`/auto page-layout switch (depends on the\n * web-only `useBreakpoint` hook), `variant` (tinted/blurred backgrounds —\n * the blurred variant needs a native blur view this package doesn't depend\n * on), and the `<nav>` landmark role (RN's `AccessibilityRole` union has no\n * \"navigation\" value).\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const Sidebar = forwardRef<View, SidebarProps>(function Sidebar(\n { children, collapsed = false, filter = '', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const isFilterActive = filter.length > 0;\n const items = Children.toArray(children)\n .filter(Boolean)\n .filter((child) => isChildVisible(child, filter));\n\n const hasMatches = !isFilterActive || items.length > 0;\n\n return (\n <SidebarCollapsedContext.Provider value={collapsed}>\n <SidebarFilterContext.Provider value={filter}>\n <RNView\n ref={ref}\n style={[\n {\n flexShrink: 0,\n width: collapsed ? theme.layoutSidebarRailWidth : theme.layoutSidebarDefaultWidth,\n backgroundColor: theme.sidebarBgColor,\n borderRightWidth: 1,\n borderRightColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <ScrollView contentContainerStyle={{ padding: theme.space1 }}>\n {isFilterActive && !hasMatches ? (\n <Text\n variant=\"caption\"\n color=\"dim\"\n style={{ textAlign: 'center', padding: theme.space4 }}\n >\n No items match your search.\n </Text>\n ) : (\n items.map((child, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: children have no natural stable id\n <Fragment key={i}>\n {i > 0 && (\n <Separator\n testID=\"sidebar-separator\"\n style={{ marginVertical: theme.space1 }}\n />\n )}\n {child}\n </Fragment>\n ))\n )}\n </ScrollView>\n </RNView>\n </SidebarFilterContext.Provider>\n </SidebarCollapsedContext.Provider>\n );\n});\n","import { forwardRef, type ReactNode, useContext } from 'react';\nimport type { PressableProps, StyleProp, TextStyle, View, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nimport { SidebarFilterContext, useSidebarCollapsed } from './Sidebar';\n\nexport interface SidebarItemProps extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Primary label. */\n label: string;\n /**\n * Icon placed at the leading edge. Rendered as-is — size/color it\n * yourself. Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`;\n * this package has no SVG icon system, so it's a plain `ReactNode` here,\n * same as `ActionRow`'s `leading` and `TabItem`'s `icon`.\n */\n icon?: ReactNode;\n /** Marks this item as the currently active view. */\n active?: boolean;\n /** Trailing widget — badge, count, button, icon… */\n suffix?: ReactNode;\n disabled?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Individual navigation row inside a `Sidebar` or `SidebarSection`.\n *\n * Automatically hidden (renders nothing) when the nearest `Sidebar`'s\n * `filter` is active and `label` doesn't match. In collapsed (rail) mode\n * the label and suffix are hidden and the icon centers — `label` still\n * reaches screen readers via `accessibilityLabel`.\n *\n * Dropped relative to `@gnome-ui/react`'s `SidebarItem`: `tooltip` (no\n * `Tooltip` port yet, and RN's touch-first model has no hover to trigger\n * one from), `menuItems` (context menu — no portal/positioning primitive\n * exists in this package yet), and `onDrop`/`acceptTypes` (HTML5\n * drag-and-drop has no RN equivalent without a gesture-handler dependency\n * this package doesn't have).\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const SidebarItem = forwardRef<View, SidebarItemProps>(function SidebarItem(\n { label, icon, active = false, suffix, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const collapsed = useSidebarCollapsed();\n const filterValue = useContext(SidebarFilterContext);\n\n const isFiltered =\n filterValue.length > 0 && !label.toLowerCase().includes(filterValue.toLowerCase());\n\n if (isFiltered) {\n return null;\n }\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => [\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: active\n ? theme.accentBgColor\n : pressed\n ? theme.hoverOverlay\n : 'transparent',\n },\n collapsed && { justifyContent: 'center', paddingHorizontal: 0 },\n style,\n ]}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0, opacity: active ? 1 : 0.85 }}>{icon}</RNView>}\n\n {!collapsed && (\n <Text\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n flex: 1,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: active ? theme.accentFgColor : theme.sidebarFgColor,\n }}\n >\n {label}\n </Text>\n )}\n\n {!collapsed && suffix && <RNView style={{ flexShrink: 0 }}>{suffix}</RNView>}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode, useContext, useImperativeHandle, useState } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Pressable, View as RNView } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\nimport { countMatchingItems } from './filterUtils';\nimport { SidebarFilterContext, useSidebarCollapsed } from './Sidebar';\n\nexport interface SidebarSectionHandle {\n expand: () => void;\n collapse: () => void;\n toggle: () => void;\n}\n\nexport interface SidebarSectionProps extends Omit<ViewProps, 'style'> {\n /** Section heading. Omit for an untitled section (e.g. the first group in a sidebar). */\n title?: string;\n /** Icon rendered left of the title. Rendered as-is — size/color it yourself. */\n icon?: ReactNode;\n /** Whether the section body can be toggled open/closed. Defaults to `false`. */\n collapsible?: boolean;\n /** Initial open state when `collapsible` is true. Defaults to `true`. */\n defaultOpen?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Named group of `SidebarItem` entries inside a `Sidebar`.\n *\n * When `collapsible`, the body toggles via the header `Pressable` or\n * imperatively via a `ref` (`expand`/`collapse`/`toggle`) — same\n * `useImperativeHandle` shape as the web version's `SidebarSectionHandle`.\n * The body stays mounted and toggles `display: 'none'` rather than\n * unmounting, the same \"stays mounted but hidden\" approach `TabPanel` uses,\n * instead of porting the web version's animated CSS-grid collapse (no\n * established animated-height pattern exists yet in this package).\n *\n * In rail (`collapsed`) mode the header — and with it the collapse toggle —\n * is hidden and the body is always shown, matching the web version's rail\n * behavior. When a `Sidebar` filter is active and no descendant matches,\n * the whole section renders nothing.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Sidebar.html\n */\nexport const SidebarSection = forwardRef<SidebarSectionHandle, SidebarSectionProps>(\n function SidebarSection(\n {\n title,\n icon,\n collapsible = false,\n defaultOpen = true,\n open: controlledOpen,\n onOpenChange,\n children,\n style,\n ...viewProps\n },\n ref,\n ) {\n const theme = useGnomeTheme();\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n\n const collapsed = useSidebarCollapsed();\n const filterValue = useContext(SidebarFilterContext);\n\n const setAndNotify = (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n\n onOpenChange?.(next);\n };\n\n useImperativeHandle(ref, () => ({\n expand: () => setAndNotify(true),\n collapse: () => setAndNotify(false),\n toggle: () => setAndNotify(!open),\n }));\n\n const hasVisibleChildren =\n filterValue.length === 0 || countMatchingItems(children, filterValue) > 0;\n\n if (!hasVisibleChildren) {\n return null;\n }\n\n const isOpen = collapsed ? true : open;\n const showHeader = !collapsed && !!(title || icon);\n\n const header = (title || icon) && (\n <RNView\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space1,\n paddingVertical: 2,\n marginTop: 4,\n marginBottom: 2,\n }}\n >\n {icon && <RNView style={{ flexShrink: 0, opacity: 0.7 }}>{icon}</RNView>}\n {title && (\n <Text variant=\"caption-heading\" color=\"dim\" style={{ flex: 1 }} numberOfLines={1}>\n {title}\n </Text>\n )}\n {collapsible && (\n <Text variant=\"caption\" color=\"dim\" style={{ flexShrink: 0 }}>\n {open ? '▾' : '▸'}\n </Text>\n )}\n </RNView>\n );\n\n return (\n <RNView style={style} {...viewProps}>\n {showHeader &&\n (collapsible ? (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ expanded: open }}\n accessibilityLabel={title}\n onPress={() => setAndNotify(!open)}\n >\n {header}\n </Pressable>\n ) : (\n header\n ))}\n\n <RNView\n accessible\n accessibilityRole=\"list\"\n style={{ display: isOpen ? 'flex' : 'none', gap: 2 }}\n >\n {children}\n </RNView>\n </RNView>\n );\n },\n);\n","import { useEffect, useRef } from 'react';\nimport type { DimensionValue, StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing, View as RNView } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport type SkeletonVariant = 'rect' | 'circle' | 'text';\n\nexport interface SkeletonProps extends Omit<ViewProps, 'style'> {\n /** Shape of the placeholder. Defaults to `\"rect\"`. */\n variant?: SkeletonVariant;\n /** Width for rectangular placeholders. Defaults to `\"100%\"`. */\n width?: DimensionValue;\n /** Height for rectangular placeholders. Defaults to `16`. */\n height?: DimensionValue;\n /** Diameter for circular placeholders. Defaults to `40`. */\n size?: number;\n /** Number of rows for text placeholders. Defaults to `3`. */\n lines?: number;\n /** Enables the pulse animation. Respects `useReducedMotion()`. Defaults to `true`. */\n animated?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Loading placeholder for content-shaped skeleton screens.\n *\n * GNOME HIG recommends `Spinner` or `ProgressBar` for loading states; this\n * is a pragmatic web-style extension for layouts that benefit from\n * placeholder shape, ported as-is from `@gnome-ui/react`.\n *\n * The web version's shimmer is a `linear-gradient` swept across the shape\n * via `transform: translateX()`; this package has no gradient dependency\n * (no `expo-linear-gradient`/`react-native-linear-gradient` in its\n * dependency tree, and adding one for a single component would be scope\n * creep), so the animation is a plain opacity pulse instead — animating\n * `theme.skeletonBaseColor`'s own opacity between `1` and `0.5` on a\n * 1.4s round trip, the same cycle length as the web shimmer. This is a\n * common RN-idiomatic substitute for a CSS shimmer (compare Tailwind's own\n * `animate-pulse` utility, which uses the identical technique). Unlike\n * `Spinner` (slows) and `ProgressBar` (stops one state, slows the other),\n * `useReducedMotion()` here fully disables the pulse and shows a static\n * base color — mirroring the source CSS's own\n * `@media (prefers-reduced-motion: reduce) { animation: none }`, which has\n * no partial-motion in-between state to preserve.\n *\n * `theme.skeletonBaseColor` already resolves correctly per color scheme\n * (unlike `Spinner`'s track color, which the source CSS never actually\n * tokenizes), so no `useResolvedColorScheme()` branching is needed here.\n *\n * `accessible={false}` mirrors the web version's `aria-hidden=\"true\"` — a\n * loading placeholder carries no information a screen reader user needs,\n * same reasoning `Separator` already established for a purely decorative\n * element.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/progress.html\n */\nexport const Skeleton = ({\n variant = 'rect',\n width = '100%',\n height = 16,\n size = 40,\n lines = 3,\n animated = true,\n style,\n ...viewProps\n}: SkeletonProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n const pulse = useRef(new Animated.Value(1)).current;\n\n const isPulsing = animated && !reducedMotion;\n\n useEffect(() => {\n if (!isPulsing) {\n pulse.setValue(1);\n\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n const easing = Easing.bezier(x1, y1, x2, y2);\n\n const animation = Animated.loop(\n Animated.sequence([\n Animated.timing(pulse, { toValue: 0.5, duration: 700, easing, useNativeDriver: true }),\n Animated.timing(pulse, { toValue: 1, duration: 700, easing, useNativeDriver: true }),\n ]),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [isPulsing, pulse, theme.easingDefault]);\n\n if (variant === 'text') {\n const lineCount = Math.max(1, Math.floor(lines));\n\n return (\n <RNView accessible={false} style={[{ gap: 8 }, style]} {...viewProps}>\n {Array.from({ length: lineCount }, (_, index) => (\n <Animated.View\n // biome-ignore lint/suspicious/noArrayIndexKey: lines have no natural stable id\n key={index}\n style={{\n width: index === lineCount - 1 ? '60%' : '100%',\n height: 12,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.skeletonBaseColor,\n opacity: pulse,\n }}\n />\n ))}\n </RNView>\n );\n }\n\n const shapeStyle: ViewStyle =\n variant === 'circle'\n ? { width: size, height: size, borderRadius: size / 2 }\n : { width, height, borderRadius: theme.radiusMd };\n\n return (\n <Animated.View\n accessible={false}\n style={[shapeStyle, { backgroundColor: theme.skeletonBaseColor, opacity: pulse }, style]}\n {...viewProps}\n />\n );\n};\n","import { useCallback, useMemo, useState } from 'react';\nimport type {\n AccessibilityActionEvent,\n GestureResponderEvent,\n LayoutChangeEvent,\n StyleProp,\n ViewProps,\n ViewStyle,\n} from 'react-native';\nimport { PanResponder, Text, View } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nconst TRACK_HEIGHT = 6;\nconst THUMB_SIZE = 22;\nconst TICK_SIZE = 4;\n\nexport interface SliderMark {\n value: number;\n label?: string;\n}\n\nexport interface SliderProps extends Omit<ViewProps, 'style'> {\n /** Current value. Must be between `min` and `max`. */\n value: number;\n /** Called when the value changes. */\n onChange: (value: number) => void;\n /** Minimum value. Defaults to `0`. */\n min?: number;\n /** Maximum value. Defaults to `100`. */\n max?: number;\n /**\n * Granularity of each step.\n * - The `adjustable` accessibility action (VoiceOver/TalkBack swipe up/down) moves by one step.\n * Defaults to `1`.\n */\n step?: number;\n /** Disables the control. */\n disabled?: boolean;\n /**\n * Marks to display along the track.\n * Each mark can have an optional label rendered below the track.\n */\n marks?: SliderMark[];\n /** Accessible label. Required — RN has no visible-label association to fall back on. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.min(max, Math.max(min, v));\n}\n\nfunction snapToStep(v: number, min: number, step: number, decimals: number) {\n return parseFloat((Math.round((v - min) / step) * step + min).toFixed(decimals));\n}\n\nfunction countDecimals(n: number) {\n const s = n.toString();\n const dot = s.indexOf('.');\n\n return dot === -1 ? 0 : s.length - dot - 1;\n}\n\n/**\n * Draggable range slider following the Adwaita `GtkScale` pattern.\n *\n * - Touch drag (via `PanResponder`) sets the value continuously.\n * - `accessibilityRole=\"adjustable\"` + `onAccessibilityAction` handles the\n * \"increment\"/\"decrement\" actions VoiceOver (swipe up/down) and TalkBack\n * generate for an adjustable element — RN's native analog of the web\n * version's ← / → keyboard stepping, since a touch-first device has no\n * keyboard to drive `ArrowLeft`/`ArrowRight`/`Home`/`End`/`PageUp`/\n * `PageDown` with. Those bigger/edge jumps have no equivalent gesture on\n * either platform's screen reader, so only single-step increment/decrement\n * is ported.\n * - Optional tick marks with labels.\n * - Fills the track from the left up to the thumb (accent colour).\n *\n * RN's `transform` only accepts pixel offsets, not the CSS `%` units the\n * web version's `left: X%; transform: translate(-50%, -50%)` centering\n * trick relies on — so the thumb and tick marks are positioned with a\n * plain pixel `left` (`(pct / 100) * trackWidth - size / 2`, measured via\n * `onLayout`) instead, and vertical centering comes from the track's own\n * `justifyContent: 'center'` rather than a transform.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/sliders.html\n */\nexport const Slider = ({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n marks,\n accessibilityLabel,\n style,\n onLayout,\n ...viewProps\n}: SliderProps) => {\n const theme = useGnomeTheme();\n const [trackWidth, setTrackWidth] = useState(0);\n const [labelWidths, setLabelWidths] = useState<Record<number, number>>({});\n\n const dp = countDecimals(step);\n const clamped = clamp(value, min, max);\n const pct = ((clamped - min) / (max - min)) * 100;\n\n const handleTrackLayout = useCallback(\n (event: LayoutChangeEvent) => {\n setTrackWidth(event.nativeEvent.layout.width);\n onLayout?.(event);\n },\n [onLayout],\n );\n\n const commit = useCallback(\n (locationX: number) => {\n if (disabled || trackWidth <= 0) {\n return;\n }\n\n const raw = (locationX / trackWidth) * (max - min) + min;\n\n onChange(clamp(snapToStep(raw, min, step, dp), min, max));\n },\n [disabled, trackWidth, min, max, step, dp, onChange],\n );\n\n const panResponder = useMemo(\n () =>\n PanResponder.create({\n onStartShouldSetPanResponder: () => !disabled,\n onMoveShouldSetPanResponder: () => !disabled,\n onPanResponderGrant: (event: GestureResponderEvent) => commit(event.nativeEvent.locationX),\n onPanResponderMove: (event: GestureResponderEvent) => commit(event.nativeEvent.locationX),\n }),\n [disabled, commit],\n );\n\n const handleAccessibilityAction = useCallback(\n (event: AccessibilityActionEvent) => {\n if (disabled) {\n return;\n }\n\n switch (event.nativeEvent.actionName) {\n case 'increment':\n onChange(clamp(snapToStep(value + step, min, step, dp), min, max));\n break;\n case 'decrement':\n onChange(clamp(snapToStep(value - step, min, step, dp), min, max));\n break;\n }\n },\n [disabled, value, step, min, max, dp, onChange],\n );\n\n const hasMarks = marks && marks.length > 0;\n const hasLabels = hasMarks && marks.some((m) => m.label);\n\n const thumbLeft = (pct / 100) * trackWidth - THUMB_SIZE / 2;\n\n return (\n <View\n style={[{ width: '100%', paddingTop: 10, paddingBottom: hasLabels ? 0 : 10 }, style]}\n {...viewProps}\n >\n <View\n onLayout={handleTrackLayout}\n accessible\n accessibilityRole=\"adjustable\"\n accessibilityLabel={accessibilityLabel}\n accessibilityValue={{ min, max, now: clamped }}\n accessibilityState={{ disabled }}\n accessibilityActions={[\n { name: 'increment', label: 'increment' },\n { name: 'decrement', label: 'decrement' },\n ]}\n onAccessibilityAction={handleAccessibilityAction}\n style={{\n justifyContent: 'center',\n height: THUMB_SIZE,\n opacity: disabled ? theme.opacityDisabled : 1,\n }}\n {...panResponder.panHandlers}\n >\n <View\n pointerEvents=\"none\"\n style={{\n width: '100%',\n height: TRACK_HEIGHT,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.cardShadeColor,\n overflow: 'hidden',\n }}\n >\n <View\n style={{\n height: '100%',\n width: `${pct}%`,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.accentBgColor,\n }}\n />\n </View>\n\n <View\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: thumbLeft,\n width: THUMB_SIZE,\n height: THUMB_SIZE,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.accentBgColor,\n borderWidth: 2,\n borderColor: theme.windowBgColor,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 1 },\n shadowOpacity: 0.25,\n shadowRadius: 3,\n elevation: 3,\n }}\n />\n\n {hasMarks &&\n marks.map((m) => {\n const mPct = ((clamp(m.value, min, max) - min) / (max - min)) * 100;\n const tickLeft = (mPct / 100) * trackWidth - TICK_SIZE / 2;\n\n return (\n <View\n key={m.value}\n pointerEvents=\"none\"\n importantForAccessibility=\"no\"\n style={{\n position: 'absolute',\n left: tickLeft,\n width: TICK_SIZE,\n height: TICK_SIZE,\n borderRadius: TICK_SIZE / 2,\n backgroundColor: theme.windowBgColor,\n }}\n />\n );\n })}\n </View>\n\n {hasLabels && (\n <View\n importantForAccessibility=\"no\"\n style={{ position: 'relative', width: '100%', height: 20, marginTop: 6 }}\n >\n {marks.map((m) => {\n const mPct = ((clamp(m.value, min, max) - min) / (max - min)) * 100;\n const centerX = (mPct / 100) * trackWidth;\n const labelWidth = labelWidths[m.value] ?? 0;\n\n return (\n // Positioned by a pixel `left` computed from the label's own\n // measured width (0 until its first `onLayout`, so it starts\n // left-aligned to the mark and snaps to centered a frame\n // later) — a zero-width `View` with `alignItems: 'center'`\n // was tried first hoping Yoga would center an overflowing\n // child around it the way a CSS `%`-of-self `transform:\n // translateX(-50%)` does, but the iOS Simulator screenshot\n // check (never skip it) showed the labels not rendering at\n // all, so self-measurement replaced it.\n <Text\n key={m.value}\n numberOfLines={1}\n onLayout={(event) => {\n const {\n layout: { width },\n } = event.nativeEvent;\n\n setLabelWidths((prev) =>\n prev[m.value] === width ? prev : { ...prev, [m.value]: width },\n );\n }}\n style={{\n position: 'absolute',\n left: centerX - labelWidth / 2,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeCaption,\n color: theme.windowFgColor,\n opacity: theme.opacityDim,\n }}\n >\n {m.label}\n </Text>\n );\n })}\n </View>\n )}\n </View>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\n\nconst SIZES: Record<SpinnerSize, { dimension: number; borderWidth: number }> = {\n sm: { dimension: 16, borderWidth: 2 },\n md: { dimension: 24, borderWidth: 2.5 },\n lg: { dimension: 36, borderWidth: 3 },\n};\n\nexport interface SpinnerProps extends Omit<ViewProps, 'style'> {\n /** Size of the spinner. Defaults to `\"md\"`. */\n size?: SpinnerSize;\n /**\n * Accessible label announced by screen readers. Defaults to\n * `\"Loading…\"`. Set to `\"\"` to silence if a sibling label is present.\n */\n label?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Indeterminate loading indicator following the Adwaita spinner style.\n *\n * Rebuilt on `Animated.View` rather than ported from `@gnome-ui/react`'s\n * pure-CSS `@keyframes spin` animation: the ring itself reuses the same\n * per-side-border trick the CSS does (`borderColor` for the track,\n * `borderTopColor` for the accent-colored \"head\" of the spinner, on a\n * `borderRadius: 50%` circle) — that part translates directly, since RN's\n * `View` supports independent per-side border colors too. The rotation\n * itself is an `Animated.loop`d `Animated.timing` driving a `rotate`\n * transform, `useNativeDriver: true` since only a transform is animated.\n *\n * `useReducedMotion()` mirrors the source CSS's own\n * `@media (prefers-reduced-motion: reduce) { animation-duration: 2s }` —\n * slowed to 2s, not stopped outright, exactly matching the web behavior\n * rather than dropping the animation entirely.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"progressbar\"` is the closest match for an\n * indeterminate loading indicator and is what's used here — omitting\n * `accessibilityValue` is RN's equivalent of omitting `aria-valuenow` for\n * an indeterminate progress bar. `@gnome-ui/react`'s two hardcoded\n * per-color-scheme track colors (the `--gnome-spinner-track-color` CSS\n * variable is referenced but never actually defined in `@gnome-ui/core`'s\n * tokens, so the CSS fallback value is always what renders) are ported as\n * the same hardcoded `rgba()` pair, branched on `useResolvedColorScheme()`\n * — the same pattern `Switch`/`Checkbox`/`RadioButton` already use for\n * colors the source CSS hardcodes rather than tokenizes.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/style-classes.html\n */\nexport const Spinner = ({ size = 'md', label = 'Loading…', style, ...viewProps }: SpinnerProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const spin = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n spin.setValue(0);\n\n const animation = Animated.loop(\n Animated.timing(spin, {\n toValue: 1,\n duration: reducedMotion ? 2000 : 750,\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n\n animation.start();\n\n return () => animation.stop();\n }, [spin, reducedMotion]);\n\n const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'] });\n const { dimension, borderWidth } = SIZES[size];\n const trackColor = scheme === 'dark' ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)';\n\n return (\n <Animated.View\n accessible\n accessibilityRole=\"progressbar\"\n accessibilityLabel={label || undefined}\n accessibilityElementsHidden={label === ''}\n importantForAccessibility={label === '' ? 'no-hide-descendants' : 'yes'}\n style={[\n {\n width: dimension,\n height: dimension,\n borderRadius: dimension / 2,\n borderWidth,\n borderColor: trackColor,\n borderTopColor: theme.accentColor,\n transform: [{ rotate }],\n },\n style,\n ]}\n {...viewProps}\n />\n );\n};\n","import { forwardRef, useEffect, useRef } from 'react';\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface SwitchProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {\n /** Whether the switch is on. */\n value: boolean;\n /** Called with the next value when the switch is pressed. */\n onValueChange?: (value: boolean) => void;\n /** Accessible label. Required when no visible label is associated. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nconst TRACK_WIDTH = 56;\nconst TRACK_HEIGHT = 28;\nconst THUMB_SIZE = 20;\nconst THUMB_INSET = 3;\n/** Matches `@gnome-ui/react`'s `.switch:checked::before { transform: translateX(28px) }`. */\nconst THUMB_TRAVEL = 28;\n\n/**\n * On/off toggle following the Adwaita switch style.\n *\n * Rebuilt on `Pressable`/`Animated.View` rather than ported from\n * `@gnome-ui/react`'s `<input type=\"checkbox\" role=\"switch\">`: RN has no\n * checkbox primitive to style, and the platform-supplied `Switch` can't be\n * skinned to match Adwaita, so the track and thumb are drawn by hand.\n * `value`/`onValueChange` (not `checked`/`onChange`) mirror RN's own\n * `Switch` API, which is the ecosystem convention this component overlaps\n * with — it's fully controlled, with no `defaultValue` escape hatch.\n *\n * Two of `Switch.module.css`'s colors are hardcoded per color scheme\n * inside a component-level `@media (prefers-color-scheme: dark)` block\n * rather than driven by a semantic token, so — unlike `Button`/`Link`/\n * `TextField`, which read a single token that already resolves correctly\n * per theme — the unchecked track/thumb colors here branch explicitly on\n * `useResolvedColorScheme()` to match. Track background/border color\n * animate (mirroring the CSS `transition` on `.switch`); the thumb's own\n * fill color does not, since the source CSS only transitions its\n * `transform`, not its `background-color`.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/switches.html\n */\nexport const Switch = forwardRef<View, SwitchProps>(function Switch(\n { value, onValueChange, disabled, style, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const contrast = useResolvedContrast();\n const progress = useRef(new Animated.Value(value ? 1 : 0)).current;\n const isInitialMount = useRef(true);\n\n useEffect(() => {\n // The initial `Animated.Value` above already matches `value` — skip\n // animating into a state the switch is already rendering, so it never\n // plays a transition before the user has touched it.\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: value ? 1 : 0,\n duration: theme.durationFast,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: false,\n }).start();\n }, [value, progress, theme.durationFast, theme.easingDefault]);\n\n const trackColorOff = colorScheme === 'dark' ? theme.dark2 : theme.light4;\n const thumbColorOff = colorScheme === 'dark' ? theme.light3 : '#fff';\n\n const backgroundColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [trackColorOff, theme.accentBgColor],\n });\n const borderColor = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [theme.borderSubtle, theme.accentBgColor],\n });\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: value, disabled: !!disabled }}\n onPress={() => onValueChange?.(!value)}\n style={[{ opacity: disabled ? theme.opacityDisabled : 1 }, style]}\n {...pressableProps}\n >\n <Animated.View\n style={{\n width: TRACK_WIDTH,\n height: TRACK_HEIGHT,\n borderRadius: theme.radiusPill,\n borderWidth: contrast === 'more' ? 2 : 1,\n borderColor,\n backgroundColor,\n }}\n >\n <Animated.View\n style={[\n {\n position: 'absolute',\n top: THUMB_INSET,\n left: THUMB_INSET,\n width: THUMB_SIZE,\n height: THUMB_SIZE,\n borderRadius: theme.radiusPill,\n backgroundColor: value ? '#fff' : thumbColorOff,\n transform: [\n {\n translateX: progress.interpolate({\n inputRange: [0, 1],\n outputRange: [0, THUMB_TRAVEL],\n }),\n },\n ],\n },\n contrast !== 'more' && {\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 1 },\n shadowOpacity: 0.25,\n shadowRadius: 3,\n elevation: 2,\n },\n ]}\n />\n </Animated.View>\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { ScrollView, ScrollViewProps, StyleProp, ViewStyle } from 'react-native';\nimport { ScrollView as RNScrollView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface TabBarProps extends Omit<ScrollViewProps, 'style' | 'horizontal' | 'children'> {\n children?: ReactNode;\n /** Accessible label for the tab list. */\n accessibilityLabel?: string;\n /**\n * Removes the header-bar background so the tab bar blends into any surface.\n * Use when placing the bar inside a card, content area, or custom container.\n * Mirrors the `.inline` style class.\n */\n inline?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Horizontal, horizontally-scrollable tab bar that holds `TabItem` elements.\n *\n * Rebuilt on a horizontal `ScrollView` rather than ported from\n * `@gnome-ui/react`'s `overflow-x: auto` `<div role=\"tablist\">` — RN's\n * `AccessibilityRole` union does include `\"tablist\"`, so that semantic\n * carries over directly, but the web version's roving-tabindex ← → / Home /\n * End keyboard navigation doesn't: RN's touch-first focus model has no\n * per-app arrow-key convention to port, so it's dropped here rather than\n * faking it.\n *\n * `style={{ flexGrow: 0 }}` on the `ScrollView` is deliberate, not\n * decorative — a horizontal `ScrollView` with no explicit `flexGrow` can\n * stretch to fill the cross-axis of whatever flex column it's placed in\n * (confirmed the hard way debugging the example app's own tab-like\n * `ControlsBar`), so it's baked in here once rather than left for every\n * consumer to rediscover.\n *\n * @see https://developer.gnome.org/hig/patterns/nav/tabs.html\n */\nexport const TabBar = forwardRef<ScrollView, TabBarProps>(function TabBar(\n { children, inline = false, accessibilityLabel = 'Tabs', style, ...scrollViewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <RNScrollView\n ref={ref}\n horizontal\n showsHorizontalScrollIndicator={false}\n contentInsetAdjustmentBehavior=\"never\"\n accessible\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n style={[\n {\n flexGrow: 0,\n backgroundColor: inline ? 'transparent' : theme.headerbarBgColor,\n borderBottomWidth: inline ? 0 : 1,\n borderBottomColor: theme.headerbarBorderColor,\n },\n style,\n ]}\n contentContainerStyle={{\n flexDirection: 'row',\n alignItems: 'stretch',\n paddingHorizontal: theme.space1,\n gap: 2,\n minHeight: 40,\n }}\n {...scrollViewProps}\n >\n {children}\n </RNScrollView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, TextStyle, View } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface TabItemProps extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Tab label. */\n label: string;\n /**\n * Icon placed before the label. Rendered as-is — size/color it yourself.\n * Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`; this package\n * has no SVG icon system (see [[react-native-port-status]]), so it's a\n * plain `ReactNode` here instead, same as `ActionRow`'s `leading`.\n */\n icon?: ReactNode;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user taps the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n /** Optional count shown as a small badge next to the label. Values above 99 render as \"99+\". */\n count?: number;\n disabled?: boolean;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n *\n * Web's `panelId` (which sets `aria-controls`) is dropped — RN has no ARIA\n * relationship attributes, so there's nothing for it to wire up; keep the\n * tab ↔ panel link in your own state instead. The count badge is a small\n * inline pill rather than the web version's separate `Badge` component,\n * since `Badge` hasn't been ported to this package yet and pulling in a\n * whole new component just for this one pill would be scope creep.\n *\n * The close button is a nested `Pressable` inside the tab's own\n * `Pressable` — unlike the web version, no explicit \"stop propagation\" is\n * needed: RN's touch responder system grants an in-progress touch to the\n * innermost view that claims it, so pressing the close button never also\n * fires the outer tab's `onPress`. It also gets a `hitSlop` the web\n * version has no equivalent of, since its 18×18 visual size is well under\n * the ~44pt touch target guidance both major mobile platforms recommend.\n *\n * The label `Text` deliberately has no `flex: 1` (unlike the web version's\n * `.tabLabel`) — the outer `Pressable`'s width here is content-driven\n * (`minWidth`/`maxWidth`, not a definite width), and giving a `flex: 1`\n * child to a row whose own width isn't definite collapses that child to a\n * near-zero width in Yoga (confirmed visually: every label truncated to\n * 3-4 characters despite ample room). CSS flexbox resolves this fine\n * because browsers can grow a flex child within an intrinsically-sized\n * container; Yoga can't. `numberOfLines`/`ellipsizeMode` alone are enough\n * to truncate genuinely-too-long labels against `maxWidth`.\n */\nexport const TabItem = forwardRef<View, TabItemProps>(function TabItem(\n {\n label,\n icon,\n active = false,\n onClose,\n closeLabel = 'Close tab',\n count,\n disabled,\n ...pressableProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => ({\n position: 'relative',\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space1,\n paddingHorizontal: theme.space2,\n minWidth: 80,\n maxWidth: 200,\n minHeight: 40,\n borderRadius: theme.radiusMd,\n opacity: disabled ? theme.opacityDisabled : active ? 1 : 0.7,\n backgroundColor: active\n ? theme.activeOverlay\n : pressed\n ? theme.hoverOverlay\n : 'transparent',\n })}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0 }}>{icon}</RNView>}\n\n <RNText\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: theme.headerbarFgColor,\n }}\n >\n {label}\n </RNText>\n\n {count !== undefined && (\n <RNView\n style={{\n flexShrink: 0,\n minWidth: 18,\n height: 18,\n paddingHorizontal: 5,\n borderRadius: 9,\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: theme.accentBgColor,\n }}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: 11,\n fontWeight: '600' as TextStyle['fontWeight'],\n color: theme.accentFgColor,\n }}\n >\n {count > 99 ? '99+' : count}\n </RNText>\n </RNView>\n )}\n\n {onClose && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={closeLabel}\n hitSlop={8}\n onPress={onClose}\n style={({ pressed }) => ({\n flexShrink: 0,\n width: 18,\n height: 18,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: 15,\n lineHeight: 16,\n color: theme.headerbarFgColor,\n }}\n >\n {'×'}\n </RNText>\n </Pressable>\n )}\n\n {active && (\n <RNView\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n bottom: 0,\n left: theme.space2,\n right: theme.space2,\n height: 2,\n borderRadius: 1,\n backgroundColor: theme.accentBgColor,\n }}\n />\n )}\n </Pressable>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nexport interface TabPanelProps extends Omit<ViewProps, 'style'> {\n /** Controls whether this panel is visible. */\n active?: boolean;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Content panel associated with a `TabItem`.\n *\n * Web's `id` (paired with `TabItem`'s `panelId`, together wiring up\n * `aria-controls`) is dropped on both sides here — RN has no ARIA\n * relationship attributes for it to drive, so track which tab is active in\n * your own state (index, key, whatever) and pass the matching panel\n * `active={true}` directly, rather than reaching for an id-matching\n * convention with nothing underneath it.\n *\n * Hidden panels stay mounted with `display: 'none'` rather than being\n * conditionally unmounted — same as the web version keeping them in the\n * DOM via the `hidden` attribute — so a panel's internal state (scroll\n * position, form input, etc.) survives switching tabs away and back. RN\n * has no `\"tabpanel\"` value in its `AccessibilityRole` union (unlike\n * `TabBar`'s `\"tablist\"` and `TabItem`'s `\"tab\"`, both of which do exist),\n * so no role is set here — same reasoning as `Separator` dropping a role\n * RN doesn't have rather than reaching for an inaccurate substitute.\n */\nexport const TabPanel = forwardRef<View, TabPanelProps>(function TabPanel(\n { active = false, style, children, ...viewProps },\n ref,\n) {\n return (\n <RNView ref={ref} style={[{ display: active ? 'flex' : 'none' }, style]} {...viewProps}>\n {children}\n </RNView>\n );\n});\n","import { forwardRef, useState } from 'react';\nimport type { StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport { TextInput as RNTextInput, View } from 'react-native';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface TextFieldProps extends Omit<TextInputProps, 'style'> {\n /** Visible label rendered above the input. */\n label?: string;\n /** Helper text rendered below the input. Hidden when `error` is set. */\n helperText?: string;\n /**\n * Error message rendered below the input in place of `helperText`.\n * Also applies the error visual state to the input border.\n */\n error?: string;\n /** Style applied to the wrapping `View`. */\n style?: StyleProp<ViewStyle>;\n /** Style applied to the `TextInput` itself. */\n inputStyle?: StyleProp<TextStyle>;\n}\n\n/**\n * Multiplies an `rgba(r, g, b, a)` token's alpha channel. Tokens that\n * aren't `rgba()` (e.g. `windowFgColor` in some variants resolves to a flat\n * hex) are returned unchanged — good enough here since this is only ever\n * used to dim `windowFgColor`, which the generated theme always emits as\n * `rgba()`.\n */\nfunction dimColor(color: string, factor: number): string {\n const match = color.match(/^rgba?\\(([^,]+),([^,]+),([^,]+),?([^)]+)?\\)$/);\n\n if (!match) {\n return color;\n }\n\n const [, r, g, b, a] = match;\n const alpha = (a ? Number.parseFloat(a) : 1) * factor;\n\n return `rgba(${r.trim()}, ${g.trim()}, ${b.trim()}, ${alpha})`;\n}\n\n/**\n * Single-line text input with label, helper text, and error state.\n *\n * Follows the Adwaita `GtkEntry` / `.entry` style class.\n *\n * Rebuilt on RN's `TextInput` rather than ported from `@gnome-ui/react`'s\n * `<input>`: there's no `<label htmlFor>`/`aria-describedby` pairing on RN,\n * so `label` doubles as `accessibilityLabel` and `error`/`helperText`\n * double as `accessibilityHint` — announced together with the input the\n * same way `aria-describedby` reads them on the web. `:focus-visible`'s\n * accent border becomes plain `onFocus`/`onBlur` state — RN has no\n * hover/keyboard-vs-pointer focus distinction to mirror, and no outer\n * `box-shadow` ring, so focus is just a border-color change rather than a\n * grown ring. The web version's `disabled` prop is RN's own\n * `editable={false}` — mirrored here as a dimmed wrapper the same way\n * `@gnome-ui/react`'s `.disabled` class dims the label and hint alongside\n * the input.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/text-fields.html\n */\nexport const TextField = forwardRef<TextInput, TextFieldProps>(function TextField(\n {\n label,\n helperText,\n error,\n style,\n inputStyle,\n editable = true,\n onFocus,\n onBlur,\n accessibilityLabel,\n accessibilityHint,\n ...inputProps\n },\n ref,\n) {\n const theme = useGnomeTheme();\n const contrast = useResolvedContrast();\n const [focused, setFocused] = useState(false);\n const disabled = !editable;\n const hint = error ?? helperText;\n\n const borderColor = error ? theme.errorColor : focused ? theme.accentColor : theme.borderSubtle;\n\n return (\n <View style={[{ gap: theme.space1, opacity: disabled ? theme.opacityDisabled : 1 }, style]}>\n {label && (\n <Text\n variant=\"body\"\n style={{ fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'] }}\n >\n {label}\n </Text>\n )}\n\n <RNTextInput\n ref={ref}\n editable={editable}\n accessibilityLabel={accessibilityLabel ?? label}\n accessibilityHint={accessibilityHint ?? hint}\n placeholderTextColor={dimColor(theme.windowFgColor, theme.opacityDim)}\n onFocus={(event) => {\n setFocused(true);\n onFocus?.(event);\n }}\n onBlur={(event) => {\n setFocused(false);\n onBlur?.(event);\n }}\n style={[\n {\n width: '100%',\n paddingVertical: 8,\n paddingHorizontal: theme.space2,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n lineHeight: Math.round(theme.fontSizeBody * theme.lineHeightBody),\n color: theme.viewFgColor,\n backgroundColor: theme.viewBgColor,\n borderRadius: theme.radiusMd,\n borderWidth: contrast === 'more' ? 2 : 1,\n borderColor,\n } satisfies TextStyle,\n inputStyle,\n ]}\n {...inputProps}\n />\n\n {hint && (\n <Text\n variant=\"caption\"\n style={{\n color: error ? theme.errorColor : theme.windowFgColor,\n opacity: error ? 1 : theme.opacityDim,\n }}\n >\n {hint}\n </Text>\n )}\n </View>\n );\n});\n","import { type ReactNode, useCallback, useEffect, useRef } from 'react';\nimport type { StyleProp, TextStyle, ViewProps, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable, Text as RNText } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\n/**\n * `Animated`'s style interpolation only takes effect on `Animated.*`\n * host components — a plain `Pressable` would silently ignore the\n * animated `opacity`/`transform` in its style. Hoisted to module scope so\n * it isn't recreated on every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nexport interface ToastProps extends Omit<ViewProps, 'style'> {\n /** The notification message. Keep it short — one sentence. */\n title: ReactNode;\n /**\n * Auto-dismiss timeout in milliseconds.\n * - Set to `0` to disable auto-dismiss (user must press action or dismiss).\n * - Defaults to `3000`.\n */\n duration?: number;\n /** Called when the toast should be removed — after timeout or user action. */\n onDismiss?: () => void;\n /** Label for the optional action button. */\n actionLabel?: string;\n /** Called when the user presses the action button. */\n onAction?: () => void;\n /** Whether to show a manual dismiss (×) button. */\n dismissible?: boolean;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Non-blocking temporary notification following the Adwaita `AdwToast`\n * pattern. Auto-dismisses after `duration` ms (default 3s, `0` disables\n * it); the timer pauses while the toast is pressed and held. Use inside\n * `Toaster` for correct positioning and stacking.\n *\n * The auto-dismiss/pause timer logic (`timerRef`/`remainingRef`/\n * `startedAtRef`) is ported verbatim from `@gnome-ui/react` — it's plain\n * `setTimeout`/`Date.now()` bookkeeping, no DOM API involved, so nothing\n * platform-specific to change. The pause trigger is: RN has no hover, so\n * `onPressIn`/`onPressOut` (touch-down/touch-up) stand in for the web\n * version's `onMouseEnter`/`onMouseLeave` — pausing while the user is\n * actively touching the toast, the closest RN analog to \"giving the user\n * time to read it.\" `onFocus`/`onBlur`-triggered pausing (keyboard\n * accessibility on web) has no port here — the outer card itself isn't a\n * focusable element in RN's touch-first model, only its action/dismiss\n * buttons are, and RN has no \"focus-within\" primitive to detect that\n * without an extra dependency.\n *\n * The entrance is an `Animated.timing` fading + sliding + scaling in\n * (`opacity`/`translateY`/`scale`, all transform-safe for\n * `useNativeDriver: true`), matching the web version's `@keyframes\n * toast-in`; `useReducedMotion()` skips straight to the settled state,\n * matching the source CSS's `animation: none`. There's no exit animation\n * to port either — the web version doesn't define one, removal is\n * immediate once the consumer drops the `Toast` from its list.\n *\n * RN's `AccessibilityRole` union has no \"status\" value (the web version's\n * `role=\"status\"`); `\"alert\"` is the closest available role for content\n * that should interrupt and be announced, paired with\n * `accessibilityLiveRegion=\"polite\"` (Android's live-region API) as the\n * nearest match to the web's `aria-live=\"polite\"` — deliberately not\n * `\"assertive\"`, matching the same politeness level the source chose.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Toast.html\n */\nexport const Toast = ({\n title,\n duration = 3000,\n onDismiss,\n actionLabel,\n onAction,\n dismissible = false,\n style,\n ...viewProps\n}: ToastProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const remainingRef = useRef(duration);\n const startedAtRef = useRef(0);\n const progress = useRef(new Animated.Value(reducedMotion ? 1 : 0)).current;\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const startTimer = useCallback(\n (ms: number) => {\n if (ms <= 0 || !onDismiss) {\n return;\n }\n\n clearTimer();\n startedAtRef.current = Date.now();\n timerRef.current = setTimeout(() => onDismiss(), ms);\n },\n [onDismiss, clearTimer],\n );\n\n useEffect(() => {\n if (duration > 0) {\n remainingRef.current = duration;\n startTimer(duration);\n }\n\n return clearTimer;\n }, [duration, startTimer, clearTimer]);\n\n useEffect(() => {\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [reducedMotion, progress, theme.durationNormal, theme.easingDefault]);\n\n const handlePressIn = () => {\n if (timerRef.current) {\n const elapsed = Date.now() - startedAtRef.current;\n\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\n clearTimer();\n }\n };\n\n const handlePressOut = () => {\n startTimer(remainingRef.current);\n };\n\n const handleAction = () => {\n clearTimer();\n onAction?.();\n onDismiss?.();\n };\n\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.4, shadowRadius: 12, elevation: 6 }\n : { shadowOpacity: 0.15, shadowRadius: 8, elevation: 4 };\n\n return (\n <AnimatedPressable\n accessible\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n style={[\n {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.space2,\n paddingVertical: 10,\n paddingRight: theme.space2,\n paddingLeft: theme.space3,\n minHeight: 44,\n maxWidth: 480,\n minWidth: 240,\n backgroundColor: theme.cardBgColor,\n borderRadius: theme.radiusLg,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n opacity: progress,\n transform: [\n {\n translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [12, 0] }),\n },\n { scale: progress.interpolate({ inputRange: [0, 1], outputRange: [0.96, 1] }) },\n ],\n ...shadow,\n },\n style,\n ]}\n {...viewProps}\n >\n <Text\n variant=\"body\"\n style={{ flex: 1, minWidth: 0 }}\n numberOfLines={typeof title === 'string' ? 2 : undefined}\n >\n {title}\n </Text>\n\n {(actionLabel || dismissible) && (\n <>\n {actionLabel && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={actionLabel}\n onPress={handleAction}\n style={({ pressed }) => ({\n paddingVertical: 4,\n paddingHorizontal: theme.space1,\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n color: theme.accentColor,\n }}\n >\n {actionLabel}\n </RNText>\n </Pressable>\n )}\n\n {dismissible && (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={4}\n onPress={() => {\n clearTimer();\n onDismiss?.();\n }}\n style={({ pressed }) => ({\n width: 28,\n height: 28,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.radiusSm,\n opacity: pressed ? 1 : 0.55,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n })}\n >\n <RNText style={{ fontSize: theme.fontSizeBody, color: theme.windowFgColor }}>\n {'×'}\n </RNText>\n </Pressable>\n )}\n </>\n )}\n </AnimatedPressable>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { StyleProp, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface ToasterProps extends Omit<ViewProps, 'style'> {\n /**\n * Where to position the toast stack within its container.\n * - `\"bottom\"` (default) — bottom-center, following the GNOME HIG.\n * - `\"top\"` — top-center.\n */\n position?: 'bottom' | 'top';\n /** `Toast` elements to display. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Absolutely-positioned container that stacks `Toast` notifications.\n *\n * RN has no `document.body`/portal target to render into the way the web\n * version's `createPortal(node, container ?? document.body)` does, so\n * there's no `container` prop here — mount `Toaster` yourself as the\n * **last** child of your app's root-level `View` (so it paints on top of\n * everything else) with that root `View` given `position: 'relative'` (or\n * left as the default relative positioning). `Toaster` then positions\n * itself with `position: 'absolute'`, spanning the full width and\n * anchored to `top`/`bottom` by `position`.\n *\n * `pointerEvents=\"box-none\"` is RN's equivalent of the web version's\n * `pointer-events: none` on the container — the empty space around the\n * toast stack doesn't intercept touches, but each `Toast` inside (a\n * `Pressable`) still handles its own.\n *\n * @example\n * ```tsx\n * <View style={{ flex: 1 }}>\n * <YourAppContent />\n * <Toaster>\n * {toasts.map((t) => (\n * <Toast key={t.id} title={t.message} onDismiss={() => remove(t.id)} />\n * ))}\n * </Toaster>\n * </View>\n * ```\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Toast.html\n */\nexport const Toaster = ({ position = 'bottom', children, style, ...viewProps }: ToasterProps) => {\n const theme = useGnomeTheme();\n\n return (\n <RNView\n pointerEvents=\"box-none\"\n accessibilityLabel=\"Notifications\"\n style={[\n {\n position: 'absolute',\n left: 0,\n right: 0,\n alignItems: 'center',\n gap: theme.space1,\n zIndex: 9999,\n },\n position === 'top' ? { top: theme.space4 } : { bottom: theme.space4 },\n style,\n ]}\n {...viewProps}\n >\n {children}\n </RNView>\n );\n};\n","import {\n cloneElement,\n type ReactElement,\n type Ref,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n GestureResponderEvent,\n LayoutChangeEvent,\n MouseEvent,\n NativeSyntheticEvent,\n PressableProps,\n TargetedEvent,\n TextStyle,\n} from 'react-native';\nimport { Animated, Dimensions, Modal, StyleSheet, View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface TooltipProps {\n /**\n * The tooltip label. Keep it short — a noun phrase or brief description.\n * Do not duplicate information already visible on screen.\n */\n label: string;\n /**\n * Preferred placement relative to the trigger.\n * The tooltip flips automatically if there is not enough space.\n * Defaults to `\"top\"`.\n */\n placement?: TooltipPlacement;\n /**\n * Delay in milliseconds before the tooltip appears, on both the\n * long-press and hover/focus triggers. Defaults to `500`. Set to `0` for\n * instant.\n */\n delay?: number;\n /**\n * The element that triggers the tooltip.\n * Must be a single element built on `Pressable` (e.g. `Button`, `Card`)\n * that forwards its `ref` to the underlying `View`.\n */\n children: ReactElement<PressableProps & { ref?: Ref<View> }>;\n}\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface Size {\n width: number;\n height: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n placement: TooltipPlacement;\n}\n\nconst GAP = 6;\nconst MARGIN = 8;\nconst ARROW = 5;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (!ref) {\n return;\n }\n\n if (typeof ref === 'function') {\n ref(value);\n\n return;\n }\n\n (ref as { current: T | null }).current = value;\n}\n\nfunction placementRect(trigger: Rect, tooltip: Size, placement: TooltipPlacement) {\n switch (placement) {\n case 'top':\n return {\n top: trigger.y - tooltip.height - GAP,\n left: trigger.x + trigger.width / 2 - tooltip.width / 2,\n };\n case 'bottom':\n return {\n top: trigger.y + trigger.height + GAP,\n left: trigger.x + trigger.width / 2 - tooltip.width / 2,\n };\n case 'left':\n return {\n top: trigger.y + trigger.height / 2 - tooltip.height / 2,\n left: trigger.x - tooltip.width - GAP,\n };\n case 'right':\n return {\n top: trigger.y + trigger.height / 2 - tooltip.height / 2,\n left: trigger.x + trigger.width + GAP,\n };\n }\n}\n\nfunction computePosition(trigger: Rect, tooltip: Size, preferred: TooltipPlacement): Position {\n const { width: vw, height: vh } = Dimensions.get('window');\n\n const opposite: TooltipPlacement =\n preferred === 'top'\n ? 'bottom'\n : preferred === 'bottom'\n ? 'top'\n : preferred === 'left'\n ? 'right'\n : 'left';\n const placements: TooltipPlacement[] = [preferred, opposite, 'top', 'bottom', 'left', 'right'];\n\n for (const p of placements) {\n const { top, left } = placementRect(trigger, tooltip, p);\n const fitsH = left >= MARGIN && left + tooltip.width <= vw - MARGIN;\n const fitsV = top >= MARGIN && top + tooltip.height <= vh - MARGIN;\n\n if (fitsH && fitsV) {\n return {\n top: Math.max(MARGIN, Math.min(top, vh - tooltip.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - tooltip.width - MARGIN)),\n placement: p,\n };\n }\n }\n\n const { top, left } = placementRect(trigger, tooltip, preferred);\n\n return {\n top: Math.max(MARGIN, Math.min(top, vh - tooltip.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - tooltip.width - MARGIN)),\n placement: preferred,\n };\n}\n\n/**\n * Informational tooltip following the Adwaita / GNOME HIG pattern.\n *\n * Wraps a single trigger element and shows a floating label. Positioned\n * automatically and flips if there is not enough space, mirroring\n * `@gnome-ui/react`'s `Tooltip`.\n *\n * **Trigger differs from the web version by necessity**: the web `Tooltip`\n * shows only on mouse hover / keyboard focus — touch has no hover state, so\n * it explicitly never shows on touch. RN is touch-first, so the primary\n * trigger here is long-press (`delayLongPress={delay}`, released via\n * `onPressOut`) — the standard mobile \"peek\" idiom. `onHoverIn`/`onHoverOut`\n * are also wired for hover-capable input (trackpad/mouse on iPad or a\n * pointer-driven RN target) and `onFocus`/`onBlur` for external-keyboard\n * accessibility, both delayed the same way the web version delays hover.\n *\n * Built on RN's own `Modal` (transparent, `pointerEvents=\"box-none\"`), the\n * same portal-substitute `Dialog` uses — no DOM `Portal` equivalent exists.\n * Unlike `Dialog`, `visible` is set synchronously on trigger (not gated on\n * the async `measureInWindow` result): the trigger's on-screen rect and the\n * tooltip's own rendered size each resolve independently into state, and a\n * separate effect computes the final position only once both have arrived.\n * Gating `visible` itself on `measureInWindow`'s callback was tried first\n * and dropped — that callback never fires in this package's Jest\n * environment (no real native view to measure), which would make the\n * component untestable, and in production it would also lose a real\n * quick-tap-then-release press if the callback resolved after `onPressOut`\n * had already fired.\n *\n * `role=\"tooltip\"` ports 1:1 — RN's newer web-aligned `Role` union (the\n * same one `Dialog` uses for `role=\"dialog\"`) already has a `\"tooltip\"`\n * value, no substitution needed. `aria-describedby` has no RN equivalent\n * (no cross-platform description-relationship prop exists), so the label is\n * set as the trigger's `accessibilityHint` instead — read after the\n * trigger's own label by VoiceOver/TalkBack, the nearest analog. The CSS\n * arrow reuses the same zero-size / transparent-border-on-three-sides\n * triangle trick as the web version — RN Views support per-side\n * `border*Color` just like CSS, the same technique `Spinner`'s ring\n * already relies on, applied here to a triangle instead of an arc.\n *\n * Not ported: repositioning on scroll/resize while visible (the web\n * version listens for both) — RN has no global scroll event, and a\n * long-press is naturally cancelled by a scroll gesture starting, so the\n * window to go stale is negligible for the touch trigger; orientation\n * change mid-hover is an accepted edge case for a component this transient.\n * `tooltipBgColor`/`tooltipFgColor` are not real `@gnome-ui/core` tokens\n * (only referenced as CSS var fallbacks, never defined) — hardcoded to the\n * same literal light/dark values as the web fallback, the same workaround\n * `Spinner`'s track color already established for this class of gap.\n *\n * @example\n * <Tooltip label=\"Save file\">\n * <Button accessibilityLabel=\"Save\"><Icon icon={Save} /></Button>\n * </Tooltip>\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/tooltips.html\n */\nexport const Tooltip = ({\n label,\n placement: preferredPlacement = 'top',\n delay = 500,\n children,\n}: TooltipProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const [visible, setVisible] = useState(false);\n const [triggerRect, setTriggerRect] = useState<Rect | null>(null);\n const [tooltipSize, setTooltipSize] = useState<Size | null>(null);\n const [pos, setPos] = useState<Position | null>(null);\n\n const triggerRef = useRef<View>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const progress = useRef(new Animated.Value(0)).current;\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const open = useCallback(() => {\n clearTimer();\n setVisible(true);\n }, [clearTimer]);\n\n const openDelayed = useCallback(() => {\n clearTimer();\n timerRef.current = setTimeout(open, delay);\n }, [clearTimer, open, delay]);\n\n const close = useCallback(() => {\n clearTimer();\n setVisible(false);\n }, [clearTimer]);\n\n // Measure the trigger's on-screen rect as soon as it's asked to show.\n useEffect(() => {\n if (!visible) {\n setTriggerRect(null);\n setTooltipSize(null);\n setPos(null);\n\n return;\n }\n\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerRect({ x, y, width, height });\n });\n }, [visible]);\n\n // Resolve the final position once both the trigger's rect and the\n // tooltip's own rendered size are known.\n useEffect(() => {\n if (!triggerRect || !tooltipSize) {\n return;\n }\n\n setPos(computePosition(triggerRect, tooltipSize, preferredPlacement));\n }, [triggerRect, tooltipSize, preferredPlacement]);\n\n useEffect(() => {\n if (!pos) {\n return;\n }\n\n if (reducedMotion) {\n progress.setValue(1);\n\n return;\n }\n\n progress.setValue(0);\n Animated.timing(progress, {\n toValue: 1,\n duration: theme.durationFast,\n useNativeDriver: true,\n }).start();\n }, [pos, reducedMotion, progress, theme.durationFast]);\n\n useEffect(() => clearTimer, [clearTimer]);\n\n const handleTooltipLayout = (e: LayoutChangeEvent) => {\n const { width, height } = e.nativeEvent.layout;\n\n setTooltipSize({ width, height });\n };\n\n const bg = scheme === 'dark' ? '#c0bfbc' : '#3d3d3d';\n const fg = scheme === 'dark' ? 'rgba(0, 0, 0, 0.8)' : '#fff';\n const shadow =\n scheme === 'dark'\n ? { shadowOpacity: 0.4, shadowRadius: 8, elevation: 6 }\n : { shadowOpacity: 0.2, shadowRadius: 8, elevation: 4 };\n\n const arrowBase = {\n position: 'absolute' as const,\n width: 0,\n height: 0,\n borderWidth: ARROW,\n borderColor: 'transparent',\n };\n\n const arrowStyle = (() => {\n switch (pos?.placement) {\n case 'top':\n return {\n ...arrowBase,\n top: '100%' as const,\n left: '50%' as const,\n marginLeft: -ARROW,\n borderTopColor: bg,\n };\n case 'bottom':\n return {\n ...arrowBase,\n bottom: '100%' as const,\n left: '50%' as const,\n marginLeft: -ARROW,\n borderBottomColor: bg,\n };\n case 'left':\n return {\n ...arrowBase,\n left: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderLeftColor: bg,\n };\n case 'right':\n return {\n ...arrowBase,\n right: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderRightColor: bg,\n };\n default:\n return null;\n }\n })();\n\n const existingRef = (children.props as { ref?: Ref<View> }).ref;\n\n const child = cloneElement(children, {\n ref: (node: View | null) => {\n (triggerRef as { current: View | null }).current = node;\n assignRef(existingRef, node);\n },\n delayLongPress: delay,\n accessibilityHint: children.props.accessibilityHint ?? label,\n onLongPress: (e: GestureResponderEvent) => {\n open();\n children.props.onLongPress?.(e);\n },\n onPressOut: (e: GestureResponderEvent) => {\n close();\n children.props.onPressOut?.(e);\n },\n onHoverIn: (e: MouseEvent) => {\n openDelayed();\n children.props.onHoverIn?.(e);\n },\n onHoverOut: (e: MouseEvent) => {\n close();\n children.props.onHoverOut?.(e);\n },\n onFocus: (e: NativeSyntheticEvent<TargetedEvent>) => {\n openDelayed();\n children.props.onFocus?.(e);\n },\n onBlur: (e: NativeSyntheticEvent<TargetedEvent>) => {\n close();\n children.props.onBlur?.(e);\n },\n });\n\n return (\n <>\n {child}\n <Modal visible={visible} transparent animationType=\"none\" statusBarTranslucent>\n <View pointerEvents=\"box-none\" style={StyleSheet.absoluteFill}>\n <Animated.View\n onLayout={handleTooltipLayout}\n accessible\n role=\"tooltip\"\n style={[\n {\n position: 'absolute',\n maxWidth: 240,\n paddingVertical: 4,\n paddingHorizontal: theme.space2,\n backgroundColor: bg,\n borderRadius: theme.radiusSm,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n ...shadow,\n },\n pos\n ? { top: pos.top, left: pos.left, opacity: progress }\n : { top: -9999, left: -9999, opacity: 0 },\n ]}\n >\n <Text\n style={{\n color: fg,\n fontSize: theme.fontSizeCaption,\n fontWeight: String(theme.fontWeightNormal) as TextStyle['fontWeight'],\n lineHeight: theme.fontSizeCaption * theme.lineHeightBody,\n textAlign: 'center',\n }}\n >\n {label}\n </Text>\n {arrowStyle && <View style={arrowStyle} />}\n </Animated.View>\n </View>\n </Modal>\n </>\n );\n};\n","import { forwardRef, type ReactNode } from 'react';\nimport type { StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { View as RNView, StyleSheet } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme } from '@/GnomeProvider';\n\nexport interface ViewSwitcherProps extends Omit<ViewProps, 'style'> {\n children?: ReactNode;\n /** Accessible label for the group. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * Segmented control for switching between major views.\n *\n * Mirrors the Adwaita `AdwViewSwitcher` pattern. Place as a `HeaderBar`'s\n * `title` for the canonical GNOME layout. Compose with `ViewSwitcherItem`\n * for each option.\n *\n * The web version's pill background is `color-mix(in srgb,\n * var(--gnome-headerbar-bg-color) 75%, black 25%)` (70/30 in dark mode) —\n * RN has no `color-mix()`, but alpha-compositing a flat semi-transparent\n * black `View` over an opaque background produces the exact same math\n * (`background × (1 − alpha) + black × alpha`), so that's what's layered\n * here instead, matching `Card`'s established color-mix-avoidance pattern.\n * `useResolvedColorScheme()` picks the 25%/30% split to match the web\n * value exactly rather than reusing a nearby overlay token.\n *\n * Roving-tabindex ← → / Home / End keyboard navigation isn't ported —\n * same reasoning as `TabBar`: no per-app arrow-key convention exists in\n * RN's touch-first focus model to port it to.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ViewSwitcher.html\n * @see https://developer.gnome.org/hig/patterns/nav/view-switchers.html\n */\nexport const ViewSwitcher = forwardRef<View, ViewSwitcherProps>(function ViewSwitcher(\n { children, accessibilityLabel = 'View switcher', style, ...viewProps },\n ref,\n) {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n\n return (\n <RNView\n ref={ref}\n accessible\n accessibilityRole=\"radiogroup\"\n accessibilityLabel={accessibilityLabel}\n style={[\n {\n alignSelf: 'flex-start',\n borderRadius: theme.radiusPill,\n overflow: 'hidden',\n backgroundColor: theme.headerbarBgColor,\n },\n style,\n ]}\n {...viewProps}\n >\n <RNView\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n { backgroundColor: scheme === 'dark' ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.25)' },\n ]}\n />\n <RNView style={{ flexDirection: 'row', alignItems: 'center', gap: 2, padding: 3 }}>\n {children}\n </RNView>\n </RNView>\n );\n});\n","import { forwardRef, type ReactNode } from 'react';\nimport type { PressableProps, TextStyle, View } from 'react-native';\nimport { Pressable, Text as RNText, View as RNView } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface ViewSwitcherItemProps\n extends Omit<PressableProps, 'children' | 'style' | 'disabled'> {\n /** Display label. */\n label: string;\n /**\n * Icon placed before the label. Rendered as-is — size/color it yourself.\n * Web's `icon` takes an `@gnome-ui/icons` `IconDefinition`; this package\n * has no SVG icon system, so it's a plain `ReactNode` here, same as\n * `TabItem`'s `icon`.\n */\n icon?: ReactNode;\n /** Marks this item as the currently active view. */\n active?: boolean;\n disabled?: boolean;\n}\n\n/**\n * Individual option inside a `ViewSwitcher`.\n *\n * Renders with `accessibilityRole=\"radio\"` so the group reads as a proper\n * radio group. The pressed-state tint on non-active items\n * (`theme.activeOverlay`) isn't a stand-in approximation here — its light\n * (`rgba(0, 0, 0, 0.12)`) and dark (`rgba(255, 255, 255, 0.14)`) values\n * happen to match the web version's `:active` colors exactly, so it's\n * reused directly rather than hand-rolled.\n */\nexport const ViewSwitcherItem = forwardRef<View, ViewSwitcherItemProps>(function ViewSwitcherItem(\n { label, icon, active = false, disabled, ...pressableProps },\n ref,\n) {\n const theme = useGnomeTheme();\n\n return (\n <Pressable\n ref={ref}\n disabled={disabled}\n accessibilityRole=\"radio\"\n accessibilityState={{ checked: active, disabled: !!disabled }}\n accessibilityLabel={label}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.space1,\n paddingVertical: 5,\n paddingHorizontal: theme.space2,\n borderRadius: theme.radiusPill - 3,\n opacity: disabled ? theme.opacityDisabled : 1,\n backgroundColor: active\n ? theme.headerbarBgColor\n : pressed\n ? theme.activeOverlay\n : 'transparent',\n })}\n {...pressableProps}\n >\n {icon && <RNView style={{ flexShrink: 0 }}>{icon}</RNView>}\n\n <RNText\n style={{\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontWeight: String(\n active ? theme.fontWeightSemibold : theme.fontWeightNormal,\n ) as TextStyle['fontWeight'],\n color: theme.headerbarFgColor,\n }}\n >\n {label}\n </RNText>\n </Pressable>\n );\n});\n"],"mappings":"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"}