@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 +141 -2
- package/dist/components/Chip/Chip.d.ts +63 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Drawer/Drawer.d.ts +117 -0
- package/dist/components/Drawer/index.d.ts +2 -0
- package/dist/components/FileTypeIcon/FileTypeIcon.d.ts +45 -0
- package/dist/components/FileTypeIcon/fileType.d.ts +8 -0
- package/dist/components/FileTypeIcon/index.d.ts +3 -0
- package/dist/components/IconButton/IconButton.d.ts +34 -0
- package/dist/components/IconButton/index.d.ts +2 -0
- package/dist/components/SegmentedBar/SegmentedBar.d.ts +64 -0
- package/dist/components/SegmentedBar/index.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1034 -558
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
24
|
-
>
|
|
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,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,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,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,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;
|