# Piplup - Collection of Lightweight modular libraries (/docs) ## Introduction [#introduction] **Piplup** is a collection of lightweight, modular libraries designed to simplify the development of fast, interactive, and reusable user interfaces. It focuses on improving developer experience (DX) by providing clean abstractions and production-ready utilities that help you build scalable applications more efficiently. Piplup currently includes the following packages: Core utilities and primitives for building form-connected components with React Hook Form. Pre-built adapters for integrating custom and third-party UI components with React Hook Form. Utilities for managing and invalidating application cache effectively. A Vite plugin for automated cache busting, powered by @piplup/cache-buster. A flexible access control layer for managing roles and permissions in React applications. Shared helper functions, hooks, and common utilities used across Piplup packages. # Installation - @piplup/cache-buster (/docs/cache-buster/installation) `@piplup/cache-buster` is a lightweight React utility that ensures users always get the latest deployed version of your app. npm pnpm yarn bun ```bash npm install @piplup/cache-buster ``` ```bash pnpm add @piplup/cache-buster ``` ```bash yarn add @piplup/cache-buster ``` ```bash bun add @piplup/cache-buster ``` ## Setup build integration [#setup-build-integration] Cache busting requires a release ID to be generated at build time. ### Option 1: CLI [#option-1-cli] Update your package.json: ```json { "scripts": { "build": "piplup-cache-buster --publicDir=public && react-scripts build" } } ``` This will: * Generate a unique release ID * Save it in your public/ directory * Allow runtime comparison ### Option 2: Vite plugin [#option-2-vite-plugin] If you're using Vite: npm pnpm yarn bun ```bash npm install @piplup/vite-plugin-cache-buster ``` ```bash pnpm add @piplup/vite-plugin-cache-buster ``` ```bash yarn add @piplup/vite-plugin-cache-buster ``` ```bash bun add @piplup/vite-plugin-cache-buster ``` Update `vite.config.(ts|mts|js|mjs)`: ```tsx import { vitePluginCacheBuster } from "@piplup/vite-plugin-cache-buster"; export default { plugins: [vitePluginCacheBuster()], }; ``` ### Why this step is required [#why-this-step-is-required] The library works by comparing: * Current release ID (from server) * Stored release ID (in browser) Without generating this file at build time, cache busting cannot work. # Installation — @piplup/react-acl (/docs/react-acl/installation) `@piplup/react-acl` provides a small ACL context, a `HasAccess` conditional component, and a `useAcl` hook for programmatic checks. npm pnpm yarn bun ```bash npm install @piplup/react-acl ``` ```bash pnpm add @piplup/react-acl ``` ```bash yarn add @piplup/react-acl ``` ```bash bun add @piplup/react-acl ``` ## Quickstart [#quickstart] Wrap your app with `AclProvider` and pass roles/permissions (can be loaded asynchronously): ```tsx import { AclProvider } from "@piplup/react-acl"; export default function App({ children }) { // load roles/permissions from API return ( {children} ); } ``` See the `AclProvider`, `HasAccess`, and `useAcl` pages for API details and examples. ## See also [#see-also] * [AclProvider](/docs/react-acl/components/acl-provider) * [HasAccess](/docs/react-acl/components/has-access) * [useAcl](/docs/react-acl/hooks/use-acl) # Installation — @piplup/rhf-core (/docs/rhf-core/installation) ## Install Core Package [#install-core-package] Install the core package: npm pnpm yarn bun ```bash npm install @piplup/rhf-core ``` ```bash pnpm add @piplup/rhf-core ``` ```bash yarn add @piplup/rhf-core ``` ```bash bun add @piplup/rhf-core ``` Optionally, install the adapters package for pre-built integrations: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters ``` ```bash pnpm add @piplup/rhf-adapters ``` ```bash yarn add @piplup/rhf-adapters ``` ```bash bun add @piplup/rhf-adapters ``` # Installation — @piplup/utils (/docs/utils/installation) `@piplup/utils` contains small helpers and React hooks used across Piplup packages. npm pnpm yarn bun ```bash npm install @piplup/utils ``` ```bash pnpm add @piplup/utils ``` ```bash yarn add @piplup/utils ``` ```bash bun add @piplup/utils ``` ## Quick usage [#quick-usage] Import individual helpers: ```tsx import { compact } from "@piplup/utils"; const arr = compact([1, null, 2]); ``` See the `helpers` and `hooks` pages for API details and examples. # Installation — @piplup/vite-plugin-cache-buster (/docs/vite-plugin-cache-buster/installation) `@piplup/vite-plugin-cache-buster` generates a release ID during your Vite build, enabling `@piplup/cache-buster` to detect new deployments and refresh stale client caches. npm pnpm yarn bun ```bash npm install @piplup/vite-plugin-cache-buster ``` ```bash pnpm add @piplup/vite-plugin-cache-buster ``` ```bash yarn add @piplup/vite-plugin-cache-buster ``` ```bash bun add @piplup/vite-plugin-cache-buster ``` ## Setup [#setup] Add the plugin to your Vite config: ```tsx import { vitePluginCacheBuster } from "@piplup/vite-plugin-cache-buster"; export default { plugins: [vitePluginCacheBuster()], }; ``` ## How it works [#how-it-works] During build, the plugin: * Generates a unique release ID * Writes it to a static file (e.g. `/release.txt`) * Makes it accessible to the browser at runtime This file is later fetched by `@piplup/cache-buster` to detect updates. ## Why this is required [#why-this-is-required] Cache busting relies on comparing: * **Current release ID (from server file)** * **Stored release ID (in browser storage)** Without generating this file during build, the app cannot detect updates. ## When to use [#when-to-use] Use this plugin if: * You're using **Vite** * You're using `@piplup/cache-buster` * You want **automatic release ID generation** ## Next step [#next-step] Integrate the runtime check — use `useReleaseStatus` or `` in your app. ## See also [#see-also] * [Cache Buster - Installation](/docs/cache-buster/installation) * [useReleaseStats](/docs/cache-buster/hooks/use-release-status) * [CacheBuster](/docs/cache-buster/components/cache-buster) # CacheBuster (/docs/cache-buster/components/cache-buster) `CacheBuster` is a convenience wrapper around the `useReleaseStatus` hook. It automatically checks for new deployments and **reloads the page when a new version is detected**. ## Basic usage [#basic-usage] ```tsx import { CacheBuster } from '@piplup/cache-buster'; function App() { return ( ); } ``` ## Props [#props] ## See also [#see-also] * [useReleaseStatus](/docs/cache-buster/hooks/use-release-status) # useReleaseStatus (/docs/cache-buster/hooks/use-release-status) # Usage [#usage] `useReleaseStatus` allows you to detect whether a new release is available and decide how your app should respond. ## Basic example [#basic-example] ```tsx import { useReleaseStatus } from '@piplup/cache-buster'; function App() { const status = useReleaseStatus({ storageKey: 'RELEASE', }); if (status === 'new-release') { return (

New version available

); } return ; } ``` ## Props [#props] ## Return value [#return-value] The `useReleaseStatus` hook returns one of the following statuses: `error`, `new-release`, `no-release` or `null`. # AclProvider (/docs/react-acl/components/acl-provider) ## Import [#import] ```tsx import { AclProvider } from "@piplup/react-acl"; ``` ## Usage [#usage] ```tsx ``` ## Props [#props] ## Notes [#notes] * `roles` and `permissions` accept `string` or `number` values. * Use the `loading` prop while your identity/ACL data is being fetched. # HasAccess (/docs/react-acl/components/has-access) ## Import [#import] ```tsx import { HasAccess } from "@piplup/react-acl"; ``` ## Basic example [#basic-example] ```tsx
Visible to users with read permission
``` ## Props [#props] ## Examples [#examples] * `fallback` can be used to render alternative UI when access is denied. * `loading` prop can be supplied to show a loading placeholder while ACL data resolves. # useAcl (/docs/react-acl/hooks/use-acl) ## Import [#import] ```tsx import { useAcl } from "@piplup/react-acl"; ``` ## Basic example [#basic-example] ```tsx function CheckAccess() { const { isAuthorized, loading } = useAcl(); if (loading) return
Loading ACL...
; return
{isAuthorized({ permissions: 'read' }) ? 'Allowed' : 'Denied'}
; } ``` ## Return value [#return-value] # Installation — @piplup/rhf-adapters (HTML) (/docs/rhf-adapters/html/installation) `@piplup/rhf-adapters` provides prebuilt adapter hooks and components that connect UI elements to React Hook Form. The package is organized by subpath, so you only import the adapter family you need. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters ``` ```bash pnpm add @piplup/rhf-adapters ``` ```bash yarn add @piplup/rhf-adapters ``` ```bash bun add @piplup/rhf-adapters ``` ## Import [#import] Import HTML adapters from the `html` subpath: ```tsx import { HtmlInputElement, HtmlTextareaElement, useHtmlInputAdapter, } from "@piplup/rhf-adapters/html"; ``` The root `@piplup/rhf-adapters` entrypoint is not where the practical component and hook APIs live. Use the package `/html` subpath instead. ## See also [#see-also] Install the core primitives that the adapter hooks build on. # Installation — @piplup/rhf-adapters (mui-chips-input) (/docs/rhf-adapters/mui-chips-input/installation) `@piplup/rhf-adapters/mui-chips-input` connects `mui-chips-input` fields to React Hook Form. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package together with the MUI Material and mui-chips-input peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-chips-input ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-chips-input ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-chips-input ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-chips-input ``` ## Import [#import] ```tsx import { MuiChipsInputElement, useMuiChipsInputAdapter } from "@piplup/rhf-adapters/mui-chips-input"; ``` The root `@piplup/rhf-adapters` entrypoint is not where the practical component and hook APIs live. Use the package `/mui-chips-input` subpath instead. ## See also [#see-also] * [@piplup/rhf-core](/docs/rhf-core/installation) * [mui-chips-input](https://viclafouch.github.io/mui-chips-input/) # Installation — @piplup/rhf-adapters (mui-color-input) (/docs/rhf-adapters/mui-color-input/installation) `@piplup/rhf-adapters/mui-color-input` connects `mui-color-input` fields to React Hook Form. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package together with the MUI Material and mui-color-input peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-color-input ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-color-input ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-color-input ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-color-input ``` ## Import [#import] ```tsx import { MuiColorInputElement, useMuiColorInputAdapter } from "@piplup/rhf-adapters/mui-color-input"; ``` Use `/mui-color-input` subpath when you need `mui-chips-input` components to stay in sync with `react-hook-form`. ## See also [#see-also] * [mui-color-input](https://viclafouch.github.io/mui-color-input/) # Installation — @piplup/rhf-adapters (mui-file-input) (/docs/rhf-adapters/mui-file-input/installation) `@piplup/rhf-adapters/mui-file-input` connects `mui-file-input` fields to React Hook Form. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package together with the MUI Material and mui-file-input peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-file-input ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-file-input ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-file-input ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-file-input ``` ## Import [#import] ```tsx import { MuiFileInputElement, useMuiFileInputAdapter } from "@piplup/rhf-adapters/mui-file-input"; ``` Use `/mui-file-input` subpath when you need `mui-file-input` components to stay in sync with `react-hook-form`. ## See also [#see-also] * [mui-file-input](https://viclafouch.github.io/mui-file-input/) # Installation — @piplup/rhf-adapters (@mui/material) (/docs/rhf-adapters/mui-material/installation) `@piplup/rhf-adapters/mui-material` provides pre-integrated Material UI components and adapter hooks for React Hook Form. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then install the adapters package together with the MUI Material peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled ``` ## Import [#import] ```tsx import { MuiTextFieldElement, useMuiTextFieldAdapter, } from "@piplup/rhf-adapters/mui-material"; ``` Use `/mui-material` subpath when you want MUI components to participate in form state, validation, helper text composition, and `react-hook-form` controlled value handling without writing the wiring yourself. ## See also [#see-also] * [Components](./components/mui-autocomplete-element) * [Hooks](./hooks/use-mui-autocomplete-adapter) * [useControllerAdapter](/Users/Sadik/code/piplup-react-hook-form-docs/content/docs/rhf-core/hooks/use-controller-adapter.mdx) # Installation — @piplup/rhf-adapters (mui-one-time-password-input) (/docs/rhf-adapters/mui-one-time-password-input/installation) `@piplup/rhf-adapters/mui-one-time-password-input` connects `mui-one-time-password-input` components to `react-hook-form`. npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package together with the MUI Material and mui-one-time-password-input peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-one-time-password-input ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-one-time-password-input ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-one-time-password-input ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-one-time-password-input ``` ## Import [#import] ```tsx import { MuiOtpInputElement, useMuiOtpInputAdapter } from "@piplup/rhf-adapters/mui-one-time-password-input"; ``` Use `/mui-one-time-password-input` subpath when you need `mui-one-time-password-input` components to stay in sync with `react-hook-form`. ## See also [#see-also] * [mui-one-time-password-input](https://viclafouch.github.io/mui-otp-input/) # Installation — @piplup/rhf-adapters (mui-tel-input) (/docs/rhf-adapters/mui-tel-input/installation) `@piplup/rhf-adapters/mui-tel-input` connects `mui-tel-input` components to `react-hook-form`. npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then, install the adapters package together with the MUI Material and mui-tel-input peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-tel-input ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-tel-input ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-tel-input ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers mui-tel-input ``` ## Import [#import] ```tsx import { MuiTelInputElement, useMuiTelInputAdapter } from "@piplup/rhf-adapters/mui-tel-input"; ``` Use `/mui-tel-input` subpath when you need `mui-tel-input` components to stay in sync with `react-hook-form`. ## See also [#see-also] * [mui-tel-input](https://viclafouch.github.io/mui-tel-input/) # Installation — @piplup/rhf-adapters (@mui/x-date-pickers) (/docs/rhf-adapters/mui-x-date-pickers/installation) `@piplup/rhf-adapters/mui-x-date-pickers` provides pre-integrated MUI X Date Picker components and adapter hooks for React Hook Form. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then install the adapters package together with the MUI Material and MUI X Date Pickers peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled @mui/x-date-pickers ``` Additionally, install the date library of your choice for MUI X Date Pickers npm pnpm yarn bun ```bash npm install dayjs ``` ```bash pnpm add dayjs ``` ```bash yarn add dayjs ``` ```bash bun add dayjs ``` npm pnpm yarn bun ```bash npm install date-fns ``` ```bash pnpm add date-fns ``` ```bash yarn add date-fns ``` ```bash bun add date-fns ``` npm pnpm yarn bun ```bash npm install luxon ``` ```bash pnpm add luxon ``` ```bash yarn add luxon ``` ```bash bun add luxon ``` npm pnpm yarn bun ```bash npm install moment ``` ```bash pnpm add moment ``` ```bash yarn add moment ``` ```bash bun add moment ``` ## Import [#import] ```tsx import { MuiXDatePickerElement, useMuiXDatePickerAdapter, } from "@piplup/rhf-adapters/mui-x-date-pickers"; ``` Use `/mui-x-date-pickers` subpath when you want MUI X Date Pickers components to participate in form state, validation, helper text composition, and `react-hook-form` controlled value handling without writing the wiring yourself. ## See also [#see-also] * [Components](./components/mui-x-date-calendar-element) * [Hooks](./hooks/use-mui-x-date-calendar-adapter) * [MUI X Date Pickers - QuickStart](https://mui.com/x/react-date-pickers/quickstart/) # Installation — @piplup/rhf-adapters (react-number-format) (/docs/rhf-adapters/react-number-format/installation) `@piplup/rhf-adapters/react-number-format` provides adapters for `react-number-format` inputs that need `react-hook-form` controlled value handling. First, install the core packages, if not installed already: npm pnpm yarn bun ```bash npm install @piplup/rhf-core react-hook-form ``` ```bash pnpm add @piplup/rhf-core react-hook-form ``` ```bash yarn add @piplup/rhf-core react-hook-form ``` ```bash bun add @piplup/rhf-core react-hook-form ``` Then install the adapters package together with the MUI Material and `react-number-format` peer dependencies: npm pnpm yarn bun ```bash npm install @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled react-number-format ``` ```bash pnpm add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled react-number-format ``` ```bash yarn add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled react-number-format ``` ```bash bun add @piplup/rhf-adapters @mui/material @emotion/react @emotion/styled react-number-format ``` ## Import [#import] ```tsx import { NumericFormatElement, useNumericFormatAdapter } from "@piplup/rhf-adapters/react-number-format"; ``` Use `/react-number-format` subpath when you need `react-number-format` components to stay in sync with `react-hook-form`. ## See also [#see-also] * [React Number Format](https://s-yadav.github.io/react-number-format/docs/intro/) # FormContainer (/docs/rhf-core/components/form-container) ## Import [#import] ```tsx import { FormContainer } from "@piplup/rhf-core"; ``` ## Usage [#usage] Basic usage with `FormContainer`. It accepts the same options you would normally pass to `useForm` (for example: `defaultValues`, `resolver`, etc.) and handles form registration and submission wiring for you. ## Props [#props] `FormContainer` forwards refs to the underlying `
` element and exposes the `onSubmit` prop for reading the submitted form data. ## Notes [#notes] * Use `useFormContext()` inside nested components to access `register`, `watch`, `setValue`, etc. * You can pass any options accepted by `useForm` directly to `FormContainer` or `formContext` returned by `useForm` hook. * Because `FormContainer` renders a native `` with `noValidate` prop, therefore, browser-level validations are ignored unless explicitly enabled. ## See also [#see-also] Custom hook for managing forms with ease. Hook to access form context values in nested components. # FormErrorProvider (/docs/rhf-core/components/form-error-provider) ## Import [#import] ```tsx import { FormErrorProvider } from "@piplup/rhf-core"; ``` ## Usage [#usage] Wrap your form with `FormErrorProvider`. Provide an `errorParser` function to translate raw error objects into user-friendly messages, or rely on default behavior. ## Props [#props] ## Patterns [#patterns] * **Global mapping:** Use a single `errorParser` at the app root to ensure consistent copy and localization. * **Field-level overrides:** Components can still render custom error messages when they need special phrasing. * **i18n:** Combine `errorParser` with your localization system to return translated messages. ## Notes [#notes] * `FormErrorProvider` does not replace form validation — it only maps and exposes error messages for rendering. * `FormContainer` is pre-configured with `FormErrorProvider`, so you can directly use `errorParser` prop without wrapping with another FormErrorProvider. # useControllerAdapter (/docs/rhf-core/hooks/use-controller-adapter) `useControllerAdapter` is one of the main adapter building hook. It wraps React Hook Form's `useController` and returns an object for custom input components, including `value`, `onChange`, `onBlur`, `ref`, validation rules, helper text, and composed disabled or error state. Use it when you are building an input-like component that needs both field binding and UI state in one place. If you only need field state for surrounding UI, `useFieldStateAdapter` is usually a better fit. ## Import [#import] ```tsx import { useControllerAdapter } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] ## Return value [#return-value] ## Notes [#notes] * `transform.input` changes the value your component receives, while `transform.output` changes what gets stored in the form. ## See also [#see-also] * [useController](https://react-hook-form.com/docs/usecontroller) * [useFieldStateAdapter](./use-field-state-adapter) # useFieldStateAdapter (/docs/rhf-core/hooks/use-field-state-adapter) `useFieldStateAdapter` is a lightweight adapter hook for components that need to react to a field's state without becoming the field input itself. It is useful for labels, helper text, wrappers, and other companion UI that should reflect validation or submission state. Unlike `useControllerAdapter`, this hook does not return `value`, `onChange`, or `onBlur`. It focuses only on presentation-oriented field state. ## Import [#import] ```tsx import { useFieldStateAdapter } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] ## Return value [#return-value] ## Notes [#notes] * Use this hook for field-adjacent UI, not for the interactive input element itself. * The hook reads state from a single field path and composes helper text from the current field error when available. * If your component also needs field value binding, switch to `useControllerAdapter`. ## See also [#see-also] * [useFieldState](./use-field-state) * [useControllerAdapter](./use-controller-adapter) # useFieldState (/docs/rhf-core/hooks/use-field-state) `useFieldState` is a low-level hook for reading the state of one field from the current form. It is helpful when you want to react to a field being invalid, touched, dirty, disabled, or currently validating, but you do not need the adapter props returned by `useFieldStateAdapter` or `useControllerAdapter`. The hook returns field-level state plus a few useful form-derived flags such as `disabled` and `isSubmitting`. ## Import [#import] ```tsx import { useFieldState } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] ## Return value [#return-value] ## Notes [#notes] * This hook is best when you want state only and plan to render your own UI from it. * It reads a single field path and does not provide input binding helpers such as `value` or `onChange`. * If you want helper text, class names, or style to be composed for you, use `useFieldStateAdapter` instead. ## See also [#see-also] * [useFieldStateAdapter](./use-field-state-adapter) * [useFormState](https://react-hook-form.com/docs/useformstate) # useFormReset (/docs/rhf-core/hooks/use-form-reset) `useFormReset` returns a `reset` function that behaves like the one returned by React Hook Form's `useForm`. It is useful when a nested component needs to reset the form without receiving the full form instance as a prop. If you do not pass a `control`, the hook reads it from form context, which makes it a good fit for components rendered inside `FormContainer` or `FormProvider`. ## Import [#import] ```tsx import { useFormReset } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] # Return value [#return-value] ## Passing values and options [#passing-values-and-options] The returned function accepts the same arguments as React Hook Form's `reset`: an optional values object and an optional reset options object. Reset to the current `defaultValues`: ```ts reset(); ``` Reset with new values: ```ts reset({ name: "" }); ``` Forward RHF reset options such as `keepDirty`: ```ts reset({}, { keepDirty: true, keepValues: false }); ``` ## Notes [#notes] * Pass `control` explicitly when you want to use the hook outside form context. * The returned function mirrors React Hook Form's `reset` behavior and supported options. ## See also [#see-also] * [reset](https://react-hook-form.com/docs/useform/reset) * [useFormContext](https://react-hook-form.com/docs/useformcontext) # useFormSetFocus (/docs/rhf-core/hooks/use-form-set-focus) `useFormSetFocus` returns a `setFocus` function for moving focus to a registered field. It is useful when buttons, error summaries, or other nested components need to focus a form field without receiving the full form instance as a prop. If you do not pass a `control`, the hook reads it from form context, which makes it easy to use inside `FormContainer` or `FormProvider`. ## Import [#import] ```tsx import { useFormSetFocus } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] ## Return value [#return-value] ## Notes [#notes] * Use this hook when nested components need focus control. * The returned function mirrors the familiar `react-hookf-form` `setFocus` API, including support for `shouldSelect`. * The field must be registered and backed by a focusable element for focus to succeed. ## See also [#see-also] * [setFocus](https://react-hook-form.com/docs/useform/setfocus) * [useFormContext](https://react-hook-form.com/docs/useformcontext) # useFormStateAdapter (/docs/rhf-core/hooks/use-form-state-adapter) `useFormStateAdapter` adapts React Hook Form's `useFormState` output into a UI-friendly object that can be consumed by form-level components. It is useful for submit buttons, banners, summaries, and other components that should react to overall form validity, submission state, or scoped errors. Compared with `useFieldStateAdapter`, this hook works from form state and optional field subscriptions rather than a single field's controller state. ## Import [#import] ```tsx import { useFormStateAdapter } from "@piplup/rhf-core"; ``` ## Usage [#usage] ## Props [#props] ## Return value [#return-value] ## Notes [#notes] * Use `name` when the component should react only to a subset of form fields. * `exact` matters when you want to avoid broader subscriptions for nested field paths. * This hook is a good fit for form-level UI, while `useFieldStateAdapter` is better for UI tied to one field. ## See also [#see-also] * [useFormState](https://react-hook-form.com/docs/useformstate) * [useFieldStateAdapter](./use-field-state-adapter) # Helpers Overview (/docs/utils/helpers/overview) ## compact [#compact] Removes `null`/`undefined` values from arrays. ```tsx import { compact } from "@piplup/utils"; const clean = compact([1, null, 2]); // [1,2] ``` ## execSequentially [#execsequentially] Run multiple functions in sequence producing a new function. ```tsx import { execSequentially } from "@piplup/utils"; const combined = execSequentially(fn1, fn2); combined(); ``` ## forkRef [#forkref] Utilities for combining multiple refs. ```tsx import { forkRef } from "@piplup/utils"; const ref = forkRef(refA, refB); ``` ## hasOwnProperty [#hasownproperty] Type-safe `hasOwnProperty` helper. ```ts import { hasOwnProperty } from "@piplup/utils"; if (hasOwnProperty(obj, 'key')) { /* ... */ } ``` ## setRef [#setref] Helper to set callback or mutable refs. ## Storage helpers: `getItem`, `setItem`, `removeItem` [#storage-helpers-getitem-setitem-removeitem] Small wrappers around `localStorage` access; use `useLocalStorage` hook for reactive state. # useEventCallback (/docs/utils/hooks/use-event-callback) ```tsx import { useEventCallback } from "@piplup/utils"; function Component() { const handle = useEventCallback((value: string) => { console.log(value); }); return ; } ``` ## Props [#props] ## Return value [#return-value] # useEventListener (/docs/utils/hooks/use-event-listener) ```tsx import { useEventListener } from "@piplup/utils"; function Component() { useEventListener('resize', () => { console.log('resized'); }); } ``` ## Signature [#signature] ```tsx import * as React from 'react'; export function useEventListener( eventName: EventName, handler: (event: MediaQueryListEventMap[EventName]) => void, element: React.RefObject, options?: AddEventListenerOptions | boolean ): void; export function useEventListener( eventName: EventName, handler: (event: WindowEventMap[EventName]) => void, element?: undefined, options?: AddEventListenerOptions | boolean ): void; export function useEventListener< EventName extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement >( eventName: EventName, handler: (event: HTMLElementEventMap[EventName]) => void, element: React.RefObject, options?: AddEventListenerOptions | boolean ): void; export function useEventListener( eventName: EventName, handler: (event: DocumentEventMap[EventName]) => void, element: React.RefObject, options?: AddEventListenerOptions | boolean ): void; export function useEventListener< EventName extends string, EventElement extends HTMLElement = HTMLDivElement >( eventName: EventName, handler: (event: Event) => void, element?: React.RefObject, options?: AddEventListenerOptions | boolean ): void; export function useEventListener< EventName extends string, EventNameWindow extends keyof WindowEventMap, EventNameHTMLElement extends keyof HTMLElementEventMap, EventNameMediaQuery extends keyof MediaQueryListEventMap, EventElement extends HTMLElement | MediaQueryList | void = void >( eventName: EventName | EventNameHTMLElement | EventNameMediaQuery | EventNameWindow, handler: ( event: | Event | HTMLElementEventMap[EventNameHTMLElement] | MediaQueryListEventMap[EventNameMediaQuery] | WindowEventMap[EventNameWindow] ) => void, element?: React.RefObject, options?: AddEventListenerOptions | boolean ): void; ``` ### Type parameters and overrides [#type-parameters-and-overrides] * `EventName`: union of allowed event string keys for the selected target (e.g. `keyof WindowEventMap` or `keyof HTMLElementEventMap`). * `T` / `EventElement`: when targeting an element, `T` (or `EventElement`) constrains the element/ref type (e.g. `HTMLButtonElement`). * `EventNameWindow`, `EventNameHTMLElement`, `EventNameMediaQuery`: internal helpers used by the broad overload that accepts any of the supported event maps. When you need to force a specific overload or narrow the handler/event types you can provide explicit generics. Examples: ```tsx // Narrow to an HTML element event (click on a button) useEventListener<'click', HTMLButtonElement>( 'click', (e) => { /* e is MouseEvent */ }, buttonRef ); // Window event (no element required) useEventListener<'resize'>( 'resize', (e) => { /* e is UIEvent */ } ); // MediaQueryList event useEventListener<'change'>( 'change', (e: MediaQueryListEvent) => { /* ... */ }, mediaQueryRef ); ``` These overloads allow the hook to infer the correct event type based on the chosen overload and optional explicit generic arguments. The final broad overload accepts any string event and falls back to `Event` when a more specific map does not apply. # useForkRef (/docs/utils/hooks/use-fork-ref) ```tsx import { useForkRef } from "@piplup/utils"; function Component({ externalRef }) { const localRef = React.useRef(null); const combined = useForkRef(localRef, externalRef); return
; } ``` ## Props [#props] ## Return value [#return-value] # useIsomorphicEffect (/docs/utils/hooks/use-isomorphic-effect) ```tsx import { useIsomorphicEffect } from "@piplup/utils"; function Component() { useIsomorphicEffect(() => { // runs like useLayoutEffect in client environments }, []); return null; } ``` ## Props [#props] # useLocalStorage (/docs/utils/hooks/use-local-storage) ```tsx import { useLocalStorage } from "@piplup/utils"; function Component() { const [value, setValue] = useLocalStorage('my-key', 'default'); return (
Value: {value}
); } ``` ## Props [#props] ## Return value [#return-value] # HtmlButtonElement (/docs/rhf-adapters/html/components/html-button-element) `HtmlButtonElement` is a native `