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

@timeax/form-palette

v0.1.27

Published

This package extracts and standardizes the **form + input + variant system** from an existing Laravel/Inertia/React project into a **reusable, framework-friendly** library

Readme

Index

Form Palette

A small but powerful React form runtime built around three ideas:

  1. A single <Form /> shell that wires up state, submission and validation.
  2. <InputField /> as the universal “field wrapper” that renders a registered variant (text, number, select, json-editor, etc.) and handles label / description / errors / layout.
  3. Adapters that decide what “submit” means (local, axios, inertia, or your own).

Quick start

Installation:

npm install @timeax/form-palette

import * as React from "react";
import {
  Form,
  InputField,
  registerCoreVariants,
  registerAxiosAdapter,
  registerInertiaAdapter,
} from "@timeax/form-palette";

// App boot (once)
registerCoreVariants();
registerAxiosAdapter();
await registerInertiaAdapter();

If you only use one adapter, only register the one you need.


Form

Form is the main form component exported from the package entrypoint (it is CoreShell, re-exported as Form).

Minimal “local” form

Use adapter="local" when you want submission to be handled purely in JS.

function Example() {
  return (
          <Form
                  name="profile"
                  adapter="local"
                  onSubmit={(e) => {
                    // Current outbound snapshot
                    console.log(e.formData);
                    // You can also mutate outbound data via e.editData(...)
                  }}
          >
            <InputField
                    name="email"
                    variant="text"
                    label="Email"
                    required
            />

            <InputField
                    name="age"
                    variant="number"
                    label="Age"
            />

            <button type="submit">Save</button>
          </Form>
  );
}

Axios adapter

<Form
        name="profile"
        adapter="axios"
        url="/api/profile"
        method="post"
        onSubmitted={(form, payload) => {
          console.log(payload);
        }}
>
  <InputField name="email" variant="text" label="Email" required />
  <button type="submit">Save</button>
</Form>

Inertia adapter

<Form
        name="profile"
        adapter="inertia"
        url="/profile"
        method="post"
        onSubmitted={(form, payload) => {
          // payload is the resolved inertia Page (or normalized error on failure)
          console.log(payload);
        }}
>
  <InputField name="email" variant="text" label="Email" required />
  <button type="submit">Save</button>
</Form>

InputField

InputField is the form runtime’s “field wrapper”. It:

  • Pulls the chosen variant from the variant registry and renders it.

  • Connects to form state when used inside <Form /> (by name).

  • Computes layout (label placement, helper slots, spacing, etc.) by combining:

    • variant defaults
    • host overrides
    • optional variant.resolveLayout(...)
  • Normalizes validation results into a consistent list of errors.

Basic usage

<InputField
        name="username"
        variant="text"
        label="Username"
        description="Public handle"
        required
        placeholder="@davy"
/>

Helper slots

Most helper UI (description, help text, error text, tags, etc.) is rendered through a layout graph.

<InputField
        name="bio"
        variant="textarea"
        label="Bio"
        helpText="Keep it short"
        errorText=""
/>

Standalone mode

InputField can run without a surrounding <Form /> (it will fall back to a self-managed field state).

<InputField
        variant="text"
        label="Standalone"
        defaultValue="Hello"
        onChange={({ value }) => {
          console.log(value);
        }}
/>

Adapters

Adapters define how the form submits.

Built-in adapter keys

  • local – no network; calls your callbacks.
  • axios – HTTP submit via Axios.
  • inertia – submit via Inertia.

Registering adapters

import { registerAdapter } from "@timeax/form-palette";

registerAdapter("my-adapter", (config) => {
  return {
    submit() {
      // fire-and-forget
    },
    async send() {
      // resolve a result shape that matches AdapterOk<"my-adapter">
      return { data: config.data } as any;
    },
    run() {
      this.submit();
    },
  };
});

Adapter-specific props

Some adapters expose additional props on <Form /> (e.g. url, method, config).


Recommended boot order

  1. Register variants (so InputField can resolve variant → component).
  2. Register the adapters you will use.
  3. Render forms.
registerCoreVariants();
registerAxiosAdapter();
await registerInertiaAdapter();

Variant props + InputField usage

Below are the variant-specific props you can pass to <InputField /> for:

  • text
  • textarea
  • toggle-group
  • number
  • phone
  • password
  • slider
  • toggle
  • treeselect
  • multi-select
  • select
  • radio
  • checkbox
  • chips
  • color
  • date
  • keyvalue
  • editor
  • file
  • icon
  • image-icon
  • json-editor
  • lister
  • custom

Note: Some props like value, onValue, error, disabled, readOnly, size, density are typically injected by the core runtime/InputField. The tables focus on the props you usually configure.


text

Variant props

| Prop | Description | |--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| | trim?: boolean | boolean — If true, the value is trimmed before validation (visual input stays as typed). | | minLength?: number | number — Minimum allowed length (after optional trimming). | | maxLength?: number | number — Maximum allowed length (after optional trimming). | | joinControls?: boolean | boolean — If true and there are controls, the input + controls share one box (border/radius/focus). | | extendBoxToControls?: boolean | boolean — When joinControls is true, controls are either visually “inside” the same box (true) or separate (false). | | inputClassName?: string | string — Extra classes for the inner <input> element (not the wrapper). | | prefix?: string | string — Fixed prefix rendered as part of the visible input string (e.g. ₦, ID: ). | | suffix?: string | string — Fixed suffix rendered as part of the visible input string (e.g. %, kg). | | stripPrefix?: boolean | boolean — If true (default), the prefix is stripped from the emitted model value before calling onValue internally. | | stripSuffix?: boolean | boolean — If true (default), the suffix is stripped from the emitted model value before calling onValue internally. | | mask?: string | string — Mask pattern (PrimeReact style), e.g. "99/99/9999", "(999) 999-9999". | | maskDefinitions?: Record<string, RegExp> | Record — Per-symbol slot definitions (kept for future custom engine; unused by current implementation). | | slotChar?: string | string — Placeholder slot character (default _). | | autoClear?: boolean | boolean — If true, “empty” masked values emit "" instead of a fully-masked placeholder string. | | unmask?: "raw" \| "masked" \| boolean | union — Controls whether the model value is raw vs masked. ("raw"/true ⇒ emit unmasked; "masked"/false/undefined ⇒ emit masked). | | maskInsertMode?: "stream" \| "caret" | union — Reserved for future caret-mode logic (currently unused; kept for API compatibility). | | ...inputProps | All other standard React.InputHTMLAttributes<HTMLInputElement> (except value, defaultValue, onChange, size) are forwarded. |

Sample usage (InputField)

import { InputField } from "@timeax/form-palette";

export function ExampleText() {
  return (
          <InputField
                  variant="text"
                  name="phone"
                  label="Phone number"
                  description="We’ll use this for account recovery."

                  // semantic validation flags (core layer)
                  trim
                  minLength={11}
                  maxLength={11}

                  // mask + UI props (preset layer)
                  prefix="+234 "
                  mask="999 999 9999"
                  unmask="raw"
                  autoClear

                  // regular input attributes
                  type="tel"
                  inputMode="tel"
                  placeholder="803 123 4567"
          />
  );
}

textarea

Variant props

| Prop | Description | |--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ...textareaProps | The textarea variant primarily forwards props from the underlying UI Textarea component (UiTextareaProps), excluding value, defaultValue, and onChange because the variant emits changes via the form runtime. |

Sample usage (InputField)

import { InputField } from "@timeax/form-palette";

export function ExampleTextarea() {
  return (
          <InputField
                  variant="textarea"
                  name="bio"
                  label="About you"
                  helpText="Keep it short and clear."

                  // typical textarea attributes (usually supported via UiTextareaProps)
                  rows={4}
                  placeholder="Tell us a little about yourself..."
          />
  );
}

toggle-group

Variant props

| Prop | Description | |------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| | options: (ToggleOption \| string \| number \| boolean)[] | Options for the toggle group. You can pass full option objects or primitive shorthand (primitives are normalized to { value: String(x), label: String(x) }). | | multiple?: boolean | boolean — If true, enables multi-select (value becomes an array of strings internally). | | variant?: "default" \| "outline" | union — Visual style passed to the underlying ToggleGroup. | | layout?: "horizontal" \| "vertical" \| "grid" | union — Layout mode. | | gridCols?: number | number — Column count when layout="grid" (defaults to 2 in the component). | | fillWidth?: boolean | boolean — If true, makes the group/items stretch to fill available width (adds w-full and related item sizing). | | optionValue?: string | string — When options are custom objects, the property name to read value from (fallback: obj.value). | | optionLabel?: string | string — When options are custom objects, the property name to read label from (fallback: obj.label or String(value)). | | optionIcon?: string | string — When options are custom objects, the property name to read icon from (fallback: obj.icon). | | optionDisabled?: string | string — When options are custom objects, the property name to read disabled flag from (fallback: obj.disabled). | | optionTooltip?: string | string — When options are custom objects, the property name to read tooltip content from (fallback: obj.tooltip). | | optionMeta?: string | string — When options are custom objects, the property name to read meta from (fallback: obj.meta). | | renderOption?: (option, isSelected) => React.ReactNode | Custom renderer per option (receives normalized option + selected state). | | className?: string | Class for the toggle group container. | | itemClassName?: string | Base class applied to all toggle items. | | activeClassName?: string | Class applied only to selected items (merged with default active styles). | | autoCap?: boolean | If true, capitalizes the first letter of string labels. | | gap?: number | Gap between buttons in pixels (applies to flex + grid layouts). |

ToggleOption shape (when not using primitive shorthand):

  • label: React.ReactNode
  • value: string
  • icon?: React.ReactNode
  • disabled?: boolean
  • tooltip?: React.ReactNode
  • meta?: any

Sample usage (InputField)

import { InputField } from "@timeax/form-palette";

export function ExampleToggleGroup() {
  return (
          <InputField
                  variant="toggle-group"
                  name="plan"
                  label="Choose a plan"
                  required

                  options={[
                    { value: "basic", label: "Basic" },
                    { value: "pro", label: "Pro" },
                    { value: "team", label: "Team", disabled: true, tooltip: "Coming soon" },
                  ]}
                  layout="horizontal"
                  variant="outline"
                  fillWidth
                  gap={8}
                  activeClassName="ring-1 ring-primary"
          />
  );
}

number

| Prop | Description | |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| | showButtons | When true, renders built-in step controls (±) alongside the number input. | | buttonLayout | Layout for the step controls when showButtons is enabled. Supported layouts: "stacked" (vertical on the right) and "inline" (- left, + right). | | step | Step amount used by the built-in controls and stepping logic (forwarded to the underlying number input). | | min | Minimum numeric value constraint (used by the stepping logic and forwarded to the underlying number input). | | max | Maximum numeric value constraint (used by the stepping logic and forwarded to the underlying number input). |

Also accepts the rest of the underlying InputNumberProps (they’re forwarded to the number input).

Sample

<InputField
        variant="number"
        name="quantity"
        label="Quantity"
        description="How many items?"
        min={1}
        max={99}
        step={1}
        showButtons
        buttonLayout="inline"
/>

password

| Prop | Description | |-------------------------|-----------------------------------------------------------| | autoComplete | Sets the input autoComplete hint for password managers. | | minLength | Minimum allowed length (HTML constraint). | | maxLength | Maximum allowed length (HTML constraint). | | revealToggle | Show / hide the reveal toggle button. | | defaultRevealed | Initial revealed state (defaults to hidden). | | onRevealChange | Called when revealed state changes. | | renderToggleIcon | Custom renderer for the toggle icon. | | toggleAriaLabel | ARIA label for the toggle button. | | toggleButtonClassName | ClassName hook for the toggle button. | | strengthMeter | Enable the strength meter UI. | | ruleDefinitions | Custom rule definitions used by the strength meter. | | ruleUses | Which rules should be considered when computing strength. | | meterStyle | Visual style of the strength meter. | | renderMeter | Custom renderer for the full meter block. | | meterWrapperClassName | ClassName hook for the meter wrapper. |

Password inherits the visual props from the text variant (it reuses the text UI), but controls type, value wiring, and trailing controls internally.

Sample

<InputField
        variant="password"
        name="password"
        label="Password"
        required
        minLength={8}
        autoComplete="new-password"
        revealToggle
        strengthMeter
        ruleUses={["minLen", "upper", "lower", "number", "symbol"]}
/>

phone

| Prop | Description | |------------------------|---------------------------------------------------------------------------------| | countries | List of allowed countries (and their dial codes) shown in the country selector. | | defaultCountryCode | The default selected country code (e.g. "NG"). | | allowCountrySearch | Enable searching in the country list. | | allowCountryClear | Allow clearing the selected country. | | countryPlaceholder | Placeholder text for the country selector. | | showFlag | Show the flag in the country selector. | | showCountryName | Show the country name in the selector / list. | | showDialCode | Show dial codes in the country list. | | showSelectedDialCode | Show the selected dial code next to the input. | | dialCodeDelimiter | Delimiter between dial code and the input number (e.g. " ", "-"). | | valueMode | Controls how the field value is emitted (e.g. E.164 vs local formats). | | mask | Optional input mask (string or resolver function). | | lazy | IMask “lazy” mode (placeholder chars hidden until typed). | | keepCharPositions | IMask option to keep character positions stable. | | unmask | How the underlying mask value is emitted (IMask option). |

Phone inherits the visual props from the text variant, but controls value parsing/formatting and the country selector internally.

Sample

<InputField
        variant="phone"
        name="phone"
        label="Phone number"
        defaultCountryCode="NG"
        allowCountrySearch
        showSelectedDialCode
        dialCodeDelimiter=" "
        valueMode="e164"
/>

Slider (slider)

Value type: number | undefined

Props

| Prop | Description | |----------------------------|--------------------------------------------------------| | value | Current slider value (number). | | onValue | Called when the value changes. | | error | Validation/error message for the field. | | disabled | Disables interaction. | | readOnly | Prevents changes but still displays the value. | | size | Sizing preset for the control. | | density | Density preset for the control (spacing). | | min | Minimum value (default 0). | | max | Maximum value (default 100). | | step | Step size (default 1). | | showValue | Show the current numeric value next to the slider. | | valuePlacement | Where to render the value when showValue is enabled. | | formatValue | Format the displayed value. | | className | Root wrapper className. | | sliderClassName | Slider track/handle className. | | valueClassName | Value label className. | | leadingIcons | Icons rendered before the slider/value. | | trailingIcons | Icons rendered after the slider/value. | | icon | Single icon (shorthand). | | iconGap | Gap between icon(s) and content. | | leadingIconSpacing | Spacing between multiple leading icons. | | trailingIconSpacing | Spacing between multiple trailing icons. | | leadingControl | Optional control element rendered before the slider. | | trailingControl | Optional control element rendered after the slider. | | leadingControlClassName | Wrapper className for the leading control. | | trailingControlClassName | Wrapper className for the trailing control. | | joinControls | Join controls visually to the slider box. | | extendBoxToControls | Extend slider “box” background behind controls. | | controlVariant | Variant for the +/- controls (if shown). | | controlStep | Step used by +/- controls (falls back to step). | | controlDecrementIcon | Custom icon node for decrement control. | | controlIncrementIcon | Custom icon node for increment control. |

Example

<InputField
        name="rating"
        label="Rating"
        variant="slider"
        min={0}
        max={100}
        step={5}
        showValue
        valuePlacement="right"
        formatValue={(v) => `${v}%`}
        controlVariant="ghost"
        controlStep={5}
/>

Toggle (toggle)

Value type: boolean | undefined

Props

| Prop | Description | |------------------------|--------------------------------------------| | value | Current toggle value (boolean). | | onValue | Called when the value changes. | | error | Validation/error message for the field. | | size | Visual size of the switch. | | density | Spacing density for the wrapper. | | onText | Text shown when the value is true. | | offText | Text shown when the value is false. | | label | Optional label rendered beside the switch. | | containerClassName | Wrapper className. | | switchRootClassName | ClassName for the Switch root element. | | switchThumbClassName | ClassName for the Switch thumb. |

Example

<InputField
        name="enabled"
        label="Enabled"
        variant="toggle"
        onText="On"
        offText="Off"
        density="sm"
/>

TreeSelect (treeselect)

Value type: TreeKey | TreeKey[] | undefined (where TreeKey is string | number)

Base props

| Prop | Description | |-------------------------|--------------------------------------------------------------------------------| | value | Selected key(s). Single value is a key; multi is an array of keys. | | onValue | Called when selection changes. | | error | Validation/error message for the field. | | disabled | Disables interaction. | | readOnly | Prevents changes but still displays the selection. | | size | Sizing preset for trigger/list rows. | | density | Density preset for trigger/list rows. | | options | Tree of options to render. | | multiple | Allow selecting multiple keys (returns TreeKey[]). | | autoCap | (Option mapping helper) Auto-capitalize generated labels when mapping options. | | optionLabel | (Option mapping helper) Label accessor (key name or function). | | optionValue | (Option mapping helper) Value accessor (key name or function). | | optionDescription | (Option mapping helper) Description accessor. | | optionDisabled | (Option mapping helper) Disabled accessor. | | optionIcon | (Option mapping helper) Icon accessor. | | optionKey | (Option mapping helper) Key accessor. | | searchable | Enable search input in the dropdown. | | searchPlaceholder | Placeholder text for the search input. | | emptyLabel | Content shown when there are no options. | | emptySearchText | Content shown when search returns no matches. | | clearable | Show a clear/reset action. | | placeholder | Text shown when nothing is selected. | | className | Wrapper className for the whole field. | | triggerClassName | ClassName for the trigger/button area. | | contentClassName | ClassName for the dropdown content. | | renderOption | Custom renderer for an option row. | | renderValue | Custom renderer for the trigger's current value display. | | expandAll | Expand all nodes by default. | | defaultExpandedValues | Keys that should start expanded by default. | | leafOnly | Restrict selection to leaf nodes only. |

Mode: default (mode omitted or "default")

| Prop | Description | |----------------------------|-----------------------------------------------------------------| | mode | Omit or set to 'default' to use the standard field trigger. | | button | Optional custom trigger button renderer. | | selectedBadge | Optional selected-count badge renderer. | | icon | Single icon rendered near the trigger value. | | iconGap | Gap between icon and content. | | leadingIcons | One or more icons before the value. | | trailingIcons | One or more icons after the value. | | leadingControl | Custom control element before the trigger (e.g., clear button). | | trailingControl | Custom control element after the trigger. | | leadingControlClassName | ClassName for leading control wrapper. | | trailingControlClassName | ClassName for trailing control wrapper. | | joinControls | Visually join controls to the trigger box (shared border). | | extendBoxToControls | Extend trigger background behind controls. | | rootClassName | Wrapper className around controls + trigger. | | triggerInnerClassName | ClassName for the trigger’s inner content. |

Mode: button (mode="button")

| Prop | Description | |----------------------------|-----------------------------------------------------------------| | mode | Set to 'button' to render a button-style trigger. | | button | (mode='button') If provided, this is the trigger renderer. | | selectedBadge | (mode='button') Selected-count badge renderer. | | icon | Single icon rendered near the trigger value. | | iconGap | Gap between icon and content. | | leadingIcons | One or more icons before the value. | | trailingIcons | One or more icons after the value. | | leadingControl | Custom control element before the trigger (e.g., clear button). | | trailingControl | Custom control element after the trigger. | | leadingControlClassName | ClassName for leading control wrapper. | | trailingControlClassName | ClassName for trailing control wrapper. | | joinControls | Visually join controls to the trigger box (shared border). | | extendBoxToControls | Extend trigger background behind controls. |

Example (default mode)

<InputField
        name="category"
        label="Category"
        variant="treeselect"
        options={[
          {
            key: "social",
            label: "Social",
            children: [
              { key: "twitter", label: "Twitter" },
              { key: "instagram", label: "Instagram" },
            ],
          },
        ]}
        searchable
        placeholder="Pick one…"
/>

Example (multiple + button mode)

<InputField
        name="tags"
        variant="treeselect"
        mode="button"
        multiple
        options={[
          { key: 1, label: "Starter" },
          { key: 2, label: "Pro" },
          { key: 3, label: "Enterprise" },
        ]}
/>

multi-select

Variant props

| Prop | Description | |---------------------|---------------------------------------------------------------------------------------------------------------------------------| | options | Options for the multi-select. Accepts primitives or objects. | | autoCap | Capitalise the first letter of the label (when the resolved label is a string). | | optionLabel | How to read the label from each option (string key or mapper function). If omitted: uses label, else String(value). | | optionValue | How to read the value from each option (string key or mapper function). If omitted: primitives are used directly, else value. | | optionDescription | How to read the description from each option (string key or mapper function). If omitted: uses description. | | optionIcon | How to read the icon from each option (string key or mapper function). If omitted: uses icon. | | optionDisabled | How to detect disabled options (string key or mapper function). If omitted: uses disabled. | | optionKey | How to compute stable keys for items (string key or mapper function). If omitted: uses index. | | searchable | Enable search field in the list. | | searchPlaceholder | Placeholder for the search field. | | emptySearchText | Text when there are no matches for the current search. | | showSelectAll | Show a “Select all” row. | | selectAllLabel | Label for the “Select all” row. | | selectAllPosition | Where to render the “Select all” row. | | clearable | Show a clear action when there is at least one selection. | | placeholder | Placeholder when nothing is selected. | | renderOption | Optional global renderer for an option row. (An option may also provide its own per-option render.) | | renderCheckbox | Optional renderer for the checkbox element used by each option row. | | renderValue | Custom renderer for the trigger summary (selected values). | | maxListHeight | Max height for the list (px). | | className | Wrapper class for the whole variant. | | triggerClassName | Class for the trigger button. | | contentClassName | Class for the popover content container. |

Options can be passed as:

  • primitives: ['ng', 'gh', 'ke']
  • objects: [{ label, value, ...extra }]

Mode and trigger props

| Prop | Description | |-------------------------------|------------------------------------------------------------------------------------------------------| | mode | Choose trigger style: "default" (standard input-like trigger) or "button" (custom trigger node). | | leadingIcons | Icons shown before the summary text inside the trigger (default mode). | | trailingIcons | Icons shown after the summary / clear button inside the trigger. | | icon | Single icon shorthand (falls into leadingIcons). | | iconGap | Base gap (px) used between icon groups and text. | | leadingIconSpacing | Override spacing (px) between leading icons and text. | | trailingIconSpacing | Override spacing (px) between trailing icons and the right-side controls. | | leadingControl | Custom node rendered on the far-left outside the trigger (e.g., a compact action button). | | trailingControl | Custom node rendered on the far-right outside the trigger. | | leadingControlClassName | ClassName for the leading control wrapper. | | trailingControlClassName | ClassName for the trailing control wrapper. | | joinControls | Visually joins leading/trailing controls with the trigger (no gaps). | | extendBoxToControls | Extends the input box styling (border/background) around the joined controls. | | button | Used when mode="button". If provided, this is the trigger. If not provided, children is used. | | children | When mode="button" and button is not provided, children is used as the trigger content. | | selectedBadge | Selected-count badge (mode="button" only). | | selectedBadgeHiddenWhenZero | Hide the badge when selected count is 0 (mode="button"). | | selectedBadgeClassName | ClassName for the selected-count badge. | | selectedBadgePlacement | Where to place the badge relative to the trigger content (mode="button"). |

Sample usage

import { InputField } from "@timeax/form-palette"; // adjust import to your project

export function MultiSelectExample() {
  return (
          <InputField
                  variant="multi-select"
                  name="countries"
                  label="Countries"
                  description="Pick one or more countries."
                  options={[
                    { label: "Nigeria", value: "ng" },
                    { label: "Ghana", value: "gh" },
                    { label: "Kenya", value: "ke" },
                  ]}
                  searchable
                  searchPlaceholder="Search countries..."
                  showSelectAll
                  selectAllLabel="Select all"
                  clearable
                  placeholder="Select countries..."
          />
  );
}

radio

Variant props

| Prop | Description | |------------------------|-----------------------------------------------------------------------------------------------------------------------| | items | Alias of options (list of items to render). | | options | Options to render. Supports RadioItem objects or custom items via mappers. | | mappers | Mapping functions for TItem → value/label/description/disabled/key/render. Takes precedence over option* props. | | optionValue | Shortcut mapping for value (used only if mappers is not provided). | | optionLabel | Shortcut mapping for label (used only if mappers is not provided). | | renderOption | Global option renderer (can be overridden per item via item.render). | | layout | Layout mode: "stack" or "grid". | | columns | Number of columns when layout="grid". | | itemGapPx | Gap (px) between items. | | size | Variant size override for the radio control. | | density | Variant density override for spacing. | | autoCap | Auto-capitalise labels when the resolved label is a string. | | aria-label | ARIA label forwarded to the radio group wrapper. | | aria-labelledby | ARIA aria-labelledby forwarded to the radio group wrapper. | | aria-describedby | ARIA aria-describedby forwarded to the radio group wrapper. | | groupClassName | ClassName for the group wrapper. | | optionClassName | ClassName for each option container. | | labelClassName | ClassName for the option label. | | descriptionClassName | ClassName for the option description. | | id | Optional id for the group wrapper. | | name | HTML name attribute to group radio inputs. | | className | Alias for groupClassName. |

Supported option shapes

  • RadioItem<TValue>: { value, label, description?, disabled?, key?, render? }
  • Any TItem shape, as long as you provide mappers (or optionLabel/optionValue shortcuts)

Sample usage

import { InputField } from "@timeax/form-palette"; // adjust import to your project

export function RadioExample() {
  return (
          <InputField
                  variant="radio"
                  name="plan"
                  label="Plan"
                  description="Choose a plan."
                  items={[
                    { value: "free", label: "Free", description: "Basic features" },
                    { value: "pro", label: "Pro", description: "Everything included" },
                    { value: "team", label: "Team", description: "For small teams" },
                  ]}
                  layout="grid"
                  columns={3}
                  autoCap
          />
  );
}

select

Variant props

| Prop | Description | |----------------------------|---------------------------------------------------------------------------------------------------------------------------------| | options | Options for the select. Accepts primitives or objects. | | autoCap | Capitalise the first letter of the label (when the resolved label is a string). | | optionLabel | How to read the label from each option (string key or mapper function). If omitted: uses label, else String(value). | | optionValue | How to read the value from each option (string key or mapper function). If omitted: primitives are used directly, else value. | | optionDescription | How to read the description from each option (string key or mapper function). If omitted: uses description. | | optionIcon | How to read the icon from each option (string key or mapper function). If omitted: uses icon. | | optionDisabled | How to detect disabled options (string key or mapper function). If omitted: uses disabled. | | optionKey | How to compute stable keys for items (string key or mapper function). If omitted: uses index. | | searchable | Enable search field in the list. | | searchPlaceholder | Placeholder for the search field. | | emptySearchText | Text shown when there are no matches for the current search. | | clearable | Show a clear action (x) when a value is selected. | | emptyLabel | Label to show when no value is selected (acts like “none”). | | placeholder | Placeholder when no value is selected (and emptyLabel not shown). | | renderOption | Optional global renderer for a list option. (An option may also provide its own per-option render.) | | renderValue | Custom renderer for the trigger display (selected option). | | virtualScroll | Enable virtual scrolling for large option lists. | | virtualScrollThreshold | Number of items after which virtual scroll is enabled (when virtualScroll=true). | | virtualScrollPageSize | How many items to render per virtual page/chunk. | | leadingControl | Custom node rendered on the far-left outside the trigger. | | leadingControlClassName | ClassName for the leading control wrapper. | | leadingIconSpacing | Override spacing (px) between leading icons and the selected value. | | trailingIcons | Icons shown on the right side of the trigger. | | trailingControl | Custom node rendered on the far-right outside the trigger. | | trailingControlClassName | ClassName for the trailing control wrapper. | | trailingIconSpacing | Override spacing (px) between selected value and trailing icons. | | joinControls | Visually joins leading/trailing controls with the trigger (no gaps). | | extendBoxToControls | Extends the input box styling (border/background) around the joined controls. | | icon | Single icon shorthand (used in default mode). | | iconGap | Base gap (px) used between icon and text. | | className | Wrapper class for the whole variant. | | triggerClassName | Class for the trigger button. | | contentClassName | Class for the popover content container. | | mode | Choose trigger style: "default" (normal select trigger) or "button" (custom trigger node). | | leadingIcons | Icons shown before the selected value inside the trigger (default mode). | | button | Used when mode="button". If provided, this is the trigger. If not provided, children is used. | | children | When mode="button" and button is not provided, children is used as the trigger content. |

Options can be passed as:

  • primitives: ['ng', 'gh', 'ke']
  • objects: [{ label, value, ...extra }]

Sample usage

import { InputField } from "@timeax/form-palette"; // adjust import to your project

export function SelectExample() {
  return (
          <InputField
                  variant="select"
                  name="country"
                  label="Country"
                  options={[
                    { label: "Nigeria", value: "ng", description: "NG" },
                    { label: "Ghana", value: "gh", description: "GH" },
                    { label: "Kenya", value: "ke", description: "KE" },
                  ]}
                  searchable
                  searchPlaceholder="Search..."
                  clearable
                  emptyLabel="No selection"
                  placeholder="Select a country..."
                  virtualScroll
                  virtualScrollThreshold={80}
                  virtualScrollPageSize={30}
          />
  );
}

checkbox

| Prop | Description | | | |------------------------|------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|------------------------| | single | Render a single boolean checkbox instead of an option group. | | | | singleLabel | Label text shown next to the checkbox in single mode. | | | | singleDescription | Optional helper text shown under the single checkbox label. | | | | options | Option list for group mode. Accepts primitives or objects (normalized to { value, label, description?, disabled?, key? }). | | | | items | Alias for options (alternate naming). | | | | mappers | Override normalization: { mapValue?, mapLabel?, mapDescription?, mapDisabled?, mapKey? }. | | | | optionValue | Map item → option value (overrides mappers.mapValue). | | | | optionLabel | Map item → option label (overrides mappers.mapLabel). | | | | optionDescription | Map item → option description (overrides mappers.mapDescription). | | | | optionDisabled | Map item → disabled boolean (overrides mappers.mapDisabled). | | | | optionKey | Map item → stable React key (overrides mappers.mapKey). | | | | renderOption | Custom option renderer (gets { item, index, state, effectiveTristate, disabled, size, density, checkboxId, click(), checkbox }). | | | | tristate | Enable tri-state cycling for group options (none → true → false → none). | | | | layout | Group layout: "list" or "grid". | | | | columns | Grid columns when layout="grid" (default: 2). | | | | itemGapPx | Gap between options in px (defaults vary by layout). | | | | size | Checkbox size: "sm" | "md" | "lg"(default:"md"). | | density | Spacing preset: "compact" | "normal"(default:"normal"). | | | autoCap | Auto-capitalize option labels. | | | | groupClassName | Class applied to the options wrapper. | | | | className | Alias for groupClassName. | | | | optionClassName | Class applied to each option container. | | | | labelClassName | Class applied to label text (single + option labels). | | | | optionLabelClassName | Extra class applied to each option label. | | | | descriptionClassName | Extra class applied to option descriptions. | | | | id | Wrapper id. | | | | name | Base name used for hidden inputs in group mode. | | | | aria-label | Accessibility label for the group wrapper. | | | | aria-labelledby | Id of an element that labels the group wrapper. | | | | aria-describedby | Id of an element that describes the group wrapper. | | |

Value shape notes

  • Single mode: boolean | undefined

  • Group mode: CheckboxGroupEntry[] | undefined, where each entry is { value, state }.

    • "none" is an internal state only (it never appears in the public value).

Sample usage

// single (boolean)
<InputField
        name="agree_tos"
        label="Terms"
        variant="checkbox"
        single
        singleLabel="I agree to the Terms of Service"
/>

// group (with tri-state)
<InputField
        name="notify_prefs"
        label="Notify me"
        variant="checkbox"
        tristate
        layout="grid"
        columns={2}
        options={[
          { label: "Email", value: "email", description: "Marketing + account alerts" },
          { label: "SMS", value: "sms" },
          { label: "Push", value: "push" },
        ]}
/>

chips

| Prop | Description | | |------------------------|--------------------------------------------------------------------------|-------------------------------| | placeholder | Placeholde