@gnome-ui/react-native 1.4.0 → 1.5.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 CHANGED
@@ -20,8 +20,9 @@ React Native component library following the [GNOME Human Interface Guidelines](
20
20
  > own public component) shipped — `Status Page` skipped for now. Tier 5
21
21
  > Advanced Controls fully ported: `Dropdown`, `Slider`, `SpinButton`,
22
22
  > `Avatar`, `Badge`, and `Popover`. Beyond Tier 5, `BottomSheet` (Tier 14)
23
- > and `Overlay`/`LevelBar`/`Expander`/`Divider`/`Highlight` (Tier 20) also
24
- > shipped. Component ports from
23
+ > and `Overlay`/`LevelBar`/`Expander`/`Divider`/`Highlight`/`FileTypeIcon`/
24
+ > `SegmentedBar` (Tier 20), `Chip` (Tier 7), and `IconButton`/`Drawer`
25
+ > (Tier 8/Tier 20) also shipped. Component ports from
25
26
  > `@gnome-ui/react` continue tier by tier — see this package's own
26
27
  > [ROADMAP.md](./ROADMAP.md) for full
27
28
  > per-tier status against all 130 `@gnome-ui/react` components, and the
@@ -1291,6 +1292,144 @@ dropped, not a behavior gap. `prefers-contrast: more`'s solid-background/
1291
1292
  white-text swap ports via `useResolvedContrast()`, the same hook `Button`
1292
1293
  already uses for its own high-contrast branching.
1293
1294
 
1295
+ ### FileTypeIcon
1296
+
1297
+ ```tsx
1298
+ import { FileTypeIcon } from '@gnome-ui/react-native';
1299
+
1300
+ <FileTypeIcon name="report.pdf" />
1301
+ <FileTypeIcon mimeType="image/png" />
1302
+ <FileTypeIcon name="cover.jpg" thumbnail={thumbnailUrl} />
1303
+ <FileTypeIcon isFolder />
1304
+ ```
1305
+
1306
+ Small icon — optionally a thumbnail — resolved from a file's MIME type or
1307
+ name extension. Useful for file-manager-style listings. Mirrors
1308
+ `@gnome-ui/react`'s `FileTypeIcon`, falling back to the generic file icon
1309
+ (freedesktop's `text-x-generic`) when the type can't be resolved.
1310
+
1311
+ `fileType.ts`'s category-resolution logic (MIME type / extension → one of
1312
+ 13 categories, plus the freedesktop icon and generated label per category)
1313
+ is pure, DOM-free TS — duplicated verbatim from `@gnome-ui/react` rather
1314
+ than imported cross-package, the same `Icon.tsx` precedent already
1315
+ established for logic that isn't worth a shared package for one file's
1316
+ worth of code. `role="img"` + `accessibilityLabel` ports 1:1, and the
1317
+ thumbnail reuses `Avatar`'s own `Image`/`resizeMode="cover"` recipe, sized
1318
+ from `Icon`'s own size map so swapping between the resolved icon and a
1319
+ thumbnail never shifts layout.
1320
+
1321
+ ### Chip
1322
+
1323
+ ```tsx
1324
+ import { Chip } from '@gnome-ui/react-native';
1325
+
1326
+ <Chip label="React" />
1327
+ <Chip label="React" onRemove={() => {}} />
1328
+ <Chip label="React" selectable selected={selected} onToggle={() => setSelected((s) => !s)} />
1329
+ ```
1330
+
1331
+ Compact pill-shaped label for tags, filters, and selection states. Mirrors
1332
+ `@gnome-ui/react`'s `Chip`. Three usage modes: **static** (just a visual
1333
+ label), **removable** (add `onRemove` for a × button), and **selectable**
1334
+ (add `selectable` + `selected` + `onToggle` for toggle behavior — same
1335
+ `isInteractive = selectable && !onRemove` precedence as the web version,
1336
+ so passing both renders the remove button, not a toggle). Pair with
1337
+ `WrapBox` for multi-chip layouts.
1338
+
1339
+ The selected background/border tint
1340
+ (`color-mix(in srgb, accent 15%/50%, transparent)`) resolves to a literal
1341
+ 8-digit `#RRGGBBAA` hex, the same `Highlight` precedent. The web version's
1342
+ `:hover`/`:active` background transitions collapse into a single
1343
+ pressed-state overlay tinted by `theme.activeOverlay` (the same
1344
+ `ActionRow`/`Card` recipe), since touch has no hover. The leading icon and
1345
+ remove (×) icon stay in the default foreground color rather than tracking
1346
+ the selected accent text (`color: inherit` on the web) — RN's `Icon` has
1347
+ no `currentColor` equivalent and only accepts a fixed named-swatch
1348
+ palette, none of which tracks the app's configurable accent color, so
1349
+ this is a decorative nicety dropped, not a behavior gap.
1350
+ `accessibilityRole="checkbox"` on the selectable form ports 1:1, the same
1351
+ `Checkbox` precedent.
1352
+
1353
+ ### SegmentedBar
1354
+
1355
+ ```tsx
1356
+ import { SegmentedBar } from '@gnome-ui/react-native';
1357
+
1358
+ <SegmentedBar
1359
+ values={[
1360
+ { label: 'TypeScript', value: 60, color: '#3178c6' },
1361
+ { label: 'JavaScript', value: 30, color: '#f7df1e' },
1362
+ { label: 'CSS', value: 10, color: '#563d7c' },
1363
+ ]}
1364
+ />
1365
+ ```
1366
+
1367
+ Horizontal bar split into proportional segments, one per category. Mirrors
1368
+ `@gnome-ui/react`'s `SegmentedBar`. Typical use case: repository language
1369
+ distribution. Values are normalized proportionally when they don't sum to
1370
+ 100.
1371
+
1372
+ The web version's hover interaction (dim every segment but the one under
1373
+ the pointer, brighten that one via `filter: brightness()`) is rebuilt for
1374
+ touch rather than dropped: each segment is a `Pressable`, and touching one
1375
+ dims the rest immediately via `onPressIn`/`onPressOut` — deliberately not
1376
+ gated behind `Tooltip`'s own long-press delay, since this feedback is the
1377
+ RN analog of a `Pressable`'s own instant `pressed` state, not the "peek"
1378
+ affordance a tooltip reveal is. Each segment is also wrapped in `Tooltip`
1379
+ (`placement="top"`, `delay={200}`, ported 1:1) for the label/percentage
1380
+ readout — `Tooltip` clones its own handlers onto the child while still
1381
+ calling the child's original ones, so the dim/highlight and the tooltip
1382
+ compose cleanly on the same `Pressable`. `filter: brightness(1.15)` on the
1383
+ actively-touched segment has no RN equivalent — dropped as a decorative
1384
+ nicety, since the touched segment already reads as highlighted by
1385
+ contrast once every other segment dims to 35% opacity.
1386
+
1387
+ ### IconButton
1388
+
1389
+ ```tsx
1390
+ import { IconButton } from '@gnome-ui/react-native';
1391
+ import { Search } from '@gnome-ui/icons';
1392
+
1393
+ <IconButton icon={Search} label="Search" />
1394
+ <IconButton icon={Search} label="Search" tooltip="Search files" />
1395
+ ```
1396
+
1397
+ Icon-only action button composed from `Button`, `Icon`, and optionally
1398
+ `Tooltip` — mirrors `@gnome-ui/react`'s `IconButton`, itself already just a
1399
+ thin composition of those same three pieces. `label` is required since the
1400
+ button has no visible text. Built as a genuine prerequisite for `Drawer`'s
1401
+ `rail`, not scope creep — every piece it composes already existed.
1402
+
1403
+ ### Drawer
1404
+
1405
+ ```tsx
1406
+ import { Drawer } from '@gnome-ui/react-native';
1407
+
1408
+ <Drawer open={open} title="Details" onClose={() => setOpen(false)}>
1409
+ <Text>Drawer content can be any React node passed as children.</Text>
1410
+ </Drawer>
1411
+ ```
1412
+
1413
+ Slide-in panel for supplementary content, anchored to the left or right
1414
+ edge. Mirrors `@gnome-ui/react`'s `Drawer`. Supports a `rail` (an
1415
+ `IconButton` strip on the drawer's inner edge for switching panels without
1416
+ closing it) and nested-drawer width auto-scaling via context — a `Drawer`
1417
+ opened from within another drawer's content automatically renders
1418
+ narrower (`0.85^depth`, floored at 240px), so stacked drawers read as a
1419
+ drill-in hierarchy.
1420
+
1421
+ Floats with a margin on every side and all four corners rounded, matching
1422
+ `@gnome-ui/react`'s own recent CSS update to the same look — positioned
1423
+ within the padded backdrop via `justifyContent` rather than the web CSS's
1424
+ `margin: auto` on the drawer itself, since RN auto-margin support was
1425
+ unverified for this Yoga version (confirmed correct with an on-device
1426
+ debug-color check before trusting it; `BottomSheet` already proves the
1427
+ same `justifyContent: 'flex-end'` mechanism on its own vertical axis).
1428
+ Unlike `BottomSheet`, there's no drag-to-dismiss — the web source defines
1429
+ no exit keyframes at all, so this follows `Dialog`'s simpler animation
1430
+ shape instead. `backdrop-filter: blur(4px)` has no port (no native blur
1431
+ dependency in this package).
1432
+
1294
1433
  ## Installation
1295
1434
 
1296
1435
  ```bash
@@ -0,0 +1,63 @@
1
+ import { IconDefinition } from '@gnome-ui/icons';
2
+ import { StyleProp, ViewStyle } from 'react-native';
3
+ export interface ChipProps {
4
+ /** Text label displayed inside the chip. */
5
+ label: string;
6
+ /** Leading icon from `@gnome-ui/icons`. */
7
+ icon?: IconDefinition;
8
+ /**
9
+ * When provided, renders a remove (×) button and calls this handler.
10
+ * The chip root becomes a plain `View`; only the remove button is
11
+ * interactive.
12
+ */
13
+ onRemove?: () => void;
14
+ /**
15
+ * When true the chip renders as a toggle button.
16
+ * Use `selected` + `onToggle` to control its state.
17
+ */
18
+ selectable?: boolean;
19
+ /** Active/selected state. Only relevant when `selectable` is true. */
20
+ selected?: boolean;
21
+ /**
22
+ * Called when a selectable chip is pressed.
23
+ * Only relevant when `selectable` is true.
24
+ */
25
+ onToggle?: () => void;
26
+ /** Disabled state — applies to both selectable chips and the remove button. */
27
+ disabled?: boolean;
28
+ style?: StyleProp<ViewStyle>;
29
+ testID?: string;
30
+ }
31
+ /**
32
+ * Compact pill-shaped label for tags, filters, and selection states.
33
+ * Mirrors `@gnome-ui/react`'s `Chip`.
34
+ *
35
+ * Three usage modes:
36
+ * - **Static** — just a visual label (no `onRemove`, no `selectable`).
37
+ * - **Removable** — add `onRemove` to show a × button.
38
+ * - **Selectable** — add `selectable` + `selected` + `onToggle` for toggle
39
+ * behavior. Same `isInteractive = selectable && !onRemove` precedence as
40
+ * the web version: passing both `selectable` and `onRemove` renders the
41
+ * remove button, not a toggle.
42
+ *
43
+ * Pair with `WrapBox` for multi-chip layouts.
44
+ *
45
+ * Rebuilt with `Pressable`/`View`/`Text` rather than ported from
46
+ * `@gnome-ui/react`'s `<button>`/`<span>`: the selected background/border
47
+ * tint (`color-mix(in srgb, accent 15%/50%, transparent)`) has no RN
48
+ * equivalent, resolved to a literal 8-digit `#RRGGBBAA` hex instead — the
49
+ * same `Highlight` precedent, since `accentBgColor` is always a plain
50
+ * 6-digit hex. The `:hover`/`:active` background transitions collapse into
51
+ * a single pressed-state overlay tinted by `theme.activeOverlay` (the same
52
+ * `ActionRow`/`Card` recipe), since touch has no hover. The leading icon
53
+ * and remove (×) icon don't recolor to match the selected accent text
54
+ * (`color: inherit` on the web) — RN's `Icon` has no `currentColor`
55
+ * equivalent and only accepts a fixed named-swatch palette, none of which
56
+ * tracks the app's configurable accent color, so both icons stay in the
57
+ * default foreground color; a decorative nicety dropped, not a behavior
58
+ * gap. `accessibilityRole="checkbox"` on the selectable form ports 1:1
59
+ * (the same `Checkbox` precedent).
60
+ *
61
+ * @see https://developer.gnome.org/hig/patterns/selection.html
62
+ */
63
+ export declare const Chip: ({ label, icon, onRemove, selectable, selected, onToggle, disabled, style, testID, }: ChipProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export type { ChipProps } from './Chip';
2
+ export { Chip } from './Chip';
@@ -0,0 +1,117 @@
1
+ import { IconDefinition } from '@gnome-ui/icons';
2
+ import { ReactNode } from 'react';
3
+ import { StyleProp, ViewStyle } from 'react-native';
4
+ export type DrawerSide = 'left' | 'right';
5
+ export type DrawerSize = 'classic' | 'wide';
6
+ export interface DrawerRailItem {
7
+ /** Stable unique identifier. */
8
+ id: string;
9
+ /** Icon shown for this rail entry. */
10
+ icon: IconDefinition;
11
+ /** Accessible name, also used as the tooltip. */
12
+ label: string;
13
+ /** Whether this entry represents the currently visible drawer/panel. */
14
+ active?: boolean;
15
+ disabled?: boolean;
16
+ onPress: () => void;
17
+ }
18
+ export interface DrawerProps {
19
+ /** Whether the drawer is visible. */
20
+ open: boolean;
21
+ /** Edge that the drawer slides in from. Defaults to `"right"`. */
22
+ side?: DrawerSide;
23
+ /** Preset drawer width. Defaults to `"classic"`. */
24
+ size?: DrawerSize;
25
+ /** Optional drawer heading. */
26
+ title?: ReactNode;
27
+ /** Drawer content when a prop is preferred over `children`. */
28
+ content?: ReactNode;
29
+ /** Drawer content. Used when `content` is not provided. */
30
+ children?: ReactNode;
31
+ /** Called when the user dismisses the drawer with the Android back button or the backdrop. */
32
+ onClose?: () => void;
33
+ /** Whether pressing the backdrop closes the drawer. Defaults to `true`. */
34
+ closeOnBackdrop?: boolean;
35
+ /**
36
+ * Narrow icon rail rendered on the drawer's inner edge (the edge facing
37
+ * the backdrop), for switching between related drawers or panels without
38
+ * closing the drawer. Purely presentational — pressing an entry only
39
+ * calls its `onPress`; the caller decides what happens (swap `content`,
40
+ * open a different drawer, etc).
41
+ */
42
+ rail?: DrawerRailItem[];
43
+ style?: StyleProp<ViewStyle>;
44
+ /** Forwarded to the backdrop — useful for testing. */
45
+ testID?: string;
46
+ }
47
+ /**
48
+ * Slide-in panel for supplementary content, anchored to the left or right
49
+ * edge. Mirrors `@gnome-ui/react`'s `Drawer`.
50
+ *
51
+ * Rebuilt with `View`/`Modal` rather than ported from the web version's
52
+ * `createPortal(document.body)` + manual focus trap + Escape listener:
53
+ * `Modal` already floats above everything with no portal target needed,
54
+ * and `BackHandler`'s `hardwareBackPress` is the Android analog of the
55
+ * Escape listener (the same `Dialog`/`BottomSheet` precedent). Focus
56
+ * trapping has no port — no DOM `Tab`/`document.activeElement` concept in
57
+ * RN's touch-first model.
58
+ *
59
+ * **Floats with a margin on every side, all four corners rounded** — the
60
+ * backdrop `Pressable` carries `padding: theme.space3` (matching the
61
+ * `@gnome-ui/react` source's own recent update to the same floating-card
62
+ * look, not a divergence), and the drawer itself gets a uniform
63
+ * `borderRadius` instead of the flat-edge-on-the-anchored-side look a
64
+ * flush-to-the-screen-edge panel would need. Positioning within that
65
+ * padded backdrop uses `justifyContent: 'flex-end'`/`'flex-start'` on the
66
+ * backdrop (not the web CSS's `margin-left/right: auto` on the drawer
67
+ * itself) — confirmed empirically (a throwaway build with saturated debug
68
+ * colors standing in for the real theme colors, screenshotted on-device)
69
+ * that `justifyContent` renders correctly while auto-margins were, at
70
+ * best, unverified for this RN/Yoga version; `BottomSheet` already proves
71
+ * the same `justifyContent: 'flex-end'` mechanism works on this exact
72
+ * setup, just on the vertical axis instead of horizontal. On a phone-width
73
+ * screen the `classic`/`wide` presets (420/640, sized for wider viewports)
74
+ * get capped to fill essentially the entire available width after the
75
+ * margin either way, so the anchored side becomes visually obvious mainly
76
+ * on tablets — the same responsive behavior the web version would show at
77
+ * an equally narrow browser width, not an RN-specific gap.
78
+ *
79
+ * **No drag-to-dismiss, unlike `BottomSheet`**: the web source only
80
+ * defines entrance keyframes for both the backdrop and the panel, so this
81
+ * follows `Dialog`'s simpler shape (a single `progress` `Animated.Value`
82
+ * replayed via `useEffect` keyed on `open`, no separate exit animation or
83
+ * lagging `visible` state) rather than `BottomSheet`'s
84
+ * `PanResponder`-plus-timed-exit machinery.
85
+ *
86
+ * **The slide distance needs no `onLayout` measurement**, unlike
87
+ * `BottomSheet`'s content-driven height: the drawer's width is a value
88
+ * this component already computes in JS (`size`'s preset, scaled down by
89
+ * `DrawerDepthContext` depth, capped by the available space after the
90
+ * backdrop's margin) — RN's `transform` has no percentage-of-self units
91
+ * (the same `BottomSheet`/`Avatar`/`Slider` pitfall), but since the exact
92
+ * pixel width is already known synchronously, `translateX` can animate
93
+ * from that known offset to `0` immediately, with no first-frame
94
+ * imprecision to accept.
95
+ *
96
+ * **`DrawerDepthContext` (nested-drawer width auto-scaling) ports 1:1** —
97
+ * pure React Context state, no DOM dependency at all. A `Drawer` opened
98
+ * from within another drawer's `content`/`children` is detected via
99
+ * context and scales its own preset width down (`0.85^depth`, floored at
100
+ * `DRAWER_MIN_WIDTH`) so stacked drawers read as a drill-in hierarchy
101
+ * instead of identical overlapping panels.
102
+ *
103
+ * **`rail` reuses the newly-added `IconButton`** (itself just `Button` +
104
+ * `Icon` + optional `Tooltip`, the same composition `@gnome-ui/react`'s own
105
+ * `IconButton` already is) — `aria-pressed` becomes
106
+ * `accessibilityState={{ selected: item.active }}`, the closest RN
107
+ * equivalent for a toggleable icon button with no dedicated visual
108
+ * "pressed" style on either platform's source.
109
+ *
110
+ * `backdrop-filter: blur(4px)` has no port — no native blur view
111
+ * dependency exists in this package, the same gap already dropped from
112
+ * `Sidebar`'s blurred `variant`/`BottomSheet`'s backdrop. `role="dialog"` +
113
+ * `accessibilityViewIsModal` port 1:1 from `Dialog`'s own precedent.
114
+ *
115
+ * @see https://developer.gnome.org/hig/patterns/containers.html
116
+ */
117
+ export declare const Drawer: ({ open, side, size, title, content, children, onClose, closeOnBackdrop, rail, style, testID, }: DrawerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export type { DrawerProps, DrawerRailItem, DrawerSide, DrawerSize } from './Drawer';
2
+ export { Drawer } from './Drawer';
@@ -0,0 +1,45 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ import { IconSize } from '../Icon';
3
+ export interface FileTypeIconProps {
4
+ /** File name (e.g. `"report.pdf"`) — resolves the icon from its extension. */
5
+ name?: string;
6
+ /**
7
+ * MIME type (e.g. `"application/pdf"`, `"inode/directory"`).
8
+ * Takes precedence over `name` when both are provided.
9
+ */
10
+ mimeType?: string;
11
+ /** Renders the folder icon regardless of `name`/`mimeType`. */
12
+ isFolder?: boolean;
13
+ /** Thumbnail image URL. When provided, renders the image instead of the resolved icon. */
14
+ thumbnail?: string;
15
+ /** Accessible label. Defaults to a generated description (e.g. `"PDF document"`). */
16
+ label?: string;
17
+ /** Icon size. Defaults to `"md"`. */
18
+ size?: IconSize;
19
+ style?: StyleProp<ViewStyle>;
20
+ testID?: string;
21
+ }
22
+ /**
23
+ * Small icon — optionally a thumbnail — resolved from a file's MIME type
24
+ * or name extension. Useful for file-manager-style listings. Mirrors
25
+ * `@gnome-ui/react`'s `FileTypeIcon`.
26
+ *
27
+ * Falls back to the generic file icon (mirrors freedesktop's
28
+ * `text-x-generic`) when the type can't be resolved.
29
+ *
30
+ * `fileType.ts`'s category-resolution logic (MIME type / extension → one of
31
+ * 13 categories, plus the freedesktop icon and generated label per
32
+ * category) is pure, DOM-free TS — duplicated verbatim from
33
+ * `@gnome-ui/react` rather than imported cross-package, the same
34
+ * `isIconDefinition`/`Icon.tsx` precedent already established for
35
+ * DOM-independent logic that still isn't worth a shared package for one
36
+ * function's worth of code.
37
+ *
38
+ * `role="img"` + `accessibilityLabel` ports 1:1 (the same `Avatar`/
39
+ * `LevelBar` precedent for RN's newer web-aligned `Role` union). The
40
+ * thumbnail reuses `Avatar`'s own `Image`/`resizeMode="cover"` recipe,
41
+ * sized from `Icon`'s own `ICON_SIZE_MAP` so swapping between the resolved
42
+ * icon and a thumbnail never shifts layout — the same reasoning the web
43
+ * version's `.sm`/`.md`/`.lg` classes document.
44
+ */
45
+ export declare const FileTypeIcon: ({ name, mimeType, isFolder, thumbnail, label, size, style, testID, }: FileTypeIconProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { IconDefinition } from '@gnome-ui/icons';
2
+ export type FileTypeCategory = 'folder' | 'image' | 'audio' | 'video' | 'text' | 'pdf' | 'archive' | 'document' | 'spreadsheet' | 'presentation' | 'font' | 'executable' | 'unknown';
3
+ /** Resolves a file-type category from a MIME type (e.g. `"image/png"`). */
4
+ export declare function categoryFromMimeType(mimeType: string): FileTypeCategory | null;
5
+ /** Resolves a file-type category from a file name's extension (e.g. `"report.pdf"`). */
6
+ export declare function categoryFromName(name: string): FileTypeCategory | null;
7
+ export declare function getFileTypeIcon(category: FileTypeCategory): IconDefinition;
8
+ export declare function getFileTypeLabel(category: FileTypeCategory): string;
@@ -0,0 +1,3 @@
1
+ export type { FileTypeIconProps } from './FileTypeIcon';
2
+ export { FileTypeIcon } from './FileTypeIcon';
3
+ export type { FileTypeCategory } from './fileType';
@@ -0,0 +1,34 @@
1
+ import { IconDefinition } from '@gnome-ui/icons';
2
+ import { View } from 'react-native';
3
+ import { ButtonProps, ButtonSize, ButtonVariant } from '../Button';
4
+ import { IconSize } from '../Icon';
5
+ import { TooltipPlacement } from '../Tooltip';
6
+ export type IconButtonVariant = ButtonVariant | 'osd';
7
+ export type IconButtonSize = ButtonSize;
8
+ export interface IconButtonProps extends Omit<ButtonProps, 'accessibilityLabel' | 'children' | 'leadingIcon' | 'osd' | 'shape' | 'trailingIcon' | 'variant'> {
9
+ /** Icon definition imported from `@gnome-ui/icons`. */
10
+ icon: IconDefinition;
11
+ /** Accessible name for the icon-only button. */
12
+ label: string;
13
+ /** Visual style of the button. Use `"osd"` for media overlay controls. */
14
+ variant?: IconButtonVariant;
15
+ /** Size of the button. */
16
+ size?: IconButtonSize;
17
+ /** Override the rendered icon size. Defaults to a size matched to `size`. */
18
+ iconSize?: IconSize;
19
+ /** Optional tooltip label shown on long-press/hover/focus. */
20
+ tooltip?: string;
21
+ /** Preferred tooltip placement. */
22
+ tooltipPlacement?: TooltipPlacement;
23
+ /** Tooltip delay in milliseconds. */
24
+ tooltipDelay?: number;
25
+ }
26
+ /**
27
+ * Icon-only action button composed from `Button`, `Icon`, and optionally
28
+ * `Tooltip` — mirrors `@gnome-ui/react`'s `IconButton`, itself already just
29
+ * a thin composition of those same three pieces (its own JSDoc example
30
+ * shows the identical `<Tooltip><Button><Icon /></Button></Tooltip>`
31
+ * nesting `IconButton` here just formalizes into a named, reusable export).
32
+ * `label` is required since the button has no visible text.
33
+ */
34
+ export declare const IconButton: import('react').ForwardRefExoticComponent<IconButtonProps & import('react').RefAttributes<View>>;
@@ -0,0 +1,2 @@
1
+ export type { IconButtonProps, IconButtonSize, IconButtonVariant } from './IconButton';
2
+ export { IconButton } from './IconButton';
@@ -0,0 +1,64 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ export interface SegmentedBarSegment {
3
+ /** Category name shown in the tooltip. */
4
+ label: string;
5
+ /**
6
+ * Percentage value 0–100.
7
+ * The sum of all segments should equal 100.
8
+ * If it does not, values are redistributed proportionally.
9
+ */
10
+ value: number;
11
+ /**
12
+ * Color for this segment.
13
+ * When omitted, a cycling palette of GNOME design tokens is used.
14
+ */
15
+ color?: string;
16
+ }
17
+ export interface SegmentedBarProps {
18
+ /** Segments to display. Each segment contributes its share of the full bar width. */
19
+ values: SegmentedBarSegment[];
20
+ /**
21
+ * Accessible label for the bar as a whole.
22
+ * Auto-generated from `values` when omitted (e.g. "TypeScript 60%, JavaScript 30%").
23
+ */
24
+ accessibilityLabel?: string;
25
+ style?: StyleProp<ViewStyle>;
26
+ testID?: string;
27
+ }
28
+ /**
29
+ * Horizontal bar split into proportional segments, one per category.
30
+ * Mirrors `@gnome-ui/react`'s `SegmentedBar`. Typical use case: repository
31
+ * language distribution.
32
+ *
33
+ * ```tsx
34
+ * <SegmentedBar
35
+ * values={[
36
+ * { label: 'TypeScript', value: 60, color: '#3178c6' },
37
+ * { label: 'JavaScript', value: 30, color: '#f7df1e' },
38
+ * { label: 'CSS', value: 10, color: '#563d7c' },
39
+ * ]}
40
+ * />
41
+ * ```
42
+ *
43
+ * The web version's hover interaction (dim every segment but the one under
44
+ * the pointer, brighten that one via `filter: brightness()`) is rebuilt for
45
+ * touch rather than dropped: each segment is a `Pressable`, and touching
46
+ * one dims the rest immediately via `onPressIn`/`onPressOut` — deliberately
47
+ * not gated behind `Tooltip`'s own long-press delay, since this feedback is
48
+ * the RN analog of a `Pressable`'s own instant `pressed` state, not the
49
+ * "peek" affordance a tooltip reveal is. Each segment is also wrapped in
50
+ * `Tooltip` (`label`/`placement="top"`/`delay={200}`, ported 1:1 from the
51
+ * web version's own tooltip) for the actual label/percentage readout,
52
+ * composing cleanly with the dim/highlight `onPressIn`/`onPressOut` since
53
+ * `Tooltip` clones its own handlers onto the child *and* still calls the
54
+ * child's original ones. `filter: brightness(1.15)` on the actively-touched
55
+ * segment has no RN equivalent (no `filter` support) — dropped as a
56
+ * decorative nicety, since the touched segment already reads as
57
+ * highlighted by contrast once every other segment dims to 35% opacity.
58
+ *
59
+ * `role="img"` + `accessibilityLabel` ports 1:1 from RN's newer web-aligned
60
+ * `Role` union (the same `Avatar`/`LevelBar` precedent).
61
+ *
62
+ * @see https://developer.gnome.org/hig/patterns/feedback/progress.html
63
+ */
64
+ export declare const SegmentedBar: ({ values, accessibilityLabel, style, testID }: SegmentedBarProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export type { SegmentedBarProps, SegmentedBarSegment } from './SegmentedBar';
2
+ export { SegmentedBar } from './SegmentedBar';