react-native-focal

Humble kit to professionally handle the focus/blur experience for controlled components.

Usage no npm install needed!

<script type="module">
  import reactNativeFocal from 'https://cdn.skypack.dev/react-native-focal';
</script>

README

react-native-focal 👓

NPM downloads

Roses are red.
Violets are blue.
Inputs aint blurring.
But I know what to do.

After carefully monitoring the community's struggle with non blurring TextInputs. This package is a simple solution for anyone seeking quick focusing & blurring over their components. Let's dig into the docs, shall we?

🍏 Motivation

React Native's TextInput is a wonderful component, yet it sometimes triggers several nerves to get blurred properly upon tapping outside of the component or clicking on another component. The struggle is real and is well heard. Thus, the methodology here is pretty simple and implies determining a focal component set correspondingly once a component is pressed or focused. Once the ref of that component is obtained, logic is applied to track your presses and blur the component accordingly.

🛫 Installation

Let's get down to business first, use your intimate npm package manager. Do not forget the peer dependencies.

$ yarn add react-native-focal react-native-gesture-handler

or

$ npm install --save react-native-focal react-native-gesture-handler

Linking the peer dependency

Do not forget to properly link the react-native-gesture-handler according to your project's config. Here's the link to the Get Started.

🗞️ API

Container

Component responsible to wrap your screen with a tappable View that detects when a touch is pressed outside a component.

Props

Same as ViewProps

Name Description Default
onPress extra function to be executed upon clicking anywhere inside the container undefined

Controller

Component responsible to wrap your desired component that is subject to some action, ie: TextInput, Text, Button. Once you wrap the component with this Controller, you can modify how this controller will interact with the focal component and shape its experience.

Props
Name Description Default
isFocusable boolean indicating whether the wrapped component behaves as a focusable component or not true
onBlur function responsible to shape the component blurring experience through a passed method expecting as input the node (component ref) itself to properly handle the blurring effect. Also expecting as a return a boolean to whether remove the component from the focus or not. true to remove the component, false to keep the component logically focused. (node) => { node?.blur?.(); return true; }
onFocus function responsible to add an extra functionality upon focusing on the controlled component undefined

⚔️ Samurai Tip

Requires a TypeScript configured project

This is a generic component! Yes! sir! it! is!
Let me elaborate... The Controller allows you to provide a generic type of the component you're controlling, and this is mainly to offer better suggestions when using onBlur if your component is strictly typed. You can easily use this feature as follows.

<Controller<TextInput>
  onBlur={(node) => {
    node.clear()
    node.blur()
    return true
  }}
>
  <TextInput />
</Controller>

Methods

blur

@param force boolean responsible whether to force the removal of the focused ref logically.

Function responsible for getting the focused component upon execution and if any tries to blur it. Keep in mind it's not necessarily blur the component if the Controller's onBlur is set to something different. Calling this method will execute whatever onBlur holds for the controlled component.

import { blur } from 'react-native-focal'

/* Default handling */
blur()

/* Strictly denotes to remove the focused if any */
blur(true)

resetFocuses

Function responsible for retrieving the number of actual nodes in the focal object.

import { resetFocuses } from 'react-native-focal'

resetFocuses()

getByIndex

Function responsible for retrieving a certain node within the focal object via index if valid.

import { getByIndex } from 'react-native-focal'

const { node, onBlur } = getByIndex(1)

getFocused

Function responsible for getting the focused component. Returned object has a node for the actual ref and onBlur which is the string passed through onBlur

import { getFocused } from 'react-native-focal'

const { node, onBlur } = getFocused()

getFocusedId

Function responsible for getting the focused component's id.

import { getFocusedId } from 'react-native-focal'

const privateId = getFocusedId()

getLength

Function responsible for retrieving the number of actual nodes in the focal object.

import { getLength } from 'react-native-focal'

const size = getLength()

Example

import { Container, Controller, blur } from 'react-native-focal'
import { TextInput, Button } from 'react-native'

const Screen = () => (
  <Container
    onPress={() => {
      Alert.alert('Pressed Outside')
    }}
  >
    {/* TextInput handled by the default `onBlur` */}
    <Controller>
      <TextInput />
    </Controller>

    {/* TextInput handled by the passed `onBlur` with a signal to not remove the node from the focus */}
    <Controller
      onFocus={() => {
        Alert.alert('Second Input Focused')
      }}
      onBlur={(node) => {
        node.clear()
        return false
      }}
    >
      <TextInput />
    </Controller>

    {/* Button handles blur onPress internally */}
    <Controller isFocusable={false}>
      <Button />
    </Controller>

    {/* Button handles blur onPress externally */}
    <Button onPress={blur} />
  </Container>
)

🎮 Showcase

You can follow this link to snack.expo.dev for a quick trial of the package. In the deployed snack, you will find different use cases of the Controller wrapping TextInputs and simulating how to shape the experience of each one.

🌟 Encouragement

Kindly stargaze ⭐ this repository if it helped you achieve anything good!

👏 Contribute

This package is free of charge for the only purpose to help the community with the related concerns. Thus, any helping hand is more than welcome to evolve the package if it is proven to be worth evolving.

Check CONTRIBUTING.md for some contribution guidelines.

License

MIT © yousseftarekkh