@gnome-ui/react-native 1.6.0 → 1.8.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 +533 -4
- package/dist/components/Bin/Bin.d.ts +18 -0
- package/dist/components/Bin/index.d.ts +2 -0
- package/dist/components/Blockquote/Blockquote.d.ts +40 -0
- package/dist/components/Blockquote/index.d.ts +2 -0
- package/dist/components/BottomTabBar/BottomTabBar.d.ts +106 -0
- package/dist/components/BottomTabBar/index.d.ts +2 -0
- package/dist/components/ButtonRow/ButtonRow.d.ts +41 -0
- package/dist/components/ButtonRow/index.d.ts +2 -0
- package/dist/components/Callout/Callout.d.ts +36 -0
- package/dist/components/Callout/index.d.ts +2 -0
- package/dist/components/CheckRow/CheckRow.d.ts +47 -0
- package/dist/components/CheckRow/index.d.ts +2 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +81 -0
- package/dist/components/ColorPicker/ColorSwatch.d.ts +50 -0
- package/dist/components/ColorPicker/index.d.ts +4 -0
- package/dist/components/ComboRow/ComboRow.d.ts +77 -0
- package/dist/components/ComboRow/index.d.ts +2 -0
- package/dist/components/EntryRow/EntryRow.d.ts +77 -0
- package/dist/components/EntryRow/index.d.ts +2 -0
- package/dist/components/ExpanderRow/ExpanderRow.d.ts +58 -0
- package/dist/components/ExpanderRow/index.d.ts +2 -0
- package/dist/components/FieldGroup/FieldGroup.d.ts +52 -0
- package/dist/components/FieldGroup/index.d.ts +2 -0
- package/dist/components/FilterableMultiSelectDropdown/FilterableMultiSelectDropdown.d.ts +46 -0
- package/dist/components/FilterableMultiSelectDropdown/index.d.ts +2 -0
- package/dist/components/Icon/Icon.d.ts +11 -1
- package/dist/components/MultiSelectDropdown/MultiSelectDropdown.d.ts +55 -0
- package/dist/components/MultiSelectDropdown/index.d.ts +2 -0
- package/dist/components/PasswordEntryRow/PasswordEntryRow.d.ts +45 -0
- package/dist/components/PasswordEntryRow/index.d.ts +2 -0
- package/dist/components/PasswordField/PasswordField.d.ts +48 -0
- package/dist/components/PasswordField/index.d.ts +2 -0
- package/dist/components/RangeSlider/RangeSlider.d.ts +73 -0
- package/dist/components/RangeSlider/index.d.ts +2 -0
- package/dist/components/StatusBadge/StatusBadge.d.ts +47 -0
- package/dist/components/StatusBadge/index.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.js +2454 -778
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { AnyIconDefinition } from '@gnome-ui/icons';
|
|
2
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
export interface BottomTabBarItem<V extends string = string> {
|
|
4
|
+
/** The value reported to `onChange` when this tab is pressed. */
|
|
5
|
+
value: V;
|
|
6
|
+
/** Label shown below the icon. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Icon shown while this tab is not the selected one. */
|
|
9
|
+
icon: AnyIconDefinition;
|
|
10
|
+
/**
|
|
11
|
+
* Icon shown while this tab *is* selected — the filled-vs-outline
|
|
12
|
+
* convention iOS/Android system tab bars both use (e.g. a hollow heart
|
|
13
|
+
* outline that becomes solid when active). Optional: omit to reuse
|
|
14
|
+
* `icon` for both states, tinted differently.
|
|
15
|
+
*/
|
|
16
|
+
activeIcon?: AnyIconDefinition;
|
|
17
|
+
/**
|
|
18
|
+
* Notification indicator. `true` renders a small dot (unread/pending,
|
|
19
|
+
* no count); a `number` renders a counted badge (values above 99 render
|
|
20
|
+
* as `"99+"`, matching `TabItem`'s own count-badge convention).
|
|
21
|
+
*/
|
|
22
|
+
badge?: number | boolean;
|
|
23
|
+
/** Disables this one tab. */
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface BottomTabBarProps<V extends string = string> {
|
|
27
|
+
/** The tabs to render, in order. */
|
|
28
|
+
items: BottomTabBarItem<V>[];
|
|
29
|
+
/** The currently selected tab's value. */
|
|
30
|
+
value: V;
|
|
31
|
+
/** Called when the user presses a tab. */
|
|
32
|
+
onChange: (value: V) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Extra bottom padding, in addition to the bar's own vertical padding —
|
|
35
|
+
* pass your own `useSafeAreaInsets().bottom` here so the bar clears the
|
|
36
|
+
* home indicator / gesture area on notched devices. This package takes
|
|
37
|
+
* no dependency on `react-native-safe-area-context` itself (the same
|
|
38
|
+
* "no new peer dependency without a deliberate decision" standard
|
|
39
|
+
* `AnimatedIcon`'s `react-native-svg` addition was held to) — the
|
|
40
|
+
* consumer's own app almost certainly already has it for its root
|
|
41
|
+
* layout, so threading the value in here is cheaper than this package
|
|
42
|
+
* depending on it too. Defaults to `0`.
|
|
43
|
+
*/
|
|
44
|
+
bottomInset?: number;
|
|
45
|
+
style?: StyleProp<ViewStyle>;
|
|
46
|
+
testID?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fixed bottom navigation bar — the iOS/Android "tab bar" pattern (Music,
|
|
50
|
+
* Instagram, most system apps): a small, fixed set of top-level
|
|
51
|
+
* destinations, each an icon + label, always visible at the foot of the
|
|
52
|
+
* screen. No GNOME/libadwaita widget mirrors this (desktop apps don't use
|
|
53
|
+
* bottom navigation), so this is an original component for this package,
|
|
54
|
+
* not a port — built to fill a real gap once mobile "modern app shell"
|
|
55
|
+
* navigation was requested.
|
|
56
|
+
*
|
|
57
|
+
* Distinct from the existing `TabBar`/`TabItem` (an in-page, horizontally
|
|
58
|
+
* scrollable content switcher mirroring `@gnome-ui/react`'s `Tabs`) — that
|
|
59
|
+
* one reuses `headerbarFgColor` for every tab's label regardless of
|
|
60
|
+
* selection state, signaling "active" purely via a background pill +
|
|
61
|
+
* bold weight + accent underline, never by tinting the icon/label
|
|
62
|
+
* themselves. A bottom tab bar's whole visual signature is the opposite:
|
|
63
|
+
* the active icon+label *are* the app's accent color. `Icon`'s `color`
|
|
64
|
+
* prop can't express that on its own — it only resolves to a fixed
|
|
65
|
+
* named-palette swatch (`color="blue"` always means `theme.blue3`, never
|
|
66
|
+
* whatever accent the app actually configured via `GnomeProvider
|
|
67
|
+
* accentColor`) — so this is the first consumer of `Icon`'s new
|
|
68
|
+
* `tintColor` prop, passing `theme.accentColor` directly for the selected
|
|
69
|
+
* tab and leaving it unset (dimmed default) for the rest.
|
|
70
|
+
*
|
|
71
|
+
* The optional notification indicator reuses the real `Badge` component
|
|
72
|
+
* for the dot/pill itself, but positions it manually rather than through
|
|
73
|
+
* `Badge`'s own `anchor` mode — `anchor` wraps `[anchor, badge]` in a
|
|
74
|
+
* `View` with a hardcoded `alignSelf: 'flex-start'`, which is fine for
|
|
75
|
+
* `Badge`'s usual context (a row where the anchor is meant to hug the
|
|
76
|
+
* start) but silently broke centering here: a bare icon (no badge) is a
|
|
77
|
+
* direct child of this component's centered column, while a badged icon's
|
|
78
|
+
* extra `anchor`-mode wrapper overrode that centering and pinned itself to
|
|
79
|
+
* the left edge — the two looked visibly misaligned side by side. Every
|
|
80
|
+
* tab now gets the identical `position: 'relative'` wrapper shape
|
|
81
|
+
* regardless of whether it has a badge, so centering behaves identically
|
|
82
|
+
* across all of them; the badge itself is a plain (non-`anchor`) `Badge`,
|
|
83
|
+
* absolutely positioned and re-sized for this icon's actual scale (`size="lg"`
|
|
84
|
+
* is only 20px — `Badge`'s own default dot/offset sizing assumes a much
|
|
85
|
+
* larger anchor like an avatar or `IconButton`, and would otherwise nearly
|
|
86
|
+
* cover the icon rather than sit as a small corner accent). Press feedback
|
|
87
|
+
* is the same `pressed ? theme.activeOverlay : 'transparent'` recipe every
|
|
88
|
+
* other `Pressable` in this package already uses.
|
|
89
|
+
*
|
|
90
|
+
* `bottomInset` stands in for real safe-area awareness without this
|
|
91
|
+
* package taking on `react-native-safe-area-context` as a dependency —
|
|
92
|
+
* see its own doc comment.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* <BottomTabBar
|
|
96
|
+
* items={[
|
|
97
|
+
* { value: 'home', label: 'Home', icon: HomeOutline, activeIcon: HomeFilled },
|
|
98
|
+
* { value: 'search', label: 'Search', icon: Search },
|
|
99
|
+
* { value: 'profile', label: 'Profile', icon: Person, badge: true },
|
|
100
|
+
* ]}
|
|
101
|
+
* value={tab}
|
|
102
|
+
* onChange={setTab}
|
|
103
|
+
* bottomInset={insets.bottom}
|
|
104
|
+
* />
|
|
105
|
+
*/
|
|
106
|
+
export declare const BottomTabBar: <V extends string = string>({ items, value, onChange, bottomInset, style, testID, }: BottomTabBarProps<V>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { PressableProps, StyleProp, View, ViewStyle } from 'react-native';
|
|
3
|
+
export type ButtonRowVariant = 'default' | 'suggested' | 'destructive';
|
|
4
|
+
export interface ButtonRowProps extends Omit<PressableProps, 'children' | 'style'> {
|
|
5
|
+
/** Label displayed centered in the row. */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Visual style that colours the title text. */
|
|
8
|
+
variant?: ButtonRowVariant;
|
|
9
|
+
/** Icon placed at the leading edge. Rendered as-is — size/color it yourself. */
|
|
10
|
+
leading?: ReactNode;
|
|
11
|
+
/** Icon placed at the trailing edge. Rendered as-is — size/color it yourself. */
|
|
12
|
+
trailing?: ReactNode;
|
|
13
|
+
style?: StyleProp<ViewStyle>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Full-width activatable row styled as a button, for use inside a
|
|
17
|
+
* `BoxedList`. Mirrors `AdwButtonRow` and `@gnome-ui/react`'s own
|
|
18
|
+
* `ButtonRow` — use when an entire list row should trigger a single action
|
|
19
|
+
* with a centered label; prefer `ActionRow` with `interactive` when the row
|
|
20
|
+
* also needs a title/subtitle layout.
|
|
21
|
+
*
|
|
22
|
+
* Rebuilt with `Pressable` rather than ported from the web `<button>` —
|
|
23
|
+
* same pressed-state-overlay recipe `ActionRow`/`Card` already established
|
|
24
|
+
* (`theme.activeOverlay` stands in for the web's `:hover`/`:active`
|
|
25
|
+
* `background-color` transition, since RN has no hover state). The title's
|
|
26
|
+
* color reuses `Text`'s own `TextColor` union (`"accent"`/`"destructive"`
|
|
27
|
+
* already resolve to the exact same `theme.accentColor`/`destructiveColor`
|
|
28
|
+
* tokens the source CSS's `suggested`/`destructive` variants reference) —
|
|
29
|
+
* no separate color-resolution logic needed. Unlike the web version, the
|
|
30
|
+
* variant color does *not* propagate to `leading`/`trailing` — RN's `Icon`
|
|
31
|
+
* has no `currentColor` equivalent and only accepts a fixed named-swatch
|
|
32
|
+
* palette, the same dropped nicety `Chip` already accepted for its own
|
|
33
|
+
* leading/remove icons. The title gets `flex: 1` + `textAlign: 'center'`
|
|
34
|
+
* (the source CSS's own `.title { flex: 1; text-align: center }`) rather
|
|
35
|
+
* than centering the row via `justifyContent` — that keeps the label
|
|
36
|
+
* centered in the row's full width even when only one of `leading`/
|
|
37
|
+
* `trailing` is present, matching the web behavior exactly.
|
|
38
|
+
*
|
|
39
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ButtonRow.html
|
|
40
|
+
*/
|
|
41
|
+
export declare const ButtonRow: import('react').ForwardRefExoticComponent<ButtonRowProps & import('react').RefAttributes<View>>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, ViewProps, ViewStyle } from 'react-native';
|
|
3
|
+
export type CalloutVariant = 'info' | 'warning' | 'tip';
|
|
4
|
+
export interface CalloutProps extends Omit<ViewProps, 'style'> {
|
|
5
|
+
/**
|
|
6
|
+
* Visual emphasis level.
|
|
7
|
+
* - `info` (default) — neutral, accent-colored. General contextual notes.
|
|
8
|
+
* - `warning` — yellow. Recoverable problems or things to double-check.
|
|
9
|
+
* - `tip` — green. Optional suggestions or shortcuts.
|
|
10
|
+
*/
|
|
11
|
+
variant?: CalloutVariant;
|
|
12
|
+
/** The message content. */
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
/** When true a dismiss (×) button is shown at the trailing edge. */
|
|
15
|
+
dismissible?: boolean;
|
|
16
|
+
/** Called when the user presses the dismiss button. */
|
|
17
|
+
onDismiss?: () => void;
|
|
18
|
+
style?: StyleProp<ViewStyle>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Inline, dismissible admonition box for contextual help text within forms
|
|
22
|
+
* and cards. Mirrors `@gnome-ui/react`'s `Callout`.
|
|
23
|
+
*
|
|
24
|
+
* Unlike `Banner` (a persistent, edge-to-edge strip at the top of a view)
|
|
25
|
+
* and `Toast` (a temporary notification), `Callout` is a contained, tinted
|
|
26
|
+
* box meant to sit inline alongside the content it annotates.
|
|
27
|
+
*
|
|
28
|
+
* `role="note"` ports 1:1 from RN's newer web-aligned `Role` union (the
|
|
29
|
+
* same one `Dialog`/`Tooltip` already use) — `accessible` is set alongside
|
|
30
|
+
* it, per the `BoxedList` lesson that a bare `View` isn't an accessibility
|
|
31
|
+
* element by default. The leading icon is decorative, hidden from
|
|
32
|
+
* assistive tech the same way `Blockquote`'s own icon is.
|
|
33
|
+
*
|
|
34
|
+
* @see https://developer.gnome.org/hig/patterns/feedback/
|
|
35
|
+
*/
|
|
36
|
+
export declare const Callout: ({ variant, children, dismissible, onDismiss, style, ...viewProps }: CalloutProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { PressableProps, StyleProp, View, ViewStyle } from 'react-native';
|
|
3
|
+
export interface CheckRowProps extends Omit<PressableProps, 'children' | 'style' | 'onPress'> {
|
|
4
|
+
/** Primary label. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Secondary line below the title. */
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
/** Icon or image placed at the leading edge, after the checkbox. */
|
|
9
|
+
leading?: ReactNode;
|
|
10
|
+
/** Controlled checked state. */
|
|
11
|
+
checked?: boolean;
|
|
12
|
+
/** Initial checked state when uncontrolled. Defaults to `false`. */
|
|
13
|
+
defaultChecked?: boolean;
|
|
14
|
+
/** Called with the next value when the row is pressed. */
|
|
15
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
16
|
+
style?: StyleProp<ViewStyle>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Activatable row with an integrated checkbox, mirroring
|
|
20
|
+
* `@gnome-ui/react`'s `CheckRow`. The entire row is a single pressable —
|
|
21
|
+
* pressing anywhere toggles the checked state. Use inside a `BoxedList`
|
|
22
|
+
* when a user must select or deselect individual items in a list; prefer a
|
|
23
|
+
* `SwitchRow` (once ported) for a single on/off setting.
|
|
24
|
+
*
|
|
25
|
+
* Supports both controlled (`checked`) and uncontrolled (`defaultChecked`)
|
|
26
|
+
* modes, the same `isControlled`/internal-state-fallback shape already
|
|
27
|
+
* established by `Expander`/`ComboRow`/`Popover`.
|
|
28
|
+
*
|
|
29
|
+
* The checkbox visual reuses `Checkbox`'s exact border/background
|
|
30
|
+
* `Animated.Value` interpolation and checkmark-fade-in recipe — but as a
|
|
31
|
+
* plain, non-interactive `View` rather than importing the real `Checkbox`
|
|
32
|
+
* component, since `Checkbox` is itself a `Pressable` and nesting one
|
|
33
|
+
* touchable inside another (the row's own `Pressable`) would create two
|
|
34
|
+
* overlapping tap targets. `aria-labelledby` (pointing the web button's
|
|
35
|
+
* `role="checkbox"` at the title/subtitle content) has no RN equivalent —
|
|
36
|
+
* `accessibilityLabel` combining title and subtitle is the substitution,
|
|
37
|
+
* the same "no relationship attribute" gap `Tooltip`'s dropped
|
|
38
|
+
* `aria-describedby` already established. The title reads `theme.cardFgColor`
|
|
39
|
+
* directly (not `Text`'s own `"default"`, which resolves to
|
|
40
|
+
* `windowFgColor`) to match the source CSS's `--gnome-card-fg-color`
|
|
41
|
+
* ambient row color exactly — the two tokens happen to share the same
|
|
42
|
+
* value in every theme this package ships, but the source CSS's intent is
|
|
43
|
+
* specifically "card foreground," so the port keeps that distinction.
|
|
44
|
+
*
|
|
45
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.CheckButton.html
|
|
46
|
+
*/
|
|
47
|
+
export declare const CheckRow: import('react').ForwardRefExoticComponent<CheckRowProps & import('react').RefAttributes<View>>;
|
|
@@ -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,77 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import { DropdownOption } from '../Dropdown';
|
|
4
|
+
/** Same shape as `Dropdown`'s own option — re-exported so `ComboRow` reads self-contained. */
|
|
5
|
+
export type ComboRowOption<V extends string = string> = DropdownOption<V>;
|
|
6
|
+
export interface ComboRowProps<V extends string = string> {
|
|
7
|
+
/** Primary label. */
|
|
8
|
+
title: string;
|
|
9
|
+
/** Secondary line below the title. */
|
|
10
|
+
subtitle?: string;
|
|
11
|
+
/** Icon or image placed at the leading edge. */
|
|
12
|
+
leading?: ReactNode;
|
|
13
|
+
/** The list of selectable options. */
|
|
14
|
+
options: ComboRowOption<V>[];
|
|
15
|
+
/** The currently selected value (controlled). */
|
|
16
|
+
value?: V;
|
|
17
|
+
/** Initial value when uncontrolled. */
|
|
18
|
+
defaultValue?: V;
|
|
19
|
+
/** Called when the user selects an option. */
|
|
20
|
+
onValueChange?: (value: V) => void;
|
|
21
|
+
/** Shown in the trigger while nothing is selected. Defaults to `"—"`. */
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
/** Accessible name for the selector. Defaults to `title`. */
|
|
24
|
+
accessibilityLabel?: string;
|
|
25
|
+
/** Disables the row and its selector. */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
style?: StyleProp<ViewStyle>;
|
|
28
|
+
testID?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Settings row with an inline combo selector at the trailing edge, mirroring
|
|
32
|
+
* `AdwComboRow` and `@gnome-ui/react`'s own `ComboRow`. Use inside a
|
|
33
|
+
* `BoxedList` for a setting that picks one of a set of options.
|
|
34
|
+
*
|
|
35
|
+
* **This is a composition of `ActionRow` + `Dropdown`, where the web version
|
|
36
|
+
* hand-rolls its own listbox inline** — around 200 lines re-implementing the
|
|
37
|
+
* trigger, the flip-up placement, outside-click dismissal, roving
|
|
38
|
+
* `aria-activedescendant` and the whole keyboard layer, none of which is
|
|
39
|
+
* meaningfully different from that package's own `Dropdown`. Nothing forced
|
|
40
|
+
* the duplication visually either: `.row` is `ActionRow`'s exact metrics
|
|
41
|
+
* (12/24 dp padding, 52 dp min-height) and `.trigger` is `Dropdown`'s exact
|
|
42
|
+
* trigger (card background, 1 px shade border turning accent when open,
|
|
43
|
+
* `radius-md`, chevron). So this port composes the two already-shipped,
|
|
44
|
+
* already-verified components instead — which also means the flip-to-fit
|
|
45
|
+
* placement, the tap-outside dismissal and the `Modal`-based list all come
|
|
46
|
+
* along for free rather than being rebuilt and re-debugged.
|
|
47
|
+
*
|
|
48
|
+
* The web keeps its own `useState` for the uncontrolled case; `Dropdown` is
|
|
49
|
+
* controlled-only, so that state lives here — same behaviour, one level up.
|
|
50
|
+
*
|
|
51
|
+
* The keyboard layer (`↑`/`↓`/`Home`/`End`/`Enter`/`Escape`) drops as it
|
|
52
|
+
* does everywhere else in this package, and `Dropdown` already provides the
|
|
53
|
+
* touch equivalents it was built with.
|
|
54
|
+
*
|
|
55
|
+
* The dimming for `disabled` is applied here rather than left to
|
|
56
|
+
* `ActionRow`, which only dims in its `interactive` branch — on a plain
|
|
57
|
+
* (non-pressable) row its `disabled` prop currently reaches a `View` that
|
|
58
|
+
* does nothing with it. Making this row `interactive` isn't the answer: the
|
|
59
|
+
* `Dropdown` is the control, and the row itself has nothing to press.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* <BoxedList>
|
|
63
|
+
* <ComboRow
|
|
64
|
+
* title="Language"
|
|
65
|
+
* subtitle="Used across the whole app"
|
|
66
|
+
* value={language}
|
|
67
|
+
* onValueChange={setLanguage}
|
|
68
|
+
* options={[
|
|
69
|
+
* { value: 'en', label: 'English' },
|
|
70
|
+
* { value: 'es', label: 'Español' },
|
|
71
|
+
* ]}
|
|
72
|
+
* />
|
|
73
|
+
* </BoxedList>
|
|
74
|
+
*
|
|
75
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ComboRow.html
|
|
76
|
+
*/
|
|
77
|
+
export declare const ComboRow: <V extends string = string>({ title, subtitle, leading, options, value: controlledValue, defaultValue, onValueChange, placeholder, accessibilityLabel, disabled, style, testID, }: ComboRowProps<V>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TextInput as RNTextInput, StyleProp, TextInputProps, ViewStyle } from 'react-native';
|
|
3
|
+
export interface EntryRowProps extends Omit<TextInputProps, 'style' | 'value' | 'defaultValue' | 'editable' | 'testID'> {
|
|
4
|
+
/**
|
|
5
|
+
* Acts as a floating label: shown small above the input once the field has
|
|
6
|
+
* content or focus, and as the placeholder while it's empty and unfocused.
|
|
7
|
+
*/
|
|
8
|
+
title: string;
|
|
9
|
+
/** Controlled value. Omit for an uncontrolled field. */
|
|
10
|
+
value?: string;
|
|
11
|
+
/** Initial value when uncontrolled. */
|
|
12
|
+
defaultValue?: string;
|
|
13
|
+
/** Called when the input value changes. */
|
|
14
|
+
onValueChange?: (value: string) => void;
|
|
15
|
+
/** Icon or widget placed at the leading edge. */
|
|
16
|
+
leading?: ReactNode;
|
|
17
|
+
/** Icon or widget placed at the trailing edge (e.g. a clear or reveal button). */
|
|
18
|
+
trailing?: ReactNode;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Applied to the row, not the input — the convention every other component
|
|
22
|
+
* in this package follows. Reach the field itself with the accessible name
|
|
23
|
+
* (`getByLabelText(title)`).
|
|
24
|
+
*/
|
|
25
|
+
testID?: string;
|
|
26
|
+
style?: StyleProp<ViewStyle>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Row with an inline text entry field, mirroring `AdwEntryRow` and
|
|
30
|
+
* `@gnome-ui/react`'s own `EntryRow`. The `title` rises above the input as a
|
|
31
|
+
* small label once the field is focused or has content, and stands in for
|
|
32
|
+
* the placeholder until then. Use inside a `BoxedList` for settings that
|
|
33
|
+
* take free-form text.
|
|
34
|
+
*
|
|
35
|
+
* The float is one JS-driven `Animated.Value` (`useNativeDriver: false`):
|
|
36
|
+
* `fontSize` is part of the transition and can't be native-driven, and
|
|
37
|
+
* mixing a native with a JS value on one component throws — the same
|
|
38
|
+
* trade-off `Expander` and `InlineViewSwitcher` already accepted.
|
|
39
|
+
* `useReducedMotion()` snaps between the two states instead.
|
|
40
|
+
*
|
|
41
|
+
* **The label's travel is measured, not hardcoded.** The web can express its
|
|
42
|
+
* resting position as `top: 50%; transform: translateY(-50%)` and its
|
|
43
|
+
* floated one as `top: 6px`, but RN can't interpolate between a percentage
|
|
44
|
+
* and a fixed offset, so the row reports its own height through `onLayout`
|
|
45
|
+
* and the distance is derived from it. That also keeps the label centred if
|
|
46
|
+
* a consumer makes the row taller than the 56 dp minimum.
|
|
47
|
+
*
|
|
48
|
+
* The `:focus` inset ring is dropped rather than approximated. `TextField`'s
|
|
49
|
+
* own precedent — recolor the border on focus — doesn't transfer, because an
|
|
50
|
+
* `EntryRow` has no border of its own to recolor: it's a row inside a
|
|
51
|
+
* `BoxedList`, and adding one would shift the list's geometry. On a touch
|
|
52
|
+
* device the state is already unmistakable anyway: the label floats up, the
|
|
53
|
+
* text fades in, and the keyboard opens. The `prefers-contrast: more` block
|
|
54
|
+
* is a variation on that same ring, so it goes with it.
|
|
55
|
+
*
|
|
56
|
+
* Tapping anywhere on the row focuses the field, the same affordance the web
|
|
57
|
+
* version's row-level `onClick` provides.
|
|
58
|
+
*
|
|
59
|
+
* The visible label is hidden from assistive tech and the `title` becomes
|
|
60
|
+
* the input's `accessibilityLabel` instead. On the web the two are bound by
|
|
61
|
+
* `<label htmlFor>`, which RN has no equivalent for — left as-is, the label
|
|
62
|
+
* would be announced as loose text next to an unnamed field. `testID` lands
|
|
63
|
+
* on the row rather than the input (unlike the web version, which spreads
|
|
64
|
+
* every remaining prop onto the `<input>`), matching what every other
|
|
65
|
+
* component in this package does; reach the field itself by its accessible
|
|
66
|
+
* name.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const [name, setName] = useState('');
|
|
70
|
+
*
|
|
71
|
+
* <BoxedList>
|
|
72
|
+
* <EntryRow title="Display name" value={name} onValueChange={setName} />
|
|
73
|
+
* </BoxedList>
|
|
74
|
+
*
|
|
75
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.EntryRow.html
|
|
76
|
+
*/
|
|
77
|
+
export declare const EntryRow: import('react').ForwardRefExoticComponent<EntryRowProps & import('react').RefAttributes<RNTextInput>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, View, ViewStyle } from 'react-native';
|
|
3
|
+
export interface ExpanderRowProps {
|
|
4
|
+
/** Primary label. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Secondary line below the title. */
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
/** Icon or image placed at the leading edge of the header row. */
|
|
9
|
+
leading?: ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* Widget placed at the trailing edge of the header row, before the
|
|
12
|
+
* chevron (e.g. a value label or a `Switch`). Stop event propagation
|
|
13
|
+
* inside it so the row's toggle isn't triggered.
|
|
14
|
+
*/
|
|
15
|
+
trailing?: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Nested rows revealed when expanded. Use `ActionRow`, `ButtonRow`, or
|
|
18
|
+
* any row-shaped element — separators are inserted automatically.
|
|
19
|
+
*/
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
/** Controlled expanded state. */
|
|
22
|
+
expanded?: boolean;
|
|
23
|
+
/** Initial expanded state when uncontrolled. Defaults to `false`. */
|
|
24
|
+
defaultExpanded?: boolean;
|
|
25
|
+
/** Called when the expanded state changes. */
|
|
26
|
+
onExpandedChange?: (expanded: boolean) => void;
|
|
27
|
+
style?: StyleProp<ViewStyle>;
|
|
28
|
+
testID?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Collapsible `ActionRow` that reveals nested rows on activation, mirroring
|
|
32
|
+
* `@gnome-ui/react`'s `ExpanderRow`. The header row toggles a smooth reveal
|
|
33
|
+
* animation exposing child rows. Supports both controlled (`expanded`) and
|
|
34
|
+
* uncontrolled (`defaultExpanded`) modes.
|
|
35
|
+
*
|
|
36
|
+
* The reveal panel reuses the standalone `Expander`'s exact recipe — a
|
|
37
|
+
* single `Animated.View` with a directly-driven numeric `height` (RN has no
|
|
38
|
+
* CSS grid to lean on for the web version's `grid-template-rows: 0fr → 1fr`
|
|
39
|
+
* trick), content staying mounted while collapsed
|
|
40
|
+
* (`accessibilityElementsHidden`/`importantForAccessibility` standing in
|
|
41
|
+
* for the web's `inert`), and the "show natural height until first
|
|
42
|
+
* `onLayout` measurement lands, then hand control to `Animated`" guard for
|
|
43
|
+
* a `defaultExpanded` initial mount. The only difference from `Expander`
|
|
44
|
+
* itself: the chevron is `PanDown` (a straight down-arrow, matching the
|
|
45
|
+
* source CSS's hand-drawn `M4 6l4 4 4-4` path and rotating 0deg → 180deg)
|
|
46
|
+
* rather than `Expander`'s `PanEnd` triangle rotating 0deg → 90deg — the
|
|
47
|
+
* same icon/rotation pair `Dropdown`'s own chevron already established.
|
|
48
|
+
*
|
|
49
|
+
* Nested children get a `Separator` inserted before each one (including
|
|
50
|
+
* the first, directly under the header) via `Children.toArray(children)
|
|
51
|
+
* .filter(Boolean)`, the same falsy-child-filtering `ExpanderRow`'s web
|
|
52
|
+
* version already does. Unlike `CheckRow`/`ButtonRow`, this component has
|
|
53
|
+
* no `disabled` prop — the source `@gnome-ui/react` version doesn't expose
|
|
54
|
+
* one either, so none is added here.
|
|
55
|
+
*
|
|
56
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.ExpanderRow.html
|
|
57
|
+
*/
|
|
58
|
+
export declare const ExpanderRow: import('react').ForwardRefExoticComponent<ExpanderRowProps & import('react').RefAttributes<View>>;
|