No description
Find a file
autocommit 4d3249c71c
Some checks failed
Publish / publish (push) Failing after 0s
deps-upgrade(deps): ⬆️ Update dependencies to latest versions for bug fixes and security patches
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-10 21:22:23 -07:00
.forgejo/workflows chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
src chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
.gitignore chore: add .gitignore, remove node_modules/dist/.turbo from tracking 2026-04-20 01:13:11 -07:00
eslint.config.js chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
package.json deps-upgrade(deps): ⬆️ Update dependencies to latest versions for bug fixes and security patches 2026-06-10 21:22:23 -07:00
README.md chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
tsconfig.json chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
vitest-setup.ts chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00
vitest.config.ts chore: initial package split from monorepo 2026-04-20 01:11:31 -07:00

@lilith/ui-forms

Complex form components for multi-step forms, date pickers, color pickers, phone inputs, and other advanced form elements.

Features

  • Multi-step forms with progress indicators and validation
  • Date and DateTime pickers with min/max constraints
  • Range sliders with customizable tracks
  • Color picker with preset colors and custom input
  • Phone input with country code selection
  • Address input with structured fields
  • Tag input for managing lists of tags
  • Searchable multi-select dropdowns
  • Dynamic field arrays for repeatable form sections
  • Conditional fields that show/hide based on form state
  • Theme-aware styling using styled-components

Installation

pnpm add @lilith/ui-forms

Peer Dependencies

{
  "react": "^18.0.0",
  "react-dom": "^18.0.0",
  "styled-components": "^6.0.0"
}

Usage

MultiStepForm

Create wizard-style forms with validation per step:

import { MultiStepForm, type FormStep } from '@lilith/ui-forms';

const steps: FormStep[] = [
  {
    id: 'personal',
    label: 'Personal Info',
    component: <PersonalInfoStep />,
    validate: () => validatePersonalInfo(),
  },
  {
    id: 'address',
    label: 'Address',
    component: <AddressStep />,
    validate: () => validateAddress(),
  },
  {
    id: 'confirmation',
    label: 'Confirm',
    component: <ConfirmationStep />,
  },
];

function RegistrationForm() {
  return (
    <MultiStepForm
      steps={steps}
      onComplete={() => handleSubmit()}
      onCancel={() => handleCancel()}
      showProgress={true}
    />
  );
}

DatePicker

import { DatePicker } from '@lilith/ui-forms';

function DateForm() {
  const [date, setDate] = useState<Date | null>(null);

  return (
    <DatePicker
      value={date}
      onChange={setDate}
      min={new Date('2024-01-01')}
      max={new Date('2024-12-31')}
      placeholder="Select date"
    />
  );
}

DateTimePicker

import { DateTimePicker } from '@lilith/ui-forms';

function EventForm() {
  const [dateTime, setDateTime] = useState<Date | null>(null);

  return (
    <DateTimePicker
      value={dateTime}
      onChange={setDateTime}
      placeholder="Select date and time"
    />
  );
}

RangeSlider

import { RangeSlider } from '@lilith/ui-forms';

function PriceFilter() {
  const [range, setRange] = useState({ min: 0, max: 100 });

  return (
    <RangeSlider
      min={0}
      max={500}
      value={range}
      onChange={setRange}
      step={10}
    />
  );
}

ColorPicker

import { ColorPicker } from '@lilith/ui-forms';

function ThemeEditor() {
  const [color, setColor] = useState('#3b82f6');

  return (
    <ColorPicker
      value={color}
      onChange={setColor}
    />
  );
}

PhoneInput

import { PhoneInput } from '@lilith/ui-forms';

function ContactForm() {
  const [phone, setPhone] = useState('');

  return (
    <PhoneInput
      value={phone}
      onChange={setPhone}
      defaultCountry="US"
    />
  );
}

AddressInput

import { AddressInput, type Address } from '@lilith/ui-forms';

function ShippingForm() {
  const [address, setAddress] = useState<Address>({
    street: '',
    city: '',
    state: '',
    zipCode: '',
    country: '',
  });

  return (
    <AddressInput
      value={address}
      onChange={setAddress}
    />
  );
}

TagInput

import { TagInput } from '@lilith/ui-forms';

function SkillsForm() {
  const [tags, setTags] = useState<string[]>(['react', 'typescript']);

  return (
    <TagInput
      value={tags}
      onChange={setTags}
      placeholder="Add a skill..."
    />
  );
}

SearchableMultiSelect

import { SearchableMultiSelect, type SearchableSelectOption } from '@lilith/ui-forms';

const options: SearchableSelectOption[] = [
  { value: 'react', label: 'React' },
  { value: 'vue', label: 'Vue' },
  { value: 'angular', label: 'Angular' },
];

function TechStackForm() {
  const [selected, setSelected] = useState<string[]>([]);

  return (
    <SearchableMultiSelect
      options={options}
      value={selected}
      onChange={setSelected}
      placeholder="Search frameworks..."
    />
  );
}

DynamicFieldArray

import { DynamicFieldArray } from '@lilith/ui-forms';

function TeamForm() {
  const [members, setMembers] = useState([{ name: '', role: '' }]);

  return (
    <DynamicFieldArray
      value={members}
      onChange={setMembers}
      renderField={(item, index, onChange) => (
        <div>
          <input
            value={item.name}
            onChange={(e) => onChange({ ...item, name: e.target.value })}
          />
        </div>
      )}
      addButtonLabel="Add Member"
    />
  );
}

ConditionalFields

import { ConditionalFields } from '@lilith/ui-forms';

function SurveyForm() {
  const [hasOther, setHasOther] = useState(false);

  return (
    <>
      <Checkbox checked={hasOther} onChange={setHasOther} label="Other" />
      <ConditionalFields show={hasOther}>
        <Input placeholder="Please specify..." />
      </ConditionalFields>
    </>
  );
}

FormField

Generic form field component with icon support:

import { FormField, getFieldIcon } from '@lilith/ui-forms';

function DynamicForm() {
  return (
    <FormField
      type="email"
      label="Email Address"
      name="email"
      required
    />
  );
}

LabeledSlider & WeightSlider

import { LabeledSlider, WeightSlider } from '@lilith/ui-forms';

function PreferencesForm() {
  const [volume, setVolume] = useState(50);
  const [weight, setWeight] = useState(1.0);

  return (
    <>
      <LabeledSlider
        label="Volume"
        value={volume}
        onChange={setVolume}
        min={0}
        max={100}
      />
      <WeightSlider
        label="Priority Weight"
        value={weight}
        onChange={setWeight}
        min={0}
        max={2}
        step={0.1}
      />
    </>
  );
}

API Reference

MultiStepFormProps

Prop Type Default Description
steps FormStep[] required Array of form steps
onComplete () => void | Promise<void> required Called when form is completed
onCancel () => void - Called when cancel button is clicked
showProgress boolean true Show progress bar

FormStep

Prop Type Description
id string Unique step identifier
label string Step label shown in progress bar
component ReactNode Step content
validate () => boolean | Promise<boolean> Optional validation function

DatePickerProps

Prop Type Default Description
value Date | null required Selected date
onChange (date: Date | null) => void required Change handler
min Date - Minimum selectable date
max Date - Maximum selectable date
disabled boolean false Disable input
placeholder string 'Select date' Placeholder text

AddressInputProps

Prop Type Description
value Address Current address value
onChange (address: Address) => void Change handler

Address

interface Address {
  street: string;
  city: string;
  state: string;
  zipCode: string;
  country: string;
}

Types

All component props and types are exported:

import type {
  FormStep,
  MultiStepFormProps,
  DatePickerProps,
  DateTimePickerProps,
  RangeSliderProps,
  ColorPickerProps,
  PhoneInputProps,
  AddressInputProps,
  Address,
  TagInputProps,
  SearchableMultiSelectProps,
  SearchableSelectOption,
  DynamicFieldArrayProps,
  ConditionalFieldsProps,
  FormFieldProps,
  FormFieldConfig,
  FormFieldOption,
  LabeledSliderProps,
  WeightSliderProps,
  StepIndicatorProps,
} from '@lilith/ui-forms';

License

MIT