@gnome-ui/react-native 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +324 -4
- package/dist/components/Avatar/Avatar.d.ts +53 -0
- package/dist/components/Avatar/index.d.ts +2 -0
- package/dist/components/Badge/Badge.d.ts +48 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/BottomSheet/BottomSheet.d.ts +82 -0
- package/dist/components/BottomSheet/index.d.ts +2 -0
- package/dist/components/Divider/Divider.d.ts +36 -0
- package/dist/components/Divider/index.d.ts +2 -0
- package/dist/components/Expander/Expander.d.ts +64 -0
- package/dist/components/Expander/index.d.ts +2 -0
- package/dist/components/Highlight/Highlight.d.ts +42 -0
- package/dist/components/Highlight/index.d.ts +2 -0
- package/dist/components/LevelBar/LevelBar.d.ts +72 -0
- package/dist/components/LevelBar/index.d.ts +2 -0
- package/dist/components/Overlay/Overlay.d.ts +41 -0
- package/dist/components/Overlay/index.d.ts +2 -0
- package/dist/components/Popover/Popover.d.ts +91 -0
- package/dist/components/Popover/index.d.ts +2 -0
- package/dist/components/SpinButton/SpinButton.d.ts +57 -0
- package/dist/components/SpinButton/index.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1395 -444
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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/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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"}
|
|
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/Avatar/Avatar.tsx","../src/components/Badge/Badge.tsx","../src/components/Banner/Banner.tsx","../src/components/BottomSheet/BottomSheet.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/Divider/Divider.tsx","../src/components/Dropdown/Dropdown.tsx","../src/components/Expander/Expander.tsx","../src/components/HeaderBar/HeaderBar.tsx","../src/components/Highlight/Highlight.tsx","../src/components/LevelBar/LevelBar.tsx","../src/components/Link/Link.tsx","../src/components/Overlay/Overlay.tsx","../src/components/PathBar/PathBar.tsx","../src/components/Popover/Popover.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/SpinButton/SpinButton.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 { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Image, Text, View } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * Named color palette for the initials fallback.\n * Mirrors libadwaita's avatar color set.\n */\nexport type AvatarColor =\n | 'blue'\n | 'green'\n | 'yellow'\n | 'orange'\n | 'red'\n | 'purple'\n | 'brown'\n | 'teal'\n | 'slate';\n\nexport interface AvatarProps {\n /**\n * Full name used to generate initials and — when `color` is omitted —\n * to deterministically pick a background color.\n */\n name?: string;\n /** Image URL. When provided the initials fallback is hidden. */\n src?: string;\n /** Accessible label. Defaults to `name`, then `\"Avatar\"`. */\n alt?: string;\n /** Size of the avatar. Defaults to `\"md\"`. */\n size?: AvatarSize;\n /**\n * Override the auto-derived background color for the initials fallback.\n * When omitted a color is derived from `name` via a stable hash.\n */\n color?: AvatarColor;\n style?: StyleProp<ViewStyle>;\n}\n\nconst COLOR_LIST: AvatarColor[] = [\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n 'teal',\n 'slate',\n];\n\nconst SIZE_BOX: Record<AvatarSize, number> = { sm: 24, md: 32, lg: 48, xl: 64 };\n\n/**\n * Initials font size as a multiple of the theme's base body size — ports the\n * source CSS's `.initials { font-size: 0.42em }` overridden per size\n * (`sm` 0.5em, `md` 0.6em, `lg` 1em, `xl` 1.4em), which is relative to the\n * *inherited* ambient font size (the avatar box itself sets none), not to\n * the avatar's own box size.\n */\nconst SIZE_INITIALS_RATIO: Record<AvatarSize, number> = { sm: 0.5, md: 0.6, lg: 1, xl: 1.4 };\n\n/** Stable, non-cryptographic hash → index into COLOR_LIST. */\nfunction nameToColor(name: string): AvatarColor {\n let hash = 0;\n for (let i = 0; i < name.length; i++) {\n hash = (hash * 31 + name.charCodeAt(i)) >>> 0;\n }\n\n return COLOR_LIST[hash % COLOR_LIST.length];\n}\n\n/** Extract up to 2 initials from a name string. */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n\n if (parts.length === 0) {\n return '';\n }\n\n if (parts.length === 1) {\n return parts[0].charAt(0).toUpperCase();\n }\n\n return parts[0].charAt(0).toUpperCase() + parts[parts.length - 1].charAt(0).toUpperCase();\n}\n\ninterface ColorSwatch {\n backgroundColor: string;\n initialsColor: string;\n}\n\nfunction getColorSwatch(theme: GnomeThemeTokens, color: AvatarColor): ColorSwatch {\n switch (color) {\n case 'blue':\n return { backgroundColor: theme.blue3, initialsColor: '#fff' };\n case 'green':\n return { backgroundColor: theme.green4, initialsColor: '#fff' };\n case 'yellow':\n // Yellow needs dark initials for contrast, independent of color scheme.\n return { backgroundColor: theme.yellow4, initialsColor: 'rgba(0, 0, 0, 0.8)' };\n case 'orange':\n return { backgroundColor: theme.orange4, initialsColor: '#fff' };\n case 'red':\n return { backgroundColor: theme.red3, initialsColor: '#fff' };\n case 'purple':\n return { backgroundColor: theme.purple3, initialsColor: '#fff' };\n case 'brown':\n return { backgroundColor: theme.brown3, initialsColor: '#fff' };\n case 'teal':\n // Not a real @gnome-ui/core token — the web CSS hardcodes this hex too.\n return { backgroundColor: '#2190a4', initialsColor: '#fff' };\n case 'slate':\n return { backgroundColor: theme.dark2, initialsColor: '#fff' };\n }\n}\n\n/**\n * Circular avatar with image or initials fallback.\n *\n * Follows the Adwaita `AdwAvatar` pattern — deterministic color from name,\n * up to two initials when no image is supplied. Rebuilt with `View`/`Image`/\n * `Text` rather than ported from `@gnome-ui/react`'s DOM-based JSX, but\n * mirrors its prop API and color-hash/initials math (pure JS, ported\n * verbatim).\n *\n * The outer container carries `role=\"img\"` + `accessibilityLabel` — RN's\n * newer web-aligned `Role` union has an `\"img\"` value, a direct 1:1 port of\n * the web version's `role=\"img\"`, no substitution needed (same as\n * `ProgressBar`'s `role=\"progressbar\"`). The image/initials underneath are\n * hidden from the accessibility tree\n * (`accessibilityElementsHidden`/`importantForAccessibility=\"no\"`, mirroring\n * the web version's `aria-hidden` on both), so a screen reader gets one\n * stop, not two — same reasoning as `SpinButton`'s hidden −/+ buttons.\n *\n * The web CSS's `box-shadow: inset 0 0 0 1px …` ring (drawn on top, doesn't\n * affect layout) becomes a real 1px `borderWidth`/`borderColor` here (RN has\n * no inset shadow) — the same substitution `Slider`'s thumb border already\n * used for a ring effect, at the cost of a negligible 1px content-box inset\n * the web version doesn't have.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Avatar.html\n */\nexport const Avatar = ({ name = '', src, alt, size = 'md', color, style }: AvatarProps) => {\n const theme = useGnomeTheme();\n const resolvedColorScheme = useResolvedColorScheme();\n\n const resolvedColor = color ?? (name ? nameToColor(name) : 'blue');\n const initials = getInitials(name);\n const box = SIZE_BOX[size];\n const { backgroundColor, initialsColor } = getColorSwatch(theme, resolvedColor);\n const ringColor =\n resolvedColorScheme === 'dark' ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.08)';\n\n return (\n <View\n accessible\n role=\"img\"\n accessibilityLabel={alt ?? (name || undefined) ?? 'Avatar'}\n style={[\n {\n width: box,\n height: box,\n borderRadius: theme.radiusPill,\n overflow: 'hidden',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: src ? undefined : backgroundColor,\n borderWidth: 1,\n borderColor: ringColor,\n },\n style,\n ]}\n >\n {src ? (\n <Image\n testID=\"avatar-image\"\n source={{ uri: src }}\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n resizeMode=\"cover\"\n style={{ width: '100%', height: '100%' }}\n />\n ) : (\n <Text\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n fontFamily: theme.fontFamily,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n fontSize: theme.fontSizeBody * SIZE_INITIALS_RATIO[size],\n lineHeight: theme.fontSizeBody * SIZE_INITIALS_RATIO[size],\n color: initialsColor,\n }}\n >\n {initials}\n </Text>\n )}\n </View>\n );\n};\n","import type { ReactNode } from 'react';\nimport type { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { Text, View } from 'react-native';\n\nimport { useGnomeTheme, useResolvedColorScheme } from '@/GnomeProvider';\nimport type { GnomeResolvedColorScheme, GnomeThemeTokens } from '@/theme';\n\nexport type BadgeVariant = 'accent' | 'success' | 'warning' | 'error' | 'neutral';\n\nexport interface BadgeProps {\n /**\n * Visual style. Defaults to `\"accent\"`.\n * - `accent` — blue, for counts and highlights.\n * - `success` — green, for positive status.\n * - `warning` — yellow, for cautionary status.\n * - `error` — red, for failures or urgent counts.\n * - `neutral` — gray, for inactive or secondary counts.\n */\n variant?: BadgeVariant;\n /**\n * When true, renders a small dot with no label — used for unread/online indicators.\n * The `children` are ignored in dot mode.\n */\n dot?: boolean;\n /** Number or short text to display. Keep to 1–3 characters. String/number render as a themed label; other nodes render as-is. */\n children?: ReactNode;\n /**\n * When provided, the badge is positioned over this child element at the\n * top-right corner.\n */\n anchor?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\ninterface VariantColors {\n backgroundColor: string;\n color: string;\n}\n\nfunction getVariantColors(\n theme: GnomeThemeTokens,\n colorScheme: GnomeResolvedColorScheme,\n variant: BadgeVariant,\n): VariantColors {\n switch (variant) {\n case 'accent':\n return { backgroundColor: theme.accentBgColor, color: theme.accentFgColor };\n case 'success':\n return { backgroundColor: theme.successBgColor, color: theme.successFgColor };\n case 'warning':\n return { backgroundColor: theme.warningBgColor, color: theme.warningFgColor };\n case 'error':\n return { backgroundColor: theme.errorBgColor, color: theme.errorFgColor };\n case 'neutral':\n return {\n backgroundColor: colorScheme === 'dark' ? theme.dark2 : theme.light4,\n color: theme.windowFgColor,\n };\n }\n}\n\n/**\n * Counter or status indicator, optionally overlaid on another element.\n *\n * Rebuilt with `View`/`Text` rather than ported from `@gnome-ui/react`'s\n * DOM-based JSX, but mirrors its prop API. `children` renders as a themed\n * `Text` label when it's a string or number (the common case — counts and\n * short text); any other node renders as-is, the same convention `Button`'s\n * `children` already established.\n *\n * The web CSS's `box-shadow: 0 0 0 2px var(--gnome-window-bg-color)` ring\n * (always present, separating the badge from whatever's behind it) has no\n * RN equivalent that avoids affecting layout — RN's `border*` shrinks the\n * content box instead of drawing outside it. Reproduced instead with an\n * outer wrapping `View` (2px padding, `theme.windowBgColor` background,\n * pill radius) around the actual colored badge, so the ring appears to\n * spread outward exactly like the web version's non-blurred shadow, without\n * eating into the badge's own text padding.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/badges.html\n */\nexport const Badge = ({ variant = 'accent', dot = false, children, anchor, style }: BadgeProps) => {\n const theme = useGnomeTheme();\n const colorScheme = useResolvedColorScheme();\n const { backgroundColor, color } = getVariantColors(theme, colorScheme, variant);\n\n const badgeEl = (\n <View\n testID=\"badge-ring\"\n style={[\n {\n padding: 2,\n borderRadius: theme.radiusPill,\n backgroundColor: theme.windowBgColor,\n },\n anchor\n ? {\n position: 'absolute' as const,\n top: dot ? -2 : -4,\n right: dot ? -2 : -4,\n zIndex: 1,\n }\n : null,\n ]}\n >\n <View\n testID=\"badge\"\n style={[\n {\n minWidth: dot ? 10 : 18,\n height: dot ? 10 : 18,\n paddingHorizontal: dot ? 0 : 5,\n borderRadius: theme.radiusPill,\n backgroundColor,\n alignItems: 'center',\n justifyContent: 'center',\n },\n style,\n ]}\n >\n {!dot &&\n (typeof children === 'string' || typeof children === 'number' ? (\n <Text\n style={{\n fontFamily: theme.fontFamily,\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n fontSize: 11,\n lineHeight: 13,\n color,\n }}\n >\n {children}\n </Text>\n ) : (\n children\n ))}\n </View>\n </View>\n );\n\n if (anchor) {\n return (\n <View style={{ alignSelf: 'flex-start' }}>\n {anchor}\n {badgeEl}\n </View>\n );\n }\n\n return badgeEl;\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 { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport {\n Animated,\n BackHandler,\n Dimensions,\n Modal,\n PanResponder,\n Pressable,\n View,\n} from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion } 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 * `Dialog`. Hoisted to module scope so it isn't recreated on every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nconst DRAG_CLOSE_THRESHOLD = 150;\n\nexport interface BottomSheetProps {\n /** Whether the sheet is visible. */\n open: boolean;\n /** Optional heading shown below the drag handle. */\n title?: ReactNode;\n children?: ReactNode;\n /** Called when the user dismisses the sheet (backdrop press, Android back button, or drag down). */\n onClose?: () => void;\n /** Whether pressing the backdrop closes the sheet. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n style?: StyleProp<ViewStyle>;\n /** Applied to the backdrop, mirroring `Dialog`'s own `testID`. */\n testID?: string;\n}\n\n/**\n * Slide-up panel that overlays content from the bottom edge, mirroring\n * `AdwBottomSheet` (libadwaita 1.6+) and `@gnome-ui/react`'s `BottomSheet`.\n *\n * Rebuilt with `View`/`Modal`/`PanResponder` rather than ported from the web\n * version's DOM `Portal` + manual focus trap + raw pointer events —\n * reusing this package's own established pieces: `Dialog`'s backdrop-\n * opacity-on-an-`AnimatedPressable` + no-op-`Pressable`-around-the-card\n * (so a tap on the card never bubbles to the backdrop) recipe, and\n * `BackHandler`'s `hardwareBackPress` as the Android analog of the web\n * version's Escape listener (same pattern `Dialog`/`Popover` already use).\n * Focus-trapping and focus-restore-on-close have no port — no DOM\n * `document.activeElement`/`querySelector` equivalent exists in RN, the\n * same gap already present in every other floating component here.\n *\n * **Real drag-to-dismiss, not a fixed-panel simplification**: unlike the\n * web version's raw `PointerEvent` handlers directly mutating\n * `style.transform`, this uses `PanResponder` (the same core RN API\n * `Slider` already proved handles a threshold-based drag gesture) driving\n * a single `Animated.Value` — the *same* value used for the slide-in/\n * slide-out entrance animation. `PanResponder`'s `gestureState.dy` is the\n * cumulative vertical delta since the gesture started, so a plain\n * `translateY.setValue(Math.max(0, gestureState.dy))` during\n * `onPanResponderMove` reproduces the web version's own\n * `Math.max(0, e.clientY - dragStartY.current)` clamp exactly, and a\n * release past `DRAG_CLOSE_THRESHOLD` (150 px, same constant as the web\n * version) animates the rest of the way down before calling `onClose`,\n * otherwise it springs back to `0`. The gesture responder is attached only\n * to the handle bar `View`, not the whole sheet, mirroring the web\n * version's `onPointerDown` being scoped to `.handle` alone.\n *\n * **A real slide-up needs the sheet's own height first** — RN's\n * `transform` has no percentage-of-self units (the same `Slider`/`Avatar`\n * pitfall), unlike the web version's `translateY(100%)`. The sheet renders\n * once off-screen (measured via `onLayout`, starting `translateY` at that\n * measured height) before animating to `0` — the same \"resolve own\n * rendered size, then animate\" two-step every other sized-on-open\n * component in this package (`Dialog`, `Dropdown`, `Popover`) already\n * needs, just for a transform offset instead of a floating position.\n *\n * **Real, timed exit animation, unlike `Dialog`**: `Dialog`'s web source\n * has no exit keyframes at all (`Modal`'s `visible={false}` unmounts\n * immediately, matching the web version's plain `return null`) — but\n * `BottomSheet`'s web source explicitly animates both the backdrop fade\n * and the sheet's slide-out before removing it. Ported with a local\n * `visible` state that lags one animation behind the `open` prop: closing\n * starts the exit `Animated.timing`s and only flips `visible` to `false`\n * (unmounting the `Modal`'s content) in the animation's own completion\n * callback — not a `setTimeout` racing a hardcoded duration like the web\n * version, since `Animated`'s callback already fires exactly when the\n * animation actually finishes.\n *\n * The web version's `backdrop-filter: blur(4px)` has no port — this\n * package has no native blur view dependency, the same reasoning that\n * already dropped `Sidebar`'s blurred `variant`. `useBodyScrollLock` has no\n * RN equivalent needed: `Modal` already blocks all interaction with\n * whatever's behind it, there is no scrollable \"body\" to lock separately.\n *\n * `role=\"dialog\"` + `accessibilityViewIsModal` port 1:1 from `Dialog`'s own\n * precedent. `children`, when a plain string, must be wrapped in `Text`\n * before rendering — RN throws if a raw string is a `View`'s child, unlike\n * the web version's `<div>{children}</div>`, which needed no such check.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.BottomSheet.html\n */\nexport const BottomSheet = ({\n open,\n title,\n children,\n onClose,\n closeOnBackdrop = true,\n style,\n testID,\n}: BottomSheetProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const [visible, setVisible] = useState(open);\n const [sheetHeight, setSheetHeight] = useState(0);\n\n const translateY = useRef(new Animated.Value(Dimensions.get('window').height)).current;\n const backdropOpacity = useRef(new Animated.Value(0)).current;\n const isDragging = useRef(false);\n\n useEffect(() => {\n if (open) {\n setVisible(true);\n }\n }, [open]);\n\n // Animate in once the sheet is mounted and measured; animate out (then\n // actually unmount) when `open` flips false — skipped mid-drag, since the\n // gesture handlers below already own `translateY` in that case.\n useEffect(() => {\n if (!visible || isDragging.current) {\n return;\n }\n\n if (open) {\n if (reducedMotion) {\n translateY.setValue(0);\n backdropOpacity.setValue(1);\n\n return;\n }\n\n if (sheetHeight > 0) {\n translateY.setValue(sheetHeight);\n Animated.timing(translateY, {\n toValue: 0,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start();\n }\n\n Animated.timing(backdropOpacity, {\n toValue: 1,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start();\n } else {\n if (reducedMotion) {\n setVisible(false);\n\n return;\n }\n\n Animated.timing(translateY, {\n toValue: sheetHeight || Dimensions.get('window').height,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start(({ finished }) => {\n if (finished) {\n setVisible(false);\n }\n });\n Animated.timing(backdropOpacity, {\n toValue: 0,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start();\n }\n }, [\n open,\n visible,\n sheetHeight,\n reducedMotion,\n translateY,\n backdropOpacity,\n theme.durationNormal,\n ]);\n\n // Android hardware back button closes the sheet — the analog of the web\n // version's document-level Escape listener, same pattern `Dialog` uses.\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n onClose?.();\n\n return true;\n });\n\n return () => subscription.remove();\n }, [open, onClose]);\n\n const panResponder = useMemo(\n () =>\n PanResponder.create({\n onStartShouldSetPanResponder: () => true,\n onPanResponderGrant: () => {\n isDragging.current = true;\n },\n onPanResponderMove: (_event, gestureState) => {\n translateY.setValue(Math.max(0, gestureState.dy));\n },\n onPanResponderRelease: (_event, gestureState) => {\n isDragging.current = false;\n\n const dy = Math.max(0, gestureState.dy);\n\n if (dy >= DRAG_CLOSE_THRESHOLD) {\n // Just request the close — the `open` → `false` effect above\n // owns the actual exit animation (and reduced-motion handling),\n // continuing smoothly from wherever the drag left `translateY`\n // rather than duplicating that animation here.\n onClose?.();\n } else {\n Animated.timing(translateY, {\n toValue: 0,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start();\n }\n },\n }),\n [translateY, theme.durationNormal, onClose],\n );\n\n const handleSheetLayout = (e: LayoutChangeEvent) => {\n setSheetHeight(e.nativeEvent.layout.height);\n };\n\n if (!visible) {\n return null;\n }\n\n return (\n <Modal\n visible={visible}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={onClose}\n >\n <AnimatedPressable\n testID={testID}\n onPress={closeOnBackdrop ? onClose : undefined}\n accessible={false}\n style={{\n flex: 1,\n justifyContent: 'flex-end',\n backgroundColor: theme.dialogBackdropColor,\n opacity: backdropOpacity,\n }}\n >\n <Pressable onPress={() => {}} accessible={false}>\n <Animated.View\n onLayout={handleSheetLayout}\n accessible\n role=\"dialog\"\n accessibilityViewIsModal\n style={[\n {\n alignSelf: 'center',\n width: '100%',\n maxWidth: 560,\n backgroundColor: theme.dialogBgColor,\n borderTopLeftRadius: theme.radiusXl,\n borderTopRightRadius: theme.radiusXl,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: -4 },\n shadowOpacity: 0.18,\n shadowRadius: 24,\n elevation: 12,\n transform: [{ translateY }],\n },\n style,\n ]}\n >\n <View\n testID=\"bottom-sheet-handle\"\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n alignItems: 'center',\n paddingTop: theme.space2,\n paddingBottom: theme.space1,\n }}\n {...panResponder.panHandlers}\n >\n <View\n style={{\n width: 36,\n height: 4,\n borderRadius: 2,\n backgroundColor: theme.windowFgColor,\n opacity: 0.2,\n }}\n />\n </View>\n\n {title && (\n <Text\n variant=\"title-4\"\n style={{\n paddingHorizontal: theme.space4,\n paddingBottom: theme.space2,\n textAlign: 'center',\n fontWeight: String(theme.fontWeightBold) as TextStyle['fontWeight'],\n }}\n >\n {title}\n </Text>\n )}\n\n {children && (\n <View style={{ paddingHorizontal: theme.space4, paddingBottom: theme.space4 }}>\n {typeof children === 'string' ? <Text variant=\"body\">{children}</Text> : children}\n </View>\n )}\n </Animated.View>\n </Pressable>\n </AnimatedPressable>\n </Modal>\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 type { ReactNode } from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { View } from 'react-native';\n\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nexport interface DividerProps {\n /** Optional centered label (e.g. `\"OR\"`, `\"Continue with\"`). */\n children?: ReactNode;\n /** Accessible name. Defaults to `children` when it's a string. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\n/**\n * Horizontal rule with an optional centered label — common auth/login-form\n * pattern (\"Sign in\" / **OR** / \"Continue with Google\"). Mirrors\n * `@gnome-ui/react`'s `Divider`.\n *\n * For a bare dividing line with no label, use `Separator` instead — it also\n * supports a vertical orientation, which `Divider` does not.\n *\n * `role=\"separator\"` ports 1:1 from RN's newer web-aligned `Role` union\n * (the same one `Avatar`/`Badge`/`LevelBar` already reach for), unlike\n * `Separator`'s own choice to render as `accessible={false}` — that\n * component is purely decorative with nothing for a screen reader to\n * announce, while a labelled `Divider` (\"OR\") is exactly the kind of\n * content a screen reader user needs read aloud, so it stays in the\n * accessibility tree instead. The label reuses `Text`'s `variant=\"caption\"\n * color=\"dim\"` verbatim rather than hand-rolled styles, since that\n * combination already resolves to the same font-size/weight/dim-opacity\n * the web version's `.label` class hard-codes.\n *\n * The web version's `aria-orientation=\"horizontal\"` has no port — `Divider`\n * has no `orientation` prop at all (unlike `Separator`), so there is only\n * ever one orientation to announce.\n *\n * @see https://developer.gnome.org/hig/patterns/containers.html\n */\nexport const Divider = ({ children, accessibilityLabel, style, testID }: DividerProps) => {\n const theme = useGnomeTheme();\n const hasLabel = Boolean(children);\n\n return (\n <View\n testID={testID}\n accessible\n role=\"separator\"\n accessibilityLabel={\n accessibilityLabel ?? (typeof children === 'string' ? children : undefined)\n }\n style={[\n { flexDirection: 'row', alignItems: 'center', width: '100%', gap: theme.space2 },\n style,\n ]}\n >\n <View style={{ flex: 1, height: 1, backgroundColor: theme.cardShadeColor }} />\n {hasLabel && (\n <>\n {typeof children === 'string' ? (\n <Text variant=\"caption\" color=\"dim\">\n {children}\n </Text>\n ) : (\n children\n )}\n <View style={{ flex: 1, height: 1, backgroundColor: theme.cardShadeColor }} />\n </>\n )}\n </View>\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 { PanEnd } from '@gnome-ui/icons';\nimport { type ReactNode, useEffect, useRef, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';\nimport { Animated, Easing, Pressable, View } from 'react-native';\n\nimport { Icon } from '@/components/Icon';\nimport { Text } from '@/components/Text';\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport interface ExpanderProps {\n /** Clickable header label. String children render as a themed `Text` label; other nodes render as-is. */\n label: ReactNode;\n /** Content revealed when expanded. */\n children?: ReactNode;\n /** Controlled expanded state. */\n expanded?: boolean;\n /** Initial expanded state when uncontrolled. Defaults to `false`. */\n defaultExpanded?: boolean;\n /** Called when the expanded state changes. */\n onExpandedChange?: (expanded: boolean) => void;\n /** Disables the toggle. */\n disabled?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\n/**\n * Standalone disclosure triangle + collapsible content — mirrors\n * `GtkExpander` and `@gnome-ui/react`'s `Expander`.\n *\n * A bare, unstyled counterpart to `ExpanderRow`. Use `Expander` outside a\n * settings-row context, e.g. \"Show advanced options\" in a form, or \"Show\n * details\" under an error message.\n *\n * The web version clips the panel with a CSS grid-height animation and\n * rides the content's `padding-top` on a second, separate transition (so a\n * collapsed expander doesn't reserve blank space for padding that belongs\n * to hidden content). RN has no CSS grid to lean on, so the panel is a\n * single `Animated.View` whose numeric `height` is driven directly —\n * `useNativeDriver: false`, the same accepted (and documented) trade-off\n * `Checkbox`/`RadioButton`/`Switch`/`AnimatedIcon` already make for\n * non-transform properties. Because the inner content `View`'s `onLayout`\n * measurement already includes its own `paddingTop`, animating that single\n * height value reproduces the web version's two-transition result with one\n * `Animated.Value` instead of two. Content stays mounted while collapsed\n * (matching the web version's `inert`, unmounted-from-the-tab-order-only\n * behavior) — `accessibilityElementsHidden` / `importantForAccessibility`\n * is RN's closest equivalent, applied to the panel wrapper.\n *\n * On first mount with `defaultExpanded`, the panel briefly renders at its\n * natural (unmeasured) height instead of the animated value, so the initial\n * reveal doesn't start from a wrong, pre-measurement `0` and pop once\n * `onLayout` resolves — the same \"let layout report the truth once, then\n * hand control to `Animated`\" shape `Dropdown`/`Tooltip` use for their own\n * `onLayout`-measured dimensions.\n *\n * The chevron is `PanEnd` (GNOME's own `pan-end-symbolic` disclosure\n * triangle) rather than a chevron glyph, matching the web version's\n * hand-drawn arrow shape. It rotates 0deg → 90deg on an `Animated.Value`\n * (the same `interpolate`-to-`rotate` recipe `Spinner` uses for its own\n * indeterminate spin), unlike `Dropdown`'s chevron, which snaps instantly\n * since that panel's own reveal has no comparable \"settle\" affordance.\n *\n * `role=\"region\"` on the panel and `accessibilityState={{ expanded }}` on\n * the header port 1:1 from the web version's `aria-controls`/`aria-expanded`\n * pair — RN has no DOM ids, so the id-based `aria-labelledby`/`aria-controls`\n * relationship itself has no port, the same `ProgressBar`/`LevelBar`\n * precedent for dropping id-relationship-only ARIA props.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Expander.html\n */\nexport const Expander = ({\n label,\n children,\n expanded: controlledExpanded,\n defaultExpanded = false,\n onExpandedChange,\n disabled = false,\n style,\n testID,\n}: ExpanderProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const isControlled = controlledExpanded !== undefined;\n const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);\n const expanded = isControlled ? controlledExpanded : uncontrolledExpanded;\n\n const [contentHeight, setContentHeight] = useState(0);\n const hasMeasured = useRef(false);\n const heightAnim = useRef(new Animated.Value(0)).current;\n const chevronAnim = useRef(new Animated.Value(defaultExpanded ? 1 : 0)).current;\n\n const toggle = () => {\n if (disabled) {\n return;\n }\n\n const next = !expanded;\n\n if (!isControlled) {\n setUncontrolledExpanded(next);\n }\n\n onExpandedChange?.(next);\n };\n\n const handleContentLayout = (e: LayoutChangeEvent) => {\n const h = e.nativeEvent.layout.height;\n\n if (h === contentHeight) {\n hasMeasured.current = true;\n\n return;\n }\n\n if (expanded && !hasMeasured.current) {\n heightAnim.setValue(h);\n }\n\n hasMeasured.current = true;\n setContentHeight(h);\n };\n\n useEffect(() => {\n const [x1, y1, x2, y2] = theme.easingDefault;\n const easing = Easing.bezier(x1, y1, x2, y2);\n const target = expanded ? contentHeight : 0;\n\n if (reducedMotion) {\n heightAnim.setValue(target);\n chevronAnim.setValue(expanded ? 1 : 0);\n\n return;\n }\n\n Animated.parallel([\n Animated.timing(heightAnim, {\n toValue: target,\n duration: theme.durationNormal,\n easing,\n useNativeDriver: false,\n }),\n Animated.timing(chevronAnim, {\n toValue: expanded ? 1 : 0,\n duration: theme.durationFast,\n easing,\n useNativeDriver: true,\n }),\n ]).start();\n }, [\n expanded,\n contentHeight,\n reducedMotion,\n heightAnim,\n chevronAnim,\n theme.durationNormal,\n theme.durationFast,\n theme.easingDefault,\n ]);\n\n const showsNaturalHeight = expanded && !hasMeasured.current;\n const rotate = chevronAnim.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '90deg'] });\n\n return (\n <View testID={testID} style={[{ width: '100%' }, style]}>\n <Pressable\n role=\"button\"\n disabled={disabled}\n accessibilityState={{ expanded, disabled }}\n onPress={toggle}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n gap: theme.space2,\n padding: theme.space1,\n margin: -theme.space1,\n borderRadius: theme.radiusSm,\n backgroundColor: pressed ? theme.activeOverlay : 'transparent',\n opacity: disabled ? theme.opacityDisabled : 1,\n })}\n >\n <Animated.View style={{ opacity: 0.55, transform: [{ rotate }] }}>\n <Icon icon={PanEnd} size=\"md\" />\n </Animated.View>\n\n {typeof label === 'string' ? (\n <Text style={{ color: theme.windowFgColor }}>{label}</Text>\n ) : (\n label\n )}\n </Pressable>\n\n <Animated.View\n style={{ height: showsNaturalHeight ? undefined : heightAnim, overflow: 'hidden' }}\n accessibilityElementsHidden={!expanded}\n importantForAccessibility={expanded ? 'yes' : 'no'}\n >\n <View\n accessible\n role=\"region\"\n onLayout={handleContentLayout}\n style={{ paddingTop: theme.space2 }}\n >\n {children}\n </View>\n </Animated.View>\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 { Text as RNText, type TextStyle } from 'react-native';\n\nimport { Text, type TextProps } from '@/components/Text';\nimport { useGnomeTheme, useResolvedContrast } from '@/GnomeProvider';\n\nexport interface HighlightProps extends Omit<TextProps, 'children'> {\n /** Full text to render. */\n text: string;\n /**\n * Term or terms to highlight within `text`. Pass an array to highlight\n * multiple distinct terms at once (e.g. each word of a multi-word search\n * query). Empty or whitespace-only terms are ignored.\n */\n query: string | string[];\n /** Match case-sensitively. Defaults to `false`. */\n caseSensitive?: boolean;\n}\n\nfunction escapeRegExp(s: string) {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Wraps every occurrence of `query` within `text` in a highlighted inline\n * run — mirrors `@gnome-ui/react`'s `Highlight`, which wraps matches in a\n * `<mark>`. Pairs with `SearchBar`'s suggestion list and any filterable\n * list to show users which part of a result matched what they typed.\n *\n * The outer span is the themed `Text` component (so callers get the same\n * `variant`/`color` API as everywhere else), but each matched run is a\n * plain, unthemed RN `Text` carrying only the highlight's own overrides —\n * RN's `Text` is the one primitive that inherits ambient `fontSize`/\n * `color`/`fontFamily` from a parent `Text` when nested, the same way the\n * web version's `<mark>` inherits from its surrounding text and only\n * overrides `background-color`/`font-weight`. Reaching for the themed\n * `Text` for the marked runs too would reset them to its own default\n * `variant=\"body\"` sizing instead of inheriting whatever variant the\n * caller chose for the whole string.\n *\n * The web version's translucent `color-mix(in srgb, accent 30%,\n * transparent)` background has no RN equivalent (`color-mix` is CSS-only)\n * — resolved to a literal 8-digit `#RRGGBBAA` hex instead, since\n * `accentBgColor` is always a plain 6-digit hex across all four theme\n * variants. `border-radius` on the `<mark>` has no reliable port either:\n * RN only paints `backgroundColor` on an inline (nested) `Text` run, not\n * `borderRadius` — a decorative nicety dropped here, not a behavior gap.\n * `prefers-contrast: more`'s solid-background/white-text swap ports via\n * `useResolvedContrast()`, the same hook `Button` already uses for its own\n * high-contrast branching.\n */\nexport const Highlight = ({ text, query, caseSensitive = false, ...textProps }: HighlightProps) => {\n const theme = useGnomeTheme();\n const contrast = useResolvedContrast();\n\n const terms = (Array.isArray(query) ? query : [query]).map((q) => q.trim()).filter(Boolean);\n\n if (terms.length === 0) {\n return <Text {...textProps}>{text}</Text>;\n }\n\n const pattern = new RegExp(`(${terms.map(escapeRegExp).join('|')})`, caseSensitive ? 'g' : 'gi');\n const parts = text.split(pattern);\n\n const markStyle: TextStyle = {\n fontWeight: String(theme.fontWeightSemibold) as TextStyle['fontWeight'],\n ...(contrast === 'more'\n ? { backgroundColor: theme.accentBgColor, color: '#fff' }\n : { backgroundColor: `${theme.accentBgColor}4D` }),\n };\n\n return (\n <Text {...textProps}>\n {parts.map((part, i) =>\n i % 2 === 1 ? (\n <RNText key={i} style={markStyle}>\n {part}\n </RNText>\n ) : (\n part\n ),\n )}\n </Text>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { Animated, Easing, View } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion, useResolvedColorScheme } from '@/GnomeProvider';\nimport type { GnomeThemeTokens } from '@/theme';\n\nexport type LevelBarVariant = 'accent' | 'success' | 'warning' | 'error';\n\nexport interface LevelBarProps {\n /** Current value, between `min` and `max`. */\n value: number;\n /** Minimum value. Defaults to `0`. */\n min?: number;\n /** Maximum value. Defaults to `1`. */\n max?: number;\n /** Threshold at or below which the bar renders in `lowVariant`. */\n low?: number;\n /** Color used when `value <= low`. Defaults to `\"warning\"`. */\n lowVariant?: LevelBarVariant;\n /** Threshold at or above which the bar renders in `highVariant`. */\n high?: number;\n /** Color used when `value >= high`. Defaults to `\"error\"`. */\n highVariant?: LevelBarVariant;\n /** Color used between `low` and `high`. Defaults to `\"accent\"`. */\n variant?: LevelBarVariant;\n /**\n * Render as a row of discrete blocks instead of a continuous fill —\n * mirrors `GtkLevelBar`'s discrete mode (e.g. signal-strength indicators).\n */\n discrete?: boolean;\n /** Number of blocks when `discrete` is true. Defaults to `10`. */\n numBlocks?: number;\n /** Accessible label describing what the level represents. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nfunction resolveVariant(\n value: number,\n low: number | undefined,\n lowVariant: LevelBarVariant,\n high: number | undefined,\n highVariant: LevelBarVariant,\n variant: LevelBarVariant,\n): LevelBarVariant {\n if (low !== undefined && value <= low) {\n return lowVariant;\n }\n\n if (high !== undefined && value >= high) {\n return highVariant;\n }\n\n return variant;\n}\n\nfunction variantColor(theme: GnomeThemeTokens, variant: LevelBarVariant): string {\n switch (variant) {\n case 'accent':\n return theme.accentBgColor;\n case 'success':\n return theme.successBgColor;\n case 'warning':\n return theme.warningBgColor;\n case 'error':\n return theme.errorBgColor;\n }\n}\n\n/**\n * Discrete level indicator with color-coded low/high offset zones —\n * mirrors `GtkLevelBar` and `@gnome-ui/react`'s `LevelBar`. Use for a\n * gauge/measurement display (disk usage, battery, signal strength), not\n * for task progress (see `ProgressBar`) or a proportional category\n * breakdown (see `SegmentedBar`).\n *\n * The continuous fill reuses `ProgressBar`'s exact animation technique\n * rather than animating `width` directly: a fixed `width: '100%'` fill\n * with `transformOrigin: 'left'` and an animated `transform: [{ scaleX }]`,\n * so the whole thing runs on `useNativeDriver: true` — a JS-driven\n * (`useNativeDriver: false`) `width` animation schedules its next frame via\n * a plain `setTimeout` that routinely fires after a test's `render()`\n * returns but before unmount, producing a real \"update not wrapped in\n * act()\" warning, the same reasoning `ProgressBar`'s own docstring\n * documents. `useReducedMotion()` mirrors `ProgressBar`'s determinate\n * behavior: the transition duration drops to `0` (an immediate jump)\n * rather than the animation being skipped in some other way.\n *\n * Discrete mode's per-block `background-color` transition has no port —\n * unlike the continuous fill's width change, a value change in discrete\n * mode is a binary color swap per block with no established `Animated`\n * color-interpolation precedent elsewhere in this package, so it's a\n * plain, unanimated style swap; a decorative nicety, not a behavior gap.\n * Discrete blocks are hidden from the accessibility tree\n * (`accessibilityElementsHidden`/`importantForAccessibility=\"no\"`,\n * mirroring the web version's `aria-hidden`) since the meter's value is\n * already exposed once via `accessibilityValue` on the container.\n *\n * `role=\"meter\"` ports 1:1 from RN's newer web-aligned `Role` union (unlike\n * `AccessibilityRole`, which has no `\"meter\"` value at all) — the same\n * precedent `Dialog`/`Avatar`/`Badge` already established for reaching for\n * `role` over `accessibilityRole` when only the newer union has the value\n * needed. Web's `aria-labelledby` (an id-relationship prop) has no RN\n * equivalent — RN has no DOM ids — so only `aria-label`\n * (`accessibilityLabel`) is ported, the same `ProgressBar`/`Slider`\n * precedent.\n *\n * @see https://developer.gnome.org/hig/patterns/feedback/progress.html\n */\nexport const LevelBar = ({\n value,\n min = 0,\n max = 1,\n low,\n lowVariant = 'warning',\n high,\n highVariant = 'error',\n variant = 'accent',\n discrete = false,\n numBlocks = 10,\n accessibilityLabel,\n style,\n testID,\n}: LevelBarProps) => {\n const theme = useGnomeTheme();\n const scheme = useResolvedColorScheme();\n const reducedMotion = useReducedMotion();\n\n const range = max - min;\n const clamped = Math.min(max, Math.max(min, value));\n const fraction = range > 0 ? (clamped - min) / range : 0;\n const resolvedVariant = resolveVariant(clamped, low, lowVariant, high, highVariant, variant);\n\n const scaleX = useRef(new Animated.Value(fraction)).current;\n\n useEffect(() => {\n if (discrete) {\n return;\n }\n\n const [x1, y1, x2, y2] = theme.easingDefault;\n\n Animated.timing(scaleX, {\n toValue: fraction,\n duration: reducedMotion ? 0 : theme.durationNormal,\n easing: Easing.bezier(x1, y1, x2, y2),\n useNativeDriver: true,\n }).start();\n }, [fraction, discrete, reducedMotion, scaleX, theme.durationNormal, theme.easingDefault]);\n\n const trackColor = scheme === 'dark' ? theme.dark2 : theme.light3;\n\n return (\n <View\n testID={testID}\n accessible\n role=\"meter\"\n accessibilityLabel={accessibilityLabel}\n accessibilityValue={{ min, max, now: clamped }}\n style={[\n {\n flexDirection: 'row',\n width: '100%',\n height: 6,\n borderRadius: discrete ? 0 : theme.radiusPill,\n backgroundColor: discrete ? 'transparent' : trackColor,\n overflow: discrete ? 'visible' : 'hidden',\n gap: discrete ? 2 : 0,\n },\n style,\n ]}\n >\n {discrete ? (\n Array.from({ length: numBlocks }, (_, i) => {\n const blockFraction = (i + 1) / numBlocks;\n const filled = blockFraction <= fraction;\n\n return (\n <View\n key={i}\n testID=\"level-bar-block\"\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n flex: 1,\n height: '100%',\n minWidth: 2,\n borderRadius: 1,\n backgroundColor: filled ? variantColor(theme, resolvedVariant) : trackColor,\n }}\n />\n );\n })\n ) : (\n <Animated.View\n testID={testID ? `${testID}-fill` : undefined}\n style={{\n width: '100%',\n height: '100%',\n borderRadius: theme.radiusPill,\n backgroundColor: variantColor(theme, resolvedVariant),\n transformOrigin: 'left',\n transform: [{ scaleX }],\n }}\n />\n )}\n </View>\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, useEffect, useRef, useState } from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { Animated, Modal, Pressable } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion } 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 * `Dialog`/`BottomSheet`. Hoisted to module scope so it isn't recreated on\n * every render.\n */\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable);\n\nexport interface OverlayProps {\n /** Whether the overlay is visible. */\n open: boolean;\n /** Called when the backdrop itself (not its content) is pressed. */\n onDismiss?: () => void;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\n/**\n * Standalone backdrop/scrim layer with a fade transition and\n * press-to-dismiss — the shared building block behind `Dialog`,\n * `Dropdown`, `Popover`, and `BottomSheet`'s backdrops, extracted here for\n * building custom overlay UI, mirroring `@gnome-ui/react`'s `Overlay`.\n *\n * Deliberately minimal, same as the web version: no focus trap, no\n * `BackHandler`/Escape handling, no `role`. Use `Dialog`/`Popover`/\n * `BottomSheet` directly when you need those — this is only the fade +\n * dismiss-on-backdrop-tap primitive underneath them.\n *\n * Built on `Modal` rather than the web version's `createPortal` — no\n * `container` prop exists here, since RN's `Modal` has no equivalent\n * mount-target concept (it always renders at the top of the native view\n * hierarchy). Reuses `Dialog`'s exact backdrop recipe: an\n * `AnimatedPressable` backdrop whose `onPress` fires `onDismiss`, wrapping\n * `children` in a no-op `Pressable` so a tap on the content itself never\n * bubbles to the backdrop and dismisses it — the RN analog of the web\n * version's `e.target === e.currentTarget` check, which has no meaning in\n * RN's touch-responder model.\n *\n * **Real, timed exit animation, same technique as `BottomSheet`**: a local\n * `visible` state lags one animation behind the `open` prop, flipping to\n * `false` only in the fade-out `Animated.timing`'s own completion callback\n * — not a `setTimeout` racing a hardcoded duration like the web version,\n * since `Animated`'s callback already fires exactly when the animation\n * actually finishes. `useBodyScrollLock` has no RN equivalent needed —\n * `Modal` already blocks all interaction with whatever's behind it.\n */\nexport const Overlay = ({ open, onDismiss, children, style, testID }: OverlayProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const [visible, setVisible] = useState(open);\n const opacity = useRef(new Animated.Value(open ? 1 : 0)).current;\n\n useEffect(() => {\n if (open) {\n setVisible(true);\n }\n }, [open]);\n\n useEffect(() => {\n if (!visible) {\n return;\n }\n\n if (open) {\n if (reducedMotion) {\n opacity.setValue(1);\n\n return;\n }\n\n opacity.setValue(0);\n Animated.timing(opacity, {\n toValue: 1,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start();\n } else {\n if (reducedMotion) {\n setVisible(false);\n\n return;\n }\n\n Animated.timing(opacity, {\n toValue: 0,\n duration: theme.durationNormal,\n useNativeDriver: true,\n }).start(({ finished }) => {\n if (finished) {\n setVisible(false);\n }\n });\n }\n }, [open, visible, reducedMotion, opacity, theme.durationNormal]);\n\n if (!visible) {\n return null;\n }\n\n return (\n <Modal visible={visible} transparent animationType=\"none\" statusBarTranslucent>\n <AnimatedPressable\n testID={testID}\n onPress={onDismiss}\n accessible={false}\n style={[\n {\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: theme.dialogBackdropColor,\n opacity,\n },\n style,\n ]}\n >\n <Pressable onPress={() => {}} accessible={false}>\n {children}\n </Pressable>\n </AnimatedPressable>\n </Modal>\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 {\n cloneElement,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n GestureResponderEvent,\n LayoutChangeEvent,\n PressableProps,\n StyleProp,\n ViewStyle,\n} from 'react-native';\nimport { Animated, BackHandler, Dimensions, Modal, Pressable, View } from 'react-native';\n\nimport { useGnomeTheme, useReducedMotion } from '@/GnomeProvider';\n\nexport type PopoverPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface PopoverProps {\n /**\n * The rich content rendered inside the popover panel.\n * Can include interactive elements (buttons, links, forms).\n */\n content: ReactNode;\n /**\n * Preferred placement relative to the trigger.\n * Flips automatically when there is not enough viewport space.\n * Defaults to `\"bottom\"`.\n */\n placement?: PopoverPlacement;\n /**\n * Whether the popover is open (controlled mode).\n * Omit to use uncontrolled mode where the trigger toggles it.\n */\n open?: boolean;\n /** Called when open state should change. */\n onOpenChange?: (open: boolean) => void;\n /** Extra style on the popover panel itself. */\n panelStyle?: StyleProp<ViewStyle>;\n /**\n * The trigger element. Must be a single element built on `Pressable`\n * (e.g. `Button`, `Card`) 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: PopoverPlacement;\n}\n\nconst GAP = 8;\nconst MARGIN = 10;\nconst ARROW = 6;\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, panel: Size, placement: PopoverPlacement) {\n switch (placement) {\n case 'top':\n return {\n top: trigger.y - panel.height - GAP,\n left: trigger.x + trigger.width / 2 - panel.width / 2,\n };\n case 'bottom':\n return {\n top: trigger.y + trigger.height + GAP,\n left: trigger.x + trigger.width / 2 - panel.width / 2,\n };\n case 'left':\n return {\n top: trigger.y + trigger.height / 2 - panel.height / 2,\n left: trigger.x - panel.width - GAP,\n };\n case 'right':\n return {\n top: trigger.y + trigger.height / 2 - panel.height / 2,\n left: trigger.x + trigger.width + GAP,\n };\n }\n}\n\nfunction computePosition(trigger: Rect, panel: Size, preferred: PopoverPlacement): Position {\n const { width: vw, height: vh } = Dimensions.get('window');\n\n const opposite: PopoverPlacement =\n preferred === 'top'\n ? 'bottom'\n : preferred === 'bottom'\n ? 'top'\n : preferred === 'left'\n ? 'right'\n : 'left';\n const placements: PopoverPlacement[] = [preferred, opposite, 'bottom', 'top', 'left', 'right'];\n\n for (const p of placements) {\n const { top, left } = placementRect(trigger, panel, p);\n const fitsH = left >= MARGIN && left + panel.width <= vw - MARGIN;\n const fitsV = top >= MARGIN && top + panel.height <= vh - MARGIN;\n\n if (fitsH && fitsV) {\n return {\n top: Math.max(MARGIN, Math.min(top, vh - panel.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - panel.width - MARGIN)),\n placement: p,\n };\n }\n }\n\n const { top, left } = placementRect(trigger, panel, preferred);\n\n return {\n top: Math.max(MARGIN, Math.min(top, vh - panel.height - MARGIN)),\n left: Math.max(MARGIN, Math.min(left, vw - panel.width - MARGIN)),\n placement: preferred,\n };\n}\n\n/**\n * Floating panel anchored to a trigger element, following the Adwaita\n * `GtkPopover` pattern. Unlike `Tooltip`, a popover can contain rich\n * interactive content (buttons, links, forms).\n *\n * Rebuilt with `View`/`Pressable`/`Modal` rather than ported from\n * `@gnome-ui/react`'s DOM `Portal` + manual focus trap, reusing this\n * package's own established pieces rather than re-deriving them: `Tooltip`'s\n * `cloneElement`-onto-an-arbitrary-trigger architecture and 4-placement\n * fallback-cascade positioning (`computePosition`, same shape, no arrow-\n * offset-shift-when-clamped complexity — same simplification `Tooltip`\n * already accepted), and `Dropdown`'s toggle-on-press + full-screen backdrop\n * `Pressable` that closes on an outside tap (the RN analog of the web\n * version's document-level \"click outside\" listener) plus reduced-motion\n * fade-in.\n *\n * **Deliberate divergence from `Dropdown`'s backdrop structure**: `Dropdown`\n * nests its panel directly inside the backdrop `Pressable` and gets away\n * with it because almost every pixel of its panel is itself a `Pressable`\n * option row, which claims the touch responder before it can bubble to the\n * backdrop. A popover's `content` is arbitrary — likely to have inert\n * padding/whitespace/text with no `Pressable` of its own — so nesting the\n * same way would let a tap on inert panel space fall through to the\n * backdrop and close the popover, unlike the web version's `.contains()`\n * check (which never closes on *any* tap inside the panel). Fixed with\n * `onStartShouldSetResponder={() => true}` on the panel itself: it claims\n * the touch responder for any touch RN's negotiation hasn't already given to\n * a deeper `Pressable` inside `content`, without making the panel itself\n * behave like a button.\n *\n * `BackHandler`'s `hardwareBackPress` (wired the same way `Dialog` already\n * does) is the Android analog of the web version's document-level Escape\n * listener — there is no keyboard `Escape` to catch on a touch-first device.\n * Focus-trapping and focus-restore-on-close have no port: there is no DOM\n * `document.activeElement`/`querySelector` equivalent in RN, the same gap\n * that already left every other floating component in this package (\n * `Dialog`, `Tooltip`, `Dropdown`) without them.\n *\n * The web version's rotated-square-with-matching-background arrow (relying\n * on same-color blending across a straddled panel edge and CSS stacking\n * order) is replaced with `Tooltip`'s simpler transparent-border-triangle\n * technique — same visual affordance (a pointer toward the trigger), a much\n * simpler RN-native primitive.\n *\n * `role=\"dialog\"` on the panel ports 1:1 from RN's newer web-aligned `Role`\n * union (the same one `Dialog`/`Tooltip` already use) — no substitution\n * needed. `aria-haspopup`/`aria-controls` have no RN equivalent (no\n * cross-platform relationship-attribute prop); only `accessibilityState.\n * expanded` is wired on the trigger, the same subset `Dropdown`'s own\n * trigger already exposes.\n *\n * @example\n * <Popover content={<Text>Rich content here</Text>}>\n * <Button>Open</Button>\n * </Popover>\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Popover.html\n */\nexport const Popover = ({\n content,\n placement: preferredPlacement = 'bottom',\n open: controlledOpen,\n onOpenChange,\n panelStyle,\n children,\n}: PopoverProps) => {\n const theme = useGnomeTheme();\n const reducedMotion = useReducedMotion();\n\n const isControlled = controlledOpen !== undefined;\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = isControlled ? controlledOpen : uncontrolledOpen;\n\n const [triggerRect, setTriggerRect] = useState<Rect | null>(null);\n const [panelSize, setPanelSize] = useState<Size | 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 setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(next);\n }\n\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n const close = useCallback(() => setOpen(false), [setOpen]);\n const toggle = useCallback(() => setOpen(!open), [open, setOpen]);\n\n // Measure the trigger's on-screen rect as soon as it's asked to show.\n useEffect(() => {\n if (!open) {\n setTriggerRect(null);\n setPanelSize(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 // Resolve the final position once both the trigger's rect and the panel's\n // own rendered size are known.\n useEffect(() => {\n if (!triggerRect || !panelSize) {\n return;\n }\n\n setPos(computePosition(triggerRect, panelSize, preferredPlacement));\n }, [triggerRect, panelSize, 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 // Android hardware back button closes the popover — the analog of the web\n // version's document-level Escape listener, same pattern `Dialog` uses.\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n close();\n\n return true;\n });\n\n return () => subscription.remove();\n }, [open, close]);\n\n const handlePanelLayout = (e: LayoutChangeEvent) => {\n const { width, height } = e.nativeEvent.layout;\n\n setPanelSize({ width, height });\n };\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: theme.popoverBgColor,\n };\n case 'bottom':\n return {\n ...arrowBase,\n bottom: '100%' as const,\n left: '50%' as const,\n marginLeft: -ARROW,\n borderBottomColor: theme.popoverBgColor,\n };\n case 'left':\n return {\n ...arrowBase,\n left: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderLeftColor: theme.popoverBgColor,\n };\n case 'right':\n return {\n ...arrowBase,\n right: '100%' as const,\n top: '50%' as const,\n marginTop: -ARROW,\n borderRightColor: theme.popoverBgColor,\n };\n default:\n return null;\n }\n })();\n\n const existingRef = (children.props as { ref?: Ref<View> }).ref;\n\n const trigger = cloneElement(children, {\n ref: (node: View | null) => {\n (triggerRef as { current: View | null }).current = node;\n assignRef(existingRef, node);\n },\n accessibilityState: { expanded: open, ...children.props.accessibilityState },\n onPress: (e: GestureResponderEvent) => {\n toggle();\n children.props.onPress?.(e);\n },\n });\n\n return (\n <>\n {trigger}\n <Modal\n visible={open}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={close}\n >\n <Pressable onPress={close} accessible={false} style={{ flex: 1 }}>\n <Animated.View\n onLayout={handlePanelLayout}\n role=\"dialog\"\n accessible\n onStartShouldSetResponder={() => true}\n style={[\n {\n position: 'absolute',\n minWidth: 180,\n maxWidth: 320,\n backgroundColor: theme.popoverBgColor,\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusLg,\n padding: theme.space2,\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, opacity: progress }\n : { top: -9999, left: -9999, opacity: 0 },\n panelStyle,\n ]}\n >\n {content}\n {arrowStyle && <View style={arrowStyle} />}\n </Animated.View>\n </Pressable>\n </Modal>\n </>\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 { useCallback } from 'react';\nimport type { AccessibilityActionEvent, StyleProp, ViewStyle } from 'react-native';\nimport { Pressable, Text, View } from 'react-native';\n\nimport { useGnomeTheme } from '@/GnomeProvider';\n\nconst BTN_SIZE = 36;\n\nexport interface SpinButtonProps {\n /** Current value. */\n value: number;\n /** Called when the value changes. */\n onChange: (value: number) => void;\n /** Minimum allowed value. Defaults to `0`. */\n min?: number;\n /** Maximum allowed value. Defaults to `100`. */\n max?: number;\n /** Amount to increment/decrement per step. Defaults to `1`. */\n step?: number;\n /** Number of decimal places shown. Derived from `step` when omitted. */\n decimals?: number;\n /**\n * Wrap around instead of clamping at the edges — stepping past `max` returns\n * to `min` and vice versa, and the −/+ buttons never disable. Mirrors\n * `GtkSpinButton:wrap`; used for cyclic values like hours and minutes.\n */\n wrap?: boolean;\n /**\n * Custom display formatter for the current value (e.g. zero-padding, or\n * mapping a numeric value to `AM`/`PM`). Defaults to fixed-decimal text. When\n * provided, its result is also exposed as the accessibility value's `text`.\n */\n format?: (value: number) => string;\n /** Disables the control. */\n disabled?: boolean;\n /** Accessible label. Required — RN has no visible-label association to fall back on. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nfunction countDecimals(n: number): number {\n const s = n.toString();\n const dot = s.indexOf('.');\n\n return dot === -1 ? 0 : s.length - dot - 1;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction wrapValue(value: number, min: number, max: number, step: number): number {\n const range = max - min + step;\n return ((((value - min) % range) + range) % range) + min;\n}\n\n/**\n * Numeric input with − and + buttons following the Adwaita `GtkSpinButton` style.\n *\n * Rebuilt with `View`/`Pressable`/`Text` rather than ported from\n * `@gnome-ui/react`'s DOM-based JSX, but mirrors its prop API and clamp/wrap/\n * decimal math (pure JS, ported verbatim).\n *\n * The primary interaction is tapping the visible −/+ buttons, same as a\n * sighted mouse user on the web version. The web version's keyboard\n * interaction (↑/↓ one step, Page Up/Down ten steps, Home/End to bounds) has\n * no RN equivalent — a touch-first device has no keyboard to drive it, the\n * same reasoning `Slider` already applied. Rather than dropping value\n * adjustment accessibility entirely, single-step increment/decrement is\n * wired through `accessibilityRole=\"adjustable\"` + `onAccessibilityAction`\n * (VoiceOver's swipe-up/down, TalkBack's local-context menu), reusing the\n * exact recipe `Slider` already proved works — the bigger Page Up/Down and\n * Home/End jumps have no equivalent screen-reader gesture on either\n * platform, so those alone are dropped, same as `Slider`. The visible\n * buttons are hidden from the accessibility tree (mirrors the web version's\n * `aria-hidden`/`tabIndex={-1}` on both `<button>`s) so a screen reader user\n * gets one adjustable stop, not three.\n *\n * @see https://developer.gnome.org/hig/patterns/controls/spin-buttons.html\n */\nexport const SpinButton = ({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n decimals,\n wrap = false,\n format,\n disabled = false,\n accessibilityLabel,\n style,\n}: SpinButtonProps) => {\n const theme = useGnomeTheme();\n const dp = decimals ?? countDecimals(step);\n\n const set = useCallback(\n (next: number) => {\n const bounded = wrap ? wrapValue(next, min, max, step) : clamp(next, min, max);\n onChange(parseFloat(bounded.toFixed(dp)));\n },\n [onChange, min, max, step, dp, wrap],\n );\n\n const displayText = format ? format(value) : value.toFixed(dp);\n\n const handleAccessibilityAction = useCallback(\n (event: AccessibilityActionEvent) => {\n if (disabled) {\n return;\n }\n\n switch (event.nativeEvent.actionName) {\n case 'increment':\n set(value + step);\n break;\n case 'decrement':\n set(value - step);\n break;\n }\n },\n [disabled, value, step, set],\n );\n\n const decrementDisabled = disabled || (!wrap && value <= min);\n const incrementDisabled = disabled || (!wrap && value >= max);\n\n return (\n <View\n accessible\n accessibilityRole=\"adjustable\"\n accessibilityLabel={accessibilityLabel}\n accessibilityValue={{ min, max, now: value, text: format ? displayText : undefined }}\n accessibilityState={{ disabled }}\n accessibilityActions={[\n { name: 'increment', label: 'increment' },\n { name: 'decrement', label: 'decrement' },\n ]}\n onAccessibilityAction={handleAccessibilityAction}\n style={[\n {\n flexDirection: 'row',\n alignSelf: 'flex-start',\n alignItems: 'center',\n borderWidth: 1,\n borderColor: theme.cardShadeColor,\n borderRadius: theme.radiusMd,\n backgroundColor: theme.viewBgColor,\n overflow: 'hidden',\n opacity: disabled ? theme.opacityDisabled : 1,\n },\n style,\n ]}\n >\n <Pressable\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n disabled={decrementDisabled}\n onPress={() => set(value - step)}\n style={({ pressed }) => ({\n width: BTN_SIZE,\n height: BTN_SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderRightWidth: 1,\n borderRightColor: theme.cardShadeColor,\n backgroundColor: pressed && !decrementDisabled ? theme.activeOverlay : 'transparent',\n opacity: decrementDisabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text style={{ fontSize: 17, lineHeight: 20, color: theme.viewFgColor }}>−</Text>\n </Pressable>\n\n <Text\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={{\n minWidth: 56,\n textAlign: 'center',\n paddingHorizontal: theme.space2,\n fontFamily: theme.fontFamily,\n fontSize: theme.fontSizeBody,\n fontVariant: ['tabular-nums'],\n color: theme.viewFgColor,\n }}\n >\n {displayText}\n </Text>\n\n <Pressable\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n disabled={incrementDisabled}\n onPress={() => set(value + step)}\n style={({ pressed }) => ({\n width: BTN_SIZE,\n height: BTN_SIZE,\n alignItems: 'center',\n justifyContent: 'center',\n borderLeftWidth: 1,\n borderLeftColor: theme.cardShadeColor,\n backgroundColor: pressed && !incrementDisabled ? theme.activeOverlay : 'transparent',\n opacity: incrementDisabled ? theme.opacityDisabled : 1,\n })}\n >\n <Text style={{ fontSize: 17, lineHeight: 20, color: theme.viewFgColor }}>+</Text>\n </Pressable>\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":";;;;;;AAgJA,IAAa,KAA+B;CAC1C,eAAe;CACf,aAAa;CACb,eAAe;CACf,eAAe;CACf,uBAAuB;CACvB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,cAAc;CACd,eAAe;EAAC;EAAM;EAAM;EAAM;CAAI;CACtC,cAAc;CACd,YAAY;CACZ,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,oBAAoB;CACpB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,oBAAoB;CACpB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,cAAc;CACd,wBAAwB;CACxB,wBAAwB;CACxB,sBAAsB;CACtB,sBAAsB;CACtB,6BAA6B;CAC7B,8BAA8B;CAC9B,2BAA2B;CAC3B,uBAAuB;CACvB,uBAAuB;CACvB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,mBAAmB;CACnB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,iBAAiB;CACjB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,gBAAgB;CAChB,gBAAgB;CAChB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,UAAU;CACV,UAAU;CACV,YAAY;CACZ,UAAU;CACV,UAAU;CACV,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,gBAAgB;CAChB,gBAAgB;CAChB,mBAAmB;CACnB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,KAA8B;CACzC,eAAe;CACf,aAAa;CACb,eAAe;CACf,eAAe;CACf,uBAAuB;CACvB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,cAAc;CACd,eAAe;EAAC;EAAM;EAAM;EAAM;CAAI;CACtC,cAAc;CACd,YAAY;CACZ,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,oBAAoB;CACpB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,oBAAoB;CACpB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,cAAc;CACd,wBAAwB;CACxB,wBAAwB;CACxB,sBAAsB;CACtB,sBAAsB;CACtB,6BAA6B;CAC7B,8BAA8B;CAC9B,2BAA2B;CAC3B,uBAAuB;CACvB,uBAAuB;CACvB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,mBAAmB;CACnB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,iBAAiB;CACjB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,gBAAgB;CAChB,gBAAgB;CAChB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,UAAU;CACV,UAAU;CACV,YAAY;CACZ,UAAU;CACV,UAAU;CACV,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,gBAAgB;CAChB,gBAAgB;CAChB,mBAAmB;CACnB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,KAAsC;CACjD,eAAe;CACf,aAAa;CACb,eAAe;CACf,eAAe;CACf,uBAAuB;CACvB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,cAAc;CACd,eAAe;EAAC;EAAM;EAAM;EAAM;CAAI;CACtC,cAAc;CACd,YAAY;CACZ,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,oBAAoB;CACpB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,oBAAoB;CACpB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,cAAc;CACd,wBAAwB;CACxB,wBAAwB;CACxB,sBAAsB;CACtB,sBAAsB;CACtB,6BAA6B;CAC7B,8BAA8B;CAC9B,2BAA2B;CAC3B,uBAAuB;CACvB,uBAAuB;CACvB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,mBAAmB;CACnB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,iBAAiB;CACjB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,gBAAgB;CAChB,gBAAgB;CAChB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,UAAU;CACV,UAAU;CACV,YAAY;CACZ,UAAU;CACV,UAAU;CACV,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,gBAAgB;CAChB,gBAAgB;CAChB,mBAAmB;CACnB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,KAA0C;CACrD,eAAe;CACf,aAAa;CACb,eAAe;CACf,eAAe;CACf,uBAAuB;CACvB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,cAAc;CACd,eAAe;EAAC;EAAM;EAAM;EAAM;CAAI;CACtC,cAAc;CACd,YAAY;CACZ,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,oBAAoB;CACpB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,oBAAoB;CACpB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,cAAc;CACd,wBAAwB;CACxB,wBAAwB;CACxB,sBAAsB;CACtB,sBAAsB;CACtB,6BAA6B;CAC7B,8BAA8B;CAC9B,2BAA2B;CAC3B,uBAAuB;CACvB,uBAAuB;CACvB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,mBAAmB;CACnB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,iBAAiB;CACjB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,gBAAgB;CAChB,gBAAgB;CAChB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,UAAU;CACV,UAAU;CACV,YAAY;CACZ,UAAU;CACV,UAAU;CACV,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,gBAAgB;CAChB,gBAAgB;CAChB,mBAAmB;CACnB,wBAAwB;CACxB,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,aAAa;CACb,gBAAgB;CAChB,cAAc;CACd,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;AACX,GAEa,KAAiB;CAC5B,2BAA2B;CAC3B,wBAAwB;CACxB,2BAA2B;CAC3B,0BAA0B;CAC1B,mCAAmC;CACnC,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,yBAAyB;CACzB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gCAAgC;CAChC,6BAA6B;CAC7B,gCAAgC;CAChC,gCAAgC;CAChC,iCAAiC;CACjC,2BAA2B;CAC3B,2BAA2B;CAC3B,yBAAyB;CACzB,yBAAyB;CACzB,2BAA2B;CAC3B,yBAAyB;CACzB,0BAA0B;CAC1B,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B;CAC1B,4BAA4B;CAC5B,6BAA6B;CAC7B,4BAA4B;CAC5B,uBAAuB;CACvB,4BAA4B;CAC5B,0BAA0B;CAC1B,6BAA6B;CAC7B,iCAAiC;CACjC,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,4BAA4B;CAC5B,8BAA8B;CAC9B,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,8BAA8B;CAC9B,kCAAkC;CAClC,8BAA8B;CAC9B,iCAAiC;CACjC,yBAAyB;CACzB,oCAAoC;CACpC,oCAAoC;CACpC,kCAAkC;CAClC,kCAAkC;CAClC,0CAA0C;CAC1C,2CAA2C;CAC3C,wCAAwC;CACxC,oCAAoC;CACpC,oCAAoC;CACpC,wCAAwC;CACxC,qCAAqC;CACrC,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,+BAA+B;CAC/B,6BAA6B;CAC7B,wBAAwB;CACxB,qBAAqB;CACrB,wBAAwB;CACxB,0BAA0B;CAC1B,uBAAuB;CACvB,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,4BAA4B;CAC5B,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,uBAAuB;CACvB,qBAAqB;CACrB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,qBACE;CACF,qBAAqB;CACrB,qBAAqB;CACrB,4BAA4B;CAC5B,4BAA4B;CAC5B,+BAA+B;CAC/B,oCAAoC;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,2BAA2B;CAC3B,2BAA2B;CAC3B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;AACtB,GAEa,KAAgB;CAC3B,2BAA2B;CAC3B,wBAAwB;CACxB,2BAA2B;CAC3B,0BAA0B;CAC1B,mCAAmC;CACnC,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,yBAAyB;CACzB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gCAAgC;CAChC,6BAA6B;CAC7B,gCAAgC;CAChC,gCAAgC;CAChC,iCAAiC;CACjC,2BAA2B;CAC3B,2BAA2B;CAC3B,yBAAyB;CACzB,yBAAyB;CACzB,2BAA2B;CAC3B,yBAAyB;CACzB,0BAA0B;CAC1B,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B;CAC1B,4BAA4B;CAC5B,6BAA6B;CAC7B,4BAA4B;CAC5B,uBAAuB;CACvB,4BAA4B;CAC5B,0BAA0B;CAC1B,6BAA6B;CAC7B,iCAAiC;CACjC,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,4BAA4B;CAC5B,8BAA8B;CAC9B,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,8BAA8B;CAC9B,kCAAkC;CAClC,8BAA8B;CAC9B,iCAAiC;CACjC,yBAAyB;CACzB,oCAAoC;CACpC,oCAAoC;CACpC,kCAAkC;CAClC,kCAAkC;CAClC,0CAA0C;CAC1C,2CAA2C;CAC3C,wCAAwC;CACxC,oCAAoC;CACpC,oCAAoC;CACpC,wCAAwC;CACxC,qCAAqC;CACrC,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,+BAA+B;CAC/B,6BAA6B;CAC7B,wBAAwB;CACxB,qBAAqB;CACrB,wBAAwB;CACxB,0BAA0B;CAC1B,uBAAuB;CACvB,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,4BAA4B;CAC5B,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,uBAAuB;CACvB,qBAAqB;CACrB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,qBACE;CACF,qBAAqB;CACrB,qBAAqB;CACrB,4BAA4B;CAC5B,4BAA4B;CAC5B,+BAA+B;CAC/B,oCAAoC;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,2BAA2B;CAC3B,2BAA2B;CAC3B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;AACtB,GAEa,KAAwB;CACnC,2BAA2B;CAC3B,wBAAwB;CACxB,2BAA2B;CAC3B,0BAA0B;CAC1B,mCAAmC;CACnC,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,yBAAyB;CACzB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gCAAgC;CAChC,6BAA6B;CAC7B,gCAAgC;CAChC,gCAAgC;CAChC,iCAAiC;CACjC,2BAA2B;CAC3B,2BAA2B;CAC3B,yBAAyB;CACzB,yBAAyB;CACzB,2BAA2B;CAC3B,yBAAyB;CACzB,0BAA0B;CAC1B,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B;CAC1B,4BAA4B;CAC5B,6BAA6B;CAC7B,4BAA4B;CAC5B,uBAAuB;CACvB,4BAA4B;CAC5B,0BAA0B;CAC1B,6BAA6B;CAC7B,iCAAiC;CACjC,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,4BAA4B;CAC5B,8BAA8B;CAC9B,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,8BAA8B;CAC9B,kCAAkC;CAClC,8BAA8B;CAC9B,iCAAiC;CACjC,yBAAyB;CACzB,oCAAoC;CACpC,oCAAoC;CACpC,kCAAkC;CAClC,kCAAkC;CAClC,0CAA0C;CAC1C,2CAA2C;CAC3C,wCAAwC;CACxC,oCAAoC;CACpC,oCAAoC;CACpC,wCAAwC;CACxC,qCAAqC;CACrC,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,+BAA+B;CAC/B,6BAA6B;CAC7B,wBAAwB;CACxB,qBAAqB;CACrB,wBAAwB;CACxB,0BAA0B;CAC1B,uBAAuB;CACvB,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,4BAA4B;CAC5B,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,uBAAuB;CACvB,qBAAqB;CACrB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,qBACE;CACF,qBAAqB;CACrB,qBAAqB;CACrB,4BAA4B;CAC5B,4BAA4B;CAC5B,+BAA+B;CAC/B,oCAAoC;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,2BAA2B;CAC3B,2BAA2B;CAC3B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;AACtB,GAEa,KAA4B;CACvC,2BAA2B;CAC3B,wBAAwB;CACxB,2BAA2B;CAC3B,0BAA0B;CAC1B,mCAAmC;CACnC,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,yBAAyB;CACzB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gCAAgC;CAChC,6BAA6B;CAC7B,gCAAgC;CAChC,gCAAgC;CAChC,iCAAiC;CACjC,2BAA2B;CAC3B,2BAA2B;CAC3B,yBAAyB;CACzB,yBAAyB;CACzB,2BAA2B;CAC3B,yBAAyB;CACzB,0BAA0B;CAC1B,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B;CAC1B,4BAA4B;CAC5B,6BAA6B;CAC7B,4BAA4B;CAC5B,uBAAuB;CACvB,4BAA4B;CAC5B,0BAA0B;CAC1B,6BAA6B;CAC7B,iCAAiC;CACjC,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,6BAA6B;CAC7B,4BAA4B;CAC5B,8BAA8B;CAC9B,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,8BAA8B;CAC9B,kCAAkC;CAClC,8BAA8B;CAC9B,iCAAiC;CACjC,yBAAyB;CACzB,oCAAoC;CACpC,oCAAoC;CACpC,kCAAkC;CAClC,kCAAkC;CAClC,0CAA0C;CAC1C,2CAA2C;CAC3C,wCAAwC;CACxC,oCAAoC;CACpC,oCAAoC;CACpC,wCAAwC;CACxC,qCAAqC;CACrC,gCAAgC;CAChC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,+BAA+B;CAC/B,6BAA6B;CAC7B,wBAAwB;CACxB,qBAAqB;CACrB,wBAAwB;CACxB,0BAA0B;CAC1B,uBAAuB;CACvB,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,4BAA4B;CAC5B,4BAA4B;CAC5B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,uBAAuB;CACvB,qBAAqB;CACrB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,qBACE;CACF,qBAAqB;CACrB,qBAAqB;CACrB,4BAA4B;CAC5B,4BAA4B;CAC5B,+BAA+B;CAC/B,oCAAoC;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,2BAA2B;CAC3B,2BAA2B;CAC3B,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;AACtB,GCnuCa,IAAe,EAAiC;CAC3D,QAAQ,KAAA;CACR,KAAK;CACL,cAAc,KAAA;CACd,gBAAgB,KAAA;CAChB,aAAa;CACb,qBAAqB;CACrB,UAAU;CACV,kBAAkB;CAClB,aAAa;CACb,OAAO;AACT,CAAC;AAGD,SAAgB,KAAgC;CAC9C,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,KAAmB;CACjC,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,GAAmB,GAAuD;CACxF,IAAM,EAAE,WAAQ,oBAAiB,EAAW,CAAY;CAExD,OAAO,QACC,IAAI,KAAK,aAAa,GAAQ;EAAE,GAAG;EAAc,GAAG;CAAQ,CAAC,GACnE;EAAC;EAAQ;EAAc;CAAO,CAChC;AACF;AAGA,SAAgB,GAAqB,GAA2D;CAC9F,IAAM,EAAE,WAAQ,sBAAmB,EAAW,CAAY;CAE1D,OAAO,QACC,IAAI,KAAK,eAAe,GAAQ;EAAE,GAAG;EAAgB,GAAG;CAAQ,CAAC,GACvE;EAAC;EAAQ;EAAgB;CAAO,CAClC;AACF;AAGA,SAAgB,KAAmC;CACjD,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,IAAmD;CACjE,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,KAA6B;CAC3C,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,IAA6C;CAC3D,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,KAAmC;CACjD,OAAO,EAAW,CAAY,EAAE;AAClC;AAGA,SAAgB,IAAkC;CAChD,OAAO,EAAW,CAAY,EAAE;AAClC;;;ACzEA,SAAgB,GAAkB,EAChC,gBACA,cAAW,YACkC;CAK7C,OAJI,MAAa,SACR,MAAgB,SAAS,KAAwB,KAGnD,MAAgB,SAAS,KAAY;AAC9C;;;ACVA,IAAa,KAAsB,IAAI,IAA2B;CAChE;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AASD,SAAgB,GACd,GACA,GAC0B;CAK1B,OAJI,MAAe,WAIZ,MAAsB,SAAS,SAAS,UAHtC;AAIX;AAGA,SAAgB,GACd,GACA,GACuB;CAKvB,OAJI,MAAe,WAIZ,IAAqB,SAAS,WAH5B;AAIX;AAaA,SAAgB,GACd,GACA,GACA,GACA,GACkB;CAClB,IAAI,MAAgB,QAClB,OAAO;CAGT,IAAM,IAAU,GAAoB,IAAI,CAAoC,GAEtE,IAAS,IACV,EAAM,GAAG,IAFA,MAAwB,SAAS,IAAI,OAG/C,GACE,IAAW,IACZ,EAAM,GAAG,EAAY,MACtB;CAEJ,OAAO;EACL,GAAG;EACH,aAAa;EACb,eAAe;EACf,GAAI,MAAqB,WAAW,EAAE,gBAAgB,EAAO,IAAI,CAAC;CACpE;AACF;;;ACpBA,SAAS,KAAiC;CACxC,IAAM,CAAC,GAAS,KAAc,EAAS,EAAK;CAkC5C,OAhCA,QAAgB;EACd,IAAM,IACJ,EAAS,OAAO,YACZ,EAAkB,4BAClB,EAAS,OAAO,QACd,EAAkB,8BAClB,KAAA;EAER,IAAI,CAAC,GACH;EAGF,IAAI,IAAU;EAEd,CAAC,YAAY;GACX,IAAM,IAAQ,MAAM,EAAM;GAE1B,AAAI,KACF,EAAW,CAAK;EAEpB,GAAG;EAEH,IAAM,IACJ,EAAS,OAAO,YAAY,4BAA4B,6BACpD,IAAe,EAAkB,iBAAiB,GAAW,CAAU;EAE7E,aAAa;GAEX,AADA,IAAU,IACV,EAAa,OAAO;EACtB;CACF,GAAG,CAAC,CAAC,GAEE;AACT;AAiBA,SAAgB,IAA4B;CAC1C,IAAM,CAAC,GAAS,KAAc,EAAS,EAAK;CAqB5C,OAnBA,QAAgB;EACd,IAAI,IAAU;EAEd,CAAC,YAAY;GACX,IAAM,IAAQ,MAAM,EAAkB,sBAAsB;GAE5D,AAAI,KACF,EAAW,CAAK;EAEpB,GAAG;EAEH,IAAM,IAAe,EAAkB,iBAAiB,uBAAuB,CAAU;EAEzF,aAAa;GAEX,AADA,IAAU,IACV,EAAa,OAAO;EACtB;CACF,GAAG,CAAC,CAAC,GAEE;AACT;AAGA,IAAa,MAAiB,EAC5B,WACA,QACA,iBACA,mBACA,iBAAc,UACd,cAAW,UACX,iBAAc,QACd,kBACwB;CACxB,IAAM,IAAoB,EAAqB,GACzC,IAAqB,GAAsB,GAE3C,IAAsB,GAAmB,GAAa,CAAiB,GACvE,IAAmB,GAAgB,GAAU,CAAkB,GAC/D,IAAc,MAAQ,EAAY,QAAQ,QAAQ,QAElD,IAAQ,SAYL;EACL;EACA,KAAK;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAjBY,GAJO,GAAkB;GACrC,aAAa;GACb,UAAU;EACZ,CAEE,GACA,GACA,GACA,CAaA;CACF,IACC;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,OAAO,kBAAC,EAAa,UAAd;EAA8B;EAAQ;CAAgC,CAAA;AAC/E,GCzKM,KAA6C,IAAI,IAAiB;CACtE;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAeD,SAAS,GAAgB,GAAyB,GAAiC;CACjF,IAAM,KAAU,MAAkB,OAAO,CAAK;CAE9C,QAAQ,GAAR;EACE,KAAK,eACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,GAAG;GACtB,YAAY,KAAK,MAAM,EAAM,qBAAqB,EAAM,iBAAiB;GACzE,eAAe,EAAM,qBAAqB;EAC5C;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,cAAc;GACvC,YAAY,KAAK,MAAM,EAAM,iBAAiB,EAAM,iBAAiB;EACvE;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,cAAc;GACvC,YAAY,KAAK,MAAM,EAAM,iBAAiB,EAAM,iBAAiB;EACvE;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,cAAc;GACvC,YAAY,KAAK,MAAM,EAAM,iBAAiB,EAAM,iBAAiB;EACvE;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,kBAAkB;GAC3C,YAAY,KAAK,MAAM,EAAM,iBAAiB,EAAM,iBAAiB;EACvE;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,cAAc;GACvC,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,iBAAiB;EACrE;EACF,KAAK,YACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,gBAAgB;GACzC,YAAY,KAAK,MAAM,EAAM,eAAe,IAAI;EAClD;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,gBAAgB;GACzC,YAAY,KAAK,MAAM,EAAM,kBAAkB,EAAM,cAAc;EACrE;EACF,KAAK,mBACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,kBAAkB;GAC3C,YAAY,KAAK,MAAM,EAAM,kBAAkB,EAAM,iBAAiB;GACtE,eAAe,EAAM,kBAAkB;GACvC,eAAe;EACjB;EACF,KAAK,aACH,OAAO;GACL,YAAY,EAAM;GAClB,UAAU;GACV,YAAY,KAAK,MAAM,KAAK,EAAM,cAAc;EAClD;EACF,KAAK,WACH,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,gBAAgB;GACzC,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,cAAc;GAChE,aAAa,CAAC,cAAc;EAC9B;EACF,SACE,OAAO;GACL,UAAU,EAAM;GAChB,YAAY,EAAO,EAAM,gBAAgB;GACzC,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,cAAc;EAClE;CACJ;AACF;AAOA,SAAS,GAAc,GAAyB,GAA6B;CAC3E,QAAQ,GAAR;EACE,KAAK,OACH,OAAO;GAAE,OAAO,EAAM;GAAe,SAAS,EAAM;EAAW;EACjE,KAAK,UACH,OAAO,EAAE,OAAO,EAAM,YAAY;EACpC,KAAK,eACH,OAAO,EAAE,OAAO,EAAM,iBAAiB;EACzC,KAAK,WACH,OAAO,EAAE,OAAO,EAAM,aAAa;EACrC,KAAK,WACH,OAAO,EAAE,OAAO,EAAM,aAAa;EACrC,KAAK,SACH,OAAO,EAAE,OAAO,EAAM,WAAW;EACnC,SACE,OAAO,EAAE,OAAO,EAAM,cAAc;CACxC;AACF;AAiBA,IAAa,IAAO,EAA8B,SAChD,EAAE,aAAU,QAAQ,WAAQ,WAAW,UAAO,aAAU,sBAAmB,GAAG,KAC9E,GACA;CACA,IAAM,IAAQ,EAAc;CAI5B,OACE,kBAAC,GAAD;EACO;EACL,mBALF,MAAsB,GAAiB,IAAI,CAAO,IAAI,WAAW,KAAA;EAM/D,OAAO;GACL,EAAE,YAAY,EAAM,WAAW;GAC/B,GAAgB,GAAO,CAAO;GAC9B,GAAc,GAAO,CAAK;GAC1B;EACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,CAAC,GClJY,KAAY,EAAiC,SACxD,EACE,UACA,aACA,YACA,aACA,iBAAc,IACd,aAAU,WACV,UACA,aACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAW,MAAY,YAEvB,IAAuB;EAC3B,eAAe;EACf,YAAY;EACZ,KAAK,EAAM;EACX,iBAAiB,EAAM;EACvB,mBAAmB,EAAM;EACzB,WAAW;EACX,OAAO;CACT,GAEM,IACJ,kBAAA,GAAA,EAAA,UAAA;EACG,KAAW,kBAAC,GAAD;GAAQ,OAAO,EAAE,YAAY,EAAE;aAAI;EAAgB,CAAA;EAE/D,kBAAC,GAAD;GAAQ,OAAO;IAAE,MAAM;IAAG,KAAK;GAAE;aAAjC,CACE,kBAAC,GAAD;IACE,SAAS,IAAW,YAAY;IAChC,OAAO,IAAW,QAAQ;IAC1B,eAAe;IACf,eAAc;cAEb;GACG,CAAA,GACL,KACC,kBAAC,GAAD;IACE,SAAS,IAAW,SAAS;IAC7B,OAAO,IAAW,YAAY;IAC9B,eAAe;IACf,eAAc;cAEb;GACG,CAAA,CAEF;;EAEP,KACC,kBAAC,GAAD;GACE,OAAO;IAAE,YAAY;IAAG,eAAe;IAAO,YAAY;IAAU,KAAK,EAAM;GAAO;aAErF;EACK,CAAA;CAEV,EAAA,CAAA;CAWJ,OARK,IASH,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB,EAAE,UAAU,CAAC,CAAC,EAAS;EAC3C,OAAO;GACL;GACA;IAAE,UAAU;IAAY,SAAS,IAAW,EAAM,kBAAkB;GAAE;GACtE;EACF;EACA,GAAI;aAEF,EAAE,iBACF,kBAAA,GAAA,EAAA,UAAA,CACG,GACA,KAAW,CAAC,IACX,kBAAC,GAAD;GACE,eAAc;GACd,OAAO,CAAC,EAAW,cAAc,EAAE,iBAAiB,EAAM,cAAc,CAAC;EAC1E,CAAA,IACC,IACJ,EAAA,CAAA;CAEK,CAAA,IA9BT,kBAAC,GAAD;EAAa;EAAK,OAAO,CAAC,GAAW,CAAK;EAAG,GAAI;YAC9C;CACK,CAAA;AA8Bd,CAAC,GC/IY,KAA0C;CAAE,IAAI;CAAI,IAAI;CAAI,IAAI;AAAG;AAEhF,SAAgB,GACd,GACA,GACA;CACA,QAAQ,GAAR;EACE,KAAK,QACH,OAAO,EAAM;EACf,KAAK,SACH,OAAO,EAAM;EACf,KAAK,UACH,OAAO,EAAM;EACf,KAAK,UACH,OAAO,EAAM;EACf,KAAK,OACH,OAAO,EAAM;EACf,KAAK,UACH,OAAO,EAAM;EACf,KAAK,SACH,OAAO,EAAM;EACf,SACE,OAAO,EAAM;CACjB;AACF;AAEA,SAAgB,GAAuB,GAA2B;CAChE,OAAO,IACH;EAAE,YAAY;EAAe,oBAAoB;EAAO,mBAAmB;CAAiB,IAC5F;EAAE,YAAY;EAAgB,mBAAmB;CAAgB;AACvE;;;ACkBA,SAAS,GAAiB,GAAiD;CAKzE,OAJI,WAAW,KAAQ,MAAM,QAAS,EAAwB,KAAK,IAC1D,KAGF,OAAQ,EAAwB,OAAQ,YAAY,EAAE,UAAU;AACzE;AAGA,SAAS,GAAS,GAAqD;CACrE,OAAO,MAAS,aAAa,MAAS,YAAY,IAAO,KAAA;AAC3D;AA2BA,IAAa,KAAQ,EAAE,SAAM,UAAO,MAAM,UAAO,WAAQ,UAAO,UAAO,eAAuB;CAC5F,IAAM,IAAQ,EAAc,GACtB,IAAK,GAAc,IACnB,IAAO,GAAiB,GAAO,CAAK,GAEpC,IAAkB,GAAiB,CAAI,IAAI,EAAK,UAAW,EAAK,WAAW,aAC3E,IAAS,GAAiB,CAAI,IAAI,EAAK,MAAM,KAAA,GAC7C,IAAQ,GAAiB,CAAI,IAC/B,EAAK,MACH,KAAA,IACA,EAAK,OAAO,KAAK,GAAG,MAClB,kBAAC,GAAD;EAEE,GAAG,EAAE;EACL,UAAU,GAAS,EAAE,QAAQ;EAC7B,UAAU,GAAS,EAAE,QAAQ;EAC7B,WAAW,EAAE;CACd,GALM,CAKN,CACF,IACH,CAAC,kBAAC,GAAD,EAAc,GAAG,EAAK,KAAO,GAAlB,CAAkB,CAAC,GAE7B,IAAqB,GAAuB,CAAK;CAevD,OAbI,IAEA,kBAAC,IAAD;EACE,KAAK,iBAAiB,EAAgB,IAAI,EAAO;EACjD,OAAO,KAAS;EAChB,QAAQ,KAAU;EACZ;EACC;EACP,GAAI;CACL,CAAA,IAKH,kBAAC,IAAD;EACE,SAAS;EACT,OAAO,KAAS;EAChB,QAAQ,KAAU;EACZ;EACC;EACP,GAAI;YAEH;CACE,CAAA;AAET,GCpHM,KAAY,EAAS,wBAAwB,EAAC,GAC9C,KAAe,EAAS,wBAAwB,CAAI,GACpD,KAAiB,EAAS,wBAAwB,EAAM;AAO9D,SAAS,GAAmB,GAAkB;CAC5C,IAAM,IAAQ,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE;CAiB5C,OAfA,QAAgB;EACd,IAAM,IAAY,EAAS,KACzB,EAAS,OAAO,GAAO;GACrB,SAAS;GACT;GACA,QAAQ,EAAO;GACf,iBAAiB;EACnB,CAAC,CACH;EAIA,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG,CAAC,GAAO,CAAQ,CAAC,GAEb;AACT;AAGA,SAAS,GAA0B,GAAkB,GAAe;CAClE,IAAM,IAAQ,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE;CAoB5C,OAlBA,QAAgB;EACd,IAAM,IAAY,EAAS,SAAS,CAClC,EAAS,MAAM,CAAK,GACpB,EAAS,KACP,EAAS,OAAO,GAAO;GACrB,SAAS;GACT;GACA,QAAQ,EAAO;GACf,iBAAiB;EACnB,CAAC,CACH,CACF,CAAC;EAID,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG;EAAC;EAAO;EAAU;CAAK,CAAC,GAEpB;AACT;AAOA,IAAM,MAAiB,EAAE,cAQrB,kBAAC,IAAD;CAAsB,WAPP,GAAmB,IAClB,EAAS,YAAY;EACrC,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,mBAAmB,mBAAmB;CACtD,CAGwB;WACpB,kBAAC,GAAD;EACQ;EACN,UAAS;EACT,GAAE;CACH,CAAA;AACQ,CAAA,GAQT,MAAmB,EAAE,cAAwB;CACjD,IAAM,IAAU,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE;CAgB9C,OAdA,QAAgB;EACd,IAAM,IAAS,EAAO,MAAM,EAAO,IAAI,GACjC,IAAY,EAAS,KACzB,EAAS,SAAS,CAChB,EAAS,OAAO,GAAS;GAAE,SAAS;GAAM,UAAU;GAAK;GAAQ,iBAAiB;EAAM,CAAC,GACzF,EAAS,OAAO,GAAS;GAAE,SAAS;GAAG,UAAU;GAAK;GAAQ,iBAAiB;EAAM,CAAC,CACxF,CAAC,CACH;EAIA,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG,CAAC,CAAO,CAAC,GAGV,kBAAC,IAAD;EACQ;EACG;EACT,GAAE;CACH,CAAA;AAEL,GAWM,MAAqB,EAAE,cAAwB;CACnD,IAAM,IAAW,GAAmB,IAAI,GAClC,IAAQ;EAAC;EAAG;EAAK;EAAK;EAAM;EAAK;CAAC,GAClC,IAAY,EAAS,YAAY;EACrC,YAAY;EACZ,aAAa;GACX;GACA;GACA;GACA;GACA;GACA;EACF;CACF,CAAC,GACK,IAAU,EAAS,YAAY;EAAE,YAAY;EAAO,aAAa;GAAC;GAAG;GAAG;GAAG;GAAG;GAAG;EAAC;CAAE,CAAC;CAE3F,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAAY;EAAM,GAAE;CAAiB,CAAA,GACrC,kBAAC,IAAD;EAAsB;EAAoB;YACxC,kBAAC,GAAD;GAAY;GAAM,UAAS;GAAU,GAAE;EAAuB,CAAA;CACrD,CAAA,CACX,EAAA,CAAA;AAEN;AAGA,SAAS,EAAY,GAAY,GAAY,GAAe;CAC1D,OAAO,aAAa,EAAG,IAAI,EAAG,UAAU,EAAM,cAAc,CAAC,EAAG,IAAI,CAAC,EAAG;AAC1E;AAUA,IAAM,MAAiB,EAAE,OAAI,OAAI,SAAM,eAAgC;CACrE,IAAM,IAAW,GAA0B,MAAM,CAAK,GAChD,IAAQ;EAAC;EAAG;EAAK;EAAK;CAAC;CAY7B,OACE,kBAAC,IAAD;EAAoB;EAAQ;EAAI,GAAG;EAAS;EAAe,SAZ7C,EAAS,YAAY;GAAE,YAAY;GAAO,aAAa;IAAC;IAAG;IAAK;IAAG;GAAC;EAAE,CAYzB;EAAoB,WAX/D,EAAS,YAAY;GACrC,YAAY;GACZ,aAAa;IACX,EAAY,GAAI,GAAI,CAAC;IACrB,EAAY,GAAI,GAAI,EAAG;IACvB,EAAY,GAAI,GAAI,CAAC;IACrB,EAAY,GAAI,GAAI,CAAC;GACvB;EACF,CAGiF;CAAY,CAAA;AAE/F,GA8BM,KAAU,IAAI,IAAgD;CAClE,CAAC,IAAS,EAAa;CACvB,CAAC,GAAW,EAAe;CAC3B,CAAC,IAAa,EAAiB;CAC/B,CAAC,IA5BuB,EAAE,cAExB,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GACQ;GACN,GAAE;EACH,CAAA;EACD,kBAAC,IAAD;GAAe,IAAI;GAAG,IAAI;GAAS;GAAM,OAAO;EAAI,CAAA;EACpD,kBAAC,IAAD;GAAe,IAAI;GAAG,IAAI;GAAS;GAAM,OAAO;EAAM,CAAA;EACtD,kBAAC,IAAD;GAAe,IAAI;GAAI,IAAI;GAAS;GAAM,OAAO;EAAM,CAAA;CACvD,EAAA,CAAA,CAkByB;AAC/B,CAAC,GAyBY,MAAgB,EAC3B,SACA,aAAU,IACV,UAAO,MACP,UACA,WACA,UACA,eACuB;CACvB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,IADY,KAAW,CAAC,IACH,GAAQ,IAAI,CAAI,IAAI,KAAA;CAE/C,IAAI,CAAC,GACH,OACE,kBAAC,GAAD;EAAY;EAAY;EAAa;EAAe;EAAe;EAAc;CAAQ,CAAA;CAI7F,IAAM,IAAK,GAAc,IACnB,IAAO,GAAiB,GAAO,CAAK,GACpC,IAAqB,GAAuB,CAAK;CAEvD,OACE,kBAAC,IAAD;EAAK,SAAS,EAAK;EAAS,OAAO,KAAS;EAAI,QAAQ,KAAU;EAAI,GAAI;YACxE,kBAAC,GAAD,EAAc,QAAO,CAAA;CAClB,CAAA;AAET,GCvPM,KAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,GAEM,KAAuC;CAAE,IAAI;CAAI,IAAI;CAAI,IAAI;CAAI,IAAI;AAAG,GASxE,KAAkD;CAAE,IAAI;CAAK,IAAI;CAAK,IAAI;CAAG,IAAI;AAAI;AAG3F,SAAS,GAAY,GAA2B;CAC9C,IAAI,IAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAC/B,IAAQ,IAAO,KAAK,EAAK,WAAW,CAAC,MAAO;CAG9C,OAAO,GAAW,IAAO,GAAW;AACtC;AAGA,SAAS,GAAY,GAAsB;CACzC,IAAM,IAAQ,EAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;CAUrD,OARI,EAAM,WAAW,IACZ,KAGL,EAAM,WAAW,IACZ,EAAM,GAAG,OAAO,CAAC,EAAE,YAAY,IAGjC,EAAM,GAAG,OAAO,CAAC,EAAE,YAAY,IAAI,EAAM,EAAM,SAAS,GAAG,OAAO,CAAC,EAAE,YAAY;AAC1F;AAOA,SAAS,GAAe,GAAyB,GAAiC;CAChF,QAAQ,GAAR;EACE,KAAK,QACH,OAAO;GAAE,iBAAiB,EAAM;GAAO,eAAe;EAAO;EAC/D,KAAK,SACH,OAAO;GAAE,iBAAiB,EAAM;GAAQ,eAAe;EAAO;EAChE,KAAK,UAEH,OAAO;GAAE,iBAAiB,EAAM;GAAS,eAAe;EAAqB;EAC/E,KAAK,UACH,OAAO;GAAE,iBAAiB,EAAM;GAAS,eAAe;EAAO;EACjE,KAAK,OACH,OAAO;GAAE,iBAAiB,EAAM;GAAM,eAAe;EAAO;EAC9D,KAAK,UACH,OAAO;GAAE,iBAAiB,EAAM;GAAS,eAAe;EAAO;EACjE,KAAK,SACH,OAAO;GAAE,iBAAiB,EAAM;GAAQ,eAAe;EAAO;EAChE,KAAK,QAEH,OAAO;GAAE,iBAAiB;GAAW,eAAe;EAAO;EAC7D,KAAK,SACH,OAAO;GAAE,iBAAiB,EAAM;GAAO,eAAe;EAAO;CACjE;AACF;AA4BA,IAAa,MAAU,EAAE,UAAO,IAAI,QAAK,QAAK,UAAO,MAAM,UAAO,eAAyB;CACzF,IAAM,IAAQ,EAAc,GACtB,IAAsB,EAAuB,GAE7C,IAAgB,MAAU,IAAO,GAAY,CAAI,IAAI,SACrD,IAAW,GAAY,CAAI,GAC3B,IAAM,GAAS,IACf,EAAE,oBAAiB,qBAAkB,GAAe,GAAO,CAAa,GACxE,IACJ,MAAwB,SAAS,8BAA8B;CAEjE,OACE,kBAAC,GAAD;EACE,YAAA;EACA,MAAK;EACL,oBAAoB,MAAQ,KAAQ,KAAA,MAAc;EAClD,OAAO,CACL;GACE,OAAO;GACP,QAAQ;GACR,cAAc,EAAM;GACpB,UAAU;GACV,YAAY;GACZ,gBAAgB;GAChB,iBAAiB,IAAM,KAAA,IAAY;GACnC,aAAa;GACb,aAAa;EACf,GACA,CACF;YAEC,IACC,kBAAC,GAAD;GACE,QAAO;GACP,QAAQ,EAAE,KAAK,EAAI;GACnB,6BAAA;GACA,2BAA0B;GAC1B,YAAW;GACX,OAAO;IAAE,OAAO;IAAQ,QAAQ;GAAO;EACxC,CAAA,IAED,kBAAC,GAAD;GACE,6BAAA;GACA,2BAA0B;GAC1B,OAAO;IACL,YAAY,EAAM;IAClB,YAAY,OAAO,EAAM,kBAAkB;IAC3C,UAAU,EAAM,eAAe,GAAoB;IACnD,YAAY,EAAM,eAAe,GAAoB;IACrD,OAAO;GACT;aAEC;EACG,CAAA;CAEJ,CAAA;AAEV;;;ACrKA,SAAS,GACP,GACA,GACA,GACe;CACf,QAAQ,GAAR;EACE,KAAK,UACH,OAAO;GAAE,iBAAiB,EAAM;GAAe,OAAO,EAAM;EAAc;EAC5E,KAAK,WACH,OAAO;GAAE,iBAAiB,EAAM;GAAgB,OAAO,EAAM;EAAe;EAC9E,KAAK,WACH,OAAO;GAAE,iBAAiB,EAAM;GAAgB,OAAO,EAAM;EAAe;EAC9E,KAAK,SACH,OAAO;GAAE,iBAAiB,EAAM;GAAc,OAAO,EAAM;EAAa;EAC1E,KAAK,WACH,OAAO;GACL,iBAAiB,MAAgB,SAAS,EAAM,QAAQ,EAAM;GAC9D,OAAO,EAAM;EACf;CACJ;AACF;AAsBA,IAAa,MAAS,EAAE,aAAU,UAAU,SAAM,IAAO,aAAU,WAAQ,eAAwB;CACjG,IAAM,IAAQ,EAAc,GAEtB,EAAE,oBAAiB,aAAU,GAAiB,GADhC,EACuC,GAAa,CAAO,GAEzE,IACJ,kBAAC,GAAD;EACE,QAAO;EACP,OAAO,CACL;GACE,SAAS;GACT,cAAc,EAAM;GACpB,iBAAiB,EAAM;EACzB,GACA,IACI;GACE,UAAU;GACV,KAAK,IAAM,KAAK;GAChB,OAAO,IAAM,KAAK;GAClB,QAAQ;EACV,IACA,IACN;YAEA,kBAAC,GAAD;GACE,QAAO;GACP,OAAO,CACL;IACE,UAAU,IAAM,KAAK;IACrB,QAAQ,IAAM,KAAK;IACnB,mBAAmB,IAAM,IAAI;IAC7B,cAAc,EAAM;IACpB;IACA,YAAY;IACZ,gBAAgB;GAClB,GACA,CACF;aAEC,CAAC,MACC,OAAO,KAAa,YAAY,OAAO,KAAa,WACnD,kBAAC,GAAD;IACE,OAAO;KACL,YAAY,EAAM;KAClB,YAAY,OAAO,EAAM,kBAAkB;KAC3C,UAAU;KACV,YAAY;KACZ;IACF;IAEC;GACG,CAAA,IAEN;EAEA,CAAA;CACF,CAAA;CAYR,OATI,IAEA,kBAAC,GAAD;EAAM,OAAO,EAAE,WAAW,aAAa;YAAvC,CACG,GACA,CACG;MAIH;AACT,GC9Fa,MAAU,EACrB,aAAU,QACV,aACA,gBACA,aACA,iBAAc,IACd,cACA,UACA,GAAG,QACc;CACjB,IAAM,IAAQ,EAAc,GAEtB,IAAS;EACb,MAAM;GAAE,IAAI,EAAM;GAAe,IAAI,EAAM;EAAc;EACzD,SAAS;GAAE,IAAI,EAAM;GAAgB,IAAI,EAAM;EAAe;EAC9D,OAAO;GAAE,IAAI,EAAM;GAAc,IAAI,EAAM;EAAa;EACxD,SAAS;GAAE,IAAI,EAAM;GAAgB,IAAI,EAAM;EAAe;CAChE,EAAE,IAKI,IACJ,MAAY,YAAY,wBAAwB;CAElD,OACE,kBAAC,GAAD;EACE,YAAA;EACA,mBAAkB;EAClB,yBAAwB;EACxB,OAAO,CACL;GACE,eAAe;GACf,YAAY;GACZ,KAAK,EAAM;GACX,iBAAiB;GACjB,mBAAmB,EAAM;GACzB,WAAW;GACX,OAAO;GACP,iBAAiB,EAAO;EAC1B,GACA,CACF;EACA,GAAI;YAjBN,CAmBE,kBAAC,GAAD;GAAM,SAAQ;GAAO,OAAO;IAAE,MAAM;IAAG,UAAU;IAAG,OAAO,EAAO;GAAG;GAClE;EACG,CAAA,IAEJ,KAAe,MACf,kBAAC,GAAD;GACE,OAAO;IAAE,eAAe;IAAO,YAAY;IAAU,KAAK,EAAM;IAAQ,YAAY;GAAE;aADxF,CAGG,KACC,kBAAC,GAAD;IACE,mBAAkB;IAClB,oBAAoB;IACpB,SAAS;IACT,QAAQ,EAAE,kBAAe;KACvB,iBAAiB;KACjB,mBAAmB,EAAM;KACzB,cAAc,EAAM;KACpB,iBAAiB,IAAU,IAAiB;IAC9C;cAEA,kBAAC,GAAD;KACE,OAAO;MACL,YAAY,EAAM;MAClB,UAAU,EAAM;MAChB,YAAY,OAAO,EAAM,kBAAkB;MAC3C,OAAO,EAAO;KAChB;eAEC;IACK,CAAA;GACC,CAAA,GAGZ,KACC,kBAAC,GAAD;IACE,mBAAkB;IAClB,oBAAmB;IACnB,SAAS;IACT,SAAS;IACT,QAAQ,EAAE,kBAAe;KACvB,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,gBAAgB;KAChB,cAAc,EAAM;KACpB,SAAS,IAAU,IAAI;KACvB,iBAAiB,IAAU,IAAiB;IAC9C;cAEA,kBAAC,GAAD;KAAQ,OAAO;MAAE,UAAU,EAAM;MAAc,OAAO,EAAO;KAAG;eAAI;IAAY,CAAA;GACvE,CAAA,CAET;IAEJ;;AAEV,GCxIM,KAAoB,EAAS,wBAAwB,CAAS,GAE9D,KAAuB,KAkFhB,MAAe,EAC1B,SACA,UACA,aACA,YACA,qBAAkB,IAClB,UACA,gBACsB;CACtB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,CAAC,GAAS,KAAc,EAAS,CAAI,GACrC,CAAC,GAAa,KAAkB,EAAS,CAAC,GAE1C,IAAa,EAAO,IAAI,EAAS,MAAM,EAAW,IAAI,QAAQ,EAAE,MAAM,CAAC,EAAE,SACzE,IAAkB,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAChD,IAAa,EAAO,EAAK;CAwE/B,AAtEA,QAAgB;EACd,AAAI,KACF,EAAW,EAAI;CAEnB,GAAG,CAAC,CAAI,CAAC,GAKT,QAAgB;EACV,OAAC,KAAW,EAAW,UAI3B,IAAI,GAAM;GACR,IAAI,GAAe;IAEjB,AADA,EAAW,SAAS,CAAC,GACrB,EAAgB,SAAS,CAAC;IAE1B;GACF;GAWA,AATI,IAAc,MAChB,EAAW,SAAS,CAAW,GAC/B,EAAS,OAAO,GAAY;IAC1B,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM,IAGX,EAAS,OAAO,GAAiB;IAC/B,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EACX,OAAO;GACL,IAAI,GAAe;IACjB,EAAW,EAAK;IAEhB;GACF;GAWA,AATA,EAAS,OAAO,GAAY;IAC1B,SAAS,KAAe,EAAW,IAAI,QAAQ,EAAE;IACjD,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,OAAO,EAAE,kBAAe;IACzB,AAAI,KACF,EAAW,EAAK;GAEpB,CAAC,GACD,EAAS,OAAO,GAAiB;IAC/B,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EACX;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA,EAAM;CACR,CAAC,GAID,QAAgB;EACd,IAAI,CAAC,GACH;EAGF,IAAM,IAAe,EAAY,iBAAiB,4BAChD,IAAU,GAEH,GACR;EAED,aAAa,EAAa,OAAO;CACnC,GAAG,CAAC,GAAM,CAAO,CAAC;CAElB,IAAM,IAAe,QAEjB,EAAa,OAAO;EAClB,oCAAoC;EACpC,2BAA2B;GACzB,EAAW,UAAU;EACvB;EACA,qBAAqB,GAAQ,MAAiB;GAC5C,EAAW,SAAS,KAAK,IAAI,GAAG,EAAa,EAAE,CAAC;EAClD;EACA,wBAAwB,GAAQ,MAAiB;GAK/C,AAJA,EAAW,UAAU,IAEV,KAAK,IAAI,GAAG,EAAa,EAEhC,KAAM,KAKR,IAAU,IAEV,EAAS,OAAO,GAAY;IAC1B,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EAEb;CACF,CAAC,GACH;EAAC;EAAY,EAAM;EAAgB;CAAO,CAC5C;CAUA,OAJK,IAKH,kBAAC,GAAD;EACW;EACT,aAAA;EACA,eAAc;EACd,sBAAA;EACA,gBAAgB;YAEhB,kBAAC,IAAD;GACU;GACR,SAAS,IAAkB,IAAU,KAAA;GACrC,YAAY;GACZ,OAAO;IACL,MAAM;IACN,gBAAgB;IAChB,iBAAiB,EAAM;IACvB,SAAS;GACX;aAEA,kBAAC,GAAD;IAAW,eAAe,CAAC;IAAG,YAAY;cACxC,kBAAC,EAAS,MAAV;KACE,WA7BiB,MAAyB;MAClD,EAAe,EAAE,YAAY,OAAO,MAAM;KAC5C;KA4BU,YAAA;KACA,MAAK;KACL,0BAAA;KACA,OAAO,CACL;MACE,WAAW;MACX,OAAO;MACP,UAAU;MACV,iBAAiB,EAAM;MACvB,qBAAqB,EAAM;MAC3B,sBAAsB,EAAM;MAC5B,aAAa;MACb,cAAc;OAAE,OAAO;OAAG,QAAQ;MAAG;MACrC,eAAe;MACf,cAAc;MACd,WAAW;MACX,WAAW,CAAC,EAAE,cAAW,CAAC;KAC5B,GACA,CACF;eArBF;MAuBE,kBAAC,GAAD;OACE,QAAO;OACP,6BAAA;OACA,2BAA0B;OAC1B,OAAO;QACL,YAAY;QACZ,YAAY,EAAM;QAClB,eAAe,EAAM;OACvB;OACA,GAAI,EAAa;iBAEjB,kBAAC,GAAD,EACE,OAAO;QACL,OAAO;QACP,QAAQ;QACR,cAAc;QACd,iBAAiB,EAAM;QACvB,SAAS;OACX,EACD,CAAA;MACG,CAAA;MAEL,KACC,kBAAC,GAAD;OACE,SAAQ;OACR,OAAO;QACL,mBAAmB,EAAM;QACzB,eAAe,EAAM;QACrB,WAAW;QACX,YAAY,OAAO,EAAM,cAAc;OACzC;iBAEC;MACG,CAAA;MAGP,KACC,kBAAC,GAAD;OAAM,OAAO;QAAE,mBAAmB,EAAM;QAAQ,eAAe,EAAM;OAAO;iBACzE,OAAO,KAAa,WAAW,kBAAC,GAAD;QAAM,SAAQ;QAAQ;OAAe,CAAA,IAAI;MACrE,CAAA;KAEK;;GACN,CAAA;EACM,CAAA;CACd,CAAA,IA1FA;AA4FX,GClTa,KAAY,EAAiC,SACxD,EAAE,iBAAc,cAAc,UAAO,GAAG,KACxC,GACA;CAGA,OACE,kBAAC,GAAD;EACO;EACL,YAAY;EACZ,OAAO;GACL;IAAE,iBAPM,EAOW,EAAM;IAAgB,YAAY;GAAE;GACvD,MAAgB,aACZ;IAAE,OAAO;IAAG,QAAQ;IAAQ,WAAW;GAAU,IACjD;IAAE,OAAO;IAAQ,QAAQ;GAAE;GAC/B;EACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC,GCVY,KAAY,EAAiC,SACxD,EAAE,aAAU,aAAU,WAAW,UAAO,GAAG,KAC3C,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAQ,EAAS,QAAQ,CAAQ,EAAE,OAAO,OAAO;CA8BvD,OA5BI,MAAY,aAEZ,kBAAC,GAAD;EACO;EACL,YAAA;EACA,mBAAkB;EAClB,OAAO,CAAC,EAAE,KAAK,EAAM,OAAO,GAAG,CAAK;EACpC,GAAI;YAEH,EAAM,KAAK,GAAO,MACjB,kBAAC,GAAD;GAGE,OAAO;IACL,iBAAiB,EAAM;IACvB,aAAa;IACb,aAAa,EAAM;IACnB,cAAc,EAAM;IACpB,UAAU;GACZ;aAEC;EACK,GAVD,CAUC,CACT;CACK,CAAA,IAKV,kBAAC,GAAD;EACO;EACL,YAAA;EACA,mBAAkB;EAClB,OAAO,CACL;GACE,iBAAiB,EAAM;GACvB,aAAa;GACb,aAAa,EAAM;GACnB,cAAc,EAAM;GACpB,UAAU;EACZ,GACA,CACF;EACA,GAAI;YAEH,EAAM,KAAK,GAAO,MAEjB,kBAAC,GAAD,EAAA,UAAA,CACG,IAAI,KAAK,kBAAC,IAAD,EAAW,QAAO,uBAAwB,CAAA,GACnD,CACK,EAAA,GAHK,CAGL,CACT;CACK,CAAA;AAEZ,CAAC;;;ACzDD,SAAS,GAAe,GAAyB,GAA+B;CAC9E,QAAQ,GAAR;EACE,KAAK,MACH,OAAO;GACL,WAAW;GACX,UAAU;GACV,iBAAiB;GACjB,mBAAmB,EAAM;GACzB,UAAU,EAAM;EAClB;EACF,KAAK,MACH,OAAO;GACL,WAAW;GACX,UAAU;GACV,iBAAiB,EAAM;GACvB,mBAAmB,EAAM;GACzB,UAAU,EAAM;EAClB;EACF,SACE,OAAO;GACL,WAAW;GACX,UAAU;GACV,iBAAiB,EAAM;GACvB,mBAAmB,EAAM;GACzB,UAAU,EAAM;EAClB;CACJ;AACF;AAEA,SAAS,GAAgB,GAA0B;CACjD,QAAQ,GAAR;EACE,KAAK,MACH,OAAO;EACT,KAAK,MACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAQA,SAAS,GACP,GACA,GACA,GACA,GACe;CACf,IAAI,GACF,OAAO;EACL,iBAAiB,IAAU,wBAAwB;EACnD,aAAa;EACb,OAAO;CACT;CAGF,QAAQ,GAAR;EACE,KAAK,aACH,OAAO;GACL,iBAAiB,EAAM;GACvB,aAAa;GACb,OAAO,EAAM;EACf;EACF,KAAK,eACH,OAAO;GACL,iBAAiB,EAAM;GACvB,aAAa;GACb,OAAO,EAAM;EACf;EACF,KAAK,QACH,OAAO;GACL,iBAAiB,IAAU,EAAM,gBAAgB;GACjD,aAAa;GACb,OAAO,EAAM;EACf;EACF,SACE,OAAO;GACL,iBAAiB,IAAU,EAAM,SAAS,EAAM;GAChD,aAAa,EAAM;GACnB,OAAO,EAAM;EACf;CACJ;AACF;AAiBA,IAAa,KAAS,EAA8B,SAClD,EACE,aAAU,WACV,UAAO,MACP,WAAQ,WACR,SAAM,IACN,gBACA,iBACA,aACA,UACA,cACA,aACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAW,EAAoB;CAErC,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB,EAAE,UAAU,CAAC,CAAC,EAAS;EAC3C,QAAQ,EAAE,iBAAc;GACtB,IAAM,EAAE,oBAAiB,mBAAgB,GAAiB,GAAO,GAAS,GAAS,CAAG,GAChF,IAAe,CAAC,MAAQ,MAAY,eAAe,MAAY,gBAC/D,IAAe,MAAU,aAAa,GAAgB,CAAI,IAAI,KAAA,GAC9D,EAAE,cAAW,aAAU,oBAAiB,yBAAsB,GAClE,GACA,CACF;GAEA,OAAO,CACL;IACE,eAAe;IACf,YAAY;IACZ,gBAAgB;IAChB,KAAK,EAAM;IACX,WAAW,KAAgB;IAC3B,UAAU,MAAiB,MAAU,SAAS,KAAA,IAAY;IAC1D,OAAO;IACP,QAAQ;IACR,iBAAiB,IAAe,EAAM,SAAS;IAC/C,mBAAmB,IACf,EAAM,SACN,MAAU,SACR,EAAM,SACN;IACN,cAAc,MAAU,YAAY,EAAM,WAAW,EAAM;IAC3D,aAAa,MAAY,aAAa,MAAa,SAAS,IAAI;IAChE;IACA;IACA,SAAS,IAAW,EAAM,kBAAkB,KAAW,IAAe,MAAO;GAC/E,GACA,CACF;EACF;EACA,GAAI;aAEF,EAAE,iBAAc;GAChB,IAAM,EAAE,gBAAa,GAAe,GAAO,CAAI,GACzC,EAAE,aAAU,GAAiB,GAAO,GAAS,GAAS,CAAG;GAE/D,OACE,kBAAA,GAAA,EAAA,UAAA;IACG;IACA,OAAO,KAAa,WACnB,kBAAC,GAAD;KACE,OAAO,CACL;MACE,YAAY,EAAM;MAClB,YAAY,OAAO,EAAM,kBAAkB;MAC3C;MACA;KACF,GACA,CACF;KAEC;IACG,CAAA,IAEN;IAED;GACD,EAAA,CAAA;EAEN;CACS,CAAA;AAEf,CAAC;;;ACxND,SAAS,GAAW,GAAyB,GAA8B;CACzE,QAAQ,GAAR;EACE,KAAK,QACH,OAAO;EACT,KAAK,MACH,OAAO,EAAM;EACf,KAAK,MACH,OAAO,EAAM;EACf,SACE,OAAO,EAAM;CACjB;AACF;AAkBA,IAAa,KAAO,EAA4B,SAC9C,EAAE,iBAAc,IAAO,aAAU,MAAM,UAAO,aAAU,aAAU,GAAG,KACrE,GACA;CACA,IAAM,IAAQ,EAAc,GAEtB,IAAuB;EAC3B,iBAAiB,EAAM;EACvB,aAAa;EACb,aAAa,EAAM;EACnB,cAAc,EAAM;EACpB,UAAU;EACV,SAAS,GAAW,GAAO,CAAO;CACpC;CAUA,OARK,IASH,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB,EAAE,UAAU,CAAC,CAAC,EAAS;EAC3C,OAAO;GACL;GACA;IAAE,UAAU;IAAY,SAAS,IAAW,EAAM,kBAAkB;GAAE;GACtE;EACF;EACA,GAAI;aAEF,EAAE,iBACF,kBAAA,GAAA,EAAA,UAAA,CACG,GACA,KAAW,CAAC,IACX,kBAAC,GAAD;GACE,eAAc;GACd,OAAO,CACL,EAAW,cACX;IAAE,iBAAiB,EAAM;IAAe,cAAc,EAAM;GAAS,CACvE;EACD,CAAA,IACC,IACJ,EAAA,CAAA;CAEK,CAAA,IAjCT,kBAAC,GAAD;EAAa;EAAK,OAAO,CAAC,GAAW,CAAK;EAAG,GAAK;EAC/C;CACK,CAAA;AAiCd,CAAC,GCpFK,KAAO,IA8BA,KAAW,EAAgC,SACtD,EAAE,UAAO,mBAAgB,IAAO,kBAAe,aAAU,UAAO,GAAG,KACnE,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAc,EAAuB,GACrC,IAAW,EAAoB,GAC/B,IAAS,KAAS,GAClB,IAAW,EAAO,IAAI,EAAS,MAAM,IAAc,CAAC,EAAE,SACtD,IAAiB,EAAO,EAAI;CAElC,QAAgB;EAId,IAAI,EAAe,SAAS;GAC1B,EAAe,UAAU;GACzB;EACF;EAEA,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAU;GACxB,SAAS;GACT,UAAU,EAAM;GAChB,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAQ;EAAU,EAAM;EAAc,EAAM;CAAa,CAAC;CAE9D,IAAM,IACJ,MAAa,SAAS,EAAM,gBAAgB,MAAgB,SAAS,EAAM,QAAQ,EAAM,QAErF,IAAc,EAAS,YAAY;EACvC,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,GAAiB,EAAM,aAAa;CACpD,CAAC,GACK,IAAkB,EAAS,YAAY;EAC3C,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,EAAM,aAAa,EAAM,aAAa;CACtD,CAAC;CAED,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,SAAS,IAAgB,UAAU;GAAO,UAAU,CAAC,CAAC;EAAS;EACrF,eAAe,IAAgB,CAAC,CAAK;EACrC,OAAO,CAAC,EAAE,SAAS,IAAW,EAAM,kBAAkB,EAAE,GAAG,CAAK;EAChE,GAAI;YAEJ,kBAAC,EAAS,MAAV;GACE,OAAO;IACL,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,cAAc,EAAM;IACpB,aAAa,MAAa,SAAS,IAAI;IACvC;IACA;GACF;aAEC,IACC,kBAAC,EAAS,MAAV,EACE,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc;IACd,iBAAiB;IACjB,SAAS;GACX,EACD,CAAA,IAED,kBAAC,EAAS,MAAV;IACE,OAAO;KACL,SAAS;KACT,OAAO;KACP,UAAU;KACV,YAAY;KACZ,YAAY;IACd;cAEC;GACY,CAAA;EAEJ,CAAA;CACN,CAAA;AAEf,CAAC,GChIK,KAAoB,EAAS,wBAAwB,CAAS,GAsHvD,MAAU,EACrB,SACA,UACA,aACA,aAAU,CAAC,GACX,YACA,qBAAkB,IAClB,UAAO,UACP,cACA,eACA,UACA,gBACiB;CACjB,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GACjC,IAAW,EAAO,IAAI,EAAS,MAAM,IAAqB,CAAC,EAAE,SAE7D,IAAU,CAAC,CAAC,GAEZ,UAAqB;EACzB,IAAM,IAAS,GAAW,MAAM,MAAM,EAAE,YAAY,iBAAiB,CAAC,EAAE,QAAQ;EAEhF,AAAI,KACF,IAAa,EAAO,EAAE;CAE1B,GAEM,UAAqB;EACzB,AAAI,IACF,EAAa,IAEb,IAAU;CAEd,GAEM,IAAsB,IAAU,IAAe,IAAkB,IAAU,KAAA;CA4BjF,AA1BA,QAAgB;EACd,IAAI,CAAC,GACH;EAGF,IAAI,GAAe;GACjB,EAAS,SAAS,CAAC;GAEnB;EACF;EAEA,EAAS,SAAS,CAAC;EAEnB,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAU;GACxB,SAAS;GACT,UAAU,EAAM;GAChB,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAM;EAAe;EAAU,EAAM;EAAgB,EAAM;CAAa,CAAC,GAK7E,QAAgB;EACd,IAAI,CAAC,GACH;EAGF,IAAM,IAAe,EAAY,iBAAiB,4BAChD,EAAa,GAEN,GACR;EAED,aAAa,EAAa,OAAO;CAEnC,GAAG;EAAC;EAAM;EAAS;EAAW;EAAY;CAAO,CAAC;CAElD,IAAM,UAAsB;EAC1B,IAAM,IAAO,KAAW,IAAY,IAAY;EAMhD,OAJI,EAAK,WAAW,IACX,OAIP,kBAAC,GAAD;GAAM,OAAO;IAAE,gBAAgB;IAAG,gBAAgB,EAAM;GAAe;aACpE,EAAK,KAAK,GAAK,MAAU;IACxB,IAAM,IAAU,EAAI,WAAW,WACzB,IAAQ,MAAY,gBAAgB,EAAM,mBAAmB,EAAM,aACnE,IAAU,UACN,IAAc,EAA4B,EAAE,IACjD,EAAqB;IAE1B,OACE,kBAAC,GAAD;KAEE,mBAAkB;KAClB,oBAAoB,EAAE,UAAU,EAAI,SAAS;KAC7C,UAAU,EAAI;KACL;KACT,QAAQ,EAAE,kBAAe;MACvB,iBAAiB;MACjB,mBAAmB,EAAM;MACzB,mBAAmB,MAAQ,EAAK,SAAS;MACzC,mBAAmB,EAAM;MACzB,iBAAiB,IAAU,EAAM,gBAAgB;MACjD,SAAS,EAAI,WAAW,EAAM,kBAAkB;KAClD;eAEA,kBAAC,GAAD;MACE,SAAQ;MACR,OAAO;OACL,WAAW;OACX;OACA,YACE,MAAY,cACP,OAAO,EAAM,kBAAkB,IAChC,KAAA;MACR;gBAEC,EAAI;KACD,CAAA;IACG,GA3BJ,IAAW,EAA4B,KAAK,EAAI,KA2B5C;GAEf,CAAC;EACG,CAAA;CAEV,GAEM,IACJ,MAAW,SACP;EAAE,eAAe;EAAK,cAAc;EAAI,WAAW;CAAG,IACtD;EAAE,eAAe;EAAM,cAAc;EAAI,WAAW;CAAE;CAE5D,OACE,kBAAC,GAAD;EACE,SAAS;EACT,aAAA;EACA,eAAc;EACd,sBAAA;EACA,gBAAgB;YAEhB,kBAAC,IAAD;GACU;GACR,SAAS;GACT,OAAO;IACL,MAAM;IACN,YAAY;IACZ,gBAAgB;IAChB,mBAAmB;IACnB,iBAAiB,EAAM;IACvB,SAAS;GACX;aAEA,kBAAC,GAAD;IAAW,eAAe,CAAC;IAAG,YAAY;IAAO,OAAO;KAAE,OAAO;KAAQ,UAAU;IAAI;cACrF,kBAAC,EAAS,MAAV;KACE,YAAA;KACM;KACN,0BAAA;KACA,OAAO,CACL;MACE,iBAAiB,EAAM;MACvB,cAAc,EAAM;MACpB,UAAU;MACV,aAAa;MACb,cAAc;OAAE,OAAO;OAAG,QAAQ;MAAE;MACpC,GAAG;MACH,SAAS;MACT,WAAW,CACT,EACE,YAAY,EAAS,YAAY;OAAE,YAAY,CAAC,GAAG,CAAC;OAAG,aAAa,CAAC,IAAI,CAAC;MAAE,CAAC,EAC/E,GACA,EAAE,OAAO,EAAS,YAAY;OAAE,YAAY,CAAC,GAAG,CAAC;OAAG,aAAa,CAAC,KAAM,CAAC;MAAE,CAAC,EAAE,CAChF;KACF,GACA,CACF;eArBF;MAuBG,KACC,kBAAC,GAAD;OACE,SAAQ;OACR,OAAO;QACL,SAAS,EAAM;QACf,eAAe,IAAW,IAAI,EAAM;QACpC,WAAW;QACX,YAAY,OAAO,EAAM,cAAc;OACzC;iBAEC;MACG,CAAA;MAGP,KACC,kBAAC,GAAD;OAAM,OAAO;QAAE,iBAAiB,EAAM;QAAQ,mBAAmB,EAAM;OAAO;iBAC3E,OAAO,KAAa,WACnB,kBAAC,GAAD;QAAM,SAAQ;QAAO,OAAO;SAAE,WAAW;SAAU,SAAS,EAAM;QAAW;QAC1E;OACG,CAAA,IAEN;MAEE,CAAA;MAGP,EAAc;KACF;;GACN,CAAA;EACM,CAAA;CACd,CAAA;AAEX,GC9Sa,MAAW,EAAE,aAAU,uBAAoB,UAAO,gBAA2B;CACxF,IAAM,IAAQ,EAAc,GACtB,IAAW,EAAQ;CAEzB,OACE,kBAAC,GAAD;EACU;EACR,YAAA;EACA,MAAK;EACL,oBACE,MAAuB,OAAO,KAAa,WAAW,IAAW,KAAA;EAEnE,OAAO,CACL;GAAE,eAAe;GAAO,YAAY;GAAU,OAAO;GAAQ,KAAK,EAAM;EAAO,GAC/E,CACF;YAVF,CAYE,kBAAC,GAAD,EAAM,OAAO;GAAE,MAAM;GAAG,QAAQ;GAAG,iBAAiB,EAAM;EAAe,EAAI,CAAA,GAC5E,KACC,kBAAA,GAAA,EAAA,UAAA,CACG,OAAO,KAAa,WACnB,kBAAC,GAAD;GAAM,SAAQ;GAAU,OAAM;GAC3B;EACG,CAAA,IAEN,GAEF,kBAAC,GAAD,EAAM,OAAO;GAAE,MAAM;GAAG,QAAQ;GAAG,iBAAiB,EAAM;EAAe,EAAI,CAAA,CAC7E,EAAA,CAAA,CAEA;;AAEV,GCtBM,KAAM,GACN,KAAS,GACT,KAAkB;AAExB,SAAS,GAAgB,GAAe,GAA+B;CACrE,IAAM,EAAE,QAAQ,MAAO,EAAW,IAAI,QAAQ,GAExC,IADa,KAAM,EAAQ,IAAI,EAAQ,UACjB,KAAe,EAAQ,IAAI,GACjD,IAAM,IAAS,EAAQ,IAAI,IAAc,KAAM,EAAQ,IAAI,EAAQ,SAAS;CAElF,OAAO;EACL,KAAK,KAAK,IAAI,IAAQ,KAAK,IAAI,GAAK,IAAK,IAAc,EAAM,CAAC;EAC9D,MAAM,EAAQ;EACd,OAAO,EAAQ;EACf;CACF;AACF;AA8BA,IAAa,MAAuC,EAClD,YACA,UACA,aACA,iBAAc,oBACd,uBACA,aACA,UACA,gBACsB;CACtB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,CAAC,GAAM,KAAW,EAAS,EAAK,GAChC,CAAC,GAAa,KAAkB,EAAsB,IAAI,GAC1D,CAAC,GAAa,KAAkB,EAAwB,IAAI,GAC5D,CAAC,GAAK,KAAU,EAA0B,IAAI,GAE9C,IAAa,EAAa,IAAI,GAC9B,IAAW,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAEzC,IAAW,EAAQ,MAAM,MAAM,EAAE,UAAU,CAAK,GAEhD,UAAiB;EACjB,KAIJ,EAAQ,EAAI;CACd,GAEM,UAAkB,EAAQ,EAAK,GAE/B,KAAgB,MAA2B;EAC3C,EAAI,aAIR,IAAW,EAAI,KAAK,GACpB,EAAU;CACZ;CA+CA,OA7CA,QAAgB;EACd,IAAI,CAAC,GAAM;GAGT,AAFA,EAAe,IAAI,GACnB,EAAe,IAAI,GACnB,EAAO,IAAI;GAEX;EACF;EAEA,EAAW,SAAS,iBAAiB,GAAG,GAAG,GAAO,MAAW;GAC3D,EAAe;IAAE;IAAG;IAAG;IAAO;GAAO,CAAC;EACxC,CAAC;CACH,GAAG,CAAC,CAAI,CAAC,GAET,QAAgB;EACV,MAAgB,QAAQ,MAAgB,QAI5C,EAAO,GAAgB,GAAa,CAAW,CAAC;CAClD,GAAG,CAAC,GAAa,CAAW,CAAC,GAE7B,QAAgB;EACT,OAIL;OAAI,GAAe;IACjB,EAAS,SAAS,CAAC;IAEnB;GACF;GAGA,AADA,EAAS,SAAS,CAAC,GACnB,EAAS,OAAO,GAAU;IACxB,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EAPT;CAQF,GAAG;EAAC;EAAK;EAAe;EAAU,EAAM;CAAY,CAAC,GAOnD,kBAAC,GAAD;EAAa;YAAb,CACE,kBAAC,GAAD;GACE,KAAK;GACG;GACR,MAAK;GACe;GACpB,oBAAoB;IAAE,UAAU;IAAM,UAAU,CAAC,CAAC;GAAS;GACjD;GACV,eAAgB,IAAO,EAAU,IAAI,EAAS;GAC9C,QAAQ,EAAE,kBAAe;IACvB,eAAe;IACf,YAAY;IACZ,gBAAgB;IAChB,KAAK,EAAM;IACX,WAAW;IACX,UAAU;IACV,iBAAiB;IACjB,mBAAmB,EAAM;IACzB,iBAAiB,IAAU,EAAM,gBAAgB,EAAM;IACvD,aAAa;IACb,aAAa,IAAO,EAAM,cAAc,EAAM;IAC9C,cAAc,EAAM;IACpB,SAAS,IAAW,EAAM,kBAAkB;GAC9C;aAtBF,CAwBE,kBAAC,GAAD;IACE,eAAe;IACf,OAAO;KACL,MAAM;KACN,UAAU,EAAM;KAChB,OAAO,EAAM;KACb,SAAS,IAAW,IAAI,EAAM;IAChC;cAEC,GAAU,SAAS;GAChB,CAAA,GACN,kBAAC,GAAD;IACE,MAAM;IACN,MAAK;IACL,OAAM;IACN,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,IAAO,WAAW,OAAO,CAAC,EAAE;GAC5D,CAAA,CACQ;MAEX,kBAAC,GAAD;GAAO,SAAS;GAAM,aAAA;GAAY,eAAc;GAAO,sBAAA;aACrD,kBAAC,GAAD;IACE,SAAS;IACT,YAAY;IACZ,OAAO,EAAE,MAAM,EAAE;IACjB,QAAQ,IAAS,GAAG,EAAO,aAAa,KAAA;cAExC,kBAAC,EAAS,MAAV;KACE,WAzDiB,MAAyB;MAClD,EAAe,KAAK,IAAI,EAAE,YAAY,OAAO,QAAQ,EAAe,CAAC;KACvE;KAwDU,MAAK;KACL,YAAA;KACA,OAAO,CACL;MACE,UAAU;MACV,WAAW;MACX,iBAAiB,EAAM;MACvB,aAAa;MACb,aAAa,EAAM;MACnB,cAAc,EAAM;MACpB,iBAAiB;MACjB,aAAa;MACb,cAAc;OAAE,OAAO;OAAG,QAAQ;MAAE;MACpC,eAAe;MACf,cAAc;MACd,WAAW;KACb,GACA,IACI;MAAE,KAAK,EAAI;MAAK,MAAM,EAAI;MAAM,OAAO,EAAI;MAAO,SAAS;KAAS,IACpE;MAAE,KAAK;MAAO,MAAM;MAAO,OAAO;MAAK,SAAS;KAAE,CACxD;eAEA,kBAAC,GAAD;MAAY,SAAS;gBAClB,EAAQ,KAAK,MAAQ;OACpB,IAAM,IAAa,EAAI,UAAU;OAEjC,OACE,kBAAC,GAAD;QAEE,MAAK;QACL,oBAAoB;SAAE,UAAU;SAAY,UAAU,CAAC,CAAC,EAAI;QAAS;QACrE,UAAU,EAAI;QACd,eAAe,EAAa,CAAG;QAC/B,QAAQ,EAAE,kBAAe;SACvB,eAAe;SACf,YAAY;SACZ,KAAK,EAAM;SACX,WAAW;SACX,iBAAiB;SACjB,mBAAmB,EAAM;SACzB,iBAAiB,IAAU,EAAM,gBAAgB;SACjD,SAAS,EAAI,WAAW,EAAM,kBAAkB;QAClD;kBAfF,CAiBE,kBAAC,GAAD;SAAM,OAAO;UAAE,MAAM;UAAG,KAAK;SAAE;mBAA/B,CACE,kBAAC,GAAD;UACE,eAAe;UACf,OAAO;WACL,UAAU,EAAM;WAChB,OAAO,EAAM;WACb,YAAY,IACP,OAAO,EAAM,kBAAkB,IAChC,KAAA;UACN;oBAEC,EAAI;SACD,CAAA,GACL,EAAI,eACH,kBAAC,GAAD;UACE,eAAe;UACf,OAAO;WACL,UAAU,EAAM;WAChB,OAAO,EAAM;WACb,SAAS,EAAM;UACjB;oBAEC,EAAI;SACD,CAAA,CAEJ;YACL,KAAc,kBAAC,GAAD;SAAM,MAAM;SAAO,MAAK;SAAK,OAAM;QAAQ,CAAA,CACjD;UA3CJ,EAAI,KA2CA;MAEf,CAAC;KACS,CAAA;IACC,CAAA;GACN,CAAA;EACN,CAAA,CACH;;AAEV,GCvPa,MAAY,EACvB,UACA,aACA,UAAU,GACV,qBAAkB,IAClB,qBACA,cAAW,IACX,UACA,gBACmB;CACnB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,IAAe,MAAuB,KAAA,GACtC,CAAC,GAAsB,KAA2B,EAAS,CAAe,GAC1E,IAAW,IAAe,IAAqB,GAE/C,CAAC,GAAe,KAAoB,EAAS,CAAC,GAC9C,IAAc,EAAO,EAAK,GAC1B,IAAa,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAC3C,IAAc,EAAO,IAAI,EAAS,MAAM,IAAuB,CAAC,EAAE,SAElE,UAAe;EACnB,IAAI,GACF;EAGF,IAAM,IAAO,CAAC;EAMd,AAJK,KACH,EAAwB,CAAI,GAG9B,IAAmB,CAAI;CACzB,GAEM,KAAuB,MAAyB;EACpD,IAAM,IAAI,EAAE,YAAY,OAAO;EAE/B,IAAI,MAAM,GAAe;GACvB,EAAY,UAAU;GAEtB;EACF;EAOA,AALI,KAAY,CAAC,EAAY,WAC3B,EAAW,SAAS,CAAC,GAGvB,EAAY,UAAU,IACtB,EAAiB,CAAC;CACpB;CAEA,QAAgB;EACd,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM,eACzB,IAAS,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE,GACrC,IAAS,IAAW,IAAgB;EAE1C,IAAI,GAAe;GAEjB,AADA,EAAW,SAAS,CAAM,GAC1B,EAAY,SAAS,IAAgB;GAErC;EACF;EAEA,EAAS,SAAS,CAChB,EAAS,OAAO,GAAY;GAC1B,SAAS;GACT,UAAU,EAAM;GAChB;GACA,iBAAiB;EACnB,CAAC,GACD,EAAS,OAAO,GAAa;GAC3B,SAAS;GACT,UAAU,EAAM;GAChB;GACA,iBAAiB;EACnB,CAAC,CACH,CAAC,EAAE,MAAM;CACX,GAAG;EACD;EACA;EACA;EACA;EACA;EACA,EAAM;EACN,EAAM;EACN,EAAM;CACR,CAAC;CAED,IAAM,IAAqB,KAAY,CAAC,EAAY,SAC9C,IAAS,EAAY,YAAY;EAAE,YAAY,CAAC,GAAG,CAAC;EAAG,aAAa,CAAC,QAAQ,OAAO;CAAE,CAAC;CAE7F,OACE,kBAAC,GAAD;EAAc;EAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,GAAG,CAAK;YAAtD,CACE,kBAAC,GAAD;GACE,MAAK;GACK;GACV,oBAAoB;IAAE;IAAU;GAAS;GACzC,SAAS;GACT,QAAQ,EAAE,kBAAe;IACvB,eAAe;IACf,YAAY;IACZ,WAAW;IACX,KAAK,EAAM;IACX,SAAS,EAAM;IACf,QAAQ,CAAC,EAAM;IACf,cAAc,EAAM;IACpB,iBAAiB,IAAU,EAAM,gBAAgB;IACjD,SAAS,IAAW,EAAM,kBAAkB;GAC9C;aAfF,CAiBE,kBAAC,EAAS,MAAV;IAAe,OAAO;KAAE,SAAS;KAAM,WAAW,CAAC,EAAE,UAAO,CAAC;IAAE;cAC7D,kBAAC,GAAD;KAAM,MAAM;KAAQ,MAAK;IAAM,CAAA;GAClB,CAAA,GAEd,OAAO,KAAU,WAChB,kBAAC,GAAD;IAAM,OAAO,EAAE,OAAO,EAAM,cAAc;cAAI;GAAY,CAAA,IAE1D,CAEO;MAEX,kBAAC,EAAS,MAAV;GACE,OAAO;IAAE,QAAQ,IAAqB,KAAA,IAAY;IAAY,UAAU;GAAS;GACjF,6BAA6B,CAAC;GAC9B,2BAA2B,IAAW,QAAQ;aAE9C,kBAAC,GAAD;IACE,YAAA;IACA,MAAK;IACL,UAAU;IACV,OAAO,EAAE,YAAY,EAAM,OAAO;IAEjC;GACG,CAAA;EACO,CAAA,CACX;;AAEV,GCxKa,KAAY,EAAiC,SACxD,EAAE,UAAO,UAAO,QAAK,UAAO,IAAO,UAAO,GAAG,KAC7C,GACA;CACA,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACO;EACL,OAAO,CACL;GACE,eAAe;GACf,YAAY;GACZ,KAAK,EAAM;GACX,mBAAmB,EAAM;GACzB,WAAW;GACX,iBAAiB,EAAM;GACvB,mBAAmB;GACnB,mBAAmB,EAAM;EAC3B,GACA,CACF;EACA,GAAI;YAfN;GAiBE,kBAAC,GAAD;IAAQ,OAAO;KAAE,MAAM;KAAG,eAAe;KAAO,YAAY;KAAU,KAAK,EAAM;IAAO;cACrF;GACK,CAAA;GAER,kBAAC,GAAD;IACE,yBAAwB;IACxB,OAAO;KAAE,YAAY;KAAU,gBAAgB;KAAU,mBAAmB,EAAM;IAAO;cAExF,OAAO,KAAU,WAChB,kBAAC,GAAD;KACE,eAAe;KACf,eAAc;KACd,OAAO;MACL,YAAY,EAAM;MAClB,UAAU,EAAM;MAChB,YAAY,OAAO,EAAM,kBAAkB;MAC3C,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,iBAAiB;MACnE,OAAO,EAAM;KACf;eAEC;IACK,CAAA,IAER;GAEI,CAAA;GAER,kBAAC,GAAD;IACE,OAAO;KACL,MAAM;KACN,eAAe;KACf,YAAY;KACZ,gBAAgB;KAChB,KAAK,EAAM;IACb;cAEC;GACK,CAAA;EACF;;AAEZ,CAAC;;;ACxFD,SAAS,GAAa,GAAW;CAC/B,OAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AA8BA,IAAa,MAAa,EAAE,SAAM,UAAO,mBAAgB,IAAO,GAAG,QAAgC;CACjG,IAAM,IAAQ,EAAc,GACtB,IAAW,EAAoB,GAE/B,KAAS,MAAM,QAAQ,CAAK,IAAI,IAAQ,CAAC,CAAK,GAAG,KAAK,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;CAE1F,IAAI,EAAM,WAAW,GACnB,OAAO,kBAAC,GAAD;EAAM,GAAI;YAAY;CAAW,CAAA;CAG1C,IAAM,IAAc,OAAO,IAAI,EAAM,IAAI,EAAY,EAAE,KAAK,GAAG,EAAE,IAAI,IAAgB,MAAM,IAAI,GACzF,IAAQ,EAAK,MAAM,CAAO,GAE1B,IAAuB;EAC3B,YAAY,OAAO,EAAM,kBAAkB;EAC3C,GAAI,MAAa,SACb;GAAE,iBAAiB,EAAM;GAAe,OAAO;EAAO,IACtD,EAAE,iBAAiB,GAAG,EAAM,cAAc,IAAI;CACpD;CAEA,OACE,kBAAC,GAAD;EAAM,GAAI;YACP,EAAM,KAAK,GAAM,MAChB,IAAI,KAAM,IACR,kBAAC,GAAD;GAAgB,OAAO;aACpB;EACK,GAFK,CAEL,IAER,CAEJ;CACI,CAAA;AAEV;;;AC5CA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACiB;CASjB,OARI,MAAQ,KAAA,KAAa,KAAS,IACzB,IAGL,MAAS,KAAA,KAAa,KAAS,IAC1B,IAGF;AACT;AAEA,SAAS,GAAa,GAAyB,GAAkC;CAC/E,QAAQ,GAAR;EACE,KAAK,UACH,OAAO,EAAM;EACf,KAAK,WACH,OAAO,EAAM;EACf,KAAK,WACH,OAAO,EAAM;EACf,KAAK,SACH,OAAO,EAAM;CACjB;AACF;AA0CA,IAAa,MAAY,EACvB,UACA,SAAM,GACN,SAAM,GACN,QACA,gBAAa,WACb,SACA,iBAAc,SACd,aAAU,UACV,cAAW,IACX,eAAY,IACZ,uBACA,UACA,gBACmB;CACnB,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GAEjC,IAAQ,IAAM,GACd,IAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAK,CAAC,GAC5C,IAAW,IAAQ,KAAK,IAAU,KAAO,IAAQ,GACjD,IAAkB,GAAe,GAAS,GAAK,GAAY,GAAM,GAAa,CAAO,GAErF,IAAS,EAAO,IAAI,EAAS,MAAM,CAAQ,CAAC,EAAE;CAEpD,QAAgB;EACd,IAAI,GACF;EAGF,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAQ;GACtB,SAAS;GACT,UAAU,IAAgB,IAAI,EAAM;GACpC,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAU;EAAU;EAAe;EAAQ,EAAM;EAAgB,EAAM;CAAa,CAAC;CAEzF,IAAM,IAAa,MAAW,SAAS,EAAM,QAAQ,EAAM;CAE3D,OACE,kBAAC,GAAD;EACU;EACR,YAAA;EACA,MAAK;EACe;EACpB,oBAAoB;GAAE;GAAK;GAAK,KAAK;EAAQ;EAC7C,OAAO,CACL;GACE,eAAe;GACf,OAAO;GACP,QAAQ;GACR,cAAc,IAAW,IAAI,EAAM;GACnC,iBAAiB,IAAW,gBAAgB;GAC5C,UAAU,IAAW,YAAY;GACjC,KAAK,IAAW,IAAI;EACtB,GACA,CACF;YAEC,IACC,MAAM,KAAK,EAAE,QAAQ,EAAU,IAAI,GAAG,MAKlC,kBAAC,GAAD;GAEE,QAAO;GACP,6BAAA;GACA,2BAA0B;GAC1B,OAAO;IACL,MAAM;IACN,QAAQ;IACR,UAAU;IACV,cAAc;IACd,kBAdiB,IAAI,KAAK,KACA,IAaA,GAAa,GAAO,CAAe,IAAI;GACnE;EACD,GAXM,CAWN,CAEJ,IAED,kBAAC,EAAS,MAAV;GACE,QAAQ,IAAS,GAAG,EAAO,SAAS,KAAA;GACpC,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc,EAAM;IACpB,iBAAiB,GAAa,GAAO,CAAe;IACpD,iBAAiB;IACjB,WAAW,CAAC,EAAE,UAAO,CAAC;GACxB;EACD,CAAA;CAEC,CAAA;AAEV,GC7Ka,KAAO,EAA4B,SAC9C,EAAE,SAAM,cAAW,IAAO,aAAU,UAAO,cAAW,YAAS,GAAG,KAClE,GACA;CACA,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACO;EACL,mBAAkB;EAClB,mBAAmB,IAAW,qBAAqB,KAAA;EACnD,SAAS,YAAkB,EAAQ,QAAQ,CAAI;EACxC;EACP,GAAI;aAEF,EAAE,iBACF,kBAAC,GAAD;GACE,OAAO,CACL;IACE,OAAO,EAAM;IACb,oBAAoB,IAAU,cAAc;IAC5C,SAAS,IAAU,KAAM;GAC3B,GACA,CACF;aARF,CAUG,GACA,KACC,kBAAC,GAAD;IACE,6BAAA;IACA,2BAA0B;IAC1B,OAAO,EAAE,UAAU,GAAG;cAErB;GACK,CAAA,CAEN;;CAEC,CAAA;AAEf,CAAC,GChEK,KAAoB,EAAS,wBAAwB,CAAS,GAyCvD,MAAW,EAAE,SAAM,cAAW,aAAU,UAAO,gBAA2B;CACrF,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,CAAC,GAAS,KAAc,EAAS,CAAI,GACrC,IAAU,EAAO,IAAI,EAAS,MAAM,IAAY,CAAC,EAAE;CAiDzD,OA/CA,QAAgB;EACd,AAAI,KACF,EAAW,EAAI;CAEnB,GAAG,CAAC,CAAI,CAAC,GAET,QAAgB;EACT,OAIL,IAAI,GAAM;GACR,IAAI,GAAe;IACjB,EAAQ,SAAS,CAAC;IAElB;GACF;GAGA,AADA,EAAQ,SAAS,CAAC,GAClB,EAAS,OAAO,GAAS;IACvB,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EACX,OAAO;GACL,IAAI,GAAe;IACjB,EAAW,EAAK;IAEhB;GACF;GAEA,EAAS,OAAO,GAAS;IACvB,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,OAAO,EAAE,kBAAe;IACzB,AAAI,KACF,EAAW,EAAK;GAEpB,CAAC;EACH;CACF,GAAG;EAAC;EAAM;EAAS;EAAe;EAAS,EAAM;CAAc,CAAC,GAE3D,IAKH,kBAAC,GAAD;EAAgB;EAAS,aAAA;EAAY,eAAc;EAAO,sBAAA;YACxD,kBAAC,IAAD;GACU;GACR,SAAS;GACT,YAAY;GACZ,OAAO,CACL;IACE,MAAM;IACN,YAAY;IACZ,gBAAgB;IAChB,iBAAiB,EAAM;IACvB;GACF,GACA,CACF;aAEA,kBAAC,GAAD;IAAW,eAAe,CAAC;IAAG,YAAY;IACvC;GACQ,CAAA;EACM,CAAA;CACd,CAAA,IAxBA;AA0BX,GClFa,MAAW,EAAE,aAAU,eAAY,UAAO,GAAG,QAA8B;CACtF,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACE,OAAO,CAAC;GAAE,eAAe;GAAO,UAAU;GAAQ,YAAY;EAAS,GAAG,CAAK;EAC/E,GAAI;YAEH,EAAS,KAAK,GAAS,MAAU;GAChC,IAAM,IAAY,MAAU,EAAS,SAAS;GAE9C,OACE,kBAAC,GAAD,EAAA,UAAA,CACG,IAAQ,KACP,kBAAC,GAAD;IACE,6BAAA;IACA,2BAA0B;IAC1B,OAAO;KACL,OAAO,EAAM;KACb,SAAS;KACT,kBAAkB;KAClB,UAAU,EAAM;IAClB;cAEC;GACK,CAAA,GAGT,IACC,kBAAC,GAAD;IACE,OAAO;KACL,eAAe;KACf,YAAY;KACZ,KAAK;KACL,iBAAiB;KACjB,mBAAmB,EAAM;KACzB,UAAU;IACZ;cARF,CAUG,EAAQ,QAAQ,kBAAC,GAAD;KAAQ,OAAO,EAAE,YAAY,EAAE;eAAI,EAAQ;IAAa,CAAA,GACzE,kBAAC,GAAD;KACE,eAAe;KACf,eAAc;KACd,OAAO;MACL,YAAY,EAAM;MAClB,UAAU,EAAM;MAChB,YAAY,OAAO,EAAM,kBAAkB;MAC3C,OAAO,EAAM;KACf;eAEC,EAAQ;IACH,CAAA,CACF;QAER,kBAAC,GAAD;IACE,mBAAkB;IAClB,oBAAoB,EAAQ;IAC5B,eAAe,IAAa,EAAQ,MAAM,CAAK;IAC/C,QAAQ,EAAE,kBAAe;KACvB,eAAe;KACf,YAAY;KACZ,KAAK;KACL,iBAAiB;KACjB,mBAAmB,EAAM;KACzB,UAAU;KACV,cAAc,EAAM;KACpB,iBAAiB,IAAU,EAAM,gBAAgB;IACnD;cAbF,CAeG,EAAQ,QAAQ,kBAAC,GAAD;KAAQ,OAAO,EAAE,YAAY,EAAE;eAAI,EAAQ;IAAa,CAAA,GACzE,kBAAC,GAAD;KACE,eAAe;KACf,eAAc;KACd,OAAO;MACL,YAAY,EAAM;MAClB,UAAU,EAAM;MAChB,OAAO,EAAM;KACf;eAEC,EAAQ;IACH,CAAA,CACC;KAEL,EAAA,GAvEK,EAAQ,IAuEb;EAEd,CAAC;CACK,CAAA;AAEZ,GCpEM,IAAM,GACN,IAAS,IACT,KAAQ;AAEd,SAAS,GAAa,GAAyB,GAAiB;CACzD,OAIL;MAAI,OAAO,KAAQ,YAAY;GAC7B,EAAI,CAAK;GAET;EACF;EAEA,EAA+B,UAAU;CAFzC;AAGF;AAEA,SAAS,GAAc,GAAe,GAAa,GAA6B;CAC9E,QAAQ,GAAR;EACE,KAAK,OACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAM,SAAS;GAChC,MAAM,EAAQ,IAAI,EAAQ,QAAQ,IAAI,EAAM,QAAQ;EACtD;EACF,KAAK,UACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS;GAClC,MAAM,EAAQ,IAAI,EAAQ,QAAQ,IAAI,EAAM,QAAQ;EACtD;EACF,KAAK,QACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS,IAAI,EAAM,SAAS;GACrD,MAAM,EAAQ,IAAI,EAAM,QAAQ;EAClC;EACF,KAAK,SACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS,IAAI,EAAM,SAAS;GACrD,MAAM,EAAQ,IAAI,EAAQ,QAAQ;EACpC;CACJ;AACF;AAEA,SAAS,GAAgB,GAAe,GAAa,GAAuC;CAC1F,IAAM,EAAE,OAAO,GAAI,QAAQ,MAAO,EAAW,IAAI,QAAQ,GAUnD,IAAiC;EAAC;EAPtC,MAAc,QACV,WACA,MAAc,WACZ,QACA,MAAc,SACZ,UACA;EACmD;EAAU;EAAO;EAAQ;CAAO;CAE7F,KAAK,IAAM,KAAK,GAAY;EAC1B,IAAM,EAAE,QAAK,YAAS,GAAc,GAAS,GAAO,CAAC,GAC/C,IAAQ,KAAQ,KAAU,IAAO,EAAM,SAAS,IAAK,GACrD,IAAQ,KAAO,KAAU,IAAM,EAAM,UAAU,IAAK;EAE1D,IAAI,KAAS,GACX,OAAO;GACL,KAAK,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAK,IAAK,EAAM,SAAS,CAAM,CAAC;GAC/D,MAAM,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAM,IAAK,EAAM,QAAQ,CAAM,CAAC;GAChE,WAAW;EACb;CAEJ;CAEA,IAAM,EAAE,QAAK,YAAS,GAAc,GAAS,GAAO,CAAS;CAE7D,OAAO;EACL,KAAK,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAK,IAAK,EAAM,SAAS,CAAM,CAAC;EAC/D,MAAM,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAM,IAAK,EAAM,QAAQ,CAAM,CAAC;EAChE,WAAW;CACb;AACF;AA4DA,IAAa,MAAW,EACtB,YACA,WAAW,IAAqB,UAChC,MAAM,GACN,iBACA,eACA,kBACkB;CAClB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GAEjC,IAAe,MAAmB,KAAA,GAClC,CAAC,GAAkB,KAAuB,EAAS,EAAK,GACxD,IAAO,IAAe,IAAiB,GAEvC,CAAC,GAAa,KAAkB,EAAsB,IAAI,GAC1D,CAAC,GAAW,KAAgB,EAAsB,IAAI,GACtD,CAAC,GAAK,KAAU,EAA0B,IAAI,GAE9C,IAAa,EAAa,IAAI,GAC9B,IAAW,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAEzC,IAAU,GACb,MAAkB;EAKjB,AAJK,KACH,EAAoB,CAAI,GAG1B,IAAe,CAAI;CACrB,GACA,CAAC,GAAc,CAAY,CAC7B,GAEM,IAAQ,QAAkB,EAAQ,EAAK,GAAG,CAAC,CAAO,CAAC,GACnD,IAAS,QAAkB,EAAQ,CAAC,CAAI,GAAG,CAAC,GAAM,CAAO,CAAC;CAgDhE,AA7CA,QAAgB;EACd,IAAI,CAAC,GAAM;GAGT,AAFA,EAAe,IAAI,GACnB,EAAa,IAAI,GACjB,EAAO,IAAI;GAEX;EACF;EAEA,EAAW,SAAS,iBAAiB,GAAG,GAAG,GAAO,MAAW;GAC3D,EAAe;IAAE;IAAG;IAAG;IAAO;GAAO,CAAC;EACxC,CAAC;CACH,GAAG,CAAC,CAAI,CAAC,GAIT,QAAgB;EACV,CAAC,KAAe,CAAC,KAIrB,EAAO,GAAgB,GAAa,GAAW,CAAkB,CAAC;CACpE,GAAG;EAAC;EAAa;EAAW;CAAkB,CAAC,GAE/C,QAAgB;EACT,OAIL;OAAI,GAAe;IACjB,EAAS,SAAS,CAAC;IAEnB;GACF;GAGA,AADA,EAAS,SAAS,CAAC,GACnB,EAAS,OAAO,GAAU;IACxB,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EAPT;CAQF,GAAG;EAAC;EAAK;EAAe;EAAU,EAAM;CAAY,CAAC,GAIrD,QAAgB;EACd,IAAI,CAAC,GACH;EAGF,IAAM,IAAe,EAAY,iBAAiB,4BAChD,EAAM,GAEC,GACR;EAED,aAAa,EAAa,OAAO;CACnC,GAAG,CAAC,GAAM,CAAK,CAAC;CAEhB,IAAM,MAAqB,MAAyB;EAClD,IAAM,EAAE,UAAO,cAAW,EAAE,YAAY;EAExC,EAAa;GAAE;GAAO;EAAO,CAAC;CAChC,GAEM,IAAY;EAChB,UAAU;EACV,OAAO;EACP,QAAQ;EACR,aAAa;EACb,aAAa;CACf,GAEM,WAAoB;EACxB,QAAQ,GAAK,WAAb;GACE,KAAK,OACH,OAAO;IACL,GAAG;IACH,KAAK;IACL,MAAM;IACN,YAAY;IACZ,gBAAgB,EAAM;GACxB;GACF,KAAK,UACH,OAAO;IACL,GAAG;IACH,QAAQ;IACR,MAAM;IACN,YAAY;IACZ,mBAAmB,EAAM;GAC3B;GACF,KAAK,QACH,OAAO;IACL,GAAG;IACH,MAAM;IACN,KAAK;IACL,WAAW;IACX,iBAAiB,EAAM;GACzB;GACF,KAAK,SACH,OAAO;IACL,GAAG;IACH,OAAO;IACP,KAAK;IACL,WAAW;IACX,kBAAkB,EAAM;GAC1B;GACF,SACE,OAAO;EACX;CACF,GAAG,GAEG,IAAe,EAAS,MAA8B;CAc5D,OACE,kBAAA,GAAA,EAAA,UAAA,CAbc,EAAa,GAAU;EACrC,MAAM,MAAsB;GAE1B,AADA,EAAyC,UAAU,GACnD,GAAU,GAAa,CAAI;EAC7B;EACA,oBAAoB;GAAE,UAAU;GAAM,GAAG,EAAS,MAAM;EAAmB;EAC3E,UAAU,MAA6B;GAErC,AADA,EAAO,GACP,EAAS,MAAM,UAAU,CAAC;EAC5B;CACF,CAIK,GACD,kBAAC,GAAD;EACE,SAAS;EACT,aAAA;EACA,eAAc;EACd,sBAAA;EACA,gBAAgB;YAEhB,kBAAC,GAAD;GAAW,SAAS;GAAO,YAAY;GAAO,OAAO,EAAE,MAAM,EAAE;aAC7D,kBAAC,EAAS,MAAV;IACE,UAAU;IACV,MAAK;IACL,YAAA;IACA,iCAAiC;IACjC,OAAO;KACL;MACE,UAAU;MACV,UAAU;MACV,UAAU;MACV,iBAAiB,EAAM;MACvB,aAAa;MACb,aAAa,EAAM;MACnB,cAAc,EAAM;MACpB,SAAS,EAAM;MACf,aAAa;MACb,cAAc;OAAE,OAAO;OAAG,QAAQ;MAAE;MACpC,eAAe;MACf,cAAc;MACd,WAAW;KACb;KACA,IACI;MAAE,KAAK,EAAI;MAAK,MAAM,EAAI;MAAM,SAAS;KAAS,IAClD;MAAE,KAAK;MAAO,MAAM;MAAO,SAAS;KAAE;KAC1C;IACF;cAzBF,CA2BG,GACA,KAAc,kBAAC,GAAD,EAAM,OAAO,EAAa,CAAA,CAC5B;;EACN,CAAA;CACN,CAAA,CACP,EAAA,CAAA;AAEN,GChVa,MAAe,EAC1B,UACA,aAAU,UACV,uBACA,UACA,aACA,GAAG,QACmB;CACtB,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GAEjC,IAAkB,KAAiC,MACnD,IAAU,IAAkB,KAAA,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAK,CAAC,GACtE,IAAU,MAAY,KAAA,IAA4B,KAAA,IAAhB,IAAU,KAE5C,IAAQ,EAAO,IAAI,EAAS,MAAM,KAAW,CAAC,CAAC,EAAE,SACjD,IAAQ,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SACtC,CAAC,GAAY,KAAiB,EAAS,CAAC,GAExC,KAAqB,MAA6B;EAEtD,AADA,EAAc,EAAM,YAAY,OAAO,KAAK,GAC5C,IAAW,CAAK;CAClB;CAiBA,AAfA,QAAgB;EACd,IAAI,GACF;EAGF,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAO;GACrB,SAAS,KAAW;GACpB,UAAU,IAAgB,IAAI,EAAM;GACpC,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAS;EAAiB;EAAe;EAAO,EAAM;EAAgB,EAAM;CAAa,CAAC,GAE9F,QAAgB;EACd,IAAI,CAAC,KAAmB,GACtB;EAGF,EAAM,SAAS,CAAC;EAEhB,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM,eAEzB,IAAY,EAAS,KACzB,EAAS,OAAO,GAAO;GACrB,SAAS;GACT,UAAU;GACV,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,CACH;EAIA,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG;EAAC;EAAiB;EAAe;EAAO,EAAM;CAAa,CAAC;CAE/D,IAAM,IAAa,MAAW,SAAS,EAAM,QAAQ,EAAM,QACrD,IAAmD;EACvD,QAAQ,EAAM;EACd,SAAS,EAAM;EACf,SAAS,EAAM;EACf,OAAO,EAAM;CACf,GAEM,IAAY,IACd,IACE;EAAE,MAAM;EAAG,OAAO;EAAQ,SAAS;CAAI,IACvC;EACE,MAAM;EACN,OAAO;EACP,WAAW,CACT,EACE,YAAY,EAAM,YAAY;GAC5B,YAAY,CAAC,GAAG,CAAC;GACjB,aAAa,CAAC,MAAO,GAAY,CAAU;EAC7C,CAAC,EACH,CACF;CACF,IACF;EACE,OAAO;EACP,iBAAiB;EACjB,WAAW,CAAC,EAAE,QAAQ,EAAM,CAAC;CAC/B;CAEJ,OACE,kBAAC,EAAS,MAAV;EACE,YAAA;EACA,mBAAkB;EACE;EACpB,oBACE,MAAY,KAAA,IAAuE,KAAA,IAA3D;GAAE,KAAK;GAAG,KAAK;GAAK,KAAK,KAAK,MAAM,CAAiB;EAAE;EAEjF,UAAU;EACV,OAAO,CACL;GACE,OAAO;GACP,QAAQ;GACR,cAAc,EAAM;GACpB,iBAAiB;GACjB,UAAU;EACZ,GACA,CACF;EACA,GAAI;YAEJ,kBAAC,EAAS,MAAV,EACE,OAAO,CACL;GACE,UAAU,IAAkB,aAAa;GACzC,KAAK;GACL,QAAQ;GACR,cAAc,EAAM;GACpB,iBAAiB,EAAa;EAChC,GACA,CACF,EACD,CAAA;CACY,CAAA;AAEnB,GCvLM,KAAO,IACP,KAAW,GAqBJ,KAAc,EAAmC,SAC5D,EAAE,UAAO,aAAU,aAAU,UAAO,GAAG,KACvC,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAc,EAAuB,GACrC,IAAW,EAAoB,GAC/B,IAAW,EAAO,IAAI,EAAS,MAAM,IAAa,CAAC,EAAE,SACrD,IAAiB,EAAO,EAAI;CAElC,QAAgB;EAId,IAAI,EAAe,SAAS;GAC1B,EAAe,UAAU;GACzB;EACF;EAEA,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAU;GACxB,SAAS;GACT,UAAU,EAAM;GAChB,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAO;EAAU,EAAM;EAAc,EAAM;CAAa,CAAC;CAE7D,IAAM,IACJ,MAAa,SAAS,EAAM,gBAAgB,MAAgB,SAAS,EAAM,QAAQ,EAAM,QAErF,IAAc,EAAS,YAAY;EACvC,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,GAAiB,EAAM,aAAa;CACpD,CAAC,GACK,IAAkB,EAAS,YAAY;EAC3C,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,EAAM,aAAa,EAAM,aAAa;CACtD,CAAC;CAED,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,SAAS;GAAO,UAAU,CAAC,CAAC;EAAS;EAC3D,eAAe;GACb,AAAK,KACH,IAAW;EAEf;EACA,OAAO,CAAC,EAAE,SAAS,IAAW,EAAM,kBAAkB,EAAE,GAAG,CAAK;EAChE,GAAI;YAEJ,kBAAC,EAAS,MAAV;GACE,OAAO;IACL,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,cAAc,EAAM;IACpB,aAAa,MAAa,SAAS,IAAI;IACvC;IACA;GACF;aAEA,kBAAC,EAAS,MAAV,EACE,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc,EAAM;IACpB,iBAAiB;IACjB,SAAS;GACX,EACD,CAAA;EACY,CAAA;CACN,CAAA;AAEf,CAAC;;;ACrFD,SAAS,GAAS,GAAe,GAAwB;CACvD,IAAM,IAAQ,EAAM,MAAM,8CAA8C;CAExE,IAAI,CAAC,GACH,OAAO;CAGT,IAAM,GAAG,GAAG,GAAG,GAAG,KAAK,GACjB,KAAS,IAAI,OAAO,WAAW,CAAC,IAAI,KAAK;CAE/C,OAAO,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAM;AAC9D;AAyBA,IAAa,KAAY,EAAsC,SAC7D,EACE,SACA,YACA,YACA,aACA,UACA,iBAAc,WACd,cAAW,IACX,YAAS,IACT,gBAAa,UACb,UACA,eACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAW,EAAkB,IAAI;CAcvC,IAZA,EAAoB,SAAW,EAAS,SAAsB,CAAC,CAAC,GAEhE,QAAgB;EACd,IAAI,CAAC,GACH;EAGF,IAAM,IAAK,4BAA4B,EAAS,SAAS,MAAM,CAAC;EAEhE,aAAa,qBAAqB,CAAE;CACtC,GAAG,CAAC,CAAI,CAAC,GAEL,CAAC,GACH,OAAO;CAGT,IAAM,IAAW,CAAC,GACZ,IAAW,OAAO,KAAU,YAAY,EAAM,SAAS,GAEvD,IAAQ,IAAS,gBAAgB,EAAM,kBACvC,IAAY,IAAS,gBAAgB,EAAM;CAEjD,OACE,kBAAC,GAAD;EAAe;YAAf,CACE,kBAAC,GAAD;GAAQ,OAAO;IAAE,eAAe;IAAO,YAAY;IAAU,KAAK,EAAM;GAAO;aAA/E,CACE,kBAAC,GAAD;IACE,OAAO;KACL,MAAM;KACN,eAAe;KACf,YAAY;KACZ,KAAK,EAAM;KACX,iBAAiB,EAAM;KACvB,mBAAmB,EAAM;KACzB,iBAAiB;KACjB,mBAAmB;KACnB,mBAAmB;KACnB,SAAS,IAAW,EAAM,kBAAkB;IAC9C;cAZF;KAcE,kBAAC,GAAD;MACE,6BAAA;MACA,2BAA0B;MAC1B,OAAO;OAAE,SAAS,EAAM;OAAY,UAAU,EAAM;MAAa;gBAEhE;KACK,CAAA;KAER,kBAAC,GAAD;MACE,KAAK;MACK;MACH;MACM;MACb,sBAAsB,GAAS,EAAM,eAAe,EAAM,UAAU;MACpE,OAAO,CACL;OACE,MAAM;OACN,SAAS;OACT,YAAY,EAAM;OAClB,UAAU,EAAM;OAChB,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,cAAc;OAChE,OAAO,EAAM;MACf,GACA,CACF;MACA,GAAI;KACL,CAAA;KAEA,KACC,kBAAC,GAAD;MACE,mBAAkB;MAClB,oBAAmB;MACT;MACV,SAAS;MACT,eAAe;OAEb,AADA,IAAU,GACV,EAAS,SAAS,MAAM;MAC1B;MACA,QAAQ,EAAE,kBAAe;OACvB,OAAO;OACP,QAAQ;OACR,YAAY;OACZ,gBAAgB;OAChB,cAAc,EAAM;OACpB,SAAS,IAAW,EAAM,kBAAkB;OAC5C,iBAAiB,IAAU,EAAM,gBAAgB;MACnD;gBAEA,kBAAC,GAAD;OAAQ,OAAO;QAAE,UAAU,EAAM;QAAc,OAAO,EAAM;OAAc;iBACvE;MACK,CAAA;KACC,CAAA;IAEP;OAEP,KACC,kBAAC,GAAD;IACE,mBAAkB;IAClB,oBAAoB;IACpB,SAAS;IACT,SAAS;cAET,kBAAC,GAAD;KACE,OAAO;MACL,YAAY,EAAM;MAClB,UAAU,EAAM;MAChB,OAAO,EAAM;KACf;eAEC;IACK,CAAA;GACC,CAAA,CAEP;MAEP,KACC,kBAAC,GAAD;GACE,OAAO;IACL,eAAe;IACf,UAAU;IACV,KAAK,EAAM;IACX,SAAS,EAAM;IACf,mBAAmB,EAAM;IACzB,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;GACrB;GAEC;EACK,CAAA,CAEJ;;AAEZ,CAAC;;;AC/ND,SAAgB,GAAmB,GAAqB,GAAwB;CAC9E,IAAI,IAAQ;CAkBZ,OAhBA,EAAS,QAAQ,IAAW,MAAU;EACpC,IAAI,CAAC,EAAe,CAAK,GACvB;EAGF,IAAM,IAAQ,EAAM;EAEpB,AAAI,OAAO,EAAM,SAAU,WACrB,EAAM,MAAM,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,KACzD,MAEO,EAAM,aACf,KAAS,GAAmB,EAAM,UAAuB,CAAM;CAEnE,CAAC,GAEM;AACT;AASA,SAAgB,GAAe,GAAkB,GAAyB;CAKxE,IAJI,CAAC,KAID,CAAC,EAAe,CAAK,GACvB,OAAO;CAGT,IAAM,IAAQ,EAAM;CAUpB,OARI,OAAO,EAAM,SAAU,WAClB,EAAM,MAAM,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,IAG5D,EAAM,WACD,GAAmB,EAAM,UAAuB,CAAM,IAAI,IAG5D;AACT;;;ACtCA,IAAa,KAA0B,EAAc,EAAK;AAI1D,SAAgB,KAAsB;CACpC,OAAO,EAAW,EAAuB;AAC3C;AAIA,IAAa,IAAuB,EAAc,EAAE,GAyCvC,KAAU,EAA+B,SACpD,EAAE,aAAU,eAAY,IAAO,YAAS,IAAI,UAAO,GAAG,KACtD,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAiB,EAAO,SAAS,GACjC,IAAQ,EAAS,QAAQ,CAAQ,EACpC,OAAO,OAAO,EACd,QAAQ,MAAU,GAAe,GAAO,CAAM,CAAC,GAE5C,IAAa,CAAC,KAAkB,EAAM,SAAS;CAErD,OACE,kBAAC,GAAwB,UAAzB;EAAkC,OAAO;YACvC,kBAAC,EAAqB,UAAtB;GAA+B,OAAO;aACpC,kBAAC,GAAD;IACO;IACL,OAAO,CACL;KACE,YAAY;KACZ,OAAO,IAAY,EAAM,yBAAyB,EAAM;KACxD,iBAAiB,EAAM;KACvB,kBAAkB;KAClB,kBAAkB,EAAM;IAC1B,GACA,CACF;IACA,GAAI;cAEJ,kBAAC,GAAD;KAAY,uBAAuB,EAAE,SAAS,EAAM,OAAO;eACxD,KAAkB,CAAC,IAClB,kBAAC,GAAD;MACE,SAAQ;MACR,OAAM;MACN,OAAO;OAAE,WAAW;OAAU,SAAS,EAAM;MAAO;gBACrD;KAEK,CAAA,IAEN,EAAM,KAAK,GAAO,MAEhB,kBAAC,GAAD,EAAA,UAAA,CACG,IAAI,KACH,kBAAC,IAAD;MACE,QAAO;MACP,OAAO,EAAE,gBAAgB,EAAM,OAAO;KACvC,CAAA,GAEF,CACO,EAAA,GARK,CAQL,CACX;IAEO,CAAA;GACN,CAAA;EACqB,CAAA;CACC,CAAA;AAEtC,CAAC,GC9EY,KAAc,EAAmC,SAC5D,EAAE,UAAO,SAAM,YAAS,IAAO,WAAQ,aAAU,UAAO,GAAG,KAC3D,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAY,GAAoB,GAChC,IAAc,EAAW,CAAoB;CASnD,OANE,EAAY,SAAS,KAAK,CAAC,EAAM,YAAY,EAAE,SAAS,EAAY,YAAY,CAAC,IAG1E,OAIP,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,UAAU;GAAQ,UAAU,CAAC,CAAC;EAAS;EAC7D,oBAAoB;EACpB,QAAQ,EAAE,iBAAc;GACtB;IACE,eAAe;IACf,YAAY;IACZ,KAAK,EAAM;IACX,iBAAiB;IACjB,mBAAmB,EAAM;IACzB,cAAc,EAAM;IACpB,SAAS,IAAW,EAAM,kBAAkB;IAC5C,iBAAiB,IACb,EAAM,gBACN,IACE,EAAM,eACN;GACR;GACA,KAAa;IAAE,gBAAgB;IAAU,mBAAmB;GAAE;GAC9D;EACF;EACA,GAAI;YAxBN;GA0BG,KAAQ,kBAAC,GAAD;IAAQ,OAAO;KAAE,YAAY;KAAG,SAAS,IAAS,IAAI;IAAK;cAAI;GAAa,CAAA;GAEpF,CAAC,KACA,kBAAC,GAAD;IACE,eAAe;IACf,eAAc;IACd,OAAO;KACL,MAAM;KACN,UAAU,EAAM;KAChB,YAAY,OACV,IAAS,EAAM,qBAAqB,EAAM,gBAC5C;KACA,OAAO,IAAS,EAAM,gBAAgB,EAAM;IAC9C;cAEC;GACG,CAAA;GAGP,CAAC,KAAa,KAAU,kBAAC,GAAD;IAAQ,OAAO,EAAE,YAAY,EAAE;cAAI;GAAe,CAAA;EAClE;;AAEf,CAAC,GC1DY,KAAiB,EAC5B,SACE,EACE,UACA,SACA,iBAAc,IACd,iBAAc,IACd,MAAM,GACN,iBACA,aACA,UACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,CAAC,GAAc,KAAmB,EAAS,CAAW,GACtD,IAAe,MAAmB,KAAA,GAClC,IAAO,IAAe,IAAiB,GAEvC,IAAY,GAAoB,GAChC,IAAc,EAAW,CAAoB,GAE7C,KAAgB,MAAkB;EAKtC,AAJK,KACH,EAAgB,CAAI,GAGtB,IAAe,CAAI;CACrB;CAWA,IATA,EAAoB,UAAY;EAC9B,cAAc,EAAa,EAAI;EAC/B,gBAAgB,EAAa,EAAK;EAClC,cAAc,EAAa,CAAC,CAAI;CAClC,EAAE,GAKE,EAFF,EAAY,WAAW,KAAK,GAAmB,GAAU,CAAW,IAAI,IAGxE,OAAO;CAGT,IAAM,IAAS,IAAY,KAAO,GAC5B,IAAa,CAAC,KAAa,CAAC,EAAE,KAAS,IAEvC,KAAU,KAAS,MACvB,kBAAC,GAAD;EACE,OAAO;GACL,eAAe;GACf,YAAY;GACZ,KAAK,EAAM;GACX,mBAAmB,EAAM;GACzB,iBAAiB;GACjB,WAAW;GACX,cAAc;EAChB;YATF;GAWG,KAAQ,kBAAC,GAAD;IAAQ,OAAO;KAAE,YAAY;KAAG,SAAS;IAAI;cAAI;GAAa,CAAA;GACtE,KACC,kBAAC,GAAD;IAAM,SAAQ;IAAkB,OAAM;IAAM,OAAO,EAAE,MAAM,EAAE;IAAG,eAAe;cAC5E;GACG,CAAA;GAEP,KACC,kBAAC,GAAD;IAAM,SAAQ;IAAU,OAAM;IAAM,OAAO,EAAE,YAAY,EAAE;cACxD,IAAO,MAAM;GACV,CAAA;EAEF;;CAGV,OACE,kBAAC,GAAD;EAAe;EAAO,GAAI;YAA1B,CACG,MACE,IACC,kBAAC,GAAD;GACE,mBAAkB;GAClB,oBAAoB,EAAE,UAAU,EAAK;GACrC,oBAAoB;GACpB,eAAe,EAAa,CAAC,CAAI;aAEhC;EACQ,CAAA,IAEX,IAGJ,kBAAC,GAAD;GACE,YAAA;GACA,mBAAkB;GAClB,OAAO;IAAE,SAAS,IAAS,SAAS;IAAQ,KAAK;GAAE;GAElD;EACK,CAAA,CACF;;AAEZ,CACF,GC5Fa,MAAY,EACvB,aAAU,QACV,WAAQ,QACR,YAAS,IACT,UAAO,IACP,WAAQ,GACR,cAAW,IACX,UACA,GAAG,QACgB;CACnB,IAAM,IAAQ,EAAc,GACtB,IAAgB,EAAiB,GACjC,IAAQ,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAEtC,IAAY,KAAY,CAAC;CAwB/B,IAtBA,QAAgB;EACd,IAAI,CAAC,GAAW;GACd,EAAM,SAAS,CAAC;GAEhB;EACF;EAEA,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM,eACzB,IAAS,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE,GAErC,IAAY,EAAS,KACzB,EAAS,SAAS,CAChB,EAAS,OAAO,GAAO;GAAE,SAAS;GAAK,UAAU;GAAK;GAAQ,iBAAiB;EAAK,CAAC,GACrF,EAAS,OAAO,GAAO;GAAE,SAAS;GAAG,UAAU;GAAK;GAAQ,iBAAiB;EAAK,CAAC,CACrF,CAAC,CACH;EAIA,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG;EAAC;EAAW;EAAO,EAAM;CAAa,CAAC,GAEtC,MAAY,QAAQ;EACtB,IAAM,IAAY,KAAK,IAAI,GAAG,KAAK,MAAM,CAAK,CAAC;EAE/C,OACE,kBAAC,GAAD;GAAQ,YAAY;GAAO,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,CAAK;GAAG,GAAI;aACxD,MAAM,KAAK,EAAE,QAAQ,EAAU,IAAI,GAAG,MACrC,kBAAC,EAAS,MAAV,EAGE,OAAO;IACL,OAAO,MAAU,IAAY,IAAI,QAAQ;IACzC,QAAQ;IACR,cAAc,EAAM;IACpB,iBAAiB,EAAM;IACvB,SAAS;GACX,EACD,GARM,CAQN,CACF;EACK,CAAA;CAEZ;CAEA,IAAM,IACJ,MAAY,WACR;EAAE,OAAO;EAAM,QAAQ;EAAM,cAAc,IAAO;CAAE,IACpD;EAAE;EAAO;EAAQ,cAAc,EAAM;CAAS;CAEpD,OACE,kBAAC,EAAS,MAAV;EACE,YAAY;EACZ,OAAO;GAAC;GAAY;IAAE,iBAAiB,EAAM;IAAmB,SAAS;GAAM;GAAG;EAAK;EACvF,GAAI;CACL,CAAA;AAEL,GCpHM,KAAe,GACf,IAAa,IACb,KAAY;AAkClB,SAAS,EAAM,GAAW,GAAa,GAAa;CAClD,OAAO,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAC,CAAC;AACvC;AAEA,SAAS,GAAW,GAAW,GAAa,GAAc,GAAkB;CAC1E,OAAO,YAAY,KAAK,OAAO,IAAI,KAAO,CAAI,IAAI,IAAO,GAAK,QAAQ,CAAQ,CAAC;AACjF;AAEA,SAAS,GAAc,GAAW;CAChC,IAAM,IAAI,EAAE,SAAS,GACf,IAAM,EAAE,QAAQ,GAAG;CAEzB,OAAO,MAAQ,KAAK,IAAI,EAAE,SAAS,IAAM;AAC3C;AA0BA,IAAa,MAAU,EACrB,UACA,aACA,SAAM,GACN,SAAM,KACN,UAAO,GACP,cAAW,IACX,UACA,uBACA,UACA,aACA,GAAG,QACc;CACjB,IAAM,IAAQ,EAAc,GACtB,CAAC,GAAY,KAAiB,EAAS,CAAC,GACxC,CAAC,GAAa,KAAkB,EAAiC,CAAC,CAAC,GAEnE,IAAK,GAAc,CAAI,GACvB,IAAU,EAAM,GAAO,GAAK,CAAG,GAC/B,KAAQ,IAAU,MAAQ,IAAM,KAAQ,KAExC,IAAoB,GACvB,MAA6B;EAE5B,AADA,EAAc,EAAM,YAAY,OAAO,KAAK,GAC5C,IAAW,CAAK;CAClB,GACA,CAAC,CAAQ,CACX,GAEM,IAAS,GACZ,MAAsB;EACjB,KAAY,KAAc,KAM9B,EAAS,EAAM,GAFF,IAAY,KAAe,IAAM,KAAO,GAEtB,GAAK,GAAM,CAAE,GAAG,GAAK,CAAG,CAAC;CAC1D,GACA;EAAC;EAAU;EAAY;EAAK;EAAK;EAAM;EAAI;CAAQ,CACrD,GAEM,IAAe,QAEjB,EAAa,OAAO;EAClB,oCAAoC,CAAC;EACrC,mCAAmC,CAAC;EACpC,sBAAsB,MAAiC,EAAO,EAAM,YAAY,SAAS;EACzF,qBAAqB,MAAiC,EAAO,EAAM,YAAY,SAAS;CAC1F,CAAC,GACH,CAAC,GAAU,CAAM,CACnB,GAEM,IAA4B,GAC/B,MAAoC;EAC/B,QAIJ,QAAQ,EAAM,YAAY,YAA1B;GACE,KAAK;IACH,EAAS,EAAM,GAAW,IAAQ,GAAM,GAAK,GAAM,CAAE,GAAG,GAAK,CAAG,CAAC;IACjE;GACF,KAAK;IACH,EAAS,EAAM,GAAW,IAAQ,GAAM,GAAK,GAAM,CAAE,GAAG,GAAK,CAAG,CAAC;IACjE;EACJ;CACF,GACA;EAAC;EAAU;EAAO;EAAM;EAAK;EAAK;EAAI;CAAQ,CAChD,GAEM,IAAW,KAAS,EAAM,SAAS,GACnC,IAAY,KAAY,EAAM,MAAM,MAAM,EAAE,KAAK,GAEjD,IAAa,IAAM,MAAO,IAAa,IAAa;CAE1D,OACE,kBAAC,GAAD;EACE,OAAO,CAAC;GAAE,OAAO;GAAQ,YAAY;GAAI,eAAe,IAAY,IAAI;EAAG,GAAG,CAAK;EACnF,GAAI;YAFN,CAIE,kBAAC,GAAD;GACE,UAAU;GACV,YAAA;GACA,mBAAkB;GACE;GACpB,oBAAoB;IAAE;IAAK;IAAK,KAAK;GAAQ;GAC7C,oBAAoB,EAAE,YAAS;GAC/B,sBAAsB,CACpB;IAAE,MAAM;IAAa,OAAO;GAAY,GACxC;IAAE,MAAM;IAAa,OAAO;GAAY,CAC1C;GACA,uBAAuB;GACvB,OAAO;IACL,gBAAgB;IAChB,QAAQ;IACR,SAAS,IAAW,EAAM,kBAAkB;GAC9C;GACA,GAAI,EAAa;aAjBnB;IAmBE,kBAAC,GAAD;KACE,eAAc;KACd,OAAO;MACL,OAAO;MACP,QAAQ;MACR,cAAc,EAAM;MACpB,iBAAiB,EAAM;MACvB,UAAU;KACZ;eAEA,kBAAC,GAAD,EACE,OAAO;MACL,QAAQ;MACR,OAAO,GAAG,EAAI;MACd,cAAc,EAAM;MACpB,iBAAiB,EAAM;KACzB,EACD,CAAA;IACG,CAAA;IAEN,kBAAC,GAAD;KACE,eAAc;KACd,OAAO;MACL,UAAU;MACV,MAAM;MACN,OAAO;MACP,QAAQ;MACR,cAAc,EAAM;MACpB,iBAAiB,EAAM;MACvB,aAAa;MACb,aAAa,EAAM;MACnB,aAAa;MACb,cAAc;OAAE,OAAO;OAAG,QAAQ;MAAE;MACpC,eAAe;MACf,cAAc;MACd,WAAW;KACb;IACD,CAAA;IAEA,KACC,EAAM,KAAK,MAKP,kBAAC,GAAD;KAEE,eAAc;KACd,2BAA0B;KAC1B,OAAO;MACL,UAAU;MACV,OAVS,EAAM,EAAE,OAAO,GAAK,CAAG,IAAI,MAAQ,IAAM,KAAQ,MACvC,MAAO,IAAa,KAAY;MAUnD,OAAO;MACP,QAAQ;MACR,cAAc,KAAY;MAC1B,iBAAiB,EAAM;KACzB;IACD,GAXM,EAAE,KAWR,CAEJ;GACC;MAEL,KACC,kBAAC,GAAD;GACE,2BAA0B;GAC1B,OAAO;IAAE,UAAU;IAAY,OAAO;IAAQ,QAAQ;IAAI,WAAW;GAAE;aAEtE,EAAM,KAAK,MAeR,kBAAC,GAAD;IAEE,eAAe;IACf,WAAW,MAAU;KACnB,IAAM,EACJ,QAAQ,EAAE,eACR,EAAM;KAEV,GAAgB,MACd,EAAK,EAAE,WAAW,IAAQ,IAAO;MAAE,GAAG;OAAO,EAAE,QAAQ;KAAM,CAC/D;IACF;IACA,OAAO;KACL,UAAU;KACV,OA5BS,EAAM,EAAE,OAAO,GAAK,CAAG,IAAI,MAAQ,IAAM,KAAQ,MACxC,MAAO,KACZ,EAAY,EAAE,UAAU,KA0BR;KAC7B,YAAY,EAAM;KAClB,UAAU,EAAM;KAChB,OAAO,EAAM;KACb,SAAS,EAAM;IACjB;cAEC,EAAE;GACC,GArBC,EAAE,KAqBH,CAET;EACG,CAAA,CAEJ;;AAEV,GCrSM,KAAW;AAkCjB,SAAS,GAAc,GAAmB;CACxC,IAAM,IAAI,EAAE,SAAS,GACf,IAAM,EAAE,QAAQ,GAAG;CAEzB,OAAO,MAAQ,KAAK,IAAI,EAAE,SAAS,IAAM;AAC3C;AAEA,SAAS,GAAM,GAAe,GAAa,GAAqB;CAC9D,OAAO,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAK,CAAC;AAC3C;AAEA,SAAS,GAAU,GAAe,GAAa,GAAa,GAAsB;CAChF,IAAM,IAAQ,IAAM,IAAM;CAC1B,SAAW,IAAQ,KAAO,IAAS,KAAS,IAAS;AACvD;AA0BA,IAAa,MAAc,EACzB,UACA,aACA,SAAM,GACN,SAAM,KACN,UAAO,GACP,aACA,UAAO,IACP,WACA,cAAW,IACX,uBACA,eACqB;CACrB,IAAM,IAAQ,EAAc,GACtB,IAAK,KAAY,GAAc,CAAI,GAEnC,IAAM,GACT,MAAiB;EAChB,IAAM,IAAU,IAAO,GAAU,GAAM,GAAK,GAAK,CAAI,IAAI,GAAM,GAAM,GAAK,CAAG;EAC7E,EAAS,WAAW,EAAQ,QAAQ,CAAE,CAAC,CAAC;CAC1C,GACA;EAAC;EAAU;EAAK;EAAK;EAAM;EAAI;CAAI,CACrC,GAEM,IAAc,IAAS,EAAO,CAAK,IAAI,EAAM,QAAQ,CAAE,GAEvD,IAA4B,GAC/B,MAAoC;EAC/B,QAIJ,QAAQ,EAAM,YAAY,YAA1B;GACE,KAAK;IACH,EAAI,IAAQ,CAAI;IAChB;GACF,KAAK;IACH,EAAI,IAAQ,CAAI;IAChB;EACJ;CACF,GACA;EAAC;EAAU;EAAO;EAAM;CAAG,CAC7B,GAEM,IAAoB,KAAa,CAAC,KAAQ,KAAS,GACnD,IAAoB,KAAa,CAAC,KAAQ,KAAS;CAEzD,OACE,kBAAC,GAAD;EACE,YAAA;EACA,mBAAkB;EACE;EACpB,oBAAoB;GAAE;GAAK;GAAK,KAAK;GAAO,MAAM,IAAS,IAAc,KAAA;EAAU;EACnF,oBAAoB,EAAE,YAAS;EAC/B,sBAAsB,CACpB;GAAE,MAAM;GAAa,OAAO;EAAY,GACxC;GAAE,MAAM;GAAa,OAAO;EAAY,CAC1C;EACA,uBAAuB;EACvB,OAAO,CACL;GACE,eAAe;GACf,WAAW;GACX,YAAY;GACZ,aAAa;GACb,aAAa,EAAM;GACnB,cAAc,EAAM;GACpB,iBAAiB,EAAM;GACvB,UAAU;GACV,SAAS,IAAW,EAAM,kBAAkB;EAC9C,GACA,CACF;YAxBF;GA0BE,kBAAC,GAAD;IACE,6BAAA;IACA,2BAA0B;IAC1B,UAAU;IACV,eAAe,EAAI,IAAQ,CAAI;IAC/B,QAAQ,EAAE,kBAAe;KACvB,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,gBAAgB;KAChB,kBAAkB;KAClB,kBAAkB,EAAM;KACxB,iBAAiB,KAAW,CAAC,IAAoB,EAAM,gBAAgB;KACvE,SAAS,IAAoB,EAAM,kBAAkB;IACvD;cAEA,kBAAC,GAAD;KAAM,OAAO;MAAE,UAAU;MAAI,YAAY;MAAI,OAAO,EAAM;KAAY;eAAG;IAAO,CAAA;GACvE,CAAA;GAEX,kBAAC,GAAD;IACE,6BAAA;IACA,2BAA0B;IAC1B,OAAO;KACL,UAAU;KACV,WAAW;KACX,mBAAmB,EAAM;KACzB,YAAY,EAAM;KAClB,UAAU,EAAM;KAChB,aAAa,CAAC,cAAc;KAC5B,OAAO,EAAM;IACf;cAEC;GACG,CAAA;GAEN,kBAAC,GAAD;IACE,6BAAA;IACA,2BAA0B;IAC1B,UAAU;IACV,eAAe,EAAI,IAAQ,CAAI;IAC/B,QAAQ,EAAE,kBAAe;KACvB,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,gBAAgB;KAChB,iBAAiB;KACjB,iBAAiB,EAAM;KACvB,iBAAiB,KAAW,CAAC,IAAoB,EAAM,gBAAgB;KACvE,SAAS,IAAoB,EAAM,kBAAkB;IACvD;cAEA,kBAAC,GAAD;KAAM,OAAO;MAAE,UAAU;MAAI,YAAY;MAAI,OAAO,EAAM;KAAY;eAAG;IAAO,CAAA;GACvE,CAAA;EACP;;AAEV,GCzMM,KAAyE;CAC7E,IAAI;EAAE,WAAW;EAAI,aAAa;CAAE;CACpC,IAAI;EAAE,WAAW;EAAI,aAAa;CAAI;CACtC,IAAI;EAAE,WAAW;EAAI,aAAa;CAAE;AACtC,GA4Ca,MAAW,EAAE,UAAO,MAAM,WAAQ,YAAY,UAAO,GAAG,QAA8B;CACjG,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GAEjC,IAAO,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE;CAE3C,QAAgB;EACd,EAAK,SAAS,CAAC;EAEf,IAAM,IAAY,EAAS,KACzB,EAAS,OAAO,GAAM;GACpB,SAAS;GACT,UAAU,IAAgB,MAAO;GACjC,QAAQ,EAAO;GACf,iBAAiB;EACnB,CAAC,CACH;EAIA,OAFA,EAAU,MAAM,SAEH,EAAU,KAAK;CAC9B,GAAG,CAAC,GAAM,CAAa,CAAC;CAExB,IAAM,IAAS,EAAK,YAAY;EAAE,YAAY,CAAC,GAAG,CAAC;EAAG,aAAa,CAAC,QAAQ,QAAQ;CAAE,CAAC,GACjF,EAAE,cAAW,mBAAgB,GAAM,IACnC,IAAa,MAAW,SAAS,8BAA8B;CAErE,OACE,kBAAC,EAAS,MAAV;EACE,YAAA;EACA,mBAAkB;EAClB,oBAAoB,KAAS,KAAA;EAC7B,6BAA6B,MAAU;EACvC,2BAA2B,MAAU,KAAK,wBAAwB;EAClE,OAAO,CACL;GACE,OAAO;GACP,QAAQ;GACR,cAAc,IAAY;GAC1B;GACA,aAAa;GACb,gBAAgB,EAAM;GACtB,WAAW,CAAC,EAAE,UAAO,CAAC;EACxB,GACA,CACF;EACA,GAAI;CACL,CAAA;AAEL,GC1FM,KAAc,IACd,KAAe,IACf,KAAa,IACb,KAAc,GAEd,KAAe,IAyBR,KAAS,EAA8B,SAClD,EAAE,UAAO,kBAAe,aAAU,UAAO,GAAG,KAC5C,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAc,EAAuB,GACrC,IAAW,EAAoB,GAC/B,IAAW,EAAO,IAAI,EAAS,MAAM,IAAa,CAAC,EAAE,SACrD,IAAiB,EAAO,EAAI;CAElC,QAAgB;EAId,IAAI,EAAe,SAAS;GAC1B,EAAe,UAAU;GACzB;EACF;EAEA,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAU;GACxB,SAAS;GACT,UAAU,EAAM;GAChB,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAO;EAAU,EAAM;EAAc,EAAM;CAAa,CAAC;CAE7D,IAAM,IAAgB,MAAgB,SAAS,EAAM,QAAQ,EAAM,QAC7D,IAAgB,MAAgB,SAAS,EAAM,SAAS,QAExD,IAAkB,EAAS,YAAY;EAC3C,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,GAAe,EAAM,aAAa;CAClD,CAAC,GACK,IAAc,EAAS,YAAY;EACvC,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,EAAM,cAAc,EAAM,aAAa;CACvD,CAAC;CAED,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,SAAS;GAAO,UAAU,CAAC,CAAC;EAAS;EAC3D,eAAe,IAAgB,CAAC,CAAK;EACrC,OAAO,CAAC,EAAE,SAAS,IAAW,EAAM,kBAAkB,EAAE,GAAG,CAAK;EAChE,GAAI;YAEJ,kBAAC,EAAS,MAAV;GACE,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc,EAAM;IACpB,aAAa,MAAa,SAAS,IAAI;IACvC;IACA;GACF;aAEA,kBAAC,EAAS,MAAV,EACE,OAAO,CACL;IACE,UAAU;IACV,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,cAAc,EAAM;IACpB,iBAAiB,IAAQ,SAAS;IAClC,WAAW,CACT,EACE,YAAY,EAAS,YAAY;KAC/B,YAAY,CAAC,GAAG,CAAC;KACjB,aAAa,CAAC,GAAG,EAAY;IAC/B,CAAC,EACH,CACF;GACF,GACA,MAAa,UAAU;IACrB,aAAa;IACb,cAAc;KAAE,OAAO;KAAG,QAAQ;IAAE;IACpC,eAAe;IACf,cAAc;IACd,WAAW;GACb,CACF,EACD,CAAA;EACY,CAAA;CACN,CAAA;AAEf,CAAC,GCnGY,KAAS,EAAoC,SACxD,EAAE,aAAU,YAAS,IAAO,wBAAqB,QAAQ,UAAO,GAAG,KACnE,GACA;CACA,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACO;EACL,YAAA;EACA,gCAAgC;EAChC,gCAA+B;EAC/B,YAAA;EACA,mBAAkB;EACE;EACpB,OAAO,CACL;GACE,UAAU;GACV,iBAAiB,IAAS,gBAAgB,EAAM;GAChD,mBAAmB;GACnB,mBAAmB,EAAM;EAC3B,GACA,CACF;EACA,uBAAuB;GACrB,eAAe;GACf,YAAY;GACZ,mBAAmB,EAAM;GACzB,KAAK;GACL,WAAW;EACb;EACA,GAAI;EAEH;CACW,CAAA;AAElB,CAAC,GCjBY,KAAU,EAA+B,SACpD,EACE,UACA,SACA,YAAS,IACT,YACA,gBAAa,aACb,UACA,aACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,UAAU;GAAQ,UAAU,CAAC,CAAC;EAAS;EAC7D,oBAAoB;EACpB,QAAQ,EAAE,kBAAe;GACvB,UAAU;GACV,eAAe;GACf,YAAY;GACZ,KAAK,EAAM;GACX,mBAAmB,EAAM;GACzB,UAAU;GACV,UAAU;GACV,WAAW;GACX,cAAc,EAAM;GACpB,SAAS,IAAW,EAAM,kBAAkB,IAAS,IAAI;GACzD,iBAAiB,IACb,EAAM,gBACN,IACE,EAAM,eACN;EACR;EACA,GAAI;YAvBN;GAyBG,KAAQ,kBAAC,GAAD;IAAQ,OAAO,EAAE,YAAY,EAAE;cAAI;GAAa,CAAA;GAEzD,kBAAC,GAAD;IACE,eAAe;IACf,eAAc;IACd,OAAO;KACL,YAAY,EAAM;KAClB,UAAU,EAAM;KAChB,YAAY,OACV,IAAS,EAAM,qBAAqB,EAAM,gBAC5C;KACA,OAAO,EAAM;IACf;cAEC;GACK,CAAA;GAEP,MAAU,KAAA,KACT,kBAAC,GAAD;IACE,OAAO;KACL,YAAY;KACZ,UAAU;KACV,QAAQ;KACR,mBAAmB;KACnB,cAAc;KACd,YAAY;KACZ,gBAAgB;KAChB,iBAAiB,EAAM;IACzB;cAEA,kBAAC,GAAD;KACE,OAAO;MACL,YAAY,EAAM;MAClB,UAAU;MACV,YAAY;MACZ,OAAO,EAAM;KACf;eAEC,IAAQ,KAAK,QAAQ;IAChB,CAAA;GACF,CAAA;GAGT,KACC,kBAAC,GAAD;IACE,mBAAkB;IAClB,oBAAoB;IACpB,SAAS;IACT,SAAS;IACT,QAAQ,EAAE,kBAAe;KACvB,YAAY;KACZ,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,gBAAgB;KAChB,cAAc,EAAM;KACpB,iBAAiB,IAAU,EAAM,gBAAgB;IACnD;cAEA,kBAAC,GAAD;KACE,OAAO;MACL,YAAY,EAAM;MAClB,UAAU;MACV,YAAY;MACZ,OAAO,EAAM;KACf;eAEC;IACK,CAAA;GACC,CAAA;GAGZ,KACC,kBAAC,GAAD;IACE,eAAc;IACd,OAAO;KACL,UAAU;KACV,QAAQ;KACR,MAAM,EAAM;KACZ,OAAO,EAAM;KACb,QAAQ;KACR,cAAc;KACd,iBAAiB,EAAM;IACzB;GACD,CAAA;EAEM;;AAEf,CAAC,GC7JY,KAAW,EAAgC,SACtD,EAAE,YAAS,IAAO,UAAO,aAAU,GAAG,KACtC,GACA;CACA,OACE,kBAAC,GAAD;EAAa;EAAK,OAAO,CAAC,EAAE,SAAS,IAAS,SAAS,OAAO,GAAG,CAAK;EAAG,GAAI;EAC1E;CACK,CAAA;AAEZ,CAAC;;;ACVD,SAAS,GAAS,GAAe,GAAwB;CACvD,IAAM,IAAQ,EAAM,MAAM,8CAA8C;CAExE,IAAI,CAAC,GACH,OAAO;CAGT,IAAM,GAAG,GAAG,GAAG,GAAG,KAAK,GACjB,KAAS,IAAI,OAAO,WAAW,CAAC,IAAI,KAAK;CAE/C,OAAO,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAM;AAC9D;AAsBA,IAAa,KAAY,EAAsC,SAC7D,EACE,UACA,eACA,UACA,UACA,eACA,cAAW,IACX,YACA,WACA,uBACA,sBACA,GAAG,KAEL,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAW,EAAoB,GAC/B,CAAC,GAAS,KAAc,EAAS,EAAK,GACtC,IAAW,CAAC,GACZ,IAAO,KAAS,GAEhB,IAAc,IAAQ,EAAM,aAAa,IAAU,EAAM,cAAc,EAAM;CAEnF,OACE,kBAAC,GAAD;EAAM,OAAO,CAAC;GAAE,KAAK,EAAM;GAAQ,SAAS,IAAW,EAAM,kBAAkB;EAAE,GAAG,CAAK;YAAzF;GACG,KACC,kBAAC,GAAD;IACE,SAAQ;IACR,OAAO,EAAE,YAAY,OAAO,EAAM,kBAAkB,EAA6B;cAEhF;GACG,CAAA;GAGR,kBAAC,GAAD;IACO;IACK;IACV,oBAAoB,KAAsB;IAC1C,mBAAmB,KAAqB;IACxC,sBAAsB,GAAS,EAAM,eAAe,EAAM,UAAU;IACpE,UAAU,MAAU;KAElB,AADA,EAAW,EAAI,GACf,IAAU,CAAK;IACjB;IACA,SAAS,MAAU;KAEjB,AADA,EAAW,EAAK,GAChB,IAAS,CAAK;IAChB;IACA,OAAO,CACL;KACE,OAAO;KACP,iBAAiB;KACjB,mBAAmB,EAAM;KACzB,YAAY,EAAM;KAClB,UAAU,EAAM;KAChB,YAAY,KAAK,MAAM,EAAM,eAAe,EAAM,cAAc;KAChE,OAAO,EAAM;KACb,iBAAiB,EAAM;KACvB,cAAc,EAAM;KACpB,aAAa,MAAa,SAAS,IAAI;KACvC;IACF,GACA,CACF;IACA,GAAI;GACL,CAAA;GAEA,KACC,kBAAC,GAAD;IACE,SAAQ;IACR,OAAO;KACL,OAAO,IAAQ,EAAM,aAAa,EAAM;KACxC,SAAS,IAAQ,IAAI,EAAM;IAC7B;cAEC;GACG,CAAA;EAEJ;;AAEV,CAAC,GClIK,KAAoB,EAAS,wBAAwB,CAAS,GA0DvD,MAAS,EACpB,UACA,cAAW,KACX,cACA,gBACA,aACA,iBAAc,IACd,UACA,GAAG,QACa;CAChB,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GAEjC,IAAW,EAA6C,IAAI,GAC5D,IAAe,EAAO,CAAQ,GAC9B,IAAe,EAAO,CAAC,GACvB,IAAW,EAAO,IAAI,EAAS,MAAM,IAAqB,CAAC,EAAE,SAE7D,IAAa,QAAkB;EACnC,AAEE,EAAS,aADT,aAAa,EAAS,OAAO,GACV;CAEvB,GAAG,CAAC,CAAC,GAEC,IAAa,GAChB,MAAe;EACV,KAAM,KAAK,CAAC,MAIhB,EAAW,GACX,EAAa,UAAU,KAAK,IAAI,GAChC,EAAS,UAAU,iBAAiB,EAAU,GAAG,CAAE;CACrD,GACA,CAAC,GAAW,CAAU,CACxB;CAWA,AATA,SACM,IAAW,MACb,EAAa,UAAU,GACvB,EAAW,CAAQ,IAGd,IACN;EAAC;EAAU;EAAY;CAAU,CAAC,GAErC,QAAgB;EACd,IAAI,GAAe;GACjB,EAAS,SAAS,CAAC;GAEnB;EACF;EAEA,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAM;EAE/B,EAAS,OAAO,GAAU;GACxB,SAAS;GACT,UAAU,EAAM;GAChB,QAAQ,EAAO,OAAO,GAAI,GAAI,GAAI,CAAE;GACpC,iBAAiB;EACnB,CAAC,EAAE,MAAM;CACX,GAAG;EAAC;EAAe;EAAU,EAAM;EAAgB,EAAM;CAAa,CAAC;CAEvE,IAAM,UAAsB;EAC1B,IAAI,EAAS,SAAS;GACpB,IAAM,IAAU,KAAK,IAAI,IAAI,EAAa;GAG1C,AADA,EAAa,UAAU,KAAK,IAAI,GAAG,EAAa,UAAU,CAAO,GACjE,EAAW;EACb;CACF,GAEM,UAAuB;EAC3B,EAAW,EAAa,OAAO;CACjC,GAEM,UAAqB;EAGzB,AAFA,EAAW,GACX,IAAW,GACX,IAAY;CACd,GAEM,IACJ,MAAW,SACP;EAAE,eAAe;EAAK,cAAc;EAAI,WAAW;CAAE,IACrD;EAAE,eAAe;EAAM,cAAc;EAAG,WAAW;CAAE;CAE3D,OACE,kBAAC,IAAD;EACE,YAAA;EACA,mBAAkB;EAClB,yBAAwB;EACxB,WAAW;EACX,YAAY;EACZ,OAAO,CACL;GACE,eAAe;GACf,YAAY;GACZ,KAAK,EAAM;GACX,iBAAiB;GACjB,cAAc,EAAM;GACpB,aAAa,EAAM;GACnB,WAAW;GACX,UAAU;GACV,UAAU;GACV,iBAAiB,EAAM;GACvB,cAAc,EAAM;GACpB,aAAa;GACb,cAAc;IAAE,OAAO;IAAG,QAAQ;GAAE;GACpC,SAAS;GACT,WAAW,CACT,EACE,YAAY,EAAS,YAAY;IAAE,YAAY,CAAC,GAAG,CAAC;IAAG,aAAa,CAAC,IAAI,CAAC;GAAE,CAAC,EAC/E,GACA,EAAE,OAAO,EAAS,YAAY;IAAE,YAAY,CAAC,GAAG,CAAC;IAAG,aAAa,CAAC,KAAM,CAAC;GAAE,CAAC,EAAE,CAChF;GACA,GAAG;EACL,GACA,CACF;EACA,GAAI;YAhCN,CAkCE,kBAAC,GAAD;GACE,SAAQ;GACR,OAAO;IAAE,MAAM;IAAG,UAAU;GAAE;GAC9B,eAAe,OAAO,KAAU,WAAW,IAAI,KAAA;aAE9C;EACG,CAAA,IAEJ,KAAe,MACf,kBAAA,GAAA,EAAA,UAAA,CACG,KACC,kBAAC,GAAD;GACE,mBAAkB;GAClB,oBAAoB;GACpB,SAAS;GACT,QAAQ,EAAE,kBAAe;IACvB,iBAAiB;IACjB,mBAAmB,EAAM;IACzB,cAAc,EAAM;IACpB,iBAAiB,IAAU,EAAM,gBAAgB;GACnD;aAEA,kBAAC,GAAD;IACE,OAAO;KACL,YAAY,EAAM;KAClB,UAAU,EAAM;KAChB,YAAY,OAAO,EAAM,kBAAkB;KAC3C,OAAO,EAAM;IACf;cAEC;GACK,CAAA;EACC,CAAA,GAGZ,KACC,kBAAC,GAAD;GACE,mBAAkB;GAClB,oBAAmB;GACnB,SAAS;GACT,eAAe;IAEb,AADA,EAAW,GACX,IAAY;GACd;GACA,QAAQ,EAAE,kBAAe;IACvB,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,cAAc,EAAM;IACpB,SAAS,IAAU,IAAI;IACvB,iBAAiB,IAAU,EAAM,gBAAgB;GACnD;aAEA,kBAAC,GAAD;IAAQ,OAAO;KAAE,UAAU,EAAM;KAAc,OAAO,EAAM;IAAc;cACvE;GACK,CAAA;EACC,CAAA,CAEb,EAAA,CAAA,CAEa;;AAEvB,GCjNa,MAAW,EAAE,cAAW,UAAU,aAAU,UAAO,GAAG,QAA8B;CAC/F,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACE,eAAc;EACd,oBAAmB;EACnB,OAAO;GACL;IACE,UAAU;IACV,MAAM;IACN,OAAO;IACP,YAAY;IACZ,KAAK,EAAM;IACX,QAAQ;GACV;GACA,MAAa,QAAQ,EAAE,KAAK,EAAM,OAAO,IAAI,EAAE,QAAQ,EAAM,OAAO;GACpE;EACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,GCJM,KAAM,GACN,IAAS,GACT,KAAQ;AAEd,SAAS,GAAa,GAAyB,GAAiB;CACzD,OAIL;MAAI,OAAO,KAAQ,YAAY;GAC7B,EAAI,CAAK;GAET;EACF;EAEA,EAA+B,UAAU;CAFzC;AAGF;AAEA,SAAS,GAAc,GAAe,GAAe,GAA6B;CAChF,QAAQ,GAAR;EACE,KAAK,OACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS;GAClC,MAAM,EAAQ,IAAI,EAAQ,QAAQ,IAAI,EAAQ,QAAQ;EACxD;EACF,KAAK,UACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS;GAClC,MAAM,EAAQ,IAAI,EAAQ,QAAQ,IAAI,EAAQ,QAAQ;EACxD;EACF,KAAK,QACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS,IAAI,EAAQ,SAAS;GACvD,MAAM,EAAQ,IAAI,EAAQ,QAAQ;EACpC;EACF,KAAK,SACH,OAAO;GACL,KAAK,EAAQ,IAAI,EAAQ,SAAS,IAAI,EAAQ,SAAS;GACvD,MAAM,EAAQ,IAAI,EAAQ,QAAQ;EACpC;CACJ;AACF;AAEA,SAAS,GAAgB,GAAe,GAAe,GAAuC;CAC5F,IAAM,EAAE,OAAO,GAAI,QAAQ,MAAO,EAAW,IAAI,QAAQ,GAUnD,IAAiC;EAAC;EAPtC,MAAc,QACV,WACA,MAAc,WACZ,QACA,MAAc,SACZ,UACA;EACmD;EAAO;EAAU;EAAQ;CAAO;CAE7F,KAAK,IAAM,KAAK,GAAY;EAC1B,IAAM,EAAE,QAAK,YAAS,GAAc,GAAS,GAAS,CAAC,GACjD,IAAQ,KAAQ,KAAU,IAAO,EAAQ,SAAS,IAAK,GACvD,IAAQ,KAAO,KAAU,IAAM,EAAQ,UAAU,IAAK;EAE5D,IAAI,KAAS,GACX,OAAO;GACL,KAAK,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAK,IAAK,EAAQ,SAAS,CAAM,CAAC;GACjE,MAAM,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAM,IAAK,EAAQ,QAAQ,CAAM,CAAC;GAClE,WAAW;EACb;CAEJ;CAEA,IAAM,EAAE,QAAK,YAAS,GAAc,GAAS,GAAS,CAAS;CAE/D,OAAO;EACL,KAAK,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAK,IAAK,EAAQ,SAAS,CAAM,CAAC;EACjE,MAAM,KAAK,IAAI,GAAQ,KAAK,IAAI,GAAM,IAAK,EAAQ,QAAQ,CAAM,CAAC;EAClE,WAAW;CACb;AACF;AA2DA,IAAa,MAAW,EACtB,UACA,WAAW,IAAqB,OAChC,WAAQ,KACR,kBACkB;CAClB,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB,GAChC,IAAgB,EAAiB,GAEjC,CAAC,GAAS,KAAc,EAAS,EAAK,GACtC,CAAC,GAAa,KAAkB,EAAsB,IAAI,GAC1D,CAAC,GAAa,KAAkB,EAAsB,IAAI,GAC1D,CAAC,GAAK,KAAU,EAA0B,IAAI,GAE9C,IAAa,EAAa,IAAI,GAC9B,IAAW,EAA6C,IAAI,GAC5D,IAAW,EAAO,IAAI,EAAS,MAAM,CAAC,CAAC,EAAE,SAEzC,IAAa,QAAkB;EACnC,AAEE,EAAS,aADT,aAAa,EAAS,OAAO,GACV;CAEvB,GAAG,CAAC,CAAC,GAEC,IAAO,QAAkB;EAE7B,AADA,EAAW,GACX,EAAW,EAAI;CACjB,GAAG,CAAC,CAAU,CAAC,GAET,IAAc,QAAkB;EAEpC,AADA,EAAW,GACX,EAAS,UAAU,WAAW,GAAM,CAAK;CAC3C,GAAG;EAAC;EAAY;EAAM;CAAK,CAAC,GAEtB,IAAQ,QAAkB;EAE9B,AADA,EAAW,GACX,EAAW,EAAK;CAClB,GAAG,CAAC,CAAU,CAAC;CA8Cf,AA3CA,QAAgB;EACd,IAAI,CAAC,GAAS;GAGZ,AAFA,EAAe,IAAI,GACnB,EAAe,IAAI,GACnB,EAAO,IAAI;GAEX;EACF;EAEA,EAAW,SAAS,iBAAiB,GAAG,GAAG,GAAO,MAAW;GAC3D,EAAe;IAAE;IAAG;IAAG;IAAO;GAAO,CAAC;EACxC,CAAC;CACH,GAAG,CAAC,CAAO,CAAC,GAIZ,QAAgB;EACV,CAAC,KAAe,CAAC,KAIrB,EAAO,GAAgB,GAAa,GAAa,CAAkB,CAAC;CACtE,GAAG;EAAC;EAAa;EAAa;CAAkB,CAAC,GAEjD,QAAgB;EACT,OAIL;OAAI,GAAe;IACjB,EAAS,SAAS,CAAC;IAEnB;GACF;GAGA,AADA,EAAS,SAAS,CAAC,GACnB,EAAS,OAAO,GAAU;IACxB,SAAS;IACT,UAAU,EAAM;IAChB,iBAAiB;GACnB,CAAC,EAAE,MAAM;EAPT;CAQF,GAAG;EAAC;EAAK;EAAe;EAAU,EAAM;CAAY,CAAC,GAErD,QAAgB,GAAY,CAAC,CAAU,CAAC;CAExC,IAAM,KAAuB,MAAyB;EACpD,IAAM,EAAE,UAAO,cAAW,EAAE,YAAY;EAExC,EAAe;GAAE;GAAO;EAAO,CAAC;CAClC,GAEM,IAAK,MAAW,SAAS,YAAY,WACrC,KAAK,MAAW,SAAS,uBAAuB,QAChD,IACJ,MAAW,SACP;EAAE,eAAe;EAAK,cAAc;EAAG,WAAW;CAAE,IACpD;EAAE,eAAe;EAAK,cAAc;EAAG,WAAW;CAAE,GAEpD,IAAY;EAChB,UAAU;EACV,OAAO;EACP,QAAQ;EACR,aAAa;EACb,aAAa;CACf,GAEM,WAAoB;EACxB,QAAQ,GAAK,WAAb;GACE,KAAK,OACH,OAAO;IACL,GAAG;IACH,KAAK;IACL,MAAM;IACN,YAAY;IACZ,gBAAgB;GAClB;GACF,KAAK,UACH,OAAO;IACL,GAAG;IACH,QAAQ;IACR,MAAM;IACN,YAAY;IACZ,mBAAmB;GACrB;GACF,KAAK,QACH,OAAO;IACL,GAAG;IACH,MAAM;IACN,KAAK;IACL,WAAW;IACX,iBAAiB;GACnB;GACF,KAAK,SACH,OAAO;IACL,GAAG;IACH,OAAO;IACP,KAAK;IACL,WAAW;IACX,kBAAkB;GACpB;GACF,SACE,OAAO;EACX;CACF,GAAG,GAEG,KAAe,EAAS,MAA8B;CAmC5D,OACE,kBAAA,GAAA,EAAA,UAAA,CAlCY,EAAa,GAAU;EACnC,MAAM,MAAsB;GAE1B,AADA,EAAyC,UAAU,GACnD,GAAU,IAAa,CAAI;EAC7B;EACA,gBAAgB;EAChB,mBAAmB,EAAS,MAAM,qBAAqB;EACvD,cAAc,MAA6B;GAEzC,AADA,EAAK,GACL,EAAS,MAAM,cAAc,CAAC;EAChC;EACA,aAAa,MAA6B;GAExC,AADA,EAAM,GACN,EAAS,MAAM,aAAa,CAAC;EAC/B;EACA,YAAY,MAAkB;GAE5B,AADA,EAAY,GACZ,EAAS,MAAM,YAAY,CAAC;EAC9B;EACA,aAAa,MAAkB;GAE7B,AADA,EAAM,GACN,EAAS,MAAM,aAAa,CAAC;EAC/B;EACA,UAAU,MAA2C;GAEnD,AADA,EAAY,GACZ,EAAS,MAAM,UAAU,CAAC;EAC5B;EACA,SAAS,MAA2C;GAElD,AADA,EAAM,GACN,EAAS,MAAM,SAAS,CAAC;EAC3B;CACF,CAIK,GACD,kBAAC,GAAD;EAAgB;EAAS,aAAA;EAAY,eAAc;EAAO,sBAAA;YACxD,kBAAC,GAAD;GAAM,eAAc;GAAW,OAAO,EAAW;aAC/C,kBAAC,EAAS,MAAV;IACE,UAAU;IACV,YAAA;IACA,MAAK;IACL,OAAO,CACL;KACE,UAAU;KACV,UAAU;KACV,iBAAiB;KACjB,mBAAmB,EAAM;KACzB,iBAAiB;KACjB,cAAc,EAAM;KACpB,aAAa;KACb,cAAc;MAAE,OAAO;MAAG,QAAQ;KAAE;KACpC,GAAG;IACL,GACA,IACI;KAAE,KAAK,EAAI;KAAK,MAAM,EAAI;KAAM,SAAS;IAAS,IAClD;KAAE,KAAK;KAAO,MAAM;KAAO,SAAS;IAAE,CAC5C;cAnBF,CAqBE,kBAAC,GAAD;KACE,OAAO;MACL,OAAO;MACP,UAAU,EAAM;MAChB,YAAY,OAAO,EAAM,gBAAgB;MACzC,YAAY,EAAM,kBAAkB,EAAM;MAC1C,WAAW;KACb;eAEC;IACG,CAAA,GACL,KAAc,kBAAC,GAAD,EAAM,OAAO,EAAa,CAAA,CAC5B;;EACX,CAAA;CACD,CAAA,CACP,EAAA,CAAA;AAEN,GC1Ya,KAAe,EAAoC,SAC9D,EAAE,aAAU,wBAAqB,iBAAiB,UAAO,GAAG,KAC5D,GACA;CACA,IAAM,IAAQ,EAAc,GACtB,IAAS,EAAuB;CAEtC,OACE,kBAAC,GAAD;EACO;EACL,YAAA;EACA,mBAAkB;EACE;EACpB,OAAO,CACL;GACE,WAAW;GACX,cAAc,EAAM;GACpB,UAAU;GACV,iBAAiB,EAAM;EACzB,GACA,CACF;EACA,GAAI;YAdN,CAgBE,kBAAC,GAAD;GACE,eAAc;GACd,OAAO,CACL,EAAW,cACX,EAAE,iBAAiB,MAAW,SAAS,uBAAuB,sBAAsB,CACtF;EACD,CAAA,GACD,kBAAC,GAAD;GAAQ,OAAO;IAAE,eAAe;IAAO,YAAY;IAAU,KAAK;IAAG,SAAS;GAAE;GAC7E;EACK,CAAA,CACF;;AAEZ,CAAC,GCxCY,KAAmB,EAAwC,SACtE,EAAE,UAAO,SAAM,YAAS,IAAO,aAAU,GAAG,KAC5C,GACA;CACA,IAAM,IAAQ,EAAc;CAE5B,OACE,kBAAC,GAAD;EACO;EACK;EACV,mBAAkB;EAClB,oBAAoB;GAAE,SAAS;GAAQ,UAAU,CAAC,CAAC;EAAS;EAC5D,oBAAoB;EACpB,QAAQ,EAAE,kBAAe;GACvB,eAAe;GACf,YAAY;GACZ,gBAAgB;GAChB,KAAK,EAAM;GACX,iBAAiB;GACjB,mBAAmB,EAAM;GACzB,cAAc,EAAM,aAAa;GACjC,SAAS,IAAW,EAAM,kBAAkB;GAC5C,iBAAiB,IACb,EAAM,mBACN,IACE,EAAM,gBACN;EACR;EACA,GAAI;YArBN,CAuBG,KAAQ,kBAAC,GAAD;GAAQ,OAAO,EAAE,YAAY,EAAE;aAAI;EAAa,CAAA,GAEzD,kBAAC,GAAD;GACE,OAAO;IACL,YAAY,EAAM;IAClB,UAAU,EAAM;IAChB,YAAY,OACV,IAAS,EAAM,qBAAqB,EAAM,gBAC5C;IACA,OAAO,EAAM;GACf;aAEC;EACK,CAAA,CACC;;AAEf,CAAC"}
|