Package Exports
- hazo_collab_forms
- hazo_collab_forms/components
- hazo_collab_forms/lib
- hazo_collab_forms/utils
Readme
Hazo Collab Forms
React form components with integrated chat collaboration, built for Next.js with TypeScript and Tailwind CSS.
Features
- Integrated Chat Collaboration: Each form field supports real-time chat discussions
- Advanced Field Controls: Visibility toggle, lock/unlock, field duplication, and soft delete
- Role-Based UI: Author and responder roles for granular control over field interactions
- File Upload with Validation: Built-in file upload with custom validation callbacks
- Mandatory File Indicator: Visual indicators (red asterisk) for required file uploads
- Custom File Validators: Implement custom validation logic before file upload
- Form Sets: JSON-based dynamic form generation with full file upload support
- Type-Safe: Written in TypeScript with comprehensive type definitions
- Tailwind CSS Styling: Fully customizable with Tailwind CSS classes
- shadcn/ui Components: Built on top of accessible Radix UI primitives
Installation
Step 1: Install the Package
npm install hazo_collab_formsStep 2: Install Peer Dependencies
# Core React dependencies (skip if already installed)
npm install react react-dom
# UI dependencies
npm install react-icons sonner lucide-react
npm install @radix-ui/react-dialog @radix-ui/react-label
# Hazo ecosystem packages (required for chat functionality)
npm install hazo_chat hazo_ui hazo_auth hazo_configStep 3: Install shadcn/ui Components
This package requires shadcn/ui components. If you haven't initialized shadcn/ui yet:
npx shadcn@latest initThen install the required components:
# Core components (required for all form fields)
npx shadcn@latest add button label dialog tooltip sonner
# For HazoCollabFormCombo (dropdown/select)
npx shadcn@latest add popover command
# For HazoCollabFormDate (date picker)
npx shadcn@latest add calendar
# For file upload functionality (required when using accept_files prop)
npx shadcn@latest add accordion
# Optional but recommended
npx shadcn@latest add separator cardStep 4: Configure Next.js
Add to your next.config.js:
const nextConfig = {
transpilePackages: ['hazo_collab_forms'],
};
module.exports = nextConfig;Step 5: Configure Tailwind CSS
Add to tailwind.config.ts content array:
content: [
// ... your existing paths
"./node_modules/hazo_collab_forms/**/*.{js,ts,jsx,tsx}",
],Step 6: Create Config Files
Copy the template config files to your project root:
cp node_modules/hazo_collab_forms/templates/*.ini ./This creates:
hazo_collab_forms_config.ini- Main package confighazo_chat_config.ini- Chat functionality confighazo_auth_config.ini- Authentication config
Step 7: Verify Installation
npx hazo-collab-forms-verifyThis checks all dependencies, config files, and shadcn components are properly installed.
Quick Reference
One-Line Install (All Dependencies)
npm install hazo_collab_forms react react-dom react-icons sonner lucide-react \
@radix-ui/react-dialog @radix-ui/react-label hazo_chat hazo_ui hazo_auth hazo_configOne-Line shadcn Install (All Components)
npx shadcn@latest add button label dialog tooltip sonner popover command calendar accordion separator cardUsage
Basic Example
'use client';
import { HazoCollabFormInputbox } from 'hazo_collab_forms';
import { useState } from 'react';
export default function MyForm() {
const [value, setValue] = useState('');
return (
<HazoCollabFormInputbox
label="Your Name"
value={value}
onChange={setValue}
field_data_id="user-name"
field_name="User Name"
hazo_chat_receiver_user_id="recipient-user-id"
/>
);
}File Upload with Validation
'use client';
import { HazoCollabFormInputbox } from 'hazo_collab_forms';
import { useState } from 'react';
export default function DocumentUpload() {
const [value, setValue] = useState('');
return (
<HazoCollabFormInputbox
label="Invoice Upload"
value={value}
onChange={setValue}
accept_files={true}
files_dir="public/uploads"
min_files={1} // Shows red asterisk (mandatory indicator)
max_files={5}
file_accept=".pdf"
file_validator={(file) => {
// Custom validation - filename pattern check
if (!file.name.match(/^INV-\d{4}\.pdf$/i)) {
return 'File name must match pattern: INV-0000.pdf';
}
// Size check (5MB limit)
if (file.size > 5 * 1024 * 1024) {
return 'File size must be under 5MB';
}
return null; // Accept file
}}
/>
);
}Advanced Field Control Icons
The package exports standalone control icons for building custom form workflows:
'use client';
import {
HazoCollabFormInputbox,
CollabFormVisibilityIcon,
CollabFormLockIcon,
CollabFormAddEntryIcon,
CollabFormDeleteEntryIcon,
CollabFormDeleteFieldIcon,
} from 'hazo_collab_forms';
import { useState } from 'react';
export default function AdvancedForm() {
const [value, setValue] = useState('');
const [visibility, setVisibility] = useState<'visible' | 'hidden'>('visible');
const [locked, setLocked] = useState(false);
return (
<div>
{/* Visibility Toggle - author role only */}
<CollabFormVisibilityIcon
label="Company Name"
visibility={visibility}
on_visibility_change={setVisibility}
user_role="author"
/>
{/* Lock/Unlock Field - author role only */}
<CollabFormLockIcon
label="Company Name"
locked={locked}
on_lock_change={setLocked}
user_role="author"
/>
{/* Add Entry - duplicate field */}
<CollabFormAddEntryIcon
label="Contact Person"
field_id="contact_person"
on_add_entry={(field_id) => console.log('Add entry:', field_id)}
/>
{/* Delete Entry - remove duplicated field */}
<CollabFormDeleteEntryIcon
label="Contact Person"
field_id="contact_person_2"
on_delete_entry={(field_id) => console.log('Delete entry:', field_id)}
/>
{/* Delete Field - soft delete - author role only */}
<CollabFormDeleteFieldIcon
label="Optional Field"
field_id="optional_field"
on_delete={(field_id) => console.log('Delete field:', field_id)}
user_role="author"
/>
</div>
);
}Icon Components:
| Icon Component | Description | User Role Restriction |
|---|---|---|
CollabFormVisibilityIcon |
Toggle field visibility (show/hide) | Author only |
CollabFormLockIcon |
Toggle field lock (read-only mode) | Author only |
CollabFormAddEntryIcon |
Duplicate a field entry | None |
CollabFormDeleteEntryIcon |
Remove a duplicated entry | None |
CollabFormDeleteFieldIcon |
Soft delete a field | Author only |
Role-Based Rendering:
- Icons marked "Author only" render only when
user_role="author"is passed - Default
user_roleis"responder", which hides author-only controls - This allows the same component to behave differently for form authors vs. responders
Field-Level Controls in HazoCollabFormSet
When using HazoCollabFormSet with JSON-based field definitions, you can configure lock, visibility, and delete controls at the field level. This allows different fields to have different controls.
Cascade Priority:
- Field-level
FieldConfigproperties → overrides form-level defaults - Form-level
HazoCollabFormSetProps→ applies to all fields - Hardcoded fallback →
false(disabled)
'use client';
import { HazoCollabFormSet, FieldConfig } from 'hazo_collab_forms';
const fields: FieldConfig[] = [
{
id: "customer_name",
label: "Customer Name",
field_type: "field",
component_type: "HazoCollabFormInputbox",
value: "",
// Uses form-level defaults
},
{
id: "tax_file_number",
label: "Tax File Number",
field_type: "field",
component_type: "HazoCollabFormInputbox",
value: "",
enable_lock: true,
enable_visibility_toggle: true, // Field-level override
enable_delete: false
},
{
id: "internal_notes",
label: "Internal Notes",
field_type: "field",
component_type: "HazoCollabFormTextArea",
value: "",
enable_lock: false, // Hide lock on this field
enable_visibility_toggle: true,
enable_delete: true // Show delete on this field
}
];
export default function CustomerForm() {
return (
<HazoCollabFormSet
fields_set={{ name: "Customer Form", fields }}
user_role="author"
enable_lock={true} // Default for all fields
enable_visibility_toggle={false} // Default for all fields
enable_delete={false} // Default for all fields
/>
);
}Available FieldConfig Control Properties:
enable_lock?: boolean- Show lock iconenable_visibility_toggle?: boolean- Show visibility toggle iconenable_delete?: boolean- Show delete iconlocked?: boolean- Initial lock statevisibility?: 'visible' | 'hidden'- Initial visibility state
Components
| Component | Description | Required shadcn |
|---|---|---|
HazoCollabFormInputbox |
Text input with validation | button, label, dialog |
HazoCollabFormTextArea |
Multi-line text input | button, label, dialog |
HazoCollabFormCheckbox |
Boolean toggle | button, label, dialog |
HazoCollabFormCombo |
Dropdown select with search | + popover, command |
HazoCollabFormRadio |
Radio button group | button, label, dialog |
HazoCollabFormDate |
Date or date-range picker | + calendar |
HazoCollabFormGroup |
Field grouping container | button, label, dialog |
HazoCollabFormSet |
Complete form with field arrays | all components |
| File Upload | When using accept_files prop |
+ accordion (required) |
Import Paths
// Default: All client-safe components and utilities
import { HazoCollabFormInputbox, cn } from 'hazo_collab_forms';
// Components only
import { HazoCollabFormInputbox } from 'hazo_collab_forms/components';
// Utilities only
import { cn, use_collab_chat } from 'hazo_collab_forms/utils';
// Server-only (config functions)
import { get_config } from 'hazo_collab_forms/lib';Troubleshooting
lucide-react Version Conflicts
Different Hazo packages require different versions of lucide-react. Add this to your package.json:
"overrides": {
"lucide-react": "^0.553.0"
}Missing shadcn Components
If you see errors about missing components, install the specific shadcn component:
npx shadcn@latest add [component-name]Important: If you're using file upload functionality (accept_files prop on any form field), you must install the accordion component:
npx shadcn@latest add accordionVerify Your Setup
Run the verification tool to check for common issues:
npx hazo-collab-forms-verifySee SETUP_CHECKLIST.md for detailed troubleshooting.
Development
Package Structure
- Root: ES module npm package
- test-app: Next.js application for testing
Commands
npm run build # Build the package
npm run dev:package # Watch mode for development
npm run dev:test-app # Build and run test app
npm run build:test-app # Build for production
npm run clean # Remove dist directoryTypeScript Configuration
tsconfig.json: Development (bundler module resolution)tsconfig.build.json: Build (Node16 for ES module output)
ES Module Exports
All exports use explicit .js extensions as required for ES modules:
export * from './lib/index.js';
export * from './components/index.js';License
MIT