ripal-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ import React, { useState } from "react";
2
+ import { Pressable, ScrollView, StyleSheet, View } from "react-native";
3
+ import config from "../config";
4
+ import Text from "./Text";
5
+ import Inline from "./Inline";
6
+ import Ionicons from "@expo/vector-icons/Ionicons";
7
+
8
+ const Dropdown = ({options, value, setValue, onChange, color = config.colors.primary, label = null, placeholder = 'Choose', objectKey = null, withSearch = false}) => {
9
+ const [isExpanded, setExpanded] = useState(false);
10
+ const isObject = objectKey === null ? false : true;
11
+
12
+ return (
13
+ <View style={{gap: 5}}>
14
+ {
15
+ label !== null &&
16
+ <Text size={12} weight="400Regular">{label}</Text>
17
+ }
18
+ <View style={styles.area}>
19
+ <Inline onPress={() => {
20
+ setExpanded(!isExpanded)
21
+ }}>
22
+ <Text style={{flexGrow: 1}}>{value || placeholder}</Text>
23
+ <Ionicons name={isExpanded ? 'chevron-up-outline' : 'chevron-down-outline'} />
24
+ </Inline>
25
+
26
+ {
27
+ isExpanded &&
28
+ <ScrollView style={{
29
+ maxHeight: 200,
30
+ }}>
31
+ { options.map((opt, o) => {
32
+ let isActive = isObject ? opt[objectKey] === value : opt === value;
33
+ return (
34
+ <Inline key={o} style={styles.item} onPress={() => {
35
+ if (onChange) {
36
+ onChange(opt);
37
+ } else {
38
+ setValue(isObject ? opt[objectKey] : opt);
39
+ }
40
+ setExpanded(false);
41
+ }}>
42
+ <Text weight={isActive ? '600SemiBold' : '400Regular'} color={isActive ? color : config.colors.slate[500]}>{isObject ? opt[objectKey] : opt}</Text>
43
+ </Inline>
44
+ )
45
+ })}
46
+ </ScrollView>
47
+ }
48
+ </View>
49
+ </View>
50
+ )
51
+ }
52
+
53
+ const styles = StyleSheet.create({
54
+ area: {
55
+ padding: 15,
56
+ borderWidth: 1,
57
+ borderColor: config.colors.slate[200],
58
+ borderRadius: 12,
59
+ gap: 15,
60
+ },
61
+ item: {
62
+ height: 40,
63
+ }
64
+ })
65
+
66
+ export default Dropdown
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import { Pressable, StyleSheet, View } from "react-native";
3
+
4
+ const Inline = ({children, alignItems = "center", justifyContent = "flex-start", gap = 20, style, onPress, onLayout}) => {
5
+ return (
6
+ <Pressable style={{
7
+ flexDirection: 'row',
8
+ alignItems, justifyContent, gap,
9
+ ...style
10
+ }} onPress={onPress} onLayout={onLayout}>
11
+ {children}
12
+ </Pressable>
13
+ )
14
+ }
15
+
16
+ export default Inline
@@ -0,0 +1,48 @@
1
+ import React, { useRef, useState } from "react";
2
+ import { View, TextInput, StyleSheet } from "react-native";
3
+ import Text from "./Text";
4
+ import Inline from "./Inline";
5
+ import config from "../config";
6
+
7
+ const Input = ({label = null, left = null, right = null, height = 50, placeholder = null, mode = "text", secureTextEntry = false, onChangeText}) => {
8
+ const [isFocused, setFocused] = useState(false);
9
+
10
+ return (
11
+ <View style={{gap: 5}}>
12
+ {
13
+ label !== null &&
14
+ <Text size={12} weight="400Regular" color={isFocused ? config.colors.primary : config.colors.slate[500]}>{label}</Text>
15
+ }
16
+ <Inline style={{
17
+ ...styles.input,
18
+ borderColor: isFocused ? config.colors.primary : config.colors.slate[100],
19
+ }}>
20
+ {
21
+ left !== null && left
22
+ }
23
+ <TextInput placeholder={placeholder} style={{
24
+ height,
25
+ flexGrow: 1,
26
+ }} onFocus={() => setFocused(true)} onChangeText={onChangeText} onBlur={() => setFocused(false)} inputMode={mode} secureTextEntry={secureTextEntry} />
27
+ {
28
+ right !== null && right
29
+ }
30
+ </Inline>
31
+ </View>
32
+ )
33
+ }
34
+
35
+ const styles = StyleSheet.create({
36
+ inline: {
37
+ flexDirection: 'row',
38
+ alignItems: 'center',
39
+ },
40
+ input: {
41
+ flexGrow: 1,
42
+ borderWidth: 1,
43
+ borderRadius: 12,
44
+ paddingHorizontal: 20,
45
+ }
46
+ })
47
+
48
+ export default Input
@@ -0,0 +1,29 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import { View, StyleSheet } from "react-native";
3
+ import config from "../config";
4
+
5
+ const ProgressBar = ({value, from = 100, size = 5, style, percentage = null}) => {
6
+ const [percent, setPercent] = useState(null);
7
+ useEffect(() => {
8
+ if (percent == null) {
9
+ setPercent(value / from * 100);
10
+ }
11
+ })
12
+
13
+ return (
14
+ <View style={{...barStyle.area, ...style, height: size}}>
15
+ <View style={{...barStyle.value, width: `${percent}%`, height: size}}></View>
16
+ </View>
17
+ )
18
+ }
19
+
20
+ const barStyle = StyleSheet.create({
21
+ area: {
22
+ backgroundColor: config.colors.slate[200],
23
+ height: 5,
24
+ flexGrow: 1
25
+ },
26
+ value: { backgroundColor: config.colors.primary }
27
+ })
28
+
29
+ export default ProgressBar;
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import { StyleSheet, View } from "react-native";
3
+ import Inline from "./Inline";
4
+ import config from "../config";
5
+ import Text from "./Text";
6
+
7
+ const Separator = ({children, width = "100%", space = 20, height = 1, color = config.colors.slate[200], textProps}) => {
8
+ return (
9
+ <Inline justifyContent="center">
10
+ <View style={{
11
+ backgroundColor: color,
12
+ width, height,
13
+ marginVertical: space,
14
+ }}></View>
15
+ {
16
+ children &&
17
+ <Text size={12} style={{
18
+ position: 'absolute',
19
+ backgroundColor: '#fff',
20
+ padding: 10,
21
+ paddingHorizontal: 20,
22
+ }} {...textProps}>{children}</Text>
23
+ }
24
+ </Inline>
25
+ )
26
+ }
27
+
28
+ const styles = StyleSheet.create({
29
+ //
30
+ })
31
+
32
+ export default Separator
@@ -0,0 +1,50 @@
1
+ import React, { useEffect, useRef } from "react";
2
+ import { Animated, StyleSheet, View } from "react-native";
3
+ import config from "../config";
4
+
5
+ const Skeleton = ({color = config.colors.slate[200], rounded = 8, width = `${Math.floor(Math.random() * (99 - 11 + 1)) + 11}%`, height = 20, aspectRatio = null}) => {
6
+ const aspectRatioStyles = { aspectRatio: aspectRatio};
7
+ const heightStyles = { height: height};
8
+ const opacity = useRef(new Animated.Value(1)).current;
9
+ const defaultStyles = {
10
+ backgroundColor: color,
11
+ width,
12
+ borderRadius: rounded,
13
+ opacity,
14
+ };
15
+
16
+ useEffect(() => {
17
+ const bounce = () => {
18
+ opacity.setValue(1);
19
+ Animated.timing(opacity, {
20
+ toValue: 0.4,
21
+ duration: 1000,
22
+ useNativeDriver: true,
23
+ }).start(() => {
24
+ Animated.timing(opacity, {
25
+ toValue: 0.8,
26
+ duration: 1000,
27
+ useNativeDriver: true,
28
+ }).start(bounce);
29
+ });
30
+ };
31
+
32
+ bounce();
33
+ }, [opacity]);
34
+
35
+ return (
36
+ <Animated.View style={aspectRatio === null ? [
37
+ defaultStyles,
38
+ heightStyles
39
+ ] : [
40
+ defaultStyles,
41
+ aspectRatioStyles
42
+ ]}></Animated.View>
43
+ )
44
+ }
45
+
46
+ const styles = StyleSheet.create({
47
+ //
48
+ })
49
+
50
+ export default Skeleton
@@ -0,0 +1,49 @@
1
+ import React, { useState } from "react";
2
+ import { Pressable, StyleSheet, View } from "react-native";
3
+ import config from "../config";
4
+ import Inline from "./Inline";
5
+
6
+ const Switch = ({active = false, size = 24, spacer = 5, onChange = null}) => {
7
+ const [isActive, setActive] = useState(active);
8
+
9
+ return (
10
+ <Pressable onPress={() => {
11
+ setActive(!isActive);
12
+ if (onChange !== null) {
13
+ onChange();
14
+ }
15
+ console.log('hehe');
16
+ }}>
17
+ <Inline style={{
18
+ backgroundColor: isActive ? config.colors.green[500] : config.colors.slate[200],
19
+ padding: spacer,
20
+ borderRadius: 999,
21
+ width: size * 2 + spacer + 5,
22
+ }}>
23
+ {
24
+ isActive &&
25
+ <View style={{flexGrow: 1}}></View>
26
+ }
27
+ <View style={{
28
+ height: size,
29
+ ...styles.circle,
30
+ }}>
31
+ {/* */}
32
+ </View>
33
+ </Inline>
34
+ </Pressable>
35
+ )
36
+ }
37
+
38
+ const styles = StyleSheet.create({
39
+ area: {
40
+ backgroundColor: config.colors.slate[100],
41
+ },
42
+ circle: {
43
+ backgroundColor: '#fff',
44
+ aspectRatio: 1,
45
+ borderRadius: 9999,
46
+ }
47
+ })
48
+
49
+ export default Switch
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import { Text as RNText } from "react-native";
3
+ import { useFonts, Poppins_300Light, Poppins_400Regular, Poppins_500Medium, Poppins_600SemiBold, Poppins_700Bold, Poppins_900Black } from "@expo-google-fonts/poppins";
4
+ import config from "../config";
5
+
6
+ const Text = ({children, weight = "400Regular", size, color = config.colors.slate[500], align = "left", limit = 0, spacing = 0, lineHeight = null, style}) => {
7
+ const fontName = "Poppins";
8
+ let [fontsLoaded] = useFonts({
9
+ Poppins_300Light, Poppins_400Regular, Poppins_500Medium, Poppins_600SemiBold, Poppins_700Bold, Poppins_900Black
10
+ });
11
+
12
+ if (config.appLangs.default !== null) {
13
+ // children = config.appLangs[config.appLangs.default][children];
14
+ let ogChildren = children;
15
+ if (typeof children === "string") {
16
+ children = children.split('.').reduce((acc, key) => {
17
+ return acc && acc[key] !== undefined ? acc[key] : ogChildren;
18
+ }, config.appLangs[config.appLangs.default]);
19
+ }
20
+ }
21
+
22
+ if (!fontsLoaded) {
23
+ <RNText>{children}</RNText>
24
+ }
25
+
26
+ if (limit > 0 && children.length > limit) {
27
+ children = children.substr(0, limit) + '...';
28
+ }
29
+
30
+ return <RNText style={{
31
+ fontSize: size,
32
+ color: color,
33
+ letterSpacing: spacing,
34
+ lineHeight: lineHeight,
35
+ ...style,
36
+ fontFamily: `${fontName}_${weight}`,
37
+ textAlign: align
38
+ }}>{children}</RNText>
39
+
40
+ }
41
+
42
+ export default Text;
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import { Pressable, StyleSheet, View } from "react-native";
3
+
4
+ import config from "../config";
5
+ import Text from "./Text";
6
+ import Inline from "./Inline";
7
+
8
+ const Toggle = ({options, value, setValue}) => {
9
+ return (
10
+ <Inline style={styles.area}>
11
+ { options.map((opt, o) => {
12
+ let isActive = value === opt;
13
+ return (
14
+ <Pressable key={o} style={[styles.item, isActive ? styles.item_active : null]} onPress={() => setValue(opt)}>
15
+ <Text
16
+ color={isActive ? config.colors.primary : config.colors.slate[500]}
17
+ weight={isActive ? '600SemiBold' : '400Regular'}
18
+ >{opt}</Text>
19
+ </Pressable>
20
+ )
21
+ })}
22
+ </Inline>
23
+ )
24
+ }
25
+
26
+ const styles = StyleSheet.create({
27
+ area: {
28
+ padding: 10,
29
+ backgroundColor: config.colors.slate[100],
30
+ borderRadius: 12,
31
+ },
32
+ item: {
33
+ flexGrow: 1,
34
+ flexDirection: 'row',
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ paddingVertical: 10,
38
+ borderRadius: 12
39
+ },
40
+ item_active: {
41
+ backgroundColor: '#fff',
42
+ shadowColor: config.colors.slate[300],
43
+ shadowOpacity: 0.4,
44
+ shadowRadius: 12,
45
+ }
46
+ })
47
+
48
+ export default Toggle
@@ -0,0 +1,11 @@
1
+ export { default as Button } from './Button';
2
+ export { default as Dialog } from './Dialog';
3
+ export { default as Dropdown } from './Dropdown';
4
+ export { default as Inline } from './Inline';
5
+ export { default as Input } from './Input';
6
+ export { default as ProgressBar } from './ProgressBar';
7
+ export { default as Separator } from './Separator';
8
+ export { default as Skeleton } from './Skeleton';
9
+ export { default as Switch } from './Switch';
10
+ export { default as Text } from './Text';
11
+ export { default as Toggle } from './Toggle';
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './elements';
2
+ export * from './components';
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "ripal-ui",
3
+ "version": "1.0.0",
4
+ "description": "A collection of React elements and components",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "build": "babel elements components --out-dir dist"
8
+ },
9
+ "dependencies": {
10
+ "react": "^18.0.0",
11
+ "react-native": "^0.70.0"
12
+ },
13
+ "devDependencies": {
14
+ "@babel/cli": "^7.25.6",
15
+ "@babel/core": "^7.25.2",
16
+ "@babel/preset-env": "^7.25.4",
17
+ "@babel/preset-react": "^7.24.7"
18
+ }
19
+ }