@gnome-ui/react-native 1.11.0 → 1.12.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 +100 -0
- package/dist/components/LinkedGroup/LinkedGroup.d.ts +50 -0
- package/dist/components/LinkedGroup/index.d.ts +2 -0
- package/dist/components/NavigationSplitView/NavigationSplitView.d.ts +69 -0
- package/dist/components/NavigationSplitView/index.d.ts +2 -0
- package/dist/components/RatingStars/RatingStars.d.ts +48 -0
- package/dist/components/RatingStars/index.d.ts +2 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +751 -591
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -294,6 +294,43 @@ announces the same thing, mirroring the web version's `aria-label` on its
|
|
|
294
294
|
icon span. Unlike the web `Link`, RN has no tab concept, so `external` is
|
|
295
295
|
purely presentational — `href` always opens the same way regardless.
|
|
296
296
|
|
|
297
|
+
### LinkedGroup
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
import { Button, LinkedGroup } from '@gnome-ui/react-native';
|
|
301
|
+
|
|
302
|
+
<LinkedGroup>
|
|
303
|
+
<Button>Cut</Button>
|
|
304
|
+
<Button>Copy</Button>
|
|
305
|
+
<Button>Paste</Button>
|
|
306
|
+
</LinkedGroup>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Renders children as a single visually-connected unit with no gap and
|
|
310
|
+
merged borders — the canonical GNOME pattern for button groups and
|
|
311
|
+
segmented inputs. Mirrors `@gnome-ui/react`'s `LinkedGroup`, itself
|
|
312
|
+
mirroring the libadwaita `.linked` style class.
|
|
313
|
+
|
|
314
|
+
The web version reaches every child's border-radius via a CSS `> *`
|
|
315
|
+
universal child selector — RN has no equivalent way for a parent `View`
|
|
316
|
+
to reach into an arbitrary child's own internally-computed styles.
|
|
317
|
+
Reimagined as the same `cloneElement`-onto-children technique
|
|
318
|
+
`Popover`/`Tooltip` already use on their own trigger: each child gets a
|
|
319
|
+
computed corner-radius/negative-margin override merged onto whatever
|
|
320
|
+
`style` it already has, generalizing the "zero the shared inner corners,
|
|
321
|
+
keep `theme.radiusMd` on the outer ones, overlap by 1 dp to collapse the
|
|
322
|
+
shared border" recipe `SplitButton` already proved for its own fixed
|
|
323
|
+
two-piece connected border. This only works because every component in
|
|
324
|
+
this package already merges a passed-in `style` prop last — the same
|
|
325
|
+
assumption `Popover`'s own trigger-cloning already depends on, so any
|
|
326
|
+
custom child passed to `LinkedGroup` needs to follow that same
|
|
327
|
+
convention.
|
|
328
|
+
|
|
329
|
+
The web CSS also raises a hovered/focused child's `z-index` so its own
|
|
330
|
+
border isn't visually covered by the next sibling's overlapping edge —
|
|
331
|
+
dropped here: RN is touch-first (no `:hover`), and no component in this
|
|
332
|
+
package currently renders an escaping focus ring that overlap could clip.
|
|
333
|
+
|
|
297
334
|
### TextField
|
|
298
335
|
|
|
299
336
|
```tsx
|
|
@@ -2510,6 +2547,40 @@ panel-height positioning almost verbatim, and gives each option row a
|
|
|
2510
2547
|
leading checkbox-square visual instead of `Dropdown`'s single trailing
|
|
2511
2548
|
checkmark.
|
|
2512
2549
|
|
|
2550
|
+
### NavigationSplitView
|
|
2551
|
+
|
|
2552
|
+
```tsx
|
|
2553
|
+
import { NavigationSplitView } from '@gnome-ui/react-native';
|
|
2554
|
+
|
|
2555
|
+
const [showContent, setShowContent] = useState(false);
|
|
2556
|
+
|
|
2557
|
+
<NavigationSplitView
|
|
2558
|
+
showContent={showContent}
|
|
2559
|
+
sidebar={<MailList onSelect={() => setShowContent(true)} />}
|
|
2560
|
+
content={<MailDetail onBack={() => setShowContent(false)} />}
|
|
2561
|
+
/>;
|
|
2562
|
+
```
|
|
2563
|
+
|
|
2564
|
+
Two-pane sidebar + content layout following the Adwaita
|
|
2565
|
+
`AdwNavigationSplitView` pattern — mirrors `@gnome-ui/react`'s
|
|
2566
|
+
`NavigationSplitView`. On wide screens (`useBreakpoint().isNarrow ===
|
|
2567
|
+
false`, > 400 dp) both panes render side by side, separated by a
|
|
2568
|
+
`Separator`. On narrow screens only one pane shows at a time; `showContent`
|
|
2569
|
+
switches between the sidebar list and the detail view.
|
|
2570
|
+
|
|
2571
|
+
The web version's `clamp(min, fraction * 100%, max)` sidebar width has no
|
|
2572
|
+
RN equivalent, so the container measures its own width via `onLayout` and
|
|
2573
|
+
the same clamp is computed in JS. Narrow-mode pane switching is animated
|
|
2574
|
+
(`translateX`) rather than an instant `display: 'none'` swap like
|
|
2575
|
+
`TabPanel` — both panes stay laid out and absolutely positioned, sliding
|
|
2576
|
+
via one shared `Animated.Value`, since RN `transform` has no
|
|
2577
|
+
percentage-of-self units to use a bare `-100%`/`100%` the way the web CSS
|
|
2578
|
+
does. The web's `inert` attribute (removes the hidden pane from the a11y
|
|
2579
|
+
tree and tab order while it stays mounted off-screen) has no single RN
|
|
2580
|
+
equivalent — reproduced with `accessibilityElementsHidden` +
|
|
2581
|
+
`importantForAccessibility="no-hide-descendants"` plus `pointerEvents="none"`
|
|
2582
|
+
so the off-screen pane can't intercept touches meant for the visible one.
|
|
2583
|
+
|
|
2513
2584
|
### FilterableMultiSelectDropdown
|
|
2514
2585
|
|
|
2515
2586
|
```tsx
|
|
@@ -2589,6 +2660,35 @@ two independent `accessibilityRole="adjustable"` elements (one per thumb),
|
|
|
2589
2660
|
the same VoiceOver/TalkBack increment/decrement analog `Slider` already
|
|
2590
2661
|
established.
|
|
2591
2662
|
|
|
2663
|
+
### RatingStars
|
|
2664
|
+
|
|
2665
|
+
```tsx
|
|
2666
|
+
import { RatingStars } from '@gnome-ui/react-native';
|
|
2667
|
+
|
|
2668
|
+
// Read-only — omit onChange
|
|
2669
|
+
<RatingStars value={4.2} accessibilityLabel="Average rating: 4.2 out of 5" />
|
|
2670
|
+
|
|
2671
|
+
// Interactive — pass onChange
|
|
2672
|
+
<RatingStars value={rating} onChange={setRating} />
|
|
2673
|
+
```
|
|
2674
|
+
|
|
2675
|
+
Star rating display and input — mirrors `@gnome-ui/react`'s `RatingStars`.
|
|
2676
|
+
Renders `role="radiogroup"` of `role="radio"` stars when `onChange` is
|
|
2677
|
+
provided, or a static `role="img"` when it isn't (e.g. showing an
|
|
2678
|
+
average/read-only rating); passing `disabled` always falls back to the
|
|
2679
|
+
read-only display even with `onChange` provided. The web version's
|
|
2680
|
+
`radiogroup` layer also owns an `onKeyDown` handler for arrow-key
|
|
2681
|
+
roving-tabindex navigation and a mouse-hover preview that doesn't commit
|
|
2682
|
+
until clicked — neither has a touch counterpart, so both drop, the same
|
|
2683
|
+
standing convention `ToggleGroup` already established for this package.
|
|
2684
|
+
What's left, tapping a star to commit that rating, is a strict subset of
|
|
2685
|
+
the web interaction rather than an approximation of it. Each star's fill
|
|
2686
|
+
uses `tintColor={theme.warningBgColor}` rather than `Icon`'s fixed
|
|
2687
|
+
`color="yellow"` — the source CSS reads `var(--gnome-warning-bg-color)`
|
|
2688
|
+
directly with no `color-mix()` darkening step, so the semantic warning
|
|
2689
|
+
token (already tracking dark mode and every contrast level) is the exact
|
|
2690
|
+
match, not an approximation through the fixed palette.
|
|
2691
|
+
|
|
2592
2692
|
### StatusBadge
|
|
2593
2693
|
|
|
2594
2694
|
```tsx
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, View, ViewStyle } from 'react-native';
|
|
3
|
+
export interface LinkedGroupProps {
|
|
4
|
+
/**
|
|
5
|
+
* Each child must accept and merge a `style` prop the way every
|
|
6
|
+
* `@gnome-ui/react-native` component already does (`style` last in its
|
|
7
|
+
* own internal style array) — see the component doc for why.
|
|
8
|
+
*/
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
/** Stack children vertically instead of horizontally. */
|
|
11
|
+
vertical?: boolean;
|
|
12
|
+
style?: StyleProp<ViewStyle>;
|
|
13
|
+
testID?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders children as a single visually-connected unit with no gap and
|
|
17
|
+
* merged borders — the canonical GNOME pattern for button groups and
|
|
18
|
+
* segmented inputs. Mirrors `@gnome-ui/react`'s `LinkedGroup`, itself
|
|
19
|
+
* mirroring the libadwaita `.linked` style class.
|
|
20
|
+
*
|
|
21
|
+
* The web version reaches every child's border-radius via a CSS
|
|
22
|
+
* `> *` universal child selector — RN has no equivalent way for a parent
|
|
23
|
+
* `View` to reach into an arbitrary child's own internally-computed
|
|
24
|
+
* styles. Reimagined instead as the same `cloneElement`-onto-children
|
|
25
|
+
* technique `Popover`/`Tooltip` already use on their own trigger:
|
|
26
|
+
* each child gets a computed corner-radius/negative-margin override
|
|
27
|
+
* merged onto whatever `style` it already has, using the same
|
|
28
|
+
* "zero the shared inner corners, keep `theme.radiusMd` on the outer
|
|
29
|
+
* ones, overlap by 1 dp to collapse the shared border" recipe
|
|
30
|
+
* `SplitButton` already proved for its own two-piece connected border —
|
|
31
|
+
* generalized here from a fixed two children to an arbitrary list. This
|
|
32
|
+
* only works because every component in this package already merges a
|
|
33
|
+
* passed-in `style` prop last, the same assumption `Popover`'s own
|
|
34
|
+
* trigger-cloning already depends on.
|
|
35
|
+
*
|
|
36
|
+
* The web CSS also raises a hovered/focused child's `z-index` so its own
|
|
37
|
+
* border isn't visually covered by the next sibling's overlapping edge —
|
|
38
|
+
* dropped here: RN is touch-first (no `:hover`), and no component in this
|
|
39
|
+
* package currently renders an escaping focus ring that overlap could
|
|
40
|
+
* clip, so there's nothing yet for the z-index bump to protect.
|
|
41
|
+
*
|
|
42
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1-latest/style-classes.html#linked-style-class
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* <LinkedGroup>
|
|
46
|
+
* <Button variant="flat">Bold</Button>
|
|
47
|
+
* <Button variant="flat">Italic</Button>
|
|
48
|
+
* </LinkedGroup>
|
|
49
|
+
*/
|
|
50
|
+
export declare const LinkedGroup: import('react').ForwardRefExoticComponent<LinkedGroupProps & import('react').RefAttributes<View>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
export interface NavigationSplitViewProps {
|
|
4
|
+
/**
|
|
5
|
+
* The sidebar / list pane (left side on wide screens).
|
|
6
|
+
* On narrow screens this is the "list" view shown when `showContent` is false.
|
|
7
|
+
*/
|
|
8
|
+
sidebar: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* The detail / content pane (right side on wide screens).
|
|
11
|
+
* On narrow screens this is the "detail" view shown when `showContent` is true.
|
|
12
|
+
*/
|
|
13
|
+
content: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Controls which pane is visible on narrow screens (≤ 400 dp).
|
|
16
|
+
* - `false` (default) — show the sidebar list.
|
|
17
|
+
* - `true` — show the content detail.
|
|
18
|
+
*
|
|
19
|
+
* Has no effect on wide screens where both panes are visible simultaneously.
|
|
20
|
+
*/
|
|
21
|
+
showContent?: boolean;
|
|
22
|
+
/** Minimum sidebar width in dp. Defaults to `180`. */
|
|
23
|
+
minSidebarWidth?: number;
|
|
24
|
+
/** Maximum sidebar width in dp. Defaults to `280`. */
|
|
25
|
+
maxSidebarWidth?: number;
|
|
26
|
+
/** Fraction of total width given to the sidebar (0–1). Defaults to `0.25`. */
|
|
27
|
+
sidebarWidthFraction?: number;
|
|
28
|
+
style?: StyleProp<ViewStyle>;
|
|
29
|
+
testID?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Two-pane sidebar + content layout following the Adwaita
|
|
33
|
+
* `AdwNavigationSplitView` pattern — mirrors `@gnome-ui/react`'s
|
|
34
|
+
* `NavigationSplitView`.
|
|
35
|
+
*
|
|
36
|
+
* On **wide** screens (`useBreakpoint().isNarrow === false`, > 400 dp) both
|
|
37
|
+
* panes are visible side-by-side, separated by a `Separator`. On **narrow**
|
|
38
|
+
* screens only one pane is shown at a time; `showContent` switches between
|
|
39
|
+
* the sidebar list and the detail view.
|
|
40
|
+
*
|
|
41
|
+
* The web version's `clamp(min, fraction * 100%, max)` sidebar width has no
|
|
42
|
+
* RN equivalent (`StyleSheet` values aren't CSS `calc`/`clamp` expressions),
|
|
43
|
+
* so the container measures its own width via `onLayout` and the same clamp
|
|
44
|
+
* is computed in JS — `0` until the first layout pass resolves, the same
|
|
45
|
+
* one-frame imprecision this package already accepts elsewhere (e.g.
|
|
46
|
+
* `ProgressBar`'s `trackWidth`-dependent math).
|
|
47
|
+
*
|
|
48
|
+
* Narrow-mode pane switching is animated (`translateX`, matching the web
|
|
49
|
+
* CSS's own `transition: transform`), so — unlike `TabPanel`'s simpler
|
|
50
|
+
* `display: 'none'` swap — both panes stay laid out and absolutely
|
|
51
|
+
* positioned rather than being removed from flow, using the same measured
|
|
52
|
+
* container width for the slide distance (RN `transform` has no
|
|
53
|
+
* percentage-of-self units, so this can't be a bare `-100%`/`100%` the way
|
|
54
|
+
* the web version's CSS is). One shared `Animated.Value` drives both
|
|
55
|
+
* panes' opposite-direction translation, the same "skip the animation on
|
|
56
|
+
* initial mount, only animate subsequent prop changes" guard `Switch`/
|
|
57
|
+
* `StepIndicator` already established for a controlled boolean prop.
|
|
58
|
+
*
|
|
59
|
+
* The web's `inert` attribute (removes the hidden pane from both the a11y
|
|
60
|
+
* tree and the tab order while it stays mounted off-screen) has no single
|
|
61
|
+
* RN equivalent — reproduced with `accessibilityElementsHidden` +
|
|
62
|
+
* `importantForAccessibility="no-hide-descendants"` (the whole-subtree a11y
|
|
63
|
+
* exclusion, not just the single-element `"no"` `PathBar`'s decorative
|
|
64
|
+
* separator uses) plus `pointerEvents="none"` so the off-screen pane can't
|
|
65
|
+
* intercept touches meant for the visible one.
|
|
66
|
+
*
|
|
67
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.NavigationSplitView.html
|
|
68
|
+
*/
|
|
69
|
+
export declare const NavigationSplitView: ({ sidebar, content, showContent, minSidebarWidth, maxSidebarWidth, sidebarWidthFraction, style, testID, }: NavigationSplitViewProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { IconSize } from '../Icon';
|
|
3
|
+
export interface RatingStarsProps {
|
|
4
|
+
/** Current rating, between `0` and `max`. */
|
|
5
|
+
value: number;
|
|
6
|
+
/** Number of stars. Defaults to `5`. */
|
|
7
|
+
max?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Called when the user picks a rating. Omit to render a read-only
|
|
10
|
+
* display (e.g. an average rating) instead of an interactive input.
|
|
11
|
+
*/
|
|
12
|
+
onChange?: (value: number) => void;
|
|
13
|
+
/** Star size. Defaults to `"md"`. */
|
|
14
|
+
size?: IconSize;
|
|
15
|
+
/** Renders as read-only even when `onChange` is provided. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** Accessible label. Defaults to `"Rating"` (interactive) or a generated `"N out of M stars"` (read-only). */
|
|
18
|
+
accessibilityLabel?: string;
|
|
19
|
+
style?: StyleProp<ViewStyle>;
|
|
20
|
+
testID?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Star rating display and input. Mirrors `@gnome-ui/react`'s `RatingStars`.
|
|
24
|
+
*
|
|
25
|
+
* Renders `role="radiogroup"` of `role="radio"` stars when `onChange` is
|
|
26
|
+
* provided, or a static `role="img"` when it isn't — e.g. for showing an
|
|
27
|
+
* average/read-only rating.
|
|
28
|
+
*
|
|
29
|
+
* The web version's `role="radiogroup"` layer also owns an `onKeyDown`
|
|
30
|
+
* handler for arrow-key roving-tabindex navigation and a mouse-hover
|
|
31
|
+
* preview that doesn't commit until clicked; neither has a touch
|
|
32
|
+
* counterpart, so both drop — same standing convention `ToggleGroup`
|
|
33
|
+
* already established for this package (its own doc comment covers the
|
|
34
|
+
* reasoning). What's left, tapping a star to commit that rating, is a
|
|
35
|
+
* strict subset of the web interaction, not an approximation of it.
|
|
36
|
+
*
|
|
37
|
+
* Each star's fill color is `tintColor={theme.warningBgColor}` rather than
|
|
38
|
+
* `Icon`'s own fixed `color="yellow"` (→ `theme.yellow4`, a different hex):
|
|
39
|
+
* the source CSS reads `var(--gnome-warning-bg-color, #f6d32d)` directly
|
|
40
|
+
* with no `color-mix()` darkening step, so the semantic warning token
|
|
41
|
+
* itself — already tracking dark mode and every contrast level — is the
|
|
42
|
+
* exact match, not an approximation through the fixed palette. Stars carry
|
|
43
|
+
* no `label` on `Icon` (decorative — `iconAccessibilityProps` already hides
|
|
44
|
+
* an unlabeled icon from the tree); the accessible name lives on the
|
|
45
|
+
* container (read-only) or each `Pressable` (interactive) instead, mirroring
|
|
46
|
+
* `ToggleGroupItem`'s icon-only items.
|
|
47
|
+
*/
|
|
48
|
+
export declare const RatingStars: ({ value, max, onChange, size, disabled, accessibilityLabel, style, testID, }: RatingStarsProps) => import("react/jsx-runtime").JSX.Element;
|