@sibipro/sprinkles-native 0.1.8
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 +101 -0
- package/dist/components/Avatar.d.ts +9 -0
- package/dist/components/Avatar.d.ts.map +1 -0
- package/dist/components/Avatar.js +27 -0
- package/dist/components/Avatar.js.map +1 -0
- package/dist/components/Badge.d.ts +10 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +26 -0
- package/dist/components/Badge.js.map +1 -0
- package/dist/components/Banner.d.ts +8 -0
- package/dist/components/Banner.d.ts.map +1 -0
- package/dist/components/Banner.js +13 -0
- package/dist/components/Banner.js.map +1 -0
- package/dist/components/Button.d.ts +12 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +43 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/Card.d.ts +8 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +11 -0
- package/dist/components/Card.js.map +1 -0
- package/dist/components/Checkbox.d.ts +9 -0
- package/dist/components/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox.js +10 -0
- package/dist/components/Checkbox.js.map +1 -0
- package/dist/components/Chip.d.ts +8 -0
- package/dist/components/Chip.d.ts.map +1 -0
- package/dist/components/Chip.js +8 -0
- package/dist/components/Chip.js.map +1 -0
- package/dist/components/EmptyState.d.ts +11 -0
- package/dist/components/EmptyState.d.ts.map +1 -0
- package/dist/components/EmptyState.js +8 -0
- package/dist/components/EmptyState.js.map +1 -0
- package/dist/components/Input.d.ts +25 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +28 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/Label.d.ts +6 -0
- package/dist/components/Label.d.ts.map +1 -0
- package/dist/components/Label.js +7 -0
- package/dist/components/Label.js.map +1 -0
- package/dist/components/ProgressBar.d.ts +8 -0
- package/dist/components/ProgressBar.d.ts.map +1 -0
- package/dist/components/ProgressBar.js +8 -0
- package/dist/components/ProgressBar.js.map +1 -0
- package/dist/components/Separator.d.ts +7 -0
- package/dist/components/Separator.d.ts.map +1 -0
- package/dist/components/Separator.js +7 -0
- package/dist/components/Separator.js.map +1 -0
- package/dist/components/Skeleton.d.ts +6 -0
- package/dist/components/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton.js +25 -0
- package/dist/components/Skeleton.js.map +1 -0
- package/dist/components/Switch.d.ts +7 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +10 -0
- package/dist/components/Switch.js.map +1 -0
- package/dist/components/Text.d.ts +12 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/Text.js +27 -0
- package/dist/components/Text.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/theming/color-palettes.d.ts +82 -0
- package/dist/theming/color-palettes.d.ts.map +1 -0
- package/dist/theming/color-palettes.js +82 -0
- package/dist/theming/color-palettes.js.map +1 -0
- package/dist/theming/types.d.ts +81 -0
- package/dist/theming/types.d.ts.map +1 -0
- package/dist/theming/types.js +2 -0
- package/dist/theming/types.js.map +1 -0
- package/dist/utils/cn.d.ts +3 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +6 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +51 -0
- package/src/components/Avatar.tsx +58 -0
- package/src/components/Badge.tsx +70 -0
- package/src/components/Banner.tsx +34 -0
- package/src/components/Button.tsx +96 -0
- package/src/components/Card.tsx +28 -0
- package/src/components/Checkbox.tsx +43 -0
- package/src/components/Chip.tsx +38 -0
- package/src/components/EmptyState.tsx +41 -0
- package/src/components/Input.tsx +123 -0
- package/src/components/Label.tsx +16 -0
- package/src/components/ProgressBar.tsx +32 -0
- package/src/components/Separator.tsx +25 -0
- package/src/components/Skeleton.tsx +38 -0
- package/src/components/Switch.tsx +32 -0
- package/src/components/Text.tsx +57 -0
- package/src/index.ts +52 -0
- package/src/styles/global.css +245 -0
- package/src/theming/color-palettes.ts +81 -0
- package/src/theming/types.ts +82 -0
- package/src/types/react-native.d.ts +31 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export type BannerVariant = 'info' | 'warn' | 'danger' | 'success';
|
|
6
|
+
|
|
7
|
+
const variantClasses: Record<BannerVariant, string> = {
|
|
8
|
+
info: 'bg-info-50 dark:bg-info-900',
|
|
9
|
+
warn: 'bg-warn-50 dark:bg-warn-900',
|
|
10
|
+
danger: 'bg-danger-50 dark:bg-danger-900',
|
|
11
|
+
success: 'bg-success-50 dark:bg-success-900',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export interface BannerProps extends ViewProps {
|
|
15
|
+
variant?: BannerVariant;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function Banner({
|
|
20
|
+
variant = 'info',
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: BannerProps) {
|
|
24
|
+
return (
|
|
25
|
+
<View
|
|
26
|
+
className={cn(
|
|
27
|
+
'rounded-2xl p-4 flex-row items-start gap-2.5',
|
|
28
|
+
variantClasses[variant],
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable, type PressableProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { Text } from './Text';
|
|
5
|
+
|
|
6
|
+
export type ButtonVariant =
|
|
7
|
+
| 'primary'
|
|
8
|
+
| 'secondary'
|
|
9
|
+
| 'tertiary'
|
|
10
|
+
| 'tertiary-brand'
|
|
11
|
+
| 'tertiary-danger'
|
|
12
|
+
| 'danger'
|
|
13
|
+
| 'ghost'
|
|
14
|
+
| 'link';
|
|
15
|
+
|
|
16
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
17
|
+
|
|
18
|
+
const variantClasses: Record<ButtonVariant, string> = {
|
|
19
|
+
primary: 'bg-button-primary',
|
|
20
|
+
secondary: 'bg-button-secondary border border-border',
|
|
21
|
+
tertiary: 'bg-transparent',
|
|
22
|
+
'tertiary-brand': 'bg-transparent',
|
|
23
|
+
'tertiary-danger': 'bg-transparent',
|
|
24
|
+
danger: 'bg-danger-500',
|
|
25
|
+
ghost: 'bg-transparent',
|
|
26
|
+
link: 'bg-transparent',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const pressedClasses: Record<ButtonVariant, string> = {
|
|
30
|
+
primary: 'bg-button-primary-hover',
|
|
31
|
+
secondary: 'bg-button-secondary-hover',
|
|
32
|
+
tertiary: 'bg-button-tertiary-hover',
|
|
33
|
+
'tertiary-brand': 'bg-brand-25',
|
|
34
|
+
'tertiary-danger': 'bg-danger-25',
|
|
35
|
+
danger: 'bg-danger-600',
|
|
36
|
+
ghost: 'bg-accent',
|
|
37
|
+
link: 'opacity-70',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const textClasses: Record<ButtonVariant, string> = {
|
|
41
|
+
primary: 'text-button-primary-foreground',
|
|
42
|
+
secondary: 'text-button-secondary-foreground',
|
|
43
|
+
tertiary: 'text-button-tertiary-foreground',
|
|
44
|
+
'tertiary-brand': 'text-brand-500',
|
|
45
|
+
'tertiary-danger': 'text-danger-500',
|
|
46
|
+
danger: 'text-white',
|
|
47
|
+
ghost: 'text-foreground',
|
|
48
|
+
link: 'text-brand-500 underline',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const sizeClasses: Record<ButtonSize, string> = {
|
|
52
|
+
sm: 'h-8 px-3',
|
|
53
|
+
md: 'h-10 px-4',
|
|
54
|
+
lg: 'h-12 px-5',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export interface ButtonProps extends Omit<PressableProps, 'children'> {
|
|
58
|
+
variant?: ButtonVariant;
|
|
59
|
+
size?: ButtonSize;
|
|
60
|
+
className?: string;
|
|
61
|
+
children: React.ReactNode;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function Button({
|
|
65
|
+
variant = 'secondary',
|
|
66
|
+
size = 'md',
|
|
67
|
+
className,
|
|
68
|
+
disabled,
|
|
69
|
+
children,
|
|
70
|
+
...props
|
|
71
|
+
}: ButtonProps) {
|
|
72
|
+
return (
|
|
73
|
+
<Pressable
|
|
74
|
+
className={({ pressed }) =>
|
|
75
|
+
cn(
|
|
76
|
+
'rounded-lg flex-row items-center justify-center gap-2',
|
|
77
|
+
variantClasses[variant],
|
|
78
|
+
sizeClasses[size],
|
|
79
|
+
pressed && pressedClasses[variant],
|
|
80
|
+
disabled && 'opacity-50',
|
|
81
|
+
className,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
disabled={disabled}
|
|
85
|
+
{...props}
|
|
86
|
+
>
|
|
87
|
+
{typeof children === 'string' ? (
|
|
88
|
+
<Text size="sm" weight="bold" className={textClasses[variant]}>
|
|
89
|
+
{children}
|
|
90
|
+
</Text>
|
|
91
|
+
) : (
|
|
92
|
+
children
|
|
93
|
+
)}
|
|
94
|
+
</Pressable>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export type CardVariant = 'default' | 'outline';
|
|
6
|
+
|
|
7
|
+
const variantClasses: Record<CardVariant, string> = {
|
|
8
|
+
default: 'bg-background shadow-md',
|
|
9
|
+
outline: 'bg-background border border-border',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface CardProps extends ViewProps {
|
|
13
|
+
variant?: CardVariant;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function Card({
|
|
18
|
+
variant = 'default',
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: CardProps) {
|
|
22
|
+
return (
|
|
23
|
+
<View
|
|
24
|
+
className={cn('rounded-xl p-4', variantClasses[variant], className)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable, View } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { Text } from './Text';
|
|
5
|
+
|
|
6
|
+
export interface CheckboxProps {
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
label?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Checkbox({
|
|
15
|
+
checked = false,
|
|
16
|
+
onCheckedChange,
|
|
17
|
+
disabled,
|
|
18
|
+
label,
|
|
19
|
+
className,
|
|
20
|
+
}: CheckboxProps) {
|
|
21
|
+
return (
|
|
22
|
+
<Pressable
|
|
23
|
+
onPress={() => !disabled && onCheckedChange?.(!checked)}
|
|
24
|
+
className={cn('flex-row items-center gap-2', disabled && 'opacity-50', className)}
|
|
25
|
+
accessibilityRole="checkbox"
|
|
26
|
+
accessibilityState={{ checked, disabled }}
|
|
27
|
+
>
|
|
28
|
+
<View
|
|
29
|
+
className={cn(
|
|
30
|
+
'h-5 w-5 rounded border items-center justify-center',
|
|
31
|
+
checked
|
|
32
|
+
? 'bg-brand-500 border-brand-500'
|
|
33
|
+
: 'bg-background border-border',
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{checked && (
|
|
37
|
+
<Text className="text-white text-xs">✓</Text>
|
|
38
|
+
)}
|
|
39
|
+
</View>
|
|
40
|
+
{label && <Text className="text-foreground">{label}</Text>}
|
|
41
|
+
</Pressable>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Pressable, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { Text } from './Text';
|
|
5
|
+
|
|
6
|
+
export interface ChipProps extends ViewProps {
|
|
7
|
+
label: string;
|
|
8
|
+
onDismiss?: () => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Chip({ label, onDismiss, className, ...props }: ChipProps) {
|
|
13
|
+
return (
|
|
14
|
+
<View
|
|
15
|
+
className={cn(
|
|
16
|
+
'h-7 rounded-full bg-background-tertiary px-2.5 flex-row items-center gap-1',
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
<Text size="sm" className="text-foreground">
|
|
22
|
+
{label}
|
|
23
|
+
</Text>
|
|
24
|
+
{onDismiss && (
|
|
25
|
+
<Pressable
|
|
26
|
+
onPress={onDismiss}
|
|
27
|
+
className="ml-0.5"
|
|
28
|
+
accessibilityRole="button"
|
|
29
|
+
accessibilityLabel={`Remove ${label}`}
|
|
30
|
+
>
|
|
31
|
+
<Text size="sm" className="text-foreground-label">
|
|
32
|
+
✕
|
|
33
|
+
</Text>
|
|
34
|
+
</Pressable>
|
|
35
|
+
)}
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
import { Text } from './Text';
|
|
5
|
+
|
|
6
|
+
export interface EmptyStateProps extends ViewProps {
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
icon?: React.ReactNode;
|
|
10
|
+
action?: React.ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function EmptyState({
|
|
15
|
+
title,
|
|
16
|
+
description,
|
|
17
|
+
icon,
|
|
18
|
+
action,
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: EmptyStateProps) {
|
|
22
|
+
return (
|
|
23
|
+
<View
|
|
24
|
+
className={cn('items-center py-12 px-4 gap-3', className)}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
{icon}
|
|
28
|
+
<View className="items-center gap-1">
|
|
29
|
+
<Text variant="heading" className="text-2xl text-center">
|
|
30
|
+
{title}
|
|
31
|
+
</Text>
|
|
32
|
+
{description && (
|
|
33
|
+
<Text className="text-lg text-foreground text-center">
|
|
34
|
+
{description}
|
|
35
|
+
</Text>
|
|
36
|
+
)}
|
|
37
|
+
</View>
|
|
38
|
+
{action}
|
|
39
|
+
</View>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TextInput,
|
|
4
|
+
View,
|
|
5
|
+
Pressable,
|
|
6
|
+
type TextInputProps,
|
|
7
|
+
type ViewProps,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { cn } from '../utils/cn';
|
|
10
|
+
import { Text } from './Text';
|
|
11
|
+
|
|
12
|
+
export type InputVariant = 'default' | 'search' | 'ghost';
|
|
13
|
+
export type InputGirth = 'sm' | 'md' | 'lg';
|
|
14
|
+
|
|
15
|
+
const variantClasses: Record<InputVariant, string> = {
|
|
16
|
+
default: 'border border-border bg-background',
|
|
17
|
+
search: 'border-0 bg-background-secondary',
|
|
18
|
+
ghost: 'border-0 bg-transparent',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const girthClasses: Record<InputGirth, string> = {
|
|
22
|
+
sm: 'h-8',
|
|
23
|
+
md: 'h-10',
|
|
24
|
+
lg: 'min-h-[48px] py-3',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export interface InputProps extends TextInputProps {
|
|
28
|
+
variant?: InputVariant;
|
|
29
|
+
girth?: InputGirth;
|
|
30
|
+
error?: boolean;
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Input = React.forwardRef<TextInput, InputProps>(
|
|
35
|
+
({ variant = 'default', girth = 'md', error, className, ...props }, ref) => {
|
|
36
|
+
return (
|
|
37
|
+
<TextInput
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn(
|
|
40
|
+
'w-full rounded-xl px-4 text-base text-foreground',
|
|
41
|
+
variantClasses[variant],
|
|
42
|
+
girthClasses[girth],
|
|
43
|
+
error && 'border-2 border-danger-500',
|
|
44
|
+
props.editable === false && 'opacity-60',
|
|
45
|
+
className,
|
|
46
|
+
)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export interface InputWithExtrasProps extends InputProps {
|
|
54
|
+
before?: React.ReactNode;
|
|
55
|
+
after?: React.ReactNode;
|
|
56
|
+
containerClassName?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const InputWithExtras = React.forwardRef<TextInput, InputWithExtrasProps>(
|
|
60
|
+
({ before, after, containerClassName, variant = 'default', girth = 'md', error, className, ...props }, ref) => {
|
|
61
|
+
const innerRef = useRef<TextInput>(null);
|
|
62
|
+
const inputRef = (ref as React.RefObject<TextInput>) ?? innerRef;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Pressable onPress={() => inputRef.current?.focus()}>
|
|
66
|
+
<View
|
|
67
|
+
className={cn(
|
|
68
|
+
'flex-row items-center gap-1',
|
|
69
|
+
variantClasses[variant],
|
|
70
|
+
girthClasses[girth],
|
|
71
|
+
'rounded-xl px-4',
|
|
72
|
+
error && 'border-2 border-danger-500',
|
|
73
|
+
containerClassName,
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
{before}
|
|
77
|
+
<Input
|
|
78
|
+
ref={inputRef}
|
|
79
|
+
variant="ghost"
|
|
80
|
+
girth={girth}
|
|
81
|
+
className={cn('flex-1 h-full px-0', className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
{after}
|
|
85
|
+
</View>
|
|
86
|
+
</Pressable>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
export interface InputWithLabelProps extends InputProps {
|
|
92
|
+
label?: string;
|
|
93
|
+
description?: string;
|
|
94
|
+
errorMessage?: string;
|
|
95
|
+
containerClassName?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const InputWithLabel = React.forwardRef<TextInput, InputWithLabelProps>(
|
|
99
|
+
({ label, description, errorMessage, containerClassName, error, ...props }, ref) => {
|
|
100
|
+
const hasError = error || !!errorMessage;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<View className={cn('gap-1 w-full', containerClassName)}>
|
|
104
|
+
{label && (
|
|
105
|
+
<Text size="sm" weight="semibold" className="text-foreground">
|
|
106
|
+
{label}
|
|
107
|
+
</Text>
|
|
108
|
+
)}
|
|
109
|
+
<Input ref={ref} error={hasError} {...props} />
|
|
110
|
+
{description && !errorMessage && (
|
|
111
|
+
<Text size="xs" className="text-foreground-label">
|
|
112
|
+
{description}
|
|
113
|
+
</Text>
|
|
114
|
+
)}
|
|
115
|
+
{errorMessage && (
|
|
116
|
+
<Text size="xs" weight="semibold" className="text-danger-700">
|
|
117
|
+
{errorMessage}
|
|
118
|
+
</Text>
|
|
119
|
+
)}
|
|
120
|
+
</View>
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text as RNText, type TextProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export interface LabelProps extends TextProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Label({ className, ...props }: LabelProps) {
|
|
10
|
+
return (
|
|
11
|
+
<RNText
|
|
12
|
+
className={cn('text-sm font-semibold text-foreground', className)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export interface ProgressBarProps extends ViewProps {
|
|
6
|
+
value: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ProgressBar({
|
|
12
|
+
value,
|
|
13
|
+
max = 100,
|
|
14
|
+
className,
|
|
15
|
+
...props
|
|
16
|
+
}: ProgressBarProps) {
|
|
17
|
+
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<View
|
|
21
|
+
className={cn('h-2 w-full rounded-full bg-background-tertiary', className)}
|
|
22
|
+
accessibilityRole="progressbar"
|
|
23
|
+
accessibilityValue={{ min: 0, max, now: value }}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
<View
|
|
27
|
+
className="h-full rounded-full bg-brand-500"
|
|
28
|
+
style={{ width: `${percentage}%` }}
|
|
29
|
+
/>
|
|
30
|
+
</View>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export interface SeparatorProps extends ViewProps {
|
|
6
|
+
orientation?: 'horizontal' | 'vertical';
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Separator({
|
|
11
|
+
orientation = 'horizontal',
|
|
12
|
+
className,
|
|
13
|
+
...props
|
|
14
|
+
}: SeparatorProps) {
|
|
15
|
+
return (
|
|
16
|
+
<View
|
|
17
|
+
className={cn(
|
|
18
|
+
'bg-border',
|
|
19
|
+
orientation === 'horizontal' ? 'h-px w-full' : 'w-px h-full',
|
|
20
|
+
className,
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { Animated, View, type ViewProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export interface SkeletonProps extends ViewProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Skeleton({ className, style, ...props }: SkeletonProps) {
|
|
10
|
+
const opacity = useRef(new Animated.Value(1)).current;
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const animation = Animated.loop(
|
|
14
|
+
Animated.sequence([
|
|
15
|
+
Animated.timing(opacity, {
|
|
16
|
+
toValue: 0.5,
|
|
17
|
+
duration: 1000,
|
|
18
|
+
useNativeDriver: true,
|
|
19
|
+
}),
|
|
20
|
+
Animated.timing(opacity, {
|
|
21
|
+
toValue: 1,
|
|
22
|
+
duration: 1000,
|
|
23
|
+
useNativeDriver: true,
|
|
24
|
+
}),
|
|
25
|
+
]),
|
|
26
|
+
);
|
|
27
|
+
animation.start();
|
|
28
|
+
return () => animation.stop();
|
|
29
|
+
}, [opacity]);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Animated.View
|
|
33
|
+
className={cn('rounded-md bg-background-tertiary', className)}
|
|
34
|
+
style={[{ opacity }, style]}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Switch as RNSwitch,
|
|
4
|
+
type SwitchProps as RNSwitchProps,
|
|
5
|
+
} from 'react-native';
|
|
6
|
+
import { palettes } from '../theming/color-palettes';
|
|
7
|
+
|
|
8
|
+
export interface SwitchProps extends RNSwitchProps {
|
|
9
|
+
checked?: boolean;
|
|
10
|
+
onCheckedChange?: (value: boolean) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Switch({
|
|
14
|
+
checked,
|
|
15
|
+
onCheckedChange,
|
|
16
|
+
value,
|
|
17
|
+
onValueChange,
|
|
18
|
+
...props
|
|
19
|
+
}: SwitchProps) {
|
|
20
|
+
return (
|
|
21
|
+
<RNSwitch
|
|
22
|
+
value={checked ?? value}
|
|
23
|
+
onValueChange={onCheckedChange ?? onValueChange}
|
|
24
|
+
trackColor={{
|
|
25
|
+
false: palettes.neutral[300],
|
|
26
|
+
true: palettes.purple[500],
|
|
27
|
+
}}
|
|
28
|
+
thumbColor={palettes.white}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text as RNText, type TextProps as RNTextProps } from 'react-native';
|
|
3
|
+
import { cn } from '../utils/cn';
|
|
4
|
+
|
|
5
|
+
export type TextVariant = 'body' | 'caption' | 'label' | 'heading';
|
|
6
|
+
export type TextSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
7
|
+
export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';
|
|
8
|
+
|
|
9
|
+
const variantClasses: Record<TextVariant, string> = {
|
|
10
|
+
body: 'text-base text-foreground',
|
|
11
|
+
caption: 'text-xs text-foreground-label',
|
|
12
|
+
label: 'text-sm text-foreground-label',
|
|
13
|
+
heading: 'text-lg font-bold text-foreground-heading',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const sizeClasses: Record<TextSize, string> = {
|
|
17
|
+
xs: 'text-xs',
|
|
18
|
+
sm: 'text-sm',
|
|
19
|
+
md: 'text-base',
|
|
20
|
+
lg: 'text-lg',
|
|
21
|
+
xl: 'text-xl',
|
|
22
|
+
'2xl': 'text-2xl',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const weightClasses: Record<TextWeight, string> = {
|
|
26
|
+
normal: 'font-normal',
|
|
27
|
+
medium: 'font-medium',
|
|
28
|
+
semibold: 'font-semibold',
|
|
29
|
+
bold: 'font-bold',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export interface TextProps extends RNTextProps {
|
|
33
|
+
variant?: TextVariant;
|
|
34
|
+
size?: TextSize;
|
|
35
|
+
weight?: TextWeight;
|
|
36
|
+
className?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function Text({
|
|
40
|
+
variant = 'body',
|
|
41
|
+
size,
|
|
42
|
+
weight,
|
|
43
|
+
className,
|
|
44
|
+
...props
|
|
45
|
+
}: TextProps) {
|
|
46
|
+
return (
|
|
47
|
+
<RNText
|
|
48
|
+
className={cn(
|
|
49
|
+
variantClasses[variant],
|
|
50
|
+
size && sizeClasses[size],
|
|
51
|
+
weight && weightClasses[weight],
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Components
|
|
2
|
+
export { Text } from './components/Text';
|
|
3
|
+
export type { TextProps, TextVariant, TextSize, TextWeight } from './components/Text';
|
|
4
|
+
|
|
5
|
+
export { Badge } from './components/Badge';
|
|
6
|
+
export type { BadgeProps, BadgeVariant } from './components/Badge';
|
|
7
|
+
|
|
8
|
+
export { Button } from './components/Button';
|
|
9
|
+
export type { ButtonProps, ButtonVariant, ButtonSize } from './components/Button';
|
|
10
|
+
|
|
11
|
+
export { Input, InputWithExtras, InputWithLabel } from './components/Input';
|
|
12
|
+
export type { InputProps, InputWithExtrasProps, InputWithLabelProps, InputVariant, InputGirth } from './components/Input';
|
|
13
|
+
|
|
14
|
+
export { Card } from './components/Card';
|
|
15
|
+
export type { CardProps, CardVariant } from './components/Card';
|
|
16
|
+
|
|
17
|
+
export { Banner } from './components/Banner';
|
|
18
|
+
export type { BannerProps, BannerVariant } from './components/Banner';
|
|
19
|
+
|
|
20
|
+
export { Separator } from './components/Separator';
|
|
21
|
+
export type { SeparatorProps } from './components/Separator';
|
|
22
|
+
|
|
23
|
+
export { Skeleton } from './components/Skeleton';
|
|
24
|
+
export type { SkeletonProps } from './components/Skeleton';
|
|
25
|
+
|
|
26
|
+
export { ProgressBar } from './components/ProgressBar';
|
|
27
|
+
export type { ProgressBarProps } from './components/ProgressBar';
|
|
28
|
+
|
|
29
|
+
export { Chip } from './components/Chip';
|
|
30
|
+
export type { ChipProps } from './components/Chip';
|
|
31
|
+
|
|
32
|
+
export { EmptyState } from './components/EmptyState';
|
|
33
|
+
export type { EmptyStateProps } from './components/EmptyState';
|
|
34
|
+
|
|
35
|
+
export { Avatar } from './components/Avatar';
|
|
36
|
+
export type { AvatarProps, AvatarSize } from './components/Avatar';
|
|
37
|
+
|
|
38
|
+
export { Switch } from './components/Switch';
|
|
39
|
+
export type { SwitchProps } from './components/Switch';
|
|
40
|
+
|
|
41
|
+
export { Checkbox } from './components/Checkbox';
|
|
42
|
+
export type { CheckboxProps } from './components/Checkbox';
|
|
43
|
+
|
|
44
|
+
export { Label } from './components/Label';
|
|
45
|
+
export type { LabelProps } from './components/Label';
|
|
46
|
+
|
|
47
|
+
// Utilities
|
|
48
|
+
export { cn } from './utils/cn';
|
|
49
|
+
|
|
50
|
+
// Theming
|
|
51
|
+
export { palettes } from './theming/color-palettes';
|
|
52
|
+
export type { SprinklesTheme, SprinklesColorPalette, Tone } from './theming/types';
|