@vvedantb/native-ui 0.3.17 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +146 -13
  2. package/package.json +10 -2
  3. package/src/CaptureButton.tsx +62 -0
  4. package/src/Card.tsx +37 -13
  5. package/src/ColorSwatches.tsx +133 -0
  6. package/src/DateTimeField.tsx +75 -19
  7. package/src/HeaderIconButton.tsx +18 -1
  8. package/src/IconButton.tsx +87 -0
  9. package/src/ListRow.tsx +104 -30
  10. package/src/PageIndicator.tsx +87 -0
  11. package/src/SectionLabel.tsx +48 -0
  12. package/src/SheetRow.tsx +89 -0
  13. package/src/StackPageHeader.tsx +100 -0
  14. package/src/StatGrid.tsx +80 -0
  15. package/src/StatusDot.tsx +14 -1
  16. package/src/ThemeToggle.tsx +17 -5
  17. package/src/ai/activity-step.tsx +57 -0
  18. package/src/ai/attachments.tsx +153 -0
  19. package/src/ai/chain-of-thought.tsx +143 -0
  20. package/src/ai/chat-text.ts +35 -0
  21. package/src/ai/code-block.tsx +104 -0
  22. package/src/ai/collapsible.tsx +111 -0
  23. package/src/ai/conversation.tsx +245 -0
  24. package/src/ai/file-chip.tsx +66 -0
  25. package/src/ai/icon-button.tsx +51 -0
  26. package/src/ai/index.ts +123 -0
  27. package/src/ai/message.tsx +146 -0
  28. package/src/ai/prompt-input.tsx +186 -0
  29. package/src/ai/reasoning.tsx +200 -0
  30. package/src/ai/response-text.tsx +56 -0
  31. package/src/ai/shimmer.tsx +86 -0
  32. package/src/ai/sources.tsx +100 -0
  33. package/src/ai/suggestion.tsx +93 -0
  34. package/src/ai/trace.tsx +234 -0
  35. package/src/ai/use-streaming-disclosure.ts +50 -0
  36. package/src/entries/ai.ts +4 -0
  37. package/src/entries/date-time.ts +1 -0
  38. package/src/entries/layout.ts +6 -2
  39. package/src/entries/page-title.ts +7 -2
  40. package/src/entries/primitives.ts +19 -1
  41. package/src/examples/AiChatGallery.tsx +233 -0
  42. package/src/examples/ParityGallery.tsx +205 -3
  43. package/src/index.ts +19 -0
@@ -0,0 +1,100 @@
1
+ import { Linking, Pressable, View, type ViewProps } from "react-native";
2
+ import { IconBook } from "@tabler/icons-react-native";
3
+ import { cn } from "../cn";
4
+ import { MIN_TOUCH_TARGET, touchSlop } from "../controlStyles";
5
+ import { useLargerText } from "../theme";
6
+ import { tokens } from "../tokens";
7
+ import { useScheme } from "../useScheme";
8
+ import {
9
+ Collapsible,
10
+ CollapsibleChevron,
11
+ CollapsibleContent,
12
+ CollapsibleTrigger,
13
+ useCollapsible,
14
+ type CollapsibleProps,
15
+ type CollapsibleTriggerProps,
16
+ } from "./collapsible";
17
+ import { ResponseText } from "./response-text";
18
+
19
+ /** The sources a reply used, folded (default closed). */
20
+ export function Sources({ className, ...props }: CollapsibleProps) {
21
+ return <Collapsible className={cn("w-full", className)} {...props} />;
22
+ }
23
+
24
+ /** "Used 1 source", "Used 3 sources". */
25
+ export function sourcesLabel(count: number) {
26
+ return `Used ${count} ${count === 1 ? "source" : "sources"}`;
27
+ }
28
+
29
+ export type SourcesTriggerProps = Omit<CollapsibleTriggerProps, "children"> & {
30
+ count: number;
31
+ };
32
+
33
+ /** Book icon, "Used 3 sources" and a chevron, muted (web `text-xs`, here `text-sm`). */
34
+ export function SourcesTrigger({ count, className, ...props }: SourcesTriggerProps) {
35
+ const { open } = useCollapsible();
36
+ const scheme = useScheme();
37
+ const largerText = useLargerText();
38
+ const muted = tokens.color.muted[scheme];
39
+ const iconSize = largerText ? 18 : 14;
40
+ const label = sourcesLabel(count);
41
+ return (
42
+ <CollapsibleTrigger
43
+ accessibilityLabel={label}
44
+ className={cn("flex-row items-center gap-1.5 self-start", className)}
45
+ {...props}
46
+ >
47
+ <IconBook size={iconSize} color={muted} strokeWidth={1.5} />
48
+ <ResponseText size="small" tone="muted" selectable={false}>
49
+ {label}
50
+ </ResponseText>
51
+ <CollapsibleChevron open={open} size={iconSize} color={muted} />
52
+ </CollapsibleTrigger>
53
+ );
54
+ }
55
+
56
+ /** The list of `Source` rows, shown while open (web `mt-2 space-y-2`). */
57
+ export function SourcesContent({ className, ...props }: ViewProps & { className?: string }) {
58
+ return <CollapsibleContent className={cn("mt-2 gap-2", className)} {...props} />;
59
+ }
60
+
61
+ export type SourceProps = {
62
+ href: string;
63
+ /** Shown, and read, in place of the address. */
64
+ title?: string;
65
+ /** Default: `Linking.openURL(href)`, the system browser or the app that owns the link. */
66
+ onPress?: (href: string) => void;
67
+ testID?: string;
68
+ };
69
+
70
+ /** A `text-sm` line with the web `py-2`: 36 high. The slop brings it to 44. */
71
+ const ROW_HEIGHT = 36;
72
+
73
+ /**
74
+ * One source as a link row: title (or address) on one line and a book icon.
75
+ * Pressed, it takes the web hover fill (`bg-surface-secondary`).
76
+ */
77
+ export function Source({ href, title, onPress, testID }: SourceProps) {
78
+ const scheme = useScheme();
79
+ const largerText = useLargerText();
80
+ const label = title ?? href;
81
+ return (
82
+ <Pressable
83
+ testID={testID}
84
+ accessibilityRole="link"
85
+ accessibilityLabel={label}
86
+ hitSlop={touchSlop(MIN_TOUCH_TARGET, ROW_HEIGHT)}
87
+ onPress={() => (onPress ? onPress(href) : void Linking.openURL(href))}
88
+ className="flex-row items-center justify-between gap-2 px-3 py-2"
89
+ style={({ pressed }) => ({
90
+ borderRadius: tokens.radius.md,
91
+ backgroundColor: pressed ? tokens.color.surfaceSecondary[scheme] : "transparent",
92
+ })}
93
+ >
94
+ <ResponseText size="small" tone="muted" selectable={false} numberOfLines={1} className="shrink">
95
+ {label}
96
+ </ResponseText>
97
+ <IconBook size={largerText ? 18 : 14} color={tokens.color.muted[scheme]} strokeWidth={1.5} />
98
+ </Pressable>
99
+ );
100
+ }
@@ -0,0 +1,93 @@
1
+ import type { ReactNode } from "react";
2
+ import { Pressable, ScrollView, Text, View } from "react-native";
3
+ import { cn } from "../cn";
4
+ import { MIN_TOUCH_TARGET, sizeStyle, textStyle, touchSlop } from "../controlStyles";
5
+ import { palette } from "../palette";
6
+ import { useLargerText } from "../theme";
7
+ import { tokens } from "../tokens";
8
+ import { useScheme } from "../useScheme";
9
+ import { chatTextSize } from "./chat-text";
10
+
11
+ export type SuggestionsProps = {
12
+ /** `horizontal` (default) scrolls one row of chips; `vertical` stacks them full width. */
13
+ orientation?: "horizontal" | "vertical";
14
+ className?: string;
15
+ /** Classes for the horizontal row inside the scroll view, after the web `gap-2 px-1`. */
16
+ contentContainerClassName?: string;
17
+ children?: ReactNode;
18
+ };
19
+
20
+ /**
21
+ * Prompt suggestions. Horizontal is a `ScrollView` with no scroll bar (the web
22
+ * row with its scroll arrows; a phone swipes instead).
23
+ */
24
+ export function Suggestions({
25
+ orientation = "horizontal",
26
+ className,
27
+ contentContainerClassName,
28
+ children,
29
+ }: SuggestionsProps) {
30
+ if (orientation === "vertical") {
31
+ return <View className={cn("w-full gap-2", className)}>{children}</View>;
32
+ }
33
+ return (
34
+ <ScrollView
35
+ horizontal
36
+ showsHorizontalScrollIndicator={false}
37
+ keyboardShouldPersistTaps="handled"
38
+ className={cn("w-full grow-0", className)}
39
+ contentContainerClassName={cn("items-center gap-2 px-1", contentContainerClassName)}
40
+ >
41
+ {children}
42
+ </ScrollView>
43
+ );
44
+ }
45
+
46
+ export type SuggestionProps = {
47
+ suggestion: string;
48
+ onPress?: (suggestion: string) => void;
49
+ /** Replaces the text; the accessibility label stays `suggestion`. */
50
+ children?: string;
51
+ disabled?: boolean;
52
+ testID?: string;
53
+ };
54
+
55
+ /** A `text-sm` line with the web `py-1.5`: 32 high. The slop brings it to 44. */
56
+ const CHIP_HEIGHT = 32;
57
+
58
+ /**
59
+ * A round chip with the web suggestion look: `rounded-full border
60
+ * bg-surface-secondary px-3 py-1.5 text-sm text-muted-foreground`. Pressed,
61
+ * it takes the web hover (`bg-surface-tertiary text-foreground`).
62
+ */
63
+ export function Suggestion({ suggestion, onPress, children, disabled, testID }: SuggestionProps) {
64
+ const scheme = useScheme();
65
+ const largerText = useLargerText();
66
+ const size = chatTextSize("small", largerText);
67
+ return (
68
+ <Pressable
69
+ testID={testID}
70
+ accessibilityRole="button"
71
+ accessibilityLabel={suggestion}
72
+ accessibilityState={{ disabled: Boolean(disabled) }}
73
+ disabled={disabled}
74
+ hitSlop={touchSlop(MIN_TOUCH_TARGET, CHIP_HEIGHT)}
75
+ onPress={() => onPress?.(suggestion)}
76
+ className={cn("justify-center border", largerText ? "min-h-12 px-4 py-2" : "min-h-8 px-3 py-1.5", disabled && "opacity-45")}
77
+ style={({ pressed }) => ({
78
+ borderRadius: tokens.radius.pill,
79
+ borderColor: tokens.color.border[scheme],
80
+ backgroundColor: pressed ? palette.surfaceTertiary[scheme] : tokens.color.surfaceSecondary[scheme],
81
+ })}
82
+ >
83
+ {({ pressed }) => (
84
+ <Text
85
+ className={cn(size, "font-instrument-sans")}
86
+ style={[sizeStyle(size), textStyle(pressed ? "foreground" : "muted", scheme)]}
87
+ >
88
+ {children ?? suggestion}
89
+ </Text>
90
+ )}
91
+ </Pressable>
92
+ );
93
+ }
@@ -0,0 +1,234 @@
1
+ import { createContext, useContext, type ComponentType, type ReactNode } from "react";
2
+ import { Pressable, Text, View, type ViewProps } from "react-native";
3
+ import type { IconProps } from "@tabler/icons-react-native";
4
+ import { cn } from "../cn";
5
+ import { sizeStyle, touchSlop } from "../controlStyles";
6
+ import { palette } from "../palette";
7
+ import { useLargerText } from "../theme";
8
+ import { tokens } from "../tokens";
9
+ import { useScheme } from "../useScheme";
10
+ import { chatTextSize } from "./chat-text";
11
+ import {
12
+ Collapsible,
13
+ CollapsibleChevron,
14
+ CollapsibleContent,
15
+ CollapsibleTrigger,
16
+ useCollapsible,
17
+ type CollapsibleProps,
18
+ type CollapsibleTriggerProps,
19
+ } from "./collapsible";
20
+ import { ResponseText } from "./response-text";
21
+ import { Shimmer } from "./shimmer";
22
+
23
+ // One agent step as one line: icon, title, optional faded description and an
24
+ // optional fold. Reasoning, tool calls, grouped calls and to-dos can all
25
+ // render through these parts, as on the web (`trace.tsx`). The web icon
26
+ // crossfade (`iconKey`) is not ported: the icon swaps at once.
27
+
28
+ export type AgentTraceStatus = "running" | "error" | "pending";
29
+
30
+ /** Text and icon colour of a line: muted, or the danger colour for an error (web `text-destructive`). */
31
+ export function traceLineColor(status: AgentTraceStatus | undefined, scheme: "light" | "dark") {
32
+ return status === "error" ? palette.danger[scheme] : tokens.color.muted[scheme];
33
+ }
34
+
35
+ // Native text and icons do not inherit a colour, so the line hands its own down.
36
+ const TraceLineColorContext = createContext<string | undefined>(undefined);
37
+
38
+ function useTraceColor() {
39
+ const scheme = useScheme();
40
+ return useContext(TraceLineColorContext) ?? tokens.color.muted[scheme];
41
+ }
42
+
43
+ /** A column of trace lines (web `flex w-full flex-col gap-2`). */
44
+ export function AgentTrace({ className, ...props }: ViewProps & { className?: string }) {
45
+ return <View className={cn("w-full min-w-0 gap-2", className)} {...props} />;
46
+ }
47
+
48
+ export type AgentTraceLineProps = ViewProps & {
49
+ status?: AgentTraceStatus;
50
+ className?: string;
51
+ };
52
+
53
+ /** One line: a row of icon, title and description. `pending` fades it to 60%, `error` turns it the danger colour. */
54
+ export function AgentTraceLine({ status, className, style, ...props }: AgentTraceLineProps) {
55
+ const scheme = useScheme();
56
+ return (
57
+ <TraceLineColorContext.Provider value={traceLineColor(status, scheme)}>
58
+ <View
59
+ className={cn("min-w-0 max-w-full shrink flex-row items-center gap-2", className)}
60
+ style={[status === "pending" ? { opacity: 0.6 } : null, style]}
61
+ {...props}
62
+ />
63
+ </TraceLineColorContext.Provider>
64
+ );
65
+ }
66
+
67
+ export type AgentTraceIconProps = {
68
+ /** A Tabler icon, drawn 16 (20 with larger text) in the line colour. */
69
+ icon?: ComponentType<IconProps>;
70
+ /** Anything else in the 16 box, such as a `Spinner size="sm"`. */
71
+ children?: ReactNode;
72
+ className?: string;
73
+ };
74
+
75
+ /** The 16 icon box at the start of a line. Hidden from assistive tech, as the web `aria-hidden`. */
76
+ export function AgentTraceIcon({ icon: Icon, children, className }: AgentTraceIconProps) {
77
+ const color = useTraceColor();
78
+ const largerText = useLargerText();
79
+ const size = largerText ? 20 : 16;
80
+ return (
81
+ <View
82
+ accessibilityElementsHidden
83
+ importantForAccessibility="no-hide-descendants"
84
+ className={cn("shrink-0 items-center justify-center", className)}
85
+ style={{ width: size, height: size }}
86
+ >
87
+ {Icon ? <Icon size={size} color={color} /> : children}
88
+ </View>
89
+ );
90
+ }
91
+
92
+ export type AgentTraceTitleProps = {
93
+ children: string;
94
+ /** Pulse the title while the step runs (`Shimmer`). */
95
+ shimmer?: boolean;
96
+ className?: string;
97
+ };
98
+
99
+ /** The step title, on one line, cut off at the end. */
100
+ export function AgentTraceTitle({ children, shimmer = false, className }: AgentTraceTitleProps) {
101
+ const color = useTraceColor();
102
+ const largerText = useLargerText();
103
+ if (shimmer) {
104
+ return (
105
+ <Shimmer duration={2.5} numberOfLines={1} className={className}>
106
+ {children}
107
+ </Shimmer>
108
+ );
109
+ }
110
+ const size = chatTextSize("small", largerText);
111
+ return (
112
+ <Text
113
+ numberOfLines={1}
114
+ className={cn(size, "min-w-0 shrink font-instrument-sans", className)}
115
+ style={[sizeStyle(size), { color }]}
116
+ >
117
+ {children}
118
+ </Text>
119
+ );
120
+ }
121
+
122
+ /** Faded detail after the title, such as "3 files" or "12s", in tabular figures (web `opacity-70 tabular-nums`). */
123
+ export function AgentTraceDescription({ children, className }: { children: ReactNode; className?: string }) {
124
+ const color = useTraceColor();
125
+ const largerText = useLargerText();
126
+ const size = chatTextSize("small", largerText);
127
+ return (
128
+ <Text
129
+ numberOfLines={1}
130
+ className={cn(size, "shrink-0 font-instrument-sans", className)}
131
+ style={[sizeStyle(size), { color, opacity: 0.7, fontVariant: ["tabular-nums"] }]}
132
+ >
133
+ {children}
134
+ </Text>
135
+ );
136
+ }
137
+
138
+ /** A line with a fold (web `flex w-full min-w-0 flex-col`). Spread `useStreamingDisclosure(isStreaming)` on it to follow a stream. */
139
+ export function AgentTraceCollapsible({ className, ...props }: CollapsibleProps) {
140
+ return <Collapsible className={cn("w-full min-w-0", className)} {...props} />;
141
+ }
142
+
143
+ export type AgentTraceCollapsibleTriggerProps = CollapsibleTriggerProps & {
144
+ /**
145
+ * Controls of their own (a pressable `FileChip`), drawn after the line and
146
+ * outside the trigger, as on the web, so each keeps its own press and
147
+ * accessibility label.
148
+ */
149
+ trailing?: ReactNode;
150
+ };
151
+
152
+ /** The line as a toggle, with a chevron after it that turns down when open. */
153
+ export function AgentTraceCollapsibleTrigger({
154
+ children,
155
+ trailing,
156
+ className,
157
+ ...props
158
+ }: AgentTraceCollapsibleTriggerProps) {
159
+ const { open, setOpen } = useCollapsible();
160
+ const scheme = useScheme();
161
+ const largerText = useLargerText();
162
+ const iconSize = largerText ? 20 : 16;
163
+ const chevron = (
164
+ <CollapsibleChevron open={open} variant="right" size={iconSize} color={tokens.color.muted[scheme]} />
165
+ );
166
+ if (trailing === undefined) {
167
+ return (
168
+ <CollapsibleTrigger
169
+ className={cn("max-w-full flex-row items-center gap-1 self-start", className)}
170
+ {...props}
171
+ >
172
+ {children}
173
+ {chevron}
174
+ </CollapsibleTrigger>
175
+ );
176
+ }
177
+ return (
178
+ <View className={cn("max-w-full flex-row items-center gap-2 self-start", className)}>
179
+ <CollapsibleTrigger className="min-w-0 shrink flex-row items-center" {...props}>
180
+ {children}
181
+ </CollapsibleTrigger>
182
+ {trailing}
183
+ {/* The chevron toggles too, as the web overlay makes the whole line press. The trigger already names the fold. */}
184
+ <Pressable
185
+ accessible={false}
186
+ importantForAccessibility="no-hide-descendants"
187
+ hitSlop={touchSlop(iconSize)}
188
+ onPress={() => setOpen(!open)}
189
+ >
190
+ {chevron}
191
+ </Pressable>
192
+ </View>
193
+ );
194
+ }
195
+
196
+ /**
197
+ * The folded body, indented behind a rail that starts under the centre of the
198
+ * line icon (web `ml-[calc(--spacing(2)-1px)] border-l pl-4`). A string child
199
+ * is drawn as muted `ResponseText`.
200
+ */
201
+ export function AgentTraceCollapsibleContent({
202
+ children,
203
+ className,
204
+ style,
205
+ ...props
206
+ }: ViewProps & { className?: string }) {
207
+ const scheme = useScheme();
208
+ const largerText = useLargerText();
209
+ const iconSize = largerText ? 20 : 16;
210
+ return (
211
+ <CollapsibleContent>
212
+ <View
213
+ className={cn("mb-1 mt-2 min-w-0 pl-4 pr-1", className)}
214
+ style={[
215
+ {
216
+ marginLeft: iconSize / 2 - 1,
217
+ borderLeftWidth: 1,
218
+ borderLeftColor: tokens.color.border[scheme],
219
+ },
220
+ style,
221
+ ]}
222
+ {...props}
223
+ >
224
+ {typeof children === "string" ? (
225
+ <ResponseText size="small" tone="muted">
226
+ {children}
227
+ </ResponseText>
228
+ ) : (
229
+ children
230
+ )}
231
+ </View>
232
+ </CollapsibleContent>
233
+ );
234
+ }
@@ -0,0 +1,50 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ const AUTO_CLOSE_DELAY_MS = 1000;
4
+
5
+ /**
6
+ * Open state for a fold that follows a live stream: it opens when streaming
7
+ * starts so the text is readable as it lands, and closes once, a second after
8
+ * streaming stops. A reader's own toggle cancels a pending auto-close. A port
9
+ * of the web `useStreamingDisclosure`; spread the result on a `Collapsible`
10
+ * or `AgentTraceCollapsible`.
11
+ */
12
+ export function useStreamingDisclosure(isStreaming: boolean): {
13
+ open: boolean;
14
+ onOpenChange: (open: boolean) => void;
15
+ } {
16
+ const [open, setOpen] = useState(isStreaming);
17
+ const [wasStreaming, setWasStreaming] = useState(isStreaming);
18
+ const [closeDue, setCloseDue] = useState(false);
19
+
20
+ // Adjusting state while rendering, as on the web: no extra commit with the
21
+ // old open state.
22
+ if (isStreaming !== wasStreaming) {
23
+ setWasStreaming(isStreaming);
24
+ if (isStreaming) {
25
+ setOpen(true);
26
+ setCloseDue(false);
27
+ } else {
28
+ setCloseDue(true);
29
+ }
30
+ }
31
+
32
+ // The close is a delayed reaction to the stream stopping, not to a press:
33
+ // only a timer can express "one second later".
34
+ useEffect(() => {
35
+ if (!closeDue) return;
36
+ const timer = setTimeout(() => {
37
+ setOpen(false);
38
+ setCloseDue(false);
39
+ }, AUTO_CLOSE_DELAY_MS);
40
+ return () => clearTimeout(timer);
41
+ }, [closeDue]);
42
+
43
+ return {
44
+ open,
45
+ onOpenChange: (next) => {
46
+ setCloseDue(false);
47
+ setOpen(next);
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,4 @@
1
+ // `@vvedantb/native-ui/ai`: the AI chat parts. Reaches no optional peer, not
2
+ // even a loader; the composer uses `react-native-safe-area-context` and the
3
+ // shimmer `react-native-reanimated`, both required peers.
4
+ export * from "../ai";
@@ -1,3 +1,4 @@
1
1
  // `@vvedantb/native-ui/date-time`. Imports
2
2
  // `@react-native-community/datetimepicker` and `dayjs`.
3
3
  export { DateTimeField } from "../DateTimeField";
4
+ export type { DateTimeFieldProps } from "../DateTimeField";
@@ -1,9 +1,13 @@
1
- // `@vvedantb/native-ui/layout`: screen containers, page headers and settings
2
- // chrome.
1
+ // `@vvedantb/native-ui/layout`: screen containers, page headers, section
2
+ // labels and settings chrome.
3
3
  export { SafeAreaContainer } from "../SafeAreaContainer";
4
4
  export { ScreenContainer } from "../ScreenContainer";
5
5
  export { PageTitle, PageHeader } from "../PageTitle";
6
6
  export type { PageTitleProps, PageHeaderProps } from "../PageTitle";
7
+ export { StackPageHeader } from "../StackPageHeader";
8
+ export type { StackPageHeaderProps } from "../StackPageHeader";
9
+ export { SectionLabel } from "../SectionLabel";
10
+ export type { SectionLabelProps } from "../SectionLabel";
7
11
  export { SettingsSection } from "../settings/SettingsSection";
8
12
  export { SettingsField } from "../settings/SettingsField";
9
13
  export { SettingsToggleRow } from "../settings/SettingsToggleRow";
@@ -1,4 +1,9 @@
1
- // `@vvedantb/native-ui/page-title`: `PageTitle` and `PageHeader` on their own.
2
- // Reaches no optional peer, not even a loader.
1
+ // `@vvedantb/native-ui/page-title`: `PageTitle`, `PageHeader` and (from 0.5.0)
2
+ // `StackPageHeader`. Reaches no optional peer, not even a loader.
3
+ // `StackPageHeader` imports one Tabler icon (a required peer) for its back
4
+ // button; Metro does not tree-shake by default, so that bundles the Tabler
5
+ // package with this entry.
3
6
  export { PageTitle, PageHeader } from "../PageTitle";
4
7
  export type { PageTitleProps, PageHeaderProps } from "../PageTitle";
8
+ export { StackPageHeader } from "../StackPageHeader";
9
+ export type { StackPageHeaderProps } from "../StackPageHeader";
@@ -1,6 +1,8 @@
1
1
  // `@vvedantb/native-ui/primitives`: fields, display, tabs, overlays and
2
2
  // toasts. `BottomSheetContainer`, `DateTimeField` and `AmbientBackground` are
3
- // not here; they have their own entries.
3
+ // not here; they have their own entries. `Text` and `TextClassContext` are the
4
+ // `primitives/text` variants (from 0.5.0); they are not on the root entry.
5
+ export { Text, TextClassContext } from "../primitives/text";
4
6
  export { Button } from "../Button";
5
7
  export type { ButtonProps, ButtonSize, ButtonVariant } from "../Button";
6
8
  export { Input } from "../Input";
@@ -23,6 +25,20 @@ export { Badge } from "../Badge";
23
25
  export type { BadgeProps, BadgeVariant } from "../Badge";
24
26
  export { StatusDot } from "../StatusDot";
25
27
  export type { StatusDotProps, StatusTone } from "../StatusDot";
28
+ export { ColorSwatches } from "../ColorSwatches";
29
+ export type { ColorSwatchesProps, ColorSwatchesSize } from "../ColorSwatches";
30
+ export { StatGrid } from "../StatGrid";
31
+ export type { StatGridItem, StatGridProps } from "../StatGrid";
32
+ export { SectionLabel } from "../SectionLabel";
33
+ export type { SectionLabelProps } from "../SectionLabel";
34
+ export { SheetRow } from "../SheetRow";
35
+ export type { SheetRowProps } from "../SheetRow";
36
+ export { PageIndicator } from "../PageIndicator";
37
+ export type { PageIndicatorProps } from "../PageIndicator";
38
+ export { IconButton } from "../IconButton";
39
+ export type { IconButtonProps, IconButtonSize, IconButtonVariant } from "../IconButton";
40
+ export { CaptureButton } from "../CaptureButton";
41
+ export type { CaptureButtonProps } from "../CaptureButton";
26
42
  export { Separator } from "../Separator";
27
43
  export type { SeparatorProps } from "../Separator";
28
44
  export { Progress } from "../Progress";
@@ -43,6 +59,7 @@ export type {
43
59
  TabsContentProps,
44
60
  } from "../Tabs";
45
61
  export { ListRow } from "../ListRow";
62
+ export type { ListRowProps } from "../ListRow";
46
63
  export { HeaderIconButton } from "../HeaderIconButton";
47
64
  export { ThemeToggle } from "../ThemeToggle";
48
65
  export type { ThemeToggleProps } from "../ThemeToggle";
@@ -54,6 +71,7 @@ export {
54
71
  CardContent,
55
72
  CardFooter,
56
73
  } from "../Card";
74
+ export type { CardProps } from "../Card";
57
75
  export { Skeleton, CardSkeleton } from "../Skeleton";
58
76
  export { EmptyState } from "../EmptyState";
59
77
  export type { EmptyStateVariant } from "../EmptyState";