@dailyautomations/ui 1.4.0 → 1.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.
- package/dist/components/ui/calendar.d.ts +9 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +37 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/combobox.d.ts +20 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +21 -0
- package/dist/components/ui/combobox.js.map +1 -0
- package/dist/components/ui/command.d.ts +81 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.js +30 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/date-picker.d.ts +13 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/date-picker.js +19 -0
- package/dist/components/ui/date-picker.js.map +1 -0
- package/dist/components/ui/form.d.ts +25 -0
- package/dist/components/ui/form.d.ts.map +1 -0
- package/dist/components/ui/form.js +62 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/input-otp.d.ts +15 -0
- package/dist/components/ui/input-otp.d.ts.map +1 -0
- package/dist/components/ui/input-otp.js +50 -0
- package/dist/components/ui/input-otp.js.map +1 -0
- package/dist/components/ui/textarea-autosize.d.ts +12 -0
- package/dist/components/ui/textarea-autosize.d.ts.map +1 -0
- package/dist/components/ui/textarea-autosize.js +44 -0
- package/dist/components/ui/textarea-autosize.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/native/components/common/badge.d.ts +12 -0
- package/dist/native/components/common/badge.d.ts.map +1 -0
- package/dist/native/components/common/badge.js +28 -0
- package/dist/native/components/common/badge.js.map +1 -0
- package/dist/native/components/common/button.d.ts +15 -0
- package/dist/native/components/common/button.d.ts.map +1 -0
- package/dist/native/components/common/button.js +55 -0
- package/dist/native/components/common/button.js.map +1 -0
- package/dist/native/components/common/card.d.ts +37 -0
- package/dist/native/components/common/card.d.ts.map +1 -0
- package/dist/native/components/common/card.js +23 -0
- package/dist/native/components/common/card.js.map +1 -0
- package/dist/native/components/common/checkbox.d.ts +8 -0
- package/dist/native/components/common/checkbox.d.ts.map +1 -0
- package/dist/native/components/common/checkbox.js +13 -0
- package/dist/native/components/common/checkbox.js.map +1 -0
- package/dist/native/components/common/input.d.ts +6 -0
- package/dist/native/components/common/input.d.ts.map +1 -0
- package/dist/native/components/common/input.js +8 -0
- package/dist/native/components/common/input.js.map +1 -0
- package/dist/native/components/common/label.d.ts +6 -0
- package/dist/native/components/common/label.d.ts.map +1 -0
- package/dist/native/components/common/label.js +7 -0
- package/dist/native/components/common/label.js.map +1 -0
- package/dist/native/components/common/textarea.d.ts +6 -0
- package/dist/native/components/common/textarea.d.ts.map +1 -0
- package/dist/native/components/common/textarea.js +9 -0
- package/dist/native/components/common/textarea.js.map +1 -0
- package/dist/native/components/ui/alert.d.ts +22 -0
- package/dist/native/components/ui/alert.d.ts.map +1 -0
- package/dist/native/components/ui/alert.js +32 -0
- package/dist/native/components/ui/alert.js.map +1 -0
- package/dist/native/components/ui/avatar.d.ts +23 -0
- package/dist/native/components/ui/avatar.d.ts.map +1 -0
- package/dist/native/components/ui/avatar.js +18 -0
- package/dist/native/components/ui/avatar.js.map +1 -0
- package/dist/native/components/ui/empty-state.d.ts +15 -0
- package/dist/native/components/ui/empty-state.d.ts.map +1 -0
- package/dist/native/components/ui/empty-state.js +8 -0
- package/dist/native/components/ui/empty-state.js.map +1 -0
- package/dist/native/components/ui/loading-spinner.d.ts +18 -0
- package/dist/native/components/ui/loading-spinner.d.ts.map +1 -0
- package/dist/native/components/ui/loading-spinner.js +49 -0
- package/dist/native/components/ui/loading-spinner.js.map +1 -0
- package/dist/native/components/ui/progress.d.ts +9 -0
- package/dist/native/components/ui/progress.d.ts.map +1 -0
- package/dist/native/components/ui/progress.js +22 -0
- package/dist/native/components/ui/progress.js.map +1 -0
- package/dist/native/components/ui/separator.d.ts +11 -0
- package/dist/native/components/ui/separator.d.ts.map +1 -0
- package/dist/native/components/ui/separator.js +9 -0
- package/dist/native/components/ui/separator.js.map +1 -0
- package/dist/native/components/ui/skeleton.d.ts +10 -0
- package/dist/native/components/ui/skeleton.d.ts.map +1 -0
- package/dist/native/components/ui/skeleton.js +33 -0
- package/dist/native/components/ui/skeleton.js.map +1 -0
- package/dist/native/components/ui/switch.d.ts +8 -0
- package/dist/native/components/ui/switch.d.ts.map +1 -0
- package/dist/native/components/ui/switch.js +10 -0
- package/dist/native/components/ui/switch.js.map +1 -0
- package/dist/native/index.d.ts +33 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +18 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/lib/animations.d.ts +145 -0
- package/dist/native/lib/animations.d.ts.map +1 -0
- package/dist/native/lib/animations.js +96 -0
- package/dist/native/lib/animations.js.map +1 -0
- package/dist/native/utils/cn.d.ts +5 -0
- package/dist/native/utils/cn.d.ts.map +1 -0
- package/dist/native/utils/cn.js +33 -0
- package/dist/native/utils/cn.js.map +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +2 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/tokens/colors.d.ts +493 -0
- package/dist/shared/tokens/colors.d.ts.map +1 -0
- package/dist/shared/tokens/colors.js +275 -0
- package/dist/shared/tokens/colors.js.map +1 -0
- package/dist/shared/tokens/index.d.ts +551 -0
- package/dist/shared/tokens/index.d.ts.map +1 -0
- package/dist/shared/tokens/index.js +14 -0
- package/dist/shared/tokens/index.js.map +1 -0
- package/dist/shared/tokens/radius.d.ts +17 -0
- package/dist/shared/tokens/radius.d.ts.map +1 -0
- package/dist/shared/tokens/radius.js +25 -0
- package/dist/shared/tokens/radius.js.map +1 -0
- package/dist/shared/tokens/spacing.d.ts +42 -0
- package/dist/shared/tokens/spacing.d.ts.map +1 -0
- package/dist/shared/tokens/spacing.js +48 -0
- package/dist/shared/tokens/spacing.js.map +1 -0
- package/package.json +120 -1
- package/src/native/components/common/badge.tsx +64 -0
- package/src/native/components/common/button.tsx +130 -0
- package/src/native/components/common/card.tsx +113 -0
- package/src/native/components/common/checkbox.tsx +50 -0
- package/src/native/components/common/input.tsx +42 -0
- package/src/native/components/common/label.tsx +27 -0
- package/src/native/components/common/textarea.tsx +44 -0
- package/src/native/components/ui/alert.tsx +94 -0
- package/src/native/components/ui/avatar.tsx +73 -0
- package/src/native/components/ui/empty-state.tsx +76 -0
- package/src/native/components/ui/loading-spinner.tsx +108 -0
- package/src/native/components/ui/progress.tsx +56 -0
- package/src/native/components/ui/separator.tsx +43 -0
- package/src/native/components/ui/skeleton.tsx +68 -0
- package/src/native/components/ui/switch.tsx +40 -0
- package/src/native/index.ts +74 -0
- package/src/native/lib/animations.ts +119 -0
- package/src/native/utils/cn.ts +57 -0
- package/src/shared/index.ts +6 -0
- package/src/shared/tokens/colors.ts +311 -0
- package/src/shared/tokens/index.ts +38 -0
- package/src/shared/tokens/radius.ts +39 -0
- package/src/shared/tokens/spacing.ts +61 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Alert component
|
|
3
|
+
* View-based alert matching web Alert API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { View, Text, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
|
|
10
|
+
type AlertVariant = 'default' | 'destructive' | 'success' | 'warning';
|
|
11
|
+
|
|
12
|
+
export interface AlertProps {
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
variant?: AlertVariant;
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: ViewStyle;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const variantClasses: Record<AlertVariant, { container: string; text: string }> = {
|
|
20
|
+
default: {
|
|
21
|
+
container: 'bg-card border-border',
|
|
22
|
+
text: 'text-foreground',
|
|
23
|
+
},
|
|
24
|
+
destructive: {
|
|
25
|
+
container: 'border-red-500/50 bg-red-500/10',
|
|
26
|
+
text: 'text-red-400',
|
|
27
|
+
},
|
|
28
|
+
success: {
|
|
29
|
+
container: 'border-green-500/50 bg-green-500/10',
|
|
30
|
+
text: 'text-green-400',
|
|
31
|
+
},
|
|
32
|
+
warning: {
|
|
33
|
+
container: 'border-amber-500/50 bg-amber-500/10',
|
|
34
|
+
text: 'text-amber-400',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function Alert({
|
|
39
|
+
children,
|
|
40
|
+
variant = 'default',
|
|
41
|
+
className,
|
|
42
|
+
style,
|
|
43
|
+
}: AlertProps) {
|
|
44
|
+
const variantStyle = variantClasses[variant];
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<View
|
|
48
|
+
data-slot="alert"
|
|
49
|
+
data-variant={variant}
|
|
50
|
+
className={cn(
|
|
51
|
+
'rounded-lg border p-4',
|
|
52
|
+
variantStyle.container,
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
style={style}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</View>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface AlertTitleProps {
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
className?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function AlertTitle({ children, className }: AlertTitleProps) {
|
|
68
|
+
return (
|
|
69
|
+
<Text
|
|
70
|
+
data-slot="alert-title"
|
|
71
|
+
className={cn('text-base font-semibold mb-1', className)}
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
</Text>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface AlertDescriptionProps {
|
|
79
|
+
children?: React.ReactNode;
|
|
80
|
+
className?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function AlertDescription({ children, className }: AlertDescriptionProps) {
|
|
84
|
+
return (
|
|
85
|
+
<Text
|
|
86
|
+
data-slot="alert-description"
|
|
87
|
+
className={cn('text-sm opacity-80', className)}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</Text>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type { AlertVariant };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Avatar components
|
|
3
|
+
* Image + fallback matching web Avatar API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { View, Image, Text, type ImageStyle, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
|
|
10
|
+
export interface AvatarProps {
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: ViewStyle;
|
|
14
|
+
size?: 'sm' | 'md' | 'lg';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const sizeClasses = {
|
|
18
|
+
sm: 'h-8 w-8',
|
|
19
|
+
md: 'h-10 w-10',
|
|
20
|
+
lg: 'h-12 w-12',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function Avatar({ children, className, style, size = 'md' }: AvatarProps) {
|
|
24
|
+
return (
|
|
25
|
+
<View
|
|
26
|
+
data-slot="avatar"
|
|
27
|
+
className={cn(
|
|
28
|
+
'rounded-full overflow-hidden items-center justify-center bg-muted',
|
|
29
|
+
sizeClasses[size],
|
|
30
|
+
className
|
|
31
|
+
)}
|
|
32
|
+
style={style}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
</View>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface AvatarImageProps {
|
|
40
|
+
source: { uri: string };
|
|
41
|
+
className?: string;
|
|
42
|
+
style?: ImageStyle;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function AvatarImage({ source, className, style }: AvatarImageProps) {
|
|
46
|
+
return (
|
|
47
|
+
<Image
|
|
48
|
+
data-slot="avatar-image"
|
|
49
|
+
source={source}
|
|
50
|
+
className={cn('h-full w-full', className)}
|
|
51
|
+
style={style}
|
|
52
|
+
resizeMode="cover"
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface AvatarFallbackProps {
|
|
58
|
+
children?: React.ReactNode;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function AvatarFallback({ children, className }: AvatarFallbackProps) {
|
|
63
|
+
return (
|
|
64
|
+
<View
|
|
65
|
+
data-slot="avatar-fallback"
|
|
66
|
+
className={cn('h-full w-full items-center justify-center bg-muted', className)}
|
|
67
|
+
>
|
|
68
|
+
<Text className="text-sm font-semibold text-muted-foreground">
|
|
69
|
+
{children}
|
|
70
|
+
</Text>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native EmptyState component
|
|
3
|
+
* View + Text based empty state matching web EmptyState API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { View, Text, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
|
|
10
|
+
type EmptyStateVariant = 'default' | 'compact';
|
|
11
|
+
|
|
12
|
+
export interface EmptyStateProps {
|
|
13
|
+
icon?: React.ReactNode;
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
action?: React.ReactNode;
|
|
17
|
+
variant?: EmptyStateVariant;
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: ViewStyle;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function EmptyState({
|
|
23
|
+
icon,
|
|
24
|
+
title = 'No results',
|
|
25
|
+
description,
|
|
26
|
+
action,
|
|
27
|
+
variant = 'default',
|
|
28
|
+
className,
|
|
29
|
+
style,
|
|
30
|
+
}: EmptyStateProps) {
|
|
31
|
+
const isCompact = variant === 'compact';
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View
|
|
35
|
+
data-slot="empty-state"
|
|
36
|
+
data-variant={variant}
|
|
37
|
+
className={cn(
|
|
38
|
+
'items-center justify-center py-8 px-4',
|
|
39
|
+
isCompact ? 'py-4' : 'py-8',
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
style={style}
|
|
43
|
+
>
|
|
44
|
+
{icon && (
|
|
45
|
+
<View className={cn('mb-4', isCompact && 'mb-2')}>
|
|
46
|
+
{icon}
|
|
47
|
+
</View>
|
|
48
|
+
)}
|
|
49
|
+
<Text
|
|
50
|
+
className={cn(
|
|
51
|
+
'text-center font-semibold text-muted-foreground',
|
|
52
|
+
isCompact ? 'text-sm' : 'text-lg'
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
{title}
|
|
56
|
+
</Text>
|
|
57
|
+
{description && (
|
|
58
|
+
<Text
|
|
59
|
+
className={cn(
|
|
60
|
+
'text-center text-muted-foreground mt-1',
|
|
61
|
+
isCompact ? 'text-xs' : 'text-sm'
|
|
62
|
+
)}
|
|
63
|
+
>
|
|
64
|
+
{description}
|
|
65
|
+
</Text>
|
|
66
|
+
)}
|
|
67
|
+
{action && (
|
|
68
|
+
<View className="mt-4">
|
|
69
|
+
{action}
|
|
70
|
+
</View>
|
|
71
|
+
)}
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type { EmptyStateVariant };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native LoadingSpinner components
|
|
3
|
+
* Animated spinner matching web LoadingSpinner API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { View, Animated, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
import { colors } from '../../../shared/tokens';
|
|
10
|
+
|
|
11
|
+
type SpinnerSize = 'sm' | 'md' | 'lg';
|
|
12
|
+
|
|
13
|
+
export interface LoadingSpinnerProps {
|
|
14
|
+
size?: SpinnerSize;
|
|
15
|
+
color?: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: ViewStyle;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const sizeMap: Record<SpinnerSize, number> = {
|
|
21
|
+
sm: 16,
|
|
22
|
+
md: 24,
|
|
23
|
+
lg: 32,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function LoadingSpinner({
|
|
27
|
+
size = 'md',
|
|
28
|
+
color,
|
|
29
|
+
className,
|
|
30
|
+
style,
|
|
31
|
+
}: LoadingSpinnerProps) {
|
|
32
|
+
const rotation = React.useRef(new Animated.Value(0)).current;
|
|
33
|
+
const spinnerSize = sizeMap[size];
|
|
34
|
+
const spinnerColor = color || colors.primary.hex;
|
|
35
|
+
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
const animation = Animated.loop(
|
|
38
|
+
Animated.timing(rotation, {
|
|
39
|
+
toValue: 1,
|
|
40
|
+
duration: 1000,
|
|
41
|
+
useNativeDriver: true,
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
animation.start();
|
|
46
|
+
return () => animation.stop();
|
|
47
|
+
}, [rotation]);
|
|
48
|
+
|
|
49
|
+
const spin = rotation.interpolate({
|
|
50
|
+
inputRange: [0, 1],
|
|
51
|
+
outputRange: ['0deg', '360deg'],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Animated.View
|
|
56
|
+
data-slot="loading-spinner"
|
|
57
|
+
data-size={size}
|
|
58
|
+
className={cn('items-center justify-center', className)}
|
|
59
|
+
style={[
|
|
60
|
+
{
|
|
61
|
+
width: spinnerSize,
|
|
62
|
+
height: spinnerSize,
|
|
63
|
+
transform: [{ rotate: spin }],
|
|
64
|
+
},
|
|
65
|
+
style,
|
|
66
|
+
]}
|
|
67
|
+
>
|
|
68
|
+
<View
|
|
69
|
+
style={{
|
|
70
|
+
width: spinnerSize,
|
|
71
|
+
height: spinnerSize,
|
|
72
|
+
borderRadius: spinnerSize / 2,
|
|
73
|
+
borderWidth: 2,
|
|
74
|
+
borderColor: spinnerColor,
|
|
75
|
+
borderTopColor: 'transparent',
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
</Animated.View>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface LoadingOverlayProps {
|
|
83
|
+
visible: boolean;
|
|
84
|
+
children?: React.ReactNode;
|
|
85
|
+
className?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function LoadingOverlay({
|
|
89
|
+
visible,
|
|
90
|
+
children,
|
|
91
|
+
className,
|
|
92
|
+
}: LoadingOverlayProps) {
|
|
93
|
+
if (!visible) return null;
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<View
|
|
97
|
+
data-slot="loading-overlay"
|
|
98
|
+
className={cn(
|
|
99
|
+
'absolute inset-0 bg-background/80 items-center justify-center',
|
|
100
|
+
className
|
|
101
|
+
)}
|
|
102
|
+
>
|
|
103
|
+
{children || <LoadingSpinner size="lg" />}
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type { SpinnerSize };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Progress component
|
|
3
|
+
* Animated width progress bar matching web Progress API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { View, Animated, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
|
|
10
|
+
export interface ProgressProps {
|
|
11
|
+
value?: number;
|
|
12
|
+
max?: number;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: ViewStyle;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function Progress({
|
|
18
|
+
value = 0,
|
|
19
|
+
max = 100,
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
}: ProgressProps) {
|
|
23
|
+
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
|
|
24
|
+
const animatedWidth = React.useRef(new Animated.Value(0)).current;
|
|
25
|
+
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
Animated.timing(animatedWidth, {
|
|
28
|
+
toValue: percentage,
|
|
29
|
+
duration: 300,
|
|
30
|
+
useNativeDriver: false,
|
|
31
|
+
}).start();
|
|
32
|
+
}, [percentage, animatedWidth]);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<View
|
|
36
|
+
data-slot="progress"
|
|
37
|
+
className={cn(
|
|
38
|
+
'h-2 w-full rounded-full bg-muted overflow-hidden',
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
style={style}
|
|
42
|
+
accessibilityRole="progressbar"
|
|
43
|
+
accessibilityValue={{ min: 0, max, now: value }}
|
|
44
|
+
>
|
|
45
|
+
<Animated.View
|
|
46
|
+
className="h-full bg-primary rounded-full"
|
|
47
|
+
style={{
|
|
48
|
+
width: animatedWidth.interpolate({
|
|
49
|
+
inputRange: [0, 100],
|
|
50
|
+
outputRange: ['0%', '100%'],
|
|
51
|
+
}),
|
|
52
|
+
}}
|
|
53
|
+
/>
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Separator component
|
|
3
|
+
* View-based separator matching web Separator API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { View, type ViewStyle } from 'react-native';
|
|
7
|
+
import { cn } from '../../utils/cn';
|
|
8
|
+
|
|
9
|
+
type SeparatorOrientation = 'horizontal' | 'vertical';
|
|
10
|
+
|
|
11
|
+
export interface SeparatorProps {
|
|
12
|
+
orientation?: SeparatorOrientation;
|
|
13
|
+
decorative?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: ViewStyle;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Separator({
|
|
19
|
+
orientation = 'horizontal',
|
|
20
|
+
decorative = true,
|
|
21
|
+
className,
|
|
22
|
+
style,
|
|
23
|
+
}: SeparatorProps) {
|
|
24
|
+
const isHorizontal = orientation === 'horizontal';
|
|
25
|
+
|
|
26
|
+
const containerClasses = cn(
|
|
27
|
+
'bg-border shrink-0',
|
|
28
|
+
isHorizontal ? 'h-px w-full' : 'h-full w-px',
|
|
29
|
+
className
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<View
|
|
34
|
+
data-slot="separator"
|
|
35
|
+
data-orientation={orientation}
|
|
36
|
+
className={containerClasses}
|
|
37
|
+
style={style}
|
|
38
|
+
accessibilityRole={decorative ? undefined : 'separator'}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type { SeparatorOrientation };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Skeleton component
|
|
3
|
+
* Animated placeholder for loading states
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { Animated, type ViewStyle } from 'react-native';
|
|
8
|
+
import { cn } from '../../utils/cn';
|
|
9
|
+
|
|
10
|
+
export interface SkeletonProps {
|
|
11
|
+
className?: string;
|
|
12
|
+
style?: ViewStyle;
|
|
13
|
+
width?: number | string;
|
|
14
|
+
height?: number;
|
|
15
|
+
rounded?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Skeleton({
|
|
19
|
+
className,
|
|
20
|
+
style,
|
|
21
|
+
width,
|
|
22
|
+
height = 20,
|
|
23
|
+
rounded = false,
|
|
24
|
+
}: SkeletonProps) {
|
|
25
|
+
const animatedValue = React.useRef(new Animated.Value(0.4)).current;
|
|
26
|
+
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
const animation = Animated.loop(
|
|
29
|
+
Animated.sequence([
|
|
30
|
+
Animated.timing(animatedValue, {
|
|
31
|
+
toValue: 1,
|
|
32
|
+
duration: 1000,
|
|
33
|
+
useNativeDriver: true,
|
|
34
|
+
}),
|
|
35
|
+
Animated.timing(animatedValue, {
|
|
36
|
+
toValue: 0.4,
|
|
37
|
+
duration: 1000,
|
|
38
|
+
useNativeDriver: true,
|
|
39
|
+
}),
|
|
40
|
+
])
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
animation.start();
|
|
44
|
+
|
|
45
|
+
return () => animation.stop();
|
|
46
|
+
}, [animatedValue]);
|
|
47
|
+
|
|
48
|
+
const containerClasses = cn(
|
|
49
|
+
'bg-muted',
|
|
50
|
+
rounded ? 'rounded-full' : 'rounded-md',
|
|
51
|
+
className
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Animated.View
|
|
56
|
+
data-slot="skeleton"
|
|
57
|
+
className={containerClasses}
|
|
58
|
+
style={[
|
|
59
|
+
{
|
|
60
|
+
width: width ?? '100%',
|
|
61
|
+
height,
|
|
62
|
+
opacity: animatedValue,
|
|
63
|
+
},
|
|
64
|
+
style,
|
|
65
|
+
]}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Switch component
|
|
3
|
+
* React Native Switch wrapper matching web Switch API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Switch as RNSwitch,
|
|
8
|
+
type SwitchProps as RNSwitchProps,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
import { colors } from '../../../shared/tokens';
|
|
11
|
+
|
|
12
|
+
export interface SwitchProps extends Omit<RNSwitchProps, 'value' | 'onValueChange'> {
|
|
13
|
+
checked?: boolean;
|
|
14
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Switch({
|
|
19
|
+
checked = false,
|
|
20
|
+
onCheckedChange,
|
|
21
|
+
disabled = false,
|
|
22
|
+
...props
|
|
23
|
+
}: SwitchProps) {
|
|
24
|
+
return (
|
|
25
|
+
<RNSwitch
|
|
26
|
+
data-slot="switch"
|
|
27
|
+
data-checked={checked}
|
|
28
|
+
value={checked}
|
|
29
|
+
onValueChange={onCheckedChange}
|
|
30
|
+
disabled={disabled}
|
|
31
|
+
trackColor={{
|
|
32
|
+
false: colors.muted.hex,
|
|
33
|
+
true: colors.primary.hex,
|
|
34
|
+
}}
|
|
35
|
+
thumbColor={colors.foreground.hex}
|
|
36
|
+
ios_backgroundColor={colors.muted.hex}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dailyautomations/ui/native
|
|
3
|
+
* React Native components for Daily X platform
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { Button, Card } from '@dailyautomations/ui/native';
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Utilities
|
|
10
|
+
export { cn, createVariant } from './utils/cn';
|
|
11
|
+
|
|
12
|
+
// Animations
|
|
13
|
+
export * from './lib/animations';
|
|
14
|
+
|
|
15
|
+
// Common Components
|
|
16
|
+
export { Button } from './components/common/button';
|
|
17
|
+
export type { ButtonProps, ButtonVariant, ButtonSize } from './components/common/button';
|
|
18
|
+
|
|
19
|
+
export { Input } from './components/common/input';
|
|
20
|
+
export type { InputProps } from './components/common/input';
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
Card,
|
|
24
|
+
CardHeader,
|
|
25
|
+
CardTitle,
|
|
26
|
+
CardDescription,
|
|
27
|
+
CardContent,
|
|
28
|
+
CardFooter,
|
|
29
|
+
} from './components/common/card';
|
|
30
|
+
export type {
|
|
31
|
+
CardProps,
|
|
32
|
+
CardHeaderProps,
|
|
33
|
+
CardTitleProps,
|
|
34
|
+
CardDescriptionProps,
|
|
35
|
+
CardContentProps,
|
|
36
|
+
CardFooterProps,
|
|
37
|
+
} from './components/common/card';
|
|
38
|
+
|
|
39
|
+
export { Badge } from './components/common/badge';
|
|
40
|
+
export type { BadgeProps, BadgeVariant } from './components/common/badge';
|
|
41
|
+
|
|
42
|
+
export { Label } from './components/common/label';
|
|
43
|
+
export type { LabelProps } from './components/common/label';
|
|
44
|
+
|
|
45
|
+
export { Textarea } from './components/common/textarea';
|
|
46
|
+
export type { TextareaProps } from './components/common/textarea';
|
|
47
|
+
|
|
48
|
+
export { Checkbox } from './components/common/checkbox';
|
|
49
|
+
export type { CheckboxProps } from './components/common/checkbox';
|
|
50
|
+
|
|
51
|
+
// UI Components
|
|
52
|
+
export { Alert, AlertTitle, AlertDescription } from './components/ui/alert';
|
|
53
|
+
export type { AlertProps, AlertTitleProps, AlertDescriptionProps, AlertVariant } from './components/ui/alert';
|
|
54
|
+
|
|
55
|
+
export { Skeleton } from './components/ui/skeleton';
|
|
56
|
+
export type { SkeletonProps } from './components/ui/skeleton';
|
|
57
|
+
|
|
58
|
+
export { Switch } from './components/ui/switch';
|
|
59
|
+
export type { SwitchProps } from './components/ui/switch';
|
|
60
|
+
|
|
61
|
+
export { Separator } from './components/ui/separator';
|
|
62
|
+
export type { SeparatorProps, SeparatorOrientation } from './components/ui/separator';
|
|
63
|
+
|
|
64
|
+
export { Avatar, AvatarImage, AvatarFallback } from './components/ui/avatar';
|
|
65
|
+
export type { AvatarProps, AvatarImageProps, AvatarFallbackProps } from './components/ui/avatar';
|
|
66
|
+
|
|
67
|
+
export { Progress } from './components/ui/progress';
|
|
68
|
+
export type { ProgressProps } from './components/ui/progress';
|
|
69
|
+
|
|
70
|
+
export { LoadingSpinner, LoadingOverlay } from './components/ui/loading-spinner';
|
|
71
|
+
export type { LoadingSpinnerProps, LoadingOverlayProps, SpinnerSize } from './components/ui/loading-spinner';
|
|
72
|
+
|
|
73
|
+
export { EmptyState } from './components/ui/empty-state';
|
|
74
|
+
export type { EmptyStateProps, EmptyStateVariant } from './components/ui/empty-state';
|