@particle-academy/react-fancy 1.7.1 → 1.7.3
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/dist/index.cjs +24 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/docs/Accordion.md +78 -0
- package/docs/Action.md +76 -0
- package/docs/Autocomplete.md +74 -0
- package/docs/Avatar.md +40 -0
- package/docs/Badge.md +42 -0
- package/docs/Brand.md +44 -0
- package/docs/Breadcrumbs.md +51 -0
- package/docs/Calendar.md +72 -0
- package/docs/Callout.md +46 -0
- package/docs/Canvas.md +102 -0
- package/docs/Card.md +68 -0
- package/docs/Carousel.md +97 -0
- package/docs/Chart.md +126 -0
- package/docs/Checkbox.md +86 -0
- package/docs/ColorPicker.md +49 -0
- package/docs/Command.md +88 -0
- package/docs/Composer.md +60 -0
- package/docs/ContentRenderer.md +68 -0
- package/docs/ContextMenu.md +82 -0
- package/docs/DatePicker.md +64 -0
- package/docs/Diagram.md +119 -0
- package/docs/Dropdown.md +79 -0
- package/docs/Editor.md +84 -0
- package/docs/Emoji.md +40 -0
- package/docs/EmojiSelect.md +47 -0
- package/docs/Field.md +48 -0
- package/docs/FileUpload.md +81 -0
- package/docs/Heading.md +43 -0
- package/docs/Icon.md +75 -0
- package/docs/Input.md +73 -0
- package/docs/Kanban.md +79 -0
- package/docs/Menu.md +71 -0
- package/docs/MobileMenu.md +69 -0
- package/docs/Modal.md +74 -0
- package/docs/MultiSwitch.md +64 -0
- package/docs/Navbar.md +65 -0
- package/docs/OtpInput.md +48 -0
- package/docs/Pagination.md +48 -0
- package/docs/Pillbox.md +53 -0
- package/docs/Popover.md +82 -0
- package/docs/Portal.md +40 -0
- package/docs/Profile.md +52 -0
- package/docs/Progress.md +42 -0
- package/docs/RadioGroup.md +69 -0
- package/docs/Select.md +122 -0
- package/docs/Separator.md +41 -0
- package/docs/Sidebar.md +88 -0
- package/docs/Skeleton.md +44 -0
- package/docs/Slider.md +75 -0
- package/docs/Switch.md +55 -0
- package/docs/Table.md +133 -0
- package/docs/Tabs.md +85 -0
- package/docs/Text.md +44 -0
- package/docs/Textarea.md +62 -0
- package/docs/TimePicker.md +45 -0
- package/docs/Timeline.md +118 -0
- package/docs/Toast.md +79 -0
- package/docs/Tooltip.md +46 -0
- package/docs/hooks.md +180 -0
- package/docs/utilities.md +74 -0
- package/package.json +2 -1
package/docs/Input.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Input
|
|
2
|
+
|
|
3
|
+
Text input with built-in label, error, prefix/suffix, and leading/trailing icon support.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Input } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Input label="Email" type="email" placeholder="you@example.com" />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
Extends all native `<input>` attributes (except `size`, `type`, `prefix`).
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Default | Description |
|
|
22
|
+
|------|------|---------|-------------|
|
|
23
|
+
| `type` | `"text" \| "email" \| "password" \| "number" \| "tel" \| "url" \| "search"` | `"text"` | Input type |
|
|
24
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Controls input height and text size |
|
|
25
|
+
| `label` | `string` | - | Wraps input in a `Field` with this label |
|
|
26
|
+
| `description` | `string` | - | Helper text below the input |
|
|
27
|
+
| `error` | `string` | - | Error message (red text below input, red border) |
|
|
28
|
+
| `required` | `boolean` | `false` | Red asterisk on label, sets native `required` |
|
|
29
|
+
| `dirty` | `boolean` | `false` | Amber ring to indicate unsaved changes |
|
|
30
|
+
| `disabled` | `boolean` | `false` | Disables the input |
|
|
31
|
+
| `leading` | `ReactNode` | - | Icon/element positioned inside the input on the left |
|
|
32
|
+
| `trailing` | `ReactNode` | - | Icon/element positioned inside the input on the right |
|
|
33
|
+
| `prefix` | `ReactNode` | - | Affix rendered before the input |
|
|
34
|
+
| `suffix` | `ReactNode` | - | Affix rendered after the input |
|
|
35
|
+
| `prefixPosition` | `"inside" \| "outside"` | - | Whether prefix renders inside or outside the input border |
|
|
36
|
+
| `suffixPosition` | `"inside" \| "outside"` | - | Whether suffix renders inside or outside the input border |
|
|
37
|
+
| `onValueChange` | `(value: string) => void` | - | Convenience callback with the string value directly |
|
|
38
|
+
| `className` | `string` | - | Additional CSS classes on the `<input>` element |
|
|
39
|
+
|
|
40
|
+
## Examples
|
|
41
|
+
|
|
42
|
+
### With leading icon
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { Search } from "lucide-react";
|
|
46
|
+
|
|
47
|
+
<Input
|
|
48
|
+
label="Search"
|
|
49
|
+
type="search"
|
|
50
|
+
leading={<Search size={16} />}
|
|
51
|
+
placeholder="Search..."
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### With prefix and suffix
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<Input prefix="https://" suffix=".com" placeholder="yoursite" />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Controlled with onValueChange
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
const [email, setEmail] = useState("");
|
|
65
|
+
|
|
66
|
+
<Input
|
|
67
|
+
label="Email"
|
|
68
|
+
type="email"
|
|
69
|
+
value={email}
|
|
70
|
+
onValueChange={setEmail}
|
|
71
|
+
error={email ? undefined : "Required"}
|
|
72
|
+
/>
|
|
73
|
+
```
|
package/docs/Kanban.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Kanban
|
|
2
|
+
|
|
3
|
+
A drag-and-drop kanban board using the HTML5 Drag and Drop API. Cards can be moved between columns.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Kanban } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Kanban onCardMove={(cardId, from, to) => console.log(`${cardId}: ${from} -> ${to}`)}>
|
|
15
|
+
<Kanban.Column id="todo" title="To Do">
|
|
16
|
+
<Kanban.Card id="task-1">Design homepage</Kanban.Card>
|
|
17
|
+
<Kanban.Card id="task-2">Write tests</Kanban.Card>
|
|
18
|
+
</Kanban.Column>
|
|
19
|
+
<Kanban.Column id="in-progress" title="In Progress">
|
|
20
|
+
<Kanban.Card id="task-3">Build API</Kanban.Card>
|
|
21
|
+
</Kanban.Column>
|
|
22
|
+
<Kanban.Column id="done" title="Done">
|
|
23
|
+
<Kanban.Card id="task-4">Setup CI/CD</Kanban.Card>
|
|
24
|
+
</Kanban.Column>
|
|
25
|
+
</Kanban>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Props
|
|
29
|
+
|
|
30
|
+
### Kanban (root)
|
|
31
|
+
|
|
32
|
+
| Prop | Type | Default | Description |
|
|
33
|
+
|------|------|---------|-------------|
|
|
34
|
+
| onCardMove | `(cardId: string, fromColumn: string, toColumn: string) => void` | - | Callback when a card is dropped into a different column |
|
|
35
|
+
| className | `string` | - | Additional CSS classes |
|
|
36
|
+
|
|
37
|
+
### Kanban.Column
|
|
38
|
+
|
|
39
|
+
| Prop | Type | Default | Description |
|
|
40
|
+
|------|------|---------|-------------|
|
|
41
|
+
| id | `string` | - | Unique column identifier (required) |
|
|
42
|
+
| title | `string` | - | Column header text |
|
|
43
|
+
| className | `string` | - | Additional CSS classes |
|
|
44
|
+
|
|
45
|
+
### Kanban.Card
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
|------|------|---------|-------------|
|
|
49
|
+
| id | `string` | - | Unique card identifier (required) |
|
|
50
|
+
| children | `ReactNode` | - | Card content |
|
|
51
|
+
| className | `string` | - | Additional CSS classes |
|
|
52
|
+
|
|
53
|
+
## Stateful Example
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
const [columns, setColumns] = useState({
|
|
57
|
+
todo: ["task-1", "task-2"],
|
|
58
|
+
doing: ["task-3"],
|
|
59
|
+
done: [],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function handleMove(cardId: string, from: string, to: string) {
|
|
63
|
+
setColumns((prev) => ({
|
|
64
|
+
...prev,
|
|
65
|
+
[from]: prev[from].filter((id) => id !== cardId),
|
|
66
|
+
[to]: [...prev[to], cardId],
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
<Kanban onCardMove={handleMove}>
|
|
71
|
+
{Object.entries(columns).map(([colId, cards]) => (
|
|
72
|
+
<Kanban.Column key={colId} id={colId} title={colId}>
|
|
73
|
+
{cards.map((id) => (
|
|
74
|
+
<Kanban.Card key={id} id={id}>{id}</Kanban.Card>
|
|
75
|
+
))}
|
|
76
|
+
</Kanban.Column>
|
|
77
|
+
))}
|
|
78
|
+
</Kanban>
|
|
79
|
+
```
|
package/docs/Menu.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Menu
|
|
2
|
+
|
|
3
|
+
A navigation menu supporting horizontal/vertical orientation, nested submenus, grouped items, icons, and badges.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Menu } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Menu>
|
|
15
|
+
<Menu.Item href="/" active>Home</Menu.Item>
|
|
16
|
+
<Menu.Item href="/about">About</Menu.Item>
|
|
17
|
+
<Menu.Submenu label="Products" icon={<BoxIcon />}>
|
|
18
|
+
<Menu.Item href="/products/widgets">Widgets</Menu.Item>
|
|
19
|
+
<Menu.Item href="/products/gadgets">Gadgets</Menu.Item>
|
|
20
|
+
</Menu.Submenu>
|
|
21
|
+
</Menu>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
### Menu (root)
|
|
27
|
+
|
|
28
|
+
| Prop | Type | Default | Description |
|
|
29
|
+
|------|------|---------|-------------|
|
|
30
|
+
| orientation | `"horizontal" \| "vertical"` | `"vertical"` | Layout direction |
|
|
31
|
+
| className | `string` | - | Additional CSS classes |
|
|
32
|
+
|
|
33
|
+
### Menu.Item
|
|
34
|
+
|
|
35
|
+
| Prop | Type | Default | Description |
|
|
36
|
+
|------|------|---------|-------------|
|
|
37
|
+
| children | `ReactNode` | - | Item content |
|
|
38
|
+
| href | `string` | - | Link URL |
|
|
39
|
+
| icon | `ReactNode` | - | Leading icon |
|
|
40
|
+
| active | `boolean` | - | Active state highlight |
|
|
41
|
+
| disabled | `boolean` | - | Disable the item |
|
|
42
|
+
| badge | `ReactNode` | - | Trailing badge element |
|
|
43
|
+
| onClick | `() => void` | - | Click handler |
|
|
44
|
+
| className | `string` | - | Additional CSS classes |
|
|
45
|
+
|
|
46
|
+
### Menu.Submenu
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Default | Description |
|
|
49
|
+
|------|------|---------|-------------|
|
|
50
|
+
| label | `ReactNode` | - | Submenu trigger label (required) |
|
|
51
|
+
| icon | `ReactNode` | - | Leading icon |
|
|
52
|
+
| defaultOpen | `boolean` | - | Whether the submenu starts open |
|
|
53
|
+
| className | `string` | - | Additional CSS classes |
|
|
54
|
+
|
|
55
|
+
### Menu.Group
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Default | Description |
|
|
58
|
+
|------|------|---------|-------------|
|
|
59
|
+
| children | `ReactNode` | - | Grouped items |
|
|
60
|
+
| label | `string` | - | Group heading |
|
|
61
|
+
| className | `string` | - | Additional CSS classes |
|
|
62
|
+
|
|
63
|
+
## Horizontal Menu
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
<Menu orientation="horizontal">
|
|
67
|
+
<Menu.Item href="/" active>Home</Menu.Item>
|
|
68
|
+
<Menu.Item href="/docs">Docs</Menu.Item>
|
|
69
|
+
<Menu.Item href="/pricing" badge={<span>New</span>}>Pricing</Menu.Item>
|
|
70
|
+
</Menu>
|
|
71
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# MobileMenu
|
|
2
|
+
|
|
3
|
+
Mobile navigation components with two variants: a slide-out flyout panel and a fixed bottom tab bar.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { MobileMenu } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Flyout
|
|
12
|
+
|
|
13
|
+
A slide-out panel from the left or right edge.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
const [open, setOpen] = useState(false);
|
|
17
|
+
|
|
18
|
+
<button onClick={() => setOpen(true)}>Menu</button>
|
|
19
|
+
|
|
20
|
+
<MobileMenu.Flyout open={open} onClose={() => setOpen(false)} side="left" title="Menu">
|
|
21
|
+
<MobileMenu.Item href="/" icon={<HomeIcon />} active>Home</MobileMenu.Item>
|
|
22
|
+
<MobileMenu.Item href="/about" icon={<InfoIcon />}>About</MobileMenu.Item>
|
|
23
|
+
<MobileMenu.Item href="/contact" icon={<MailIcon />}>Contact</MobileMenu.Item>
|
|
24
|
+
</MobileMenu.Flyout>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Bottom Bar
|
|
28
|
+
|
|
29
|
+
A fixed bottom navigation bar for mobile.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<MobileMenu.BottomBar>
|
|
33
|
+
<MobileMenu.Item href="/" icon={<HomeIcon />} active>Home</MobileMenu.Item>
|
|
34
|
+
<MobileMenu.Item href="/search" icon={<SearchIcon />}>Search</MobileMenu.Item>
|
|
35
|
+
<MobileMenu.Item href="/profile" icon={<UserIcon />}>Profile</MobileMenu.Item>
|
|
36
|
+
</MobileMenu.BottomBar>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Props
|
|
40
|
+
|
|
41
|
+
### MobileMenu.Flyout
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| open | `boolean` | - | Whether the flyout is visible (required) |
|
|
46
|
+
| onClose | `() => void` | - | Callback to close the flyout (required) |
|
|
47
|
+
| side | `"left" \| "right"` | - | Which edge the panel slides from |
|
|
48
|
+
| title | `string` | - | Optional header title |
|
|
49
|
+
| className | `string` | - | Additional CSS classes |
|
|
50
|
+
|
|
51
|
+
### MobileMenu.BottomBar
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
|------|------|---------|-------------|
|
|
55
|
+
| children | `ReactNode` | - | Menu items |
|
|
56
|
+
| className | `string` | - | Additional CSS classes |
|
|
57
|
+
|
|
58
|
+
### MobileMenu.Item
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Default | Description |
|
|
61
|
+
|------|------|---------|-------------|
|
|
62
|
+
| children | `ReactNode` | - | Item label |
|
|
63
|
+
| href | `string` | - | Link URL |
|
|
64
|
+
| icon | `ReactNode` | - | Icon element |
|
|
65
|
+
| active | `boolean` | - | Active state highlight |
|
|
66
|
+
| disabled | `boolean` | - | Disable the item |
|
|
67
|
+
| badge | `ReactNode` | - | Badge element |
|
|
68
|
+
| onClick | `() => void` | - | Click handler |
|
|
69
|
+
| className | `string` | - | Additional CSS classes |
|
package/docs/Modal.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Modal
|
|
2
|
+
|
|
3
|
+
A dialog overlay with backdrop, focus trapping, escape-to-close, and body scroll locking. Renders via a portal.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Modal } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
const [open, setOpen] = useState(false);
|
|
15
|
+
|
|
16
|
+
<button onClick={() => setOpen(true)}>Open Modal</button>
|
|
17
|
+
|
|
18
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
19
|
+
<Modal.Header>Confirm Action</Modal.Header>
|
|
20
|
+
<Modal.Body>
|
|
21
|
+
<p>Are you sure you want to proceed?</p>
|
|
22
|
+
</Modal.Body>
|
|
23
|
+
<Modal.Footer>
|
|
24
|
+
<button onClick={() => setOpen(false)}>Cancel</button>
|
|
25
|
+
<button onClick={handleConfirm}>Confirm</button>
|
|
26
|
+
</Modal.Footer>
|
|
27
|
+
</Modal>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Props
|
|
31
|
+
|
|
32
|
+
### Modal (root)
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Description |
|
|
35
|
+
|------|------|---------|-------------|
|
|
36
|
+
| open | `boolean` | - | Whether the modal is visible (required) |
|
|
37
|
+
| onClose | `() => void` | - | Callback to close the modal (required) |
|
|
38
|
+
| size | `"sm" \| "md" \| "lg" \| "xl" \| "full"` | `"md"` | Max width of the modal panel |
|
|
39
|
+
| className | `string` | - | Additional CSS classes for the panel |
|
|
40
|
+
|
|
41
|
+
### Modal.Header
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| children | `ReactNode` | - | Header content |
|
|
46
|
+
| className | `string` | - | Additional CSS classes |
|
|
47
|
+
|
|
48
|
+
### Modal.Body
|
|
49
|
+
|
|
50
|
+
| Prop | Type | Default | Description |
|
|
51
|
+
|------|------|---------|-------------|
|
|
52
|
+
| children | `ReactNode` | - | Body content |
|
|
53
|
+
| className | `string` | - | Additional CSS classes |
|
|
54
|
+
|
|
55
|
+
### Modal.Footer
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Default | Description |
|
|
58
|
+
|------|------|---------|-------------|
|
|
59
|
+
| children | `ReactNode` | - | Footer content (typically action buttons) |
|
|
60
|
+
| className | `string` | - | Additional CSS classes |
|
|
61
|
+
|
|
62
|
+
## Large Modal
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<Modal open={open} onClose={() => setOpen(false)} size="xl">
|
|
66
|
+
<Modal.Header>Large Content</Modal.Header>
|
|
67
|
+
<Modal.Body>
|
|
68
|
+
<p>This modal uses the xl size variant for wider content.</p>
|
|
69
|
+
</Modal.Body>
|
|
70
|
+
<Modal.Footer>
|
|
71
|
+
<button onClick={() => setOpen(false)}>Close</button>
|
|
72
|
+
</Modal.Footer>
|
|
73
|
+
</Modal>
|
|
74
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# MultiSwitch
|
|
2
|
+
|
|
3
|
+
Segmented control that allows selecting one value from a set of options, with an animated sliding indicator.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { MultiSwitch } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<MultiSwitch
|
|
15
|
+
list={["Daily", "Weekly", "Monthly"]}
|
|
16
|
+
defaultValue="Weekly"
|
|
17
|
+
/>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Description |
|
|
23
|
+
|------|------|---------|-------------|
|
|
24
|
+
| `list` | `InputOption[]` | **required** | Options as strings or `{ value, label, disabled? }` |
|
|
25
|
+
| `value` | `V` | - | Controlled selected value |
|
|
26
|
+
| `defaultValue` | `V` | first option | Default selected value (uncontrolled) |
|
|
27
|
+
| `onValueChange` | `(value: V) => void` | - | Callback when selection changes |
|
|
28
|
+
| `linear` | `boolean` | `false` | When true, clicking any button cycles to the next option instead of selecting the clicked one |
|
|
29
|
+
| `label` | `string` | - | Wraps in a `Field` with this label |
|
|
30
|
+
| `description` | `string` | - | Helper text |
|
|
31
|
+
| `error` | `string` | - | Error message |
|
|
32
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Controls padding and text size |
|
|
33
|
+
| `dirty` | `boolean` | `false` | Amber ring |
|
|
34
|
+
| `disabled` | `boolean` | `false` | Disables all options |
|
|
35
|
+
| `name` | `string` | - | Form field name (renders a hidden input) |
|
|
36
|
+
| `className` | `string` | - | Additional CSS classes |
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
### Controlled with label
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
const [interval, setInterval] = useState("monthly");
|
|
44
|
+
|
|
45
|
+
<MultiSwitch
|
|
46
|
+
label="Billing interval"
|
|
47
|
+
list={[
|
|
48
|
+
{ value: "monthly", label: "Monthly" },
|
|
49
|
+
{ value: "yearly", label: "Yearly" },
|
|
50
|
+
]}
|
|
51
|
+
value={interval}
|
|
52
|
+
onValueChange={setInterval}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Linear cycling
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<MultiSwitch
|
|
60
|
+
linear
|
|
61
|
+
list={["Off", "Low", "Medium", "High"]}
|
|
62
|
+
defaultValue="Off"
|
|
63
|
+
/>
|
|
64
|
+
```
|
package/docs/Navbar.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Navbar
|
|
2
|
+
|
|
3
|
+
A top navigation bar with brand slot, navigation items, and a mobile hamburger toggle.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Navbar } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Navbar>
|
|
15
|
+
<Navbar.Brand>
|
|
16
|
+
<a href="/">MyApp</a>
|
|
17
|
+
</Navbar.Brand>
|
|
18
|
+
<Navbar.Items>
|
|
19
|
+
<Navbar.Item href="/" active>Home</Navbar.Item>
|
|
20
|
+
<Navbar.Item href="/about">About</Navbar.Item>
|
|
21
|
+
<Navbar.Item href="/contact">Contact</Navbar.Item>
|
|
22
|
+
</Navbar.Items>
|
|
23
|
+
<Navbar.Toggle />
|
|
24
|
+
</Navbar>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Props
|
|
28
|
+
|
|
29
|
+
### Navbar (root)
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
|------|------|---------|-------------|
|
|
33
|
+
| children | `ReactNode` | - | Brand, items, toggle children |
|
|
34
|
+
| className | `string` | - | Additional CSS classes |
|
|
35
|
+
|
|
36
|
+
### Navbar.Brand
|
|
37
|
+
|
|
38
|
+
| Prop | Type | Default | Description |
|
|
39
|
+
|------|------|---------|-------------|
|
|
40
|
+
| children | `ReactNode` | - | Logo or brand element |
|
|
41
|
+
| className | `string` | - | Additional CSS classes |
|
|
42
|
+
|
|
43
|
+
### Navbar.Items
|
|
44
|
+
|
|
45
|
+
| Prop | Type | Default | Description |
|
|
46
|
+
|------|------|---------|-------------|
|
|
47
|
+
| children | `ReactNode` | - | Navigation items |
|
|
48
|
+
| className | `string` | - | Additional CSS classes |
|
|
49
|
+
|
|
50
|
+
### Navbar.Item
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
|------|------|---------|-------------|
|
|
54
|
+
| children | `ReactNode` | - | Item content |
|
|
55
|
+
| href | `string` | - | Link URL |
|
|
56
|
+
| active | `boolean` | - | Active/current page indicator |
|
|
57
|
+
| className | `string` | - | Additional CSS classes |
|
|
58
|
+
|
|
59
|
+
### Navbar.Toggle
|
|
60
|
+
|
|
61
|
+
| Prop | Type | Default | Description |
|
|
62
|
+
|------|------|---------|-------------|
|
|
63
|
+
| className | `string` | - | Additional CSS classes |
|
|
64
|
+
|
|
65
|
+
The Navbar manages a `mobileOpen` state internally. `Navbar.Toggle` toggles the mobile navigation drawer, and `Navbar.Items` responds to that state.
|
package/docs/OtpInput.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# OtpInput
|
|
2
|
+
|
|
3
|
+
One-time password input with individual digit cells, auto-advance, and paste support.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { OtpInput } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<OtpInput length={6} onChange={(code) => console.log(code)} />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Description |
|
|
20
|
+
|------|------|---------|-------------|
|
|
21
|
+
| `length` | `number` | `6` | Number of digit cells |
|
|
22
|
+
| `value` | `string` | - | Controlled value |
|
|
23
|
+
| `onChange` | `(value: string) => void` | - | Callback with the full OTP string |
|
|
24
|
+
| `disabled` | `boolean` | `false` | Disables all inputs |
|
|
25
|
+
| `autoFocus` | `boolean` | `false` | Auto-focus the first cell on mount |
|
|
26
|
+
| `className` | `string` | - | Additional CSS classes on the container |
|
|
27
|
+
|
|
28
|
+
**Behavior:**
|
|
29
|
+
- Only numeric digits are accepted.
|
|
30
|
+
- Focus advances to the next cell after input.
|
|
31
|
+
- **Backspace** clears the current cell, or moves to the previous cell if already empty.
|
|
32
|
+
- **Arrow keys** move focus between cells.
|
|
33
|
+
- **Paste** fills cells from the clipboard (non-numeric characters are stripped).
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
### 4-digit code with auto-focus
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
const [code, setCode] = useState("");
|
|
41
|
+
|
|
42
|
+
<OtpInput
|
|
43
|
+
length={4}
|
|
44
|
+
autoFocus
|
|
45
|
+
value={code}
|
|
46
|
+
onChange={setCode}
|
|
47
|
+
/>
|
|
48
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Pagination
|
|
2
|
+
|
|
3
|
+
A page navigation component with previous/next buttons, page numbers, and ellipsis for large ranges.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Pagination } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Pagination page={1} totalPages={10} onPageChange={setPage} />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Description |
|
|
20
|
+
|------|------|---------|-------------|
|
|
21
|
+
| page | `number` | **required** | Current active page (1-based) |
|
|
22
|
+
| onPageChange | `(page: number) => void` | **required** | Callback when a page is selected |
|
|
23
|
+
| totalPages | `number` | **required** | Total number of pages |
|
|
24
|
+
| siblingCount | `number` | `1` | Number of sibling pages shown around the current page |
|
|
25
|
+
| className | `string` | - | Additional CSS classes |
|
|
26
|
+
|
|
27
|
+
Renders `null` when `totalPages <= 1`. Automatically inserts ellipsis when the page count exceeds the visible slot count.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### Basic pagination
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const [page, setPage] = useState(1);
|
|
35
|
+
|
|
36
|
+
<Pagination page={page} totalPages={20} onPageChange={setPage} />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### More visible siblings
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<Pagination
|
|
43
|
+
page={page}
|
|
44
|
+
totalPages={50}
|
|
45
|
+
onPageChange={setPage}
|
|
46
|
+
siblingCount={2}
|
|
47
|
+
/>
|
|
48
|
+
```
|
package/docs/Pillbox.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Pillbox
|
|
2
|
+
|
|
3
|
+
Tag/pill input that lets users type free-text values and manage them as removable pills.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Pillbox } from "@particle-academy/react-fancy";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Pillbox placeholder="Add tags..." onChange={(tags) => console.log(tags)} />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Description |
|
|
20
|
+
|------|------|---------|-------------|
|
|
21
|
+
| `value` | `string[]` | - | Controlled list of items |
|
|
22
|
+
| `defaultValue` | `string[]` | `[]` | Default items (uncontrolled) |
|
|
23
|
+
| `onChange` | `(values: string[]) => void` | - | Callback when items change |
|
|
24
|
+
| `placeholder` | `string` | `"Type and press Enter..."` | Placeholder (shown only when no items exist) |
|
|
25
|
+
| `maxItems` | `number` | - | Maximum number of items allowed |
|
|
26
|
+
| `disabled` | `boolean` | `false` | Disables input and removal |
|
|
27
|
+
| `className` | `string` | - | Additional CSS classes |
|
|
28
|
+
|
|
29
|
+
**Behavior:**
|
|
30
|
+
- Press **Enter** to add the current text as a pill. Duplicates and empty strings are ignored.
|
|
31
|
+
- Press **Backspace** on an empty input to remove the last pill.
|
|
32
|
+
- Click the **X** on any pill to remove it.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### With max items
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<Pillbox
|
|
40
|
+
placeholder="Add up to 5 skills..."
|
|
41
|
+
maxItems={5}
|
|
42
|
+
defaultValue={["React", "TypeScript"]}
|
|
43
|
+
onChange={setSkills}
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Controlled
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
const [emails, setEmails] = useState<string[]>([]);
|
|
51
|
+
|
|
52
|
+
<Pillbox value={emails} onChange={setEmails} placeholder="Add email addresses..." />
|
|
53
|
+
```
|