Skip to content

Repository files navigation

@pulsar-framework/formular-ui

Enterprise-grade form components for Pulsar framework integrated with formular.dev

VersionLicense

A comprehensive, type-safe form component library that seamlessly combines Pulsar framework's reactive architecture with formular.dev form management capabilities.

✨ Features

  • 🎯 Type-Safe - Full TypeScript support with generics
  • Reactive - Built on Pulsar's fine-grained reactivity
  • 📋 Declarative - Define forms with simple configuration objects
  • Validation - Integrated with formular.dev validation presets
  • 🎨 Styled - Pre-styled with Tailwind CSS
  • 🔌 Context-Based - Access form state anywhere in your component tree
  • 🚪 Portal System - Flexible command button placement
  • Accessible - WCAG 2.1 compliant components
  • 📖 Documented - Comprehensive Storybook stories

📦 Installation

# Using pnpm (recommended)
pnpm add @pulsar-framework/formular-ui
# Using npm
npm install @pulsar-framework/formular-ui
# Using yarn
yarn add @pulsar-framework/formular-ui

🚀 Quick Start

1. Basic Form Example

import{bootstrapApp,AppContextProvider}from'pulsar';import{FormProvider,TextField,Checkbox,useFieldDescriptors,}from'@pulsar-framework/formular-ui';import{createMockFormular}from'@pulsar-framework/formular-ui/helpers';// Define your data interfaceinterfaceLoginData{email: string;password: string;rememberMe: boolean;}// Create your form componentconstLoginForm=()=>{// 1. Define field descriptorsconstfields=useFieldDescriptors<LoginData>({email: {type: 'email',label: 'Email Address',placeholder: 'you@example.com',},password: {type: 'password',label: 'Password',placeholder: '••••••••',},rememberMe: {type: 'checkbox',label: 'Remember me',},});// 2. Create form instanceconstform=createMockFormular('loginForm',fields);// 3. Define handlersconsthandleSave=()=>{constdata=form.getData();console.log('Login data:',data);// Send to API...};consthandleQuit=()=>{form.reset();};// 4. Render with FormProviderreturn(<FormProviderform={form}onSaveCallback={handleSave}onQuitCallback={handleQuit}><divclass="space-y-4"><TextFieldname="email"showLabel={true}showErrors={true}/><TextFieldname="password"showLabel={true}showErrors={true}/><Checkboxname="rememberMe"/></div></FormProvider>);};// Bootstrap your appconstappRoot=bootstrapApp().root('#app').onMount((el)=>console.log('Mounted',el)).build();constapp=(<AppContextProviderroot={appRoot}context={{appName: 'My App'}}><LoginForm/></AppContextProvider>);document.getElementById('app')?.appendChild(app);

2. Form with Validation

import{ValidationPresets}from'formular.dev';import{useFieldDescriptors}from'@pulsar-framework/formular-ui';interfaceUserData{username: string;email: string;age: number;}constfields=useFieldDescriptors<UserData>({username: {type: 'text',label: 'Username',validation: ValidationPresets.username(true),// true = requiredplaceholder: 'Enter username',},email: {type: 'email',label: 'Email',validation: ValidationPresets.email(true),// true = requiredplaceholder: 'you@example.com',},age: {type: 'number',label: 'Age',validation: ValidationPresets.minValue(18),// Minimum age validation},});

3. All Available Components

import{// Form ManagementFormProvider,useFormContext,useFieldDescriptors,// Input ComponentsTextField,// Text, email, password, number inputsTextareaInput,// Multi-line textCheckbox,// Single checkboxToggle,// Toggle switchSelectInput,// Dropdown selectRadioGroup,// Radio button group// Portal SystemPortal,PortalSlot,// UtilitiescreateMockFormular,}from'@pulsar-framework/formular-ui';

📚 Component API

FormProvider

Wraps your form and provides context to all child components.

Props:

  • form: IFormularBuilder - Formular instance (required)
  • data?: T - Initial form data
  • onSaveCallback?: () => void - Called when save button clicked
  • onQuitCallback?: () => void - Called when quit button clicked
  • children: HTMLElement | (() => HTMLElement) - Form fields

Example:

<FormProviderform={form}onSaveCallback={handleSave}>{/* Your form fields */}</FormProvider>

TextField

Text input with label, validation, and error display.

Props:

  • name: string - Field name (required)
  • showLabel?: boolean - Show field label (default: false)
  • showErrors?: boolean - Show validation errors (default: false)
  • showGuides?: boolean - Show helper text (default: false)
  • placeholder?: string - Input placeholder

Example:

<TextFieldname="email"showLabel={true}showErrors={true}showGuides={true}placeholder="Enter your email"/>

Checkbox

Checkbox with label and error display.

Props:

  • name: string - Field name (required)

Example:

<Checkboxname="agreeToTerms"/>

SelectInput

Dropdown select with label and validation.

Props:

  • name: string - Field name (required)
  • showLabel?: boolean - Show field label (default: false)
  • showErrors?: boolean - Show validation errors (default: false)
  • showGuides?: boolean - Show helper text (default: false)

Example:

<SelectInputname="country"showLabel={true}showErrors={true}/>

RadioGroup

Radio button group with auto-rendered options.

Props:

  • name: string - Field name (required)
  • showLabel?: boolean - Show field label (default: false)
  • showErrors?: boolean - Show validation errors (default: false)

Example:

<RadioGroupname="gender"showLabel={true}/>

TextareaInput

Multi-line text input with label and validation.

Props:

  • name: string - Field name (required)
  • showLabel?: boolean - Show field label (default: false)
  • showErrors?: boolean - Show validation errors (default: false)
  • showGuides?: boolean - Show helper text (default: false)
  • rows?: number - Number of visible rows (default: 4)

Example:

<TextareaInputname="bio"showLabel={true}rows={6}/>

Toggle

Toggle switch with label.

Props:

  • name: string - Field name (required)

Example:

<Togglename="notifications"/>

🔧 Advanced Usage

Accessing Form Context

Use useFormContext() to access form state anywhere in your component tree:

import{useFormContext}from'@pulsar-framework/formular-ui';constCustomComponent=()=>{const{ form, updateField, validateField }=useFormContext();consthandleCustomAction=()=>{constcurrentValue=form.getFieldValue('email');updateField('email','new@email.com');validateField('email');};return<buttononClick={handleCustomAction}>Update Email</button>;};

Portal System for Flexible Layouts

Place form command buttons anywhere in your UI:

import{Portal,PortalSlot}from'@pulsar-framework/formular-ui';constMyApp=()=>{return(<div><header>{/* Portal target in header */}<PortalSlotid="myForm"name="commands"/></header><FormProviderform={form}><TextFieldname="title"/>{/* Buttons render in header, not here! */}<Portalid={form.id}target="commands"><buttononClick={handleSave}>Save</button><buttononClick={handleCancel}>Cancel</button></Portal></FormProvider></div>);};

Custom Validation

import{IFieldDescriptor}from'formular.dev';constcustomEmailValidator=(value: string): string|null=>{if(!value.endsWith('@company.com')){return'Must be a company email address';}returnnull;};constfields=useFieldDescriptors<UserData>({email: {type: 'email',validation: customEmailValidator,},});

🎨 Styling

Components use Tailwind CSS. You can:

  1. Use default styles - Components work out-of-the-box with Tailwind
  2. Customize via Tailwind config - Override colors, spacing, etc.
  3. Add custom classes - Pass className props to components
// Add Tailwind CDN to your HTML<scriptsrc="https://cdn.tailwindcss.com"></script>// Or install Tailwind in your projectpnpmadd-Dtailwindcsspostcssautoprefixer

📖 Documentation

Storybook

Explore all components interactively:

cd packages/pulsar-formular-ui
pnpm storybook

Browse to http://localhost:6007

Demo Application

Run the demo app:

pnpm dev

Browse to http://localhost:3000

See src/demo.tsx for the complete implementation.

🏗️ Architecture

@pulsar-framework/formular-ui
├── src/
│ ├── components/
│ │ ├── form-provider/ # FormProvider component
│ │ ├── form-context/ # Form context and hooks
│ │ ├── integrated/ # Full-featured components
│ │ ├── primitives/ # Basic field bindings
│ │ ├── portal/ # Portal system
│ │ └── modal/ # Modal dialogs
│ ├── types/ # TypeScript interfaces
│ ├── utils/ # Utility functions and hooks
│ ├── stories/ # Storybook stories
│ └── demo.tsx # Demo application

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide.

📄 License

MIT © Tadeo Piana

🔗 Links

📝 Changelog

See CHANGELOG.md for version history.


Need Help?

About

formular.dev pulsar ui dedicated forms components

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages