@overdoser/react-toolkit 0.0.3 → 0.0.4
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/AGENTS.md +10 -12
- package/README.md +8 -8
- package/components/Button/Button.d.ts +14 -0
- package/components/Dropdown/Dropdown.d.ts +36 -8
- package/components/Dropdown/DropdownItem.d.ts +5 -0
- package/components/Form/Form.d.ts +16 -0
- package/components/Form/FormField.d.ts +25 -0
- package/components/Form/FormRow.d.ts +1 -0
- package/components/Link/Link.d.ts +12 -0
- package/components/List/List.d.ts +16 -0
- package/components/Modal/Modal.d.ts +23 -0
- package/components/Popover/Popover.d.ts +18 -0
- package/components/Table/Table.d.ts +34 -4
- package/components/Typography/Typography.d.ts +10 -0
- package/components/inputs/Checkbox/Checkbox.d.ts +14 -0
- package/components/inputs/Input/Input.d.ts +10 -0
- package/components/inputs/Radio/Radio.d.ts +22 -0
- package/components/inputs/Select/Select.d.ts +27 -0
- package/components/inputs/Textarea/Textarea.d.ts +9 -0
- package/index.d.ts +14 -0
- package/llms.txt +13 -15
- package/manifest.json +12 -14
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -25,18 +25,16 @@ For exhaustive component reference (every prop, every variant, every signature),
|
|
|
25
25
|
- Always import from the package root: `import { Button } from '@overdoser/react-toolkit'`. Do **not** reach into subpaths (`@overdoser/react-toolkit/dist/...`) — they're not part of the public API.
|
|
26
26
|
- The only valid stylesheet subpath is `@overdoser/react-toolkit/theme.css`.
|
|
27
27
|
|
|
28
|
-
##
|
|
29
|
-
|
|
30
|
-
1. **
|
|
31
|
-
2. **Inside `<Form>`, every focusable input
|
|
32
|
-
3. **`<Modal>` content
|
|
33
|
-
4. **
|
|
34
|
-
5. **`
|
|
35
|
-
6. **`
|
|
36
|
-
7.
|
|
37
|
-
8.
|
|
38
|
-
9. **Server-side `Table`:** if you provide `onSort`, the table will not sort or paginate `data` itself. Your backend must return the page already sorted and sliced. Pass `pagination.totalRows` for the paginator to compute pages.
|
|
39
|
-
10. **Theming is via CSS custom properties** (`--crk-*`) on `:root`. Don't override styles by hand-writing CSS that targets internal class names — those are hashed and unstable. Use the `classes` prop where finer control is needed.
|
|
28
|
+
## Rules
|
|
29
|
+
|
|
30
|
+
1. **Use the toolkit components for UI affordances** — `Button`, `Input`, `Select`, `Textarea`, `Link`. Styling and a11y come for free.
|
|
31
|
+
2. **Inside `<Form>`, wrap every focusable input in `<FormField>`.** `FormField` clones the child to inject `value`/`onChange`/`name`/`error`/aria — let it.
|
|
32
|
+
3. **`<Modal>` content lives in `Modal.Header`, `Modal.Body`, `Modal.Footer`.** They own focus targeting and spacing.
|
|
33
|
+
4. **Inputs use `inputSize`** (`'sm' | 'md' | 'lg'`) for the toolkit size scale; the native `size` HTML attribute is independent.
|
|
34
|
+
5. **`Typography` `color`** accepts the preset tokens (`default | muted | primary | danger | success`). For arbitrary colors, use `style` or `className`.
|
|
35
|
+
6. **`Popover` content** goes through the `content` prop.
|
|
36
|
+
7. **Server-side `Table`:** providing `onSort` puts the table in controlled mode — the backend returns the page already sorted and sliced. Pass `pagination.totalRows` so the paginator can compute pages.
|
|
37
|
+
8. **Theme via CSS custom properties** (`--crk-*`) on `:root`. For finer overrides, use each component's `classes` prop — internal class names are hashed and unstable.
|
|
40
38
|
|
|
41
39
|
## Decision flow
|
|
42
40
|
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @overdoser/react-toolkit
|
|
2
2
|
|
|
3
3
|
A modern, themeable React component library with SCSS modules.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @
|
|
8
|
+
npm install @overdoser/react-toolkit
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
@@ -13,7 +13,7 @@ npm install @crk/react-toolkit
|
|
|
13
13
|
Import the stylesheet in your app entry point:
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import '@
|
|
16
|
+
import '@overdoser/react-toolkit/theme.css';
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Theming
|
|
@@ -61,13 +61,13 @@ Override `--crk-*` CSS custom properties to customize the theme:
|
|
|
61
61
|
### Button
|
|
62
62
|
|
|
63
63
|
```tsx
|
|
64
|
-
import { Button } from '@
|
|
64
|
+
import { Button } from '@overdoser/react-toolkit';
|
|
65
65
|
|
|
66
66
|
<Button variant="primary" size="md" onClick={handleClick}>
|
|
67
67
|
Save
|
|
68
68
|
</Button>
|
|
69
69
|
|
|
70
|
-
<Button variant="danger" loading
|
|
70
|
+
<Button variant="danger" loading loadingStyle="dots">
|
|
71
71
|
Deleting...
|
|
72
72
|
</Button>
|
|
73
73
|
```
|
|
@@ -75,14 +75,14 @@ import { Button } from '@crk/react-toolkit';
|
|
|
75
75
|
### Form
|
|
76
76
|
|
|
77
77
|
```tsx
|
|
78
|
-
import { Form, FormField, Input, Button } from '@
|
|
78
|
+
import { Form, FormField, Input, Button } from '@overdoser/react-toolkit';
|
|
79
79
|
import { useForm } from 'react-hook-form';
|
|
80
80
|
|
|
81
81
|
function LoginForm() {
|
|
82
|
-
const
|
|
82
|
+
const form = useForm();
|
|
83
83
|
|
|
84
84
|
return (
|
|
85
|
-
<Form
|
|
85
|
+
<Form form={form} onSubmit={(values) => console.log(values)}>
|
|
86
86
|
<FormField name="email" label="Email">
|
|
87
87
|
<Input />
|
|
88
88
|
</FormField>
|
|
@@ -7,11 +7,25 @@ export interface ButtonClasses {
|
|
|
7
7
|
dot: string;
|
|
8
8
|
}
|
|
9
9
|
export interface ButtonProps extends ComponentPropsWithRef<'button'> {
|
|
10
|
+
/** Override class names on internal elements. */
|
|
10
11
|
classes?: Partial<ButtonClasses>;
|
|
12
|
+
/** Visual style. @default 'primary' */
|
|
11
13
|
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
|
|
14
|
+
/** Button size. @default 'md' */
|
|
12
15
|
size?: 'sm' | 'md' | 'lg';
|
|
16
|
+
/** When true, the button is disabled and `aria-busy` is set. @default false */
|
|
13
17
|
loading?: boolean;
|
|
18
|
+
/** Loading animation style. Only applied when `loading` is true. @default 'dots' */
|
|
14
19
|
loadingStyle?: 'dots' | 'shimmer' | 'border';
|
|
20
|
+
/** Stretch the button to fill its container's width. @default false */
|
|
15
21
|
fullWidth?: boolean;
|
|
16
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Styled `<button>` with variants, sizes, and three loading-state animations.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <Button variant="danger" size="lg" loading loadingStyle="shimmer" onClick={onDelete}>
|
|
28
|
+
* Delete
|
|
29
|
+
* </Button>
|
|
30
|
+
*/
|
|
17
31
|
export declare const Button: import('react').ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
2
|
export interface DropdownOption {
|
|
3
|
+
/** Selected value sent through `onChange`. */
|
|
3
4
|
value: string;
|
|
5
|
+
/** Visible label in the menu and trigger. */
|
|
4
6
|
label: React.ReactNode;
|
|
7
|
+
/** When true, the option is non-interactive. */
|
|
5
8
|
disabled?: boolean;
|
|
6
9
|
}
|
|
7
10
|
export interface DropdownClasses {
|
|
@@ -13,28 +16,53 @@ export interface DropdownClasses {
|
|
|
13
16
|
item: string;
|
|
14
17
|
}
|
|
15
18
|
export interface DropdownProps {
|
|
16
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Trigger content for **menu mode**. Required when `options` is not provided.
|
|
21
|
+
* Ignored in **select mode** (when `options` is provided) — the trigger then
|
|
22
|
+
* shows the selected option's label.
|
|
23
|
+
*/
|
|
17
24
|
trigger?: React.ReactNode;
|
|
25
|
+
/** `<DropdownItem>` children for menu mode. */
|
|
18
26
|
children?: React.ReactNode;
|
|
27
|
+
/** Menu alignment relative to the trigger. @default 'left' */
|
|
19
28
|
align?: 'left' | 'right';
|
|
20
29
|
className?: string;
|
|
21
30
|
style?: CSSProperties;
|
|
22
31
|
id?: string;
|
|
32
|
+
/** Called when the menu opens. */
|
|
23
33
|
onOpen?: () => void;
|
|
34
|
+
/** Called when the menu closes (outside click, Escape, or selection). */
|
|
24
35
|
onClose?: () => void;
|
|
25
|
-
/**
|
|
36
|
+
/** Switches Dropdown to **select mode**: the trigger shows the selected option. */
|
|
26
37
|
options?: DropdownOption[];
|
|
27
|
-
/** Placeholder shown when no value is selected */
|
|
38
|
+
/** Placeholder shown in select mode when no value is selected. @default 'Select...' */
|
|
28
39
|
placeholder?: React.ReactNode;
|
|
29
|
-
/** Controlled value */
|
|
40
|
+
/** Controlled selected value (select mode). */
|
|
30
41
|
value?: string;
|
|
31
|
-
/**
|
|
42
|
+
/** Fires when an option is selected (select mode). */
|
|
32
43
|
onChange?: (value: string) => void;
|
|
33
|
-
/** Error
|
|
44
|
+
/** Error styling on the trigger. @default false */
|
|
34
45
|
error?: boolean;
|
|
35
|
-
/**
|
|
46
|
+
/** Stretch trigger and menu to container width. @default true */
|
|
36
47
|
fullWidth?: boolean;
|
|
37
|
-
/**
|
|
48
|
+
/** Override class names on internal elements. */
|
|
38
49
|
classes?: Partial<DropdownClasses>;
|
|
39
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Two-mode dropdown:
|
|
53
|
+
* - **Menu mode**: pass `trigger` + `<DropdownItem>` children for an action menu.
|
|
54
|
+
* - **Select mode**: pass `options` + `value` + `onChange` to use as a form input.
|
|
55
|
+
* In this mode the `trigger` prop is ignored.
|
|
56
|
+
*
|
|
57
|
+
* Closes on outside click and Escape; auto-focuses the first menu item on open.
|
|
58
|
+
*
|
|
59
|
+
* @example Menu mode
|
|
60
|
+
* <Dropdown trigger="More ▾">
|
|
61
|
+
* <DropdownItem onClick={onEdit}>Edit</DropdownItem>
|
|
62
|
+
* <DropdownItem onClick={onDelete}>Delete</DropdownItem>
|
|
63
|
+
* </Dropdown>
|
|
64
|
+
*
|
|
65
|
+
* @example Select mode
|
|
66
|
+
* <Dropdown options={options} value={value} onChange={setValue} />
|
|
67
|
+
*/
|
|
40
68
|
export declare const Dropdown: import('react').ForwardRefExoticComponent<DropdownProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface DropdownItemProps extends ComponentPropsWithRef<'button'> {
|
|
3
|
+
/** Non-interactive when true. @default false */
|
|
3
4
|
disabled?: boolean;
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Action item rendered inside a `<Dropdown>` (menu mode).
|
|
8
|
+
* Renders as a `<button role="menuitem">`; supports all native button props.
|
|
9
|
+
*/
|
|
5
10
|
export declare const DropdownItem: import('react').ForwardRefExoticComponent<Omit<DropdownItemProps, "ref"> & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { UseFormReturn, FieldValues, SubmitHandler } from 'react-hook-form';
|
|
2
2
|
export interface FormProps<T extends FieldValues> {
|
|
3
|
+
/** The result of `useForm()`. */
|
|
3
4
|
form: UseFormReturn<T>;
|
|
5
|
+
/** Called with validated values. `Form` handles `preventDefault` and validation internally. */
|
|
4
6
|
onSubmit: SubmitHandler<T>;
|
|
7
|
+
/** Top-of-form error messages. Rendered above children with `role="alert"`. */
|
|
5
8
|
errors?: React.ReactNode[];
|
|
6
9
|
className?: string;
|
|
7
10
|
style?: React.CSSProperties;
|
|
8
11
|
children: React.ReactNode;
|
|
9
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* react-hook-form wrapper that provides `FormProvider` and a styled `<form>` element.
|
|
15
|
+
*
|
|
16
|
+
* Pair with `<FormField>` for each input — `FormField` reads the form context
|
|
17
|
+
* via `useFormContext` and clones its child to inject `value`/`onChange`/`name`/`error`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const form = useForm<Values>();
|
|
21
|
+
* <Form form={form} onSubmit={(values) => save(values)}>
|
|
22
|
+
* <FormField name="email" label="Email"><Input /></FormField>
|
|
23
|
+
* <Button type="submit">Save</Button>
|
|
24
|
+
* </Form>
|
|
25
|
+
*/
|
|
10
26
|
export declare function Form<T extends FieldValues>({ form, onSubmit, errors, className, style, children, }: FormProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,14 +6,39 @@ export interface FormFieldClasses {
|
|
|
6
6
|
helperText: string;
|
|
7
7
|
}
|
|
8
8
|
export interface FormFieldProps {
|
|
9
|
+
/** Field name. Becomes the field `id` and the react-hook-form path. */
|
|
9
10
|
name: string;
|
|
11
|
+
/** Field label rendered above the input. */
|
|
10
12
|
label?: ReactNode;
|
|
13
|
+
/** Helper text rendered below the input (replaced by error message when invalid). */
|
|
11
14
|
helperText?: ReactNode;
|
|
15
|
+
/** Renders a `*` indicator next to the label. Does NOT add validation rules — pass those in `rules`. */
|
|
12
16
|
required?: boolean;
|
|
17
|
+
/** react-hook-form `useController` rules (e.g., `{ required: 'msg', minLength: { value: 8, message: '…' } }`). */
|
|
13
18
|
rules?: Record<string, unknown>;
|
|
19
|
+
/** Override class names on internal elements. */
|
|
14
20
|
classes?: Partial<FormFieldClasses>;
|
|
15
21
|
className?: string;
|
|
16
22
|
style?: CSSProperties;
|
|
23
|
+
/**
|
|
24
|
+
* Exactly one input element. `FormField` clones it to inject
|
|
25
|
+
* `value`/`onChange`/`name`/`id`/`error`/aria props — do NOT pass those manually.
|
|
26
|
+
*
|
|
27
|
+
* Supported: `Input`, `Textarea`, `Select`, `Dropdown` (select-mode), `Checkbox`, `Radio`/`RadioGroup`.
|
|
28
|
+
*/
|
|
17
29
|
children: ReactElement;
|
|
18
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Bridges react-hook-form to a single child input via `cloneElement`.
|
|
33
|
+
* Must be used inside a `<Form>` (which provides `FormProvider`).
|
|
34
|
+
*
|
|
35
|
+
* Bridges automatically applied:
|
|
36
|
+
* - `Select` (multi/searchable) and `Dropdown` (select-mode): `onChange` → `onValueChange`/`onValuesChange`.
|
|
37
|
+
* - `Checkbox`: when the form value is boolean, it's bridged to `checked`.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* <FormField name="email" label="Email" required rules={{ required: 'Required' }}>
|
|
41
|
+
* <Input type="email" />
|
|
42
|
+
* </FormField>
|
|
43
|
+
*/
|
|
19
44
|
export declare function FormField({ name, label, helperText, required, rules, classes, className, style, children, }: FormFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,4 +4,5 @@ export interface FormRowProps {
|
|
|
4
4
|
className?: string;
|
|
5
5
|
style?: CSSProperties;
|
|
6
6
|
}
|
|
7
|
+
/** Horizontal flex row that lays out its children — useful for putting two `<FormField>`s side-by-side. */
|
|
7
8
|
export declare function FormRow({ children, className, style }: FormRowProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface LinkProps extends ComponentPropsWithRef<'a'> {
|
|
3
|
+
/** Visual style. @default 'default' */
|
|
3
4
|
variant?: 'default' | 'muted' | 'danger';
|
|
5
|
+
/**
|
|
6
|
+
* Mark the link as opening in a new tab.
|
|
7
|
+
* Sets `target="_blank"` and `rel="noopener noreferrer"`,
|
|
8
|
+
* and appends a visually-hidden " (opens in a new tab)" suffix for screen readers.
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
4
11
|
external?: boolean;
|
|
5
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Styled `<a>` with variants and safe external-link defaults.
|
|
15
|
+
*
|
|
16
|
+
* @example <Link href="https://example.com" external>Docs</Link>
|
|
17
|
+
*/
|
|
6
18
|
export declare const Link: import('react').ForwardRefExoticComponent<Omit<LinkProps, "ref"> & import('react').RefAttributes<HTMLAnchorElement>>;
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface ListProps extends ComponentPropsWithRef<'ul'> {
|
|
3
|
+
/**
|
|
4
|
+
* List style. `'ordered'` renders `<ol>`, `'unordered'` renders `<ul>`,
|
|
5
|
+
* `'none'` renders `<ul>` without bullets.
|
|
6
|
+
* @default 'unordered'
|
|
7
|
+
*/
|
|
3
8
|
variant?: 'unordered' | 'ordered' | 'none';
|
|
9
|
+
/** Vertical spacing between items. @default 'md' */
|
|
4
10
|
spacing?: 'sm' | 'md' | 'lg';
|
|
5
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Themed list (`<ul>` or `<ol>` based on `variant`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <List variant="ordered" spacing="lg">
|
|
17
|
+
* <ListItem>First</ListItem>
|
|
18
|
+
* <ListItem>Second</ListItem>
|
|
19
|
+
* </List>
|
|
20
|
+
*/
|
|
6
21
|
export declare const List: import('react').ForwardRefExoticComponent<Omit<ListProps, "ref"> & import('react').RefAttributes<HTMLOListElement | HTMLUListElement>>;
|
|
7
22
|
export interface ListItemProps extends ComponentPropsWithRef<'li'> {
|
|
8
23
|
}
|
|
24
|
+
/** Themed `<li>`. Use only inside `<List>`. */
|
|
9
25
|
export declare const ListItem: import('react').ForwardRefExoticComponent<Omit<ListItemProps, "ref"> & import('react').RefAttributes<HTMLLIElement>>;
|
|
@@ -11,6 +11,7 @@ export interface ModalHeaderProps {
|
|
|
11
11
|
children: ReactNode;
|
|
12
12
|
className?: string;
|
|
13
13
|
style?: CSSProperties;
|
|
14
|
+
/** When provided, renders an "×" close button in the header. */
|
|
14
15
|
onClose?: () => void;
|
|
15
16
|
}
|
|
16
17
|
export interface ModalBodyProps {
|
|
@@ -27,15 +28,23 @@ declare const Header: FC<ModalHeaderProps>;
|
|
|
27
28
|
declare const Body: FC<ModalBodyProps>;
|
|
28
29
|
declare const Footer: FC<ModalFooterProps>;
|
|
29
30
|
export interface ModalProps {
|
|
31
|
+
/** Whether the modal is visible. */
|
|
30
32
|
open: boolean;
|
|
33
|
+
/** Called when the user requests close (backdrop, Escape, or `Modal.Header` close button). */
|
|
31
34
|
onClose: () => void;
|
|
35
|
+
/** Close when the backdrop is clicked. @default true */
|
|
32
36
|
closeOnBackdrop?: boolean;
|
|
37
|
+
/** Close when Escape is pressed. @default true */
|
|
33
38
|
closeOnEscape?: boolean;
|
|
39
|
+
/** Modal size. `'fullscreen'` covers the viewport. @default 'md' */
|
|
34
40
|
size?: 'sm' | 'md' | 'lg' | 'fullscreen';
|
|
41
|
+
/** Override class names on internal elements. */
|
|
35
42
|
classes?: Partial<ModalClasses>;
|
|
36
43
|
className?: string;
|
|
37
44
|
style?: CSSProperties;
|
|
45
|
+
/** Should be `<Modal.Header>`, `<Modal.Body>`, and `<Modal.Footer>`. */
|
|
38
46
|
children: ReactNode;
|
|
47
|
+
/** Accessible label. Use this OR `aria-labelledby`. If neither is set, `Modal.Header` is auto-wired as `aria-labelledby`. */
|
|
39
48
|
'aria-label'?: string;
|
|
40
49
|
'aria-labelledby'?: string;
|
|
41
50
|
}
|
|
@@ -44,5 +53,19 @@ type ModalComponent = ReturnType<typeof forwardRef<HTMLDivElement, ModalProps>>
|
|
|
44
53
|
Body: typeof Body;
|
|
45
54
|
Footer: typeof Footer;
|
|
46
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Portal-based modal with focus trap, body scroll lock, and Escape/backdrop close.
|
|
58
|
+
* Compose with `Modal.Header`, `Modal.Body`, and `Modal.Footer`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* <Modal open={open} onClose={() => setOpen(false)} size="md">
|
|
62
|
+
* <Modal.Header onClose={() => setOpen(false)}>Title</Modal.Header>
|
|
63
|
+
* <Modal.Body>Content</Modal.Body>
|
|
64
|
+
* <Modal.Footer>
|
|
65
|
+
* <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
|
|
66
|
+
* <Button variant="primary" onClick={confirm}>OK</Button>
|
|
67
|
+
* </Modal.Footer>
|
|
68
|
+
* </Modal>
|
|
69
|
+
*/
|
|
47
70
|
export declare const Modal: ModalComponent;
|
|
48
71
|
export {};
|
|
@@ -5,14 +5,32 @@ export interface PopoverClasses {
|
|
|
5
5
|
popover: string;
|
|
6
6
|
}
|
|
7
7
|
export interface PopoverProps {
|
|
8
|
+
/** Trigger content. Wrapped in an internal `<button>`. */
|
|
8
9
|
trigger: React.ReactNode;
|
|
10
|
+
/** Panel content. Rendered inside a `[role="dialog"]` when open. */
|
|
9
11
|
content: React.ReactNode;
|
|
12
|
+
/** Side of the trigger to anchor the panel to. @default 'bottom' */
|
|
10
13
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
14
|
+
/** Controlled open state. */
|
|
11
15
|
open?: boolean;
|
|
16
|
+
/** Called when the open state changes. */
|
|
12
17
|
onOpenChange?: (open: boolean) => void;
|
|
18
|
+
/** Override class names on internal elements. */
|
|
13
19
|
classes?: Partial<PopoverClasses>;
|
|
14
20
|
className?: string;
|
|
15
21
|
style?: CSSProperties;
|
|
22
|
+
/** Use the `content` prop. */
|
|
16
23
|
children?: never;
|
|
17
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Anchored popover panel. Closes on outside click and Escape; auto-focuses
|
|
27
|
+
* the first focusable element inside `content` when opened.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* <Popover
|
|
31
|
+
* trigger="Help"
|
|
32
|
+
* content={<p>Some help text</p>}
|
|
33
|
+
* position="right"
|
|
34
|
+
* />
|
|
35
|
+
*/
|
|
18
36
|
export declare const Popover: import('react').ForwardRefExoticComponent<PopoverProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { SortConfig } from './useTableSort';
|
|
3
3
|
export interface ColumnDef<T> {
|
|
4
|
+
/** Object key on each row to read the cell value from. */
|
|
4
5
|
key: keyof T & string;
|
|
6
|
+
/** Header content (string or any ReactNode). */
|
|
5
7
|
header: ReactNode;
|
|
8
|
+
/** Enable click-to-sort on the header. */
|
|
6
9
|
sortable?: boolean;
|
|
10
|
+
/** Custom cell renderer; defaults to rendering `row[key]`. */
|
|
7
11
|
render?: (value: T[keyof T], row: T, index: number) => ReactNode;
|
|
12
|
+
/** Column width (CSS value). */
|
|
8
13
|
width?: string | number;
|
|
14
|
+
/** Text alignment for cells in this column. */
|
|
9
15
|
align?: 'left' | 'center' | 'right';
|
|
10
16
|
}
|
|
11
17
|
export interface PaginationConfig {
|
|
@@ -31,25 +37,49 @@ export interface TableClasses {
|
|
|
31
37
|
pageButton: string;
|
|
32
38
|
}
|
|
33
39
|
export interface TableProps<T extends Record<string, unknown>> {
|
|
40
|
+
/** Row data. */
|
|
34
41
|
data: T[];
|
|
42
|
+
/** Column definitions. */
|
|
35
43
|
columns: ColumnDef<T>[];
|
|
36
|
-
/** Controlled sort config
|
|
44
|
+
/** Controlled sort config. Pair with `onSort` for server-side sorting. */
|
|
37
45
|
sortConfig?: SortConfig[];
|
|
38
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Sort callback. When provided, Table is in **controlled** mode and will
|
|
48
|
+
* NOT sort `data` internally and will NOT slice for pagination — your
|
|
49
|
+
* server is expected to handle both.
|
|
50
|
+
*/
|
|
39
51
|
onSort?: (config: SortConfig[]) => void;
|
|
40
|
-
/** Enable multi-column sort via Ctrl
|
|
52
|
+
/** Enable multi-column sort via Ctrl/Cmd-click on a sortable header. @default true */
|
|
41
53
|
multiSort?: boolean;
|
|
54
|
+
/** Alternate row backgrounds. @default false */
|
|
42
55
|
striped?: boolean;
|
|
56
|
+
/** Highlight rows on hover. @default false */
|
|
43
57
|
hoverable?: boolean;
|
|
58
|
+
/** Tighter row padding. @default false */
|
|
44
59
|
compact?: boolean;
|
|
45
60
|
className?: string;
|
|
46
61
|
style?: React.CSSProperties;
|
|
62
|
+
/** Column key to use as React `key` per row. Falls back to row index. */
|
|
47
63
|
rowKey?: keyof T & string;
|
|
64
|
+
/** Content rendered when `data` is empty. @default 'No data' */
|
|
48
65
|
emptyMessage?: ReactNode;
|
|
49
|
-
/**
|
|
66
|
+
/** When provided, renders a paginator below the table. */
|
|
50
67
|
pagination?: PaginationConfig;
|
|
68
|
+
/** Override class names on internal elements. */
|
|
51
69
|
classes?: Partial<TableClasses>;
|
|
52
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Generic data table with sortable columns, multi-sort (Ctrl/Cmd-click), and
|
|
73
|
+
* client- or server-side pagination.
|
|
74
|
+
*
|
|
75
|
+
* Sort cycle on header click: `none → asc → desc → none`.
|
|
76
|
+
*
|
|
77
|
+
* **Client-side mode** (default): omit `onSort`. Table sorts and paginates internally.
|
|
78
|
+
*
|
|
79
|
+
* **Controlled mode**: pass `sortConfig` + `onSort`. Your server returns the
|
|
80
|
+
* page already sorted and sliced; pass `pagination.totalRows` so the
|
|
81
|
+
* paginator can compute page count.
|
|
82
|
+
*/
|
|
53
83
|
declare function TableInner<T extends Record<string, unknown>>({ data, columns, sortConfig: controlledSortConfig, onSort, multiSort, striped, hoverable, compact, className, style, rowKey, emptyMessage, pagination, classes, }: TableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
54
84
|
export declare const Table: typeof TableInner;
|
|
55
85
|
export {};
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
type TypographyVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'label';
|
|
3
3
|
export interface TypographyProps extends Omit<ComponentPropsWithRef<'p'>, 'color'> {
|
|
4
|
+
/** HTML tag to render. @default 'p' */
|
|
4
5
|
variant?: TypographyVariant;
|
|
6
|
+
/** Font weight. */
|
|
5
7
|
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
8
|
+
/** Preset color token. For arbitrary colors, use `style` or `className`. */
|
|
6
9
|
color?: 'default' | 'muted' | 'primary' | 'danger' | 'success';
|
|
10
|
+
/** Text alignment. */
|
|
7
11
|
align?: 'left' | 'center' | 'right';
|
|
12
|
+
/** Single-line ellipsis truncation. @default false */
|
|
8
13
|
truncate?: boolean;
|
|
9
14
|
children: React.ReactNode;
|
|
10
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Renders `h1`–`h6`, `p`, `span`, or `label` with theme-aware typography tokens.
|
|
18
|
+
*
|
|
19
|
+
* @example <Typography variant="h2" weight="bold" color="primary">Title</Typography>
|
|
20
|
+
*/
|
|
11
21
|
export declare const Typography: import('react').ForwardRefExoticComponent<Omit<TypographyProps, "ref"> & import('react').RefAttributes<HTMLElement>>;
|
|
12
22
|
export {};
|
|
@@ -5,8 +5,22 @@ export interface CheckboxClasses {
|
|
|
5
5
|
label: string;
|
|
6
6
|
}
|
|
7
7
|
export interface CheckboxProps extends ComponentPropsWithRef<'input'> {
|
|
8
|
+
/** Visible label rendered next to the box. */
|
|
8
9
|
label?: ReactNode;
|
|
10
|
+
/** Sets the DOM `indeterminate` property; visually distinct from checked/unchecked. @default false */
|
|
9
11
|
indeterminate?: boolean;
|
|
12
|
+
/** Override class names on internal elements. */
|
|
10
13
|
classes?: Partial<CheckboxClasses>;
|
|
11
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Themed checkbox. The `<input>` is wrapped in a `<label>` so clicking the
|
|
17
|
+
* label toggles the input.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <Checkbox
|
|
21
|
+
* label="Remember me"
|
|
22
|
+
* checked={remember}
|
|
23
|
+
* onChange={(e) => setRemember(e.target.checked)}
|
|
24
|
+
* />
|
|
25
|
+
*/
|
|
12
26
|
export declare const Checkbox: import('react').ForwardRefExoticComponent<Omit<CheckboxProps, "ref"> & import('react').RefAttributes<HTMLInputElement>>;
|
|
@@ -6,10 +6,20 @@ export interface InputClasses {
|
|
|
6
6
|
suffix: string;
|
|
7
7
|
}
|
|
8
8
|
export interface InputProps extends Omit<ComponentPropsWithRef<'input'>, 'prefix'> {
|
|
9
|
+
/** Toolkit size scale (independent of the native `size` HTML attribute). @default 'md' */
|
|
9
10
|
inputSize?: 'sm' | 'md' | 'lg';
|
|
11
|
+
/** Apply error styling. @default false */
|
|
10
12
|
error?: boolean;
|
|
13
|
+
/** Content rendered inside the input wrapper, before the field. */
|
|
11
14
|
prefix?: ReactNode;
|
|
15
|
+
/** Content rendered inside the input wrapper, after the field. */
|
|
12
16
|
suffix?: ReactNode;
|
|
17
|
+
/** Override class names on internal elements. */
|
|
13
18
|
classes?: Partial<InputClasses>;
|
|
14
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Themed text input with optional `prefix`/`suffix` slots.
|
|
22
|
+
*
|
|
23
|
+
* @example <Input type="email" inputSize="lg" prefix="@" placeholder="username" />
|
|
24
|
+
*/
|
|
15
25
|
export declare const Input: import('react').ForwardRefExoticComponent<Omit<InputProps, "ref"> & import('react').RefAttributes<HTMLInputElement>>;
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import { ComponentPropsWithRef, ReactNode, CSSProperties } from 'react';
|
|
2
2
|
export interface RadioGroupProps {
|
|
3
|
+
/** Shared `name` attribute applied to every `Radio` child via context. */
|
|
3
4
|
name: string;
|
|
5
|
+
/** Controlled selected value. */
|
|
4
6
|
value?: string;
|
|
7
|
+
/** Fires with the newly selected value. */
|
|
5
8
|
onChange?: (value: string) => void;
|
|
6
9
|
className?: string;
|
|
7
10
|
style?: CSSProperties;
|
|
8
11
|
children: ReactNode;
|
|
9
12
|
id?: string;
|
|
13
|
+
/** Accessible label. Use this OR `aria-labelledby`. */
|
|
10
14
|
'aria-label'?: string;
|
|
11
15
|
'aria-labelledby'?: string;
|
|
16
|
+
/** Marks the group as required (`aria-required`). */
|
|
12
17
|
required?: boolean;
|
|
13
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Manages selection state and `name` attribute for a group of `<Radio>`s via context.
|
|
21
|
+
* Inside a `<RadioGroup>`, `Radio` does not need its own `name`/`checked`/`onChange`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <RadioGroup name="plan" value={plan} onChange={setPlan} aria-label="Plan">
|
|
25
|
+
* <Radio value="free" label="Free" />
|
|
26
|
+
* <Radio value="pro" label="Pro" />
|
|
27
|
+
* </RadioGroup>
|
|
28
|
+
*/
|
|
14
29
|
export declare const RadioGroup: {
|
|
15
30
|
({ name, value, onChange, className, style, children, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, required, }: RadioGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
16
31
|
displayName: string;
|
|
@@ -21,8 +36,15 @@ export interface RadioClasses {
|
|
|
21
36
|
label: string;
|
|
22
37
|
}
|
|
23
38
|
export interface RadioProps extends Omit<ComponentPropsWithRef<'input'>, 'type'> {
|
|
39
|
+
/** Visible label rendered next to the radio. */
|
|
24
40
|
label?: ReactNode;
|
|
41
|
+
/** Value of this option. Required (used to identify the radio in the group). */
|
|
25
42
|
value: string;
|
|
43
|
+
/** Override class names on internal elements. */
|
|
26
44
|
classes?: Partial<RadioClasses>;
|
|
27
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* A single radio option. Inside a `<RadioGroup>`, `name`/`checked`/`onChange`
|
|
48
|
+
* come from group context — do not pass them manually.
|
|
49
|
+
*/
|
|
28
50
|
export declare const Radio: import('react').ForwardRefExoticComponent<Omit<RadioProps, "ref"> & import('react').RefAttributes<HTMLInputElement>>;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface SelectOption {
|
|
3
|
+
/** Value sent through `onValueChange` / form. */
|
|
3
4
|
value: string;
|
|
5
|
+
/** Plain-text label (used for filter matching and the trigger text). */
|
|
4
6
|
label: string;
|
|
7
|
+
/** Optional rich rendered content shown in the menu in place of `label`. */
|
|
5
8
|
content?: React.ReactNode;
|
|
9
|
+
/** Non-interactive when true. */
|
|
6
10
|
disabled?: boolean;
|
|
7
11
|
}
|
|
8
12
|
export interface SelectClasses {
|
|
@@ -16,18 +20,41 @@ export interface SelectClasses {
|
|
|
16
20
|
chipRemove: string;
|
|
17
21
|
}
|
|
18
22
|
export interface SelectProps extends Omit<ComponentPropsWithRef<'select'>, 'onChange' | 'value'> {
|
|
23
|
+
/** Toolkit size scale (independent of the native `size` HTML attribute). @default 'md' */
|
|
19
24
|
inputSize?: 'sm' | 'md' | 'lg';
|
|
25
|
+
/** Apply error styling. @default false */
|
|
20
26
|
error?: boolean;
|
|
27
|
+
/** Options. When omitted in native mode, `children` is used instead. */
|
|
21
28
|
options?: SelectOption[];
|
|
29
|
+
/** Placeholder shown when no value is selected. @default 'Select...' */
|
|
22
30
|
placeholder?: string;
|
|
31
|
+
/** Override class names on internal elements. */
|
|
23
32
|
classes?: Partial<SelectClasses>;
|
|
33
|
+
/** Replaces the native `<select>` with a filterable dropdown. @default false */
|
|
24
34
|
searchable?: boolean;
|
|
35
|
+
/** Placeholder for the search input (searchable mode). @default 'Search...' */
|
|
25
36
|
searchPlaceholder?: string;
|
|
37
|
+
/** Native + searchable mode change event (synthetic in searchable mode). */
|
|
26
38
|
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
39
|
+
/** Single-mode value-only callback. */
|
|
27
40
|
onValueChange?: (value: string) => void;
|
|
41
|
+
/** `string` for single mode, `string[]` for multi mode. */
|
|
28
42
|
value?: string | string[];
|
|
43
|
+
/** Enable multi-select with chip rendering and search. @default false */
|
|
29
44
|
multiple?: boolean;
|
|
45
|
+
/** Multi-mode callback. */
|
|
30
46
|
onValuesChange?: (values: string[]) => void;
|
|
47
|
+
/** Clear the search query after each toggle in multi mode. @default true */
|
|
31
48
|
clearSearchOnSelect?: boolean;
|
|
32
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Three internal modes, picked automatically:
|
|
52
|
+
* - **Native** (default): wraps `<select>`. Use `onChange` or pass options as `children`.
|
|
53
|
+
* - **Searchable**: set `searchable`. Custom dropdown with text filter.
|
|
54
|
+
* - **Multi**: set `multiple`. Chip-based multi-select with text filter.
|
|
55
|
+
*
|
|
56
|
+
* @example Native: <Select options={[{ value: 'a', label: 'A' }]} onValueChange={setValue} />
|
|
57
|
+
* @example Searchable: <Select searchable options={users} value={id} onValueChange={setId} />
|
|
58
|
+
* @example Multi: <Select multiple options={tags} value={selected} onValuesChange={setSelected} />
|
|
59
|
+
*/
|
|
33
60
|
export declare const Select: import('react').ForwardRefExoticComponent<Omit<SelectProps, "ref"> & import('react').RefAttributes<HTMLSelectElement>>;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface TextareaProps extends ComponentPropsWithRef<'textarea'> {
|
|
3
|
+
/** Toolkit size scale. @default 'md' */
|
|
3
4
|
inputSize?: 'sm' | 'md' | 'lg';
|
|
5
|
+
/** Apply error styling. @default false */
|
|
4
6
|
error?: boolean;
|
|
7
|
+
/** User resize handle direction. Ignored when `autoExpand` is true. @default 'vertical' */
|
|
5
8
|
resize?: 'none' | 'vertical' | 'horizontal' | 'both';
|
|
9
|
+
/** Auto-grow height to fit content. Suppresses `resize` while active. @default true */
|
|
6
10
|
autoExpand?: boolean;
|
|
7
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Themed textarea with optional auto-expanding height.
|
|
14
|
+
*
|
|
15
|
+
* @example <Textarea placeholder="Bio" rows={3} autoExpand />
|
|
16
|
+
*/
|
|
8
17
|
export declare const Textarea: import('react').ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & import('react').RefAttributes<HTMLTextAreaElement>>;
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @overdoser/react-toolkit
|
|
3
|
+
*
|
|
4
|
+
* Themeable React component library with SCSS modules.
|
|
5
|
+
*
|
|
6
|
+
* AI assistants: see `llms.txt` and `AGENTS.md` at the package root for an
|
|
7
|
+
* exhaustive component reference, recipes, and integration rules. A
|
|
8
|
+
* machine-readable spec is available in `manifest.json`.
|
|
9
|
+
*
|
|
10
|
+
* Setup: `import '@overdoser/react-toolkit/theme.css';` once at the app entry.
|
|
11
|
+
* Theme via `--crk-*` CSS custom properties on `:root`.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
1
15
|
export { Button } from './components/Button';
|
|
2
16
|
export type { ButtonProps, ButtonClasses } from './components/Button';
|
|
3
17
|
export { Link } from './components/Link';
|
package/llms.txt
CHANGED
|
@@ -278,7 +278,7 @@ Requires `react-hook-form` peer dependency.
|
|
|
278
278
|
Imports: `import { Form, FormField, FormRow } from '@overdoser/react-toolkit'`
|
|
279
279
|
|
|
280
280
|
`Form<T>` props:
|
|
281
|
-
- `form: UseFormReturn<T>` —
|
|
281
|
+
- `form: UseFormReturn<T>` — pass the result of `useForm()`.
|
|
282
282
|
- `onSubmit: SubmitHandler<T>` — passed through `form.handleSubmit`.
|
|
283
283
|
- `errors?: ReactNode[]` — top-of-form error list (rendered above children with `role="alert"`).
|
|
284
284
|
|
|
@@ -324,7 +324,7 @@ Import: `import { Input } from '@overdoser/react-toolkit'`
|
|
|
324
324
|
Element: `<input>` (forwards ref). Native `prefix` attribute is omitted in favor of the prop below.
|
|
325
325
|
|
|
326
326
|
Props:
|
|
327
|
-
- `inputSize?: 'sm' | 'md' | 'lg'` — default `'md'`.
|
|
327
|
+
- `inputSize?: 'sm' | 'md' | 'lg'` — default `'md'`. Toolkit size scale; independent of the native HTML `size` attribute.
|
|
328
328
|
- `error?: boolean` — default `false`
|
|
329
329
|
- `prefix?: ReactNode` — content rendered inside the input wrapper, before the field.
|
|
330
330
|
- `suffix?: ReactNode` — same, after the field.
|
|
@@ -344,7 +344,7 @@ Three internal modes, picked automatically:
|
|
|
344
344
|
3. **Multi** — set `multiple`. Chip-based multi-select with text filter.
|
|
345
345
|
|
|
346
346
|
Props:
|
|
347
|
-
- `inputSize?: 'sm' | 'md' | 'lg'` — default `'md'`.
|
|
347
|
+
- `inputSize?: 'sm' | 'md' | 'lg'` — default `'md'`. Toolkit size scale.
|
|
348
348
|
- `error?: boolean`
|
|
349
349
|
- `options?: { value: string; label: string; content?: ReactNode; disabled?: boolean }[]`
|
|
350
350
|
- `placeholder?: string` — default `'Select...'` for searchable/multi.
|
|
@@ -466,15 +466,13 @@ Binds global keydown listeners keyed by `KeyboardEvent.key`. `active` defaults t
|
|
|
466
466
|
useKeyboard({ Escape: () => close(), Enter: () => confirm() }, isOpen);
|
|
467
467
|
```
|
|
468
468
|
|
|
469
|
-
##
|
|
470
|
-
|
|
471
|
-
1.
|
|
472
|
-
2. **`
|
|
473
|
-
3. **`
|
|
474
|
-
4. **`
|
|
475
|
-
5. **`
|
|
476
|
-
6. **`
|
|
477
|
-
7.
|
|
478
|
-
8.
|
|
479
|
-
9. **Server-side `Table`:** when `onSort` is provided, the table won't sort or paginate `data` itself — your server must.
|
|
480
|
-
10. **Theme stylesheet is a separate import**: `'@overdoser/react-toolkit/theme.css'`. Without it, components render unstyled.
|
|
469
|
+
## Conventions worth knowing
|
|
470
|
+
|
|
471
|
+
1. **Inputs use `inputSize`** for the toolkit size scale. The native `size` HTML attribute is independent.
|
|
472
|
+
2. **`Typography` `color`** accepts only the preset tokens; for arbitrary colors use `style` or `className`.
|
|
473
|
+
3. **`Dropdown` has two modes:** with `options` + `value` + `onChange` it acts as a select input (the `trigger` prop is unused). Without `options`, pass `trigger` and `<DropdownItem>` children.
|
|
474
|
+
4. **`Popover` content** goes through the `content` prop.
|
|
475
|
+
5. **`Modal` content** lives in `Modal.Header`, `Modal.Body`, and `Modal.Footer` — these compound components own the spacing and aria wiring.
|
|
476
|
+
6. **`FormField` clones its single child** to inject `value`/`onChange`/`id`/`name`/`error`/aria. Pass exactly one input element and let `FormField` wire it.
|
|
477
|
+
7. **Server-side `Table`:** providing `onSort` puts the table in controlled mode — the consumer is responsible for sorting and slicing `data` server-side.
|
|
478
|
+
8. **Theme stylesheet** is imported separately: `'@overdoser/react-toolkit/theme.css'`. Without it, components render unstyled.
|
package/manifest.json
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"props": {
|
|
42
42
|
"variant": { "type": "enum", "values": ["h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label"], "default": "p" },
|
|
43
43
|
"weight": { "type": "enum", "values": ["normal", "medium", "semibold", "bold"] },
|
|
44
|
-
"color": { "type": "enum", "values": ["default", "muted", "primary", "danger", "success"], "notes": "
|
|
44
|
+
"color": { "type": "enum", "values": ["default", "muted", "primary", "danger", "success"], "notes": "For arbitrary colors, use style or className." },
|
|
45
45
|
"align": { "type": "enum", "values": ["left", "center", "right"] },
|
|
46
46
|
"truncate": { "type": "boolean", "default": false }
|
|
47
47
|
}
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"requires": "react-hook-form",
|
|
186
186
|
"generic": "T extends FieldValues",
|
|
187
187
|
"props": {
|
|
188
|
-
"form": { "type": "UseFormReturn<T>", "required": true, "notes": "The result of useForm().
|
|
188
|
+
"form": { "type": "UseFormReturn<T>", "required": true, "notes": "The result of useForm()." },
|
|
189
189
|
"onSubmit": { "type": "SubmitHandler<T>", "required": true },
|
|
190
190
|
"errors": { "type": "ReactNode[]", "notes": "Top-of-form errors rendered above children with role=alert." }
|
|
191
191
|
}
|
|
@@ -221,7 +221,7 @@
|
|
|
221
221
|
"extendsNativeProps": "input (without prefix)",
|
|
222
222
|
"forwardsRef": true,
|
|
223
223
|
"props": {
|
|
224
|
-
"inputSize": { "type": "enum", "values": ["sm", "md", "lg"], "default": "md", "notes": "
|
|
224
|
+
"inputSize": { "type": "enum", "values": ["sm", "md", "lg"], "default": "md", "notes": "Toolkit size scale; independent of the native `size` HTML attribute." },
|
|
225
225
|
"error": { "type": "boolean", "default": false },
|
|
226
226
|
"prefix": { "type": "ReactNode" },
|
|
227
227
|
"suffix": { "type": "ReactNode" },
|
|
@@ -339,17 +339,15 @@
|
|
|
339
339
|
"notes": "Only needed if you want to manage sort state outside <Table>."
|
|
340
340
|
}
|
|
341
341
|
},
|
|
342
|
-
"
|
|
343
|
-
"
|
|
344
|
-
"
|
|
345
|
-
"
|
|
346
|
-
"
|
|
347
|
-
"
|
|
348
|
-
"
|
|
349
|
-
"
|
|
350
|
-
"
|
|
351
|
-
"Server-side Table mode (onSort provided) means Table renders data verbatim — no internal sort or pagination slicing.",
|
|
352
|
-
"Theme stylesheet must be imported separately: '@overdoser/react-toolkit/theme.css'."
|
|
342
|
+
"conventions": [
|
|
343
|
+
"Inputs use `inputSize` for the toolkit size scale; the native `size` HTML attribute is independent.",
|
|
344
|
+
"Typography color accepts only the preset tokens; for arbitrary colors use `style` or `className`.",
|
|
345
|
+
"Dropdown has two modes: with `options` + `value` + `onChange` it acts as a select input (the `trigger` prop is unused); without `options`, pass `trigger` and `<DropdownItem>` children.",
|
|
346
|
+
"Popover content goes through the `content` prop.",
|
|
347
|
+
"Modal content lives in Modal.Header / Modal.Body / Modal.Footer compound components.",
|
|
348
|
+
"FormField clones a single child element to inject form props — pass exactly one input element.",
|
|
349
|
+
"Server-side Table mode (when `onSort` is provided): the consumer is responsible for sorting and slicing `data` server-side.",
|
|
350
|
+
"Theme stylesheet is imported separately: '@overdoser/react-toolkit/theme.css'."
|
|
353
351
|
],
|
|
354
352
|
"recipes": [
|
|
355
353
|
"recipes/login-form.tsx",
|