rangaat 0.1.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 (72) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +102 -0
  3. package/Rangaat.podspec +20 -0
  4. package/android/build.gradle +67 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/rangaat/RangaatPackage.kt +17 -0
  7. package/android/src/main/java/com/rangaat/RangaatView.kt +15 -0
  8. package/android/src/main/java/com/rangaat/RangaatViewManager.kt +41 -0
  9. package/ios/RangaatView.h +14 -0
  10. package/ios/RangaatView.mm +48 -0
  11. package/lib/module/RangaatView.js +17 -0
  12. package/lib/module/RangaatView.js.map +1 -0
  13. package/lib/module/RangaatView.native.js +5 -0
  14. package/lib/module/RangaatView.native.js.map +1 -0
  15. package/lib/module/RangaatViewNativeComponent.ts +11 -0
  16. package/lib/module/components/Button/Button.js +53 -0
  17. package/lib/module/components/Button/Button.js.map +1 -0
  18. package/lib/module/components/Button/index.js +4 -0
  19. package/lib/module/components/Button/index.js.map +1 -0
  20. package/lib/module/components/Button/styles.js +113 -0
  21. package/lib/module/components/Button/styles.js.map +1 -0
  22. package/lib/module/components/Button/types.js +4 -0
  23. package/lib/module/components/Button/types.js.map +1 -0
  24. package/lib/module/hooks/useTheme.js +20 -0
  25. package/lib/module/hooks/useTheme.js.map +1 -0
  26. package/lib/module/index.js +13 -0
  27. package/lib/module/index.js.map +1 -0
  28. package/lib/module/package.json +1 -0
  29. package/lib/module/theme/ThemeProvider.js +31 -0
  30. package/lib/module/theme/ThemeProvider.js.map +1 -0
  31. package/lib/module/theme/defaultTheme.js +118 -0
  32. package/lib/module/theme/defaultTheme.js.map +1 -0
  33. package/lib/module/theme/types.js +2 -0
  34. package/lib/module/theme/types.js.map +1 -0
  35. package/lib/typescript/package.json +1 -0
  36. package/lib/typescript/src/RangaatView.d.ts +7 -0
  37. package/lib/typescript/src/RangaatView.d.ts.map +1 -0
  38. package/lib/typescript/src/RangaatView.native.d.ts +3 -0
  39. package/lib/typescript/src/RangaatView.native.d.ts.map +1 -0
  40. package/lib/typescript/src/RangaatViewNativeComponent.d.ts +7 -0
  41. package/lib/typescript/src/RangaatViewNativeComponent.d.ts.map +1 -0
  42. package/lib/typescript/src/components/Button/Button.d.ts +4 -0
  43. package/lib/typescript/src/components/Button/Button.d.ts.map +1 -0
  44. package/lib/typescript/src/components/Button/index.d.ts +3 -0
  45. package/lib/typescript/src/components/Button/index.d.ts.map +1 -0
  46. package/lib/typescript/src/components/Button/styles.d.ts +37 -0
  47. package/lib/typescript/src/components/Button/styles.d.ts.map +1 -0
  48. package/lib/typescript/src/components/Button/types.d.ts +25 -0
  49. package/lib/typescript/src/components/Button/types.d.ts.map +1 -0
  50. package/lib/typescript/src/hooks/useTheme.d.ts +7 -0
  51. package/lib/typescript/src/hooks/useTheme.d.ts.map +1 -0
  52. package/lib/typescript/src/index.d.ts +8 -0
  53. package/lib/typescript/src/index.d.ts.map +1 -0
  54. package/lib/typescript/src/theme/ThemeProvider.d.ts +17 -0
  55. package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -0
  56. package/lib/typescript/src/theme/defaultTheme.d.ts +4 -0
  57. package/lib/typescript/src/theme/defaultTheme.d.ts.map +1 -0
  58. package/lib/typescript/src/theme/types.d.ts +95 -0
  59. package/lib/typescript/src/theme/types.d.ts.map +1 -0
  60. package/package.json +182 -0
  61. package/src/RangaatView.native.tsx +2 -0
  62. package/src/RangaatView.tsx +9 -0
  63. package/src/RangaatViewNativeComponent.ts +11 -0
  64. package/src/components/Button/Button.tsx +78 -0
  65. package/src/components/Button/index.ts +2 -0
  66. package/src/components/Button/styles.ts +114 -0
  67. package/src/components/Button/types.ts +26 -0
  68. package/src/hooks/useTheme.ts +12 -0
  69. package/src/index.tsx +13 -0
  70. package/src/theme/ThemeProvider.tsx +43 -0
  71. package/src/theme/defaultTheme.ts +79 -0
  72. package/src/theme/types.ts +59 -0
@@ -0,0 +1,11 @@
1
+ import {
2
+ codegenNativeComponent,
3
+ type ColorValue,
4
+ type ViewProps,
5
+ } from 'react-native';
6
+
7
+ interface NativeProps extends ViewProps {
8
+ color?: ColorValue;
9
+ }
10
+
11
+ export default codegenNativeComponent<NativeProps>('RangaatView');
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import { Pressable, Text } from 'react-native';
3
+ import { useTheme } from '../../hooks/useTheme';
4
+ import { getButtonStyles } from './styles';
5
+ import type { ButtonProps } from './types';
6
+
7
+ export const Button = React.forwardRef<any, ButtonProps>(
8
+ (
9
+ {
10
+ children,
11
+ variant = 'filled',
12
+ size = 'medium',
13
+ color,
14
+ fullWidth = false,
15
+ iconLeft,
16
+ iconRight,
17
+ style,
18
+ textStyle,
19
+ disabled = false,
20
+ ...rest
21
+ },
22
+ ref
23
+ ) => {
24
+ const theme = useTheme();
25
+
26
+ return (
27
+ <Pressable
28
+ ref={ref}
29
+ disabled={disabled}
30
+ accessibilityRole="button"
31
+ accessibilityState={{ disabled }}
32
+ style={({ pressed }) => {
33
+ const styles = getButtonStyles(
34
+ theme,
35
+ variant,
36
+ size,
37
+ pressed,
38
+ disabled,
39
+ color
40
+ );
41
+ return [
42
+ styles.container,
43
+ fullWidth && { width: '100%' },
44
+ style,
45
+ ];
46
+ }}
47
+ {...rest}
48
+ >
49
+ {({ pressed }) => {
50
+ const styles = getButtonStyles(
51
+ theme,
52
+ variant,
53
+ size,
54
+ pressed,
55
+ disabled,
56
+ color
57
+ );
58
+
59
+ return (
60
+ <>
61
+ {iconLeft}
62
+ {typeof children === 'string' ? (
63
+ <Text style={[styles.text, textStyle]} numberOfLines={1}>
64
+ {children}
65
+ </Text>
66
+ ) : (
67
+ children
68
+ )}
69
+ {iconRight}
70
+ </>
71
+ );
72
+ }}
73
+ </Pressable>
74
+ );
75
+ }
76
+ );
77
+
78
+ Button.displayName = 'Button';
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './types';
@@ -0,0 +1,114 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import type { RangaatTheme } from '../../theme/types';
3
+ import type { ButtonSize, ButtonVariant } from './types';
4
+
5
+ export const getButtonStyles = (
6
+ theme: RangaatTheme,
7
+ variant: ButtonVariant,
8
+ size: ButtonSize,
9
+ isPressed: boolean,
10
+ isDisabled: boolean,
11
+ customColor?: string
12
+ ) => {
13
+ const { colors, spacing, shapes, typography } = theme;
14
+
15
+ // 1. Determine base colors based on variant
16
+ let backgroundColor = 'transparent';
17
+ let textColor = colors.primary;
18
+ let borderColor = 'transparent';
19
+ let elevation = 0;
20
+
21
+ switch (variant) {
22
+ case 'filled':
23
+ backgroundColor = customColor || colors.primary;
24
+ textColor = colors.onPrimary;
25
+ break;
26
+ case 'tonal':
27
+ backgroundColor = colors.secondaryContainer;
28
+ textColor = colors.onSecondaryContainer;
29
+ break;
30
+ case 'elevated':
31
+ backgroundColor = colors.surface;
32
+ textColor = colors.primary;
33
+ elevation = isPressed ? 2 : 4; // Shadow
34
+ break;
35
+ case 'outlined':
36
+ borderColor = colors.outline;
37
+ textColor = customColor || colors.primary;
38
+ break;
39
+ case 'text':
40
+ textColor = customColor || colors.primary;
41
+ break;
42
+ }
43
+
44
+ // 2. Handle disabled state (Material Design 3 specs usually apply opacity or specific disabled colors)
45
+ if (isDisabled) {
46
+ if (variant === 'filled' || variant === 'tonal' || variant === 'elevated') {
47
+ backgroundColor = colors.disabled;
48
+ textColor = colors.onDisabled;
49
+ elevation = 0;
50
+ } else if (variant === 'outlined') {
51
+ borderColor = colors.disabled;
52
+ textColor = colors.onDisabled;
53
+ } else {
54
+ textColor = colors.onDisabled;
55
+ }
56
+ }
57
+
58
+ // 3. Handle pressed state (visual feedback)
59
+ let opacity = 1;
60
+ if (isPressed && !isDisabled) {
61
+ if (variant === 'filled' || variant === 'tonal' || variant === 'elevated') {
62
+ opacity = 0.85; // Simple opacity feedback
63
+ } else {
64
+ backgroundColor = `${textColor}1A`; // 10% opacity of text color for background
65
+ }
66
+ }
67
+
68
+ // 4. Determine sizing and typography
69
+ let paddingVertical = spacing.sm;
70
+ let paddingHorizontal = spacing.lg;
71
+ let textVariant = typography.labelLarge;
72
+
73
+ if (size === 'small') {
74
+ paddingVertical = spacing.xs;
75
+ paddingHorizontal = spacing.md;
76
+ textVariant = typography.labelMedium;
77
+ } else if (size === 'large') {
78
+ paddingVertical = spacing.md;
79
+ paddingHorizontal = spacing.xl;
80
+ textVariant = typography.labelLarge; // Could be larger if needed
81
+ }
82
+
83
+ return StyleSheet.create({
84
+ container: {
85
+ backgroundColor,
86
+ borderColor,
87
+ borderWidth: variant === 'outlined' ? 1 : 0,
88
+ borderRadius: shapes.pill, // Fully rounded for expressive
89
+ paddingVertical,
90
+ paddingHorizontal,
91
+ flexDirection: 'row',
92
+ alignItems: 'center',
93
+ justifyContent: 'center',
94
+ opacity,
95
+ elevation,
96
+ shadowColor: colors.outline,
97
+ shadowOffset: { width: 0, height: elevation / 2 },
98
+ shadowOpacity: elevation > 0 ? 0.15 : 0,
99
+ shadowRadius: elevation,
100
+ gap: spacing.sm, // Gap between icon and text
101
+ },
102
+ text: {
103
+ color: textColor,
104
+ fontSize: textVariant.fontSize,
105
+ fontWeight: textVariant.fontWeight as any,
106
+ lineHeight: textVariant.lineHeight,
107
+ letterSpacing: textVariant.letterSpacing,
108
+ textAlign: 'center',
109
+ },
110
+ disabled: {
111
+ opacity: 0.8, // Overall container opacity adjustment if needed, but handled above
112
+ },
113
+ });
114
+ };
@@ -0,0 +1,26 @@
1
+ import type { PressableProps, StyleProp, TextStyle, ViewStyle } from 'react-native';
2
+ import type { ReactNode } from 'react';
3
+
4
+ export type ButtonVariant = 'filled' | 'outlined' | 'text' | 'elevated' | 'tonal';
5
+ export type ButtonSize = 'small' | 'medium' | 'large';
6
+
7
+ export interface ButtonProps extends Omit<PressableProps, 'style'> {
8
+ /** The text to display inside the button */
9
+ children: ReactNode;
10
+ /** The visual variant of the button */
11
+ variant?: ButtonVariant;
12
+ /** The size of the button */
13
+ size?: ButtonSize;
14
+ /** Custom color override for the button (background for filled, text/border for outlined) */
15
+ color?: string;
16
+ /** Whether the button should take the full width of its container */
17
+ fullWidth?: boolean;
18
+ /** Icon to display before the text */
19
+ iconLeft?: ReactNode;
20
+ /** Icon to display after the text */
21
+ iconRight?: ReactNode;
22
+ /** Custom styles for the button container */
23
+ style?: StyleProp<ViewStyle>;
24
+ /** Custom styles for the button text */
25
+ textStyle?: StyleProp<TextStyle>;
26
+ }
@@ -0,0 +1,12 @@
1
+ import { useThemeContext } from '../theme/ThemeProvider';
2
+ import type { RangaatTheme } from '../theme/types';
3
+
4
+ export const useTheme = (): RangaatTheme => {
5
+ const { theme } = useThemeContext();
6
+ return theme;
7
+ };
8
+
9
+ export const useThemeActions = () => {
10
+ const { setTheme, toggleTheme } = useThemeContext();
11
+ return { setTheme, toggleTheme };
12
+ };
package/src/index.tsx ADDED
@@ -0,0 +1,13 @@
1
+ export { RangaatView } from './RangaatView';
2
+
3
+ // Theme Architecture
4
+ export { ThemeProvider, useThemeContext } from './theme/ThemeProvider';
5
+ export { lightTheme, darkTheme } from './theme/defaultTheme';
6
+ export type { RangaatTheme, ThemeColors, ThemeTypography, ThemeShapes, ThemeSpacing } from './theme/types';
7
+
8
+ // Hooks
9
+ export { useTheme, useThemeActions } from './hooks/useTheme';
10
+
11
+ // Components
12
+ export { Button } from './components/Button';
13
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './components/Button';
@@ -0,0 +1,43 @@
1
+ import React, { createContext, useContext, useState } from 'react';
2
+ import type { ReactNode } from 'react';
3
+ import type { RangaatTheme } from './types';
4
+ import { lightTheme, darkTheme } from './defaultTheme';
5
+
6
+ interface ThemeContextValue {
7
+ theme: RangaatTheme;
8
+ setTheme: (theme: RangaatTheme) => void;
9
+ toggleTheme: () => void;
10
+ }
11
+
12
+ const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);
13
+
14
+ export interface ThemeProviderProps {
15
+ children: ReactNode;
16
+ initialTheme?: RangaatTheme;
17
+ useSystemTheme?: boolean; // In a full implementation, you'd listen to Appearance.getColorScheme()
18
+ }
19
+
20
+ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
21
+ children,
22
+ initialTheme = lightTheme,
23
+ }) => {
24
+ const [theme, setTheme] = useState<RangaatTheme>(initialTheme);
25
+
26
+ const toggleTheme = () => {
27
+ setTheme((prevTheme) => (prevTheme.isDark ? lightTheme : darkTheme));
28
+ };
29
+
30
+ return (
31
+ <ThemeContext.Provider value={{ theme, setTheme, toggleTheme }}>
32
+ {children}
33
+ </ThemeContext.Provider>
34
+ );
35
+ };
36
+
37
+ export const useThemeContext = () => {
38
+ const context = useContext(ThemeContext);
39
+ if (!context) {
40
+ throw new Error('useThemeContext must be used within a ThemeProvider');
41
+ }
42
+ return context;
43
+ };
@@ -0,0 +1,79 @@
1
+ import type { RangaatTheme } from './types';
2
+
3
+ export const lightTheme: RangaatTheme = {
4
+ isDark: false,
5
+ colors: {
6
+ primary: '#6750A4',
7
+ onPrimary: '#FFFFFF',
8
+ primaryContainer: '#EADDFF',
9
+ onPrimaryContainer: '#21005D',
10
+ secondary: '#625B71',
11
+ onSecondary: '#FFFFFF',
12
+ secondaryContainer: '#E8DEF8',
13
+ onSecondaryContainer: '#1D192B',
14
+ background: '#FFFBFE',
15
+ onBackground: '#1C1B1F',
16
+ surface: '#FFFBFE',
17
+ onSurface: '#1C1B1F',
18
+ surfaceVariant: '#E7E0EC',
19
+ onSurfaceVariant: '#49454F',
20
+ outline: '#79747E',
21
+ error: '#B3261E',
22
+ onError: '#FFFFFF',
23
+ disabled: '#1C1B1F60',
24
+ onDisabled: '#1C1B1F30',
25
+ },
26
+ typography: {
27
+ h1: { fontSize: 57, fontWeight: '400', lineHeight: 64 },
28
+ h2: { fontSize: 45, fontWeight: '400', lineHeight: 52 },
29
+ h3: { fontSize: 36, fontWeight: '400', lineHeight: 44 },
30
+ bodyLarge: { fontSize: 16, fontWeight: '400', lineHeight: 24 },
31
+ bodyMedium: { fontSize: 14, fontWeight: '400', lineHeight: 20 },
32
+ bodySmall: { fontSize: 12, fontWeight: '400', lineHeight: 16 },
33
+ labelLarge: { fontSize: 14, fontWeight: '500', lineHeight: 20, letterSpacing: 0.1 },
34
+ labelMedium: { fontSize: 12, fontWeight: '500', lineHeight: 16, letterSpacing: 0.5 },
35
+ labelSmall: { fontSize: 11, fontWeight: '500', lineHeight: 16, letterSpacing: 0.5 },
36
+ },
37
+ spacing: {
38
+ xs: 4,
39
+ sm: 8,
40
+ md: 16,
41
+ lg: 24,
42
+ xl: 32,
43
+ xxl: 40,
44
+ },
45
+ shapes: {
46
+ extraSmall: 4,
47
+ small: 8,
48
+ medium: 12,
49
+ large: 16,
50
+ extraLarge: 28,
51
+ pill: 9999,
52
+ },
53
+ };
54
+
55
+ export const darkTheme: RangaatTheme = {
56
+ ...lightTheme,
57
+ isDark: true,
58
+ colors: {
59
+ primary: '#D0BCFF',
60
+ onPrimary: '#381E72',
61
+ primaryContainer: '#4F378B',
62
+ onPrimaryContainer: '#EADDFF',
63
+ secondary: '#CCC2DC',
64
+ onSecondary: '#332D41',
65
+ secondaryContainer: '#4A4458',
66
+ onSecondaryContainer: '#E8DEF8',
67
+ background: '#1C1B1F',
68
+ onBackground: '#E6E1E5',
69
+ surface: '#1C1B1F',
70
+ onSurface: '#E6E1E5',
71
+ surfaceVariant: '#49454F',
72
+ onSurfaceVariant: '#CAC4D0',
73
+ outline: '#938F99',
74
+ error: '#F2B8B5',
75
+ onError: '#601410',
76
+ disabled: '#E6E1E560',
77
+ onDisabled: '#E6E1E530',
78
+ },
79
+ };
@@ -0,0 +1,59 @@
1
+ export interface ThemeColors {
2
+ primary: string;
3
+ onPrimary: string;
4
+ primaryContainer: string;
5
+ onPrimaryContainer: string;
6
+ secondary: string;
7
+ onSecondary: string;
8
+ secondaryContainer: string;
9
+ onSecondaryContainer: string;
10
+ background: string;
11
+ onBackground: string;
12
+ surface: string;
13
+ onSurface: string;
14
+ surfaceVariant: string;
15
+ onSurfaceVariant: string;
16
+ outline: string;
17
+ error: string;
18
+ onError: string;
19
+ disabled: string;
20
+ onDisabled: string;
21
+ }
22
+
23
+ export interface ThemeTypography {
24
+ h1: { fontSize: number; fontWeight: string; lineHeight: number };
25
+ h2: { fontSize: number; fontWeight: string; lineHeight: number };
26
+ h3: { fontSize: number; fontWeight: string; lineHeight: number };
27
+ bodyLarge: { fontSize: number; fontWeight: string; lineHeight: number };
28
+ bodyMedium: { fontSize: number; fontWeight: string; lineHeight: number };
29
+ bodySmall: { fontSize: number; fontWeight: string; lineHeight: number };
30
+ labelLarge: { fontSize: number; fontWeight: string; lineHeight: number; letterSpacing: number };
31
+ labelMedium: { fontSize: number; fontWeight: string; lineHeight: number; letterSpacing: number };
32
+ labelSmall: { fontSize: number; fontWeight: string; lineHeight: number; letterSpacing: number };
33
+ }
34
+
35
+ export interface ThemeSpacing {
36
+ xs: number;
37
+ sm: number;
38
+ md: number;
39
+ lg: number;
40
+ xl: number;
41
+ xxl: number;
42
+ }
43
+
44
+ export interface ThemeShapes {
45
+ extraSmall: number;
46
+ small: number;
47
+ medium: number;
48
+ large: number;
49
+ extraLarge: number;
50
+ pill: number;
51
+ }
52
+
53
+ export interface RangaatTheme {
54
+ colors: ThemeColors;
55
+ typography: ThemeTypography;
56
+ spacing: ThemeSpacing;
57
+ shapes: ThemeShapes;
58
+ isDark: boolean;
59
+ }