@robin-ux/native 0.1.2 → 0.1.3
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/build/components/FormView.d.ts +18 -0
- package/build/components/FormView.d.ts.map +1 -0
- package/build/components/FormView.js +68 -0
- package/build/components/FormView.js.map +1 -0
- package/build/components/TextArea.d.ts +15 -0
- package/build/components/TextArea.d.ts.map +1 -0
- package/build/components/TextArea.js +55 -0
- package/build/components/TextArea.js.map +1 -0
- package/build/components/index.d.ts +4 -0
- package/build/components/index.d.ts.map +1 -1
- package/build/components/index.js +2 -0
- package/build/components/index.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/theme/defaultTheme.d.ts +1 -1
- package/build/theme/defaultTheme.d.ts.map +1 -1
- package/build/theme/defaultTheme.js +42 -40
- package/build/theme/defaultTheme.js.map +1 -1
- package/build/theme/types.d.ts +1 -0
- package/build/theme/types.d.ts.map +1 -1
- package/build/theme/types.js.map +1 -1
- package/package.json +1 -1
- package/src/components/FormView.tsx +102 -0
- package/src/components/TextArea.tsx +87 -0
- package/src/components/index.ts +6 -0
- package/src/index.ts +3 -1
- package/src/theme/defaultTheme.ts +59 -57
- package/src/theme/types.ts +30 -30
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
4
|
+
import { Edge } from "react-native-safe-area-context";
|
|
5
|
+
export interface FormViewProps {
|
|
6
|
+
title: string;
|
|
7
|
+
onBack?: () => void;
|
|
8
|
+
backIcon?: keyof typeof Ionicons.glyphMap;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
footer?: React.ReactNode;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
edges?: Edge[];
|
|
13
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
14
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
15
|
+
isModal?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function FormView({ title, onBack, backIcon, children, footer, loading, edges, containerStyle, contentContainerStyle, isModal, }: FormViewProps): React.JSX.Element;
|
|
18
|
+
//# sourceMappingURL=FormView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormView.d.ts","sourceRoot":"","sources":["../../src/components/FormView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAA8C,SAAS,EAA0B,SAAS,EAAE,MAAM,cAAc,CAAC;AACxH,OAAO,EAAE,IAAI,EAAgB,MAAM,gCAAgC,CAAC;AAKpE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,qBAAqB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,EACrB,KAAK,EACL,MAAM,EACN,QAAuB,EACvB,QAAQ,EACR,MAAM,EACN,OAAe,EACf,KAA0C,EAC1C,cAAc,EACd,qBAAqB,EACrB,OAAe,GAClB,EAAE,aAAa,qBAoEf"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
+
import { StatusBar } from "expo-status-bar";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { KeyboardAvoidingView, Platform, ScrollView, TouchableOpacity, View } from "react-native";
|
|
5
|
+
import { SafeAreaView } from "react-native-safe-area-context";
|
|
6
|
+
import { useTheme } from "../theme";
|
|
7
|
+
import { layouts, spacing, useThemedStyles } from "../utils";
|
|
8
|
+
import { Text } from "./Text";
|
|
9
|
+
export function FormView({ title, onBack, backIcon = "arrow-back", children, footer, loading = false, edges = ["top", "left", "right", "bottom"], containerStyle, contentContainerStyle, isModal = false, }) {
|
|
10
|
+
const { isDark, colors } = useTheme();
|
|
11
|
+
const styles = useThemedStyles((colors) => ({
|
|
12
|
+
container: {
|
|
13
|
+
flex: 1,
|
|
14
|
+
backgroundColor: isModal ? "transparent" : colors.background,
|
|
15
|
+
},
|
|
16
|
+
header: {
|
|
17
|
+
flexDirection: "row",
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
justifyContent: "space-between",
|
|
20
|
+
paddingHorizontal: spacing.lg,
|
|
21
|
+
paddingVertical: spacing.md,
|
|
22
|
+
borderBottomWidth: isModal ? 0 : 1,
|
|
23
|
+
borderBottomColor: colors.border,
|
|
24
|
+
},
|
|
25
|
+
headerTitle: {
|
|
26
|
+
flex: 1,
|
|
27
|
+
textAlign: "left",
|
|
28
|
+
},
|
|
29
|
+
backButton: {
|
|
30
|
+
marginRight: spacing.md,
|
|
31
|
+
padding: 4,
|
|
32
|
+
},
|
|
33
|
+
formScrollView: {
|
|
34
|
+
paddingHorizontal: spacing.lg,
|
|
35
|
+
paddingVertical: spacing.lg,
|
|
36
|
+
},
|
|
37
|
+
footer: {
|
|
38
|
+
paddingHorizontal: spacing.lg,
|
|
39
|
+
paddingBottom: spacing.xl,
|
|
40
|
+
paddingTop: spacing.md,
|
|
41
|
+
},
|
|
42
|
+
}));
|
|
43
|
+
const content = (<KeyboardAvoidingView style={layouts.flex1} behavior={Platform.OS === "ios" ? "padding" : "height"}>
|
|
44
|
+
<View style={styles.header}>
|
|
45
|
+
{onBack && (<TouchableOpacity onPress={onBack} style={styles.backButton} disabled={loading}>
|
|
46
|
+
<Ionicons name={backIcon} size={24} color={colors.icon}/>
|
|
47
|
+
</TouchableOpacity>)}
|
|
48
|
+
<Text variant="subheading" weight="extrabold" style={styles.headerTitle}>
|
|
49
|
+
{title}
|
|
50
|
+
</Text>
|
|
51
|
+
{onBack && !isModal && <View style={{ width: 32 }}/>}
|
|
52
|
+
</View>
|
|
53
|
+
|
|
54
|
+
<ScrollView style={layouts.flex1} contentContainerStyle={contentContainerStyle} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator={false}>
|
|
55
|
+
<View style={[styles.formScrollView, containerStyle]}>{children}</View>
|
|
56
|
+
</ScrollView>
|
|
57
|
+
|
|
58
|
+
{footer && <View style={styles.footer}>{footer}</View>}
|
|
59
|
+
</KeyboardAvoidingView>);
|
|
60
|
+
if (isModal) {
|
|
61
|
+
return <View style={styles.container}>{content}</View>;
|
|
62
|
+
}
|
|
63
|
+
return (<SafeAreaView style={styles.container} edges={edges}>
|
|
64
|
+
<StatusBar style={isDark ? "light" : "dark"}/>
|
|
65
|
+
{content}
|
|
66
|
+
</SafeAreaView>);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=FormView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormView.js","sourceRoot":"","sources":["../../src/components/FormView.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Ionicons } from \"@expo/vector-icons\";\nimport { StatusBar } from \"expo-status-bar\";\nimport React from \"react\";\nimport { KeyboardAvoidingView, Platform, ScrollView, StyleProp, TouchableOpacity, View, ViewStyle } from \"react-native\";\nimport { Edge, SafeAreaView } from \"react-native-safe-area-context\";\nimport { useTheme } from \"../theme\";\nimport { layouts, spacing, useThemedStyles } from \"../utils\";\nimport { Text } from \"./Text\";\n\nexport interface FormViewProps {\n title: string;\n onBack?: () => void;\n backIcon?: keyof typeof Ionicons.glyphMap;\n children: React.ReactNode;\n footer?: React.ReactNode;\n loading?: boolean;\n edges?: Edge[];\n containerStyle?: StyleProp<ViewStyle>;\n contentContainerStyle?: StyleProp<ViewStyle>;\n isModal?: boolean;\n}\n\nexport function FormView({\n title,\n onBack,\n backIcon = \"arrow-back\",\n children,\n footer,\n loading = false,\n edges = [\"top\", \"left\", \"right\", \"bottom\"],\n containerStyle,\n contentContainerStyle,\n isModal = false,\n}: FormViewProps) {\n const { isDark, colors } = useTheme();\n\n const styles = useThemedStyles((colors) => ({\n container: {\n flex: 1,\n backgroundColor: isModal ? \"transparent\" : colors.background,\n },\n header: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n paddingHorizontal: spacing.lg,\n paddingVertical: spacing.md,\n borderBottomWidth: isModal ? 0 : 1,\n borderBottomColor: colors.border,\n },\n headerTitle: {\n flex: 1,\n textAlign: \"left\",\n },\n backButton: {\n marginRight: spacing.md,\n padding: 4,\n },\n formScrollView: {\n paddingHorizontal: spacing.lg,\n paddingVertical: spacing.lg,\n },\n footer: {\n paddingHorizontal: spacing.lg,\n paddingBottom: spacing.xl,\n paddingTop: spacing.md,\n },\n }));\n\n const content = (\n <KeyboardAvoidingView style={layouts.flex1} behavior={Platform.OS === \"ios\" ? \"padding\" : \"height\"}>\n <View style={styles.header}>\n {onBack && (\n <TouchableOpacity onPress={onBack} style={styles.backButton} disabled={loading}>\n <Ionicons name={backIcon} size={24} color={colors.icon} />\n </TouchableOpacity>\n )}\n <Text variant=\"subheading\" weight=\"extrabold\" style={styles.headerTitle}>\n {title}\n </Text>\n {onBack && !isModal && <View style={{ width: 32 }} />}\n </View>\n\n <ScrollView style={layouts.flex1} contentContainerStyle={contentContainerStyle} keyboardShouldPersistTaps=\"handled\" showsVerticalScrollIndicator={false}>\n <View style={[styles.formScrollView, containerStyle]}>{children}</View>\n </ScrollView>\n\n {footer && <View style={styles.footer}>{footer}</View>}\n </KeyboardAvoidingView>\n );\n\n if (isModal) {\n return <View style={styles.container}>{content}</View>;\n }\n\n return (\n <SafeAreaView style={styles.container} edges={edges}>\n <StatusBar style={isDark ? \"light\" : \"dark\"} />\n {content}\n </SafeAreaView>\n );\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Control } from "react-hook-form";
|
|
3
|
+
import { StyleProp, TextInputProps, ViewStyle } from "react-native";
|
|
4
|
+
export interface TextAreaProps extends Omit<TextInputProps, "style"> {
|
|
5
|
+
label?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
helperText?: string;
|
|
8
|
+
minHeight?: number;
|
|
9
|
+
maxHeight?: number;
|
|
10
|
+
style?: StyleProp<ViewStyle>;
|
|
11
|
+
control?: Control<any>;
|
|
12
|
+
name?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function TextArea({ label, error, helperText, minHeight, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }: TextAreaProps): React.JSX.Element;
|
|
15
|
+
//# sourceMappingURL=TextArea.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useController } from "react-hook-form";
|
|
3
|
+
import { TextInput, View } from "react-native";
|
|
4
|
+
import { useTheme } from "../theme";
|
|
5
|
+
import { borderRadius, spacing, useThemedStyles } from "../utils";
|
|
6
|
+
import { Text } from "./Text";
|
|
7
|
+
export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }) {
|
|
8
|
+
const { colors } = useTheme();
|
|
9
|
+
// Use useController if control and name are provided
|
|
10
|
+
const controller = control && name ? useController({ control, name }) : null;
|
|
11
|
+
const inputValue = controller ? controller.field.value : value;
|
|
12
|
+
const inputOnChange = controller ? controller.field.onChange : onChangeText;
|
|
13
|
+
const inputOnBlur = controller ? controller.field.onBlur : onBlur;
|
|
14
|
+
const inputRef = controller ? controller.field.ref : undefined;
|
|
15
|
+
const styles = useThemedStyles((colors) => ({
|
|
16
|
+
container: {
|
|
17
|
+
width: "100%",
|
|
18
|
+
},
|
|
19
|
+
label: {
|
|
20
|
+
marginBottom: spacing.xs,
|
|
21
|
+
color: colors.foregroundSecondary,
|
|
22
|
+
fontSize: 14,
|
|
23
|
+
},
|
|
24
|
+
textArea: {
|
|
25
|
+
backgroundColor: colors.backgroundSecondary,
|
|
26
|
+
borderRadius: borderRadius.lg,
|
|
27
|
+
paddingHorizontal: spacing.md,
|
|
28
|
+
paddingVertical: spacing.md,
|
|
29
|
+
color: colors.foreground,
|
|
30
|
+
fontSize: 16,
|
|
31
|
+
minHeight: minHeight,
|
|
32
|
+
maxHeight: maxHeight,
|
|
33
|
+
textAlignVertical: "top",
|
|
34
|
+
borderWidth: error || controller?.fieldState.error ? 1 : 0,
|
|
35
|
+
borderColor: error || controller?.fieldState.error ? colors.error : "transparent",
|
|
36
|
+
},
|
|
37
|
+
helperText: {
|
|
38
|
+
marginTop: spacing.xs,
|
|
39
|
+
fontSize: 12,
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
return (<View style={[styles.container, style]}>
|
|
43
|
+
{label && (<Text variant="body" weight="medium" style={styles.label}>
|
|
44
|
+
{label}
|
|
45
|
+
</Text>)}
|
|
46
|
+
<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>)}
|
|
53
|
+
</View>);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=TextArea.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -12,4 +12,8 @@ export { DynamicStatusBar } from "./DynamicStatusBar";
|
|
|
12
12
|
export type { DynamicStatusBarProps } from "./DynamicStatusBar";
|
|
13
13
|
export { HeaderView } from "./HeaderView";
|
|
14
14
|
export type { HeaderViewProps } from "./HeaderView";
|
|
15
|
+
export { FormView } from "./FormView";
|
|
16
|
+
export type { FormViewProps } from "./FormView";
|
|
17
|
+
export { TextArea } from "./TextArea";
|
|
18
|
+
export type { TextAreaProps } from "./TextArea";
|
|
15
19
|
//# 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"}
|
|
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"}
|
|
@@ -11,4 +11,6 @@ export { Badge } from "./Badge";
|
|
|
11
11
|
// DynamicStatusBar
|
|
12
12
|
export { DynamicStatusBar } from "./DynamicStatusBar";
|
|
13
13
|
export { HeaderView } from "./HeaderView";
|
|
14
|
+
export { FormView } from "./FormView";
|
|
15
|
+
export { TextArea } from "./TextArea";
|
|
14
16
|
//# 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","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"]}
|
|
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"]}
|
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, HeaderView, Input, PasswordInput, SegmentedControl, Text } from "./components";
|
|
4
|
-
export type { BadgeProps, BadgeStatus, ButtonProps, ButtonSize, ButtonVariant, DynamicStatusBarProps, InputProps, Segment, SegmentedControlProps, TextAlign, TextColor, TextProps, TextVariant, TextWeight, } from "./components";
|
|
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";
|
|
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
|
package/build/index.d.ts.map
CHANGED
|
@@ -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,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,cAAc,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,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"}
|
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, HeaderView, Input, PasswordInput, SegmentedControl, Text } from "./components";
|
|
7
|
+
export { Badge, BaseInput, Button, 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
|
package/build/index.js.map
CHANGED
|
@@ -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,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defaultTheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"defaultTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defaultTheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAiChC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAiC/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAG9B,CAAC"}
|
|
@@ -3,62 +3,64 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const defaultLightColors = {
|
|
5
5
|
// Backgrounds
|
|
6
|
-
background:
|
|
7
|
-
backgroundSecondary:
|
|
6
|
+
background: "#ffffff",
|
|
7
|
+
backgroundSecondary: "#f5f5f5",
|
|
8
8
|
// Foreground (text)
|
|
9
|
-
foreground:
|
|
10
|
-
foregroundSecondary:
|
|
11
|
-
foregroundTertiary:
|
|
9
|
+
foreground: "#1a1a1a",
|
|
10
|
+
foregroundSecondary: "#666666",
|
|
11
|
+
foregroundTertiary: "#999999",
|
|
12
12
|
// Primary brand colors
|
|
13
|
-
primary:
|
|
14
|
-
primaryLight:
|
|
15
|
-
primaryDark:
|
|
13
|
+
primary: "#3b82f6",
|
|
14
|
+
primaryLight: "#60a5fa",
|
|
15
|
+
primaryDark: "#2563eb",
|
|
16
16
|
// Accent colors
|
|
17
|
-
accent:
|
|
18
|
-
accentLight:
|
|
17
|
+
accent: "#8b5cf6",
|
|
18
|
+
accentLight: "#a78bfa",
|
|
19
|
+
icon: "#1a1a1a",
|
|
19
20
|
// Semantic/status colors
|
|
20
|
-
destructive:
|
|
21
|
-
destructiveForeground:
|
|
22
|
-
success:
|
|
23
|
-
warning:
|
|
24
|
-
error:
|
|
25
|
-
info:
|
|
21
|
+
destructive: "#ef4444",
|
|
22
|
+
destructiveForeground: "#ffffff",
|
|
23
|
+
success: "#10b981",
|
|
24
|
+
warning: "#f59e0b",
|
|
25
|
+
error: "#ef4444",
|
|
26
|
+
info: "#3b82f6",
|
|
26
27
|
// UI element colors
|
|
27
|
-
border:
|
|
28
|
-
muted:
|
|
29
|
-
mutedForeground:
|
|
30
|
-
card:
|
|
28
|
+
border: "#e5e5e5",
|
|
29
|
+
muted: "#f5f5f5",
|
|
30
|
+
mutedForeground: "#666666",
|
|
31
|
+
card: "#ffffff",
|
|
31
32
|
};
|
|
32
33
|
/**
|
|
33
34
|
* Default dark theme colors - a neutral, accessible dark color palette.
|
|
34
35
|
*/
|
|
35
36
|
export const defaultDarkColors = {
|
|
36
37
|
// Backgrounds
|
|
37
|
-
background:
|
|
38
|
-
backgroundSecondary:
|
|
38
|
+
background: "#0a0a0a",
|
|
39
|
+
backgroundSecondary: "#171717",
|
|
39
40
|
// Foreground (text)
|
|
40
|
-
foreground:
|
|
41
|
-
foregroundSecondary:
|
|
42
|
-
foregroundTertiary:
|
|
41
|
+
foreground: "#fafafa",
|
|
42
|
+
foregroundSecondary: "#a3a3a3",
|
|
43
|
+
foregroundTertiary: "#737373",
|
|
43
44
|
// Primary brand colors
|
|
44
|
-
primary:
|
|
45
|
-
primaryLight:
|
|
46
|
-
primaryDark:
|
|
45
|
+
primary: "#60a5fa",
|
|
46
|
+
primaryLight: "#93c5fd",
|
|
47
|
+
primaryDark: "#3b82f6",
|
|
47
48
|
// Accent colors
|
|
48
|
-
accent:
|
|
49
|
-
accentLight:
|
|
49
|
+
accent: "#a78bfa",
|
|
50
|
+
accentLight: "#c4b5fd",
|
|
51
|
+
icon: "#fafafa",
|
|
50
52
|
// Semantic/status colors
|
|
51
|
-
destructive:
|
|
52
|
-
destructiveForeground:
|
|
53
|
-
success:
|
|
54
|
-
warning:
|
|
55
|
-
error:
|
|
56
|
-
info:
|
|
53
|
+
destructive: "#f87171",
|
|
54
|
+
destructiveForeground: "#ffffff",
|
|
55
|
+
success: "#34d399",
|
|
56
|
+
warning: "#fbbf24",
|
|
57
|
+
error: "#f87171",
|
|
58
|
+
info: "#60a5fa",
|
|
57
59
|
// UI element colors
|
|
58
|
-
border:
|
|
59
|
-
muted:
|
|
60
|
-
mutedForeground:
|
|
61
|
-
card:
|
|
60
|
+
border: "#262626",
|
|
61
|
+
muted: "#262626",
|
|
62
|
+
mutedForeground: "#a3a3a3",
|
|
63
|
+
card: "#171717",
|
|
62
64
|
};
|
|
63
65
|
/**
|
|
64
66
|
* Default light theme - used as fallback when no ThemeProvider is present.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTheme.js","sourceRoot":"","sources":["../../src/theme/defaultTheme.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgB;
|
|
1
|
+
{"version":3,"file":"defaultTheme.js","sourceRoot":"","sources":["../../src/theme/defaultTheme.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC3C,cAAc;IACd,UAAU,EAAE,SAAS;IACrB,mBAAmB,EAAE,SAAS;IAE9B,oBAAoB;IACpB,UAAU,EAAE,SAAS;IACrB,mBAAmB,EAAE,SAAS;IAC9B,kBAAkB,EAAE,SAAS;IAE7B,uBAAuB;IACvB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IACvB,WAAW,EAAE,SAAS;IAEtB,gBAAgB;IAChB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,SAAS;IAEf,yBAAyB;IACzB,WAAW,EAAE,SAAS;IACtB,qBAAqB,EAAE,SAAS;IAChC,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IAEf,oBAAoB;IACpB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,eAAe,EAAE,SAAS;IAC1B,IAAI,EAAE,SAAS;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgB;IAC1C,cAAc;IACd,UAAU,EAAE,SAAS;IACrB,mBAAmB,EAAE,SAAS;IAE9B,oBAAoB;IACpB,UAAU,EAAE,SAAS;IACrB,mBAAmB,EAAE,SAAS;IAC9B,kBAAkB,EAAE,SAAS;IAE7B,uBAAuB;IACvB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IACvB,WAAW,EAAE,SAAS;IAEtB,gBAAgB;IAChB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,SAAS;IAEf,yBAAyB;IACzB,WAAW,EAAE,SAAS;IACtB,qBAAqB,EAAE,SAAS;IAChC,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IAEf,oBAAoB;IACpB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,eAAe,EAAE,SAAS;IAC1B,IAAI,EAAE,SAAS;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAU;IAC/B,MAAM,EAAE,kBAAkB;IAC1B,MAAM,EAAE,KAAK;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAU;IACnC,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,IAAI;CACf,CAAC","sourcesContent":["import { Theme, ThemeColors } from \"./types\";\n\n/**\n * Default light theme colors - a neutral, accessible color palette.\n */\nexport const defaultLightColors: ThemeColors = {\n // Backgrounds\n background: \"#ffffff\",\n backgroundSecondary: \"#f5f5f5\",\n\n // Foreground (text)\n foreground: \"#1a1a1a\",\n foregroundSecondary: \"#666666\",\n foregroundTertiary: \"#999999\",\n\n // Primary brand colors\n primary: \"#3b82f6\",\n primaryLight: \"#60a5fa\",\n primaryDark: \"#2563eb\",\n\n // Accent colors\n accent: \"#8b5cf6\",\n accentLight: \"#a78bfa\",\n icon: \"#1a1a1a\",\n\n // Semantic/status colors\n destructive: \"#ef4444\",\n destructiveForeground: \"#ffffff\",\n success: \"#10b981\",\n warning: \"#f59e0b\",\n error: \"#ef4444\",\n info: \"#3b82f6\",\n\n // UI element colors\n border: \"#e5e5e5\",\n muted: \"#f5f5f5\",\n mutedForeground: \"#666666\",\n card: \"#ffffff\",\n};\n\n/**\n * Default dark theme colors - a neutral, accessible dark color palette.\n */\nexport const defaultDarkColors: ThemeColors = {\n // Backgrounds\n background: \"#0a0a0a\",\n backgroundSecondary: \"#171717\",\n\n // Foreground (text)\n foreground: \"#fafafa\",\n foregroundSecondary: \"#a3a3a3\",\n foregroundTertiary: \"#737373\",\n\n // Primary brand colors\n primary: \"#60a5fa\",\n primaryLight: \"#93c5fd\",\n primaryDark: \"#3b82f6\",\n\n // Accent colors\n accent: \"#a78bfa\",\n accentLight: \"#c4b5fd\",\n icon: \"#fafafa\",\n\n // Semantic/status colors\n destructive: \"#f87171\",\n destructiveForeground: \"#ffffff\",\n success: \"#34d399\",\n warning: \"#fbbf24\",\n error: \"#f87171\",\n info: \"#60a5fa\",\n\n // UI element colors\n border: \"#262626\",\n muted: \"#262626\",\n mutedForeground: \"#a3a3a3\",\n card: \"#171717\",\n};\n\n/**\n * Default light theme - used as fallback when no ThemeProvider is present.\n */\nexport const defaultTheme: Theme = {\n colors: defaultLightColors,\n isDark: false,\n};\n\n/**\n * Default dark theme variant.\n */\nexport const defaultDarkTheme: Theme = {\n colors: defaultDarkColors,\n isDark: true,\n};\n"]}
|
package/build/theme/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,WAAW;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,WAAW;IAExB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAG5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAG3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IAGpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAEb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,KAAK,CAAC;CAChB"}
|
package/build/theme/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Theme color definitions for @robin-ux/native components.\n * These define all the semantic colors used by components.\n */\nexport interface ThemeColors {\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Theme color definitions for @robin-ux/native components.\n * These define all the semantic colors used by components.\n */\nexport interface ThemeColors {\n // Backgrounds\n background: string;\n backgroundSecondary: string;\n\n // Foreground (text)\n foreground: string;\n foregroundSecondary: string;\n foregroundTertiary: string;\n\n // Primary brand colors\n primary: string;\n primaryLight: string;\n primaryDark: string;\n\n // Accent colors\n accent: string;\n accentLight: string;\n\n // Semantic/status colors\n destructive: string;\n destructiveForeground: string;\n success: string;\n warning: string;\n error: string;\n info: string;\n icon: string;\n // UI element colors\n border: string;\n muted: string;\n mutedForeground: string;\n card: string;\n}\n\n/**\n * Complete theme object containing colors and mode information.\n */\nexport interface Theme {\n colors: ThemeColors;\n isDark: boolean;\n}\n\n/**\n * Theme context value type.\n */\nexport interface ThemeContextValue {\n theme: Theme;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
+
import { StatusBar } from "expo-status-bar";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { KeyboardAvoidingView, Platform, ScrollView, StyleProp, TouchableOpacity, View, ViewStyle } from "react-native";
|
|
5
|
+
import { Edge, SafeAreaView } from "react-native-safe-area-context";
|
|
6
|
+
import { useTheme } from "../theme";
|
|
7
|
+
import { layouts, spacing, useThemedStyles } from "../utils";
|
|
8
|
+
import { Text } from "./Text";
|
|
9
|
+
|
|
10
|
+
export interface FormViewProps {
|
|
11
|
+
title: string;
|
|
12
|
+
onBack?: () => void;
|
|
13
|
+
backIcon?: keyof typeof Ionicons.glyphMap;
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
footer?: React.ReactNode;
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
edges?: Edge[];
|
|
18
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
19
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
20
|
+
isModal?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function FormView({
|
|
24
|
+
title,
|
|
25
|
+
onBack,
|
|
26
|
+
backIcon = "arrow-back",
|
|
27
|
+
children,
|
|
28
|
+
footer,
|
|
29
|
+
loading = false,
|
|
30
|
+
edges = ["top", "left", "right", "bottom"],
|
|
31
|
+
containerStyle,
|
|
32
|
+
contentContainerStyle,
|
|
33
|
+
isModal = false,
|
|
34
|
+
}: FormViewProps) {
|
|
35
|
+
const { isDark, colors } = useTheme();
|
|
36
|
+
|
|
37
|
+
const styles = useThemedStyles((colors) => ({
|
|
38
|
+
container: {
|
|
39
|
+
flex: 1,
|
|
40
|
+
backgroundColor: isModal ? "transparent" : colors.background,
|
|
41
|
+
},
|
|
42
|
+
header: {
|
|
43
|
+
flexDirection: "row",
|
|
44
|
+
alignItems: "center",
|
|
45
|
+
justifyContent: "space-between",
|
|
46
|
+
paddingHorizontal: spacing.lg,
|
|
47
|
+
paddingVertical: spacing.md,
|
|
48
|
+
borderBottomWidth: isModal ? 0 : 1,
|
|
49
|
+
borderBottomColor: colors.border,
|
|
50
|
+
},
|
|
51
|
+
headerTitle: {
|
|
52
|
+
flex: 1,
|
|
53
|
+
textAlign: "left",
|
|
54
|
+
},
|
|
55
|
+
backButton: {
|
|
56
|
+
marginRight: spacing.md,
|
|
57
|
+
padding: 4,
|
|
58
|
+
},
|
|
59
|
+
formScrollView: {
|
|
60
|
+
paddingHorizontal: spacing.lg,
|
|
61
|
+
paddingVertical: spacing.lg,
|
|
62
|
+
},
|
|
63
|
+
footer: {
|
|
64
|
+
paddingHorizontal: spacing.lg,
|
|
65
|
+
paddingBottom: spacing.xl,
|
|
66
|
+
paddingTop: spacing.md,
|
|
67
|
+
},
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
const content = (
|
|
71
|
+
<KeyboardAvoidingView style={layouts.flex1} behavior={Platform.OS === "ios" ? "padding" : "height"}>
|
|
72
|
+
<View style={styles.header}>
|
|
73
|
+
{onBack && (
|
|
74
|
+
<TouchableOpacity onPress={onBack} style={styles.backButton} disabled={loading}>
|
|
75
|
+
<Ionicons name={backIcon} size={24} color={colors.icon} />
|
|
76
|
+
</TouchableOpacity>
|
|
77
|
+
)}
|
|
78
|
+
<Text variant="subheading" weight="extrabold" style={styles.headerTitle}>
|
|
79
|
+
{title}
|
|
80
|
+
</Text>
|
|
81
|
+
{onBack && !isModal && <View style={{ width: 32 }} />}
|
|
82
|
+
</View>
|
|
83
|
+
|
|
84
|
+
<ScrollView style={layouts.flex1} contentContainerStyle={contentContainerStyle} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator={false}>
|
|
85
|
+
<View style={[styles.formScrollView, containerStyle]}>{children}</View>
|
|
86
|
+
</ScrollView>
|
|
87
|
+
|
|
88
|
+
{footer && <View style={styles.footer}>{footer}</View>}
|
|
89
|
+
</KeyboardAvoidingView>
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (isModal) {
|
|
93
|
+
return <View style={styles.container}>{content}</View>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<SafeAreaView style={styles.container} edges={edges}>
|
|
98
|
+
<StatusBar style={isDark ? "light" : "dark"} />
|
|
99
|
+
{content}
|
|
100
|
+
</SafeAreaView>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Control, useController } from "react-hook-form";
|
|
3
|
+
import { StyleProp, TextInput, TextInputProps, View, ViewStyle } from "react-native";
|
|
4
|
+
import { useTheme } from "../theme";
|
|
5
|
+
import { borderRadius, spacing, useThemedStyles } from "../utils";
|
|
6
|
+
import { Text } from "./Text";
|
|
7
|
+
|
|
8
|
+
export interface TextAreaProps extends Omit<TextInputProps, "style"> {
|
|
9
|
+
label?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
helperText?: string;
|
|
12
|
+
minHeight?: number;
|
|
13
|
+
maxHeight?: number;
|
|
14
|
+
style?: StyleProp<ViewStyle>;
|
|
15
|
+
control?: Control<any>;
|
|
16
|
+
name?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function TextArea({ label, error, helperText, minHeight = 120, maxHeight, style, control, name, value, onChangeText, onBlur, ...props }: TextAreaProps) {
|
|
20
|
+
const { colors } = useTheme();
|
|
21
|
+
|
|
22
|
+
// Use useController if control and name are provided
|
|
23
|
+
const controller = control && name ? useController({ control, name }) : null;
|
|
24
|
+
|
|
25
|
+
const inputValue = controller ? controller.field.value : value;
|
|
26
|
+
const inputOnChange = controller ? controller.field.onChange : onChangeText;
|
|
27
|
+
const inputOnBlur = controller ? controller.field.onBlur : onBlur;
|
|
28
|
+
const inputRef = controller ? controller.field.ref : undefined;
|
|
29
|
+
|
|
30
|
+
const styles = useThemedStyles((colors) => ({
|
|
31
|
+
container: {
|
|
32
|
+
width: "100%",
|
|
33
|
+
},
|
|
34
|
+
label: {
|
|
35
|
+
marginBottom: spacing.xs,
|
|
36
|
+
color: colors.foregroundSecondary,
|
|
37
|
+
fontSize: 14,
|
|
38
|
+
},
|
|
39
|
+
textArea: {
|
|
40
|
+
backgroundColor: colors.backgroundSecondary,
|
|
41
|
+
borderRadius: borderRadius.lg,
|
|
42
|
+
paddingHorizontal: spacing.md,
|
|
43
|
+
paddingVertical: spacing.md,
|
|
44
|
+
color: colors.foreground,
|
|
45
|
+
fontSize: 16,
|
|
46
|
+
minHeight: minHeight,
|
|
47
|
+
maxHeight: maxHeight,
|
|
48
|
+
textAlignVertical: "top",
|
|
49
|
+
borderWidth: error || controller?.fieldState.error ? 1 : 0,
|
|
50
|
+
borderColor: error || controller?.fieldState.error ? colors.error : "transparent",
|
|
51
|
+
},
|
|
52
|
+
helperText: {
|
|
53
|
+
marginTop: spacing.xs,
|
|
54
|
+
fontSize: 12,
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<View style={[styles.container, style]}>
|
|
60
|
+
{label && (
|
|
61
|
+
<Text variant="body" weight="medium" style={styles.label}>
|
|
62
|
+
{label}
|
|
63
|
+
</Text>
|
|
64
|
+
)}
|
|
65
|
+
<TextInput
|
|
66
|
+
ref={inputRef as any}
|
|
67
|
+
value={inputValue}
|
|
68
|
+
onChangeText={inputOnChange}
|
|
69
|
+
onBlur={inputOnBlur}
|
|
70
|
+
placeholderTextColor={colors.foregroundSecondary}
|
|
71
|
+
multiline
|
|
72
|
+
{...props}
|
|
73
|
+
style={styles.textArea}
|
|
74
|
+
/>
|
|
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
|
+
)}
|
|
85
|
+
</View>
|
|
86
|
+
);
|
|
87
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -24,3 +24,9 @@ export type { DynamicStatusBarProps } from "./DynamicStatusBar";
|
|
|
24
24
|
|
|
25
25
|
export { HeaderView } from "./HeaderView";
|
|
26
26
|
export type { HeaderViewProps } from "./HeaderView";
|
|
27
|
+
|
|
28
|
+
export { FormView } from "./FormView";
|
|
29
|
+
export type { FormViewProps } from "./FormView";
|
|
30
|
+
|
|
31
|
+
export { TextArea } from "./TextArea";
|
|
32
|
+
export type { TextAreaProps } from "./TextArea";
|
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, HeaderView, Input, PasswordInput, SegmentedControl, Text } from "./components";
|
|
11
|
+
export { Badge, BaseInput, Button, DynamicStatusBar, FormView, HeaderView, Input, PasswordInput, SegmentedControl, Text, TextArea } from "./components";
|
|
12
12
|
|
|
13
13
|
export type {
|
|
14
14
|
BadgeProps,
|
|
@@ -17,10 +17,12 @@ export type {
|
|
|
17
17
|
ButtonSize,
|
|
18
18
|
ButtonVariant,
|
|
19
19
|
DynamicStatusBarProps,
|
|
20
|
+
FormViewProps,
|
|
20
21
|
InputProps,
|
|
21
22
|
Segment,
|
|
22
23
|
SegmentedControlProps,
|
|
23
24
|
TextAlign,
|
|
25
|
+
TextAreaProps,
|
|
24
26
|
TextColor,
|
|
25
27
|
TextProps,
|
|
26
28
|
TextVariant,
|
|
@@ -1,91 +1,93 @@
|
|
|
1
|
-
import { Theme, ThemeColors } from
|
|
1
|
+
import { Theme, ThemeColors } from "./types";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Default light theme colors - a neutral, accessible color palette.
|
|
5
5
|
*/
|
|
6
6
|
export const defaultLightColors: ThemeColors = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
// Backgrounds
|
|
8
|
+
background: "#ffffff",
|
|
9
|
+
backgroundSecondary: "#f5f5f5",
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
// Foreground (text)
|
|
12
|
+
foreground: "#1a1a1a",
|
|
13
|
+
foregroundSecondary: "#666666",
|
|
14
|
+
foregroundTertiary: "#999999",
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
// Primary brand colors
|
|
17
|
+
primary: "#3b82f6",
|
|
18
|
+
primaryLight: "#60a5fa",
|
|
19
|
+
primaryDark: "#2563eb",
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// Accent colors
|
|
22
|
+
accent: "#8b5cf6",
|
|
23
|
+
accentLight: "#a78bfa",
|
|
24
|
+
icon: "#1a1a1a",
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
// Semantic/status colors
|
|
27
|
+
destructive: "#ef4444",
|
|
28
|
+
destructiveForeground: "#ffffff",
|
|
29
|
+
success: "#10b981",
|
|
30
|
+
warning: "#f59e0b",
|
|
31
|
+
error: "#ef4444",
|
|
32
|
+
info: "#3b82f6",
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
// UI element colors
|
|
35
|
+
border: "#e5e5e5",
|
|
36
|
+
muted: "#f5f5f5",
|
|
37
|
+
mutedForeground: "#666666",
|
|
38
|
+
card: "#ffffff",
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Default dark theme colors - a neutral, accessible dark color palette.
|
|
42
43
|
*/
|
|
43
44
|
export const defaultDarkColors: ThemeColors = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// Backgrounds
|
|
46
|
+
background: "#0a0a0a",
|
|
47
|
+
backgroundSecondary: "#171717",
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
// Foreground (text)
|
|
50
|
+
foreground: "#fafafa",
|
|
51
|
+
foregroundSecondary: "#a3a3a3",
|
|
52
|
+
foregroundTertiary: "#737373",
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
// Primary brand colors
|
|
55
|
+
primary: "#60a5fa",
|
|
56
|
+
primaryLight: "#93c5fd",
|
|
57
|
+
primaryDark: "#3b82f6",
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// Accent colors
|
|
60
|
+
accent: "#a78bfa",
|
|
61
|
+
accentLight: "#c4b5fd",
|
|
62
|
+
icon: "#fafafa",
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
// Semantic/status colors
|
|
65
|
+
destructive: "#f87171",
|
|
66
|
+
destructiveForeground: "#ffffff",
|
|
67
|
+
success: "#34d399",
|
|
68
|
+
warning: "#fbbf24",
|
|
69
|
+
error: "#f87171",
|
|
70
|
+
info: "#60a5fa",
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
// UI element colors
|
|
73
|
+
border: "#262626",
|
|
74
|
+
muted: "#262626",
|
|
75
|
+
mutedForeground: "#a3a3a3",
|
|
76
|
+
card: "#171717",
|
|
75
77
|
};
|
|
76
78
|
|
|
77
79
|
/**
|
|
78
80
|
* Default light theme - used as fallback when no ThemeProvider is present.
|
|
79
81
|
*/
|
|
80
82
|
export const defaultTheme: Theme = {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
colors: defaultLightColors,
|
|
84
|
+
isDark: false,
|
|
83
85
|
};
|
|
84
86
|
|
|
85
87
|
/**
|
|
86
88
|
* Default dark theme variant.
|
|
87
89
|
*/
|
|
88
90
|
export const defaultDarkTheme: Theme = {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
colors: defaultDarkColors,
|
|
92
|
+
isDark: true,
|
|
91
93
|
};
|
package/src/theme/types.ts
CHANGED
|
@@ -3,50 +3,50 @@
|
|
|
3
3
|
* These define all the semantic colors used by components.
|
|
4
4
|
*/
|
|
5
5
|
export interface ThemeColors {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// Backgrounds
|
|
7
|
+
background: string;
|
|
8
|
+
backgroundSecondary: string;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
// Foreground (text)
|
|
11
|
+
foreground: string;
|
|
12
|
+
foregroundSecondary: string;
|
|
13
|
+
foregroundTertiary: string;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// Primary brand colors
|
|
16
|
+
primary: string;
|
|
17
|
+
primaryLight: string;
|
|
18
|
+
primaryDark: string;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
// Accent colors
|
|
21
|
+
accent: string;
|
|
22
|
+
accentLight: string;
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
// Semantic/status colors
|
|
25
|
+
destructive: string;
|
|
26
|
+
destructiveForeground: string;
|
|
27
|
+
success: string;
|
|
28
|
+
warning: string;
|
|
29
|
+
error: string;
|
|
30
|
+
info: string;
|
|
31
|
+
icon: string;
|
|
32
|
+
// UI element colors
|
|
33
|
+
border: string;
|
|
34
|
+
muted: string;
|
|
35
|
+
mutedForeground: string;
|
|
36
|
+
card: string;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Complete theme object containing colors and mode information.
|
|
41
41
|
*/
|
|
42
42
|
export interface Theme {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
colors: ThemeColors;
|
|
44
|
+
isDark: boolean;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Theme context value type.
|
|
49
49
|
*/
|
|
50
50
|
export interface ThemeContextValue {
|
|
51
|
-
|
|
51
|
+
theme: Theme;
|
|
52
52
|
}
|