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

@waysnx/ui-core

v0.4.0

Published

Core UI components from WaysNX - includes inputs, buttons, date pickers, and form controls

Readme

@waysnx/ui-core

Core UI components from WaysNX - A comprehensive React component library with form controls, inputs, buttons, date pickers, and more.

Table of Contents

Features

  • 🎨 Modern, accessible UI components
  • 📝 Complete form controls (Input, Select, Checkbox, Radio, etc.)
  • 📅 Date and date range pickers
  • 🔒 Built-in XSS protection with DOMPurify
  • 🎯 TypeScript support
  • 🌙 Dark mode ready
  • 📦 Tree-shakeable
  • 🎨 CSS variables for easy theming
  • 📋 JSON Schema to Form converter
  • ✅ Built-in validation system
  • 🎭 Input masking (number, phone, currency)
  • 🔗 Dynamic options loading (x-xref pattern)
  • ⚡ Optimized and minified for production

Installation

Quick Install

npm install @waysnx/ui-core react-datepicker

Import CSS

Import the required CSS files in your main entry file (e.g., main.tsx or App.tsx):

import '@waysnx/ui-core/dist/index.css';
import 'react-datepicker/dist/react-datepicker.css';

Choosing the Right Package

This package provides core UI components only. If you need schema-driven forms:

  • For complete features: Install @waysnx/ui-kit (includes everything)
  • For schema forms: Install @waysnx/ui-core + @waysnx/ui-form-builder

📖 Installation Guide for detailed comparison and examples.

Dependencies

The package includes these dependencies:

  • dompurify - XSS protection for HTML content
  • react-number-format - Number and currency masking
  • react-imask - Phone and custom pattern masking

Peer dependencies (you need to install):

  • react >= 18
  • react-dom >= 18
  • react-datepicker ^8.0.0

Quick Start

Get started in 3 simple steps:

import { Input, Button } from '@waysnx/ui-core';
import '@waysnx/ui-core/dist/index.css';
import { useState } from 'react';

function App() {
  const [name, setName] = useState('');

  return (
    <div>
      <Input
        label="Your Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
      />
      <Button variant="primary" onClick={() => alert(`Hello, ${name}!`)}>
        Submit
      </Button>
    </div>
  );
}

Usage

Basic Components

import { Button, Input, Select, Checkbox } from '@waysnx/ui-core';
import { useState } from 'react';

function MyForm() {
  const [name, setName] = useState('');
  const [country, setCountry] = useState('');
  const [agreed, setAgreed] = useState(false);

  return (
    <div>
      <Input
        label="Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
        required
      />

      <Select
        label="Country"
        value={country}
        onChange={(e) => setCountry(e.target.value)}
        options={[
          { value: 'us', label: 'United States' },
          { value: 'uk', label: 'United Kingdom' },
          { value: 'ca', label: 'Canada' }
        ]}
      />

      <Checkbox
        label="I agree to terms and conditions"
        checked={agreed}
        onChange={(e) => setAgreed(e.target.checked)}
      />

      <Button variant="primary" type="submit">
        Submit
      </Button>
    </div>
  );
}

Switch Component

import { Switch } from '@waysnx/ui-core';
import { useState } from 'react';

function MyComponent() {
  const [enabled, setEnabled] = useState(false);

  return (
    <Switch
      label="Enable notifications"
      checked={enabled}
      onChange={(e) => setEnabled(e.target.checked)}
    />
  );
}

Date Picker

import { DatePicker } from '@waysnx/ui-core';
import { useState } from 'react';

function MyComponent() {
  const [date, setDate] = useState(null);

  return (
    <DatePicker
      label="Select Date"
      selected={date}
      onChange={setDate}
      placeholder="Choose a date"
    />
  );
}

Multi-Select with Select All

import { Select } from '@waysnx/ui-core';
import { useState } from 'react';

function MyComponent() {
  const [selected, setSelected] = useState([]);

  return (
    <Select
      label="Select Skills"
      value={selected}
      onChange={setSelected}
      options={[
        { value: 'js', label: 'JavaScript' },
        { value: 'ts', label: 'TypeScript' },
        { value: 'react', label: 'React' }
      ]}
      multiple
      showSelectAll
    />
  );
}

Searchable Select

Add searchable prop to enable a search box in the dropdown. Works with both single and multi-select.

<Select
  label="Country"
  searchable
  options={[
    { value: 'us', label: 'United States' },
    { value: 'uk', label: 'United Kingdom' },
    { value: 'ca', label: 'Canada' },
  ]}
  value={country}
  onChange={setCountry}
/>

For JSON Schema, use "x-searchable": true:

{
  "country": {
    "type": "string",
    "enum": ["us", "uk", "ca"],
    "x-enum-labels": ["United States", "United Kingdom", "Canada"],
    "x-searchable": true
  }
}

File Upload

Upload files with drag & drop, preview, and validation:

import { FileUpload } from '@waysnx/ui-core';
import { useState } from 'react';

function MyComponent() {
  const [file, setFile] = useState(null);

  return (
    <FileUpload
      label="Upload Document"
      accept=".pdf,.doc,.docx"
      maxSize={5} // 5MB
      format="blob"
      showPreview
      showLastModified
      onChange={(fileData) => setFile(fileData)}
      onError={(error) => console.error(error)}
    />
  );
}

FileUpload Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | label | string | - | Label for the upload area | | accept | string | - | Accepted file types (e.g., '.pdf,.jpg') | | maxSize | number | - | Max file size in MB | | format | 'blob' \| 'binary' | 'blob' | Output format | | multiple | boolean | false | Allow multiple files | | showPreview | boolean | false | Show image preview | | showLastModified | boolean | false | Show last modified date | | autoUpload | boolean | false | Auto-upload on select | | browseButtonText | string | 'Browse' | Custom button text | | disabled | boolean | false | Disable upload | | onChange | (file) => void | - | Called when file selected | | onError | (error) => void | - | Called on error |

JSON Schema FileUpload

const schema = {
  type: 'object',
  properties: {
    resume: {
      type: 'string',
      format: 'binary',
      title: 'Upload Resume',
      'x-accept': '.pdf,.doc,.docx',
      'x-file-size': 5, // MB
      'x-file-format': 'blob',
      'x-show-file-preview': true,
      'x-show-last-modified': true,
      'x-browse-button-text': 'Choose File',
    },
    photos: {
      type: 'array',
      title: 'Upload Photos',
      items: {
        type: 'string',
        format: 'binary',
      },
      'x-accept': '.jpg,.jpeg,.png',
      'x-file-size': 10,
      'x-show-file-preview': true,
    },
  },
};

Validation

Built-in validation system with support for common validation rules:

import { Input } from '@waysnx/ui-core';
import { useState } from 'react';

function MyForm() {
  const [email, setEmail] = useState('');

  return (
    <Input
      label="Email"
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
      required
      pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
      minLength={5}
      maxLength={100}
      errorMessage="Please enter a valid email address"
      validateOnBlur
      onValidation={(isValid, error) => {
        console.log('Valid:', isValid, 'Error:', error);
      }}
    />
  );
}

Validation Props

  • required - Field is required
  • pattern - Regex pattern validation
  • minLength / maxLength - String length validation
  • min / max - Number range validation
  • errorMessage - Custom error message
  • validateOnChange - Validate on every change
  • validateOnBlur - Validate on blur (default: true)
  • onValidation - Callback with validation result

JSON Schema Validation

const schema = {
  type: 'object',
  properties: {
    email: {
      type: 'string',
      format: 'email',
      title: 'Email',
      minLength: 5,
      maxLength: 100,
      'x-error-message': 'Please enter a valid email'
    },
    age: {
      type: 'number',
      title: 'Age',
      minimum: 18,
      maximum: 120,
      'x-error-message': 'Age must be between 18 and 120'
    }
  },
  required: ['email', 'age']
};

Input Masking

Professional input masking for numbers, phone numbers, and currency.

Number Masking

import { Input } from '@waysnx/ui-core';

<Input
  label="Amount"
  type="number"
  mask
  thousandSeparator=","
  decimalSeparator="."
  decimalScale={2}
  allowNegative={false}
  value={amount}
  onChange={(e) => setAmount(e.target.value)}
/>
// Output: 1,234.56

Phone Masking

import { Input } from '@waysnx/ui-core';

// Custom pattern
<Input
  label="Phone"
  type="tel"
  mask="+1 (000) 000-0000"
  value={phone}
  onChange={(e) => setPhone(e.target.value)}
/>
// Output: +1 (555) 123-4567

// Basic validation (allows phone characters)
<Input
  label="Phone"
  type="tel"
  mask={true}
  value={phone}
  onChange={(e) => setPhone(e.target.value)}
/>

Currency Component

import { Currency } from '@waysnx/ui-core';

// US Dollar
<Currency
  label="Price"
  currencySymbol="$"
  currencySymbolPosition="start"
  precision={2}
  value={price}
  onChange={setPrice}
/>
// Output: $1,234.56

// Euro (European format)
<Currency
  label="Price"
  currencySymbol="€"
  currencySymbolPosition="end"
  precision={2}
  thousandSeparator="."
  decimalSeparator=","
  value={price}
  onChange={setPrice}
/>
// Output: 1.234,56€

Common Mask Patterns

US Phone:     +1 (000) 000-0000
UK Phone:     +44 00 0000 0000
Simple Phone: 000-000-0000
Parens Phone: (000) 000-0000

JSON Schema Masking

const schema = {
  type: 'object',
  properties: {
    amount: {
      type: 'number',
      title: 'Amount',
      'x-mask': true,
      'x-thousand-separator': ',',
      'x-decimal-scale': 2
    },
    phone: {
      type: 'string',
      format: 'tel',
      title: 'Phone',
      'x-mask': '+1 (000) 000-0000'
    },
    price: {
      type: 'number',
      title: 'Price',
      'x-currency-symbol': '$',
      'x-currency-position': 'start',
      'x-precision': 2
    }
  }
};

Dynamic Options (x-xref Pattern)

Load options dynamically from APIs for Select, Radio, Checkbox, and Autocomplete components.

Basic Usage

import { Select } from '@waysnx/ui-core';

// API client function (you provide this)
const fetchOptions = async (url) => {
  const response = await fetch(url);
  return response.json();
};

<Select
  label="Country"
  fetchOptions={fetchOptions}
  xrefUrl="/api/countries"
  xrefIdProp="id"
  xrefDisplayProp="name"
  value={country}
  onChange={setCountry}
  onLoadStart={() => console.log('Loading...')}
  onLoadEnd={() => console.log('Loaded!')}
  onError={(error) => console.error(error)}
/>

How It Works

  1. You control HTTP requests - Pass your own fetchOptions function
  2. Library handles UI - Loading states, error display, option mapping
  3. Secure by design - No SSRF vulnerability (apps control all network calls)

Supported Components

  • Select - Dropdown with dynamic options
  • Radio - Radio group with dynamic options
  • Checkbox - Checkbox group with dynamic options
  • Autocomplete - Searchable dropdown with dynamic options

Props

  • fetchOptions - Your function to fetch data: (url: string) => Promise<any[]>
  • xrefUrl - API endpoint URL
  • xrefIdProp - Property name for option value (e.g., 'id')
  • xrefDisplayProp - Property name for option label (e.g., 'name')
  • onLoadStart - Callback when loading starts
  • onLoadEnd - Callback when loading completes
  • onError - Callback on error

Priority

Static options take priority over dynamic options:

// If options prop is provided, x-xref is ignored
<Select
  options={[{ value: '1', label: 'Option 1' }]}
  xrefUrl="/api/options"  // This will be ignored
/>

JSON Schema x-xref

import { schemaToFormFields } from '@waysnx/ui-form-builder';

const schema = {
  type: 'object',
  properties: {
    country: {
      type: 'string',
      title: 'Country',
      'x-xref-url': '/api/countries',
      'x-xref-id-prop': 'id',
      'x-xref-display-prop': 'name'
    }
  }
};

// Your API client
const fetchOptions = async (url) => {
  const response = await fetch(url);
  return response.json();
};

// Generate fields
const fields = schemaToFormFields(schema, formData, handleChange);

// Render with fetchOptions
{fields.map(field => (
  <div key={field.name}>
    {field.useFormFieldLabel && <label>{field.label}</label>}
    {React.cloneElement(field.component, { fetchOptions })}
  </div>
))}

Note: schemaToFormFields is from @waysnx/ui-form-builder package. Install it separately if you need schema-driven forms.

Example API Response

Your API should return an array of objects:

[
  { "id": "us", "name": "United States" },
  { "id": "uk", "name": "United Kingdom" },
  { "id": "ca", "name": "Canada" }
]

Or an object with a data property:

{
  "data": [
    { "id": "us", "name": "United States" },
    { "id": "uk", "name": "United Kingdom" }
  ]
}

JSON Schema to Form

This package provides the core UI components. For schema-driven forms, install @waysnx/ui-form-builder:

npm install @waysnx/ui-form-builder

The form builder package provides:

  • schemaToFormFields - Convert JSON Schema to form components
  • FormArray - Dynamic repeatable form sections
  • Conditional logic (x-show-when, x-disable-when, x-required-when)

See the @waysnx/ui-form-builder package documentation for complete JSON Schema form examples.

Available Components

Form Controls

  • Input - Text, email, password, number inputs with optional password toggle and masking
  • Currency - Currency input with symbol, precision, and formatting
  • Select - Single and multi-select dropdowns with optional select-all, search, and dynamic options
  • Checkbox - Single checkbox or checkbox group with dynamic options (supports columns prop for grid layout)
  • Radio - Radio button group with dynamic options (supports columns prop for grid layout)
  • Textarea - Multi-line text input
  • Switch - Toggle switch
  • Slider - Range slider
  • Autocomplete - Searchable dropdown with filtering and dynamic options
  • FileUpload - File upload with drag & drop, preview, and validation

Date & Time Components

  • DatePicker - Single date picker
  • DateRangePicker - Date range picker
  • DateTimePicker - Date and time picker
  • TimePicker - Time picker

Buttons & Navigation

  • Button - Button with variants (primary, secondary, destructive, outline, ghost)
  • Link - Styled link component

Content & Display

  • HtmlEditor - Rich text editor (sanitized with DOMPurify)
  • HtmlContent - Display HTML content (sanitized with DOMPurify)

Layout & Structure

  • Hidden - Conditionally hide content
  • Tree - Tree view component

Utilities

  • ErrorMessage - Form field error message display
  • useDebounce - Debounce hook for performance

Note: For JSON Schema to form conversion, see @waysnx/ui-form-builder package which provides:

  • schemaToFormFields - Convert JSON Schema to form components
  • FormArray - Dynamic repeatable form sections
  • Conditional logic (x-show-when, x-disable-when, x-required-when)

Button Variants

<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>

Theming

All components use CSS variables for theming. Override these in your CSS to match your brand — no per-component configuration needed.

Quick Start

/* my-theme.css */
:root {
  --wx-color-primary: #2563eb;
  --wx-color-primary-hover: #1d4ed8;
  --wx-color-primary-light: #eff6ff;
  --wx-shadow-focus: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

Import after the library CSS:

import '@waysnx/ui-core/dist/styles/index.css';
import './my-theme.css'; // Your overrides

Available CSS Variables

:root {
  /* Brand */
  --wx-color-primary: #f19924;
  --wx-color-primary-hover: #e08916;
  --wx-color-primary-contrast: #ffffff;
  --wx-color-primary-light: #fff5e6;

  /* Text */
  --wx-color-text: #1e293b;
  --wx-color-text-muted: #64748b;
  --wx-color-text-light: #94a3b8;

  /* Surfaces */
  --wx-color-surface: #ffffff;
  --wx-color-surface-alt: #f8fafc;
  --wx-color-surface-hover: #f1f5f9;

  /* Borders */
  --wx-color-border: #e2e8f0;

  /* Status */
  --wx-color-error: #ef4444;
  --wx-color-error-hover: #b91c1c;
  --wx-color-error-light: #fef2f2;
  --wx-color-success: #22c55e;
  --wx-color-success-light: #f0fdf4;
  --wx-color-warning: #f59e0b;
  --wx-color-info: #3b82f6;

  /* Focus & Overlay */
  --wx-shadow-focus: 0 0 0 3px rgba(241, 153, 36, 0.1);
  --wx-overlay-bg: rgba(0, 0, 0, 0.4);

  /* Input Height */
  --wx-input-height: 40px;
}

Dark Mode

[data-theme="dark"] {
  --wx-color-surface: #1e1e1e;
  --wx-color-surface-alt: #141414;
  --wx-color-surface-hover: #334155;
  --wx-color-text: #f8fafc;
  --wx-color-text-muted: #cbd5e1;
  --wx-color-text-light: #94a3b8;
  --wx-color-border: #475569;
  --wx-color-primary-light: #3b2a10;
}

These same variables work across all WaysNX libraries (ui-core, ui-form-builder, ui-layout, ui-feedback).

JSON Schema Extensions

The library supports custom JSON Schema extensions using the x- prefix:

General Extensions

  • x-placeholder - Placeholder text for inputs
  • x-error-message - Custom validation error message
  • x-component - Force specific component:
    • 'checkbox' - Single checkbox for boolean
    • 'checkbox-group' - Multiple checkboxes for array
    • 'toggle' or 'switch' - Toggle switch for boolean
    • 'button' - Render as button
    • 'multiselect' - Multi-select dropdown
    • 'tree' - Tree view
    • 'link' - Link component
    • 'htmlEditor' - HTML editor
    • 'dateRange' - Date range picker
    • 'hidden' - Hidden field
  • x-button-type - Button type ('submit', 'button', 'reset')
  • x-button-variant - Button variant ('primary', 'secondary', 'destructive', 'outline', 'ghost')

Masking Extensions

  • x-mask - Enable masking (boolean or pattern string)
  • x-thousand-separator - Thousand separator (default: ',')
  • x-decimal-separator - Decimal separator (default: '.')
  • x-decimal-scale - Number of decimal places (default: 2)
  • x-currency-symbol - Currency symbol (e.g., '$', '€', '£')
  • x-currency-position - Symbol position ('start' or 'end')
  • x-precision - Currency decimal precision (default: 2)

Dynamic Options Extensions (x-xref)

  • x-xref-url - API endpoint URL for dynamic options
  • x-xref-id-prop - Property name for option value
  • x-xref-display-prop - Property name for option label

File Upload Extensions

  • x-accept - Accepted file types (e.g., '.pdf,.jpg')
  • x-file-size - Maximum file size in MB
  • x-file-format - Output format ('blob' or 'binary')
  • x-show-file-preview - Show image preview (boolean)
  • x-show-last-modified - Show last modified date (boolean)
  • x-skip-file-upload-btn - Hide browse button (boolean)
  • x-browse-button-text - Custom browse button text

Conditional Logic Extensions

  • x-show-when - Array of conditions to show field
  • x-disable-when - Array of conditions to disable field
  • x-required-when - Array of conditions to make field required

Condition Format

{
  name: string;        // Field name to watch
  value?: any;         // Value to compare against
  operator?: '==' | '!=' | '>' | '<' | '>=' | '<=' | 'notEmpty' | 'isEmpty';
}

Conditional Logic Example

const schema = {
  type: 'object',
  properties: {
    accountType: {
      type: 'string',
      enum: ['personal', 'business'],
    },
    companyName: {
      type: 'string',
      title: 'Company Name',
      'x-show-when': [{ name: 'accountType', value: 'business' }],
    },
    age: {
      type: 'integer',
      title: 'Age',
    },
    parentConsent: {
      type: 'boolean',
      title: 'Parent Consent',
      'x-show-when': [{ name: 'age', value: 18, operator: '<' }],
    },
  },
};

Note: Conditional logic is implemented in @waysnx/ui-form-builder. Install that package separately for this functionality.

Other Extensions

  • x-data - Static data for components (tree, autocomplete)
  • x-columns - Number of columns for Radio/Checkbox group grid layout (e.g., 3 renders options in 3 columns)

JSON Schema Type Mappings

The library automatically maps JSON Schema types to components:

| Schema Type | Format | Component | |------------|--------|-----------| | string | - | Input (text) | | string | email | Input (email) | | string | password | Input (password) with toggle | | string | date | DatePicker | | string | date-time | DateTimePicker | | string | time | TimePicker | | string | binary | FileUpload | | string | uri | Input (url) | | string | textarea | Textarea | | string | html | HtmlEditor | | string | enum | Select (single) | | integer / number | - | Input (number) | | integer / number | with min/max | Slider | | boolean | - | Switch (default) | | boolean | x-component: 'checkbox' | Checkbox | | array | enum items | Select (multi) or Checkbox group |

TypeScript Support

Full TypeScript support with type definitions included:

import type { 
  InputProps,
  SelectProps,
  CheckboxProps,
  ButtonProps,
  // ... other component props
} from '@waysnx/ui-core';

// For JSON Schema types, import from ui-form-builder
import type { JSONSchema, JSONSchemaProperty } from '@waysnx/ui-form-builder';

Security

This package is designed with security as a top priority:

XSS Protection ✅

  • All HTML content is sanitized using DOMPurify
  • HtmlEditor and HtmlContent components use strict allowlists
  • No direct innerHTML manipulation
  • Safe to render user-generated content

SSRF Protection ✅

  • Hybrid architecture - Library doesn't make HTTP requests directly
  • Applications control all network requests via fetchOptions callback
  • No SSRF vulnerability in library code
  • Applications MUST implement URL validation (see SECURITY_GUIDE.md)

Code Injection Protection ✅

  • No eval() or new Function() usage
  • Safe operator-based conditional logic
  • No dynamic code execution

For detailed security information and best practices, see:

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Peer Dependencies

  • react >= 18
  • react-dom >= 18
  • react-datepicker ^8.0.0

Complete Example

Here's a comprehensive example using validation, masking, and dynamic options:

import { Input, Currency, Select } from '@waysnx/ui-core';
import { schemaToFormFields } from '@waysnx/ui-form-builder';
import { useState } from 'react';

// Your API client
const fetchOptions = async (url) => {
  const response = await fetch(url);
  return response.json();
};

function CompleteForm() {
  const [formData, setFormData] = useState({});

  const schema = {
    type: 'object',
    properties: {
      // Text input with validation
      email: {
        type: 'string',
        format: 'email',
        title: 'Email',
        minLength: 5,
        maxLength: 100,
        'x-placeholder': '[email protected]',
        'x-error-message': 'Please enter a valid email'
      },
      // Number input with masking
      amount: {
        type: 'number',
        title: 'Amount',
        'x-mask': true,
        'x-thousand-separator': ',',
        'x-decimal-scale': 2,
        minimum: 0,
        maximum: 1000000
      },
      // Phone input with pattern
      phone: {
        type: 'string',
        format: 'tel',
        title: 'Phone Number',
        'x-mask': '+1 (000) 000-0000'
      },
      // Currency input
      price: {
        type: 'number',
        title: 'Price',
        'x-currency-symbol': '$',
        'x-currency-position': 'start',
        'x-precision': 2
      },
      // Select with dynamic options
      country: {
        type: 'string',
        title: 'Country',
        'x-xref-url': '/api/countries',
        'x-xref-id-prop': 'id',
        'x-xref-display-prop': 'name'
      },
      // Date picker
      birthdate: {
        type: 'string',
        format: 'date',
        title: 'Date of Birth'
      },
      // Checkbox group
      interests: {
        type: 'array',
        title: 'Interests',
        items: {
          type: 'string',
          enum: ['Technology', 'Sports', 'Music', 'Travel']
        },
        'x-component': 'checkbox-group'
      }
    },
    required: ['email', 'phone', 'country']
  };

  const handleChange = (name, value) => {
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form data:', formData);
  };

  const fields = schemaToFormFields(schema, formData, handleChange);

  return (
    <form onSubmit={handleSubmit}>
      {fields.map(field => (
        <div key={field.name}>
          {field.useFormFieldLabel && (
            <label>
              {field.label}
              {field.required && <span>*</span>}
            </label>
          )}
          {React.cloneElement(field.component, { fetchOptions })}
        </div>
      ))}
      <button type="submit">Submit</button>
    </form>
  );
}

Installation for JSON Schema forms:

npm install @waysnx/ui-core @waysnx/ui-form-builder react-datepicker

## License

MIT

## Links

- **npm Package**: [@waysnx/ui-core](https://www.npmjs.com/package/@waysnx/ui-core)
- **Security**: Contact [email protected] for security documentation

## Support

- 📧 Email: [email protected]
- 📖 Documentation: This README
- 🔒 Security: [email protected]

## Author

**WaysNX Technologies**

---

Made with ❤️ by WaysNX Technologies