Skip to main content

Helpers

@ovok/native re-exports a handful of utilities used internally by other components. They're publicly exported so apps can reuse the same Formik field wrappers, conditional rendering, and Sentry-aware logger that the SDK uses itself — no need to redefine them.

Source: src/modules/helpers/index.tsx.

Exports at a glance

import {
Conditional,
FormField,
FormSelect,
FormDateField,
slog,
withAnimated,
BottomSheetModalProvider,
} from "@ovok/native";
ExportModule pathSource library
Conditional./conditional.tsxSDK
FormField./form-items/form-field.tsxSDK (wraps react-native-paper TextInput)
FormSelect./form-items/form-select.tsxSDK (wraps react-native-element-dropdown)
FormDateField./form-items/form-date-field.tsxSDK (wraps react-native-modal-datetime-picker)
slog./utils/s-log.tsSDK (wraps @sentry/react-native)
withAnimated./utils/with-animated.tsxSDK (Reanimated HOC bridge)
BottomSheetModalProvider(direct re-export)@gorhom/bottom-sheet

<Conditional>

Renders children only when condition is truthy. Cleaner than {cond && <View>...</View>} for multi-line branches and easier to scan in deeply-nested trees.

interface ConditionalProps {
condition: boolean;
children: React.ReactNode;
}
<Conditional condition={isMfaRequired}>
<MfaCodeInput onSubmit={handleMfa} />
</Conditional>

condition === false → returns null. No fallback prop; pair with a sibling for else branches.

<FormField>

A Formik-bound text input. Reads value/error/touched from the Formik context you pass via context and routes change/blur back through the form. Renders react-native-paper's <TextInput mode="outlined"> plus a <HelperText> for errors, with the error message run through react-i18next's t().

interface FormFieldProps extends Omit<TextInputProps, "onChangeText" | "value" | "testID"> {
name: string;
context: React.Context<ReturnType<typeof useFormik>>;
containerStyle?: ViewStyle;
testID?: string;
}
import { useFormik } from "formik";
import * as React from "react";
import { FormField } from "@ovok/native";

const FormContext = React.createContext<ReturnType<typeof useFormik> | null>(null);

function SignInForm() {
const form = useFormik({
initialValues: { email: "" },
onSubmit: async (values) => { /* ... */ },
});
return (
<FormContext.Provider value={form}>
<FormField name="email" context={FormContext} label="Email" />
</FormContext.Provider>
);
}

Error messages are looked up as translation keys, so feed Yup/Zod schemas key names like "validation.email.required" rather than raw English strings.

<FormSelect>

Formik-bound dropdown with an animated floating label. Wraps react-native-element-dropdown's <Dropdown>. Generic on the option type T.

interface FormSelectProps<T extends object> extends Omit<DropdownProps<T>, "data" | "onChange" | "onBlur" | "placeholder"> {
name: string;
context: React.Context<ReturnType<typeof useFormik>>;
label?: string;
options: T[];
labelStyle?: TextStyle;
onChange?: (item: T) => void;
onBlur?: () => void;
}
<FormSelect
name="country"
context={FormContext}
label="Country"
options={countries}
labelField="name"
valueField="code"
/>

The selected value is written via setFieldValue(name, item[valueField]) — so valueField must be a key of T whose value is the discriminator your schema validates.

<FormDateField>

Formik-bound date picker. Wraps react-native-modal-datetime-picker and writes the result back as a YYYY-MM-DD string (via date.toISOString().split('T')[0]). Supports mode: 'date' | 'time' | 'datetime'; default is 'date'.

interface FormDateFieldProps {
name: string;
context: React.Context<ReturnType<typeof useFormik>>;
label?: string;
testID?: string;
containerStyle?: ViewStyle;
labelStyle?: TextStyle;
mode?: "date" | "time" | "datetime";
}
<FormDateField name="dateOfBirth" context={FormContext} label="Date of birth" />

Note: in 'datetime' mode the date is still serialized as YYYY-MM-DD — the time component is discarded. If you need full ISO timestamps, write a separate field wrapper.

slog(error, scope, additionalData?, level?)

Structured logger. In __DEV__ it console.logs; in production it calls Sentry.captureException with the scope + extras.

slog(
error: any,
scope: string,
additionalData?: Record<string, any>,
level?: "error" | "warning" | "info" | "debug",
): void;
try {
await someBleOperation();
} catch (e) {
slog(e, "bt.connect", { deviceSn: device.sn }, "warning");
}

Use the scope argument to grep across logs — it's free text, but consistent prefixes (bt.*, auth.*, fhir.*) pay off later.

withAnimated(Component)

Higher-order component that bridges a React Native Paper class component into a react-native-reanimated animated component. Worked around callstack/react-native-paper#2364createAnimatedComponent on a class component requires a class wrapper, which is what this HOC supplies.

const withAnimated: <T extends object>(
WrappedComponent: React.ComponentType<T>,
) => React.ComponentClass<AnimatedProps<T>, any>;
import { Card } from "react-native-paper";
import { withAnimated } from "@ovok/native";

const AnimatedCard = withAnimated(Card);

Use only when a Paper class component needs useAnimatedStyle/useSharedValue. Function components don't need this — Animated.createAnimatedComponent accepts them directly.

BottomSheetModalProvider

Direct re-export of BottomSheetModalProvider from @gorhom/bottom-sheet, surfaced for apps that consume <PickerSheet> or other SDK components that present bottom sheets. Mount once at the root, inside GestureHandlerRootView:

import { GestureHandlerRootView } from "react-native-gesture-handler";
import { BottomSheetModalProvider, ThemeProvider as OvokThemeProvider } from "@ovok/native";

function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<BottomSheetModalProvider>
<OvokThemeProvider theme={themeConfig}>
<YourScreens />
</OvokThemeProvider>
</BottomSheetModalProvider>
</GestureHandlerRootView>
);
}

This is the same provider you'd import from @gorhom/bottom-sheet directly — re-exported here so apps don't need a separate dependency entry just for this single symbol.