@retray-dev/ui-kit 0.1.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.
Files changed (56) hide show
  1. package/COMPONENTS.md +710 -0
  2. package/LICENSE +21 -0
  3. package/README.md +150 -0
  4. package/dist/index.d.mts +345 -4
  5. package/dist/index.d.ts +345 -4
  6. package/dist/index.js +1644 -58
  7. package/dist/index.mjs +1590 -58
  8. package/package.json +44 -5
  9. package/src/components/Accordion/Accordion.tsx +173 -0
  10. package/src/components/Accordion/index.ts +2 -0
  11. package/src/components/Alert/Alert.tsx +59 -0
  12. package/src/components/Alert/index.ts +2 -0
  13. package/src/components/Avatar/Avatar.tsx +71 -0
  14. package/src/components/Avatar/index.ts +2 -0
  15. package/src/components/Badge/Badge.tsx +48 -0
  16. package/src/components/Badge/index.ts +2 -0
  17. package/src/components/Button/Button.tsx +94 -45
  18. package/src/components/Card/Card.tsx +103 -0
  19. package/src/components/Card/index.ts +9 -0
  20. package/src/components/Checkbox/Checkbox.tsx +98 -0
  21. package/src/components/Checkbox/index.ts +2 -0
  22. package/src/components/EmptyState/EmptyState.tsx +67 -0
  23. package/src/components/EmptyState/index.ts +2 -0
  24. package/src/components/Input/Input.tsx +28 -35
  25. package/src/components/Progress/Progress.tsx +52 -0
  26. package/src/components/Progress/index.ts +2 -0
  27. package/src/components/RadioGroup/RadioGroup.tsx +132 -0
  28. package/src/components/RadioGroup/index.ts +2 -0
  29. package/src/components/Select/Select.tsx +232 -0
  30. package/src/components/Select/index.ts +2 -0
  31. package/src/components/Separator/Separator.tsx +33 -0
  32. package/src/components/Separator/index.ts +2 -0
  33. package/src/components/Sheet/Sheet.tsx +115 -0
  34. package/src/components/Sheet/index.ts +2 -0
  35. package/src/components/Skeleton/Skeleton.tsx +63 -0
  36. package/src/components/Skeleton/index.ts +2 -0
  37. package/src/components/Slider/Slider.tsx +143 -0
  38. package/src/components/Slider/index.ts +2 -0
  39. package/src/components/Spinner/Spinner.tsx +21 -0
  40. package/src/components/Spinner/index.ts +2 -0
  41. package/src/components/Switch/Switch.tsx +86 -0
  42. package/src/components/Switch/index.ts +2 -0
  43. package/src/components/Tabs/Tabs.tsx +196 -0
  44. package/src/components/Tabs/index.ts +2 -0
  45. package/src/components/Text/Text.tsx +10 -4
  46. package/src/components/Textarea/Textarea.tsx +89 -0
  47. package/src/components/Textarea/index.ts +2 -0
  48. package/src/components/Toast/Toast.tsx +200 -0
  49. package/src/components/Toast/index.ts +2 -0
  50. package/src/components/Toggle/Toggle.tsx +92 -0
  51. package/src/components/Toggle/index.ts +2 -0
  52. package/src/index.ts +26 -0
  53. package/src/theme/ThemeProvider.tsx +47 -0
  54. package/src/theme/colors.ts +45 -0
  55. package/src/theme/index.ts +4 -0
  56. package/src/theme/types.ts +33 -0
@@ -0,0 +1,92 @@
1
+ import React, { useRef } from 'react'
2
+ import { TouchableOpacity, Animated, Text, StyleSheet, TouchableOpacityProps, ViewStyle } from 'react-native'
3
+ import * as Haptics from 'expo-haptics'
4
+ import { useTheme } from '../../theme'
5
+
6
+ export type ToggleVariant = 'default' | 'outline'
7
+ export type ToggleSize = 'sm' | 'md' | 'lg'
8
+
9
+ export interface ToggleProps extends TouchableOpacityProps {
10
+ pressed?: boolean
11
+ onPressedChange?: (pressed: boolean) => void
12
+ variant?: ToggleVariant
13
+ size?: ToggleSize
14
+ label?: string
15
+ icon?: React.ReactNode
16
+ }
17
+
18
+ const sizeStyles: Record<ToggleSize, ViewStyle> = {
19
+ sm: { paddingHorizontal: 12, paddingVertical: 8, minWidth: 40, minHeight: 40 },
20
+ md: { paddingHorizontal: 16, paddingVertical: 12, minWidth: 44, minHeight: 44 },
21
+ lg: { paddingHorizontal: 20, paddingVertical: 14, minWidth: 48, minHeight: 48 },
22
+ }
23
+
24
+ export function Toggle({
25
+ pressed = false,
26
+ onPressedChange,
27
+ variant = 'default',
28
+ size = 'md',
29
+ label,
30
+ icon,
31
+ disabled,
32
+ style,
33
+ ...props
34
+ }: ToggleProps) {
35
+ const { colors } = useTheme()
36
+ const scale = useRef(new Animated.Value(1)).current
37
+
38
+ const handlePressIn = () => {
39
+ if (disabled) return
40
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start()
41
+ }
42
+
43
+ const handlePressOut = () => {
44
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start()
45
+ }
46
+
47
+ const containerStyle: ViewStyle = pressed
48
+ ? { backgroundColor: colors.accent }
49
+ : variant === 'outline'
50
+ ? { backgroundColor: 'transparent', borderWidth: 1, borderColor: colors.border }
51
+ : { backgroundColor: 'transparent' }
52
+
53
+ const textColor = pressed ? colors.accentForeground : colors.foreground
54
+
55
+ return (
56
+ <Animated.View style={{ transform: [{ scale }] }}>
57
+ <TouchableOpacity
58
+ style={[styles.base, containerStyle, sizeStyles[size], disabled && styles.disabled, style]}
59
+ onPress={() => {
60
+ Haptics.selectionAsync()
61
+ onPressedChange?.(!pressed)
62
+ }}
63
+ onPressIn={handlePressIn}
64
+ onPressOut={handlePressOut}
65
+ disabled={disabled}
66
+ activeOpacity={1}
67
+ touchSoundDisabled={true}
68
+ {...props}
69
+ >
70
+ {icon}
71
+ {label ? <Text style={[styles.label, { color: textColor }]}>{label}</Text> : null}
72
+ </TouchableOpacity>
73
+ </Animated.View>
74
+ )
75
+ }
76
+
77
+ const styles = StyleSheet.create({
78
+ base: {
79
+ borderRadius: 8,
80
+ flexDirection: 'row',
81
+ alignItems: 'center',
82
+ justifyContent: 'center',
83
+ gap: 8,
84
+ },
85
+ disabled: {
86
+ opacity: 0.45,
87
+ },
88
+ label: {
89
+ fontSize: 14,
90
+ fontWeight: '500',
91
+ },
92
+ })
@@ -0,0 +1,2 @@
1
+ export { Toggle } from './Toggle'
2
+ export type { ToggleProps, ToggleVariant, ToggleSize } from './Toggle'
package/src/index.ts CHANGED
@@ -1,3 +1,29 @@
1
+ // Theme
2
+ export { ThemeProvider, useTheme } from './theme'
3
+ export type { ThemeProviderProps, ThemeColors, Theme, ColorScheme } from './theme'
4
+ export { defaultLight, defaultDark } from './theme'
5
+
6
+ // Components
1
7
  export * from './components/Button'
2
8
  export * from './components/Text'
3
9
  export * from './components/Input'
10
+ export * from './components/Badge'
11
+ export * from './components/Card'
12
+ export * from './components/Separator'
13
+ export * from './components/Spinner'
14
+ export * from './components/Skeleton'
15
+ export * from './components/Avatar'
16
+ export * from './components/Alert'
17
+ export * from './components/Progress'
18
+ export * from './components/EmptyState'
19
+ export * from './components/Textarea'
20
+ export * from './components/Checkbox'
21
+ export * from './components/Switch'
22
+ export * from './components/Toggle'
23
+ export * from './components/RadioGroup'
24
+ export * from './components/Tabs'
25
+ export * from './components/Accordion'
26
+ export * from './components/Slider'
27
+ export * from './components/Sheet'
28
+ export * from './components/Select'
29
+ export * from './components/Toast'
@@ -0,0 +1,47 @@
1
+ import React, { createContext, useContext, useMemo } from 'react'
2
+ import { useColorScheme } from 'react-native'
3
+ import { ThemeColors, Theme, ColorScheme, ThemeContextValue } from './types'
4
+ import { defaultLight, defaultDark } from './colors'
5
+
6
+ const ThemeContext = createContext<ThemeContextValue>({
7
+ colors: defaultLight,
8
+ colorScheme: 'light',
9
+ })
10
+
11
+ export interface ThemeProviderProps {
12
+ children: React.ReactNode
13
+ /**
14
+ * Override individual color tokens per scheme. Only provide the tokens you want
15
+ * to change — the rest fall back to the defaults.
16
+ * @example
17
+ * { light: { primary: '#6366f1', primaryForeground: '#fff' },
18
+ * dark: { primary: '#818cf8', primaryForeground: '#fff' } }
19
+ */
20
+ theme?: Theme
21
+ /**
22
+ * - `'system'` (default): auto-detects device setting and updates when it changes.
23
+ * - `'light'` / `'dark'`: forces a specific scheme regardless of device setting.
24
+ */
25
+ colorScheme?: ColorScheme
26
+ }
27
+
28
+ export function ThemeProvider({ children, theme, colorScheme = 'system' }: ThemeProviderProps) {
29
+ const systemScheme = useColorScheme() ?? 'light'
30
+ const resolvedScheme: 'light' | 'dark' = colorScheme === 'system' ? systemScheme : colorScheme
31
+
32
+ const colors = useMemo<ThemeColors>(() => {
33
+ const base = resolvedScheme === 'dark' ? defaultDark : defaultLight
34
+ const overrides = resolvedScheme === 'dark' ? theme?.dark : theme?.light
35
+ return { ...base, ...overrides }
36
+ }, [resolvedScheme, theme])
37
+
38
+ return (
39
+ <ThemeContext.Provider value={{ colors, colorScheme: resolvedScheme }}>
40
+ {children}
41
+ </ThemeContext.Provider>
42
+ )
43
+ }
44
+
45
+ export function useTheme(): ThemeContextValue {
46
+ return useContext(ThemeContext)
47
+ }
@@ -0,0 +1,45 @@
1
+ import { ThemeColors } from './types'
2
+
3
+ export const defaultLight: ThemeColors = {
4
+ background: '#ffffff',
5
+ foreground: '#171717',
6
+ card: '#ffffff',
7
+ cardForeground: '#171717',
8
+ primary: '#1a1a1a',
9
+ primaryForeground: '#fafafa',
10
+ secondary: '#f5f5f5',
11
+ secondaryForeground: '#1a1a1a',
12
+ muted: '#f5f5f5',
13
+ mutedForeground: '#646464',
14
+ accent: '#f5f5f5',
15
+ accentForeground: '#1a1a1a',
16
+ destructive: '#ef4444',
17
+ destructiveForeground: '#fafafa',
18
+ border: '#e5e5e5',
19
+ input: '#e5e5e5',
20
+ ring: '#a3a3a3',
21
+ success: '#16a34a',
22
+ successForeground: '#ffffff',
23
+ }
24
+
25
+ export const defaultDark: ThemeColors = {
26
+ background: '#171717',
27
+ foreground: '#fafafa',
28
+ card: '#1f1f1f',
29
+ cardForeground: '#fafafa',
30
+ primary: '#fafafa',
31
+ primaryForeground: '#1a1a1a',
32
+ secondary: '#2a2a2a',
33
+ secondaryForeground: '#fafafa',
34
+ muted: '#2a2a2a',
35
+ mutedForeground: '#a3a3a3',
36
+ accent: '#2a2a2a',
37
+ accentForeground: '#fafafa',
38
+ destructive: '#dc2626',
39
+ destructiveForeground: '#fafafa',
40
+ border: '#2a2a2a',
41
+ input: '#2a2a2a',
42
+ ring: '#d4d4d4',
43
+ success: '#22c55e',
44
+ successForeground: '#ffffff',
45
+ }
@@ -0,0 +1,4 @@
1
+ export { ThemeProvider, useTheme } from './ThemeProvider'
2
+ export type { ThemeProviderProps } from './ThemeProvider'
3
+ export type { ThemeColors, Theme, ColorScheme } from './types'
4
+ export { defaultLight, defaultDark } from './colors'
@@ -0,0 +1,33 @@
1
+ export type ThemeColors = {
2
+ background: string
3
+ foreground: string
4
+ card: string
5
+ cardForeground: string
6
+ primary: string
7
+ primaryForeground: string
8
+ secondary: string
9
+ secondaryForeground: string
10
+ muted: string
11
+ mutedForeground: string
12
+ accent: string
13
+ accentForeground: string
14
+ destructive: string
15
+ destructiveForeground: string
16
+ border: string
17
+ input: string
18
+ ring: string
19
+ success: string
20
+ successForeground: string
21
+ }
22
+
23
+ export type Theme = {
24
+ light?: Partial<ThemeColors>
25
+ dark?: Partial<ThemeColors>
26
+ }
27
+
28
+ export type ColorScheme = 'light' | 'dark' | 'system'
29
+
30
+ export type ThemeContextValue = {
31
+ colors: ThemeColors
32
+ colorScheme: 'light' | 'dark'
33
+ }