@umituz/react-native-design-system 2.4.11 → 2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "2.4.11",
3
+ "version": "2.5.0",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -1,66 +1,72 @@
1
1
  import React from 'react';
2
- import { Text, StyleProp, TextStyle } from 'react-native';
3
- import { useAppDesignTokens, useResponsiveDesignTokens } from '../theme';
4
- import type { TextStyleVariant, ColorVariant } from '../typography';
5
- import { getTextColor } from '../typography';
2
+ import { Text, type StyleProp, type TextStyle, type TextProps } from 'react-native';
3
+ import { useAppDesignTokens } from '../theme';
4
+ import { getTextColor, type TextStyleVariant, type ColorVariant } from '../typography';
6
5
 
7
- export interface AtomicTextProps {
8
- children: React.ReactNode;
6
+ export interface AtomicTextProps extends TextProps {
7
+ /** Typographic style variant from tokens */
9
8
  type?: TextStyleVariant;
9
+
10
+ /** Color variant from tokens or custom hex color */
10
11
  color?: ColorVariant | string;
11
- numberOfLines?: number;
12
- ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
13
- textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify';
12
+
13
+ /** Text alignment */
14
+ align?: TextStyle['textAlign'];
15
+
16
+ /** Content to render */
17
+ children: React.ReactNode;
18
+
19
+ /** Custom text style */
14
20
  style?: StyleProp<TextStyle>;
21
+
22
+ /** Test ID for automation */
15
23
  testID?: string;
16
- /** Enable responsive font sizing (scales based on device) */
17
- responsive?: boolean;
18
24
  }
19
25
 
20
- export const AtomicText: React.FC<AtomicTextProps> = ({
21
- children,
26
+ /**
27
+ * AtomicText - Primitive Text Component
28
+ *
29
+ * ✅ Responsive by default
30
+ * ✅ Theme-aware
31
+ * ✅ SOLID, DRY, KISS
32
+ */
33
+ export const AtomicText = ({
22
34
  type = 'bodyMedium',
23
- color,
24
- numberOfLines,
25
- ellipsizeMode,
26
- textAlign,
35
+ color = 'textPrimary',
36
+ align,
37
+ children,
27
38
  style,
28
39
  testID,
29
- responsive = false,
30
- }) => {
31
- const staticTokens = useAppDesignTokens();
32
- const responsiveTokens = useResponsiveDesignTokens();
33
-
34
- // Use responsive tokens if enabled, otherwise use static
35
- const tokens = responsive ? responsiveTokens : staticTokens;
40
+ ...props
41
+ }: AtomicTextProps) => {
42
+ const tokens = useAppDesignTokens();
36
43
 
37
44
  // Get typography style from tokens
38
45
  const typographyStyle = (tokens.typography as Record<string, any>)[type];
46
+
47
+ // Use responsive font size if available
48
+ const fontSize = typographyStyle?.responsiveFontSize || typographyStyle?.fontSize;
39
49
 
40
- // Get color from tokens or use custom color using utility function
41
- const resolvedColor = getTextColor(color, tokens);
42
-
43
- // Use responsive font size if enabled and available
44
- const fontSize = responsive && typographyStyle.responsiveFontSize
45
- ? typographyStyle.responsiveFontSize
46
- : typographyStyle.fontSize;
50
+ // Resolve color
51
+ const resolvedColor = typeof color === 'string' && !color.includes('.')
52
+ ? getTextColor(color as ColorVariant, tokens)
53
+ : color;
47
54
 
48
55
  const textStyle: StyleProp<TextStyle> = [
49
56
  typographyStyle,
50
57
  {
51
- color: resolvedColor,
58
+ color: resolvedColor as string,
52
59
  ...(fontSize && { fontSize }),
53
- ...(textAlign && { textAlign }),
60
+ ...(align && { textAlign: align }),
54
61
  },
55
62
  style,
56
63
  ];
57
64
 
58
65
  return (
59
66
  <Text
60
- numberOfLines={numberOfLines}
61
- ellipsizeMode={ellipsizeMode}
62
67
  style={textStyle}
63
68
  testID={testID}
69
+ {...props}
64
70
  >
65
71
  {children}
66
72
  </Text>
package/src/index.ts CHANGED
@@ -18,7 +18,6 @@
18
18
 
19
19
  export {
20
20
  useAppDesignTokens,
21
- useResponsiveDesignTokens,
22
21
  useCommonStyles,
23
22
  useDesignSystemTheme,
24
23
  useTheme,
@@ -34,7 +33,6 @@ export {
34
33
  typography,
35
34
  borders,
36
35
  createDesignTokens,
37
- createResponsiveDesignTokens,
38
36
  lightTheme,
39
37
  darkTheme,
40
38
  createResponsiveValue,
@@ -53,10 +51,8 @@ export {
53
51
  type AvatarSizes,
54
52
  type ComponentSizes,
55
53
  type DesignTokens,
56
- type ResponsiveDesignTokens,
57
54
  type ResponsiveSpacing,
58
55
  type ResponsiveTypography,
59
- type ResponsiveBorderRadius,
60
56
  type Theme,
61
57
  type ExtendedColorPalette,
62
58
  type NavigationTheme,
@@ -414,14 +410,6 @@ export {
414
410
  type CountdownTarget,
415
411
  type CountdownFormatOptions,
416
412
  type CountdownDisplayConfig,
417
- // Photo Upload
418
- PhotoUploadCard,
419
- type PhotoUploadCardProps,
420
- type PhotoUploadCardConfig,
421
- // Image Picker
422
- ImagePickerBox,
423
- type ImagePickerBoxProps,
424
- type ImagePickerBoxConfig,
425
413
  // Step Header
426
414
  StepHeader,
427
415
  type StepHeaderProps,
@@ -8,7 +8,7 @@
8
8
  import React, { useMemo } from 'react';
9
9
  import { View, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
10
10
  import { useResponsive } from '../../responsive';
11
- import { useResponsiveDesignTokens } from '../../theme';
11
+ import { useAppDesignTokens } from '../../theme';
12
12
 
13
13
  export interface ContainerProps {
14
14
  /** Container content */
@@ -49,7 +49,7 @@ export const Container: React.FC<ContainerProps> = ({
49
49
  testID,
50
50
  }) => {
51
51
  const { maxContentWidth } = useResponsive();
52
- const tokens = useResponsiveDesignTokens();
52
+ const tokens = useAppDesignTokens();
53
53
 
54
54
  const containerWidth = maxWidth || maxContentWidth;
55
55
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  import React, { useMemo } from 'react';
9
9
  import { View, ScrollView, KeyboardAvoidingView, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
10
- import { useResponsiveDesignTokens } from '../../theme';
10
+ import { useAppDesignTokens } from '../../theme';
11
11
  import { useResponsive } from '../../responsive';
12
12
 
13
13
  export interface FormLayoutProps {
@@ -51,7 +51,7 @@ export const FormLayout: React.FC<FormLayoutProps> = ({
51
51
  disableScroll = false,
52
52
  testID,
53
53
  }) => {
54
- const tokens = useResponsiveDesignTokens();
54
+ const tokens = useAppDesignTokens();
55
55
  const { insets } = useResponsive();
56
56
 
57
57
  const styles = useMemo(
@@ -8,7 +8,7 @@
8
8
  import React, { useMemo } from 'react';
9
9
  import { View, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
10
10
  import { useResponsive } from '../../responsive';
11
- import { useResponsiveDesignTokens } from '../../theme';
11
+ import { useAppDesignTokens } from '../../theme';
12
12
 
13
13
  export interface GridProps {
14
14
  /** Grid items to render */
@@ -51,7 +51,7 @@ export const Grid: React.FC<GridProps> = ({
51
51
  testID,
52
52
  }) => {
53
53
  const { gridColumns, spacingMultiplier } = useResponsive();
54
- const tokens = useResponsiveDesignTokens();
54
+ const tokens = useAppDesignTokens();
55
55
 
56
56
  // Calculate responsive columns
57
57
  const columns = gridColumns || (mobileColumns && tabletColumns
@@ -7,7 +7,7 @@
7
7
 
8
8
  import React from 'react';
9
9
  import { FlatList, RefreshControl, type FlatListProps, type ListRenderItem } from 'react-native';
10
- import { useResponsiveDesignTokens } from '../../theme';
10
+ import { useAppDesignTokens } from '../../theme';
11
11
 
12
12
  export interface ListProps<T> extends Omit<FlatListProps<T>, 'renderItem'> {
13
13
  /** Data array */
@@ -53,7 +53,7 @@ export const List = <T,>({
53
53
  contentPadding = false,
54
54
  ...rest
55
55
  }: ListProps<T>) => {
56
- const tokens = useResponsiveDesignTokens();
56
+ const tokens = useAppDesignTokens();
57
57
 
58
58
  return (
59
59
  <FlatList
@@ -48,12 +48,6 @@ export * from './animation';
48
48
  // Long Press Menu
49
49
  export * from './long-press-menu';
50
50
 
51
- // Photo Upload
52
- export * from './PhotoUploadCard';
53
-
54
- // Image Picker
55
- export * from './ImagePickerBox';
56
-
57
51
  // Step Header
58
52
  export * from './StepHeader';
59
53
 
@@ -1,89 +1,68 @@
1
- /**
2
- * TOKEN FACTORY - THEME INJECTION LOGIC
3
- *
4
- * ✅ Factory Pattern for creating complete design tokens
5
- * ✅ Combines static tokens (BaseTokens) + dynamic colors (ColorPalette)
6
- * ✅ Type-safe token generation
7
- * ✅ Zero duplication - SINGLE SOURCE OF TRUTH
8
- *
9
- * @module TokenFactory
10
- */
11
-
12
1
  import { BASE_TOKENS } from './BaseTokens';
13
2
  import { getColorPalette, withAlpha, type ThemeMode, type ColorPalette } from './ColorPalette';
14
3
  import { applyCustomColors, type CustomThemeColors } from './CustomColors';
15
-
16
- // =============================================================================
17
- // DESIGN TOKENS TYPE
18
- // =============================================================================
19
-
20
- /**
21
- * Complete design tokens shape
22
- * Combines static tokens (spacing, typography, borders) + dynamic colors
23
- */
24
- export type DesignTokens = {
25
- colors: ColorPalette;
26
- spacing: typeof BASE_TOKENS.spacing;
27
- typography: typeof BASE_TOKENS.typography;
28
- iconSizes: typeof BASE_TOKENS.iconSizes;
29
- opacity: typeof BASE_TOKENS.opacity;
30
- avatarSizes: typeof BASE_TOKENS.avatarSizes;
31
- borderRadius: typeof BASE_TOKENS.borders.radius;
32
- borders: typeof BASE_TOKENS.borders & {
33
- card: typeof BASE_TOKENS.borders.card & { borderColor: string };
34
- input: typeof BASE_TOKENS.borders.input & { borderColor: string };
35
- };
36
- };
37
-
38
- // =============================================================================
39
- // TOKEN FACTORY FUNCTION
40
- // =============================================================================
4
+ import { type DesignTokens, type ResponsiveTypography } from '../types/ThemeTypes';
41
5
 
42
6
  /**
43
7
  * Create complete design tokens for a specific theme mode
8
+ *
9
+ * ✅ Responsive by default
10
+ * ✅ SINGLE SOURCE OF TRUTH
44
11
  *
45
12
  * @param mode - Theme mode ('light' or 'dark')
46
13
  * @param customColors - Optional custom colors to override default colors
47
- * @returns Complete design tokens object
48
- *
49
- * @example
50
- * ```typescript
51
- * const lightTokens = createDesignTokens('light');
52
- * const darkTokens = createDesignTokens('dark');
53
- * const customTokens = createDesignTokens('dark', { primary: '#FF6B35' });
54
- *
55
- * // Use in components
56
- * <View style={{ backgroundColor: lightTokens.colors.primary }}>
57
- * <Text style={lightTokens.typography.bodyLarge}>Hello!</Text>
58
- * </View>
59
- * ```
14
+ * @param multiplier - Device-based spacing multiplier
15
+ * @param getFontSize - Function to get responsive font size
16
+ * @returns Complete responsive design tokens object
60
17
  */
61
18
  export const createDesignTokens = (
62
19
  mode: ThemeMode,
63
20
  customColors?: CustomThemeColors,
21
+ multiplier: number = 1,
22
+ getFontSize: (size: number) => number = (s) => s,
64
23
  ): DesignTokens => {
65
- // Get color palette for theme mode
66
24
  const baseColors = getColorPalette(mode);
67
-
68
- // Apply custom colors if provided
69
25
  const colors = applyCustomColors(baseColors, customColors);
70
26
 
71
- // Combine static tokens + dynamic colors
27
+ // Responsive Spacing
28
+ const spacing = Object.keys(BASE_TOKENS.spacing).reduce((acc, key) => {
29
+ const value = BASE_TOKENS.spacing[key as keyof typeof BASE_TOKENS.spacing];
30
+ acc[key as keyof typeof BASE_TOKENS.spacing] = typeof value === 'number' ? value * multiplier : value;
31
+ return acc;
32
+ }, {} as any);
33
+
34
+ // Responsive Typography
35
+ const typography = Object.keys(BASE_TOKENS.typography).reduce((acc, key) => {
36
+ const style = BASE_TOKENS.typography[key as keyof typeof BASE_TOKENS.typography];
37
+ if (typeof style === 'object' && style.fontSize) {
38
+ acc[key as keyof typeof BASE_TOKENS.typography] = {
39
+ ...(style as any),
40
+ responsiveFontSize: getFontSize(style.fontSize as number),
41
+ };
42
+ } else {
43
+ acc[key as keyof typeof BASE_TOKENS.typography] = style as any;
44
+ }
45
+ return acc;
46
+ }, {} as any) as ResponsiveTypography;
47
+
48
+ // Responsive Borders
49
+ const borderRadius = Object.keys(BASE_TOKENS.borders.radius).reduce((acc, key) => {
50
+ const value = BASE_TOKENS.borders.radius[key as keyof typeof BASE_TOKENS.borders.radius];
51
+ acc[key as keyof typeof BASE_TOKENS.borders.radius] = value === 0 || key === 'full' ? value : Math.round(value * multiplier);
52
+ return acc;
53
+ }, {} as any);
54
+
72
55
  return {
73
- // ✅ DYNAMIC: Colors from theme mode + custom overrides
74
56
  colors,
75
-
76
- // ✅ STATIC: These don't change with theme
77
- spacing: BASE_TOKENS.spacing,
78
- typography: BASE_TOKENS.typography,
57
+ spacing,
58
+ typography,
79
59
  iconSizes: BASE_TOKENS.iconSizes,
80
60
  opacity: BASE_TOKENS.opacity,
81
61
  avatarSizes: BASE_TOKENS.avatarSizes,
82
- borderRadius: BASE_TOKENS.borders.radius,
83
-
84
- // ✅ BORDERS: Static + injected border colors from theme
62
+ borderRadius,
85
63
  borders: {
86
64
  ...BASE_TOKENS.borders,
65
+ radius: borderRadius,
87
66
  card: {
88
67
  ...BASE_TOKENS.borders.card,
89
68
  borderColor: colors.border,
@@ -93,13 +72,13 @@ export const createDesignTokens = (
93
72
  borderColor: colors.border,
94
73
  },
95
74
  },
75
+ spacingMultiplier: multiplier,
76
+ baseSpacing: BASE_TOKENS.spacing,
77
+ baseTypography: BASE_TOKENS.typography,
78
+ baseBorderRadius: BASE_TOKENS.borders.radius,
96
79
  };
97
80
  };
98
81
 
99
- // =============================================================================
100
- // UTILITY EXPORTS
101
- // =============================================================================
102
-
103
82
  export { withAlpha };
104
83
  export type { ThemeMode, ColorPalette };
105
84
 
@@ -1,27 +1,35 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useDesignSystemTheme } from '../infrastructure/globalThemeStore';
3
- import { createDesignTokens, type DesignTokens } from '../core/TokenFactory';
3
+ import { createDesignTokens } from '../core/TokenFactory';
4
+ import { useResponsive } from '../../responsive/useResponsive';
5
+ import { type DesignTokens } from '../types/ThemeTypes';
4
6
 
5
7
  /**
6
8
  * Hook to access current design tokens (colors, spacing, typography, etc.)
7
9
  *
8
- * This hook is the primary way for components to access theme tokens.
9
- * It automatically updates when the theme mode or custom colors change
10
- * in the design system global store.
10
+ * Responsive by default - Scales based on device type
11
+ * Theme-aware - Automatically updates on light/dark mode changes
12
+ * Dynamic - Supports custom color overrides
11
13
  *
12
- * @returns {DesignTokens} The current design tokens
14
+ * @returns {DesignTokens} The current responsive design tokens
13
15
  *
14
16
  * @example
15
17
  * ```tsx
16
18
  * const tokens = useAppDesignTokens();
17
- * return <View style={{ backgroundColor: tokens.colors.backgroundPrimary }} />;
19
+ * return (
20
+ * <View style={{
21
+ * padding: tokens.spacing.md,
22
+ * backgroundColor: tokens.colors.backgroundPrimary
23
+ * }} />
24
+ * );
18
25
  * ```
19
26
  */
20
27
  export const useAppDesignTokens = (): DesignTokens => {
21
28
  const { themeMode, customColors } = useDesignSystemTheme();
29
+ const { spacingMultiplier, getFontSize } = useResponsive();
22
30
 
23
31
  return useMemo(
24
- () => createDesignTokens(themeMode, customColors),
25
- [themeMode, customColors]
32
+ () => createDesignTokens(themeMode, customColors, spacingMultiplier, getFontSize),
33
+ [themeMode, customColors, spacingMultiplier, getFontSize]
26
34
  );
27
35
  };
@@ -52,27 +52,20 @@ export {
52
52
 
53
53
  export {
54
54
  createDesignTokens,
55
- type DesignTokens,
56
55
  } from './core/TokenFactory';
57
56
 
58
- // =============================================================================
59
- // RESPONSIVE TOKEN FACTORY
60
- // =============================================================================
61
-
62
- export {
63
- createResponsiveDesignTokens,
64
- type ResponsiveDesignTokens,
65
- type ResponsiveSpacing,
66
- type ResponsiveTypography,
67
- type ResponsiveBorderRadius,
68
- } from './core/ResponsiveTokenFactory';
57
+ export type {
58
+ DesignTokens,
59
+ ResponsiveSpacing,
60
+ ResponsiveTypography,
61
+ ResponsiveBorderRadius,
62
+ } from './types/ThemeTypes';
69
63
 
70
64
  // =============================================================================
71
65
  // HOOKS
72
66
  // =============================================================================
73
67
 
74
68
  export { useAppDesignTokens } from './hooks/useAppDesignTokens';
75
- export { useResponsiveDesignTokens } from './hooks/useResponsiveDesignTokens';
76
69
  export { useDesignSystemTheme } from './infrastructure/globalThemeStore';
77
70
  export { useTheme } from './infrastructure/stores/themeStore';
78
71
  export { useThemedStyles, useThemedStyleSheet } from './hooks/useThemedStyles';
@@ -0,0 +1,62 @@
1
+ import { type TextStyle } from 'react-native';
2
+ import { type ColorPalette, type ThemeMode } from '../core/ColorPalette';
3
+ import { type BaseTokens, type Spacing, type Typography, type Borders } from '../core/tokens/BaseTokens';
4
+
5
+ /**
6
+ * Responsive Spacing Type
7
+ */
8
+ export type ResponsiveSpacing = Spacing;
9
+
10
+ /**
11
+ * Responsive Border Radius Type
12
+ */
13
+ export type ResponsiveBorderRadius = Borders['radius'];
14
+
15
+ /**
16
+ * Responsive Typography Type
17
+ */
18
+ export type ResponsiveTypography = Typography & {
19
+ displayLarge: TextStyle & { responsiveFontSize: number };
20
+ displayMedium: TextStyle & { responsiveFontSize: number };
21
+ displaySmall: TextStyle & { responsiveFontSize: number };
22
+ headlineLarge: TextStyle & { responsiveFontSize: number };
23
+ headlineMedium: TextStyle & { responsiveFontSize: number };
24
+ headlineSmall: TextStyle & { responsiveFontSize: number };
25
+ titleLarge: TextStyle & { responsiveFontSize: number };
26
+ titleMedium: TextStyle & { responsiveFontSize: number };
27
+ titleSmall: TextStyle & { responsiveFontSize: number };
28
+ bodyLarge: TextStyle & { responsiveFontSize: number };
29
+ bodyMedium: TextStyle & { responsiveFontSize: number };
30
+ bodySmall: TextStyle & { responsiveFontSize: number };
31
+ labelLarge: TextStyle & { responsiveFontSize: number };
32
+ labelMedium: TextStyle & { responsiveFontSize: number };
33
+ labelSmall: TextStyle & { responsiveFontSize: number };
34
+ };
35
+
36
+ /**
37
+ * Combined Design Tokens Type
38
+ * Now responsive by default
39
+ */
40
+ export type DesignTokens = {
41
+ colors: ColorPalette;
42
+ spacing: ResponsiveSpacing;
43
+ typography: ResponsiveTypography;
44
+ iconSizes: BaseTokens['iconSizes'];
45
+ opacity: BaseTokens['opacity'];
46
+ avatarSizes: BaseTokens['avatarSizes'];
47
+ borderRadius: ResponsiveBorderRadius;
48
+ borders: Borders & {
49
+ card: Borders['card'] & { borderColor: string };
50
+ input: Borders['input'] & { borderColor: string };
51
+ };
52
+
53
+ // Responsive metadata
54
+ spacingMultiplier: number;
55
+
56
+ // Base tokens for reference if needed
57
+ baseSpacing: Spacing;
58
+ baseTypography: Typography;
59
+ baseBorderRadius: Borders['radius'];
60
+ };
61
+
62
+ export type { ThemeMode };
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
1
2
  /**
2
3
  * React 19 JSX Compatibility for React Native
3
4
  * Fixes JSX namespace issues between React 19 and react-native
@@ -1,171 +0,0 @@
1
- /**
2
- * ImagePickerBox Component
3
- * Generic image picker box with gradient design
4
- * Props-driven for 100+ apps compatibility
5
- *
6
- * @package @umituz/react-native-design-system
7
- */
8
-
9
- import React, { useMemo } from "react";
10
- import {
11
- View,
12
- StyleSheet,
13
- TouchableOpacity,
14
- Image,
15
- type ViewStyle,
16
- } from "react-native";
17
- import { LinearGradient } from "expo-linear-gradient";
18
- import { AtomicText } from "../../atoms/AtomicText";
19
- import { AtomicIcon } from "../../atoms/AtomicIcon";
20
- import { useAppDesignTokens } from "../../theme/hooks/useAppDesignTokens";
21
-
22
- export interface ImagePickerBoxConfig {
23
- readonly variant?: "portrait" | "square" | "landscape";
24
- readonly size?: "sm" | "md" | "lg";
25
- readonly uploadIcon?: string;
26
- readonly editIcon?: string;
27
- }
28
-
29
- export interface ImagePickerBoxProps {
30
- readonly imageUri: string | null;
31
- readonly isDisabled?: boolean;
32
- readonly onPress: () => void;
33
- readonly placeholderText: string;
34
- readonly gradientColors?: readonly [string, string, ...string[]];
35
- readonly config?: ImagePickerBoxConfig;
36
- }
37
-
38
- const VARIANT_STYLES: Record<string, ViewStyle> = {
39
- portrait: { width: 200, height: 280, borderRadius: 20 },
40
- square: { width: "100%" as unknown as number, aspectRatio: 1, borderRadius: 24 },
41
- landscape: { width: "100%" as unknown as number, aspectRatio: 16 / 9, borderRadius: 16 },
42
- };
43
-
44
- const SIZE_MULTIPLIERS = { sm: 0.7, md: 1, lg: 1.3 };
45
-
46
- const DEFAULT_CONFIG: ImagePickerBoxConfig = {
47
- variant: "portrait",
48
- size: "md",
49
- uploadIcon: "cloud-upload-outline",
50
- editIcon: "image-outline",
51
- };
52
-
53
- export const ImagePickerBox: React.FC<ImagePickerBoxProps> = ({
54
- imageUri,
55
- isDisabled = false,
56
- onPress,
57
- placeholderText,
58
- gradientColors = ["#667eea", "#764ba2"],
59
- config = DEFAULT_CONFIG,
60
- }) => {
61
- const tokens = useAppDesignTokens();
62
- const cfg = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);
63
-
64
- const multiplier = SIZE_MULTIPLIERS[cfg.size || "md"];
65
- const baseStyle = VARIANT_STYLES[cfg.variant || "portrait"];
66
- const iconSize = Math.round(32 * multiplier);
67
-
68
- const styles = useMemo(
69
- () =>
70
- StyleSheet.create({
71
- container: {
72
- marginVertical: 16,
73
- alignItems: "center",
74
- },
75
- box: {
76
- overflow: "hidden",
77
- ...baseStyle,
78
- backgroundColor: tokens.colors.backgroundSecondary,
79
- },
80
- imageContainer: {
81
- flex: 1,
82
- position: "relative",
83
- },
84
- image: {
85
- width: "100%",
86
- height: "100%",
87
- },
88
- imageOverlay: {
89
- position: "absolute",
90
- bottom: 0,
91
- left: 0,
92
- right: 0,
93
- height: "30%",
94
- justifyContent: "flex-end",
95
- alignItems: "flex-end",
96
- padding: 12,
97
- },
98
- editBadge: {
99
- borderRadius: 20,
100
- padding: 8,
101
- backgroundColor: `${gradientColors[1]}E6`,
102
- },
103
- placeholder: {
104
- flex: 1,
105
- justifyContent: "center",
106
- alignItems: "center",
107
- },
108
- placeholderContent: {
109
- alignItems: "center",
110
- justifyContent: "center",
111
- paddingHorizontal: 16,
112
- },
113
- uploadIconContainer: {
114
- backgroundColor: "rgba(255,255,255,0.2)",
115
- borderRadius: 40,
116
- padding: 16,
117
- marginBottom: 12,
118
- },
119
- placeholderText: {
120
- textAlign: "center",
121
- fontWeight: "600",
122
- color: "#FFFFFF",
123
- },
124
- }),
125
- [tokens, baseStyle, gradientColors]
126
- );
127
-
128
- return (
129
- <View style={styles.container}>
130
- <TouchableOpacity
131
- style={styles.box}
132
- onPress={onPress}
133
- disabled={isDisabled}
134
- activeOpacity={0.8}
135
- >
136
- {imageUri ? (
137
- <View style={styles.imageContainer}>
138
- <Image source={{ uri: imageUri }} style={styles.image} />
139
- <LinearGradient
140
- colors={["transparent", "rgba(0,0,0,0.3)"]}
141
- style={styles.imageOverlay}
142
- >
143
- <View style={styles.editBadge}>
144
- <AtomicIcon
145
- name={cfg.editIcon || "image-outline"}
146
- customSize={Math.round(16 * multiplier)}
147
- customColor="#FFFFFF"
148
- />
149
- </View>
150
- </LinearGradient>
151
- </View>
152
- ) : (
153
- <LinearGradient colors={gradientColors} style={styles.placeholder}>
154
- <View style={styles.placeholderContent}>
155
- <View style={styles.uploadIconContainer}>
156
- <AtomicIcon
157
- name={cfg.uploadIcon || "cloud-upload-outline"}
158
- customSize={iconSize}
159
- customColor="#FFFFFF"
160
- />
161
- </View>
162
- <AtomicText type="bodyMedium" style={styles.placeholderText}>
163
- {placeholderText}
164
- </AtomicText>
165
- </View>
166
- </LinearGradient>
167
- )}
168
- </TouchableOpacity>
169
- </View>
170
- );
171
- };
@@ -1,2 +0,0 @@
1
- export { ImagePickerBox } from "./ImagePickerBox";
2
- export type { ImagePickerBoxProps, ImagePickerBoxConfig } from "./ImagePickerBox";
@@ -1,241 +0,0 @@
1
- /**
2
- * PhotoUploadCard Component
3
- * Beautiful photo upload card with validation status and responsive design
4
- *
5
- * @package @umituz/react-native-design-system
6
- */
7
-
8
- import React, { useMemo } from "react";
9
- import {
10
- View,
11
- Image,
12
- StyleSheet,
13
- Pressable,
14
- TouchableOpacity,
15
- ActivityIndicator,
16
- type ViewStyle,
17
- type StyleProp,
18
- } from "react-native";
19
- import { LinearGradient } from "expo-linear-gradient";
20
- import { AtomicText } from "../../atoms/AtomicText";
21
- import { AtomicIcon } from "../../atoms/AtomicIcon";
22
- import { useAppDesignTokens } from "../../theme/hooks/useAppDesignTokens";
23
-
24
- export interface PhotoUploadCardConfig {
25
- aspectRatio?: number;
26
- borderRadius?: number;
27
- iconSize?: number;
28
- showValidationStatus?: boolean;
29
- allowChange?: boolean;
30
- borderStyle?: "solid" | "dashed";
31
- }
32
-
33
- export interface PhotoUploadCardProps {
34
- imageUri: string | null;
35
- onPress: () => void;
36
- isValidating?: boolean;
37
- isValid?: boolean | null;
38
- disabled?: boolean;
39
- config?: PhotoUploadCardConfig;
40
- translations: {
41
- tapToUpload: string;
42
- selectPhoto: string;
43
- change: string;
44
- analyzing?: string;
45
- };
46
- style?: StyleProp<ViewStyle>;
47
- }
48
-
49
- const DEFAULT_CONFIG: PhotoUploadCardConfig = {
50
- aspectRatio: 1,
51
- borderRadius: 28,
52
- iconSize: 40,
53
- showValidationStatus: true,
54
- allowChange: true,
55
- borderStyle: "dashed",
56
- };
57
-
58
- export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
59
- imageUri,
60
- onPress,
61
- isValidating = false,
62
- isValid = null,
63
- disabled = false,
64
- config = DEFAULT_CONFIG,
65
- translations,
66
- style,
67
- }) => {
68
- const tokens = useAppDesignTokens();
69
- const cfg = { ...DEFAULT_CONFIG, ...config };
70
-
71
- const borderColor = useMemo(() => {
72
- if (!cfg.showValidationStatus) {
73
- return `${tokens.colors.primary}40`;
74
- }
75
- if (isValidating) return tokens.colors.primary;
76
- if (isValid === true) return tokens.colors.success;
77
- if (isValid === false) return tokens.colors.error;
78
- return `${tokens.colors.primary}40`;
79
- }, [isValidating, isValid, tokens, cfg.showValidationStatus]);
80
-
81
- const styles = useMemo(
82
- () =>
83
- StyleSheet.create({
84
- container: {
85
- marginHorizontal: 24,
86
- marginBottom: 24,
87
- },
88
- card: {
89
- aspectRatio: cfg.aspectRatio,
90
- backgroundColor: tokens.colors.surfaceSecondary,
91
- borderRadius: cfg.borderRadius,
92
- justifyContent: "center",
93
- alignItems: "center",
94
- overflow: "hidden",
95
- borderWidth: 2,
96
- borderStyle: imageUri ? "solid" : cfg.borderStyle,
97
- },
98
- placeholder: {
99
- alignItems: "center",
100
- padding: 32,
101
- },
102
- iconCircle: {
103
- width: 88,
104
- height: 88,
105
- borderRadius: 44,
106
- justifyContent: "center",
107
- alignItems: "center",
108
- marginBottom: 20,
109
- borderWidth: 2,
110
- borderColor: `${tokens.colors.primary}30`,
111
- },
112
- iconGradient: {
113
- width: 88,
114
- height: 88,
115
- borderRadius: 44,
116
- justifyContent: "center",
117
- alignItems: "center",
118
- },
119
- title: {
120
- fontSize: 20,
121
- fontWeight: "700",
122
- color: tokens.colors.textPrimary,
123
- marginBottom: 8,
124
- letterSpacing: 0.3,
125
- },
126
- subtitle: {
127
- fontSize: 14,
128
- color: tokens.colors.textSecondary,
129
- textAlign: "center",
130
- lineHeight: 20,
131
- maxWidth: 240,
132
- },
133
- image: {
134
- width: "100%",
135
- height: "100%",
136
- resizeMode: "cover",
137
- },
138
- imageOverlay: {
139
- ...StyleSheet.absoluteFillObject,
140
- backgroundColor: "rgba(0,0,0,0.15)",
141
- },
142
- changeButton: {
143
- position: "absolute",
144
- bottom: 20,
145
- right: 20,
146
- backgroundColor: tokens.colors.surface,
147
- paddingHorizontal: 18,
148
- paddingVertical: 12,
149
- borderRadius: 28,
150
- flexDirection: "row",
151
- alignItems: "center",
152
- gap: 8,
153
- },
154
- changeText: {
155
- fontSize: 14,
156
- fontWeight: "700",
157
- color: tokens.colors.primary,
158
- },
159
- validatingContainer: {
160
- alignItems: "center",
161
- padding: 32,
162
- },
163
- validatingText: {
164
- fontSize: 16,
165
- fontWeight: "600",
166
- color: tokens.colors.primary,
167
- marginTop: 20,
168
- },
169
- pulseRing: {
170
- position: "absolute",
171
- width: 100,
172
- height: 100,
173
- borderRadius: 50,
174
- borderWidth: 2,
175
- borderColor: `${tokens.colors.primary}30`,
176
- },
177
- }),
178
- [tokens, imageUri, cfg],
179
- );
180
-
181
- return (
182
- <View style={[styles.container, style]}>
183
- <Pressable
184
- style={[styles.card, { borderColor }]}
185
- onPress={onPress}
186
- disabled={disabled || isValidating}
187
- >
188
- {isValidating ? (
189
- <View style={styles.validatingContainer}>
190
- <View style={styles.pulseRing} />
191
- <ActivityIndicator size="large" color={tokens.colors.primary} />
192
- <AtomicText style={styles.validatingText}>
193
- {translations.analyzing || "Analyzing..."}
194
- </AtomicText>
195
- </View>
196
- ) : imageUri ? (
197
- <>
198
- <Image source={{ uri: imageUri }} style={styles.image} />
199
- <View style={styles.imageOverlay} />
200
- {cfg.allowChange && (
201
- <TouchableOpacity style={styles.changeButton} onPress={onPress}>
202
- <AtomicIcon
203
- name="camera"
204
- size={18}
205
- customColor={tokens.colors.primary}
206
- />
207
- <AtomicText style={styles.changeText}>
208
- {translations.change}
209
- </AtomicText>
210
- </TouchableOpacity>
211
- )}
212
- </>
213
- ) : (
214
- <View style={styles.placeholder}>
215
- <View style={styles.iconCircle}>
216
- <LinearGradient
217
- colors={[
218
- `${tokens.colors.primary}20`,
219
- `${tokens.colors.primary}10`,
220
- ]}
221
- style={styles.iconGradient}
222
- >
223
- <AtomicIcon
224
- name="camera"
225
- size={cfg.iconSize}
226
- customColor={tokens.colors.primary}
227
- />
228
- </LinearGradient>
229
- </View>
230
- <AtomicText style={styles.title}>
231
- {translations.tapToUpload}
232
- </AtomicText>
233
- <AtomicText style={styles.subtitle}>
234
- {translations.selectPhoto}
235
- </AtomicText>
236
- </View>
237
- )}
238
- </Pressable>
239
- </View>
240
- );
241
- };
@@ -1,5 +0,0 @@
1
- export { PhotoUploadCard } from "./PhotoUploadCard";
2
- export type {
3
- PhotoUploadCardProps,
4
- PhotoUploadCardConfig,
5
- } from "./PhotoUploadCard";
@@ -1,266 +0,0 @@
1
- /**
2
- * RESPONSIVE TOKEN FACTORY
3
- *
4
- * ✅ Extends base TokenFactory with responsive capabilities
5
- * ✅ Device-aware spacing, typography, and sizing
6
- * ✅ Automatically scales all tokens based on device type
7
- * ✅ Backward compatible with existing token system
8
- *
9
- * @module ResponsiveTokenFactory
10
- */
11
-
12
- import { BASE_TOKENS } from './BaseTokens';
13
- import { createDesignTokens, type DesignTokens, type ThemeMode } from './TokenFactory';
14
- import { type CustomThemeColors } from './CustomColors';
15
-
16
- // =============================================================================
17
- // RESPONSIVE DESIGN TOKENS TYPE
18
- // =============================================================================
19
-
20
- /**
21
- * Responsive spacing tokens that scale based on device
22
- */
23
- export type ResponsiveSpacing = {
24
- // Base Spacing Scale (scales with spacingMultiplier)
25
- xs: number;
26
- sm: number;
27
- md: number;
28
- lg: number;
29
- xl: number;
30
- xxl: number;
31
- xxxl: number;
32
-
33
- // Semantic Spacing (scales with device)
34
- screenPadding: number;
35
- cardPadding: number;
36
- buttonPadding: number;
37
- inputPadding: number;
38
- sectionSpacing: number;
39
-
40
- // Icon Sizes (scales with device)
41
- iconSizeSmall: number;
42
- iconSizeMedium: number;
43
- iconSizeLarge: number;
44
- iconSizeXLarge: number;
45
- iconSizeHero: number;
46
-
47
- // Component Heights (scales with device)
48
- buttonHeight: number;
49
- inputHeight: number;
50
- appBarHeight: number;
51
- tabBarHeight: number;
52
- };
53
-
54
- /**
55
- * Responsive typography tokens that scale based on device
56
- */
57
- export type ResponsiveTypography = typeof BASE_TOKENS.typography & {
58
- // Each typography level gets responsive fontSize
59
- displayLarge: typeof BASE_TOKENS.typography.displayLarge & { responsiveFontSize: number };
60
- displayMedium: typeof BASE_TOKENS.typography.displayMedium & { responsiveFontSize: number };
61
- displaySmall: typeof BASE_TOKENS.typography.displaySmall & { responsiveFontSize: number };
62
- headlineLarge: typeof BASE_TOKENS.typography.headlineLarge & { responsiveFontSize: number };
63
- headlineMedium: typeof BASE_TOKENS.typography.headlineMedium & { responsiveFontSize: number };
64
- headlineSmall: typeof BASE_TOKENS.typography.headlineSmall & { responsiveFontSize: number };
65
- titleLarge: typeof BASE_TOKENS.typography.titleLarge & { responsiveFontSize: number };
66
- titleMedium: typeof BASE_TOKENS.typography.titleMedium & { responsiveFontSize: number };
67
- titleSmall: typeof BASE_TOKENS.typography.titleSmall & { responsiveFontSize: number };
68
- bodyLarge: typeof BASE_TOKENS.typography.bodyLarge & { responsiveFontSize: number };
69
- bodyMedium: typeof BASE_TOKENS.typography.bodyMedium & { responsiveFontSize: number };
70
- bodySmall: typeof BASE_TOKENS.typography.bodySmall & { responsiveFontSize: number };
71
- labelLarge: typeof BASE_TOKENS.typography.labelLarge & { responsiveFontSize: number };
72
- labelMedium: typeof BASE_TOKENS.typography.labelMedium & { responsiveFontSize: number };
73
- labelSmall: typeof BASE_TOKENS.typography.labelSmall & { responsiveFontSize: number };
74
- };
75
-
76
- /**
77
- * Responsive border radius tokens that scale based on device
78
- */
79
- export type ResponsiveBorderRadius = {
80
- none: number;
81
- xs: number;
82
- sm: number;
83
- md: number;
84
- lg: number;
85
- xl: number;
86
- xxl: number;
87
- full: number;
88
- };
89
-
90
- /**
91
- * Complete responsive design tokens
92
- * Extends base DesignTokens with responsive capabilities
93
- */
94
- export type ResponsiveDesignTokens = Omit<DesignTokens, 'spacing' | 'typography' | 'borderRadius'> & {
95
- spacing: ResponsiveSpacing;
96
- typography: ResponsiveTypography;
97
- borderRadius: ResponsiveBorderRadius;
98
-
99
- // Original base tokens (for backward compatibility)
100
- baseSpacing: typeof BASE_TOKENS.spacing;
101
- baseTypography: typeof BASE_TOKENS.typography;
102
- baseBorderRadius: typeof BASE_TOKENS.borders.radius;
103
-
104
- // Responsive multiplier value
105
- spacingMultiplier: number;
106
- };
107
-
108
- // =============================================================================
109
- // RESPONSIVE TOKEN FACTORY FUNCTION
110
- // =============================================================================
111
-
112
- /**
113
- * Create responsive design tokens for a specific theme mode
114
- *
115
- * @param mode - Theme mode ('light' or 'dark')
116
- * @param spacingMultiplier - Device-based spacing multiplier (from useResponsive)
117
- * @param getFontSize - Function to get responsive font size (from useResponsive)
118
- * @param customColors - Optional custom colors to override default colors
119
- * @returns Complete responsive design tokens object
120
- *
121
- * @example
122
- * ```typescript
123
- * const { spacingMultiplier, getFontSize } = useResponsive();
124
- * const tokens = createResponsiveDesignTokens('light', spacingMultiplier, getFontSize);
125
- *
126
- * // Use in components
127
- * <View style={{ padding: tokens.spacing.md }}> // Auto-scales: 16px * 1.2 = 19.2px on tablet
128
- * <Text style={{ fontSize: tokens.typography.bodyLarge.responsiveFontSize }}>
129
- * Hello!
130
- * </Text>
131
- * </View>
132
- * ```
133
- */
134
- export const createResponsiveDesignTokens = (
135
- mode: ThemeMode,
136
- spacingMultiplier: number,
137
- getFontSize: (baseFontSize: number) => number,
138
- customColors?: CustomThemeColors,
139
- ): ResponsiveDesignTokens => {
140
- // Get base tokens from existing factory
141
- const baseTokens = createDesignTokens(mode, customColors);
142
-
143
- // Create responsive spacing (multiply all base spacing values)
144
- const responsiveSpacing: ResponsiveSpacing = {
145
- // Base Spacing Scale
146
- xs: BASE_TOKENS.spacing.xs * spacingMultiplier,
147
- sm: BASE_TOKENS.spacing.sm * spacingMultiplier,
148
- md: BASE_TOKENS.spacing.md * spacingMultiplier,
149
- lg: BASE_TOKENS.spacing.lg * spacingMultiplier,
150
- xl: BASE_TOKENS.spacing.xl * spacingMultiplier,
151
- xxl: BASE_TOKENS.spacing.xxl * spacingMultiplier,
152
- xxxl: BASE_TOKENS.spacing.xxxl * spacingMultiplier,
153
-
154
- // Semantic Spacing
155
- screenPadding: BASE_TOKENS.spacing.screenPadding * spacingMultiplier,
156
- cardPadding: BASE_TOKENS.spacing.cardPadding * spacingMultiplier,
157
- buttonPadding: BASE_TOKENS.spacing.buttonPadding * spacingMultiplier,
158
- inputPadding: BASE_TOKENS.spacing.inputPadding * spacingMultiplier,
159
- sectionSpacing: BASE_TOKENS.spacing.sectionSpacing * spacingMultiplier,
160
-
161
- // Icon Sizes
162
- iconSizeSmall: Math.round(BASE_TOKENS.spacing.iconSizeSmall * spacingMultiplier),
163
- iconSizeMedium: Math.round(BASE_TOKENS.spacing.iconSizeMedium * spacingMultiplier),
164
- iconSizeLarge: Math.round(BASE_TOKENS.spacing.iconSizeLarge * spacingMultiplier),
165
- iconSizeXLarge: Math.round(BASE_TOKENS.spacing.iconSizeXLarge * spacingMultiplier),
166
- iconSizeHero: Math.round(BASE_TOKENS.spacing.iconSizeHero * spacingMultiplier),
167
-
168
- // Component Heights
169
- buttonHeight: Math.round(BASE_TOKENS.spacing.buttonHeight * spacingMultiplier),
170
- inputHeight: Math.round(BASE_TOKENS.spacing.inputHeight * spacingMultiplier),
171
- appBarHeight: Math.round(BASE_TOKENS.spacing.appBarHeight * spacingMultiplier),
172
- tabBarHeight: Math.round(BASE_TOKENS.spacing.tabBarHeight * spacingMultiplier),
173
- };
174
-
175
- // Create responsive typography (add responsiveFontSize to each level)
176
- const responsiveTypography: ResponsiveTypography = {
177
- displayLarge: {
178
- ...BASE_TOKENS.typography.displayLarge,
179
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.displayLarge.fontSize!),
180
- },
181
- displayMedium: {
182
- ...BASE_TOKENS.typography.displayMedium,
183
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.displayMedium.fontSize!),
184
- },
185
- displaySmall: {
186
- ...BASE_TOKENS.typography.displaySmall,
187
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.displaySmall.fontSize!),
188
- },
189
- headlineLarge: {
190
- ...BASE_TOKENS.typography.headlineLarge,
191
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.headlineLarge.fontSize!),
192
- },
193
- headlineMedium: {
194
- ...BASE_TOKENS.typography.headlineMedium,
195
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.headlineMedium.fontSize!),
196
- },
197
- headlineSmall: {
198
- ...BASE_TOKENS.typography.headlineSmall,
199
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.headlineSmall.fontSize!),
200
- },
201
- titleLarge: {
202
- ...BASE_TOKENS.typography.titleLarge,
203
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.titleLarge.fontSize!),
204
- },
205
- titleMedium: {
206
- ...BASE_TOKENS.typography.titleMedium,
207
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.titleMedium.fontSize!),
208
- },
209
- titleSmall: {
210
- ...BASE_TOKENS.typography.titleSmall,
211
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.titleSmall.fontSize!),
212
- },
213
- bodyLarge: {
214
- ...BASE_TOKENS.typography.bodyLarge,
215
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.bodyLarge.fontSize!),
216
- },
217
- bodyMedium: {
218
- ...BASE_TOKENS.typography.bodyMedium,
219
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.bodyMedium.fontSize!),
220
- },
221
- bodySmall: {
222
- ...BASE_TOKENS.typography.bodySmall,
223
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.bodySmall.fontSize!),
224
- },
225
- labelLarge: {
226
- ...BASE_TOKENS.typography.labelLarge,
227
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.labelLarge.fontSize!),
228
- },
229
- labelMedium: {
230
- ...BASE_TOKENS.typography.labelMedium,
231
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.labelMedium.fontSize!),
232
- },
233
- labelSmall: {
234
- ...BASE_TOKENS.typography.labelSmall,
235
- responsiveFontSize: getFontSize(BASE_TOKENS.typography.labelSmall.fontSize!),
236
- },
237
- } as ResponsiveTypography;
238
-
239
- // Create responsive border radius
240
- const responsiveBorderRadius: ResponsiveBorderRadius = {
241
- none: 0,
242
- xs: Math.round(BASE_TOKENS.borders.radius.xs * spacingMultiplier),
243
- sm: Math.round(BASE_TOKENS.borders.radius.sm * spacingMultiplier),
244
- md: Math.round(BASE_TOKENS.borders.radius.md * spacingMultiplier),
245
- lg: Math.round(BASE_TOKENS.borders.radius.lg * spacingMultiplier),
246
- xl: Math.round(BASE_TOKENS.borders.radius.xl * spacingMultiplier),
247
- xxl: Math.round(BASE_TOKENS.borders.radius.xxl * spacingMultiplier),
248
- full: 9999, // Always full circle
249
- };
250
-
251
- // Return complete responsive tokens
252
- return {
253
- ...baseTokens,
254
- spacing: responsiveSpacing,
255
- typography: responsiveTypography,
256
- borderRadius: responsiveBorderRadius,
257
-
258
- // Keep original base tokens for backward compatibility
259
- baseSpacing: BASE_TOKENS.spacing,
260
- baseTypography: BASE_TOKENS.typography,
261
- baseBorderRadius: BASE_TOKENS.borders.radius,
262
-
263
- // Store multiplier for reference
264
- spacingMultiplier,
265
- };
266
- };
@@ -1,82 +0,0 @@
1
- /**
2
- * useResponsiveDesignTokens Hook
3
- *
4
- * ✅ Combines theme system + responsive utilities
5
- * ✅ Returns device-aware design tokens
6
- * ✅ Auto-updates on theme changes, orientation changes, screen resize
7
- * ✅ Drop-in replacement for useAppDesignTokens with responsive capabilities
8
- *
9
- * @module useResponsiveDesignTokens
10
- */
11
-
12
- import { useMemo } from 'react';
13
- import { useDesignSystemTheme } from '../infrastructure/globalThemeStore';
14
- import { createResponsiveDesignTokens, type ResponsiveDesignTokens } from '../core/ResponsiveTokenFactory';
15
- import { useResponsive } from '../../responsive/useResponsive';
16
-
17
- /**
18
- * Hook for responsive design tokens
19
- *
20
- * Returns complete design tokens with automatic responsive scaling based on device type.
21
- * All spacing, typography, and border radius values automatically scale for tablets and large phones.
22
- *
23
- * @returns ResponsiveDesignTokens - Complete tokens with responsive spacing, typography, borders
24
- *
25
- * @example
26
- * ```typescript
27
- * import { useResponsiveDesignTokens } from '../../index';
28
- *
29
- * const MyComponent = () => {
30
- * const tokens = useResponsiveDesignTokens();
31
- *
32
- * return (
33
- * <View style={{
34
- * padding: tokens.spacing.md, // Auto-scales: 16px on phone, 19.2px on tablet
35
- * borderRadius: tokens.borderRadius.lg, // Auto-scales based on device
36
- * }}>
37
- * <Text style={{
38
- * fontSize: tokens.typography.bodyLarge.responsiveFontSize, // Responsive font
39
- * color: tokens.colors.textPrimary, // Theme-aware color
40
- * }}>
41
- * Hello World!
42
- * </Text>
43
- * </View>
44
- * );
45
- * };
46
- * ```
47
- *
48
- * @example Using backward-compatible base tokens
49
- * ```typescript
50
- * const tokens = useResponsiveDesignTokens();
51
- *
52
- * // Use responsive tokens (recommended)
53
- * const padding = tokens.spacing.md; // 16px * spacingMultiplier
54
- *
55
- * // Use original base tokens (backward compatibility)
56
- * const basePadding = tokens.baseSpacing.md; // Always 16px
57
- * ```
58
- *
59
- * @example Manual responsive calculation
60
- * ```typescript
61
- * const tokens = useResponsiveDesignTokens();
62
- *
63
- * // Custom responsive value
64
- * const customPadding = 20 * tokens.spacingMultiplier; // 20px * 1.2 = 24px on tablet
65
- * ```
66
- */
67
- export const useResponsiveDesignTokens = (): ResponsiveDesignTokens => {
68
- // Get current theme mode and custom colors from theme store
69
- const { themeMode, customColors } = useDesignSystemTheme();
70
-
71
- // Get responsive utilities
72
- const { spacingMultiplier, getFontSize } = useResponsive();
73
-
74
- // Create and memoize responsive tokens
75
- // Recalculates when: theme changes, screen size changes, orientation changes
76
- const responsiveTokens = useMemo(
77
- () => createResponsiveDesignTokens(themeMode, spacingMultiplier, getFontSize, customColors),
78
- [themeMode, spacingMultiplier, getFontSize, customColors]
79
- );
80
-
81
- return responsiveTokens;
82
- };