react-native#findNodeHandle TypeScript Examples

The following examples show how to use react-native#findNodeHandle. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: a11y-element.tsx    From protect-scotland with Apache License 2.0 6 votes vote down vote up
export function useA11yElement() {
  const {
    accessibility: {screenReaderEnabled}
  } = useApplication();
  const focusRef = useRef(null);
  const isFocused = useIsFocused();

  const focusA11yElement = useCallback(
    (timeout = 250) => {
      if (screenReaderEnabled && focusRef.current && isFocused) {
        const tag = findNodeHandle(focusRef.current);
        if (tag) {
          const id = setTimeout(
            () => AccessibilityInfo.setAccessibilityFocus(tag),
            timeout
          );
          return () => clearTimeout(id);
        }
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [screenReaderEnabled, focusRef.current, isFocused]
  );

  const a11yProps = useMemo(
    () => ({
      ref: focusRef
    }),
    []
  );

  return {a11yProps, focusRef, focusA11yElement};
}
Example #2
Source File: ContextMenuButton.tsx    From react-native-ios-context-menu with MIT License 6 votes vote down vote up
dismissMenu = () => {
    if(!LIB_ENV.isContextMenuButtonSupported) return;

    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this.nativeRef),
      RNIContextMenuButtonCommands.dismissMenu,
      []
    );
  };
Example #3
Source File: Helpers.ts    From react-native-ios-context-menu with MIT License 6 votes vote down vote up
export function getNativeNodeHandle(nativeRef: React.Component){
  const nodeHandle = findNodeHandle(nativeRef);

  if(nodeHandle == null){
    throw new Error('Unable to get the node handle for the native ref.');
  };

  return nodeHandle;
}
Example #4
Source File: TutorialContent.tsx    From mobile with Apache License 2.0 5 votes vote down vote up
TutorialContent = ({item, isActive}: TutorialContentProps) => {
  const [i18n] = useI18n();
  const prefersReducedMotion = useReduceMotionPreference();
  const {width: viewportWidth, height: viewportHeight} = useWindowDimensions();

  const animationRef: React.Ref<LottieView> = useRef(null);
  useEffect(() => {
    // need to stop if user prefers reduced animations
    if (prefersReducedMotion) {
      animationRef.current?.play(animationData[item].pauseFrame, animationData[item].pauseFrame);
    } else if (isActive) {
      animationRef.current?.play();
    } else {
      animationRef.current?.reset();
    }
  }, [isActive, prefersReducedMotion, item]);

  const autoFocusRef = useRef<any>();
  useLayoutEffect(() => {
    const tag = findNodeHandle(autoFocusRef.current);
    if (isActive && tag) {
      AccessibilityInfo.setAccessibilityFocus(tag);
    }
  }, [isActive]);

  return (
    <ScrollView style={styles.flex} contentContainerStyle={styles.center}>
      <LottieView
        ref={animationRef}
        style={{width: viewportWidth, height: viewportHeight / 2}}
        source={animationData[item].source}
        imageAssetsFolder="animation/images"
        loop={!prefersReducedMotion}
      />
      <Box paddingHorizontal="xxl">
        <Text
          ref={autoFocusRef}
          textAlign="center"
          color="overlayBodyText"
          variant="bodySubTitle"
          marginBottom="m"
          accessibilityRole="header"
        >
          {i18n.translate(`Tutorial.${item}Title`)}
        </Text>
        <Text variant="bodyText" textAlign="center" color="overlayBodyText">
          {i18n.translate(`Tutorial.${item}`)}
        </Text>
      </Box>
    </ScrollView>
  );
}
Example #5
Source File: useAccessibilityAutoFocus.ts    From mobile with Apache License 2.0 5 votes vote down vote up
focusOnElement = (elementRef: any) => {
  const node = findNodeHandle(elementRef);
  if (!node) {
    return;
  }
  AccessibilityInfo.setAccessibilityFocus(node);
}
Example #6
Source File: ContextMenuViewExample15.tsx    From react-native-ios-context-menu with MIT License 5 votes vote down vote up
export function ContextMenuViewExample15(props: ContextMenuExampleProps) {
  const [targetViewNode, setTargetViewNode] = React.useState(null);

  const viewRef = React.useRef();

  React.useEffect(() => {
    setTargetViewNode(
      findNodeHandle(viewRef.current)
    );

  }, []);

  return (
    <ContextMenuView
      style={props.style}
      menuConfig={{
        menuTitle: 'ContextMenuViewExample15',
        menuItems: [{
          actionKey  : 'key-01',
          actionTitle: 'Action #1',
        }],
      }}
      previewConfig={{
        targetViewNode: targetViewNode,
      }}
      onPressMenuItem={({nativeEvent}) => {
        Alert.alert(
          'onPressMenuItem Event',
          `actionKey: ${nativeEvent.actionKey} - actionTitle: ${nativeEvent.actionTitle}`
        );
      }}
    >
      <ContextMenuCard
        index={props.index}
        title={'ContextMenuViewExample15'}
        subtitle={'Preview Target'}
        description={[
          `Example context menu with a specific preview target`
        ]}
      >
        <View
          style={styles.targetContainer}
          ref={viewRef}
        >
          <Text style={styles.text}>
            {`Hello! Target Node: ${targetViewNode}`}
          </Text>
        </View>
      </ContextMenuCard>
    </ContextMenuView>
  );
}
Example #7
Source File: useKASVWorkaround.ts    From lexicon with MIT License 5 votes vote down vote up
/**
 * `useKASVWorkaround` (KASV -> KeyboardAwareScrollView) is a reusable hook to
 * implement a (hacky) workaround [discussed with the maintainer](https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/451)
 * for a bug we were encountering after upgrading from Expo 38 to Expo 42 in July of 2021.
 *
 * For brief context, the app would crash with an undefined error after attempting to focus
 * a TextArea input that was interacting with KeyboardAwareScrollView. This was due to us
 * attempting to invoke `scrollToFocusedInput` in way recommended by the docs.
 *
 * The hook provides `props`, which are meant to be spread onto the
 * `KeyboardAwareScrollView`. This will allow the `innerRef` prop to be set correctly.
 *
 * The hook then also provides `scrollToFocusedInput`, which is the function we were
 * originally calling with a ref workaround.
 *
 */
export function useKASVWorkaround() {
  const scrollRef = React.useRef<JSX.Element>();
  const scrollToInputRef = React.useRef<ScrollToInput>();

  function innerRef(ref: JSX.Element) {
    scrollRef.current = ref;
    if (!ref) {
      return;
    }

    const refWithWorkAround = (ref as unknown) as KASVRef;

    const { getScrollResponder } = refWithWorkAround;
    if (!getScrollResponder) {
      return;
    }

    const responder = getScrollResponder();
    if (!responder) {
      return;
    }

    const { props } = responder;
    if (!props) {
      return;
    }

    const { scrollToFocusedInput } = props;

    if (!scrollToFocusedInput) {
      return;
    }

    scrollToInputRef.current = scrollToFocusedInput;
  }

  const scrollToFocusedInput: TextAreaFocusHandler = ({ target }) => {
    const { current } = scrollToInputRef;
    if (!current) {
      return;
    }

    const scrollToFocusedInput = current;
    if (!scrollToFocusedInput) {
      return;
    }

    const handle = findNodeHandle(target);
    if (handle == null) {
      return;
    }

    scrollToFocusedInput(handle);
  };

  return {
    scrollToFocusedInput,
    props: {
      innerRef,
    },
  };
}
Example #8
Source File: ContextMenuViewTest07.tsx    From react-native-ios-context-menu with MIT License 4 votes vote down vote up
export function ContextMenuViewTest07(props: ContextMenuExampleProps) {
  const [counter, setCounter] = React.useState(0);
  const [targetViewNode, setTargetViewNode] = React.useState(null);

  const [isResizeAnimated, setIsResizeAnimated] = React.useState(false);
  const [togglePreviewType, setTogglePreviewType] = React.useState(false);
  const [togglePreviewSize, setTogglePreviewSize] = React.useState(false);
  const [toggleBgTransparent, setToggleBgTransparent] = React.useState(false);
  const [toggleTargetViewNode, setToggleTargetViewNode] = React.useState(false);
  const [togglePreferredCommitStyle, setTogglePreferredCommitStyle] = React.useState(false);

  const intervalRef = React.useRef<NodeJS.Timer | undefined>();

  React.useEffect(() => {
    return () => {
      if(!intervalRef.current) return;
      clearInterval(intervalRef.current);
    };
  }, []);

  const previewConfig: MenuPreviewConfig = {
    previewType: 
      (togglePreviewType? 'CUSTOM' : 'DEFAULT'),

    previewSize: 
      (togglePreviewSize? 'STRETCH' : 'INHERIT'),

    preferredCommitStyle: 
      (togglePreferredCommitStyle? 'pop' : 'dismiss'),

    backgroundColor: 
      (toggleBgTransparent ? 'white' :  'rgba(255,255,255,0.5)'),

    isResizeAnimated,
    ...(toggleTargetViewNode && { 
      targetViewNode 
    }),
  };

  return (
    <ContextMenuView
      style={props.style}
      menuConfig={{
        menuTitle: 'ContextMenuViewTest07',
        menuItems: [{
          actionKey  : 'add',
          actionTitle: `Add 100`,
          discoverabilityTitle: `Current counter: ${counter}`,
          icon: {
            type: 'IMAGE_SYSTEM',
            imageValue: {
              systemName: 'plus',
            },
          }
        }, 
        (counter > 0) && {
          actionKey     : 'reset',
          actionTitle   : `Reset Counter`,
          menuAttributes: ['destructive'],
          icon: {
            type: 'IMAGE_SYSTEM',
            imageValue: {
              systemName: 'trash',
            },
          }
        }],
      }}
      previewConfig={previewConfig}
      renderPreview={() => (
        <View style={[styles.previewContainer]}>
          <Text style={styles.previewTitleText}>
            {'Hello World'}
          </Text>
          {(counter % 2 === 0) && (
            <Text style={styles.previewCounterText}>
              {`Counter: ${counter}`}
            </Text>
          )}
        </View>
      )}
      onMenuWillShow={() => {
        intervalRef.current = setInterval(() => {
          setCounter((prevValue) => (prevValue + 1));
        }, 1000);
      }}
      onMenuWillHide={() => {
        if(!intervalRef.current) return;
        clearInterval(intervalRef.current);
      }}
      onPressMenuItem={({nativeEvent}) => {
        switch (nativeEvent.actionKey) {
          case 'add':
            setCounter((prevValue) => (prevValue + 100));
            break;

          case 'reset':
            setCounter(0);
            break;
        };
      }}
      >
      <ContextMenuCard
        index={props.index}
        title={'ContextMenuViewTest07'}
        subtitle={'Custom Preview'}
        description={[
          `Test for the different possible custom menu preview config`
        ]}
      >
        {toggleTargetViewNode && (
          <View
            style={styles.targetViewContainer}
            ref={ref => {
              setTargetViewNode(
                findNodeHandle(ref)
              );
            }}
          >
            <Text style={styles.targetViewText}>
              {'Target View'}
            </Text>
          </View>
        )}
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'previewType'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.previewType}
            </Text>
          </View>
          <Switch
            value={togglePreviewType}
            onValueChange={(flag) => {
              setTogglePreviewType(flag);
            }}
          />
        </View>
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'previewSize'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.previewSize}
            </Text>
          </View>
          <Switch
            value={togglePreviewSize}
            onValueChange={(flag) => {
              setTogglePreviewSize(flag);
            }}
          />
        </View>
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'backgroundColor'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.backgroundColor}
            </Text>
          </View>
          <Switch
            value={toggleBgTransparent}
            onValueChange={(flag) => {
              setToggleBgTransparent(flag);
            }}
          />
        </View>
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'isResizeAnimated'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.isResizeAnimated? 'true' : 'false'}
            </Text>
          </View>
          <Switch
            value={isResizeAnimated}
            onValueChange={(flag) => {
              setIsResizeAnimated(flag);
            }}
          />
        </View>
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'preferredCommitStyle'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.preferredCommitStyle}
            </Text>
          </View>
          <Switch
            value={togglePreferredCommitStyle}
            onValueChange={(flag) => {
              setTogglePreferredCommitStyle(flag)
            }}
          />
        </View>
        <View style={styles.rowContainer}>
          <View style={styles.textRowContainer}>
            <Text style={styles.textRowTitle}>
              {'targetViewNode'}
            </Text>
            <Text style={styles.textRowSubtitle}>
              <Text style={styles.textRowSubtitleLabel}>
                {'Value: '}
              </Text>
              {previewConfig.targetViewNode}
            </Text>
          </View>
          <Switch
            value={toggleTargetViewNode}
            onValueChange={(flag) => {
              setToggleTargetViewNode(flag);
            }}
          />
        </View>
      </ContextMenuCard>
    </ContextMenuView>
  );
}
Example #9
Source File: CardField.tsx    From stripe-react-native with MIT License 4 votes vote down vote up
CardField = forwardRef<CardFieldInput.Methods, Props>(
  (
    {
      onCardChange,
      onFocus,
      onBlur,
      cardStyle,
      placeholders,
      postalCodeEnabled,
      ...props
    },
    ref
  ) => {
    const inputRef = useRef<any>(null);

    const onCardChangeHandler = useCallback(
      (event: NativeSyntheticEvent<CardFieldInput.Details>) => {
        const card = event.nativeEvent;

        const data: CardFieldInput.Details = {
          last4: card.last4,
          expiryMonth: card.expiryMonth,
          expiryYear: card.expiryYear,
          complete: card.complete,
          brand: card.brand,
          validExpiryDate: card.validExpiryDate,
          validNumber: card.validNumber,
          validCVC: card.validCVC,
        };

        if (card.hasOwnProperty('postalCode')) {
          data.postalCode = card.postalCode || '';
        }
        if (card.hasOwnProperty('number') || card.hasOwnProperty('cvc')) {
          data.number = card.number || '';
          data.cvc = card.cvc || '';
          if (__DEV__ && onCardChange && card.complete) {
            console.warn(
              `[stripe-react-native] ⚠️ WARNING: You've enabled \`dangerouslyGetFullCardDetails\`, meaning full card details are being returned. Only do this if you're certain that you fulfill the necessary PCI compliance requirements. Make sure that you're not mistakenly logging or storing full card details! See the docs for details: https://stripe.com/docs/security/guide#validating-pci-compliance`
            );
          }
        }
        onCardChange?.(data);
      },
      [onCardChange]
    );

    const onFocusHandler = useCallback(
      (event) => {
        const { focusedField } = event.nativeEvent;
        if (focusedField) {
          focusInput(inputRef.current);
          onFocus?.(focusedField);
        } else {
          onBlur?.();
        }
      },
      [onFocus, onBlur]
    );

    const focus = () => {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(inputRef.current),
        'focus' as any,
        []
      );
    };

    const blur = () => {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(inputRef.current),
        'blur' as any,
        []
      );
    };

    const clear = () => {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(inputRef.current),
        'clear' as any,
        []
      );
    };

    useImperativeHandle(ref, () => ({
      focus,
      blur,
      clear,
    }));

    useLayoutEffect(() => {
      const inputRefValue = inputRef.current;
      if (inputRefValue !== null) {
        registerInput(inputRefValue);
        return () => {
          unregisterInput(inputRefValue);
          if (currentlyFocusedInput() === inputRefValue) {
            inputRefValue.blur();
          }
        };
      }
      return () => {};
    }, [inputRef]);

    return (
      <CardFieldNative
        ref={inputRef}
        onCardChange={onCardChangeHandler}
        onFocusChange={onFocusHandler}
        postalCodeEnabled={postalCodeEnabled ?? true}
        cardStyle={{
          backgroundColor: cardStyle?.backgroundColor,
          borderColor: cardStyle?.borderColor,
          borderWidth: cardStyle?.borderWidth,
          borderRadius: cardStyle?.borderRadius,
          cursorColor: cardStyle?.cursorColor,
          fontSize: cardStyle?.fontSize,
          placeholderColor: cardStyle?.placeholderColor,
          textColor: cardStyle?.textColor,
          textErrorColor: cardStyle?.textErrorColor,
          fontFamily: cardStyle?.fontFamily,
        }}
        placeholders={{
          number: placeholders?.number,
          expiration: placeholders?.expiration,
          cvc: placeholders?.cvc,
          postalCode: placeholders?.postalCode,
        }}
        {...props}
      />
    );
  }
)
Example #10
Source File: CardForm.tsx    From stripe-react-native with MIT License 4 votes vote down vote up
CardForm = forwardRef<CardFormView.Methods, Props>(
  (
    {
      onFormComplete,
      cardStyle,
      // isUserInteractionEnabled = true,
      // postalCodeEnabled = true,
      // onFocus,
      // onBlur,
      placeholders,
      ...props
    },
    ref
  ) => {
    const inputRef = useRef<any>(null);

    const onFormCompleteHandler = useCallback(
      (event: NativeSyntheticEvent<CardFormView.Details>) => {
        const card = event.nativeEvent;

        const data: CardFormView.Details = {
          last4: card.last4,
          expiryMonth: card.expiryMonth,
          expiryYear: card.expiryYear,
          complete: card.complete,
          brand: card.brand,
          country: card.country,
          postalCode: card.postalCode,
        };

        if (card.hasOwnProperty('number') || card.hasOwnProperty('cvc')) {
          data.number = card.number || '';
          data.cvc = card.cvc || '';
          if (__DEV__ && onFormComplete && card.complete) {
            console.warn(
              `[stripe-react-native] ⚠️ WARNING: You've enabled \`dangerouslyGetFullCardDetails\`, meaning full card details are being returned. Only do this if you're certain that you fulfill the necessary PCI compliance requirements. Make sure that you're not mistakenly logging or storing full card details! See the docs for details: https://stripe.com/docs/security/guide#validating-pci-compliance`
            );
          }
        }
        onFormComplete?.(data);
      },
      [onFormComplete]
    );

    const focus = () => {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(inputRef.current),
        'focus' as any,
        []
      );
    };

    const blur = () => {
      UIManager.dispatchViewManagerCommand(
        findNodeHandle(inputRef.current),
        'blur' as any,
        []
      );
    };

    useImperativeHandle(ref, () => ({
      focus,
      blur,
    }));

    const onFocusHandler = useCallback((event) => {
      const { focusedField } = event.nativeEvent;
      if (focusedField) {
        focusInput(inputRef.current);
        // onFocus?.(focusedField);
      } else {
        // onBlur?.();
      }
    }, []);

    useLayoutEffect(() => {
      const inputRefValue = inputRef.current;
      if (inputRefValue !== null) {
        registerInput(inputRefValue);
        return () => {
          unregisterInput(inputRefValue);
          if (currentlyFocusedInput() === inputRefValue) {
            inputRefValue.blur();
          }
        };
      }
      return () => {};
    }, [inputRef]);

    return (
      <CardFormNative
        ref={inputRef}
        onFormComplete={onFormCompleteHandler}
        cardStyle={{
          backgroundColor: cardStyle?.backgroundColor,
          borderColor: cardStyle?.borderColor,
          borderWidth: cardStyle?.borderWidth,
          borderRadius: cardStyle?.borderRadius,
          cursorColor: cardStyle?.cursorColor,
          fontSize: cardStyle?.fontSize,
          placeholderColor: cardStyle?.placeholderColor,
          textColor: cardStyle?.textColor,
          textErrorColor: cardStyle?.textErrorColor,
          fontFamily: cardStyle?.fontFamily,
          // disabledBackgroundColor: cardStyle?.disabledBackgroundColor,
          // type: cardStyle?.type,
        }}
        // isUserInteractionEnabledValue={isUserInteractionEnabled}
        placeholders={{
          number: placeholders?.number,
          expiration: placeholders?.expiration,
          cvc: placeholders?.cvc,
          postalCode: placeholders?.postalCode,
        }}
        onFocusChange={onFocusHandler}
        // postalCodeEnabled={postalCodeEnabled}
        {...props}
      />
    );
  }
)