Production‑ready React Hook Form (RHF) field components built on Semantic UI React. Quickly wire up common inputs — phone, date/time, date ranges, numeric, JSON editor, WYSIWYG, sort, menus — with consistent error handling and semantics that match RHF and Semantic UI.
Highlights
Contents
Core peer dependencies (always install in your app)
npm i @karmaniverous/hook-form-semantic react react-dom react-hook-form semantic-ui-react semantic-ui-css
Install peers per component you use
# Phone + Numeric + Date
npm i react-international-phone google-libphonenumber react-responsive react-number-format react-date-picker react-datetime-picker react-calendar react-clock
# Date range
npm i @wojtekmaj/react-daterange-picker @wojtekmaj/react-datetimerange-picker react-calendar react-clock
# WYSIWYG
npm i react-draft-wysiwyg draft-js html-to-draftjs draftjs-to-html
# JSON editor
npm i vanilla-jsoneditor
# RRStack
npm i @karmaniverous/rrstack
ESM only
Add the relevant styles (typically once in your app entry):
import 'semantic-ui-css/semantic.min.css';
// Date/time + calendar
import 'react-date-picker/dist/DatePicker.css';
import 'react-datetime-picker/dist/DateTimePicker.css';
import 'react-calendar/dist/Calendar.css';
import 'react-clock/dist/Clock.css';
// Date range pickers
import '@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css';
import '@wojtekmaj/react-datetimerange-picker/dist/DateTimeRangePicker.css';
// WYSIWYG
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
// JSON editor (theme optional)
import 'vanilla-jsoneditor/themes/jse-theme-dark.css';
Only import the styles for components you actually use.
import { useForm } from 'react-hook-form';
import { Input } from 'semantic-ui-react';
import {
HookFormField,
HookFormPhone,
HookFormDatePicker,
} from '@karmaniverous/hook-form-semantic';
type FormData = { name: string; phone: string; birthDate: Date | null };
export default function Example() {
const { control, handleSubmit } = useForm<FormData>({
defaultValues: { name: '', phone: '', birthDate: null },
});
return (
<form onSubmit={handleSubmit(console.log)}>
<HookFormField<FormData, { value: string }>
control={Input}
hookControl={control}
hookName="name"
label="Name"
placeholder="Your name"
/>
<HookFormPhone<FormData>
hookControl={control}
hookName="phone"
label="Phone"
phoneDefaultCountry="us"
/>
<HookFormDatePicker<FormData>
hookControl={control}
hookName="birthDate"
label="Birth date"
/>
<button type="submit">Submit</button>
</form>
);
}
All components use RHF Controller wiring and propagate Semantic UI‑style errors. Pass Semantic UI props via the component’s prefixed prop groups (e.g., menu*
, dropdown*
) or directly where noted.
control={Input}
for simple cases or function‑as‑child for custom mapping.<HookFormField<MyForm, { checked: boolean }>
hookControl={control}
hookName="subscribed"
label="Subscribed"
>
{(field) => (
<input
type="checkbox"
checked={!!(field as { checked?: boolean }).checked}
onChange={(e) => field.onChange(e, { checked: e.currentTarget.checked })}
/>
)}
</HookFormField>
<HookFormNumeric<MyForm>
hookControl={control}
hookName="age"
label="Age"
numericAllowNegative={false}
numericDecimalScale={0}
/>
<HookFormPhone<MyForm>
hookControl={control}
hookName="phone"
label="Phone"
phoneDefaultCountry="us"
/>
<HookFormDatePicker<MyForm>
hookControl={control}
hookName="birthDate"
label="Birth date"
/>
defaultPresets
, filterPresets
, extractTimestamps
.import {
HookFormDateRangePicker,
defaultPresets,
filterPresets,
} from '@karmaniverous/hook-form-semantic';
<HookFormDateRangePicker<MyForm>
hookControl={control}
hookName="range"
label="Range"
presets={filterPresets(['past', 'present'], defaultPresets)}
/>;
<HookFormMenuDisplayMode<MyForm> hookControl={control} hookName="mode" />
[field, ascending]
tuple semantics.<HookFormSort<MyForm>
hookControl={control}
hookName="sort"
label="Sort"
dropdownOptions={[
{ key: 'name', text: 'Name', value: 'name' },
{ key: 'date', text: 'Date Created', value: 'date' },
]}
/>
<HookFormWysiwygEditor<MyForm>
hookControl={control}
hookName="content"
label="Content"
/>
<HookFormJsonEditor<MyForm>
hookControl={control}
hookName="jsonData"
label="JSON"
/>
A Vite playground is included for quick browser testing with HMR.
npm run dev # http://localhost:5173
npm run preview # production preview
The playground imports components directly from src/
(no publish needed). See playground/src/App.tsx
.
Vitest + Testing Library + jest-dom in a happy-dom environment.
npm run test # run once with coverage (v8)
npm run test:watch # watch mode
npm run test:ui # Vitest UI
npm run build # ESM modules to dist/mjs + types to dist/index.d.ts
Externalized peer deps: react
, react-dom
, react/jsx-runtime
, and others listed in package.json (install in your app).
Optional release automation (release‑it) is configured. See scripts in package.json.
npm run docs
Outputs static docs in docs/
(config in typedoc.json
). Hosted docs: docs.karmanivero.us/hook-form-semantic
Built for you with ❤️ on Bali! Find more great tools & templates on my GitHub Profile.