@gnome-ui/react-native 1.5.0 → 1.7.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 +647 -3
  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/Bin/Bin.d.ts +18 -0
  7. package/dist/components/Bin/index.d.ts +2 -0
  8. package/dist/components/Box/Box.d.ts +87 -0
  9. package/dist/components/Box/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/ColorPicker/ColorPicker.d.ts +81 -0
  17. package/dist/components/ColorPicker/ColorSwatch.d.ts +50 -0
  18. package/dist/components/ColorPicker/index.d.ts +4 -0
  19. package/dist/components/ComboRow/ComboRow.d.ts +77 -0
  20. package/dist/components/ComboRow/index.d.ts +2 -0
  21. package/dist/components/EntryRow/EntryRow.d.ts +77 -0
  22. package/dist/components/EntryRow/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/PasswordEntryRow/PasswordEntryRow.d.ts +45 -0
  28. package/dist/components/PasswordEntryRow/index.d.ts +2 -0
  29. package/dist/components/PreferencesGroup/PreferencesGroup.d.ts +52 -0
  30. package/dist/components/PreferencesGroup/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 +2057 -645
  42. package/dist/index.js.map +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,47 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ import { AvatarColor, AvatarSize } from '../Avatar';
3
+ export interface AvatarGroupItem {
4
+ name?: string;
5
+ src?: string;
6
+ alt?: string;
7
+ color?: AvatarColor;
8
+ }
9
+ export interface AvatarGroupProps {
10
+ avatars: AvatarGroupItem[];
11
+ /** Max visible avatars before showing the overflow chip. Defaults to `5`. */
12
+ max?: number;
13
+ /** Size applied to all avatars and the overflow chip. Defaults to `"md"`. */
14
+ size?: AvatarSize;
15
+ /** Accessible label for the group. Auto-generated from names when omitted. */
16
+ accessibilityLabel?: string;
17
+ style?: StyleProp<ViewStyle>;
18
+ testID?: string;
19
+ }
20
+ /**
21
+ * Overlapping stack of `Avatar`s with a "+N" overflow indicator. Mirrors
22
+ * `@gnome-ui/react`'s `AvatarGroup`.
23
+ *
24
+ * The web version's separating ring around each overlapping avatar is two
25
+ * layered `box-shadow`s (an inset 1px dark/light border plus an outset 2px
26
+ * window-colored ring) — RN can only give a `View` one border, so this
27
+ * keeps just the outer window-colored ring (`borderWidth: 2,
28
+ * borderColor: theme.windowBgColor`, overriding `Avatar`'s own subtle 1px
29
+ * ring via its `style` prop), since that's the ring doing the actual
30
+ * "stay visually distinct from the avatar behind you" work — the inner
31
+ * hairline is a decorative nicety, not a behavior gap. The overflow chip
32
+ * reuses `Avatar`'s own per-size box dimensions (`sm`/`md`/`lg`/`xl` →
33
+ * 24/32/48/64) so it lines up exactly with the avatars beside it.
34
+ *
35
+ * `role="group"` + `accessibilityLabel` ports 1:1 from RN's newer
36
+ * web-aligned `Role` union (the same `Avatar`/`Badge`/`LevelBar`
37
+ * precedent) — the label is auto-generated from `avatars[].name` (joined,
38
+ * plus "and N more" when overflowing) exactly like the web version, unless
39
+ * overridden. The overflow chip's `+N` text is hidden from the
40
+ * accessibility tree (`accessibilityElementsHidden`/
41
+ * `importantForAccessibility="no"`) in favor of the chip's own
42
+ * `accessibilityLabel="+N more"` — the same one-stop-not-two reasoning
43
+ * `SpinButton`/`Avatar` already established for a decorative inner glyph.
44
+ *
45
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Avatar.html
46
+ */
47
+ export declare const AvatarGroup: ({ avatars, max, size, accessibilityLabel, style, testID, }: AvatarGroupProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export type { AvatarGroupItem, AvatarGroupProps } from './AvatarGroup';
2
+ export { AvatarGroup } from './AvatarGroup';
@@ -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,18 @@
1
+ import { View, ViewProps } from 'react-native';
2
+ export type BinProps = ViewProps;
3
+ /**
4
+ * Single-child container with no visual styling.
5
+ *
6
+ * A transparent wrapper that forwards all `View` props (and a ref to the
7
+ * underlying `View`) straight through — useful as a neutral base for custom
8
+ * components that need to apply layout or size constraints without
9
+ * introducing any chrome of their own.
10
+ *
11
+ * Mirrors `AdwBin` and `@gnome-ui/react`'s own `Bin`. A plain RN `View`
12
+ * already has no default visual styling (no background, no border), so
13
+ * unlike the web port there's no CSS reset to strip — this is a pure
14
+ * passthrough.
15
+ *
16
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Bin.html
17
+ */
18
+ export declare const Bin: import('react').ForwardRefExoticComponent<ViewProps & import('react').RefAttributes<View>>;
@@ -0,0 +1,2 @@
1
+ export type { BinProps } from './Bin';
2
+ export { Bin } from './Bin';
@@ -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,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,81 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ import { ColorSwatchSize } from './ColorSwatch';
3
+ export interface ColorPickerColor {
4
+ /** Color value (hex recommended). */
5
+ value: string;
6
+ /** Human-readable name, used as the swatch's accessible label. */
7
+ label?: string;
8
+ }
9
+ /** Default Adwaita-named palette (matches the `Avatar` color set). */
10
+ export declare const GNOME_PALETTE: ColorPickerColor[];
11
+ export interface ColorPickerProps {
12
+ /** Currently selected color value. */
13
+ value?: string;
14
+ /** Called when the user selects a color. */
15
+ onChange?: (value: string) => void;
16
+ /** Palette to display. Defaults to `GNOME_PALETTE` (the 9 Adwaita colors). */
17
+ colors?: ColorPickerColor[];
18
+ /**
19
+ * Show a "+" button after the palette, and render any `value` outside the
20
+ * palette as its own selected swatch. Pressing either calls
21
+ * `onRequestCustom` — RN has no `<input type="color">`, so the picker UI
22
+ * itself is the consuming app's to provide. Defaults to `false`.
23
+ */
24
+ allowCustom?: boolean;
25
+ /**
26
+ * Called when the "+" button (or the current custom swatch) is pressed.
27
+ * Open your own color picker here and feed the result back through
28
+ * `value`/`onChange`.
29
+ */
30
+ onRequestCustom?: () => void;
31
+ /** Swatch size. Defaults to `"md"`. */
32
+ size?: ColorSwatchSize;
33
+ /** Accessible name for the group. Defaults to `"Color"`. */
34
+ accessibilityLabel?: string;
35
+ disabled?: boolean;
36
+ style?: StyleProp<ViewStyle>;
37
+ testID?: string;
38
+ }
39
+ /**
40
+ * Color palette picker following the Adwaita `GtkColorButton` + swatch
41
+ * pattern, mirroring `@gnome-ui/react`'s own `ColorPicker`. Renders a
42
+ * wrapping row of circular `ColorSwatch` items backed by a radio group.
43
+ *
44
+ * **`allowCustom` is the one prop that changes meaning.** On the web it
45
+ * wires a hidden `<input type="color">` and the browser supplies the whole
46
+ * picker UI; RN has no such control, and building an HSV picker would be a
47
+ * component in its own right rather than a detail of this one. So the prop
48
+ * keeps its *visible* behaviour — the "+" button, and a `value` outside the
49
+ * palette shown as its own selected swatch — while the press is handed to
50
+ * `onRequestCustom` for the app to answer with whatever picker it has. Round
51
+ * trips through `value`/`onChange` exactly as before.
52
+ *
53
+ * The container is a `WrapBox` (`display: flex; flex-wrap: wrap; gap: 8`
54
+ * with nothing else in `.picker`), and the "+" button's `border: 1.5px
55
+ * dashed` ports directly — `borderStyle: 'dashed'` is one of the few CSS
56
+ * border tricks RN does support. Its plus glyph comes from `@gnome-ui/icons`
57
+ * rather than the web's hand-drawn path, since `Add` is the same mark and
58
+ * already resolves to the foreground color `.customButton` asks for.
59
+ *
60
+ * As in `ToggleGroup`, the group takes `accessibilityRole="radiogroup"` but
61
+ * deliberately not `accessible`, which on iOS would collapse the swatches
62
+ * into one unreachable element. Arrow-key navigation and the roving
63
+ * `tabIndex` drop, as everywhere else here.
64
+ *
65
+ * @example
66
+ * const [color, setColor] = useState('#3584e4');
67
+ *
68
+ * <ColorPicker value={color} onChange={setColor} />
69
+ *
70
+ * @example
71
+ * // Custom colors, with your own picker behind the "+"
72
+ * <ColorPicker
73
+ * value={color}
74
+ * onChange={setColor}
75
+ * allowCustom
76
+ * onRequestCustom={() => setPickerOpen(true)}
77
+ * />
78
+ *
79
+ * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ColorButton.html
80
+ */
81
+ export declare const ColorPicker: ({ value, onChange, colors, allowCustom, onRequestCustom, size, accessibilityLabel, disabled, style, testID, }: ColorPickerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,50 @@
1
+ import { PressableProps, StyleProp, View, ViewStyle } from 'react-native';
2
+ export type ColorSwatchSize = 'sm' | 'md' | 'lg';
3
+ /** `.swatch-sm` / `-md` / `-lg`. */
4
+ export declare const SWATCH_DIAMETER: Record<ColorSwatchSize, number>;
5
+ /**
6
+ * Width of the selected state's outer ring. Reserved as padding on every
7
+ * swatch, selected or not, so selecting one never reflows the row — the web
8
+ * gets this for free because `box-shadow` rings don't take up space.
9
+ */
10
+ export declare const RING_WIDTH = 2;
11
+ export interface ColorSwatchProps extends Omit<PressableProps, 'children' | 'style' | 'onPress' | 'disabled'> {
12
+ /** Color value displayed as the swatch background. */
13
+ color: string;
14
+ /** Whether this swatch is the currently selected color. */
15
+ selected?: boolean;
16
+ /** Swatch diameter. Defaults to `"md"`. */
17
+ size?: ColorSwatchSize;
18
+ /** Called with `color` when the swatch is pressed. */
19
+ onSelect?: (color: string) => void;
20
+ /** Accessible name. Defaults to the color value. */
21
+ accessibilityLabel?: string;
22
+ disabled?: boolean;
23
+ style?: StyleProp<ViewStyle>;
24
+ }
25
+ /**
26
+ * Single circular color swatch. Usable standalone or composed inside
27
+ * `ColorPicker`, and shows a white checkmark when `selected`.
28
+ *
29
+ * The web's three `box-shadow` rings collapse into real box-model pieces,
30
+ * since RN gives a `View` exactly one border: the resting
31
+ * `inset 0 0 0 1px` hairline becomes `borderWidth: 1`, the selected state's
32
+ * `inset 0 0 0 2px rgb(255 255 255 / .9)` becomes a 2 dp white border, and
33
+ * the outer `0 0 0 2px var(--swatch-color)` becomes a wrapper painted in the
34
+ * swatch color. That wrapper is always rendered with the same 2 dp padding
35
+ * and only changes color, because a `box-shadow` ring costs no layout space
36
+ * on the web while a real padded wrapper does — reserving it unconditionally
37
+ * is what keeps the row from reflowing as the selection moves.
38
+ *
39
+ * The checkmark is hand-drawn with `react-native-svg` rather than taken from
40
+ * `@gnome-ui/icons`, mirroring the web version, which also hand-draws it:
41
+ * it's a stroked path, and `Icon`'s palette has no white to give it anyway.
42
+ * `filter: drop-shadow(...)` has no RN counterpart, so the path is drawn
43
+ * twice — a translucent black copy offset 1 dp down, then the white one on
44
+ * top — which is what that filter renders and is why it exists: without it
45
+ * the check disappears on a yellow swatch.
46
+ *
47
+ * `:hover { transform: scale(1.12) }` drops with hover; the selected
48
+ * `scale(1.05)` ports as-is.
49
+ */
50
+ export declare const ColorSwatch: import('react').ForwardRefExoticComponent<ColorSwatchProps & import('react').RefAttributes<View>>;
@@ -0,0 +1,4 @@
1
+ export type { ColorPickerColor, ColorPickerProps } from './ColorPicker';
2
+ export { ColorPicker, GNOME_PALETTE } from './ColorPicker';
3
+ export type { ColorSwatchProps, ColorSwatchSize } from './ColorSwatch';
4
+ export { ColorSwatch } from './ColorSwatch';