cleanplate 0.2.0 → 0.2.2

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.
@@ -0,0 +1,230 @@
1
+ # Container Component
2
+
3
+ Purpose: A layout wrapper that controls display type, width, spacing (margin, padding, gap), and flex alignment. Use it to structure content, create flex layouts, and apply consistent spacing. Below the mobile breakpoint (600px), width variants collapse to full width for a responsive default. **Spacing (margin, padding, gap)** uses the **framework-wide suffix rule** (same for all CleanPlate components); see `llms.txt`.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | children | React.ReactNode | no | — | Content to render inside the container. |
10
+ | margin | string \| string[] | no | "m-0" | Spacing **suffix** for outer margin. The component adds the `m-` prefix (e.g. `"0"` → m-0, `"b-2"` → m-b-2). Use a single string or array: `"0"`, `["1", "b-2"]`. |
11
+ | padding | string \| string[] | no | "p-4" | Spacing **suffix** for inner padding. The component adds the `p-` prefix (e.g. `"4"` → p-4, `"x-2"` → p-x-2). Use a single string or array: `"4"`, `["2", "x-4"]`. |
12
+ | display | "block" \| "flex" \| "inline-block" \| "" | no | "" | Layout mode. Use `"flex"` for flexbox; leave empty for no display class. |
13
+ | align | "start" \| "center" \| "end" \| "" | no | "" | Flex align-items. Only applies when `display="flex"`. |
14
+ | justify | "space-between" \| "center" \| "space-around" \| "space-evenly" \| "flex-end" \| "flex-start" \| "" | no | "" | Flex justify-content. Only applies when `display="flex"`. |
15
+ | width | "small" \| "medium" \| "large" \| "extra-large" \| "quarter" \| "half" \| "three-quarters" \| "full" \| "" | no | "" | Width variant. At viewports ≤600px, all variants become full width. |
16
+ | gap | string \| string[] | no | "4" | Spacing **suffix** for gap between flex children. The component adds the `g-` prefix (e.g. `"4"` → g-4). Meaningful when `display="flex"`. Use `"4"` or `["2", "3"]` for multiple. |
17
+ | showBorder | boolean | no | false | When true, shows a border around the container. |
18
+ | className | string | no | "" | Additional class names for the root element. |
19
+ | onClick | function | no | — | Click handler for the root div. |
20
+ | style | React.CSSProperties | no | — | Inline styles for the root element. |
21
+ | ...rest | React.HTMLAttributes<HTMLDivElement> | no | — | Any other div attributes (e.g. `id`, `data-*`, `aria-*`) are forwarded. |
22
+
23
+ ## Types
24
+
25
+ ### SpacingOption
26
+ ```typescript
27
+ type SpacingOption = (typeof SPACING_OPTIONS)[number];
28
+ ```
29
+
30
+ ### ContainerDisplay
31
+ ```typescript
32
+ type ContainerDisplay = "inline-block" | "block" | "flex";
33
+ ```
34
+
35
+ ### ContainerWidth
36
+ ```typescript
37
+ type ContainerWidth =
38
+ | "small"
39
+ | "medium"
40
+ | "large"
41
+ | "extra-large"
42
+ | "quarter"
43
+ | "half"
44
+ | "three-quarters"
45
+ | "full";
46
+ ```
47
+
48
+ ### ContainerJustify
49
+ ```typescript
50
+ type ContainerJustify =
51
+ | "space-between"
52
+ | "center"
53
+ | "space-around"
54
+ | "space-evenly"
55
+ | "flex-end"
56
+ | "flex-start";
57
+ ```
58
+
59
+ ### ContainerAlign
60
+ ```typescript
61
+ type ContainerAlign = "start" | "center" | "end";
62
+ ```
63
+
64
+ ### ContainerSpacing
65
+ ```typescript
66
+ type ContainerSpacing = string | SpacingOption[];
67
+ ```
68
+
69
+ ### ContainerProps
70
+ ```typescript
71
+ interface ContainerProps extends React.HTMLAttributes<HTMLDivElement> {
72
+ children?: React.ReactNode;
73
+ margin?: ContainerSpacing;
74
+ padding?: ContainerSpacing;
75
+ display?: ContainerDisplay | "";
76
+ align?: ContainerAlign | "";
77
+ justify?: ContainerJustify | "";
78
+ width?: ContainerWidth | "";
79
+ showBorder?: boolean;
80
+ className?: string;
81
+ onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
82
+ style?: React.CSSProperties;
83
+ gap?: ContainerSpacing;
84
+ }
85
+ ```
86
+
87
+ ## Usage Examples
88
+
89
+ ### Block container
90
+
91
+ ```jsx
92
+ import { Container } from "cleanplate";
93
+
94
+ export const Example = () => (
95
+ <Container display="block" padding="4" showBorder>
96
+ <p>Block container: full width, content stacks vertically.</p>
97
+ </Container>
98
+ );
99
+ ```
100
+
101
+ ### Flex container with alignment
102
+
103
+ ```jsx
104
+ import { Container } from "cleanplate";
105
+ import { Button } from "cleanplate";
106
+
107
+ export const Example = () => (
108
+ <Container
109
+ display="flex"
110
+ justify="space-between"
111
+ align="center"
112
+ padding="3"
113
+ gap="2"
114
+ showBorder
115
+ >
116
+ <span>Left</span>
117
+ <Button size="small">Action</Button>
118
+ </Container>
119
+ );
120
+ ```
121
+
122
+ ### Width variants
123
+
124
+ ```jsx
125
+ import { Container } from "cleanplate";
126
+
127
+ export const Example = () => (
128
+ <>
129
+ <Container width="small" showBorder padding="3">Small</Container>
130
+ <Container width="medium" showBorder padding="3">Medium</Container>
131
+ <Container width="half" showBorder padding="3">Half</Container>
132
+ <Container width="full" showBorder padding="3">Full</Container>
133
+ </>
134
+ );
135
+ ```
136
+
137
+ ### Inline-block (side by side)
138
+
139
+ ```jsx
140
+ import { Container } from "cleanplate";
141
+
142
+ export const Example = () => (
143
+ <Container display="inline-block" showBorder padding="2" margin="r-2">
144
+ Block 1
145
+ </Container>
146
+ <Container display="inline-block" showBorder padding="2">
147
+ Block 2
148
+ </Container>
149
+ );
150
+ ```
151
+
152
+ ### Margin and padding
153
+
154
+ ```jsx
155
+ import { Container } from "cleanplate";
156
+
157
+ export const Example = () => (
158
+ <>
159
+ <Container margin="2" padding="4" showBorder>
160
+ Single suffix values
161
+ </Container>
162
+ <Container margin={["1", "b-3"]} padding={["2", "x-4"]} showBorder>
163
+ Multiple suffixes (component adds m- / p- prefix)
164
+ </Container>
165
+ </>
166
+ );
167
+ ```
168
+
169
+ ### Flex grid (quarters)
170
+
171
+ ```jsx
172
+ import { Container } from "cleanplate";
173
+
174
+ export const Example = () => (
175
+ <Container display="flex" padding="2" gap="2" showBorder>
176
+ <Container width="quarter" showBorder padding="3">1</Container>
177
+ <Container width="quarter" showBorder padding="3">2</Container>
178
+ <Container width="quarter" showBorder padding="3">3</Container>
179
+ <Container width="quarter" showBorder padding="3">4</Container>
180
+ </Container>
181
+ );
182
+ ```
183
+
184
+ ### Clickable container
185
+
186
+ ```jsx
187
+ import { Container } from "cleanplate";
188
+
189
+ export const Example = () => (
190
+ <Container
191
+ showBorder
192
+ padding="4"
193
+ onClick={() => console.log("Clicked")}
194
+ >
195
+ Clickable area
196
+ </Container>
197
+ );
198
+ ```
199
+
200
+ ### With custom class and style
201
+
202
+ ```jsx
203
+ import { Container } from "cleanplate";
204
+
205
+ export const Example = () => (
206
+ <Container
207
+ className="my-wrapper"
208
+ style={{ minHeight: 200 }}
209
+ padding="4"
210
+ showBorder
211
+ >
212
+ Custom wrapper
213
+ </Container>
214
+ );
215
+ ```
216
+
217
+ ## Behavior Notes
218
+
219
+ - **Responsive width:** For viewport width ≤600px (mobile breakpoint), all `width` variants are overridden to `100%` in CSS. No prop change is required.
220
+ - **Flex:** When `display="flex"`, the root uses `display: flex` and `flex-wrap: wrap`. Use `align` and `justify` to control alignment; use `gap` for spacing between children.
221
+ - **Spacing:** `margin`, `padding`, and `gap` accept the **spacing suffix** (the component adds the `m-`, `p-`, or `g-` prefix via `getSpacingClass`). Use a single string (e.g. `"4"`, `"0"`, `"b-2"`) or an array of suffixes (e.g. `["1", "b-2"]`). Valid suffixes include `"0"`–`"9"`, `"auto"`, and directional forms like `"x-2"`, `"y-3"`, `"t-0"`, `"r-1"`, `"b-2"`, `"l-3"` (see `SPACING_OPTIONS`). **Note:** The component’s default props are currently `"m-0"` and `"p-4"` (full tokens); internally the util expects suffixes, so when passing values explicitly use suffix form (e.g. `"0"`, `"4"`).
222
+ - **Empty layout props:** Passing `""` or omitting `display`, `align`, `justify`, or `width` means no corresponding class is applied.
223
+ - **Border:** `showBorder` only affects border visibility; the container always reserves border space (border is 1px solid, transparent when not shown).
224
+ - The root element is a `div`; all standard HTML div attributes and ref are supported via `...rest`.
225
+
226
+ ## Related Components / Links
227
+
228
+ - Typography (often used inside Container for text)
229
+ - Button (commonly placed inside flex Containers)
230
+ - MediaObject (often wrapped in Container for layout)
@@ -0,0 +1,175 @@
1
+ # Dropdown Component
2
+
3
+ Purpose: A floating panel that shows content relative to a trigger. Use it for menus, option lists, or any content that opens on click. Supports 12 placements, optional flip/shift to stay in viewport, and three trigger modes: a `trigger` element, a `renderTrigger` function, or a `triggerLabel` for a default button.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | trigger | React.ReactElement | no | — | Trigger element to clone; ref and onClick are attached. Omit when using `renderTrigger` or `triggerLabel`. |
10
+ | content | React.ReactElement | yes | — | Content shown in the floating panel. Receives `onClose` and `className` when cloned. |
11
+ | placement | DropdownPlacement | no | "bottom-end" | Preferred position relative to trigger (e.g. "bottom-end", "top-start"). |
12
+ | offset | number | no | 4 | Gap in pixels between trigger and panel. |
13
+ | shift | boolean | no | true | When true, shift panel to stay inside viewport. |
14
+ | flip | boolean | no | true | When true, flip to opposite side when there is no space. |
15
+ | closeOnClickOutside | boolean | no | true | Close when user clicks outside trigger and panel. |
16
+ | closeOnEscape | boolean | no | true | Close when user presses Escape. |
17
+ | className | string | no | "" | Class name for the wrapper div. |
18
+ | contentClassName | string | no | "" | Class name applied to the cloned content element. |
19
+ | renderTrigger | (params: DropdownRenderTriggerParams) => React.ReactNode | no | — | Render prop for a custom trigger; receives `isOpen`, `isAnimating`, `placement`, `toggle`, `close`, `triggerProps`. |
20
+ | triggerLabel | string | no | — | Label for the default button trigger. Use when neither `trigger` nor `renderTrigger` is provided. |
21
+
22
+ ## Types
23
+
24
+ ### DropdownPlacement
25
+ ```typescript
26
+ type DropdownPlacement =
27
+ | "top" | "top-start" | "top-end"
28
+ | "bottom" | "bottom-start" | "bottom-end"
29
+ | "left" | "left-start" | "left-end"
30
+ | "right" | "right-start" | "right-end";
31
+ ```
32
+
33
+ ### DropdownTriggerProps
34
+ ```typescript
35
+ interface DropdownTriggerProps {
36
+ ref: RefObject<HTMLElement | null>;
37
+ onClick: (e: React.MouseEvent<HTMLElement>) => void;
38
+ className: string;
39
+ role: string;
40
+ "aria-expanded": boolean;
41
+ "aria-haspopup": string;
42
+ }
43
+ ```
44
+
45
+ ### DropdownRenderTriggerParams
46
+ ```typescript
47
+ interface DropdownRenderTriggerParams {
48
+ isOpen: boolean;
49
+ isAnimating: boolean;
50
+ placement: DropdownPlacement;
51
+ toggle: () => void;
52
+ close: () => void;
53
+ triggerProps: DropdownTriggerProps;
54
+ }
55
+ ```
56
+
57
+ ### DropdownProps
58
+ ```typescript
59
+ interface DropdownProps {
60
+ trigger?: React.ReactElement;
61
+ content: React.ReactElement;
62
+ placement?: DropdownPlacement;
63
+ offset?: number;
64
+ shift?: boolean;
65
+ flip?: boolean;
66
+ closeOnClickOutside?: boolean;
67
+ closeOnEscape?: boolean;
68
+ className?: string;
69
+ contentClassName?: string;
70
+ renderTrigger?: (params: DropdownRenderTriggerParams) => React.ReactNode;
71
+ triggerLabel?: string;
72
+ }
73
+ ```
74
+
75
+ ## Usage Examples
76
+
77
+ ### With trigger element
78
+
79
+ ```jsx
80
+ import { Dropdown, Button } from "cleanplate";
81
+
82
+ const MenuContent = ({ onClose }) => (
83
+ <div style={{ padding: "var(--space-2)" }}>
84
+ <button onClick={onClose}>Close</button>
85
+ <p>Menu items here</p>
86
+ </div>
87
+ );
88
+
89
+ export const Example = () => (
90
+ <Dropdown
91
+ trigger={<Button>Open Menu</Button>}
92
+ content={<MenuContent />}
93
+ placement="bottom-end"
94
+ />
95
+ );
96
+ ```
97
+
98
+ ### With triggerLabel
99
+
100
+ ```jsx
101
+ import { Dropdown } from "cleanplate";
102
+
103
+ export const Example = () => (
104
+ <Dropdown
105
+ triggerLabel="Select Option"
106
+ content={<MenuContent />}
107
+ placement="bottom-end"
108
+ />
109
+ );
110
+ ```
111
+
112
+ ### With renderTrigger
113
+
114
+ ```jsx
115
+ import { Dropdown, Button } from "cleanplate";
116
+
117
+ export const Example = () => (
118
+ <Dropdown
119
+ renderTrigger={({ isOpen, triggerProps }) => (
120
+ <Button {...triggerProps}>
121
+ {isOpen ? "Close" : "Open"}
122
+ </Button>
123
+ )}
124
+ content={<MenuContent />}
125
+ />
126
+ );
127
+ ```
128
+
129
+ ### Placement and offset
130
+
131
+ ```jsx
132
+ <Dropdown
133
+ trigger={<Button>Menu</Button>}
134
+ content={<MenuContent />}
135
+ placement="top-start"
136
+ offset={8}
137
+ />
138
+ ```
139
+
140
+ ### Disable flip / shift
141
+
142
+ ```jsx
143
+ <Dropdown
144
+ trigger={<Button>Menu</Button>}
145
+ content={<MenuContent />}
146
+ placement="top"
147
+ flip={false}
148
+ shift={false}
149
+ />
150
+ ```
151
+
152
+ ### Close behavior
153
+
154
+ ```jsx
155
+ <Dropdown
156
+ trigger={<Button>Menu</Button>}
157
+ content={<MenuContent />}
158
+ closeOnClickOutside={false}
159
+ closeOnEscape={true}
160
+ />
161
+ ```
162
+
163
+ ## Behavior Notes
164
+
165
+ - **Trigger modes:** Exactly one of `trigger`, `renderTrigger`, or `triggerLabel` must be used; the component throws if none are provided.
166
+ - **Content:** The `content` element is cloned; the component injects `onClose` and merges `className` so the panel can close and be styled.
167
+ - **Positioning:** Placement is applied via CSS classes; when `flip` or `shift` are true, the component adjusts placement/position so the panel stays in view.
168
+ - **Accessibility:** The trigger receives `aria-expanded` and `aria-haspopup`; the panel has `role="menu"`. Escape and (optionally) click-outside close the dropdown.
169
+ - **Animation:** Opening/closing uses CSS classes (`dropdown-opening` / `dropdown-closing`); a short delay (e.g. 150ms) is used before unmounting so the close animation can run.
170
+
171
+ ## Related Components / Links
172
+
173
+ - Button (commonly used as trigger or inside renderTrigger)
174
+ - MenuList (often used inside dropdown content for menu items)
175
+ - Icon (used in the default trigger when `triggerLabel` is set for arrow icons)
package/docs/Footer.md ADDED
@@ -0,0 +1,93 @@
1
+ # Footer Component
2
+
3
+ Purpose: Customizable footer with copyright text, optional powered-by link, and custom content via children. Use for app footers with branding, legal links, or column layouts. Supports sizes (small, medium, large), variants (light, dark), and margin spacing.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | margin | string \| SpacingOption[] | no | "0" | Spacing suffix(s) for outer margin; component adds m- prefix. |
10
+ | size | "small" \| "medium" \| "large" | no | "large" | Size of the footer. |
11
+ | variant | "light" \| "dark" | no | "light" | Visual variant. |
12
+ | brandName | string | no | "" | Brand name shown in copyright (e.g. "Acme Inc"). |
13
+ | poweredByLabel | string | no | "" | Label for the powered-by link (e.g. "Powered by X"). |
14
+ | poweredByLink | string | no | "" | URL for the powered-by link; shown when poweredByLabel is also set. |
15
+ | children | ReactNode | no | — | Custom content rendered above the copyright line. |
16
+ | className | string | no | "" | Additional class names for the root element. |
17
+
18
+ ## Types
19
+
20
+ ### FooterSize
21
+ ```typescript
22
+ type FooterSize = "small" | "medium" | "large";
23
+ ```
24
+
25
+ ### FooterVariant
26
+ ```typescript
27
+ type FooterVariant = "light" | "dark";
28
+ ```
29
+
30
+ ### FooterMargin
31
+ ```typescript
32
+ type FooterMargin = string | SpacingOption[];
33
+ ```
34
+
35
+ ### FooterProps
36
+ ```typescript
37
+ interface FooterProps {
38
+ margin?: FooterMargin;
39
+ size?: FooterSize;
40
+ variant?: FooterVariant;
41
+ brandName?: string;
42
+ poweredByLabel?: string;
43
+ poweredByLink?: string;
44
+ children?: React.ReactNode;
45
+ className?: string;
46
+ }
47
+ ```
48
+
49
+ ## Usage Examples
50
+
51
+ ### Basic
52
+
53
+ ```jsx
54
+ import { Footer } from "cleanplate";
55
+
56
+ <Footer brandName="Acme Inc" />
57
+ ```
58
+
59
+ ### With powered-by link
60
+
61
+ ```jsx
62
+ <Footer
63
+ brandName="Acme Inc"
64
+ poweredByLabel="Powered by Sivadass"
65
+ poweredByLink="https://sivadass.in"
66
+ />
67
+ ```
68
+
69
+ ### With custom content
70
+
71
+ ```jsx
72
+ <Footer brandName="Acme Inc">
73
+ <Container display="flex" gap="4">
74
+ <Container width="quarter">
75
+ <Typography variant="h6" margin={["0", "b-2"]}>Links</Typography>
76
+ <ul><li><a href="/contact">Contact</a></li></ul>
77
+ </Container>
78
+ </Container>
79
+ </Footer>
80
+ ```
81
+
82
+ ## Behavior Notes
83
+
84
+ - **Copyright:** Uses current year and `brandName` in "© {year} {brandName}. All rights reserved."
85
+ - **Powered-by:** Link shows only when both `poweredByLabel` and `poweredByLink` are set; link has `rel="noopener noreferrer"`.
86
+ - **children:** Rendered in a wrapper div above the copyright line.
87
+ - **Margin:** Uses the suffix API (e.g. `"0"` → m-0).
88
+
89
+ ## Related Components / Links
90
+
91
+ - Container (layout for footer columns or custom content)
92
+ - Typography (used internally for copyright)
93
+ - Header (often paired with Footer for app layout)
@@ -0,0 +1,115 @@
1
+ # FormControls
2
+
3
+ FormControls is a set of form primitives exported as a namespace: `FormControls.Input`, `FormControls.Select`, `FormControls.TextArea`, `FormControls.Date`, `FormControls.Checkbox`, `FormControls.Radio`, `FormControls.File`, `FormControls.Toggle`, `FormControls.Stepper`. Use them to build forms with consistent styling, labels, validation messages, and optional fluid layout. Common props across controls: label, isDisabled, isRequired, isFluid, className, error.
4
+
5
+ ## Controls overview
6
+
7
+ | Control | Purpose | Key props |
8
+ | --- | --- | --- |
9
+ | Input | Single-line text | placeholder, value, onChange(e), type |
10
+ | TextArea | Multi-line text | placeholder, value, onChange(e) |
11
+ | Select | Single or multi select dropdown | options ({ label, value }[]), value, onChange(option \| option[]), isMulti, placeholder |
12
+ | Date | Day/month/year picker (DD-MMM-YYYY) | defaultValue, onChange(dateValue: string) |
13
+ | Checkbox | Single checkbox | value (boolean), onChange(checked: boolean) |
14
+ | Radio | Radio input | name, value, onChange(e) |
15
+ | File | File input | onChange(e) |
16
+ | Toggle | Toggle input | name, value, onChange(e) |
17
+ | Stepper | Text input for step flows | placeholder, value, onChange(e) |
18
+
19
+ ## Types
20
+
21
+ ### SelectOption
22
+ ```typescript
23
+ interface SelectOption {
24
+ label: string;
25
+ value: string | number;
26
+ }
27
+ ```
28
+
29
+ ### SelectProps
30
+ ```typescript
31
+ interface SelectProps {
32
+ onChange?: (option: SelectOption | SelectOption[]) => void;
33
+ value?: SelectOption | SelectOption[] | null;
34
+ label?: string;
35
+ options?: SelectOption[];
36
+ placeholder?: string;
37
+ isMulti?: boolean;
38
+ isRequired?: boolean;
39
+ isDisabled?: boolean;
40
+ isFluid?: boolean;
41
+ error?: string;
42
+ className?: string;
43
+ triggerClassName?: string;
44
+ triggerActiveClassName?: string;
45
+ contentsClassName?: string;
46
+ }
47
+ ```
48
+
49
+ ### InputProps
50
+ ```typescript
51
+ interface InputProps {
52
+ name?: string;
53
+ id?: string;
54
+ onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
55
+ onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
56
+ value?: string;
57
+ defaultValue?: string;
58
+ label?: string;
59
+ placeholder?: string;
60
+ type?: string;
61
+ isRequired?: boolean;
62
+ isDisabled?: boolean;
63
+ isFluid?: boolean;
64
+ className?: string;
65
+ error?: string;
66
+ }
67
+ ```
68
+
69
+ ### Other control types
70
+ - **TextAreaProps**, **FileProps**, **RadioProps**, **ToggleProps**: label, value/defaultValue, onChange, isDisabled, isRequired, isFluid, className, error (where applicable).
71
+ - **CheckboxProps**: value (boolean), onChange(checked: boolean).
72
+ - **DateProps**: defaultValue (string "dd-mm-yyyy"), onChange(dateValue: string).
73
+ - **FormControlsStepperProps**: label, placeholder, value, onChange(e).
74
+
75
+ ## Usage Examples
76
+
77
+ ### Input and Select
78
+
79
+ ```jsx
80
+ import { FormControls } from "cleanplate";
81
+
82
+ <FormControls.Input label="Email" placeholder="user@example.com" isRequired />
83
+ <FormControls.Select
84
+ label="Fruit"
85
+ placeholder="Select"
86
+ options={[{ label: "Apple", value: "apple" }, { label: "Mango", value: "mango" }]}
87
+ onChange={(option) => console.log(option)}
88
+ />
89
+ ```
90
+
91
+ ### TextArea, Checkbox, Date
92
+
93
+ ```jsx
94
+ <FormControls.TextArea label="Message" placeholder="Hello" />
95
+ <FormControls.Checkbox label="Accept terms?" value={checked} onChange={setChecked} />
96
+ <FormControls.Date label="DOB" defaultValue="31-05-1992" onChange={(v) => {}} />
97
+ ```
98
+
99
+ ### Used by other components
100
+
101
+ Pagination uses `FormControls.Select` for rows-per-page. Pills uses `FormControls.Input` in edit mode.
102
+
103
+ ## Behavior Notes
104
+
105
+ - **Select:** options are `{ label, value }`; single select passes one option to onChange, multi passes an array. value can be option or array for multi.
106
+ - **Date:** Returns string "dd-mm-yyyy" to onChange; uses internal day/month/year Selects.
107
+ - **Error:** When `error` is set, the field shows error styling and message below.
108
+ - **isFluid:** Full-width field wrapper.
109
+
110
+ ## Related Components / Links
111
+
112
+ - Pills (uses FormControls.Input in edit mode)
113
+ - Pagination (uses FormControls.Select for rows-per-page)
114
+ - Container (layout around form fields)
115
+ - Button (submit/cancel in forms)