@trackunit/react-form-components 1.11.18 → 1.11.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -1036,10 +1036,54 @@ const IndeterminateIcon = ({ className }) => (jsxRuntime.jsx("svg", { className:
1036
1036
  *
1037
1037
  * Checkboxes are used for multiple choices, not for mutually exclusive choices. Each checkbox works independently from other checkboxes in the list, therefore checking an additional box does not affect any other selections.
1038
1038
  *
1039
- * _**Do use** checkboxes to allow selection in a form, for filtering, terms and conditions to indicate agreement, and bulk actions in lists or tables._
1039
+ * ### When to use
1040
+ * Use checkboxes to allow selection in a form, for filtering, terms and conditions to indicate agreement, and bulk actions in lists or tables.
1040
1041
  *
1041
- * _**Do not use** checkboxes if the user can only select one option from a list, radio buttons should be used instead of checkboxes._
1042
+ * ### When not to use
1043
+ * Do not use checkboxes if the user can only select one option from a list. Use RadioGroup instead.
1042
1044
  *
1045
+ * @example Basic checkbox
1046
+ * ```tsx
1047
+ * import { Checkbox } from "@trackunit/react-form-components";
1048
+ * import { useState } from "react";
1049
+ *
1050
+ * const MyForm = () => {
1051
+ * const [accepted, setAccepted] = useState(false);
1052
+ *
1053
+ * return (
1054
+ * <Checkbox
1055
+ * label="I accept the terms and conditions"
1056
+ * checked={accepted}
1057
+ * onChange={(e) => setAccepted(e.target.checked)}
1058
+ * />
1059
+ * );
1060
+ * };
1061
+ * ```
1062
+ * @example Checkbox group for multiple selections
1063
+ * ```tsx
1064
+ * import { Checkbox } from "@trackunit/react-form-components";
1065
+ * import { useState } from "react";
1066
+ *
1067
+ * const NotificationSettings = () => {
1068
+ * const [notifications, setNotifications] = useState({
1069
+ * email: true,
1070
+ * sms: false,
1071
+ * push: true,
1072
+ * });
1073
+ *
1074
+ * const handleChange = (key: keyof typeof notifications) => (e: React.ChangeEvent<HTMLInputElement>) => {
1075
+ * setNotifications((prev) => ({ ...prev, [key]: e.target.checked }));
1076
+ * };
1077
+ *
1078
+ * return (
1079
+ * <div className="flex flex-col gap-2">
1080
+ * <Checkbox label="Email notifications" checked={notifications.email} onChange={handleChange("email")} />
1081
+ * <Checkbox label="SMS notifications" checked={notifications.sms} onChange={handleChange("sms")} />
1082
+ * <Checkbox label="Push notifications" checked={notifications.push} onChange={handleChange("push")} />
1083
+ * </div>
1084
+ * );
1085
+ * };
1086
+ * ```
1043
1087
  * @description A reference to the input element is provided as the `ref` prop.
1044
1088
  * @augments props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
1045
1089
  * @param {CheckboxProps} props - The props for the Checkbox component
@@ -2096,9 +2140,41 @@ const isValidHEXColor = (value) => {
2096
2140
  return hexRegex.test(value);
2097
2141
  };
2098
2142
  /**
2099
- * The ColorField component is used to enter color.
2100
- * ColorField validates that user enters a valid color address.
2143
+ * The `<ColorField>` component is used to select and enter colors.
2144
+ * It provides both a color picker and a text input for hex color codes,
2145
+ * with validation ensuring valid hex format (#RRGGBB).
2146
+ *
2147
+ * ### When to use
2148
+ * - Color selection in theming or customization forms
2149
+ * - Brand color configuration
2150
+ * - Any input requiring a valid hex color value
2151
+ *
2152
+ * ### When not to use
2153
+ * - When you need a full color palette with named colors
2154
+ * - When opacity/alpha channel is required (only supports 6-digit hex)
2155
+ *
2156
+ * @example Basic usage
2157
+ * ```tsx
2158
+ * import { ColorField } from "@trackunit/react-form-components";
2159
+ *
2160
+ * const [color, setColor] = useState("#3B82F6");
2161
+ *
2162
+ * <ColorField
2163
+ * label="Brand Color"
2164
+ * value={color}
2165
+ * onChange={(e) => setColor(e.target.value)}
2166
+ * />
2167
+ * ```
2168
+ * @example With validation
2169
+ * ```tsx
2170
+ * import { ColorField } from "@trackunit/react-form-components";
2101
2171
  *
2172
+ * <ColorField
2173
+ * label="Primary Color"
2174
+ * helpText="Enter a valid hex color (e.g., #FF5500)"
2175
+ * required
2176
+ * />
2177
+ * ```
2102
2178
  */
2103
2179
  const ColorField = react.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid, onBlur, fieldSize = "medium", style, disabled, readOnly, isWarning, inputClassName, ...inputProps }, ref) => {
2104
2180
  const renderAsDisabled = Boolean(disabled);
@@ -2157,11 +2233,52 @@ const ColorField = react.forwardRef(({ label, id, tip, helpText, errorMessage, h
2157
2233
  ColorField.displayName = "ColorField";
2158
2234
 
2159
2235
  /**
2160
- * The date field component is used for entering date values.
2236
+ * The date field component is used for entering date values with a native date picker.
2161
2237
  *
2162
- * _**Do use**_ the DateField for date input.
2238
+ * ### When to use
2239
+ * Use DateField for selecting calendar dates such as birthdates, deadlines, or scheduling.
2163
2240
  *
2164
- * _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
2241
+ * ### When not to use
2242
+ * Do not use DateField for non-serialized dates or free-form date text input. Use TextField instead.
2243
+ *
2244
+ * @example Basic date field
2245
+ * ```tsx
2246
+ * import { DateField } from "@trackunit/react-form-components";
2247
+ * import { useState } from "react";
2248
+ *
2249
+ * const MyForm = () => {
2250
+ * const [date, setDate] = useState("");
2251
+ *
2252
+ * return (
2253
+ * <DateField
2254
+ * label="Start Date"
2255
+ * value={date}
2256
+ * onChange={(e) => setDate(e.target.value)}
2257
+ * />
2258
+ * );
2259
+ * };
2260
+ * ```
2261
+ * @example Date field with constraints
2262
+ * ```tsx
2263
+ * import { DateField } from "@trackunit/react-form-components";
2264
+ * import { useState } from "react";
2265
+ *
2266
+ * const BookingForm = () => {
2267
+ * const [checkIn, setCheckIn] = useState("");
2268
+ * const today = new Date().toISOString().split("T")[0];
2269
+ *
2270
+ * return (
2271
+ * <DateField
2272
+ * label="Check-in Date"
2273
+ * value={checkIn}
2274
+ * onChange={(e) => setCheckIn(e.target.value)}
2275
+ * min={today}
2276
+ * helpText="Select a date from today onwards"
2277
+ * required
2278
+ * />
2279
+ * );
2280
+ * };
2281
+ * ```
2165
2282
  */
2166
2283
  const DateField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, "data-testid": dataTestId, ref, ...rest }) => {
2167
2284
  const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
@@ -2229,8 +2346,63 @@ const DropZoneDefaultLabel = () => (jsxRuntime.jsx(Trans, { components: {
2229
2346
  }, i18nKey: "dropzone.label.default", values: {} }));
2230
2347
 
2231
2348
  /**
2232
- * The Drop Zone can be used to drag and drop files or to browse and select files from the file system.
2349
+ * The `<DropZone>` component provides a drag-and-drop area for file uploads.
2350
+ * Users can either drag files onto the zone or click to browse the file system.
2351
+ *
2352
+ * ### When to use
2353
+ * - Drag-and-drop file upload experience
2354
+ * - Batch file uploads
2355
+ * - When visual feedback during drag is important
2356
+ *
2357
+ * ### When not to use
2358
+ * - Simple single file uploads - use `UploadField` instead
2359
+ * - When form field styling (label, help text) is needed - use `UploadField`
2360
+ *
2361
+ * @example Basic usage
2362
+ * ```tsx
2363
+ * import { DropZone } from "@trackunit/react-form-components";
2364
+ *
2365
+ * <DropZone
2366
+ * filesSelected={(files) => handleFiles(files)}
2367
+ * accept="image/*"
2368
+ * />
2369
+ * ```
2370
+ * @example With custom label
2371
+ * ```tsx
2372
+ * import { DropZone } from "@trackunit/react-form-components";
2233
2373
  *
2374
+ * <DropZone
2375
+ * filesSelected={(files) => handleFiles(files)}
2376
+ * label={
2377
+ * <span>
2378
+ * <strong>Drop files here</strong> or click to browse
2379
+ * </span>
2380
+ * }
2381
+ * accept=".pdf,.doc,.docx"
2382
+ * />
2383
+ * ```
2384
+ * @example Multiple files with size options
2385
+ * ```tsx
2386
+ * import { DropZone } from "@trackunit/react-form-components";
2387
+ *
2388
+ * <DropZone
2389
+ * filesSelected={(files) => {
2390
+ * Array.from(files).forEach(file => uploadFile(file));
2391
+ * }}
2392
+ * multiple
2393
+ * size="medium"
2394
+ * accept="image/png,image/jpeg"
2395
+ * />
2396
+ * ```
2397
+ * @example Disabled state
2398
+ * ```tsx
2399
+ * import { DropZone } from "@trackunit/react-form-components";
2400
+ *
2401
+ * <DropZone
2402
+ * filesSelected={(files) => handleFiles(files)}
2403
+ * disabled={isUploading}
2404
+ * />
2405
+ * ```
2234
2406
  * @param {DropZoneProps} props - The props for the DropZone component
2235
2407
  * @returns {ReactElement} DropZone component
2236
2408
  */
@@ -2342,9 +2514,53 @@ const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid":
2342
2514
  };
2343
2515
 
2344
2516
  /**
2345
- * The EmailField component is used to enter email.
2346
- * EmailField validates that user enters a valid email address.
2517
+ * The `<EmailField>` component is used to enter and validate email addresses.
2518
+ * It automatically validates the format on blur and displays appropriate error messages.
2519
+ *
2520
+ * ### When to use
2521
+ * - Collecting user email addresses in forms
2522
+ * - Contact forms that require email validation
2523
+ * - Any input that must be a valid email format
2524
+ *
2525
+ * ### When not to use
2526
+ * - For general text input - use `TextField` instead
2527
+ * - For URLs - use `UrlField` instead
2528
+ * - For phone numbers - use `PhoneField` instead
2529
+ *
2530
+ * @example Basic usage
2531
+ * ```tsx
2532
+ * import { EmailField } from "@trackunit/react-form-components";
2533
+ *
2534
+ * const [email, setEmail] = useState("");
2535
+ *
2536
+ * <EmailField
2537
+ * label="Email Address"
2538
+ * value={email}
2539
+ * onChange={(e) => setEmail(e.target.value)}
2540
+ * required
2541
+ * />
2542
+ * ```
2543
+ * @example With help text
2544
+ * ```tsx
2545
+ * import { EmailField } from "@trackunit/react-form-components";
2546
+ *
2547
+ * <EmailField
2548
+ * label="Work Email"
2549
+ * helpText="We'll use this to send notifications"
2550
+ * placeholder="name@company.com"
2551
+ * />
2552
+ * ```
2553
+ * @example With custom error message
2554
+ * ```tsx
2555
+ * import { EmailField } from "@trackunit/react-form-components";
2347
2556
  *
2557
+ * <EmailField
2558
+ * label="Email"
2559
+ * value={email}
2560
+ * onChange={(e) => setEmail(e.target.value)}
2561
+ * errorMessage={isEmailTaken ? "This email is already registered" : undefined}
2562
+ * />
2563
+ * ```
2348
2564
  */
2349
2565
  const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value, onChange, onBlur, isInvalid = false, ref, ...rest }) => {
2350
2566
  const htmlForId = id ? id : "emailField-" + sharedUtils.uuidv4();
@@ -2453,9 +2669,63 @@ const FormFieldSelectAdapterMulti = (props) => {
2453
2669
  };
2454
2670
 
2455
2671
  /**
2456
- * MultiSelectField is a custom Select component wrapped in the FormGroup component
2457
- * that allows you to select multiple options from a list.
2672
+ * The `<MultiSelectField>` component allows selecting multiple options from a dropdown list.
2673
+ * It wraps the select input with FormGroup for consistent form styling including label,
2674
+ * help text, and validation.
2675
+ *
2676
+ * ### When to use
2677
+ * - Selecting multiple items from a predefined list (tags, categories, permissions)
2678
+ * - When users need to see and manage all selected items
2679
+ * - Filtering by multiple criteria
2680
+ *
2681
+ * ### When not to use
2682
+ * - Single selection - use `SelectField` instead
2683
+ * - Very long lists - consider a searchable/async variant
2684
+ * - Binary choices - use `Checkbox` or `ToggleSwitchOption` instead
2685
+ *
2686
+ * @example Basic usage
2687
+ * ```tsx
2688
+ * import { MultiSelectField } from "@trackunit/react-form-components";
2689
+ *
2690
+ * const options = [
2691
+ * { value: "read", label: "Read" },
2692
+ * { value: "write", label: "Write" },
2693
+ * { value: "delete", label: "Delete" },
2694
+ * ];
2695
+ *
2696
+ * <MultiSelectField
2697
+ * label="Permissions"
2698
+ * options={options}
2699
+ * value={selectedPermissions}
2700
+ * onChange={(selected) => setSelectedPermissions(selected)}
2701
+ * />
2702
+ * ```
2703
+ * @example With placeholder and help text
2704
+ * ```tsx
2705
+ * import { MultiSelectField } from "@trackunit/react-form-components";
2706
+ *
2707
+ * <MultiSelectField
2708
+ * label="Categories"
2709
+ * options={categoryOptions}
2710
+ * value={selectedCategories}
2711
+ * onChange={(selected) => setSelectedCategories(selected)}
2712
+ * placeholder="Select categories..."
2713
+ * helpText="Select all that apply"
2714
+ * />
2715
+ * ```
2716
+ * @example With validation
2717
+ * ```tsx
2718
+ * import { MultiSelectField } from "@trackunit/react-form-components";
2458
2719
  *
2720
+ * <MultiSelectField
2721
+ * label="Required Tags"
2722
+ * options={tagOptions}
2723
+ * value={selectedTags}
2724
+ * onChange={(selected) => setSelectedTags(selected)}
2725
+ * required
2726
+ * errorMessage={selectedTags.length === 0 ? "Select at least one tag" : undefined}
2727
+ * />
2728
+ * ```
2459
2729
  * @param {MultiSelectFieldProps} props - The props for the MultiSelectField component
2460
2730
  * @returns {ReactElement} MultiSelectField component
2461
2731
  */
@@ -2517,9 +2787,53 @@ const validateNumber = (number, required = false, min, max) => {
2517
2787
  /**
2518
2788
  * The number field component is used for entering numeric values and includes controls for incrementally increasing or decreasing the value.
2519
2789
  *
2520
- * _**Do use**_ the NumberField when the controls to incrementally increase or decrease makes the task easier for the user.
2790
+ * ### When to use
2791
+ * Use NumberField when the controls to incrementally increase or decrease makes the task easier for the user, such as quantity selectors or numeric settings.
2521
2792
  *
2522
- * _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
2793
+ * ### When not to use
2794
+ * Do not use NumberField for non-serialized numbers or IDs. Use TextField instead.
2795
+ *
2796
+ * @example Basic number field
2797
+ * ```tsx
2798
+ * import { NumberField } from "@trackunit/react-form-components";
2799
+ * import { useState } from "react";
2800
+ *
2801
+ * const MyForm = () => {
2802
+ * const [quantity, setQuantity] = useState(1);
2803
+ *
2804
+ * return (
2805
+ * <NumberField
2806
+ * label="Quantity"
2807
+ * value={quantity}
2808
+ * onChange={(e) => setQuantity(Number(e.target.value))}
2809
+ * min={1}
2810
+ * max={100}
2811
+ * />
2812
+ * );
2813
+ * };
2814
+ * ```
2815
+ * @example Number field with validation
2816
+ * ```tsx
2817
+ * import { NumberField } from "@trackunit/react-form-components";
2818
+ * import { useState } from "react";
2819
+ *
2820
+ * const TemperatureInput = () => {
2821
+ * const [temp, setTemp] = useState(20);
2822
+ *
2823
+ * return (
2824
+ * <NumberField
2825
+ * label="Temperature (°C)"
2826
+ * value={temp}
2827
+ * onChange={(e) => setTemp(Number(e.target.value))}
2828
+ * min={-40}
2829
+ * max={60}
2830
+ * step={0.5}
2831
+ * helpText="Enter a value between -40 and 60"
2832
+ * required
2833
+ * />
2834
+ * );
2835
+ * };
2836
+ * ```
2523
2837
  */
2524
2838
  const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, ...rest }) => {
2525
2839
  const htmlForId = id ? id : "numberField-" + sharedUtils.uuidv4();
@@ -2666,11 +2980,60 @@ const PasswordBaseInput = ({ ref, fieldSize, ...rest }) => {
2666
2980
  };
2667
2981
 
2668
2982
  /**
2669
- * Password fields enter a password or other confidential information. Characters are masked as they are typed.
2983
+ * The `<PasswordField>` component is used to enter passwords or other confidential information.
2984
+ * Characters are masked as they are typed, with an option to toggle visibility.
2985
+ *
2986
+ * ### When to use
2987
+ * - Password input for login or registration forms
2988
+ * - Entering sensitive data that should be obfuscated (API keys, secrets)
2989
+ * - Any confidential text input
2990
+ *
2991
+ * ### When not to use
2992
+ * - Confirming user actions like deletion - use a Checkbox instead
2993
+ * - Non-sensitive text input - use `TextField` instead
2994
+ * - PIN codes - consider a specialized PIN input
2995
+ *
2996
+ * @example Basic usage
2997
+ * ```tsx
2998
+ * import { PasswordField } from "@trackunit/react-form-components";
2999
+ *
3000
+ * const [password, setPassword] = useState("");
2670
3001
  *
2671
- * _**Do use** when the user has to input a password or something that needs to be obfuscated_
3002
+ * <PasswordField
3003
+ * label="Password"
3004
+ * value={password}
3005
+ * onChange={(e) => setPassword(e.target.value)}
3006
+ * required
3007
+ * />
3008
+ * ```
3009
+ * @example With validation
3010
+ * ```tsx
3011
+ * import { PasswordField } from "@trackunit/react-form-components";
2672
3012
  *
2673
- * _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
3013
+ * <PasswordField
3014
+ * label="New Password"
3015
+ * value={password}
3016
+ * onChange={(e) => setPassword(e.target.value)}
3017
+ * helpText="Must be at least 8 characters"
3018
+ * errorMessage={password.length < 8 ? "Password too short" : undefined}
3019
+ * />
3020
+ * ```
3021
+ * @example Confirm password pattern
3022
+ * ```tsx
3023
+ * import { PasswordField } from "@trackunit/react-form-components";
3024
+ *
3025
+ * <PasswordField
3026
+ * label="Password"
3027
+ * value={password}
3028
+ * onChange={(e) => setPassword(e.target.value)}
3029
+ * />
3030
+ * <PasswordField
3031
+ * label="Confirm Password"
3032
+ * value={confirmPassword}
3033
+ * onChange={(e) => setConfirmPassword(e.target.value)}
3034
+ * errorMessage={confirmPassword !== password ? "Passwords do not match" : undefined}
3035
+ * />
3036
+ * ```
2674
3037
  */
2675
3038
  const PasswordField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }) => {
2676
3039
  const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
@@ -2733,19 +3096,52 @@ const phoneErrorMessage = (phoneNumber, required) => {
2733
3096
  };
2734
3097
 
2735
3098
  /**
2736
- * The PhoneField component is used to enter phone number.
2737
- * It is a wrapper around the PhoneInput component and the FormGroup component.
2738
- * It is used to render a phone number field with a label, a tip, a help text, a help addon and an error message.
3099
+ * The `<PhoneField>` component is used to enter and validate phone numbers.
3100
+ * It includes built-in validation for phone number format and displays appropriate error messages.
2739
3101
  *
2740
- * @param {string} [label] - The label for the component.
2741
- * @param {string} [tip] - The tip for the component.
2742
- * @param {string} [helpText] - The help text for the component.
2743
- * @param {string} [helpAddon] - The help addon for the component.
2744
- * @param {string} [errorMessage] - The error message for the component.
2745
- * @param {string} [defaultValue] - The default value for the component.
2746
- * @param {boolean} [disabled=false] - Whether the component is disabled or not.
2747
- * @param {string} [fieldSize="medium"] - The size of the input field.
2748
- * @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
3102
+ * ### When to use
3103
+ * - Collecting phone numbers in contact forms
3104
+ * - User profile phone number fields
3105
+ * - Any input requiring phone number validation
3106
+ *
3107
+ * ### When not to use
3108
+ * - General text input - use `TextField` instead
3109
+ * - International phone with country selector - consider specialized international phone component
3110
+ *
3111
+ * @example Basic usage
3112
+ * ```tsx
3113
+ * import { PhoneField } from "@trackunit/react-form-components";
3114
+ *
3115
+ * const [phone, setPhone] = useState("");
3116
+ *
3117
+ * <PhoneField
3118
+ * label="Phone Number"
3119
+ * value={phone}
3120
+ * onChange={(e) => setPhone(e.target.value)}
3121
+ * required
3122
+ * />
3123
+ * ```
3124
+ * @example With help text
3125
+ * ```tsx
3126
+ * import { PhoneField } from "@trackunit/react-form-components";
3127
+ *
3128
+ * <PhoneField
3129
+ * label="Mobile Phone"
3130
+ * helpText="Include country code for international numbers"
3131
+ * placeholder="+1 555 123 4567"
3132
+ * />
3133
+ * ```
3134
+ * @example With custom error handling
3135
+ * ```tsx
3136
+ * import { PhoneField } from "@trackunit/react-form-components";
3137
+ *
3138
+ * <PhoneField
3139
+ * label="Contact Phone"
3140
+ * value={phone}
3141
+ * onChange={(e) => setPhone(e.target.value)}
3142
+ * errorMessage={isPhoneDuplicate ? "This phone is already registered" : undefined}
3143
+ * />
3144
+ * ```
2749
3145
  */
2750
3146
  const PhoneField = ({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, "data-testid": dataTestId, name, onBlur, ref, ...rest }) => {
2751
3147
  const htmlForId = id ? id : "phoneField-" + sharedUtils.uuidv4();
@@ -2863,10 +3259,57 @@ const RadioGroupContext = react.createContext(null);
2863
3259
  *
2864
3260
  * Radio buttons are used for mutually exclusive choices, not for multiple choices. Only one radio button can be selected at a time. When a user chooses a new item, the previous choice is automatically deselected.
2865
3261
  *
2866
- * _**Do use** Radio buttons in forms, settings, or selections in a list._
3262
+ * ### When to use
3263
+ * Use RadioGroup in forms, settings, or selections in a list where only one option can be selected.
3264
+ *
3265
+ * ### When not to use
3266
+ * Do not use RadioGroup if a user can select many options from a list. Use Checkbox instead.
3267
+ *
3268
+ * @example Basic radio group
3269
+ * ```tsx
3270
+ * import { RadioGroup, RadioItem } from "@trackunit/react-form-components";
3271
+ * import { useState, ChangeEvent } from "react";
3272
+ *
3273
+ * const MyForm = () => {
3274
+ * const [size, setSize] = useState("medium");
3275
+ *
3276
+ * return (
3277
+ * <RadioGroup
3278
+ * id="size-selection"
3279
+ * label="Select size"
3280
+ * value={size}
3281
+ * onChange={(e: ChangeEvent<HTMLInputElement>) => setSize(e.target.value)}
3282
+ * >
3283
+ * <RadioItem label="Small" value="small" />
3284
+ * <RadioItem label="Medium" value="medium" />
3285
+ * <RadioItem label="Large" value="large" />
3286
+ * </RadioGroup>
3287
+ * );
3288
+ * };
3289
+ * ```
3290
+ * @example Inline radio group with descriptions
3291
+ * ```tsx
3292
+ * import { RadioGroup, RadioItem } from "@trackunit/react-form-components";
3293
+ * import { useState, ChangeEvent } from "react";
2867
3294
  *
2868
- * _**Do not use** Radio buttons if a user can select many option from a list, use checkboxes instead of radio buttons._
3295
+ * const PlanSelector = () => {
3296
+ * const [plan, setPlan] = useState("basic");
2869
3297
  *
3298
+ * return (
3299
+ * <RadioGroup
3300
+ * id="plan-selection"
3301
+ * label="Choose your plan"
3302
+ * value={plan}
3303
+ * onChange={(e: ChangeEvent<HTMLInputElement>) => setPlan(e.target.value)}
3304
+ * inline
3305
+ * >
3306
+ * <RadioItem label="Basic" value="basic" description="$9/month" />
3307
+ * <RadioItem label="Pro" value="pro" description="$29/month" />
3308
+ * <RadioItem label="Enterprise" value="enterprise" description="Contact us" />
3309
+ * </RadioGroup>
3310
+ * );
3311
+ * };
3312
+ * ```
2870
3313
  * @param {RadioGroupProps} props - The props for the RadioGroup component
2871
3314
  * @returns {ReactElement} RadioGroup component
2872
3315
  */
@@ -3253,8 +3696,69 @@ const CreatableSelectField = ({ allowCreateWhileLoading = false, onCreateOption,
3253
3696
  CreatableSelectField.displayName = "CreatableSelectField";
3254
3697
 
3255
3698
  /**
3256
- * MultiSelect is a custom Select component wrapped in the FormGroup component
3699
+ * SelectField is a dropdown select component wrapped in the FormGroup component for selecting a single option from a list.
3700
+ *
3701
+ * ### When to use
3702
+ * Use SelectField when users need to choose one option from a predefined list of 4 or more items.
3703
+ *
3704
+ * ### When not to use
3705
+ * Do not use SelectField for fewer than 4 options. Use RadioGroup instead for better usability with small option sets.
3706
+ *
3707
+ * @example Basic select field
3708
+ * ```tsx
3709
+ * import { SelectField } from "@trackunit/react-form-components";
3710
+ * import { useState } from "react";
3711
+ *
3712
+ * const options = [
3713
+ * { value: "us", label: "United States" },
3714
+ * { value: "uk", label: "United Kingdom" },
3715
+ * { value: "de", label: "Germany" },
3716
+ * { value: "fr", label: "France" },
3717
+ * ];
3718
+ *
3719
+ * const MyForm = () => {
3720
+ * const [country, setCountry] = useState<{ value: string; label: string } | null>(null);
3721
+ *
3722
+ * return (
3723
+ * <SelectField
3724
+ * label="Country"
3725
+ * options={options}
3726
+ * value={country}
3727
+ * onChange={(option) => setCountry(option)}
3728
+ * placeholder="Select a country"
3729
+ * />
3730
+ * );
3731
+ * };
3732
+ * ```
3733
+ * @example Async select field with search
3734
+ * ```tsx
3735
+ * import { SelectField } from "@trackunit/react-form-components";
3736
+ * import { useState } from "react";
3737
+ *
3738
+ * const MyAsyncForm = () => {
3739
+ * const [selected, setSelected] = useState(null);
3257
3740
  *
3741
+ * const loadOptions = async (inputValue: string) => {
3742
+ * const response = await fetch(`/api/users?search=${inputValue}`);
3743
+ * const users = await response.json();
3744
+ * return users.map((user: { id: string; name: string }) => ({
3745
+ * value: user.id,
3746
+ * label: user.name,
3747
+ * }));
3748
+ * };
3749
+ *
3750
+ * return (
3751
+ * <SelectField
3752
+ * label="Assign to user"
3753
+ * isAsync
3754
+ * loadOptions={loadOptions}
3755
+ * value={selected}
3756
+ * onChange={setSelected}
3757
+ * isClearable
3758
+ * />
3759
+ * );
3760
+ * };
3761
+ * ```
3258
3762
  * @param {SelectFieldProps} props - The props for the SelectField component
3259
3763
  */
3260
3764
  function SelectField({ ref, ...props }) {
@@ -3274,12 +3778,54 @@ const TextLengthIndicator = ({ length, maxLength }) => {
3274
3778
  };
3275
3779
 
3276
3780
  /**
3277
- * Use a text area when you need to allow users to enter a large amount of text, such as a comment or a description.
3781
+ * The `<TextAreaField>` component is used for multi-line text input.
3782
+ * Use when you need to allow users to enter a large amount of text, such as comments or descriptions.
3783
+ *
3784
+ * ### When to use
3785
+ * - Longer text inputs like comments, descriptions, or notes
3786
+ * - When the expected input is more than one line
3787
+ * - For free-form text that benefits from a larger input area
3788
+ *
3789
+ * ### When not to use
3790
+ * - Single-line inputs - use `TextField` instead
3791
+ * - Structured data like email or phone - use specialized field components
3792
+ * - Rich text editing - consider a rich text editor component
3793
+ *
3794
+ * @example Basic usage
3795
+ * ```tsx
3796
+ * import { TextAreaField } from "@trackunit/react-form-components";
3278
3797
  *
3279
- * _**Do use** Text areas for larger text inputs, such as comments or descriptions._
3798
+ * const [description, setDescription] = useState("");
3280
3799
  *
3281
- * _**Do not use** Text areas for small text inputs, such as single-line inputs._
3800
+ * <TextAreaField
3801
+ * label="Description"
3802
+ * value={description}
3803
+ * onChange={(e) => setDescription(e.target.value)}
3804
+ * placeholder="Enter a description..."
3805
+ * />
3806
+ * ```
3807
+ * @example With character limit
3808
+ * ```tsx
3809
+ * import { TextAreaField } from "@trackunit/react-form-components";
3810
+ *
3811
+ * <TextAreaField
3812
+ * label="Comment"
3813
+ * maxLength={500}
3814
+ * helpText="Add any additional notes"
3815
+ * required
3816
+ * />
3817
+ * ```
3818
+ * @example With validation error
3819
+ * ```tsx
3820
+ * import { TextAreaField } from "@trackunit/react-form-components";
3282
3821
  *
3822
+ * <TextAreaField
3823
+ * label="Notes"
3824
+ * value={notes}
3825
+ * onChange={(e) => setNotes(e.target.value)}
3826
+ * errorMessage={notes.length < 10 ? "Notes must be at least 10 characters" : undefined}
3827
+ * />
3828
+ * ```
3283
3829
  * @param {TextAreaFieldProps} props - The props for the TextAreaField component
3284
3830
  * @returns {ReactElement} TextAreaField component
3285
3831
  */
@@ -3300,6 +3846,61 @@ TextAreaField.displayName = "TextAreaField";
3300
3846
 
3301
3847
  /**
3302
3848
  * Text fields enable the user to interact with and input content and data. This component can be used for long and short form entries. Allow the size of the text input box to reflect the length of the content you expect the user to enter.
3849
+ *
3850
+ * ### When to use
3851
+ * Use text fields for short-form text input such as names, emails, or search queries.
3852
+ *
3853
+ * ### When not to use
3854
+ * Do not use text fields for multi-line text input. Use TextAreaField instead.
3855
+ *
3856
+ * @example Basic text field
3857
+ * ```tsx
3858
+ * import { TextField } from "@trackunit/react-form-components";
3859
+ * import { useState } from "react";
3860
+ *
3861
+ * const MyForm = () => {
3862
+ * const [name, setName] = useState("");
3863
+ *
3864
+ * return (
3865
+ * <TextField
3866
+ * label="Name"
3867
+ * value={name}
3868
+ * onChange={(e) => setName(e.target.value)}
3869
+ * placeholder="Enter your name"
3870
+ * />
3871
+ * );
3872
+ * };
3873
+ * ```
3874
+ * @example Text field with validation and help text
3875
+ * ```tsx
3876
+ * import { TextField } from "@trackunit/react-form-components";
3877
+ * import { useState } from "react";
3878
+ *
3879
+ * const MyForm = () => {
3880
+ * const [email, setEmail] = useState("");
3881
+ * const [error, setError] = useState<string | undefined>();
3882
+ *
3883
+ * const handleBlur = () => {
3884
+ * if (!email.includes("@")) {
3885
+ * setError("Please enter a valid email address");
3886
+ * } else {
3887
+ * setError(undefined);
3888
+ * }
3889
+ * };
3890
+ *
3891
+ * return (
3892
+ * <TextField
3893
+ * label="Email"
3894
+ * value={email}
3895
+ * onChange={(e) => setEmail(e.target.value)}
3896
+ * onBlur={handleBlur}
3897
+ * errorMessage={error}
3898
+ * helpText="We'll never share your email"
3899
+ * required
3900
+ * />
3901
+ * );
3902
+ * };
3903
+ * ```
3303
3904
  */
3304
3905
  const TextField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, isWarning, ref, ...rest }) => {
3305
3906
  const [valueLength, setValueLength] = react.useState(value ? `${value}`.length : 0);
@@ -3402,11 +4003,55 @@ const cvaToggleSwitchThumb = cssClassVarianceUtilities.cvaMerge(["block", "round
3402
4003
  });
3403
4004
 
3404
4005
  /**
3405
- * A checkbox input wrapper with role="switch". Used as an input element for **ToggleSwitchOption**
3406
- * or custom components.
4006
+ * The `<ToggleSwitch>` is a low-level checkbox input wrapper with `role="switch"`.
4007
+ * It renders just the switch control without label or description.
4008
+ *
4009
+ * **Not intended for standalone use** - use `ToggleSwitchOption` instead for forms.
4010
+ * This component is for building custom toggle implementations or wrapping in other components.
4011
+ *
4012
+ * ### When to use
4013
+ * - Building custom toggle components with different layouts
4014
+ * - Integrating a toggle into a component that provides its own label (e.g., menu items)
4015
+ * - Creating specialized switch controls
4016
+ *
4017
+ * ### When not to use
4018
+ * - Standard forms - use `ToggleSwitchOption` instead (includes label/description)
4019
+ * - Multiple selections - use `Checkbox` components instead
4020
+ *
4021
+ * @example Basic usage (in custom component)
4022
+ * ```tsx
4023
+ * import { ToggleSwitch } from "@trackunit/react-form-components";
3407
4024
  *
3408
- * Not intended for standalone use.
4025
+ * const [isEnabled, setIsEnabled] = useState(false);
4026
+ *
4027
+ * <ToggleSwitch
4028
+ * toggled={isEnabled}
4029
+ * onChange={(toggled) => setIsEnabled(toggled)}
4030
+ * />
4031
+ * ```
4032
+ * @example Inside a custom wrapper
4033
+ * ```tsx
4034
+ * import { ToggleSwitch } from "@trackunit/react-form-components";
4035
+ *
4036
+ * <div className="flex items-center gap-2">
4037
+ * <span>Dark Mode</span>
4038
+ * <ToggleSwitch
4039
+ * toggled={darkMode}
4040
+ * onChange={(toggled) => setDarkMode(toggled)}
4041
+ * size="small"
4042
+ * />
4043
+ * </div>
4044
+ * ```
4045
+ * @example Disabled state
4046
+ * ```tsx
4047
+ * import { ToggleSwitch } from "@trackunit/react-form-components";
3409
4048
  *
4049
+ * <ToggleSwitch
4050
+ * toggled={true}
4051
+ * onChange={() => {}}
4052
+ * disabled
4053
+ * />
4054
+ * ```
3410
4055
  * @param {ToggleSwitchProps} props - The props for the ToggleSwitch component
3411
4056
  * @returns {ReactElement} ToggleSwitch component
3412
4057
  */
@@ -3453,13 +4098,65 @@ const ToggleSwitch = react.forwardRef(({ onChange, onClick, preventDefaultOnClic
3453
4098
  ToggleSwitch.displayName = "ToggleSwitch";
3454
4099
 
3455
4100
  /**
3456
- * Use ToggleSwitchOption when you have to only enable/disable a feature.
3457
- * Wrapper component for ToggleSwitch.
4101
+ * The `<ToggleSwitchOption>` component is used for binary on/off settings in forms.
4102
+ * It combines a toggle switch with a label and optional description for complete form integration.
4103
+ *
4104
+ * ### When to use
4105
+ * - Enable/disable feature toggles in settings
4106
+ * - Binary choices where the action takes effect immediately
4107
+ * - Preferences that represent on/off states
4108
+ *
4109
+ * ### When not to use
4110
+ * - Multiple selections from a list - use `Checkbox` components instead
4111
+ * - Mutually exclusive options - use `RadioGroup` instead
4112
+ * - Actions requiring confirmation - use buttons with confirmation dialog
4113
+ *
4114
+ * @example Basic usage
4115
+ * ```tsx
4116
+ * import { ToggleSwitchOption } from "@trackunit/react-form-components";
4117
+ *
4118
+ * const [notifications, setNotifications] = useState(true);
3458
4119
  *
3459
- * _**Do use** ToggleSwitchOption in forms or settings._
4120
+ * <ToggleSwitchOption
4121
+ * id="notifications"
4122
+ * label="Enable Notifications"
4123
+ * toggled={notifications}
4124
+ * onChange={(toggled) => setNotifications(toggled)}
4125
+ * />
4126
+ * ```
4127
+ * @example With description
4128
+ * ```tsx
4129
+ * import { ToggleSwitchOption } from "@trackunit/react-form-components";
3460
4130
  *
3461
- * _**Do not use** ToggleSwitchOption if a user can select multiple options from a list, use checkboxes instead of toggle._
4131
+ * <ToggleSwitchOption
4132
+ * id="email-alerts"
4133
+ * label="Email Alerts"
4134
+ * description="Receive email notifications for important updates"
4135
+ * toggled={emailAlerts}
4136
+ * onChange={(toggled) => setEmailAlerts(toggled)}
4137
+ * />
4138
+ * ```
4139
+ * @example In a settings list
4140
+ * ```tsx
4141
+ * import { ToggleSwitchOption } from "@trackunit/react-form-components";
3462
4142
  *
4143
+ * <div className="space-y-4">
4144
+ * <ToggleSwitchOption
4145
+ * id="dark-mode"
4146
+ * label="Dark Mode"
4147
+ * description="Use dark theme throughout the application"
4148
+ * toggled={darkMode}
4149
+ * onChange={(toggled) => setDarkMode(toggled)}
4150
+ * />
4151
+ * <ToggleSwitchOption
4152
+ * id="auto-save"
4153
+ * label="Auto-save"
4154
+ * description="Automatically save changes as you type"
4155
+ * toggled={autoSave}
4156
+ * onChange={(toggled) => setAutoSave(toggled)}
4157
+ * />
4158
+ * </div>
4159
+ * ```
3463
4160
  * @param {ToggleSwitchOptionProps} props - The props for the ToggleSwitchOption component
3464
4161
  * @returns {ReactElement} ToggleSwitchOption component
3465
4162
  */
@@ -3499,7 +4196,53 @@ const UploadInput = ({ disabled, acceptedTypes, nonInteractive, uploadLabel, mul
3499
4196
  UploadInput.displayName = "UploadInput";
3500
4197
 
3501
4198
  /**
3502
- * Upload fields enable the user to upload Files.
4199
+ * The `<UploadField>` component enables users to upload files through a form field.
4200
+ * It wraps the UploadInput with FormGroup for consistent form styling including label,
4201
+ * help text, and error handling.
4202
+ *
4203
+ * ### When to use
4204
+ * - Single file upload in forms (documents, images)
4205
+ * - When you need form field styling (label, validation messages)
4206
+ * - File attachments in form submissions
4207
+ *
4208
+ * ### When not to use
4209
+ * - Drag and drop file uploads - use `DropZone` instead
4210
+ * - Multiple file uploads with preview - consider specialized upload component
4211
+ * - Large file uploads requiring progress indication
4212
+ *
4213
+ * @example Basic usage
4214
+ * ```tsx
4215
+ * import { UploadField } from "@trackunit/react-form-components";
4216
+ *
4217
+ * <UploadField
4218
+ * label="Upload Document"
4219
+ * accept=".pdf,.doc,.docx"
4220
+ * onChange={(file) => handleFileUpload(file)}
4221
+ * />
4222
+ * ```
4223
+ * @example With validation
4224
+ * ```tsx
4225
+ * import { UploadField } from "@trackunit/react-form-components";
4226
+ *
4227
+ * <UploadField
4228
+ * label="Profile Picture"
4229
+ * accept="image/*"
4230
+ * helpText="Max file size: 5MB"
4231
+ * errorMessage={fileTooLarge ? "File exceeds 5MB limit" : undefined}
4232
+ * required
4233
+ * />
4234
+ * ```
4235
+ * @example In a form context
4236
+ * ```tsx
4237
+ * import { UploadField } from "@trackunit/react-form-components";
4238
+ *
4239
+ * <UploadField
4240
+ * label="Attachment"
4241
+ * tip="Optional supporting document"
4242
+ * accept=".pdf"
4243
+ * onChange={(file) => setAttachment(file)}
4244
+ * />
4245
+ * ```
3503
4246
  */
3504
4247
  const UploadField = ({ label, id, tip, helpText, errorMessage, isInvalid, className, value, "data-testid": dataTestId, ref, ...rest }) => {
3505
4248
  const renderAsInvalid = isInvalid || Boolean(errorMessage);
@@ -3551,9 +4294,53 @@ const UrlBaseInput = ({ isInvalid = false, "data-testid": dataTestId, disabled =
3551
4294
  };
3552
4295
 
3553
4296
  /**
3554
- * The UrlField component is used to enter url.
3555
- * UrlField validates that user enters a valid web address.
4297
+ * The `<UrlField>` component is used to enter and validate URLs/web addresses.
4298
+ * It automatically validates the format on blur and displays appropriate error messages.
4299
+ *
4300
+ * ### When to use
4301
+ * - Collecting website URLs in forms
4302
+ * - Social media profile links
4303
+ * - Any input requiring valid URL format
3556
4304
  *
4305
+ * ### When not to use
4306
+ * - General text input - use `TextField` instead
4307
+ * - Email addresses - use `EmailField` instead
4308
+ * - Internal application links - use standard link/routing
4309
+ *
4310
+ * @example Basic usage
4311
+ * ```tsx
4312
+ * import { UrlField } from "@trackunit/react-form-components";
4313
+ *
4314
+ * const [website, setWebsite] = useState("");
4315
+ *
4316
+ * <UrlField
4317
+ * label="Website"
4318
+ * value={website}
4319
+ * onChange={(e) => setWebsite(e.target.value)}
4320
+ * placeholder="https://example.com"
4321
+ * />
4322
+ * ```
4323
+ * @example With help text
4324
+ * ```tsx
4325
+ * import { UrlField } from "@trackunit/react-form-components";
4326
+ *
4327
+ * <UrlField
4328
+ * label="Company Website"
4329
+ * helpText="Enter the full URL including https://"
4330
+ * required
4331
+ * />
4332
+ * ```
4333
+ * @example With custom validation
4334
+ * ```tsx
4335
+ * import { UrlField } from "@trackunit/react-form-components";
4336
+ *
4337
+ * <UrlField
4338
+ * label="Documentation URL"
4339
+ * value={docUrl}
4340
+ * onChange={(e) => setDocUrl(e.target.value)}
4341
+ * errorMessage={!docUrl.includes("docs") ? "URL must point to documentation" : undefined}
4342
+ * />
4343
+ * ```
3557
4344
  */
3558
4345
  const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, isInvalid = false, value, onBlur, ref, ...rest }) => {
3559
4346
  const htmlForId = id ? id : "urlField-" + sharedUtils.uuidv4();