@vvedantb/native-ui 0.2.0 → 0.3.12
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 +160 -9
- package/package.json +88 -8
- package/src/AlertDialog.tsx +73 -0
- package/src/AmbientBackground.tsx +26 -11
- package/src/Avatar.tsx +141 -0
- package/src/Badge.tsx +108 -0
- package/src/BottomSheetContainer.tsx +7 -1
- package/src/Button.tsx +153 -52
- package/src/Card.tsx +111 -36
- package/src/Checkbox.tsx +78 -0
- package/src/Chip.tsx +5 -3
- package/src/ConfirmDialog.tsx +105 -0
- package/src/DateTimeField.tsx +6 -2
- package/src/Dialog.tsx +253 -0
- package/src/EmptyState.tsx +122 -7
- package/src/FloatingFAB.tsx +2 -4
- package/src/FloatingSurface.tsx +31 -9
- package/src/FloatingTabBar.tsx +39 -11
- package/src/Input.tsx +15 -4
- package/src/Label.tsx +31 -0
- package/src/LabeledSwitchRow.tsx +96 -0
- package/src/LiquidGlass.tsx +2 -10
- package/src/ListRow.tsx +7 -2
- package/src/PillTabs.tsx +28 -14
- package/src/Progress.tsx +67 -0
- package/src/SearchInput.tsx +163 -0
- package/src/Select.tsx +32 -6
- package/src/Separator.tsx +38 -0
- package/src/Sheet.tsx +107 -0
- package/src/Skeleton.tsx +25 -5
- package/src/Spinner.tsx +92 -0
- package/src/StatusDot.tsx +66 -0
- package/src/Switch.tsx +24 -7
- package/src/Tabs.tsx +190 -0
- package/src/Textarea.tsx +47 -0
- package/src/Toast.tsx +170 -0
- package/src/blur.ts +48 -0
- package/src/brand/AppIcons.tsx +106 -0
- package/src/brand/AppMark.tsx +83 -0
- package/src/brand/AppWordmark.tsx +97 -0
- package/src/brand/familyApps.ts +24 -0
- package/src/brand/index.ts +34 -0
- package/src/brand/svg.ts +263 -0
- package/src/brand/vProAppBenefits.ts +22 -0
- package/src/controlStyles.ts +360 -0
- package/src/dialogLayout.ts +20 -0
- package/src/entries/ambient.ts +3 -0
- package/src/entries/bottom-sheet.ts +2 -0
- package/src/entries/brand.ts +2 -0
- package/src/entries/button.ts +3 -0
- package/src/entries/date-time.ts +3 -0
- package/src/entries/floating.ts +24 -0
- package/src/entries/layout.ts +7 -0
- package/src/entries/marketing.ts +10 -0
- package/src/entries/primitives.ts +99 -0
- package/src/entries/search-input.ts +4 -0
- package/src/entries/tab-bar.ts +10 -0
- package/src/entries/theme.ts +15 -0
- package/src/entries/toast.ts +6 -0
- package/src/examples/ParityGallery.tsx +496 -0
- package/src/floating.ts +5 -1
- package/src/glassBlur.tsx +95 -0
- package/src/gradient.ts +21 -0
- package/src/haptics.ts +22 -2
- package/src/index.ts +99 -2
- package/src/initials.ts +10 -0
- package/src/marketing/PricingModal.tsx +410 -0
- package/src/marketing/UpgradeToProCard.tsx +103 -0
- package/src/marketing/pricing.ts +76 -0
- package/src/palette.ts +43 -0
- package/src/primitives/input.tsx +9 -2
- package/src/primitives/native-only-animated-view.tsx +10 -3
- package/src/primitives/overlay.tsx +179 -0
- package/src/primitives/select.tsx +25 -12
- package/src/primitives/switch.tsx +12 -13
- package/src/primitives/use-controllable-state.ts +24 -0
- package/src/settings/SettingsField.tsx +11 -2
- package/src/settings/SettingsSection.tsx +20 -6
- package/src/settings/SettingsToggleRow.tsx +7 -2
- package/src/tabBarRoutes.ts +52 -0
- package/src/toastChrome.ts +103 -0
- package/src/toastStore.ts +86 -0
- package/src/tokens.ts +19 -14
- package/src/typography.ts +24 -0
- package/src/useReduceMotion.ts +24 -0
- package/src/useScheme.ts +6 -0
package/src/floating.ts
CHANGED
|
@@ -5,7 +5,11 @@ export const FLOATING_INSET = tokens.spacing.unit;
|
|
|
5
5
|
export const FLOATING_TAB_BAR_HEIGHT = 64;
|
|
6
6
|
export const FLOATING_TAB_BAR_HEIGHT_LARGE = 72;
|
|
7
7
|
export const FLOATING_RADIUS = tokens.radius.card;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* List rows: 20, the field radius before 0.3.3 (web fields are 10). Toasts
|
|
10
|
+
* used it until 0.3.12 and the upgrade card until 0.3.8; both are 16 now.
|
|
11
|
+
*/
|
|
12
|
+
export const FLOATING_ROW_RADIUS = 20;
|
|
9
13
|
export const FLOATING_PILL_RADIUS = tokens.radius.pill;
|
|
10
14
|
|
|
11
15
|
const FLOATING_BOX_SHADOW = "0px 8px 24px rgba(10, 10, 10, 0.12)";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type ComponentRef,
|
|
9
|
+
type Dispatch,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
type RefObject,
|
|
12
|
+
type SetStateAction,
|
|
13
|
+
} from "react";
|
|
14
|
+
import { StyleSheet, View, type ViewProps } from "react-native";
|
|
15
|
+
import { loadBlur } from "./blur";
|
|
16
|
+
|
|
17
|
+
type BlurTargetRef = RefObject<ComponentRef<typeof View> | null>;
|
|
18
|
+
|
|
19
|
+
type GlassBlurContextValue = {
|
|
20
|
+
target: BlurTargetRef | null;
|
|
21
|
+
setTarget: Dispatch<SetStateAction<BlurTargetRef | null>> | null;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const NO_TARGET: GlassBlurContextValue = { target: null, setTarget: null };
|
|
25
|
+
|
|
26
|
+
const GlassBlurContext = createContext<GlassBlurContextValue>(NO_TARGET);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The mounted `GlassBlurTarget` that floating glass blurs on Android, or
|
|
30
|
+
* `null` outside a `GlassBlurProvider` and inside the target itself.
|
|
31
|
+
*/
|
|
32
|
+
export function useGlassBlurTarget() {
|
|
33
|
+
return useContext(GlassBlurContext).target;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function GlassBlurProvider({ children }: { children: ReactNode }) {
|
|
37
|
+
const [target, setTarget] = useState<BlurTargetRef | null>(null);
|
|
38
|
+
const value = useMemo(() => ({ target, setTarget }), [target]);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<GlassBlurContext.Provider value={value}>{children}</GlassBlurContext.Provider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type GlassBlurTargetProps = ViewProps & {
|
|
46
|
+
/** Set `false` while the content is hidden, such as an unfocused tab. */
|
|
47
|
+
active?: boolean;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Content that floating glass blurs on Android (an expo-blur
|
|
52
|
+
* `BlurTargetView`). Render the floating chrome outside it, inside the same
|
|
53
|
+
* `GlassBlurProvider`: a blur view must not sit inside its own target, so
|
|
54
|
+
* surfaces in here get no target. The last active target wins.
|
|
55
|
+
*/
|
|
56
|
+
export function GlassBlurTarget({
|
|
57
|
+
active = true,
|
|
58
|
+
style,
|
|
59
|
+
children,
|
|
60
|
+
...props
|
|
61
|
+
}: GlassBlurTargetProps) {
|
|
62
|
+
const { setTarget } = useContext(GlassBlurContext);
|
|
63
|
+
const ref = useRef<ComponentRef<typeof View>>(null);
|
|
64
|
+
const BlurTargetView = loadBlur()?.BlurTargetView;
|
|
65
|
+
|
|
66
|
+
// Publish the ref only once it is attached: expo-blur compares
|
|
67
|
+
// `blurTarget.current` between renders to pick up a new target.
|
|
68
|
+
useLayoutEffect(() => {
|
|
69
|
+
if (!setTarget || !active) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
setTarget(ref);
|
|
73
|
+
return () => setTarget((current) => (current === ref ? null : current));
|
|
74
|
+
}, [setTarget, active]);
|
|
75
|
+
|
|
76
|
+
const content = (
|
|
77
|
+
<GlassBlurContext.Provider value={NO_TARGET}>{children}</GlassBlurContext.Provider>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return BlurTargetView ? (
|
|
81
|
+
<BlurTargetView ref={ref} style={[styles.fill, style]} {...props}>
|
|
82
|
+
{content}
|
|
83
|
+
</BlurTargetView>
|
|
84
|
+
) : (
|
|
85
|
+
<View ref={ref} style={[styles.fill, style]} {...props}>
|
|
86
|
+
{content}
|
|
87
|
+
</View>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const styles = StyleSheet.create({
|
|
92
|
+
fill: {
|
|
93
|
+
flex: 1,
|
|
94
|
+
},
|
|
95
|
+
});
|
package/src/gradient.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as ExpoLinearGradient from "expo-linear-gradient";
|
|
2
|
+
|
|
3
|
+
export type ExpoLinearGradientModule = typeof ExpoLinearGradient;
|
|
4
|
+
|
|
5
|
+
let expoLinearGradient: ExpoLinearGradientModule | null | undefined;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `expo-linear-gradient`, or `null` when the optional peer is not installed.
|
|
9
|
+
* Metro bundles a `require` placed directly in a `try` block as an optional
|
|
10
|
+
* dependency, so a missing peer does not break the bundle.
|
|
11
|
+
*/
|
|
12
|
+
export function loadLinearGradient(): ExpoLinearGradientModule | null {
|
|
13
|
+
if (expoLinearGradient === undefined) {
|
|
14
|
+
try {
|
|
15
|
+
expoLinearGradient = require("expo-linear-gradient") as ExpoLinearGradientModule;
|
|
16
|
+
} catch {
|
|
17
|
+
expoLinearGradient = null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return expoLinearGradient;
|
|
21
|
+
}
|
package/src/haptics.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import { Platform } from "react-native";
|
|
2
|
-
import * as
|
|
2
|
+
import type * as ExpoHaptics from "expo-haptics";
|
|
3
|
+
|
|
4
|
+
export type ExpoHapticsModule = typeof ExpoHaptics;
|
|
5
|
+
|
|
6
|
+
let expoHaptics: ExpoHapticsModule | null | undefined;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `expo-haptics`, or `null` when the optional peer is not installed. Metro
|
|
10
|
+
* bundles a `require` placed directly in a `try` block as an optional
|
|
11
|
+
* dependency, so a missing peer does not break the bundle.
|
|
12
|
+
*/
|
|
13
|
+
export function loadHaptics(): ExpoHapticsModule | null {
|
|
14
|
+
if (expoHaptics === undefined) {
|
|
15
|
+
try {
|
|
16
|
+
expoHaptics = require("expo-haptics") as ExpoHapticsModule;
|
|
17
|
+
} catch {
|
|
18
|
+
expoHaptics = null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return expoHaptics;
|
|
22
|
+
}
|
|
3
23
|
|
|
4
24
|
export function selectionHaptic() {
|
|
5
25
|
if (Platform.OS === "web") {
|
|
6
26
|
return;
|
|
7
27
|
}
|
|
8
|
-
void
|
|
28
|
+
void loadHaptics()?.selectionAsync();
|
|
9
29
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,9 @@ export {
|
|
|
8
8
|
DEFAULT_ACCENT,
|
|
9
9
|
} from "./theme";
|
|
10
10
|
export type { NativeUiTheme } from "./theme";
|
|
11
|
+
export { palette, withAlpha } from "./palette";
|
|
12
|
+
export type { Palette } from "./palette";
|
|
13
|
+
export { fontClass } from "./typography";
|
|
11
14
|
export {
|
|
12
15
|
FLOATING_INSET,
|
|
13
16
|
FLOATING_TAB_BAR_HEIGHT,
|
|
@@ -29,24 +32,107 @@ export {
|
|
|
29
32
|
GlassBlurProvider,
|
|
30
33
|
GlassBlurTarget,
|
|
31
34
|
} from "./LiquidGlass";
|
|
35
|
+
export type { GlassBlurTargetProps } from "./LiquidGlass";
|
|
32
36
|
export { AmbientBackground } from "./AmbientBackground";
|
|
33
37
|
export { FloatingTabBar } from "./FloatingTabBar";
|
|
38
|
+
export type { FloatingTabBarProps } from "./FloatingTabBar";
|
|
34
39
|
export { FloatingFAB } from "./FloatingFAB";
|
|
35
40
|
export { Button } from "./Button";
|
|
36
|
-
export type { ButtonProps } from "./Button";
|
|
41
|
+
export type { ButtonProps, ButtonSize, ButtonVariant } from "./Button";
|
|
37
42
|
export { Input } from "./Input";
|
|
38
43
|
export type { InputProps } from "./Input";
|
|
44
|
+
export { SearchInput } from "./SearchInput";
|
|
45
|
+
export type { SearchInputProps } from "./SearchInput";
|
|
46
|
+
export { Textarea } from "./Textarea";
|
|
47
|
+
export type { TextareaProps } from "./Textarea";
|
|
48
|
+
export { Label } from "./Label";
|
|
49
|
+
export type { LabelProps } from "./Label";
|
|
39
50
|
export { Select } from "./Select";
|
|
40
51
|
export type { SelectOption, SelectProps } from "./Select";
|
|
41
52
|
export { Switch } from "./Switch";
|
|
42
53
|
export type { SwitchProps } from "./Switch";
|
|
54
|
+
export { LabeledSwitchRow } from "./LabeledSwitchRow";
|
|
55
|
+
export type { LabeledSwitchRowProps } from "./LabeledSwitchRow";
|
|
56
|
+
export { Checkbox } from "./Checkbox";
|
|
57
|
+
export type { CheckboxProps } from "./Checkbox";
|
|
58
|
+
export { Badge } from "./Badge";
|
|
59
|
+
export type { BadgeProps, BadgeVariant } from "./Badge";
|
|
60
|
+
export { StatusDot } from "./StatusDot";
|
|
61
|
+
export type { StatusDotProps, StatusTone } from "./StatusDot";
|
|
62
|
+
export { Separator } from "./Separator";
|
|
63
|
+
export type { SeparatorProps } from "./Separator";
|
|
64
|
+
export { Progress } from "./Progress";
|
|
65
|
+
export type { ProgressProps } from "./Progress";
|
|
66
|
+
export { Spinner, CenteredSpinner } from "./Spinner";
|
|
67
|
+
export type { SpinnerProps } from "./Spinner";
|
|
68
|
+
export { Avatar, AvatarImage, AvatarFallback } from "./Avatar";
|
|
69
|
+
export type { AvatarProps, AvatarImageProps, AvatarFallbackProps } from "./Avatar";
|
|
70
|
+
export { initials } from "./initials";
|
|
43
71
|
export { Chip } from "./Chip";
|
|
44
72
|
export { PillTabs } from "./PillTabs";
|
|
73
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent } from "./Tabs";
|
|
74
|
+
export type {
|
|
75
|
+
TabsProps,
|
|
76
|
+
TabsListProps,
|
|
77
|
+
TabsListVariant,
|
|
78
|
+
TabsTriggerProps,
|
|
79
|
+
TabsContentProps,
|
|
80
|
+
} from "./Tabs";
|
|
45
81
|
export { ListRow } from "./ListRow";
|
|
46
82
|
export { HeaderIconButton } from "./HeaderIconButton";
|
|
47
|
-
export {
|
|
83
|
+
export {
|
|
84
|
+
Card,
|
|
85
|
+
CardHeader,
|
|
86
|
+
CardTitle,
|
|
87
|
+
CardDescription,
|
|
88
|
+
CardContent,
|
|
89
|
+
CardFooter,
|
|
90
|
+
} from "./Card";
|
|
48
91
|
export { Skeleton, CardSkeleton } from "./Skeleton";
|
|
49
92
|
export { EmptyState } from "./EmptyState";
|
|
93
|
+
export type { EmptyStateVariant } from "./EmptyState";
|
|
94
|
+
export {
|
|
95
|
+
Dialog,
|
|
96
|
+
DialogTrigger,
|
|
97
|
+
DialogClose,
|
|
98
|
+
DialogContent,
|
|
99
|
+
DialogHeader,
|
|
100
|
+
DialogTitle,
|
|
101
|
+
DialogDescription,
|
|
102
|
+
DialogBody,
|
|
103
|
+
DialogFooter,
|
|
104
|
+
} from "./Dialog";
|
|
105
|
+
export type { DialogProps, DialogContentProps } from "./Dialog";
|
|
106
|
+
export {
|
|
107
|
+
AlertDialog,
|
|
108
|
+
AlertDialogTrigger,
|
|
109
|
+
AlertDialogContent,
|
|
110
|
+
AlertDialogHeader,
|
|
111
|
+
AlertDialogTitle,
|
|
112
|
+
AlertDialogDescription,
|
|
113
|
+
AlertDialogFooter,
|
|
114
|
+
AlertDialogAction,
|
|
115
|
+
AlertDialogCancel,
|
|
116
|
+
} from "./AlertDialog";
|
|
117
|
+
export type { AlertDialogProps, AlertDialogContentProps } from "./AlertDialog";
|
|
118
|
+
export { ConfirmDialog } from "./ConfirmDialog";
|
|
119
|
+
export type { ConfirmDialogProps } from "./ConfirmDialog";
|
|
120
|
+
export {
|
|
121
|
+
Sheet,
|
|
122
|
+
SheetTrigger,
|
|
123
|
+
SheetClose,
|
|
124
|
+
SheetContent,
|
|
125
|
+
SheetHandle,
|
|
126
|
+
SheetHeader,
|
|
127
|
+
SheetTitle,
|
|
128
|
+
SheetDescription,
|
|
129
|
+
SheetBody,
|
|
130
|
+
SheetFooter,
|
|
131
|
+
} from "./Sheet";
|
|
132
|
+
export type { SheetProps, SheetContentProps } from "./Sheet";
|
|
133
|
+
export { Toaster } from "./Toast";
|
|
134
|
+
export { toast } from "./toastStore";
|
|
135
|
+
export type { ToastOptions, ToastVariant } from "./toastStore";
|
|
50
136
|
export { DateTimeField } from "./DateTimeField";
|
|
51
137
|
export { BottomSheetContainer } from "./BottomSheetContainer";
|
|
52
138
|
export { SafeAreaContainer } from "./SafeAreaContainer";
|
|
@@ -56,3 +142,14 @@ export { SettingsField } from "./settings/SettingsField";
|
|
|
56
142
|
export { SettingsToggleRow } from "./settings/SettingsToggleRow";
|
|
57
143
|
export { SettingsStack } from "./settings/SettingsStack";
|
|
58
144
|
export { PINK_50, PINK_100, PINK_600, PINK_700, NEUTRAL_100, NEUTRAL_500, NEUTRAL_900, Colors } from "./colors";
|
|
145
|
+
// Family app marks and their pure data (copied from `@vvedantb/ui/brand`).
|
|
146
|
+
export * from "./brand";
|
|
147
|
+
export { UpgradeToProCard } from "./marketing/UpgradeToProCard";
|
|
148
|
+
export type { UpgradeToProCardProps } from "./marketing/UpgradeToProCard";
|
|
149
|
+
export { PricingModal } from "./marketing/PricingModal";
|
|
150
|
+
export type { PricingModalProps } from "./marketing/PricingModal";
|
|
151
|
+
export type {
|
|
152
|
+
PricingModalPeriod,
|
|
153
|
+
PricingPlan,
|
|
154
|
+
PricingPlanBenefit,
|
|
155
|
+
} from "./marketing/pricing";
|
package/src/initials.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Up to `max` uppercase initials from a name: "Ada Lovelace" → "AL", " cher " → "C". Empty for a blank name. */
|
|
2
|
+
export function initials(name: string, max = 2): string {
|
|
3
|
+
return name
|
|
4
|
+
.trim()
|
|
5
|
+
.split(/\s+/)
|
|
6
|
+
.filter(Boolean)
|
|
7
|
+
.slice(0, max)
|
|
8
|
+
.map((word) => Array.from(word)[0]!.toUpperCase())
|
|
9
|
+
.join("");
|
|
10
|
+
}
|