0.0.5 • Published 5 months ago

@kietpt2003/react-native-core-ui v0.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

React Native Core UI

Accelerate your React Native development with a rich set of customizable UI components built for consistency and performance. Designed to streamline layout and styling, these components are ideal for building modern, responsive, and scalable interfaces across all screens. Seamlessly adaptable and theme-ready for effortless branding.

!TIP

  • My info: https://github.com/kietpt2003
  • Due to some TypeScript issues that lead to unable to suggest code correctly.
  • But we have try our best, so now if you using our sub path (Example: '/utils', '/themes'), you must initialize the import first, for the auto suggestion.

Table of Contents

Installation

Please install required packages:

  • @react-native-camera-roll/camera-roll: ">=7.10.0" => For access devices media support GalleryBottomSheet & useGalleryAssets. Note: This package should be upper then 7.10.0. Due to error in v7.7.0 and lowwer version this package won't work correct in GalleryBottomSheet & useGalleryAssets
  • react-native-device-info: ">=8.1.3", => Use for knowing device is table or not
  • react-native-gesture-handler: ">=2.9.0", => Support handling gesture for GalleryBottomSheet
  • react-native-reanimated: ">=2.8.0", => For handling package animation
  • react-native-svg: ">=12.1.1", => For custom svg
  • react-native-vector-icons: ">=8.1.0", => Please config correct installation guidline for not handling icon error

Custom components

Text

Text component for displaying text with custom styles and loading state. This component also have its own view and can easily be customized.

Props

PropTypeDefaultDescription
styleStyleProp<TextStyle>NoneStyle of the Text component, just like Text Style Props
colorColorValue"black"Color of the text
boldbooleanfalseChoose to bold the text
childrenReact.ReactNodeNoneProvide the text string or another Text component
loadbooleanfalseWaiting before show Text
styleViewStyleProp<ViewStyle>NoneFor custom a View outside Text component

GalleryBottomSheet

A bottom sheet component for displaying a gallery of images and videos. It allows users to select multiple assets and provides a filter for albums.

Permissions

Android

Add this permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
iOS

Add this perission to your Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>App request permission for access your gallery</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App request permission for create assets in your gallery</string>

Props

PropTypeDefaultDescription
isOpenbooleanfalseDefine to open gallery or not.
openHeightnumberScreenHeight / 2Define the position to open gallery. Note: y coordinate of the top of the bottom sheet from the top of the screen
closeHeightnumberScreenHeightDefine the position when closed gallery. Note: y coordinate of the top of the bottom sheet from the top of the screen
maxHeightnumber0Define the maximum y coordinate that gallery should snapped at after finger release. Note: y coordinate of the top of the bottom sheet from the top of the screen
headerBarColorColorValue"#FFFFFF"Define the background color of the header bar. Note: Full control over the look at each position. Whether it's beautiful or ugly is up to you.
barIconColorColorValue"#000000"Define the header bar icon color. Note: Full control over the look at each position. Whether it's beautiful or ugly is up to you.
headerTitleStylePick<TextStyle, "color" \| "fontFamily" \| "fontWeight">{ color: '#000000' }Define styling for the header title. Only supports: color, fontFamily, fontWeight.
headerTitlestring'Tất cả ảnh'Define the header title. Will be overridden by folder name when one is selected. Will be truncated if too long.
headerTitleIconColorColorValue"#000000"Define the header title icon color.
backgroundColorColorValue"#FFFFFF"Define the background color of the gallery bottom sheet.
emptyGalleryMsgstring'Không có hình ảnh để hiển thị'Message shown when there are no media items available. Please provide meaningful content.
emptyGalleryMsgStylePick<TextStyle, "color" \| "fontFamily" \| "fontWeight">{ color: '#000000' }Define styling for the empty message. Only supports: color, fontFamily, fontWeight. See example
videoIconStyle{ circleStyle?: CircleStyleProps; polygonStyle?: CircleStyleProps }See exampleDefine styling for the video icon shown for video items. Full control over circle and polygon styles.
albumItemStyleAlbumFilterStyleProps{ titleColor: '#000000', countColor: '#A0A0A0' }Define style for album filter items. Full control over title and count colors. See example
assetType'All' | 'Photos' | 'Videos''All'Asset types to display. Can be dynamically changed with setState.
maxSelectablenumber5Max number of items selectable. Min: 0, Max: 10. Large values may cause performance issues.
onSelectedAssetsChange(assets: PhotoIdentifier[]) => voidundefinedDefine function for handling selected assets data. This function will be called when the user select an asset.
headerTitleStyle

Only support: color, fontFamily, fontWeight.

  import { GalleryBottomSheet, Text } from '@kietpt2003/react-native-core-ui';

  <GalleryBottomSheet
    isOpen={isOpen}
    ...
    headerTitleStyle={{
      color: '#000000',
      fontFamily: 'Arial',
      fontWeight: 400,      // Correct ✅
      fontSize: 20          // Wrong => Unsupport ❌
    }}
    ...
  />
videoIconStyle

Only support: fill, stroke, strokeWidth. For the strokeWidth, we accept value start from scale(5) to scale(8)

  import { GalleryBottomSheet, Text } from '@kietpt2003/react-native-core-ui';

  <GalleryBottomSheet
    isOpen={isOpen}
    ...
    videoIconStyle={{
      circleStyle: {
        fill: 'rgba(0, 0, 0, 0.5)',
        stroke: 'black',
        strokeWidth: 7
      },
      polygonStyle: {
        fill: 'rgba(0, 0, 0, 0.5)',
        stroke: 'black',
        strokeWidth: 7
      },
    }}
    ...
  />
albumItemStyle

Only support: titleColor, countColor.

  import { GalleryBottomSheet, Text } from '@kietpt2003/react-native-core-ui';

  <GalleryBottomSheet
    isOpen={isOpen}
    ...
    albumItemStyle={{
      titleColor: '#000000',
      countColor: '#A0A0A0'
    }}
    ...
  />

ScrollPercentage

ScrollPercentage is a component that displays a loading indicator with a percentage value. It can be customized with different shapes (circle or square), colors, and gradients.

Props

PropTypeDefaultDescription
hidebooleanfalseDefine to show or hide the loading figure.
percentnumber0Please provide the percent for calculate the loading percentage.
sizenumber60Provide the size for the loading figure.
borderRadiusnumber45The border radius of the square figure. Just apply with square fiugre only.
backgroundColorColorValuenoneThe inline color of the loading figure before the loading start.
strokeEmptyColorColorValue#FFFFFFThe stroke color while the percent is 0.
fillColorValue#FFFFFFThe fill of the loading figure. Can be a single color or an array of colors.
gradientDirectionGradientDirectionhorizontalThe gradient direction of the fill. This property is only affected when the fill is an array of colors. The gradient direction can be 'horizontal', 'vertical', or 'diagonal'.
checkColorColorValue#000000The color of the check mark.

Example

  import { ScrollPercentage } from '@estuary/rn-core-ui';
    const MyComponent = () => {
    const [scrollPercent, setScrollPercent] = React.useState(0);
    const [isOpen, setIsOpen] = React.useState(false);
    return (
      <ScrollPercentage
        hide={isOpen}
        size={60}
        percent={scrollPercent}
        backgroundColor="red"
        strokeEmptyColor="blue"
        fill="green" // Can be a single color or an array of colors
        gradientDirection="horizontal" // Choose the gradient direction of the fill
        checkColor="yellow" // Color of the check mark
        animateSpeed={200} // Animation speed in milliseconds when showing/hiding the loading figure
        figure="circle" // Choose between 'circle' or 'square'
        startPosition="top-left" // Only for square figure
        borderRadius={45} // Only for square figure
      />
    );
  }

Custom hooks

useGalleryAssets(defaultAssetType?: AssetType)

You can use this hook for accessing device's assets or requesting related permission.

Permissions

Android

Add this permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
iOS

Add this perission to your Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>App request permission for access your gallery</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App request permission for create assets in your gallery</string>

Props

PropTypeDefaultDescription
defaultAssetTypeAssetType'All'Initiallize the default asset type.
albumsAlbum[][]Provide list of albums on current device.
assetsRecord<string, PhotoIdentifier[]>{}Provide list of assets on current device grouped by album.
fullAssetsPhotoIdentifier[][]Provide list of assets on current device.
loadingbooleanfalseProvide loading assets state.
errorstringnullProvide string error if loading cause any error.
totalAssetsnumber0Provide the total assets that has been accessed.
fullAssetsPaginationPaginationundefinedProvide the object related for pagination on fullAssets.
loadFullAssetsPromise function | Provide function for fecth assets which not grouped by album. Return true if has next page. See example
loadAssetsPromise function | Provide function for fecth assets which grouped by album. Return true if has next page. See example
paginationPaginationundefinedProvide the object related for pagination on assets.
requestPermissionPromise function | Provide function for request permission. Return true if user provided permission. See example
checkPermissionPromise function | Provide function returning if user has provided permission. See example
hasPermissionbooleanfalseProvide a state that keep track user permisison.
changeAssetTypefunction | Provide function changing with asset type that you want to fecth. Please notice that, you should provide video permision if want to access videos. Default type 'All'. See example

Usage

  import { View, Text } from 'react-native'
  import React from 'react'
  import { useGalleryAssets } from '@kietpt2003/react-native-core-ui';

  const MyComponent = () => {
    const [selectedAlbum, setSelectedAlbum] = React.useState<Album | null>(null);
    const {
        albums,
        fullAssets,
        fullAssetsPagination,
        loadFullAssets,
        totalAssets,
        assets,
        loadAssets,
        pagination,
        requestPermission,
        hasPermission,
        changeAssetType,
    } = useGalleryAssets('All');

    const getSelectedInfo = (item: any) => {
      // Do your own selection logic
    }

    const toggleAsset = (item: any) => {
      // Do your own selection logic
    }

    return (
      <View>
        {(albums.length === 0 || fullAssets.length === 0 || totalAssets == 0) ? (
          <View>
            <Text style={[
              styles.noImage,
              safeEmptyGalleryMsgStyle
            ]}>No assets</Text>
          </View>
        ) : (
        <FlatList
          data={selectedAlbum == null ? fullAssets : assets[selectedAlbum.id]}
          keyExtractor={(item) => item.node.image.uri}
          renderItem={({ item }) => {
            const info = getSelectedInfo(item);
            return (
              <TouchableOpacity
                style={styles.image}
                onPress={() => toggleAsset(item)}
                activeOpacity={0.7}
              >
                <Image
                  source={{ uri: item.node.image.uri }}
                  style={styles.image}
                />
                  {
                    item.node.type === "video/mp4" &&
                    <PlayCircle size={videoIconSize} />
                  }
                  {info.isSelected && (
                    <SelectItem value={info.index + 1} />
                  )}
              </TouchableOpacity>
            )
          }}
          ...
          onEndReached={() => {
            //Load more assets
            if (selectedAlbum == null) {
              loadFullAssets(15, fullAssetsPagination?.endCursor, assetTypeState);
            } else {
              loadAssets(selectedAlbum, 15, pagination[selectedAlbum.id].endCursor, assetTypeState);
            }
          }}
        />
        )}
      </View>
    )
  }

  export default MyComponent

Colors

We provide a variety of palete colors and some shadows!

Usage

  import  { colors } from '@kietpt2003/react-native-core-ui/themes';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: colors.black,
    },
  });

Fontsize

We provide variety of fontSize that aldready scaled by our scaleFont API

Usage

  import  { fontSize } from '@kietpt2003/react-native-core-ui/themes';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    text: {
      fontSize: fontSize._16,
    },
  });

Scaling Function

  import { scale, verticalScale, moderateScale } from '@kietpt2003/react-native-core-ui/utils';
  import  { colors, fontSize } from '@kietpt2003/react-native-core-ui/themes'

  const Component = props =>
    <View style={{
      width: scale(30),
      height: verticalScale(50),
      padding: moderateScale(5)
    }}>
      <Text style={{
        fontSize: fontSize._16,
        color: colors.black
      }}>Component</Text>
    </View>;

scale(size: number)

Will return a linear scaled result of the provided size, based on your device's screen width.

Usage

  import  { scale } from '@kietpt2003/react-native-core-ui/utils';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    container: {
      padding: scale(5),
    },
  });

scaleH(size: number)

Will return a linear scaled result of the provided size, based on your device's screen height.

Usage

  import  { scaleH } from '@kietpt2003/react-native-core-ui/utils';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    container: {
      position: 'absolute',
      top: scaleH(5),
    },
  });

moderateScale(size: number, factor?: number)

Sometimes you don't want to scale everything in a linear manner, that's where moderateScale comes in.
The cool thing about it is that you can control the resize factor (default is 0.5).
If normal scale will increase your size by +2X, moderateScale will only increase it by +X, for example:
➡️   scale(10) = 20
➡️   moderateScale(10) = 15
➡️   moderateScale(10, 0.1) = 11

Usage

  import  { moderateScale } from '@kietpt2003/react-native-core-ui/utils';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    container: {
      padding: moderateScale(5),
    },
  });

moderateHeightScale(size: number, factor?: number)

Same as moderateScale, but using scaleH instead of scale.

Usage

  import  { moderateHeightScale } from '@kietpt2003/react-native-core-ui/utils';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    container: {
      padding: moderateHeightScale(5),
    },
  });

scaleFont(size: number)

Will return a linear scaled result of the provided size, based on PixelRatio & scaleAvg. You can use fontSize from /theme instead of using scalefont().

Usage

  import  { scaleFont } from '@kietpt2003/react-native-core-ui/utils';
  import { StyleSheet } from 'react-native';

  const styles = StyleSheet.create({
    text: {
      fontSize: scaleFont(16), // fontSize._16
    },
  });

IPHONE_12_WIDTH

Just a constants that specify iPhone 12 width.

  import { IPHONE_12_WIDTH } from '@kietpt2003/react-native-core-ui/utils';
  console.log(IPHONE_12_WIDTH); // 375

IPHONE_12_HEIGTH

Just a constants that specify iPhone 12 height.

  import { IPHONE_12_HEIGTH } from '@kietpt2003/react-native-core-ui/utils';
  console.log(IPHONE_12_HEIGTH); // 812

Resolution Function

getPaddingTop

Get the top padding based on the device type

  • 26 OPPO
  • 28 NOKIA

Usage

  import { getPaddingTop } from '@kietpt2003/react-native-core-ui/utils';
  const paddingTop = getPaddingTop();
  console.log("paddingTop:", paddingTop);

getPaddingBottom

Get the bottom padding based on the device type

Usage

  import { getPaddingBottom } from '@kietpt2003/react-native-core-ui/utils';
  const paddingBottom = getPaddingBottom();
  console.log("paddingBottom:", paddingBottom);

isTablet

Check if the device is a tablet

Usage

  import { isTablet } from '@kietpt2003/react-native-core-ui/utils';
  console.log("isTablet", isTablet); // true/false

StylePlatform

Use this function to get the styles based on the device type

@param {Object} styles - StyleProp @param {ViewStyle} styles.tablet - Styles for tablet @param {ViewStyle} styles.phone - Styles for phone

Props

PropTypeDefaultDescription
stylesStyleProp<any>undefinedInitiallize the styles for table and phone. Its contains 2 fields: tablet & phone. See example

Usage

  <View style={StylePlatform({
    tablet: styles.containerTablet,
    phone: styles.containerPhone
  })}>
    <Text style={StylePlatform({
      tablet: styles.textTablet,
      phone: styles.textPhone
    })}>
      Hello, Platform!
    </Text>
  </View>

statusBarHeight

statusBarHeight of the device

Usage

  import { statusBarHeight } from '@kietpt2003/react-native-core-ui/utils';
  console.log("statusBarHeight", statusBarHeight);

Converter and format

convertString

This function converts input into a string.

  • If the input is null or undefined, it returns an empty string.
  • If the input is an object, it returns a stringified version of the object.
  • Otherwise, it returns the string representation of the input.

Usage

  import { convertString } from '@kietpt2003/react-native-core-ui/utils';
  const str = convertString(2003); // "2003"

convertNumber

This function converts input into a number.

  • If the input is null or undefined, it returns 0.
  • If the input is not a number, it returns 0.
  • Otherwise, it returns the parsed float value of the input.

Usage

  import { convertNumber } from '@kietpt2003/react-native-core-ui/utils';
  const num = convertNumber("2003"); // 2003

convertSeconds

This function convert seconds to a string in the format "mm:ss".

  • If the input is less than 0, it returns "00:00".
  • If the input is greater than 3599, it returns "00:00".

Usage

  import { convertSeconds } from '@kietpt2003/react-native-core-ui/utils';
  const time = convertSeconds(123); // "02:03"

formatHour

Function to format seconds into a string in the format "hh:mm:ss".

  • If the input is less than 0, it returns "00:00:00".
  • If the input is greater than 86399, it returns "00:00:00".

Usage

  import { formatHour } from '@kietpt2003/react-native-core-ui/utils';
  const time = formatHour(3661); // "01:01:01"

fixedDistance

Function to format a distance value.

  • If the input is an integer, it returns the integer value.
  • If the input is a float, it returns the value formatted to a custom toFixed value decimal places.
  • If the input is null or undefined, it returns 0.

Note: The toFixed value should be between 1 and 5, otherwise it defaults to 2.

Usage

  import { fixedDistance } from '@kietpt2003/react-native-core-ui/utils';
  const distance = fixedDistance(123.456); // "123.46"
  const distance2 = fixedDistance(123.4567, 3); // "123.457"

formatMoney

Function to format money values.

Props

PropTypeDefaultDescription
numnumber0Define the value need to be format.
maximumFractionDigitsnumber0Define the maximum fraction digits. See example
langstringen-USDefine the language. This should be a BCP 47 language tag (e.g., 'en-US', 'vi-VN'). View detail

lang prop

This is a string that contains a language code and an optional country code, separated by a hyphen.

Structure: "[languageCode]-[countryCode]" Example: 'en-IN' => en: Language English, IN: Country India Reference:

Usage

  import { formatMoney } from '@kietpt2003/react-native-core-ui/utils';
  const money = formatMoney(1234567.89); // "1,234,568"
  const money2 = formatMoney(1234567.89, 2); // "1,234,567.89"
  const money3 = formatMoney(1234567.89, 2, 'vi-VN'); // "1.234.567,89"

Debounce

  • Creates a debounced function that delays invoking the provided function until after a specified delay in milliseconds has elapsed since the last time the debounced function was invoked.
  • The debounced function comes with cancel and flush methods to cancel the debounced invocation and to immediately invoke the function, respectively.

Usage

  import { debounce } from '@kietpt2003/react-native-core-ui/utils';
  const onChangeText = debounce(() => {
    console.log('Function executed!');
  }, 1000);

  //Flush case
  const debouncedLog = debounce(logMessage, 2000);
  debouncedLog("Waiting 2s...");
  setTimeout(() => {
    debouncedLog.flush(); // Immediately execute the function
  }, 1000);

  //Cancel case
  debouncedLog("Canceled");
  setTimeout(() => {
    debouncedLog.cancel(); // Don't execute the function
  }, 1000);

Others

cleanTagHTML

Provide a function to clean HTML tags and   from a string.

Usage

  import { cleanHTML } from '@kietpt2003/react-native-core-ui/utils';
  const raw = `
    <div>Hello&nbsp;&nbsp;&nbsp;World</div>
    <p>This is&nbsp;a <strong>test</strong></p>
  `;
  console.log(cleanHTML(raw));
  // Output:
  // Hello
  // World
  // This is a test

💖 Support Kiet!

Thank you so much already for checking my repos! If you want to go a step further and support my open source work, buy me a coffee: