npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hazo_collab_forms

v1.6.15

Published

Collaboration form elements

Downloads

3,497

Readme

Hazo Collab Forms

npm version License: MIT

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 via HazoChat
  • Read-Only Summary Views: Display form data in summary format with HazoCollabFormSummary component
  • Advanced Field Controls: Visibility toggle, lock/unlock, field duplication, soft delete, and notes
  • Notes Integration: Database-backed notes on fields via hazo_notes package (optional)
  • Prop-Based Controls: Enable/disable features via enable_* props for full control
  • 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
  • Data OK Workflows: Checkbox and multi-state validation with auto-hide/auto-lock features
  • Hidden States: Restrict available data OK states per field or form (e.g., hide "Pending" for agents)
  • 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_forms

Step 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 and notes functionality)
npm install hazo_chat hazo_ui hazo_auth hazo_config hazo_notes

Step 3: Install shadcn/ui Components

This package requires shadcn/ui components. If you haven't initialized shadcn/ui yet:

npx shadcn@latest init

Then 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 card

Step 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:

mkdir -p config
cp node_modules/hazo_collab_forms/templates/config/hazo_collab_forms_config.ini ./config/
cp node_modules/hazo_collab_forms/templates/*.ini ./

This creates:

  • config/hazo_collab_forms_config.ini - Main package config (in config/ subdirectory)
  • hazo_chat_config.ini - Chat functionality config
  • hazo_auth_config.ini - Authentication config

Step 7: Verify Installation

npx hazo-collab-forms-verify

This 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_config hazo_notes

One-Line shadcn Install (All Components)

npx shadcn@latest add button label dialog tooltip sonner popover command calendar accordion separator card

Usage

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 */}
      <CollabFormVisibilityIcon
        label="Company Name"
        visibility={visibility}
        on_visibility_change={setVisibility}
      />

      {/* Lock/Unlock Field */}
      <CollabFormLockIcon
        label="Company Name"
        locked={locked}
        on_lock_change={setLocked}
      />

      {/* 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 */}
      <CollabFormDeleteFieldIcon
        label="Optional Field"
        field_id="optional_field"
        on_delete={(field_id) => console.log('Delete field:', field_id)}
      />
    </div>
  );
}

Icon Components:

| Icon Component | Description | |----------------|-------------| | CollabFormVisibilityIcon | Toggle field visibility (show/hide) | | CollabFormLockIcon | Toggle field lock (read-only mode) | | CollabFormAddEntryIcon | Duplicate a field entry | | CollabFormDeleteEntryIcon | Remove a duplicated entry | | CollabFormDeleteFieldIcon | Soft delete a field |

Note: All controls are shown based on enable_* props. The consuming app decides which controls to render by passing the appropriate props.

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:

  1. Field-level FieldConfig properties → overrides form-level defaults
  2. Form-level HazoCollabFormSetProps → applies to all fields
  3. 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 }}
      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 icon
  • enable_visibility_toggle?: boolean - Show visibility toggle icon
  • enable_delete?: boolean - Show delete icon
  • enable_data_ok?: boolean - Show data OK control
  • enable_notes?: boolean - Show notes icon
  • enable_chat?: boolean - Show chat icon
  • chat_read_only?: boolean - View-only chat mode (no input, just viewing)
  • locked?: boolean - Initial lock state
  • visibility?: 'visible' | 'hidden' - Initial visibility state

Group-Level Control Propagation (Inheritance)

Groups can set enable_* props that automatically propagate to all child fields. This simplifies configuration when all fields in a group need the same controls.

Cascade Priority (highest to lowest):

  1. Field-level enable_* in FieldConfig - Individual field override
  2. Parent-group enable_* - Inherited from parent group
  3. Form-level enable_* in HazoCollabFormSetProps - Applies to all fields
  4. Hardcoded fallback - false

Inheritable Control Props:

  • enable_lock - Lock/protect field control
  • enable_visibility_toggle - Show/hide field control
  • enable_delete - Delete field control
  • enable_data_ok - Data OK validation control
  • enable_notes - Notes control
  • enable_chat - Chat control (requires chat_group_id at form level)
const fields: FieldConfig[] = [
  {
    id: "tax_details",
    label: "Tax Information",
    field_type: "group",
    // These propagate to all children
    enable_lock: true,
    enable_visibility_toggle: true,
    enable_notes: true,
    enable_chat: true,
    sub_fields: [
      // Inherits all enable_* from parent
      { id: "tfn", label: "Tax File Number", component_type: "HazoCollabFormInputbox", value: "" },
      // Override: explicitly disable lock and chat
      { id: "abn", label: "ABN", component_type: "HazoCollabFormInputbox", value: "", enable_lock: false, enable_chat: false },
    ]
  }
];

Utility Function:

import { resolve_field_controls } from 'hazo_collab_forms';

// Resolve effective controls for a field considering inheritance
const resolved = resolve_field_controls(field, parent_group, form_settings);
// Returns: { enable_lock, enable_visibility_toggle, enable_delete, enable_data_ok, enable_notes, enable_chat }

Unified Field Metadata Sync

Control field metadata (visibility, locked, deleted) from a parent component without remounting the form. This enables syncing state between form and summary views.

Props:

  • field_metadata?: Record<string, FieldMetadataInput> - External metadata for controlled sync
  • on_field_metadata_change?: (change: FieldMetadataChange) => void - Unified callback for all metadata changes

Types:

interface FieldMetadataInput {
  visibility?: 'visible' | 'hidden';  // or hidden?: boolean
  locked?: boolean;
  data_ok?: boolean | DataOkState;    // or dataOk
  deleted?: boolean;
}

interface FieldMetadataChange {
  field_id: string;
  visibility?: 'visible' | 'hidden';
  locked?: boolean;
  data_ok?: boolean | DataOkState;
  deleted?: boolean;
}

Usage Example:

import { HazoCollabFormSet } from 'hazo_collab_forms';
import type { FieldMetadataInput, FieldMetadataChange } from 'hazo_collab_forms';
import { useState } from 'react';

function MyForm({ fields }) {
  const [fieldMetadata, setFieldMetadata] = useState<Record<string, FieldMetadataInput>>({
    tax_file_number: { visibility: 'hidden', locked: true },
    name: { visibility: 'visible', locked: false },
  });

  // Unified handler - called for any metadata change
  const handleMetadataChange = (change: FieldMetadataChange) => {
    setFieldMetadata(prev => ({
      ...prev,
      [change.field_id]: { ...prev[change.field_id], ...change }
    }));
  };

  return (
    <HazoCollabFormSet
      fields_set={fields}
      enable_visibility_toggle={true}
      enable_lock={true}
      field_metadata={fieldMetadata}
      on_field_metadata_change={handleMetadataChange}
    />
  );
}

Benefits:

  • No component remount needed for metadata sync
  • Parent has full control over metadata state
  • Unified callback simplifies state management
  • Backward compatible with existing callbacks (on_visibility_change, on_lock_change, etc.)

Normalization Helper:

import { normalize_field_metadata_input } from 'hazo_collab_forms';

// Normalize input that uses alternative naming conventions
const input = { hidden: true, dataOk: 'ok', locked: true };
const normalized = normalize_field_metadata_input(input);
// Result: { visibility: 'hidden', data_ok: 'ok', locked: true }

Read-Only Summary View

Display form data in a read-only summary format for review workflows:

'use client';

import { HazoCollabFormSummary, type FormSection } from 'hazo_collab_forms';
import { LuUser, LuFileText } from 'react-icons/lu';

const iconMap = {
  LuUser: LuUser,
  LuFileText: LuFileText,
};

const sections: FormSection[] = [
  {
    group_name: "Personal Details",
    icon: "LuUser",
    field_list: [
      { id: "name", label: "Full Name", component_type: "HazoCollabFormInputbox", value: "" },
      { id: "email", label: "Email", component_type: "HazoCollabFormInputbox", value: "" },
    ]
  },
  {
    group_name: "Tax Details",
    icon: "LuFileText",
    field_list: [
      { id: "tfn", label: "Tax File Number", component_type: "HazoCollabFormInputbox", value: "" },
    ]
  }
];

export default function FormSummaryPage() {
  return (
    <HazoCollabFormSummary
      sections={sections}
      form_data={{
        name: "John Doe",
        email: "[email protected]",
        tfn: "123456789"
      }}
      render_icon={(iconName) => {
        const Icon = iconMap[iconName];
        return Icon ? <Icon className="h-5 w-5" /> : null;
      }}
      show_edit_buttons={true}
      on_edit_section={(index) => router.push(`/edit/${index}`)}
    />
  );
}

With Full Controls:

<HazoCollabFormSummary
  sections={sections}
  form_data={formData}
  field_metadata={fieldMetadata}

  // Enable field controls - each enabled via props
  // Use *_editable props to make controls clickable
  enable_data_ok={true}
  data_ok_mode="multi_state"
  data_ok_editable={true}
  enable_notes={true}
  enable_chat={true}
  chat_group_id="review-session-123"
  chat_read_only={false}  // Set to true for view-only chat mode
  enable_visibility_toggle={true}
  visibility_editable={true}
  enable_lock={true}
  lock_editable={true}
  enable_delete={true}

  // Display settings
  controls_display="popover"
  show_edit_buttons={true}
  on_edit_section={(index) => handleEdit(index)}

  // Callbacks
  on_data_ok_change={(fieldId, value) => console.log('Data OK changed:', fieldId, value)}
  on_notes_change={(fieldId, notes) => console.log('Notes updated:', fieldId, notes)}
  on_visibility_change={(fieldId, visibility) => console.log('Visibility changed:', fieldId, visibility)}
  on_lock_change={(fieldId, locked) => console.log('Lock changed:', fieldId, locked)}

  // Auto-actions
  on_data_ok_hidden={true}    // Auto-hide when marked OK
  on_data_ok_protected={true}  // Auto-lock when marked OK
/>

Key Features:

  • Composable design - enable only the features you need
  • Section icons with custom rendering
  • Edit navigation buttons
  • Field controls: data_ok, notes, chat, lock, visibility, delete
  • Two display modes: inline or popover
  • Row-level controls on DataTables
  • Auto-hide/auto-lock on data_ok change
  • Chat read-only mode for view-only scenarios

Chat Read-Only Mode

Enable view-only chat mode where users can see chat history but cannot send new messages. Useful for archived forms, review-only views, or user permission scenarios.

Props:

  • chat_read_only?: boolean - Form-level setting (applies to all fields)
  • Field-level chat_read_only in FieldConfig overrides form-level setting
// HazoCollabFormSet - all fields have view-only chat
<HazoCollabFormSet
  fields_set={fields}
  chat_group_id={groupId}
  chat_read_only={true}
/>

// HazoCollabFormSummary - view-only chat
<HazoCollabFormSummary
  sections={sections}
  form_data={formData}
  enable_chat={true}
  chat_group_id={groupId}
  chat_read_only={true}
/>

// Field-level override in FieldConfig
const fields: FieldConfig[] = [
  {
    id: "active_discussion",
    label: "Active Discussion",
    component_type: "HazoCollabFormInputbox",
    chat_read_only: false  // Can chat on this field
  },
  {
    id: "archived_data",
    label: "Archived Data",
    component_type: "HazoCollabFormInputbox",
    chat_read_only: true   // View-only chat
  }
];

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 | | HazoCollabFormDataTable | Editable data table with aggregations | button, label, dialog | | HazoCollabFormSet | Complete form with field arrays | all components | | HazoCollabFormSummary | Read-only summary view | button, label, popover | | 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 accordion

Verify Your Setup

Run the verification tool to check for common issues:

npx hazo-collab-forms-verify

See 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 directory

TypeScript 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