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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@iris711/form-renderer

v1.1.0

Published

Universal form rendering component for CUBE Apply and CUBE Enforce

Downloads

190

Readme

@cube/form-renderer

Universal form rendering component for CUBE Apply and CUBE Enforce applications. This package enables both platforms to render forms identically with full feature parity while maintaining platform-specific customisations.

Features

  • 20+ Field Types: text, number, textarea, email, phone, date, datetime, radio, select, checkbox, multi-select, file, photo_upload, and more
  • Advanced CUBE Fields: location (Address Search), business_lookup (Companies House), activities_commodities, party_creation, choice_with_pricing, price_calculation
  • Layout Fields: h1, h2, h3, paragraph, divider, spacer
  • Component Injection: Fully customisable UI components, icons, and styling
  • Mobile Optimised: Pre-built mobile components with touch-friendly interfaces
  • Value Handling: Proper nullish coalescing to preserve falsy values (0, false, empty arrays)
  • Conditional Visibility: Show/hide fields based on form state
  • Input Masking: Support for formatted inputs (phone numbers, etc.)

Installation

npm install @cube/form-renderer

Peer Dependencies

This package requires:

{
  "react": "^18.0.0",
  "react-dom": "^18.0.0"
}

Basic Usage

CUBE Apply Integration (with shadcn/ui)

import { SmartFormFieldRenderer } from '@cube/form-renderer';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
import { HelpCircle, Search, X, AlertCircle } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';

// Import specialized CUBE components
import { ActivitiesCommoditiesField } from '@/components/ActivitiesCommoditiesField';
import { PartyCreationField } from '@/components/PartyCreationField';
import AddressEntrySelector from '@/components/AddressEntrySelector';
import { ChoiceWithPricingField } from '@/components/form-fields/ChoiceWithPricingField';
import { PriceCalculationField } from '@/components/form-fields/PriceCalculationField';

// Import utilities
import { shouldShowField, applyInputMask, getRawValue } from '@/lib/formEnhancements';
import { API } from '@/lib/constants';

function MyFormRenderer({ field, value, onChange, formValues }) {
  return (
    <SmartFormFieldRenderer
      field={field}
      value={value}
      onChange={onChange}
      formValues={formValues}
      components={{
        Input,
        Label,
        Button,
        Tooltip,
        TooltipProvider,
        TooltipTrigger,
        TooltipContent,
      }}
      icons={{
        HelpIcon: HelpCircle,
        SearchIcon: Search,
        CloseIcon: X,
        AlertIcon: AlertCircle,
      }}
      specializedComponents={{
        ActivitiesCommoditiesField,
        PartyCreationField,
        AddressEntrySelector,
        ChoiceWithPricingField,
        PriceCalculationField,
      }}
      utilityFunctions={{
        shouldShowField,
        applyInputMask,
        getRawValue,
      }}
      useQuery={useQuery}
      apiConstants={{
        BUSINESSES_BASE: API.BUSINESSES.BASE,
        BUSINESSES_SEARCH: API.BUSINESSES.SEARCH,
      }}
    />
  );
}

CUBE Enforce Integration (Mobile Optimised)

import { SmartFormFieldRenderer, MobileInput, MobileLabel, MobileButton } from '@cube/form-renderer';
import { HelpCircle, Search, X, AlertCircle } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';

// Import specialized CUBE components (these should exist in CUBE Enforce)
import { ActivitiesCommoditiesField } from '@/components/ActivitiesCommoditiesField';
import { PartyCreationField } from '@/components/PartyCreationField';
import AddressEntrySelector from '@/components/AddressEntrySelector';

function MobileFormRenderer({ field, value, onChange, formValues }) {
  return (
    <SmartFormFieldRenderer
      field={field}
      value={value}
      onChange={onChange}
      formValues={formValues}
      components={{
        Input: MobileInput,
        Label: MobileLabel,
        Button: MobileButton,
        // Mobile doesn't use complex tooltips
        Tooltip: ({ children }) => <>{children}</>,
        TooltipProvider: ({ children }) => <>{children}</>,
        TooltipTrigger: () => null,
        TooltipContent: () => null,
      }}
      icons={{
        HelpIcon: HelpCircle,
        SearchIcon: Search,
        CloseIcon: X,
        AlertIcon: AlertCircle,
      }}
      specializedComponents={{
        ActivitiesCommoditiesField,
        PartyCreationField,
        AddressEntrySelector,
        // Pricing fields may not be needed in enforcement
      }}
      useQuery={useQuery}
      classNames={{
        container: "mb-4",
        label: "block text-base font-semibold text-gray-900 mb-2",
        input: "w-full px-4 py-3 border-2 border-gray-300 rounded-lg text-base",
      }}
    />
  );
}

API Reference

SmartFormFieldRendererProps

| Prop | Type | Required | Description | |------|------|----------|-------------| | field | FormField | Yes | The field definition object | | value | string \| string[] \| boolean | Yes | Current field value | | onChange | (value: any) => void | Yes | Value change handler | | formValues | Record<string, any> | Yes | All form values for conditional logic | | allFields | FormField[] | No | All form fields (needed for price_calculation) | | components | UIComponents | Yes | UI component injection | | icons | IconComponents | Yes | Icon component injection | | specializedComponents | SpecializedComponents | No | Advanced field components | | utilityFunctions | UtilityFunctions | No | Utility function injection | | useQuery | QueryHook | No | TanStack Query hook (required for business_lookup) | | classNames | StyleClassNames | No | Custom styling classes | | apiConstants | object | No | API endpoint configuration |

FormField Type

interface FormField {
  id: string;
  label: string;
  type: string;
  required?: boolean;
  placeholder?: string;
  options?: string[];
  configuration?: {
    tooltip?: string;
    helpText?: string;
    inputMask?: string;
    conditionalVisibility?: {
      enabled: boolean;
      conditions: Array<{
        fieldValue: string;
        operator: string;
        value: any;
      }>;
      logic: 'AND' | 'OR';
    };
    minDate?: string;
    maxDate?: string;
    spacingSize?: 'small' | 'medium' | 'large' | 'custom';
    customSpacing?: number;
    // ... other field-specific configuration
  };
}

Supported Field Types

Basic Fields

  • text - Single-line text input
  • number - Numeric input
  • textarea - Multi-line text input
  • email - Email address input
  • phone - Phone number input with optional masking
  • date - Date picker with relative date support
  • datetime - Date and time picker
  • radio - Radio button group
  • select - Dropdown select
  • checkbox - Single checkbox or checkbox group
  • multi-select - Multiple selection checkboxes
  • file - File upload
  • photo_upload - Image upload with AI analysis

Layout Fields

  • h1, h2, h3 - Headings
  • paragraph - Paragraph text
  • divider - Horizontal line separator
  • spacer - Vertical spacing

Advanced Fields (require specialized components)

  • location - Address search with gazetteer integration
  • business_lookup - Companies House business search
  • activities_commodities - UK licence activities/commodities selector
  • party_creation - Configurable party forms
  • choice_with_pricing - Radio buttons with dynamic pricing
  • price_calculation - Formula-based price calculation

Value Handling

The package uses nullish coalescing (??) throughout to preserve falsy values:

// ✅ Correct - preserves 0, false, empty arrays
value={value ?? ''}

// ❌ Wrong - 0 becomes '', false becomes '', [] becomes ''
value={value || ''}

This ensures:

  • Numeric 0 is preserved in number fields and price calculations
  • Boolean false is preserved in checkbox fields
  • Empty arrays [] are preserved in multi-select fields

Mobile Components

Pre-built mobile-optimised components are included:

import { 
  MobileInput,
  MobileLabel,
  MobileButton,
  MobileTooltip,
  MobileTooltipProvider,
  MobileTooltipTrigger,
  MobileTooltipContent 
} from '@cube/form-renderer';

Features:

  • 16px font size on inputs (prevents iOS zoom on focus)
  • Touch-friendly targets (larger padding, bigger hit areas)
  • Simplified tooltips (not suitable for touch devices)
  • Active state animations for better feedback

Utility Functions

Export utility functions for custom implementations:

import { 
  shouldShowField,
  applyInputMask,
  getRawValue,
  parseRelativeDate,
  formatDateForInput 
} from '@cube/form-renderer';

// Check conditional visibility
if (shouldShowField(field.configuration?.conditionalVisibility, formValues)) {
  // Render field
}

// Apply input mask
const masked = applyInputMask('1234567890', '(999) 999-9999');
// Result: (123) 456-7890

// Parse relative dates
const date = parseRelativeDate('today'); // Date object for today
const future = parseRelativeDate('+7 days'); // 7 days from now

TypeScript Support

Full TypeScript definitions are included. Import types as needed:

import type { 
  FormField,
  SmartFormFieldRendererProps,
  UIComponents,
  IconComponents,
  SpecializedComponents 
} from '@cube/form-renderer';

License

MIT

Support

For issues or questions, contact the CUBE development team.