@robin-ux/native 0.1.3 → 0.1.5

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.
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { ViewProps } from "react-native";
3
+ import { spacing } from "../utils/styles";
4
+ type CardVariant = "default" | "elevated" | "outlined";
5
+ export interface CardProps extends Omit<ViewProps, "style"> {
6
+ variant?: CardVariant;
7
+ padding?: keyof typeof spacing;
8
+ style?: ViewProps["style"];
9
+ children: React.ReactNode;
10
+ bg?: "primary" | "secondary";
11
+ }
12
+ export declare function Card({ variant, padding, style, children, bg, ...props }: CardProps): React.JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/components/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAyB,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEjE,KAAK,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IACvD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,OAAO,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,EAAE,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;CAChC;AAED,wBAAgB,IAAI,CAAC,EAAE,OAAmB,EAAE,OAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,qBA+BrG"}
@@ -0,0 +1,38 @@
1
+ import React from "react";
2
+ import { StyleSheet, View } from "react-native";
3
+ import { useTheme } from "../theme";
4
+ import { borderRadius, shadows, spacing } from "../utils/styles";
5
+ export function Card({ variant = "default", padding = "md", style, children, bg, ...props }) {
6
+ const { colors } = useTheme();
7
+ let backgroundColor = colors.card;
8
+ if (bg === "primary") {
9
+ backgroundColor = colors.background;
10
+ }
11
+ else if (bg === "secondary") {
12
+ backgroundColor = colors.background;
13
+ }
14
+ const variantStyles = {
15
+ default: {
16
+ backgroundColor: backgroundColor,
17
+ },
18
+ elevated: {
19
+ backgroundColor: backgroundColor,
20
+ ...shadows.md,
21
+ },
22
+ outlined: {
23
+ backgroundColor: backgroundColor,
24
+ borderWidth: 1,
25
+ borderColor: colors.border,
26
+ },
27
+ }[variant];
28
+ const cardStyle = [styles.card, variantStyles, { padding: spacing[padding] }, style];
29
+ return (<View style={cardStyle} {...props}>
30
+ {children}
31
+ </View>);
32
+ }
33
+ const styles = StyleSheet.create({
34
+ card: {
35
+ borderRadius: borderRadius.lg,
36
+ },
37
+ });
38
+ //# sourceMappingURL=Card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/components/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAa,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAYjE,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,KAAK,EAAa;IAClG,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9B,IAAI,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC;IAClC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACnB,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC;IACxC,CAAC;SAAM,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC;QAC5B,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC;IACxC,CAAC;IAED,MAAM,aAAa,GAAG;QAClB,OAAO,EAAE;YACL,eAAe,EAAE,eAAe;SACnC;QACD,QAAQ,EAAE;YACN,eAAe,EAAE,eAAe;YAChC,GAAG,OAAO,CAAC,EAAE;SAChB;QACD,QAAQ,EAAE;YACN,eAAe,EAAE,eAAe;YAChC,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,MAAM,CAAC,MAAM;SAC7B;KACJ,CAAC,OAAO,CAAC,CAAC;IAEX,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAErF,OAAO,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC,CAC9B;YAAA,CAAC,QAAQ,CACb;QAAA,EAAE,IAAI,CAAC,CACV,CAAC;AACN,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC7B,IAAI,EAAE;QACF,YAAY,EAAE,YAAY,CAAC,EAAE;KAChC;CACJ,CAAC,CAAC","sourcesContent":["import React from \"react\";\nimport { StyleSheet, View, ViewProps } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { borderRadius, shadows, spacing } from \"../utils/styles\";\n\ntype CardVariant = \"default\" | \"elevated\" | \"outlined\";\n\nexport interface CardProps extends Omit<ViewProps, \"style\"> {\n variant?: CardVariant;\n padding?: keyof typeof spacing;\n style?: ViewProps[\"style\"];\n children: React.ReactNode;\n bg?: \"primary\" | \"secondary\";\n}\n\nexport function Card({ variant = \"default\", padding = \"md\", style, children, bg, ...props }: CardProps) {\n const { colors } = useTheme();\n let backgroundColor = colors.card;\n if (bg === \"primary\") {\n backgroundColor = colors.background;\n } else if (bg === \"secondary\") {\n backgroundColor = colors.background;\n }\n\n const variantStyles = {\n default: {\n backgroundColor: backgroundColor,\n },\n elevated: {\n backgroundColor: backgroundColor,\n ...shadows.md,\n },\n outlined: {\n backgroundColor: backgroundColor,\n borderWidth: 1,\n borderColor: colors.border,\n },\n }[variant];\n\n const cardStyle = [styles.card, variantStyles, { padding: spacing[padding] }, style];\n\n return (\n <View style={cardStyle} {...props}>\n {children}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n borderRadius: borderRadius.lg,\n },\n});\n"]}
@@ -1,7 +1,7 @@
1
- import React from 'react';
2
- import { Control } from 'react-hook-form';
3
- import { TextInput, TextInputProps, ViewStyle } from 'react-native';
4
- export interface InputProps extends Omit<TextInputProps, 'style'> {
1
+ import React from "react";
2
+ import { Control } from "react-hook-form";
3
+ import { TextInput, TextInputProps, ViewStyle } from "react-native";
4
+ export interface InputProps extends Omit<TextInputProps, "style"> {
5
5
  /** Field label */
6
6
  label?: string;
7
7
  /** Error message to display */
@@ -9,7 +9,7 @@ export interface InputProps extends Omit<TextInputProps, 'style'> {
9
9
  /** Helper text below input */
10
10
  helperText?: string;
11
11
  /** Custom input style */
12
- style?: TextInputProps['style'];
12
+ style?: TextInputProps["style"];
13
13
  /** Container style */
14
14
  containerStyle?: ViewStyle;
15
15
  /** Input ref */
@@ -22,11 +22,13 @@ export interface InputProps extends Omit<TextInputProps, 'style'> {
22
22
  control?: Control<any>;
23
23
  /** Field name for React Hook Form (optional) */
24
24
  name?: string;
25
+ maxLength?: number;
26
+ required?: boolean;
25
27
  }
26
28
  /**
27
29
  * Base input wrapper providing label, error, and helper text layout.
28
30
  */
29
- export declare function BaseInput({ label, error, helperText, containerStyle, children, }: Pick<InputProps, 'label' | 'error' | 'helperText' | 'containerStyle' | 'children'>): React.JSX.Element;
31
+ export declare function BaseInput({ label, error, helperText, containerStyle, children, maxLength, value, required, }: Pick<InputProps, "label" | "error" | "helperText" | "containerStyle" | "children" | "maxLength" | "value" | "required">): React.JSX.Element;
30
32
  /**
31
33
  * Password input with visibility toggle.
32
34
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAM1E,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;IAC/D,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,sBAAsB;IACtB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,gBAAgB;IAChB,GAAG,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AASD;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,GACT,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,gBAAgB,GAAG,UAAU,CAAC,qBAgCpF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAuE9C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAoDtC,CAAC"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAM1E,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;IAC7D,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,sBAAsB;IACtB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,gBAAgB;IAChB,GAAG,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AASD;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACtB,KAAK,EACL,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,SAAS,EACT,KAAK,EACL,QAAQ,GACX,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,CAAC,qBAwCzH;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA2D9C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA6CtC,CAAC"}
@@ -1,10 +1,10 @@
1
- import React, { useState } from 'react';
2
- import { useController } from 'react-hook-form';
3
- import { TextInput, View } from 'react-native';
4
- import { useThemeSafe } from '../theme';
5
- import { borderRadius, spacing, useThemedStyles } from '../utils/styles';
6
- import { Button } from './Button';
7
- import { Text } from './Text';
1
+ import React, { useState } from "react";
2
+ import { useController } from "react-hook-form";
3
+ import { TextInput, View } from "react-native";
4
+ import { useThemeSafe } from "../theme";
5
+ import { borderRadius, spacing, useThemedStyles } from "../utils/styles";
6
+ import { Button } from "./Button";
7
+ import { Text } from "./Text";
8
8
  const inputStyles = {
9
9
  paddingHorizontal: spacing.md,
10
10
  paddingVertical: spacing.md,
@@ -14,7 +14,7 @@ const inputStyles = {
14
14
  /**
15
15
  * Base input wrapper providing label, error, and helper text layout.
16
16
  */
17
- export function BaseInput({ label, error, helperText, containerStyle, children, }) {
17
+ export function BaseInput({ label, error, helperText, containerStyle, children, maxLength, value, required, }) {
18
18
  const styles = useThemedStyles((colors) => ({
19
19
  label: {
20
20
  marginBottom: spacing.xs,
@@ -24,19 +24,25 @@ export function BaseInput({ label, error, helperText, containerStyle, children,
24
24
  helperText: {
25
25
  marginTop: spacing.xs,
26
26
  },
27
+ charCount: {
28
+ textAlign: "right",
29
+ },
27
30
  }));
28
31
  return (<View style={containerStyle}>
29
- {label && (<Text variant="body" weight="medium" style={styles.label}>
30
- {label}
31
- </Text>)}
32
- {children}
33
- {error && (<Text variant="caption" color="error" style={styles.helperText}>
34
- {error}
35
- </Text>)}
36
- {!error && helperText && (<Text variant="caption" color="secondary" style={styles.helperText}>
37
- {helperText}
38
- </Text>)}
39
- </View>);
32
+ {label && (<Text variant="body" weight="medium" style={styles.label}>
33
+ {label} {required && <Text color="error">*</Text>}
34
+ </Text>)}
35
+ {children}
36
+ {error && (<Text variant="caption" color="error" style={styles.helperText}>
37
+ {error}
38
+ </Text>)}
39
+ {!error && helperText && (<Text variant="caption" color="secondary" style={styles.helperText}>
40
+ {helperText}
41
+ </Text>)}
42
+ {maxLength && (<Text variant="label" color="tertiary" style={styles.charCount}>
43
+ {value?.length || 0}/{maxLength} characters
44
+ </Text>)}
45
+ </View>);
40
46
  }
41
47
  /**
42
48
  * Password input with visibility toggle.
@@ -68,28 +74,28 @@ export const PasswordInput = ({ value, onChangeText, style, onSubmitEditing, ref
68
74
  const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
69
75
  const inputRef = controller ? controller.field.ref : ref;
70
76
  const hasError = error || controller?.fieldState.error;
71
- return (<BaseInput label={props.label} error={error || controller?.fieldState.error?.message} helperText={props.helperText} containerStyle={props.containerStyle}>
72
- <View style={[
77
+ return (<BaseInput value={inputValue} label={props.label} error={error || controller?.fieldState.error?.message} helperText={props.helperText} containerStyle={props.containerStyle} required={props.required} maxLength={props.maxLength}>
78
+ <View style={[
73
79
  {
74
80
  backgroundColor: colors.backgroundSecondary,
75
81
  borderColor: hasError ? colors.error : colors.border,
76
82
  borderWidth: hasError ? 1 : 0,
77
- flexDirection: 'row',
78
- alignItems: 'center',
83
+ flexDirection: "row",
84
+ alignItems: "center",
79
85
  borderRadius: borderRadius.lg,
80
86
  },
81
87
  style,
82
88
  ]}>
83
- <TextInput placeholderTextColor={colors.foregroundSecondary} ref={inputRef} {...props} style={[
89
+ <TextInput placeholderTextColor={colors.foregroundSecondary} ref={inputRef} {...props} style={[
84
90
  inputStyles,
85
91
  {
86
92
  flex: 1,
87
93
  color: colors.foreground,
88
94
  },
89
95
  ]} value={inputValue} onChangeText={inputOnChange} autoCapitalize="none" onBlur={inputOnBlur} onSubmitEditing={onSubmitEditing} secureTextEntry={!showPassword}/>
90
- <Button variant="ghost" icon={showPassword ? 'eye-off' : 'eye'} size="sm" onPress={() => setShowPassword(!showPassword)}/>
91
- </View>
92
- </BaseInput>);
96
+ <Button variant="ghost" icon={showPassword ? "eye-off" : "eye"} size="sm" onPress={() => setShowPassword(!showPassword)}/>
97
+ </View>
98
+ </BaseInput>);
93
99
  };
94
100
  /**
95
101
  * Text input component with label, error, and helper text support.
@@ -121,8 +127,8 @@ export const Input = ({ value, error, onChangeText, onSubmitEditing, style, ref,
121
127
  const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
122
128
  const inputRef = controller ? controller.field.ref : ref;
123
129
  const hasError = error || controller?.fieldState.error;
124
- return (<BaseInput label={props.label} error={error || controller?.fieldState.error?.message} helperText={props.helperText} containerStyle={props.containerStyle}>
125
- <TextInput placeholderTextColor={colors.foregroundSecondary} ref={inputRef} value={inputValue} onChangeText={inputOnChange} onBlur={inputOnBlur} onSubmitEditing={onSubmitEditing} {...props} style={[
130
+ return (<BaseInput label={props.label} value={inputValue} error={error || controller?.fieldState.error?.message} helperText={props.helperText} containerStyle={props.containerStyle} required={props.required} maxLength={props.maxLength}>
131
+ <TextInput placeholderTextColor={colors.foregroundSecondary} ref={inputRef} value={inputValue} onChangeText={inputOnChange} onBlur={inputOnBlur} onSubmitEditing={onSubmitEditing} {...props} style={[
126
132
  inputStyles,
127
133
  {
128
134
  backgroundColor: colors.backgroundSecondary,
@@ -133,6 +139,6 @@ export const Input = ({ value, error, onChangeText, onSubmitEditing, style, ref,
133
139
  },
134
140
  style,
135
141
  ]}/>
136
- </BaseInput>);
142
+ </BaseInput>);
137
143
  };
138
144
  //# sourceMappingURL=Input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react';\nimport { Control, useController } from 'react-hook-form';\nimport { TextInput, TextInputProps, View, ViewStyle } from 'react-native';\nimport { useThemeSafe } from '../theme';\nimport { borderRadius, spacing, useThemedStyles } from '../utils/styles';\nimport { Button } from './Button';\nimport { Text } from './Text';\n\nexport interface InputProps extends Omit<TextInputProps, 'style'> {\n /** Field label */\n label?: string;\n /** Error message to display */\n error?: string;\n /** Helper text below input */\n helperText?: string;\n /** Custom input style */\n style?: TextInputProps['style'];\n /** Container style */\n containerStyle?: ViewStyle;\n /** Input ref */\n ref?: React.RefObject<TextInput | null>;\n /** Element to render at the end of the input */\n endElement?: React.ReactNode;\n /** Child elements */\n children?: React.ReactNode;\n /** React Hook Form control object (optional) */\n control?: Control<any>;\n /** Field name for React Hook Form (optional) */\n name?: string;\n}\n\nconst inputStyles = {\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.md,\n borderRadius: borderRadius.lg,\n fontSize: 16,\n};\n\n/**\n * Base input wrapper providing label, error, and helper text layout.\n */\nexport function BaseInput({\n label,\n error,\n helperText,\n containerStyle,\n children,\n}: Pick<InputProps, 'label' | 'error' | 'helperText' | 'containerStyle' | 'children'>) {\n const styles = useThemedStyles((colors) => ({\n label: {\n marginBottom: spacing.xs,\n color: colors.foregroundSecondary,\n fontSize: 14,\n },\n helperText: {\n marginTop: spacing.xs,\n },\n }));\n\n return (\n <View style={containerStyle}>\n {label && (\n <Text variant=\"body\" weight=\"medium\" style={styles.label}>\n {label}\n </Text>\n )}\n {children}\n {error && (\n <Text variant=\"caption\" color=\"error\" style={styles.helperText}>\n {error}\n </Text>\n )}\n {!error && helperText && (\n <Text variant=\"caption\" color=\"secondary\" style={styles.helperText}>\n {helperText}\n </Text>\n )}\n </View>\n );\n}\n\n/**\n * Password input with visibility toggle.\n *\n * @example\n * ```tsx\n * <PasswordInput\n * label=\"Password\"\n * placeholder=\"Enter your password\"\n * value={password}\n * onChangeText={setPassword}\n * />\n *\n * // With React Hook Form\n * <PasswordInput\n * label=\"Password\"\n * control={control}\n * name=\"password\"\n * />\n * ```\n */\nexport const PasswordInput: React.FC<InputProps> = ({\n value,\n onChangeText,\n style,\n onSubmitEditing,\n ref,\n error,\n control,\n name,\n ...props\n}) => {\n const [showPassword, setShowPassword] = useState(false);\n const { colors } = useThemeSafe();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;\n const inputRef = controller ? controller.field.ref : ref;\n\n const hasError = error || controller?.fieldState.error;\n\n return (\n <BaseInput\n label={props.label}\n error={error || controller?.fieldState.error?.message}\n helperText={props.helperText}\n containerStyle={props.containerStyle}\n >\n <View\n style={[\n {\n backgroundColor: colors.backgroundSecondary,\n borderColor: hasError ? colors.error : colors.border,\n borderWidth: hasError ? 1 : 0,\n flexDirection: 'row',\n alignItems: 'center',\n borderRadius: borderRadius.lg,\n },\n style as ViewStyle,\n ]}\n >\n <TextInput\n placeholderTextColor={colors.foregroundSecondary}\n ref={inputRef as any}\n {...props}\n style={[\n inputStyles,\n {\n flex: 1,\n color: colors.foreground,\n },\n ]}\n value={inputValue}\n onChangeText={inputOnChange}\n autoCapitalize=\"none\"\n onBlur={inputOnBlur}\n onSubmitEditing={onSubmitEditing}\n secureTextEntry={!showPassword}\n />\n <Button\n variant=\"ghost\"\n icon={showPassword ? 'eye-off' : 'eye'}\n size=\"sm\"\n onPress={() => setShowPassword(!showPassword)}\n />\n </View>\n </BaseInput>\n );\n};\n\n/**\n * Text input component with label, error, and helper text support.\n *\n * @example\n * ```tsx\n * <Input\n * label=\"Email\"\n * placeholder=\"Enter your email\"\n * value={email}\n * onChangeText={setEmail}\n * keyboardType=\"email-address\"\n * />\n *\n * // With React Hook Form\n * <Input\n * label=\"Email\"\n * control={control}\n * name=\"email\"\n * />\n * ```\n */\nexport const Input: React.FC<InputProps> = ({\n value,\n error,\n onChangeText,\n onSubmitEditing,\n style,\n ref,\n control,\n name,\n ...props\n}) => {\n const { colors } = useThemeSafe();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;\n const inputRef = controller ? controller.field.ref : ref;\n\n const hasError = error || controller?.fieldState.error;\n\n return (\n <BaseInput\n label={props.label}\n error={error || controller?.fieldState.error?.message}\n helperText={props.helperText}\n containerStyle={props.containerStyle}\n >\n <TextInput\n placeholderTextColor={colors.foregroundSecondary}\n ref={inputRef as any}\n value={inputValue}\n onChangeText={inputOnChange}\n onBlur={inputOnBlur}\n onSubmitEditing={onSubmitEditing}\n {...props}\n style={[\n inputStyles,\n {\n backgroundColor: colors.backgroundSecondary,\n color: colors.foreground,\n borderColor: hasError ? colors.error : colors.border,\n borderWidth: hasError ? 1 : 0,\n borderRadius: borderRadius.lg,\n },\n style,\n ]}\n />\n </BaseInput>\n );\n};\n"]}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from \"react\";\nimport { Control, useController } from \"react-hook-form\";\nimport { TextInput, TextInputProps, View, ViewStyle } from \"react-native\";\nimport { useThemeSafe } from \"../theme\";\nimport { borderRadius, spacing, useThemedStyles } from \"../utils/styles\";\nimport { Button } from \"./Button\";\nimport { Text } from \"./Text\";\n\nexport interface InputProps extends Omit<TextInputProps, \"style\"> {\n /** Field label */\n label?: string;\n /** Error message to display */\n error?: string;\n /** Helper text below input */\n helperText?: string;\n /** Custom input style */\n style?: TextInputProps[\"style\"];\n /** Container style */\n containerStyle?: ViewStyle;\n /** Input ref */\n ref?: React.RefObject<TextInput | null>;\n /** Element to render at the end of the input */\n endElement?: React.ReactNode;\n /** Child elements */\n children?: React.ReactNode;\n /** React Hook Form control object (optional) */\n control?: Control<any>;\n /** Field name for React Hook Form (optional) */\n name?: string;\n maxLength?: number;\n required?: boolean;\n}\n\nconst inputStyles = {\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.md,\n borderRadius: borderRadius.lg,\n fontSize: 16,\n};\n\n/**\n * Base input wrapper providing label, error, and helper text layout.\n */\nexport function BaseInput({\n label,\n error,\n helperText,\n containerStyle,\n children,\n maxLength,\n value,\n required,\n}: Pick<InputProps, \"label\" | \"error\" | \"helperText\" | \"containerStyle\" | \"children\" | \"maxLength\" | \"value\" | \"required\">) {\n const styles = useThemedStyles((colors) => ({\n label: {\n marginBottom: spacing.xs,\n color: colors.foregroundSecondary,\n fontSize: 14,\n },\n helperText: {\n marginTop: spacing.xs,\n },\n charCount: {\n textAlign: \"right\",\n },\n }));\n\n return (\n <View style={containerStyle}>\n {label && (\n <Text variant=\"body\" weight=\"medium\" style={styles.label}>\n {label} {required && <Text color=\"error\">*</Text>}\n </Text>\n )}\n {children}\n {error && (\n <Text variant=\"caption\" color=\"error\" style={styles.helperText}>\n {error}\n </Text>\n )}\n {!error && helperText && (\n <Text variant=\"caption\" color=\"secondary\" style={styles.helperText}>\n {helperText}\n </Text>\n )}\n {maxLength && (\n <Text variant=\"label\" color=\"tertiary\" style={styles.charCount}>\n {value?.length || 0}/{maxLength} characters\n </Text>\n )}\n </View>\n );\n}\n\n/**\n * Password input with visibility toggle.\n *\n * @example\n * ```tsx\n * <PasswordInput\n * label=\"Password\"\n * placeholder=\"Enter your password\"\n * value={password}\n * onChangeText={setPassword}\n * />\n *\n * // With React Hook Form\n * <PasswordInput\n * label=\"Password\"\n * control={control}\n * name=\"password\"\n * />\n * ```\n */\nexport const PasswordInput: React.FC<InputProps> = ({ value, onChangeText, style, onSubmitEditing, ref, error, control, name, ...props }) => {\n const [showPassword, setShowPassword] = useState(false);\n const { colors } = useThemeSafe();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;\n const inputRef = controller ? controller.field.ref : ref;\n\n const hasError = error || controller?.fieldState.error;\n\n return (\n <BaseInput\n value={inputValue}\n label={props.label}\n error={error || controller?.fieldState.error?.message}\n helperText={props.helperText}\n containerStyle={props.containerStyle}\n required={props.required}\n maxLength={props.maxLength}\n >\n <View\n style={[\n {\n backgroundColor: colors.backgroundSecondary,\n borderColor: hasError ? colors.error : colors.border,\n borderWidth: hasError ? 1 : 0,\n flexDirection: \"row\",\n alignItems: \"center\",\n borderRadius: borderRadius.lg,\n },\n style as ViewStyle,\n ]}\n >\n <TextInput\n placeholderTextColor={colors.foregroundSecondary}\n ref={inputRef as any}\n {...props}\n style={[\n inputStyles,\n {\n flex: 1,\n color: colors.foreground,\n },\n ]}\n value={inputValue}\n onChangeText={inputOnChange}\n autoCapitalize=\"none\"\n onBlur={inputOnBlur}\n onSubmitEditing={onSubmitEditing}\n secureTextEntry={!showPassword}\n />\n <Button variant=\"ghost\" icon={showPassword ? \"eye-off\" : \"eye\"} size=\"sm\" onPress={() => setShowPassword(!showPassword)} />\n </View>\n </BaseInput>\n );\n};\n\n/**\n * Text input component with label, error, and helper text support.\n *\n * @example\n * ```tsx\n * <Input\n * label=\"Email\"\n * placeholder=\"Enter your email\"\n * value={email}\n * onChangeText={setEmail}\n * keyboardType=\"email-address\"\n * />\n *\n * // With React Hook Form\n * <Input\n * label=\"Email\"\n * control={control}\n * name=\"email\"\n * />\n * ```\n */\nexport const Input: React.FC<InputProps> = ({ value, error, onChangeText, onSubmitEditing, style, ref, control, name, ...props }) => {\n const { colors } = useThemeSafe();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;\n const inputRef = controller ? controller.field.ref : ref;\n\n const hasError = error || controller?.fieldState.error;\n\n return (\n <BaseInput\n label={props.label}\n value={inputValue}\n error={error || controller?.fieldState.error?.message}\n helperText={props.helperText}\n containerStyle={props.containerStyle}\n required={props.required}\n maxLength={props.maxLength}\n >\n <TextInput\n placeholderTextColor={colors.foregroundSecondary}\n ref={inputRef as any}\n value={inputValue}\n onChangeText={inputOnChange}\n onBlur={inputOnBlur}\n onSubmitEditing={onSubmitEditing}\n {...props}\n style={[\n inputStyles,\n {\n backgroundColor: colors.backgroundSecondary,\n color: colors.foreground,\n borderColor: hasError ? colors.error : colors.border,\n borderWidth: hasError ? 1 : 0,\n borderRadius: borderRadius.lg,\n },\n style,\n ]}\n />\n </BaseInput>\n );\n};\n"]}
@@ -10,6 +10,7 @@ export interface TextAreaProps extends Omit<TextInputProps, "style"> {
10
10
  style?: StyleProp<ViewStyle>;
11
11
  control?: Control<any>;
12
12
  name?: string;
13
+ maxLength?: number;
13
14
  }
14
- export declare function TextArea({ label, error, helperText, minHeight, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }: TextAreaProps): React.JSX.Element;
15
+ export declare function TextArea({ label, error, helperText, minHeight, maxHeight, style, control, name, value, onChangeText, onBlur, maxLength, ...props }: TextAreaProps): React.JSX.Element;
15
16
  //# sourceMappingURL=TextArea.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../src/components/TextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAa,cAAc,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAKrF,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAe,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,qBAoE5J"}
1
+ {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../src/components/TextArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAa,cAAc,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAKrF,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAe,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,qBAkFvK"}
@@ -4,7 +4,7 @@ import { TextInput, View } from "react-native";
4
4
  import { useTheme } from "../theme";
5
5
  import { borderRadius, spacing, useThemedStyles } from "../utils";
6
6
  import { Text } from "./Text";
7
- export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }) {
7
+ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, maxLength, ...props }) {
8
8
  const { colors } = useTheme();
9
9
  // Use useController if control and name are provided
10
10
  const controller = control && name ? useController({ control, name }) : null;
@@ -37,6 +37,13 @@ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight,
37
37
  helperText: {
38
38
  marginTop: spacing.xs,
39
39
  fontSize: 12,
40
+ flexDirection: "row",
41
+ justifyContent: "space-between",
42
+ paddingHorizontal: spacing.xs,
43
+ },
44
+ charCount: {
45
+ marginTop: spacing.xs,
46
+ fontSize: 12,
40
47
  },
41
48
  }));
42
49
  return (<View style={[styles.container, style]}>
@@ -44,12 +51,17 @@ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight,
44
51
  {label}
45
52
  </Text>)}
46
53
  <TextInput ref={inputRef} value={inputValue} onChangeText={inputOnChange} onBlur={inputOnBlur} placeholderTextColor={colors.foregroundSecondary} multiline {...props} style={styles.textArea}/>
47
- {(error || controller?.fieldState.error?.message) && (<Text variant="caption" color="error" style={styles.helperText}>
48
- {error || controller?.fieldState.error?.message}
49
- </Text>)}
50
- {!error && !controller?.fieldState.error && helperText && (<Text variant="caption" color="secondary" style={styles.helperText}>
51
- {helperText}
52
- </Text>)}
54
+ <View style={styles.helperText}>
55
+ {(error || controller?.fieldState.error?.message) && (<Text variant="caption" color="error">
56
+ {error || controller?.fieldState.error?.message}
57
+ </Text>)}
58
+ {!error && !controller?.fieldState.error && helperText && (<Text variant="caption" color="secondary">
59
+ {helperText}
60
+ </Text>)}
61
+ {maxLength && (<Text variant="caption" color="tertiary">
62
+ {inputValue.length}/{maxLength}
63
+ </Text>)}
64
+ </View>
53
65
  </View>);
54
66
  }
55
67
  //# sourceMappingURL=TextArea.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.js","sourceRoot":"","sources":["../../src/components/TextArea.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { Control, useController } from \"react-hook-form\";\nimport { StyleProp, TextInput, TextInputProps, View, ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { borderRadius, spacing, useThemedStyles } from \"../utils\";\nimport { Text } from \"./Text\";\n\nexport interface TextAreaProps extends Omit<TextInputProps, \"style\"> {\n label?: string;\n error?: string;\n helperText?: string;\n minHeight?: number;\n maxHeight?: number;\n style?: StyleProp<ViewStyle>;\n control?: Control<any>;\n name?: string;\n}\n\nexport function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }: TextAreaProps) {\n const { colors } = useTheme();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : onBlur;\n const inputRef = controller ? controller.field.ref : undefined;\n\n const styles = useThemedStyles((colors) => ({\n container: {\n width: \"100%\",\n },\n label: {\n marginBottom: spacing.xs,\n color: colors.foregroundSecondary,\n fontSize: 14,\n },\n textArea: {\n backgroundColor: colors.backgroundSecondary,\n borderRadius: borderRadius.lg,\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.md,\n color: colors.foreground,\n fontSize: 16,\n minHeight: minHeight,\n maxHeight: maxHeight,\n textAlignVertical: \"top\",\n borderWidth: error || controller?.fieldState.error ? 1 : 0,\n borderColor: error || controller?.fieldState.error ? colors.error : \"transparent\",\n },\n helperText: {\n marginTop: spacing.xs,\n fontSize: 12,\n },\n }));\n\n return (\n <View style={[styles.container, style]}>\n {label && (\n <Text variant=\"body\" weight=\"medium\" style={styles.label}>\n {label}\n </Text>\n )}\n <TextInput\n ref={inputRef as any}\n value={inputValue}\n onChangeText={inputOnChange}\n onBlur={inputOnBlur}\n placeholderTextColor={colors.foregroundSecondary}\n multiline\n {...props}\n style={styles.textArea}\n />\n {(error || controller?.fieldState.error?.message) && (\n <Text variant=\"caption\" color=\"error\" style={styles.helperText}>\n {error || controller?.fieldState.error?.message}\n </Text>\n )}\n {!error && !controller?.fieldState.error && helperText && (\n <Text variant=\"caption\" color=\"secondary\" style={styles.helperText}>\n {helperText}\n </Text>\n )}\n </View>\n );\n}\n"]}
1
+ {"version":3,"file":"TextArea.js","sourceRoot":"","sources":["../../src/components/TextArea.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { Control, useController } from \"react-hook-form\";\nimport { StyleProp, TextInput, TextInputProps, View, ViewStyle } from \"react-native\";\nimport { useTheme } from \"../theme\";\nimport { borderRadius, spacing, useThemedStyles } from \"../utils\";\nimport { Text } from \"./Text\";\n\nexport interface TextAreaProps extends Omit<TextInputProps, \"style\"> {\n label?: string;\n error?: string;\n helperText?: string;\n minHeight?: number;\n maxHeight?: number;\n style?: StyleProp<ViewStyle>;\n control?: Control<any>;\n name?: string;\n maxLength?: number;\n}\n\nexport function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, maxLength, ...props }: TextAreaProps) {\n const { colors } = useTheme();\n\n // Use useController if control and name are provided\n const controller = control && name ? useController({ control, name }) : null;\n\n const inputValue = controller ? controller.field.value : value;\n const inputOnChange = controller ? controller.field.onChange : onChangeText;\n const inputOnBlur = controller ? controller.field.onBlur : onBlur;\n const inputRef = controller ? controller.field.ref : undefined;\n\n const styles = useThemedStyles((colors) => ({\n container: {\n width: \"100%\",\n },\n label: {\n marginBottom: spacing.xs,\n color: colors.foregroundSecondary,\n fontSize: 14,\n },\n textArea: {\n backgroundColor: colors.backgroundSecondary,\n borderRadius: borderRadius.lg,\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.md,\n color: colors.foreground,\n fontSize: 16,\n minHeight: minHeight,\n maxHeight: maxHeight,\n textAlignVertical: \"top\",\n borderWidth: error || controller?.fieldState.error ? 1 : 0,\n borderColor: error || controller?.fieldState.error ? colors.error : \"transparent\",\n },\n helperText: {\n marginTop: spacing.xs,\n fontSize: 12,\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n paddingHorizontal: spacing.xs,\n },\n charCount: {\n marginTop: spacing.xs,\n fontSize: 12,\n },\n }));\n\n return (\n <View style={[styles.container, style]}>\n {label && (\n <Text variant=\"body\" weight=\"medium\" style={styles.label}>\n {label}\n </Text>\n )}\n <TextInput\n ref={inputRef as any}\n value={inputValue}\n onChangeText={inputOnChange}\n onBlur={inputOnBlur}\n placeholderTextColor={colors.foregroundSecondary}\n multiline\n {...props}\n style={styles.textArea}\n />\n <View style={styles.helperText}>\n {(error || controller?.fieldState.error?.message) && (\n <Text variant=\"caption\" color=\"error\">\n {error || controller?.fieldState.error?.message}\n </Text>\n )}\n {!error && !controller?.fieldState.error && helperText && (\n <Text variant=\"caption\" color=\"secondary\">\n {helperText}\n </Text>\n )}\n {maxLength && (\n <Text variant=\"caption\" color=\"tertiary\">\n {inputValue.length}/{maxLength}\n </Text>\n )}\n </View>\n </View>\n );\n}\n"]}
@@ -16,4 +16,6 @@ export { FormView } from "./FormView";
16
16
  export type { FormViewProps } from "./FormView";
17
17
  export { TextArea } from "./TextArea";
18
18
  export type { TextAreaProps } from "./TextArea";
19
+ export { Card } from "./Card";
20
+ export type { CardProps } from "./Card";
19
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGvF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGvF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
@@ -13,4 +13,5 @@ export { DynamicStatusBar } from "./DynamicStatusBar";
13
13
  export { HeaderView } from "./HeaderView";
14
14
  export { FormView } from "./FormView";
15
15
  export { TextArea } from "./TextArea";
16
+ export { Card } from "./Card";
16
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,OAAO;AACP,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1D,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC","sourcesContent":["// Button\nexport { Button } from \"./Button\";\nexport type { ButtonProps, ButtonSize, ButtonVariant } from \"./Button\";\n\n// Text\nexport { Text } from \"./Text\";\nexport type { TextAlign, TextColor, TextProps, TextVariant, TextWeight } from \"./Text\";\n\n// Input\nexport { BaseInput, Input, PasswordInput } from \"./Input\";\nexport type { InputProps } from \"./Input\";\n\n// SegmentedControl\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { Segment, SegmentedControlProps } from \"./SegmentedControl\";\n\n// Badge\nexport { Badge } from \"./Badge\";\nexport type { BadgeProps, BadgeStatus } from \"./Badge\";\n\n// DynamicStatusBar\nexport { DynamicStatusBar } from \"./DynamicStatusBar\";\nexport type { DynamicStatusBarProps } from \"./DynamicStatusBar\";\n\nexport { HeaderView } from \"./HeaderView\";\nexport type { HeaderViewProps } from \"./HeaderView\";\n\nexport { FormView } from \"./FormView\";\nexport type { FormViewProps } from \"./FormView\";\n\nexport { TextArea } from \"./TextArea\";\nexport type { TextAreaProps } from \"./TextArea\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,OAAO;AACP,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1D,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC","sourcesContent":["// Button\nexport { Button } from \"./Button\";\nexport type { ButtonProps, ButtonSize, ButtonVariant } from \"./Button\";\n\n// Text\nexport { Text } from \"./Text\";\nexport type { TextAlign, TextColor, TextProps, TextVariant, TextWeight } from \"./Text\";\n\n// Input\nexport { BaseInput, Input, PasswordInput } from \"./Input\";\nexport type { InputProps } from \"./Input\";\n\n// SegmentedControl\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { Segment, SegmentedControlProps } from \"./SegmentedControl\";\n\n// Badge\nexport { Badge } from \"./Badge\";\nexport type { BadgeProps, BadgeStatus } from \"./Badge\";\n\n// DynamicStatusBar\nexport { DynamicStatusBar } from \"./DynamicStatusBar\";\nexport type { DynamicStatusBarProps } from \"./DynamicStatusBar\";\n\nexport { HeaderView } from \"./HeaderView\";\nexport type { HeaderViewProps } from \"./HeaderView\";\n\nexport { FormView } from \"./FormView\";\nexport type { FormViewProps } from \"./FormView\";\n\nexport { TextArea } from \"./TextArea\";\nexport type { TextAreaProps } from \"./TextArea\";\n\nexport { Card } from \"./Card\";\nexport type { CardProps } from \"./Card\";\n"]}
package/build/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { defaultDarkColors, defaultDarkTheme, defaultLightColors, defaultTheme, ThemeContext, ThemeProvider, useTheme, useThemeSafe } from "./theme";
2
2
  export type { Theme, ThemeColors, ThemeContextValue, ThemeProviderProps } from "./theme";
3
- export { Badge, BaseInput, Button, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
4
- export type { BadgeProps, BadgeStatus, ButtonProps, ButtonSize, ButtonVariant, DynamicStatusBarProps, FormViewProps, InputProps, Segment, SegmentedControlProps, TextAlign, TextAreaProps, TextColor, TextProps, TextVariant, TextWeight, } from "./components";
3
+ export { Badge, BaseInput, Button, Card, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
4
+ export type { BadgeProps, BadgeStatus, ButtonProps, ButtonSize, ButtonVariant, CardProps, DynamicStatusBarProps, FormViewProps, InputProps, Segment, SegmentedControlProps, TextAlign, TextAreaProps, TextColor, TextProps, TextVariant, TextWeight, } from "./components";
5
5
  export { borderRadius, createThemedStyle, layouts, shadows, spacing, typography, useThemedStyles } from "./utils";
6
6
  export type { BorderRadiusKey, LayoutKey, ShadowKey, SpacingKey, TypographyVariant } from "./utils";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErJ,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGzF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExJ,YAAY,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,OAAO,EACP,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAElH,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErJ,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGzF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE9J,YAAY,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,SAAS,EACT,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,OAAO,EACP,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAElH,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
package/build/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // Theme system
5
5
  export { defaultDarkColors, defaultDarkTheme, defaultLightColors, defaultTheme, ThemeContext, ThemeProvider, useTheme, useThemeSafe } from "./theme";
6
6
  // Components
7
- export { Badge, BaseInput, Button, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
7
+ export { Badge, BaseInput, Button, Card, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
8
8
  // Utilities
9
9
  export { borderRadius, createThemedStyle, layouts, shadows, spacing, typography, useThemedStyles } from "./utils";
10
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0DAA0D;AAC1D,+EAA+E;AAE/E,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIrJ,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAqBxJ,YAAY;AACZ,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC","sourcesContent":["// ============================================================================\n// @robin-ux/native - Themeable React Native UI Components\n// ============================================================================\n\n// Theme system\nexport { defaultDarkColors, defaultDarkTheme, defaultLightColors, defaultTheme, ThemeContext, ThemeProvider, useTheme, useThemeSafe } from \"./theme\";\n\nexport type { Theme, ThemeColors, ThemeContextValue, ThemeProviderProps } from \"./theme\";\n\n// Components\nexport { Badge, BaseInput, Button, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from \"./components\";\n\nexport type {\n BadgeProps,\n BadgeStatus,\n ButtonProps,\n ButtonSize,\n ButtonVariant,\n DynamicStatusBarProps,\n FormViewProps,\n InputProps,\n Segment,\n SegmentedControlProps,\n TextAlign,\n TextAreaProps,\n TextColor,\n TextProps,\n TextVariant,\n TextWeight,\n} from \"./components\";\n\n// Utilities\nexport { borderRadius, createThemedStyle, layouts, shadows, spacing, typography, useThemedStyles } from \"./utils\";\n\nexport type { BorderRadiusKey, LayoutKey, ShadowKey, SpacingKey, TypographyVariant } from \"./utils\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0DAA0D;AAC1D,+EAA+E;AAE/E,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIrJ,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAsB9J,YAAY;AACZ,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC","sourcesContent":["// ============================================================================\n// @robin-ux/native - Themeable React Native UI Components\n// ============================================================================\n\n// Theme system\nexport { defaultDarkColors, defaultDarkTheme, defaultLightColors, defaultTheme, ThemeContext, ThemeProvider, useTheme, useThemeSafe } from \"./theme\";\n\nexport type { Theme, ThemeColors, ThemeContextValue, ThemeProviderProps } from \"./theme\";\n\n// Components\nexport { Badge, BaseInput, Button, Card, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from \"./components\";\n\nexport type {\n BadgeProps,\n BadgeStatus,\n ButtonProps,\n ButtonSize,\n ButtonVariant,\n CardProps,\n DynamicStatusBarProps,\n FormViewProps,\n InputProps,\n Segment,\n SegmentedControlProps,\n TextAlign,\n TextAreaProps,\n TextColor,\n TextProps,\n TextVariant,\n TextWeight,\n} from \"./components\";\n\n// Utilities\nexport { borderRadius, createThemedStyle, layouts, shadows, spacing, typography, useThemedStyles } from \"./utils\";\n\nexport type { BorderRadiusKey, LayoutKey, ShadowKey, SpacingKey, TypographyVariant } from \"./utils\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robin-ux/native",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Themeable React Native UI components for Expo projects",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -0,0 +1,53 @@
1
+ import React from "react";
2
+ import { StyleSheet, View, ViewProps } from "react-native";
3
+ import { useTheme } from "../theme";
4
+ import { borderRadius, shadows, spacing } from "../utils/styles";
5
+
6
+ type CardVariant = "default" | "elevated" | "outlined";
7
+
8
+ export interface CardProps extends Omit<ViewProps, "style"> {
9
+ variant?: CardVariant;
10
+ padding?: keyof typeof spacing;
11
+ style?: ViewProps["style"];
12
+ children: React.ReactNode;
13
+ bg?: "primary" | "secondary";
14
+ }
15
+
16
+ export function Card({ variant = "default", padding = "md", style, children, bg, ...props }: CardProps) {
17
+ const { colors } = useTheme();
18
+ let backgroundColor = colors.card;
19
+ if (bg === "primary") {
20
+ backgroundColor = colors.background;
21
+ } else if (bg === "secondary") {
22
+ backgroundColor = colors.background;
23
+ }
24
+
25
+ const variantStyles = {
26
+ default: {
27
+ backgroundColor: backgroundColor,
28
+ },
29
+ elevated: {
30
+ backgroundColor: backgroundColor,
31
+ ...shadows.md,
32
+ },
33
+ outlined: {
34
+ backgroundColor: backgroundColor,
35
+ borderWidth: 1,
36
+ borderColor: colors.border,
37
+ },
38
+ }[variant];
39
+
40
+ const cardStyle = [styles.card, variantStyles, { padding: spacing[padding] }, style];
41
+
42
+ return (
43
+ <View style={cardStyle} {...props}>
44
+ {children}
45
+ </View>
46
+ );
47
+ }
48
+
49
+ const styles = StyleSheet.create({
50
+ card: {
51
+ borderRadius: borderRadius.lg,
52
+ },
53
+ });
@@ -1,82 +1,95 @@
1
- import React, { useState } from 'react';
2
- import { Control, useController } from 'react-hook-form';
3
- import { TextInput, TextInputProps, View, ViewStyle } from 'react-native';
4
- import { useThemeSafe } from '../theme';
5
- import { borderRadius, spacing, useThemedStyles } from '../utils/styles';
6
- import { Button } from './Button';
7
- import { Text } from './Text';
1
+ import React, { useState } from "react";
2
+ import { Control, useController } from "react-hook-form";
3
+ import { TextInput, TextInputProps, View, ViewStyle } from "react-native";
4
+ import { useThemeSafe } from "../theme";
5
+ import { borderRadius, spacing, useThemedStyles } from "../utils/styles";
6
+ import { Button } from "./Button";
7
+ import { Text } from "./Text";
8
8
 
9
- export interface InputProps extends Omit<TextInputProps, 'style'> {
10
- /** Field label */
11
- label?: string;
12
- /** Error message to display */
13
- error?: string;
14
- /** Helper text below input */
15
- helperText?: string;
16
- /** Custom input style */
17
- style?: TextInputProps['style'];
18
- /** Container style */
19
- containerStyle?: ViewStyle;
20
- /** Input ref */
21
- ref?: React.RefObject<TextInput | null>;
22
- /** Element to render at the end of the input */
23
- endElement?: React.ReactNode;
24
- /** Child elements */
25
- children?: React.ReactNode;
26
- /** React Hook Form control object (optional) */
27
- control?: Control<any>;
28
- /** Field name for React Hook Form (optional) */
29
- name?: string;
9
+ export interface InputProps extends Omit<TextInputProps, "style"> {
10
+ /** Field label */
11
+ label?: string;
12
+ /** Error message to display */
13
+ error?: string;
14
+ /** Helper text below input */
15
+ helperText?: string;
16
+ /** Custom input style */
17
+ style?: TextInputProps["style"];
18
+ /** Container style */
19
+ containerStyle?: ViewStyle;
20
+ /** Input ref */
21
+ ref?: React.RefObject<TextInput | null>;
22
+ /** Element to render at the end of the input */
23
+ endElement?: React.ReactNode;
24
+ /** Child elements */
25
+ children?: React.ReactNode;
26
+ /** React Hook Form control object (optional) */
27
+ control?: Control<any>;
28
+ /** Field name for React Hook Form (optional) */
29
+ name?: string;
30
+ maxLength?: number;
31
+ required?: boolean;
30
32
  }
31
33
 
32
34
  const inputStyles = {
33
- paddingHorizontal: spacing.md,
34
- paddingVertical: spacing.md,
35
- borderRadius: borderRadius.lg,
36
- fontSize: 16,
35
+ paddingHorizontal: spacing.md,
36
+ paddingVertical: spacing.md,
37
+ borderRadius: borderRadius.lg,
38
+ fontSize: 16,
37
39
  };
38
40
 
39
41
  /**
40
42
  * Base input wrapper providing label, error, and helper text layout.
41
43
  */
42
44
  export function BaseInput({
43
- label,
44
- error,
45
- helperText,
46
- containerStyle,
47
- children,
48
- }: Pick<InputProps, 'label' | 'error' | 'helperText' | 'containerStyle' | 'children'>) {
49
- const styles = useThemedStyles((colors) => ({
50
- label: {
51
- marginBottom: spacing.xs,
52
- color: colors.foregroundSecondary,
53
- fontSize: 14,
54
- },
55
- helperText: {
56
- marginTop: spacing.xs,
57
- },
58
- }));
45
+ label,
46
+ error,
47
+ helperText,
48
+ containerStyle,
49
+ children,
50
+ maxLength,
51
+ value,
52
+ required,
53
+ }: Pick<InputProps, "label" | "error" | "helperText" | "containerStyle" | "children" | "maxLength" | "value" | "required">) {
54
+ const styles = useThemedStyles((colors) => ({
55
+ label: {
56
+ marginBottom: spacing.xs,
57
+ color: colors.foregroundSecondary,
58
+ fontSize: 14,
59
+ },
60
+ helperText: {
61
+ marginTop: spacing.xs,
62
+ },
63
+ charCount: {
64
+ textAlign: "right",
65
+ },
66
+ }));
59
67
 
60
- return (
61
- <View style={containerStyle}>
62
- {label && (
63
- <Text variant="body" weight="medium" style={styles.label}>
64
- {label}
65
- </Text>
66
- )}
67
- {children}
68
- {error && (
69
- <Text variant="caption" color="error" style={styles.helperText}>
70
- {error}
71
- </Text>
72
- )}
73
- {!error && helperText && (
74
- <Text variant="caption" color="secondary" style={styles.helperText}>
75
- {helperText}
76
- </Text>
77
- )}
78
- </View>
79
- );
68
+ return (
69
+ <View style={containerStyle}>
70
+ {label && (
71
+ <Text variant="body" weight="medium" style={styles.label}>
72
+ {label} {required && <Text color="error">*</Text>}
73
+ </Text>
74
+ )}
75
+ {children}
76
+ {error && (
77
+ <Text variant="caption" color="error" style={styles.helperText}>
78
+ {error}
79
+ </Text>
80
+ )}
81
+ {!error && helperText && (
82
+ <Text variant="caption" color="secondary" style={styles.helperText}>
83
+ {helperText}
84
+ </Text>
85
+ )}
86
+ {maxLength && (
87
+ <Text variant="label" color="tertiary" style={styles.charCount}>
88
+ {value?.length || 0}/{maxLength} characters
89
+ </Text>
90
+ )}
91
+ </View>
92
+ );
80
93
  }
81
94
 
82
95
  /**
@@ -99,77 +112,65 @@ export function BaseInput({
99
112
  * />
100
113
  * ```
101
114
  */
102
- export const PasswordInput: React.FC<InputProps> = ({
103
- value,
104
- onChangeText,
105
- style,
106
- onSubmitEditing,
107
- ref,
108
- error,
109
- control,
110
- name,
111
- ...props
112
- }) => {
113
- const [showPassword, setShowPassword] = useState(false);
114
- const { colors } = useThemeSafe();
115
+ export const PasswordInput: React.FC<InputProps> = ({ value, onChangeText, style, onSubmitEditing, ref, error, control, name, ...props }) => {
116
+ const [showPassword, setShowPassword] = useState(false);
117
+ const { colors } = useThemeSafe();
115
118
 
116
- // Use useController if control and name are provided
117
- const controller = control && name ? useController({ control, name }) : null;
119
+ // Use useController if control and name are provided
120
+ const controller = control && name ? useController({ control, name }) : null;
118
121
 
119
- const inputValue = controller ? controller.field.value : value;
120
- const inputOnChange = controller ? controller.field.onChange : onChangeText;
121
- const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
122
- const inputRef = controller ? controller.field.ref : ref;
122
+ const inputValue = controller ? controller.field.value : value;
123
+ const inputOnChange = controller ? controller.field.onChange : onChangeText;
124
+ const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
125
+ const inputRef = controller ? controller.field.ref : ref;
123
126
 
124
- const hasError = error || controller?.fieldState.error;
127
+ const hasError = error || controller?.fieldState.error;
125
128
 
126
- return (
127
- <BaseInput
128
- label={props.label}
129
- error={error || controller?.fieldState.error?.message}
130
- helperText={props.helperText}
131
- containerStyle={props.containerStyle}
132
- >
133
- <View
134
- style={[
135
- {
136
- backgroundColor: colors.backgroundSecondary,
137
- borderColor: hasError ? colors.error : colors.border,
138
- borderWidth: hasError ? 1 : 0,
139
- flexDirection: 'row',
140
- alignItems: 'center',
141
- borderRadius: borderRadius.lg,
142
- },
143
- style as ViewStyle,
144
- ]}
145
- >
146
- <TextInput
147
- placeholderTextColor={colors.foregroundSecondary}
148
- ref={inputRef as any}
149
- {...props}
150
- style={[
151
- inputStyles,
152
- {
153
- flex: 1,
154
- color: colors.foreground,
155
- },
156
- ]}
157
- value={inputValue}
158
- onChangeText={inputOnChange}
159
- autoCapitalize="none"
160
- onBlur={inputOnBlur}
161
- onSubmitEditing={onSubmitEditing}
162
- secureTextEntry={!showPassword}
163
- />
164
- <Button
165
- variant="ghost"
166
- icon={showPassword ? 'eye-off' : 'eye'}
167
- size="sm"
168
- onPress={() => setShowPassword(!showPassword)}
169
- />
170
- </View>
171
- </BaseInput>
172
- );
129
+ return (
130
+ <BaseInput
131
+ value={inputValue}
132
+ label={props.label}
133
+ error={error || controller?.fieldState.error?.message}
134
+ helperText={props.helperText}
135
+ containerStyle={props.containerStyle}
136
+ required={props.required}
137
+ maxLength={props.maxLength}
138
+ >
139
+ <View
140
+ style={[
141
+ {
142
+ backgroundColor: colors.backgroundSecondary,
143
+ borderColor: hasError ? colors.error : colors.border,
144
+ borderWidth: hasError ? 1 : 0,
145
+ flexDirection: "row",
146
+ alignItems: "center",
147
+ borderRadius: borderRadius.lg,
148
+ },
149
+ style as ViewStyle,
150
+ ]}
151
+ >
152
+ <TextInput
153
+ placeholderTextColor={colors.foregroundSecondary}
154
+ ref={inputRef as any}
155
+ {...props}
156
+ style={[
157
+ inputStyles,
158
+ {
159
+ flex: 1,
160
+ color: colors.foreground,
161
+ },
162
+ ]}
163
+ value={inputValue}
164
+ onChangeText={inputOnChange}
165
+ autoCapitalize="none"
166
+ onBlur={inputOnBlur}
167
+ onSubmitEditing={onSubmitEditing}
168
+ secureTextEntry={!showPassword}
169
+ />
170
+ <Button variant="ghost" icon={showPassword ? "eye-off" : "eye"} size="sm" onPress={() => setShowPassword(!showPassword)} />
171
+ </View>
172
+ </BaseInput>
173
+ );
173
174
  };
174
175
 
175
176
  /**
@@ -193,56 +194,49 @@ export const PasswordInput: React.FC<InputProps> = ({
193
194
  * />
194
195
  * ```
195
196
  */
196
- export const Input: React.FC<InputProps> = ({
197
- value,
198
- error,
199
- onChangeText,
200
- onSubmitEditing,
201
- style,
202
- ref,
203
- control,
204
- name,
205
- ...props
206
- }) => {
207
- const { colors } = useThemeSafe();
197
+ export const Input: React.FC<InputProps> = ({ value, error, onChangeText, onSubmitEditing, style, ref, control, name, ...props }) => {
198
+ const { colors } = useThemeSafe();
208
199
 
209
- // Use useController if control and name are provided
210
- const controller = control && name ? useController({ control, name }) : null;
200
+ // Use useController if control and name are provided
201
+ const controller = control && name ? useController({ control, name }) : null;
211
202
 
212
- const inputValue = controller ? controller.field.value : value;
213
- const inputOnChange = controller ? controller.field.onChange : onChangeText;
214
- const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
215
- const inputRef = controller ? controller.field.ref : ref;
203
+ const inputValue = controller ? controller.field.value : value;
204
+ const inputOnChange = controller ? controller.field.onChange : onChangeText;
205
+ const inputOnBlur = controller ? controller.field.onBlur : props.onBlur;
206
+ const inputRef = controller ? controller.field.ref : ref;
216
207
 
217
- const hasError = error || controller?.fieldState.error;
208
+ const hasError = error || controller?.fieldState.error;
218
209
 
219
- return (
220
- <BaseInput
221
- label={props.label}
222
- error={error || controller?.fieldState.error?.message}
223
- helperText={props.helperText}
224
- containerStyle={props.containerStyle}
225
- >
226
- <TextInput
227
- placeholderTextColor={colors.foregroundSecondary}
228
- ref={inputRef as any}
229
- value={inputValue}
230
- onChangeText={inputOnChange}
231
- onBlur={inputOnBlur}
232
- onSubmitEditing={onSubmitEditing}
233
- {...props}
234
- style={[
235
- inputStyles,
236
- {
237
- backgroundColor: colors.backgroundSecondary,
238
- color: colors.foreground,
239
- borderColor: hasError ? colors.error : colors.border,
240
- borderWidth: hasError ? 1 : 0,
241
- borderRadius: borderRadius.lg,
242
- },
243
- style,
244
- ]}
245
- />
246
- </BaseInput>
247
- );
210
+ return (
211
+ <BaseInput
212
+ label={props.label}
213
+ value={inputValue}
214
+ error={error || controller?.fieldState.error?.message}
215
+ helperText={props.helperText}
216
+ containerStyle={props.containerStyle}
217
+ required={props.required}
218
+ maxLength={props.maxLength}
219
+ >
220
+ <TextInput
221
+ placeholderTextColor={colors.foregroundSecondary}
222
+ ref={inputRef as any}
223
+ value={inputValue}
224
+ onChangeText={inputOnChange}
225
+ onBlur={inputOnBlur}
226
+ onSubmitEditing={onSubmitEditing}
227
+ {...props}
228
+ style={[
229
+ inputStyles,
230
+ {
231
+ backgroundColor: colors.backgroundSecondary,
232
+ color: colors.foreground,
233
+ borderColor: hasError ? colors.error : colors.border,
234
+ borderWidth: hasError ? 1 : 0,
235
+ borderRadius: borderRadius.lg,
236
+ },
237
+ style,
238
+ ]}
239
+ />
240
+ </BaseInput>
241
+ );
248
242
  };
@@ -14,9 +14,10 @@ export interface TextAreaProps extends Omit<TextInputProps, "style"> {
14
14
  style?: StyleProp<ViewStyle>;
15
15
  control?: Control<any>;
16
16
  name?: string;
17
+ maxLength?: number;
17
18
  }
18
19
 
19
- export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }: TextAreaProps) {
20
+ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, maxLength, ...props }: TextAreaProps) {
20
21
  const { colors } = useTheme();
21
22
 
22
23
  // Use useController if control and name are provided
@@ -52,6 +53,13 @@ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight,
52
53
  helperText: {
53
54
  marginTop: spacing.xs,
54
55
  fontSize: 12,
56
+ flexDirection: "row",
57
+ justifyContent: "space-between",
58
+ paddingHorizontal: spacing.xs,
59
+ },
60
+ charCount: {
61
+ marginTop: spacing.xs,
62
+ fontSize: 12,
55
63
  },
56
64
  }));
57
65
 
@@ -72,16 +80,23 @@ export function TextArea({ label, error, helperText, minHeight = 120, maxHeight,
72
80
  {...props}
73
81
  style={styles.textArea}
74
82
  />
75
- {(error || controller?.fieldState.error?.message) && (
76
- <Text variant="caption" color="error" style={styles.helperText}>
77
- {error || controller?.fieldState.error?.message}
78
- </Text>
79
- )}
80
- {!error && !controller?.fieldState.error && helperText && (
81
- <Text variant="caption" color="secondary" style={styles.helperText}>
82
- {helperText}
83
- </Text>
84
- )}
83
+ <View style={styles.helperText}>
84
+ {(error || controller?.fieldState.error?.message) && (
85
+ <Text variant="caption" color="error">
86
+ {error || controller?.fieldState.error?.message}
87
+ </Text>
88
+ )}
89
+ {!error && !controller?.fieldState.error && helperText && (
90
+ <Text variant="caption" color="secondary">
91
+ {helperText}
92
+ </Text>
93
+ )}
94
+ {maxLength && (
95
+ <Text variant="caption" color="tertiary">
96
+ {inputValue.length}/{maxLength}
97
+ </Text>
98
+ )}
99
+ </View>
85
100
  </View>
86
101
  );
87
102
  }
@@ -30,3 +30,6 @@ export type { FormViewProps } from "./FormView";
30
30
 
31
31
  export { TextArea } from "./TextArea";
32
32
  export type { TextAreaProps } from "./TextArea";
33
+
34
+ export { Card } from "./Card";
35
+ export type { CardProps } from "./Card";
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ export { defaultDarkColors, defaultDarkTheme, defaultLightColors, defaultTheme,
8
8
  export type { Theme, ThemeColors, ThemeContextValue, ThemeProviderProps } from "./theme";
9
9
 
10
10
  // Components
11
- export { Badge, BaseInput, Button, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
11
+ export { Badge, BaseInput, Button, Card, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
12
12
 
13
13
  export type {
14
14
  BadgeProps,
@@ -16,6 +16,7 @@ export type {
16
16
  ButtonProps,
17
17
  ButtonSize,
18
18
  ButtonVariant,
19
+ CardProps,
19
20
  DynamicStatusBarProps,
20
21
  FormViewProps,
21
22
  InputProps,