@gnome-ui/react-native 1.4.0 → 1.6.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.
Files changed (43) hide show
  1. package/README.md +579 -2
  2. package/dist/components/AvatarGroup/AvatarGroup.d.ts +47 -0
  3. package/dist/components/AvatarGroup/index.d.ts +2 -0
  4. package/dist/components/AvatarRotator/AvatarRotator.d.ts +65 -0
  5. package/dist/components/AvatarRotator/index.d.ts +2 -0
  6. package/dist/components/Box/Box.d.ts +87 -0
  7. package/dist/components/Box/index.d.ts +2 -0
  8. package/dist/components/Chip/Chip.d.ts +63 -0
  9. package/dist/components/Chip/index.d.ts +2 -0
  10. package/dist/components/Clamp/Clamp.d.ts +61 -0
  11. package/dist/components/Clamp/index.d.ts +2 -0
  12. package/dist/components/CoachMark/CoachMark.d.ts +92 -0
  13. package/dist/components/CoachMark/CoachMarkTour.d.ts +54 -0
  14. package/dist/components/CoachMark/coachMarkUtils.d.ts +42 -0
  15. package/dist/components/CoachMark/index.d.ts +5 -0
  16. package/dist/components/Drawer/Drawer.d.ts +117 -0
  17. package/dist/components/Drawer/index.d.ts +2 -0
  18. package/dist/components/FileTypeIcon/FileTypeIcon.d.ts +45 -0
  19. package/dist/components/FileTypeIcon/fileType.d.ts +8 -0
  20. package/dist/components/FileTypeIcon/index.d.ts +3 -0
  21. package/dist/components/IconButton/IconButton.d.ts +34 -0
  22. package/dist/components/IconButton/index.d.ts +2 -0
  23. package/dist/components/InlineViewSwitcher/InlineViewSwitcher.d.ts +93 -0
  24. package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.d.ts +25 -0
  25. package/dist/components/InlineViewSwitcher/index.d.ts +4 -0
  26. package/dist/components/InlineViewSwitcher/variants.d.ts +30 -0
  27. package/dist/components/PreferencesGroup/PreferencesGroup.d.ts +52 -0
  28. package/dist/components/PreferencesGroup/index.d.ts +2 -0
  29. package/dist/components/SegmentedBar/SegmentedBar.d.ts +64 -0
  30. package/dist/components/SegmentedBar/index.d.ts +2 -0
  31. package/dist/components/StatusPage/StatusPage.d.ts +79 -0
  32. package/dist/components/StatusPage/index.d.ts +2 -0
  33. package/dist/components/ToggleGroup/ToggleGroup.d.ts +70 -0
  34. package/dist/components/ToggleGroup/ToggleGroupItem.d.ts +49 -0
  35. package/dist/components/ToggleGroup/index.d.ts +4 -0
  36. package/dist/components/WrapBox/WrapBox.d.ts +67 -0
  37. package/dist/components/WrapBox/index.d.ts +2 -0
  38. package/dist/index.cjs +1 -1
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.ts +15 -0
  41. package/dist/index.js +2147 -577
  42. package/dist/index.js.map +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,65 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ import { AvatarColor, AvatarSize } from '../Avatar';
3
+ export interface AvatarRotatorProps {
4
+ /** Full name used for the accessible label and initials fallback. */
5
+ name?: string;
6
+ /** Image URLs to rotate through. */
7
+ avatars?: string[];
8
+ /** Accessible label. Defaults to `name`. */
9
+ alt?: string;
10
+ /** Size of the avatar. Defaults to `"md"`. */
11
+ size?: AvatarSize;
12
+ /** Fallback initials color when no avatar image is available. */
13
+ color?: AvatarColor;
14
+ /** Time between avatar changes in milliseconds. Defaults to `3000`. */
15
+ interval?: number;
16
+ /** Crossfade duration in milliseconds. Defaults to `240`. */
17
+ transitionDuration?: number;
18
+ /** Pause automatic rotation while pressed and held. Defaults to `true`. */
19
+ pauseOnPress?: boolean;
20
+ /**
21
+ * Controlled active avatar index.
22
+ * When omitted the rotator manages index state internally.
23
+ */
24
+ activeIndex?: number;
25
+ /** Initial active avatar index for uncontrolled usage. Defaults to `0`. */
26
+ defaultActiveIndex?: number;
27
+ /** Called when the active avatar changes. */
28
+ onIndexChange?: (index: number) => void;
29
+ style?: StyleProp<ViewStyle>;
30
+ testID?: string;
31
+ }
32
+ /**
33
+ * Single avatar surface that crossfades through multiple image sources.
34
+ * Mirrors `@gnome-ui/react`'s `AvatarRotator`. Keeps `Avatar` focused on
35
+ * rendering one identity, while this component owns timing, crossfade
36
+ * animation, and pause behavior.
37
+ *
38
+ * Each source renders as its own absolutely-positioned `Avatar`, layered
39
+ * via `StyleSheet.absoluteFill` and crossfaded with `Animated.timing` on
40
+ * `useNativeDriver: true` — an exact reproduction of the web version's
41
+ * stacked-`.layer`-elements-with-opacity-transition technique, just with
42
+ * `RotatorLayer` (see above) owning each layer's own `Animated.Value`
43
+ * instead of a single shared CSS custom property driving them all.
44
+ *
45
+ * **`prefers-reduced-motion` stops the rotation outright, not just the
46
+ * fade** — ported exactly: the web source's own auto-advance `useEffect`
47
+ * bails out early when reduced motion is on, the same as when paused, so
48
+ * this isn't merely an instant-swap-instead-of-crossfade case like
49
+ * `ProgressBar`'s determinate transitions.
50
+ *
51
+ * The web version's `pauseOnHover` (mouseEnter/mouseLeave, focus/blur)
52
+ * becomes `pauseOnPress` (`onPressIn`/`onPressOut`) — the same touch
53
+ * substitution `Toast`'s own press-and-hold pause already established,
54
+ * kept as a real toggleable prop here (unlike `Toast`, where the web
55
+ * source bakes the behavior in without an escape hatch).
56
+ * `usePrefersReducedMotion` (the web version's `@gnome-ui/hooks` import)
57
+ * has no bearing here — this package's own `useReducedMotion()` from
58
+ * `GnomeProvider` is the correct, already-established source for this.
59
+ *
60
+ * `role="img"` + `accessibilityLabel` ports 1:1 from RN's newer
61
+ * web-aligned `Role` union (the same `Avatar`/`AvatarGroup` precedent).
62
+ *
63
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Avatar.html
64
+ */
65
+ export declare const AvatarRotator: ({ name, avatars, alt, size, color, interval, transitionDuration, pauseOnPress, activeIndex, defaultActiveIndex, onIndexChange, style, testID, }: AvatarRotatorProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export type { AvatarRotatorProps } from './AvatarRotator';
2
+ export { AvatarRotator } from './AvatarRotator';
@@ -0,0 +1,87 @@
1
+ import { ReactNode } from 'react';
2
+ import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
3
+ /** GNOME HIG standard spacing values (matches `GtkBox` spacing tokens). */
4
+ export type BoxSpacing = 3 | 6 | 12 | 18 | 24 | 32 | 48;
5
+ /** Alias of `BoxSpacing` for use as a padding scale. */
6
+ export type BoxPadding = BoxSpacing;
7
+ export type BoxOrientation = 'horizontal' | 'vertical';
8
+ export type BoxAlign = 'start' | 'center' | 'end' | 'stretch' | 'baseline';
9
+ export type BoxJustify = 'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly';
10
+ export interface BoxProps extends Omit<ViewProps, 'style'> {
11
+ /**
12
+ * Direction children are arranged.
13
+ * `"vertical"` → `flexDirection: 'column'` (default).
14
+ * `"horizontal"` → `flexDirection: 'row'`.
15
+ */
16
+ orientation?: BoxOrientation;
17
+ /**
18
+ * Gap between children, in density-independent pixels.
19
+ * Accepts any of the GNOME HIG standard spacing values or any number.
20
+ * Defaults to `6` (the HIG "standard" inner spacing).
21
+ */
22
+ spacing?: BoxSpacing | number;
23
+ /**
24
+ * Cross-axis alignment (`alignItems`).
25
+ * Defaults to `"stretch"` for vertical, `"center"` for horizontal.
26
+ */
27
+ align?: BoxAlign;
28
+ /**
29
+ * Main-axis distribution (`justifyContent`).
30
+ * Defaults to `"start"`.
31
+ */
32
+ justify?: BoxJustify;
33
+ /** Inner padding applied to all sides, in density-independent pixels. */
34
+ padding?: BoxPadding | number;
35
+ children?: ReactNode;
36
+ style?: StyleProp<ViewStyle>;
37
+ }
38
+ /**
39
+ * Fundamental flex layout primitive — the RN equivalent of `GtkBox`, and a
40
+ * 1:1 mirror of `@gnome-ui/react`'s own `Box`.
41
+ *
42
+ * Arranges children in a single row or column with consistent spacing
43
+ * following the GNOME Human Interface Guidelines spacing scale:
44
+ *
45
+ * | Token | dp | Use |
46
+ * |-------|----|-----|
47
+ * | tight | 3 | Dense UI, icon + label pairs |
48
+ * | standard | 6 | Default inner spacing |
49
+ * | medium | 12 | Between related groups |
50
+ * | large | 18 | Between loosely related sections |
51
+ * | section | 24 | Page-level section gaps |
52
+ * | loose | 32 | Large content separation |
53
+ * | jumbo | 48 | Hero / splash spacing |
54
+ *
55
+ * `BoxSpacing` keeps the web package's exact seven values rather than being
56
+ * remapped onto this package's own `theme.space1`–`space6` scale — the two
57
+ * overlap at 6/12/18/24/48 but not at 3 or 32/36, and `BoxSpacing` is a
58
+ * published type consumers may already be importing, so it ports verbatim.
59
+ *
60
+ * Two things the web version accepts don't survive the platform: `spacing`
61
+ * and `padding` are numbers only (RN's `gap`/`padding` take dp, not CSS
62
+ * strings like `"1rem"`), and `align`/`justify` — which the web passes
63
+ * straight through to CSS — are mapped from their bare `start`/`end`
64
+ * keywords onto Yoga's `flex-start`/`flex-end`. The prop values stay the
65
+ * web ones so the API reads identically across both packages; only the
66
+ * internal translation differs.
67
+ *
68
+ * `display: 'flex'` has no port and needs none — every RN `View` is already
69
+ * a flex container.
70
+ *
71
+ * @example
72
+ * // Vertical section (heading + content)
73
+ * <Box spacing={12}>
74
+ * <Text variant="caption-heading" color="dim">Devices</Text>
75
+ * <BoxedList>…</BoxedList>
76
+ * </Box>
77
+ *
78
+ * @example
79
+ * // Horizontal icon + label
80
+ * <Box orientation="horizontal" spacing={6} align="center">
81
+ * <Icon icon={Folder} />
82
+ * <Text>Documents</Text>
83
+ * </Box>
84
+ *
85
+ * @see https://developer.gnome.org/hig/guidelines/spacing.html
86
+ */
87
+ export declare const Box: import('react').ForwardRefExoticComponent<BoxProps & import('react').RefAttributes<View>>;
@@ -0,0 +1,2 @@
1
+ export type { BoxAlign, BoxJustify, BoxOrientation, BoxPadding, BoxProps, BoxSpacing, } from './Box';
2
+ export { Box } from './Box';
@@ -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,61 @@
1
+ import { ReactNode } from 'react';
2
+ import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
3
+ export interface ClampProps extends Omit<ViewProps, 'style'> {
4
+ /**
5
+ * Maximum content width in density-independent pixels.
6
+ * The container shrinks freely below this value.
7
+ * Defaults to `600` — the Adwaita recommended narrow-content width.
8
+ */
9
+ maximumSize?: number;
10
+ /**
11
+ * Fractional width (`0`–`1`) of the available space to use while that
12
+ * space is narrower than `maximumSize` — useful for keeping a
13
+ * comfortable margin on medium-width screens. Defaults to `1` (always
14
+ * fill the width).
15
+ */
16
+ tighteningThreshold?: number;
17
+ children?: ReactNode;
18
+ style?: StyleProp<ViewStyle>;
19
+ }
20
+ /**
21
+ * Constrains its children to a maximum width while letting them shrink
22
+ * freely, mirroring the Adwaita `AdwClamp` widget and `@gnome-ui/react`'s
23
+ * own `Clamp`.
24
+ *
25
+ * Use it on settings pages and forms so content never becomes too wide to
26
+ * read comfortably on a tablet or a landscape phone, while still filling
27
+ * the available width on a narrow one.
28
+ *
29
+ * The web version's `margin-inline: auto` centering becomes
30
+ * `alignSelf: 'center'` here rather than `marginHorizontal: 'auto'` —
31
+ * RN auto-margin support was left unverified for this Yoga version when
32
+ * `Drawer` needed the same trick, so this follows `Drawer`'s resolution of
33
+ * using flex alignment instead. The one consequence is that `Clamp`
34
+ * expects a column-direction parent (RN's default): `alignSelf` acts on
35
+ * the cross axis, so inside a `flexDirection: 'row'` parent it would
36
+ * centre vertically instead. Wrap it in a plain `View` there.
37
+ *
38
+ * `tighteningThreshold` is a real percentage width here, unlike in
39
+ * `@gnome-ui/react` where the prop is declared and documented but never
40
+ * reaches the DOM — implementing it exactly as that package documents it
41
+ * (a fraction of the available width, still capped by `maximumSize`)
42
+ * costs nothing on RN and avoids shipping a dead prop.
43
+ *
44
+ * Adds no padding of its own — wrap the content in its own padded
45
+ * container as needed.
46
+ *
47
+ * @example
48
+ * // Settings page — content never wider than 600 dp
49
+ * <Clamp>
50
+ * <BoxedList>…</BoxedList>
51
+ * </Clamp>
52
+ *
53
+ * @example
54
+ * // Leave a 10% margin while the screen is narrower than 480 dp
55
+ * <Clamp maximumSize={480} tighteningThreshold={0.9}>
56
+ * <Text>…</Text>
57
+ * </Clamp>
58
+ *
59
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Clamp.html
60
+ */
61
+ export declare const Clamp: import('react').ForwardRefExoticComponent<ClampProps & import('react').RefAttributes<View>>;
@@ -0,0 +1,2 @@
1
+ export type { ClampProps } from './Clamp';
2
+ export { Clamp } from './Clamp';
@@ -0,0 +1,92 @@
1
+ import { ReactNode, RefObject } from 'react';
2
+ import { StyleProp, ViewStyle, View } from 'react-native';
3
+ import { CoachMarkPlacement } from './coachMarkUtils';
4
+ export interface CoachMarkAction {
5
+ label: string;
6
+ onPress: () => void;
7
+ }
8
+ export interface CoachMarkProps {
9
+ /** Whether the coach mark is shown. */
10
+ open: boolean;
11
+ /** The element to highlight and anchor to. */
12
+ targetRef: RefObject<View | null>;
13
+ /** Heading text. */
14
+ title?: ReactNode;
15
+ /** Body copy explaining the highlighted element. */
16
+ description?: ReactNode;
17
+ /** Preferred side of the target for the bubble. Flips to stay on-screen. Defaults to `'bottom'`. */
18
+ placement?: CoachMarkPlacement;
19
+ /** Dim the rest of the screen and cut a spotlight around the target. Defaults to `true`. */
20
+ spotlight?: boolean;
21
+ /** Extra px around the target inside the spotlight cutout. Defaults to `8`. */
22
+ spotlightPadding?: number;
23
+ /** Close when the dimmed backdrop is pressed. Defaults to `false` (guided). */
24
+ dismissOnBackdrop?: boolean;
25
+ /** 1-based index of this step within a tour, for the "X of N" counter. */
26
+ step?: number;
27
+ /** Total number of steps in the tour. */
28
+ stepCount?: number;
29
+ /** Primary (suggested) action, e.g. Next / Got it. */
30
+ primaryAction?: CoachMarkAction;
31
+ /** Secondary (flat) action, e.g. Back. */
32
+ secondaryAction?: CoachMarkAction;
33
+ /** Called when the Android back button is pressed, or the backdrop is dismissed. */
34
+ onDismiss?: () => void;
35
+ style?: StyleProp<ViewStyle>;
36
+ testID?: string;
37
+ }
38
+ /**
39
+ * A single onboarding coach mark: it spotlights a target element and
40
+ * anchors a callout bubble (title, description, step counter, actions)
41
+ * beside it, guiding a user to one feature. Compose several with
42
+ * `CoachMarkTour`, or drive one directly with `open`. Mirrors
43
+ * `@gnome-ui/react`'s `CoachMark` — not a GNOME HIG widget, a pragmatic
44
+ * feature-discovery pattern.
45
+ *
46
+ * Rebuilt on RN's own `Modal` rather than the web version's DOM `Portal` —
47
+ * no `container` prop, the same `Overlay`/`Drawer` precedent for "no RN
48
+ * portal-target concept." Positions with the same two-pass viewport-aware
49
+ * flip as the web version (`coachMarkUtils.ts`, duplicated verbatim — pure
50
+ * math, no DOM), resolved from `targetRef.current?.measureInWindow(...)`
51
+ * and the bubble's own `onLayout` size, combined once both arrive — the
52
+ * same "resolve two independent async things, then combine" shape
53
+ * `Tooltip`/`Popover`/`Dropdown` already established. No focus trap (no
54
+ * DOM `Tab` concept in RN) and no scroll/resize re-positioning (RN has no
55
+ * global scroll event, the same `Tooltip` precedent for a transient
56
+ * floating element).
57
+ *
58
+ * **The spotlight cutout has no CSS `box-shadow: 0 0 0 100vmax` port** —
59
+ * that trick paints an opaque scrim everywhere *except* inside a rounded
60
+ * rect by using a huge spread shadow, which RN's `shadow*` props (real OS
61
+ * shadows, not a scrim generator) can't reproduce. Rebuilt as four plain
62
+ * `View` bands (top/bottom/left/right of the padded target rect) filling
63
+ * the screen minus a rectangular hole, plus a separate rounded
64
+ * `accentColor`-bordered ring `View` drawn on top at the target rect —
65
+ * visually equivalent (dims everything but the target, with an accent
66
+ * ring around it), just assembled from ordinary rects instead of one
67
+ * masked shape. The whole overlay (bands + ring) sits inside a single
68
+ * full-screen `Pressable`, so — matching the web version exactly — a tap
69
+ * anywhere within it (including visually "in the hole," since the web
70
+ * version's backdrop is one full-bleed element with the spotlight only
71
+ * painted on top, `pointer-events: none`) triggers `dismissOnBackdrop`,
72
+ * never the real content underneath.
73
+ *
74
+ * **`dismissOnBackdrop` has no effect when `spotlight` is `false`** —
75
+ * ported faithfully, not fixed: the web source only renders a backdrop
76
+ * element at all when `spotlight` is true, so with `spotlight={false}`
77
+ * there is nothing to press to dismiss via backdrop either way, on both
78
+ * platforms.
79
+ *
80
+ * The arrow reuses `Popover`/`Tooltip`'s transparent-border-triangle trick
81
+ * rather than the web CSS's rotated-45°-square, the same established RN
82
+ * substitution for every floating-bubble arrow in this package — offset
83
+ * along the bubble's edge by `arrowOffset` (from `computeBubblePosition`,
84
+ * unlike `Tooltip`/`Popover`'s simpler always-centered arrow).
85
+ *
86
+ * `role="dialog"` + `accessibilityViewIsModal` port 1:1 from `Dialog`'s
87
+ * own precedent. `BackHandler`'s `hardwareBackPress` is the Android analog
88
+ * of the web version's Escape listener.
89
+ *
90
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Window.html
91
+ */
92
+ export declare const CoachMark: ({ open, targetRef, title, description, placement, spotlight, spotlightPadding, dismissOnBackdrop, step, stepCount, primaryAction, secondaryAction, onDismiss, style, testID, }: CoachMarkProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,54 @@
1
+ import { ReactNode, RefObject } from 'react';
2
+ import { View } from 'react-native';
3
+ import { CoachMarkPlacement } from './coachMarkUtils';
4
+ export interface CoachMarkStep {
5
+ /** The element this step highlights. */
6
+ targetRef: RefObject<View | null>;
7
+ /** Heading for the step. */
8
+ title?: ReactNode;
9
+ /** Body copy for the step. */
10
+ description?: ReactNode;
11
+ /** Preferred bubble side for this step. Defaults to the tour's placement. */
12
+ placement?: CoachMarkPlacement;
13
+ }
14
+ export interface CoachMarkTourProps {
15
+ /** Ordered steps of the tour. */
16
+ steps: CoachMarkStep[];
17
+ /** Whether the tour is running. */
18
+ open: boolean;
19
+ /** Step to start on when the tour opens. Defaults to `0`. */
20
+ startIndex?: number;
21
+ /** Called after the primary action on the final step. */
22
+ onFinish?: () => void;
23
+ /** Called when the user skips (Skip button or Android back) before finishing. */
24
+ onSkip?: () => void;
25
+ /** Called with the new index whenever the active step changes. */
26
+ onStepChange?: (index: number) => void;
27
+ /** Default preferred bubble side for steps that don't set their own. Defaults to `'bottom'`. */
28
+ placement?: CoachMarkPlacement;
29
+ /** Spotlight the target. Defaults to `true`. */
30
+ spotlight?: boolean;
31
+ /** Close the tour when the dimmed backdrop is pressed. Defaults to `false`. */
32
+ dismissOnBackdrop?: boolean;
33
+ /** Override the action-button labels (for i18n). */
34
+ labels?: Partial<{
35
+ next: string;
36
+ back: string;
37
+ skip: string;
38
+ finish: string;
39
+ }>;
40
+ testID?: string;
41
+ }
42
+ /**
43
+ * Sequential onboarding tour built from `CoachMark` steps. Renders the
44
+ * mark for the active step, wires Next/Back/Skip/Done and the "X of N"
45
+ * counter, and advances through `steps` until finished or skipped.
46
+ * Mirrors `@gnome-ui/react`'s `CoachMarkTour` verbatim — pure state
47
+ * orchestration on top of `CoachMark`, nothing platform-specific to
48
+ * change.
49
+ *
50
+ * Uncontrolled step index: the tour tracks its own position and resets to
51
+ * `startIndex` each time it opens. Drive visibility with `open`; react to
52
+ * completion with `onFinish`/`onSkip`.
53
+ */
54
+ export declare const CoachMarkTour: ({ steps, open, startIndex, onFinish, onSkip, onStepChange, placement, spotlight, dismissOnBackdrop, labels, testID, }: CoachMarkTourProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Positioning helpers for `CoachMark`. Kept pure and measurement-free so
3
+ * they can be unit-tested directly; the component feeds them real rects
4
+ * (from `measureInWindow` instead of the web version's
5
+ * `getBoundingClientRect`, but the shape is identical either way).
6
+ *
7
+ * Duplicated verbatim from `@gnome-ui/react` rather than imported
8
+ * cross-package — the same `fileType.ts`/`Icon.tsx` precedent for
9
+ * DOM-free logic that isn't worth a shared package for one file's worth
10
+ * of code.
11
+ *
12
+ * The algorithm mirrors `Popover`'s viewport-aware flip: try the preferred
13
+ * side, then its opposite, then the rest, picking the first that fits;
14
+ * clamp the cross-axis and shift the arrow when nothing fits perfectly.
15
+ */
16
+ export type CoachMarkPlacement = 'top' | 'bottom' | 'left' | 'right';
17
+ export interface Rect {
18
+ top: number;
19
+ left: number;
20
+ width: number;
21
+ height: number;
22
+ }
23
+ export interface BubblePosition {
24
+ top: number;
25
+ left: number;
26
+ placement: CoachMarkPlacement;
27
+ /** Arrow centre offset in px from the near edge of the bubble. */
28
+ arrowOffset: number;
29
+ }
30
+ /** Grow a rect outward by `pad` on every side, e.g. the spotlight cutout. */
31
+ export declare const padRect: (rect: Rect, pad: number) => Rect;
32
+ /**
33
+ * Place the callout bubble around `target`, flipping to stay inside a
34
+ * `viewport` (width × height). `bubble` is the measured bubble size.
35
+ */
36
+ export declare const computeBubblePosition: (target: Rect, bubble: {
37
+ width: number;
38
+ height: number;
39
+ }, viewport: {
40
+ width: number;
41
+ height: number;
42
+ }, preferred: CoachMarkPlacement) => BubblePosition;
@@ -0,0 +1,5 @@
1
+ export type { CoachMarkAction, CoachMarkProps } from './CoachMark';
2
+ export { CoachMark } from './CoachMark';
3
+ export type { CoachMarkStep, CoachMarkTourProps } from './CoachMarkTour';
4
+ export { CoachMarkTour } from './CoachMarkTour';
5
+ export type { CoachMarkPlacement } from './coachMarkUtils';
@@ -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;