laif-ds 0.2.44 → 0.2.45
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/_virtual/index4.js +5 -5
- package/dist/_virtual/index5.js +5 -5
- package/dist/_virtual/index6.js +2 -2
- package/dist/_virtual/index7.js +2 -2
- package/dist/agent-docs/components/Accordion.md +157 -0
- package/dist/agent-docs/components/Alert.md +95 -0
- package/dist/agent-docs/components/AlertDialog.md +126 -0
- package/dist/agent-docs/components/AppEditor.md +90 -0
- package/dist/agent-docs/components/AppForm.md +242 -0
- package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
- package/dist/agent-docs/components/AppRadioGroup.md +223 -0
- package/dist/agent-docs/components/AppSelect.md +427 -0
- package/dist/agent-docs/components/AppSidebar.md +122 -0
- package/dist/agent-docs/components/AppStepper.md +77 -0
- package/dist/agent-docs/components/AspectRatio.md +87 -0
- package/dist/agent-docs/components/AsyncSelect.md +127 -0
- package/dist/agent-docs/components/AudioVisualizer.md +41 -0
- package/dist/agent-docs/components/Avatar.md +113 -0
- package/dist/agent-docs/components/Badge.md +118 -0
- package/dist/agent-docs/components/Breadcrumb.md +78 -0
- package/dist/agent-docs/components/Button.md +129 -0
- package/dist/agent-docs/components/Calendar.md +222 -0
- package/dist/agent-docs/components/Card.md +147 -0
- package/dist/agent-docs/components/Carousel.md +129 -0
- package/dist/agent-docs/components/Chart.md +75 -0
- package/dist/agent-docs/components/Chat.md +109 -0
- package/dist/agent-docs/components/ChatMessage.md +61 -0
- package/dist/agent-docs/components/Checkbox.md +135 -0
- package/dist/agent-docs/components/CircularProgress.md +49 -0
- package/dist/agent-docs/components/CodeHighlighter.md +31 -0
- package/dist/agent-docs/components/Collapsible.md +95 -0
- package/dist/agent-docs/components/Command.md +142 -0
- package/dist/agent-docs/components/Confirmer.md +175 -0
- package/dist/agent-docs/components/ContextMenu.md +191 -0
- package/dist/agent-docs/components/CopyButton.md +26 -0
- package/dist/agent-docs/components/DataCrossTable.md +94 -0
- package/dist/agent-docs/components/DataTable.md +254 -0
- package/dist/agent-docs/components/DatePicker.md +109 -0
- package/dist/agent-docs/components/Dialog.md +125 -0
- package/dist/agent-docs/components/Drawer.md +127 -0
- package/dist/agent-docs/components/DropdownMenu.md +57 -0
- package/dist/agent-docs/components/FilePreview.md +99 -0
- package/dist/agent-docs/components/FilePreviewer.md +139 -0
- package/dist/agent-docs/components/FileUploader.md +129 -0
- package/dist/agent-docs/components/Form.md +62 -0
- package/dist/agent-docs/components/FormComposer.md +137 -0
- package/dist/agent-docs/components/GanttChart.md +122 -0
- package/dist/agent-docs/components/HoverCard.md +37 -0
- package/dist/agent-docs/components/Icon.md +99 -0
- package/dist/agent-docs/components/Input.md +138 -0
- package/dist/agent-docs/components/InputOtp.md +40 -0
- package/dist/agent-docs/components/InputSelector.md +97 -0
- package/dist/agent-docs/components/InterruptPrompt.md +32 -0
- package/dist/agent-docs/components/Label.md +28 -0
- package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
- package/dist/agent-docs/components/Menubar.md +164 -0
- package/dist/agent-docs/components/MessageInput.md +131 -0
- package/dist/agent-docs/components/MessageList.md +96 -0
- package/dist/agent-docs/components/MultipleSelector.md +146 -0
- package/dist/agent-docs/components/NavigationMenu.md +51 -0
- package/dist/agent-docs/components/Pagination.md +55 -0
- package/dist/agent-docs/components/Popover.md +103 -0
- package/dist/agent-docs/components/Progress.md +30 -0
- package/dist/agent-docs/components/PromptSuggestions.md +33 -0
- package/dist/agent-docs/components/RadioGroup.md +90 -0
- package/dist/agent-docs/components/Resizable.md +35 -0
- package/dist/agent-docs/components/ResizePrompt.md +13 -0
- package/dist/agent-docs/components/ScrollArea.md +49 -0
- package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
- package/dist/agent-docs/components/Select.md +132 -0
- package/dist/agent-docs/components/Separator.md +32 -0
- package/dist/agent-docs/components/Sheet.md +40 -0
- package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
- package/dist/agent-docs/components/Sidebar.md +85 -0
- package/dist/agent-docs/components/Skeleton.md +29 -0
- package/dist/agent-docs/components/Slider.md +58 -0
- package/dist/agent-docs/components/Sonner.md +21 -0
- package/dist/agent-docs/components/Spinner.md +139 -0
- package/dist/agent-docs/components/Stepper.md +67 -0
- package/dist/agent-docs/components/Switch.md +42 -0
- package/dist/agent-docs/components/Table.md +63 -0
- package/dist/agent-docs/components/TableSkeleton.md +46 -0
- package/dist/agent-docs/components/Tabs.md +86 -0
- package/dist/agent-docs/components/TextArea.md +52 -0
- package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
- package/dist/agent-docs/components/Toaster.md +23 -0
- package/dist/agent-docs/components/Toggle.md +31 -0
- package/dist/agent-docs/components/ToggleGroup.md +30 -0
- package/dist/agent-docs/components/Tooltip.md +91 -0
- package/dist/agent-docs/components/TypingIndicator.md +21 -0
- package/dist/agent-docs/components/Typo.md +65 -0
- package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
- package/dist/agent-docs/components-list.md +144 -0
- package/dist/node_modules/eventemitter3/index2.js +1 -1
- package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
- package/dist/node_modules/style-to-object/cjs/index.js +1 -1
- package/dist/node_modules/unified/lib/index.js +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# ChatMessage
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Render a single chat message bubble with markdown, optional attachments preview, tool invocation blocks, reasoning collapsible, time stamps, actions and inline edit for assistant messages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
| --------------- | ------------------------ | ----------- | ----------- |
|
|
13
|
+
| `id` | `string` | **required**| Message id. |
|
|
14
|
+
| `role` | `"user" | "assistant" | (string)` | **required**| Role determines bubble style and alignment. |
|
|
15
|
+
| `content` | `string` | **required**| Message text (markdown supported). |
|
|
16
|
+
| `createdAt` | `Date` | `undefined` | Optional timestamp. |
|
|
17
|
+
| `experimental_attachments` | `{ url: string; name?: string; contentType?: string }[]` | `undefined` | Files to preview (user messages). |
|
|
18
|
+
| `toolInvocations` | `ToolInvocation[]` | `undefined` | Tool call states (`call`, `result`). |
|
|
19
|
+
| `parts` | `MessagePart[]` | `undefined` | Mixed message content (text/reasoning/tool-invocation). |
|
|
20
|
+
| `showTimeStamp` | `boolean` | `false` | Show `createdAt` under bubble. |
|
|
21
|
+
| `animation` | `"none" | "slide" | "scale" | "fade"` | `"scale"` | Entry animation.
|
|
22
|
+
| `actions` | `React.ReactNode` | `undefined` | Action buttons area (shown on hover). |
|
|
23
|
+
| `editable` | `boolean` | `false` | Force edit UI even without `onEdit`. |
|
|
24
|
+
| `onEdit` | `(newContent: string) => void` | `undefined` | Show edit UI on assistant messages. |
|
|
25
|
+
| `onMessageSave` | `(messageId: string, content: string) => void` | `undefined` | Save callback (rendered in action area). |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Behavior
|
|
30
|
+
|
|
31
|
+
- **User vs Assistant**: Different bubble alignment and token styles.
|
|
32
|
+
- **Markdown**: Rendered via `MarkdownRenderer` with async suspense fallback.
|
|
33
|
+
- **Attachments**: User attachments rendered as `FilePreview` chips.
|
|
34
|
+
- **Tool calls**: `ToolInvocation` blocks show calling/result state with icons.
|
|
35
|
+
- **Edit**: Assistant messages can be edited inline (Enter save, Esc cancel).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { ChatMessage } from "laif-ds";
|
|
43
|
+
|
|
44
|
+
export function Examples() {
|
|
45
|
+
return (
|
|
46
|
+
<div className="space-y-4">
|
|
47
|
+
<ChatMessage id="u1" role="user" content="Hello" createdAt={new Date()} showTimeStamp />
|
|
48
|
+
<ChatMessage id="a1" role="assistant" content="Hi there!" createdAt={new Date()} showTimeStamp />
|
|
49
|
+
<ChatMessage id="a2" role="assistant" content={"**Bold** and `code`"} />
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Notes
|
|
58
|
+
|
|
59
|
+
- **Reasoning**: Use `parts` with `{ type: "reasoning", reasoning: string }` to show collapsible reasoning.
|
|
60
|
+
- **Actions**: Pass small `Button`s or icons (from `laif-ds`) via `actions`.
|
|
61
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Checkbox
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Accessible checkbox with support for checked, unchecked, and indeterminate states. Keyboard focus styles and disabled state included.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### Checkbox (Root)
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| ------------------ | -------------------------------------- | ------------ | -------------------------------------------------- |
|
|
15
|
+
| `checked` | `boolean \| "indeterminate"` | `false` | Current state of the checkbox. |
|
|
16
|
+
| `disabled` | `boolean` | `false` | Disables interactions. |
|
|
17
|
+
| `onCheckedChange` | `(checked: boolean) => void` | `undefined` | Called when the state changes. |
|
|
18
|
+
| `id` | `string` | `undefined` | Useful when paired with a label's `htmlFor`. |
|
|
19
|
+
| `className` | `string` | `""` | Additional classes for size/layout. |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Behavior
|
|
24
|
+
|
|
25
|
+
- **Indeterminate**: Use `checked="indeterminate"` to display a dash indicator.
|
|
26
|
+
- **Focus & invalid**: Visual feedback for focus and invalid states is included.
|
|
27
|
+
- **Labeling**: Pair with `Label` and `htmlFor` for accessible labeling.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### Default
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { Checkbox } from "laif-ds";
|
|
37
|
+
import { Label } from "laif-ds";
|
|
38
|
+
|
|
39
|
+
export function DefaultCheckbox() {
|
|
40
|
+
return (
|
|
41
|
+
<div className="flex items-center gap-2">
|
|
42
|
+
<Checkbox id="terms" />
|
|
43
|
+
<Label htmlFor="terms">Accept terms and conditions</Label>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Indeterminate
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Checkbox } from "laif-ds";
|
|
53
|
+
import { Label } from "laif-ds";
|
|
54
|
+
|
|
55
|
+
export function IndeterminateCheckbox() {
|
|
56
|
+
return (
|
|
57
|
+
<div className="flex items-center gap-2">
|
|
58
|
+
<Checkbox id="partial" checked="indeterminate" />
|
|
59
|
+
<Label htmlFor="partial">Partially selected options</Label>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Disabled
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Checkbox } from "laif-ds";
|
|
69
|
+
import { Label } from "laif-ds";
|
|
70
|
+
|
|
71
|
+
export function DisabledCheckbox() {
|
|
72
|
+
return (
|
|
73
|
+
<div className="flex items-center gap-2">
|
|
74
|
+
<Checkbox id="disabled" disabled />
|
|
75
|
+
<Label htmlFor="disabled">Accept terms and conditions</Label>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Select All Pattern
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import * as React from "react";
|
|
85
|
+
import { Checkbox } from "laif-ds";
|
|
86
|
+
import { Label } from "laif-ds";
|
|
87
|
+
|
|
88
|
+
export function SelectAllExample() {
|
|
89
|
+
const [items, setItems] = React.useState([
|
|
90
|
+
{ id: "item1", label: "Item 1", checked: false },
|
|
91
|
+
{ id: "item2", label: "Item 2", checked: true },
|
|
92
|
+
{ id: "item3", label: "Item 3", checked: false },
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const checkedCount = items.filter((i) => i.checked).length;
|
|
96
|
+
const selectAllState =
|
|
97
|
+
checkedCount === 0 ? false : checkedCount === items.length ? true : ("indeterminate" as const);
|
|
98
|
+
|
|
99
|
+
const handleSelectAll = () => {
|
|
100
|
+
const newChecked = selectAllState !== true;
|
|
101
|
+
setItems(items.map((i) => ({ ...i, checked: newChecked })));
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div className="space-y-4">
|
|
106
|
+
<div className="flex items-center gap-2 border-b pb-2">
|
|
107
|
+
<Checkbox id="select-all" checked={selectAllState} onCheckedChange={handleSelectAll} />
|
|
108
|
+
<Label htmlFor="select-all">Select All ({checkedCount}/{items.length})</Label>
|
|
109
|
+
</div>
|
|
110
|
+
<div className="space-y-2 pl-6">
|
|
111
|
+
{items.map((item) => (
|
|
112
|
+
<div key={item.id} className="flex items-center gap-2">
|
|
113
|
+
<Checkbox
|
|
114
|
+
id={item.id}
|
|
115
|
+
checked={item.checked}
|
|
116
|
+
onCheckedChange={(checked) =>
|
|
117
|
+
setItems(items.map((i) => (i.id === item.id ? { ...i, checked: checked as boolean } : i)))
|
|
118
|
+
}
|
|
119
|
+
/>
|
|
120
|
+
<Label htmlFor={item.id}>{item.label}</Label>
|
|
121
|
+
</div>
|
|
122
|
+
))}
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Notes
|
|
132
|
+
|
|
133
|
+
- **Indicator**: A check icon is shown when `checked=true`, a dash for indeterminate.
|
|
134
|
+
- **Disabled**: Applies reduced opacity and disables pointer events.
|
|
135
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# CircularProgress
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SVG-based circular progress with customizable size, stroke widths, end-cap shape, and optional centered label.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
| ------------------- | ------------------------------------ | ----------- | ----------- |
|
|
13
|
+
| `value` | `number` | **required**| Percentage [0-100]. |
|
|
14
|
+
| `renderLabel` | `(progress: number) => number|string`| `undefined` | Custom label renderer. |
|
|
15
|
+
| `size` | `number` | `100` | Diameter in px. |
|
|
16
|
+
| `strokeWidth` | `number` | `undefined` | Overrides both circle and progress stroke widths. |
|
|
17
|
+
| `circleStrokeWidth` | `number` | `10` | Base circle stroke width. |
|
|
18
|
+
| `progressStrokeWidth`| `number` | `10` | Progress stroke width. |
|
|
19
|
+
| `shape` | `"square" | "round"` | `"round"` | Stroke line cap. |
|
|
20
|
+
| `className` | `string` | `undefined` | Base circle classes. |
|
|
21
|
+
| `progressClassName` | `string` | `undefined` | Progress circle classes. |
|
|
22
|
+
| `labelClassName` | `string` | `undefined` | Center label classes. |
|
|
23
|
+
| `showLabel` | `boolean` | `false` | Show `{value}` (or `renderLabel(value)`) inside.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { CircularProgress } from "laif-ds";
|
|
31
|
+
|
|
32
|
+
export function Basic() {
|
|
33
|
+
return <CircularProgress value={65} size={100} showLabel />;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function CustomLabel() {
|
|
37
|
+
return (
|
|
38
|
+
<CircularProgress value={42} size={120} showLabel renderLabel={(v) => `${v}%`} />
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
- **Theming**: Base circle uses `stroke-d-primary/25`; progress uses `stroke-d-primary`.
|
|
48
|
+
- **Performance**: Pure SVG; safe to animate via CSS if needed.
|
|
49
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# CodeHighlighter
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Client-side code highlighter using Shiki with internal loading state and graceful fallback.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Description |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `children` | `string` | Code string |
|
|
14
|
+
| `language` | `string` | Shiki language key |
|
|
15
|
+
| `className` | `string` | Optional classes for `<pre>` |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import CodeHighlighter from "laif-ds/CodeHighlighter";
|
|
23
|
+
|
|
24
|
+
export function CodeExample() {
|
|
25
|
+
return (
|
|
26
|
+
<CodeHighlighter language="tsx" className="rounded-md border p-3 text-sm">
|
|
27
|
+
{`export const x = (n: number) => n * 2`}
|
|
28
|
+
</CodeHighlighter>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Collapsible
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A simple container that can show/hide content. Provides a trigger element and animated content area. Useful for progressive disclosure of details.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### Collapsible (Root)
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| -------------- | -------------------- | ----------- | --------------------------------------------- |
|
|
15
|
+
| `open` | `boolean` | `undefined` | Controlled open state. |
|
|
16
|
+
| `defaultOpen` | `boolean` | `false` | Uncontrolled initial open state. |
|
|
17
|
+
| `onOpenChange` | `(open: boolean) => void` | `undefined` | Called when open state changes. |
|
|
18
|
+
| `className` | `string` | `""` | Additional classes for the root. |
|
|
19
|
+
|
|
20
|
+
### Subcomponents
|
|
21
|
+
|
|
22
|
+
- `CollapsibleTrigger`: The element that toggles visibility (can be used with `asChild`).
|
|
23
|
+
- `CollapsibleContent`: The collapsible content region.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Behavior
|
|
28
|
+
|
|
29
|
+
- **Controlled**: Use `open` + `onOpenChange` to control state.
|
|
30
|
+
- **Uncontrolled**: Use `defaultOpen` for initial state.
|
|
31
|
+
- **Accessibility**: Works with button triggers and keyboard navigation.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
### Basic
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { useState } from "react";
|
|
41
|
+
import { Button } from "laif-ds";
|
|
42
|
+
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "laif-ds";
|
|
43
|
+
|
|
44
|
+
export function BasicCollapsible() {
|
|
45
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
46
|
+
return (
|
|
47
|
+
<Collapsible open={isOpen} onOpenChange={setIsOpen} className="w-[350px] space-y-2">
|
|
48
|
+
<div className="flex items-center justify-between gap-4 px-4">
|
|
49
|
+
<h4 className="text-sm font-semibold">Details</h4>
|
|
50
|
+
<CollapsibleTrigger asChild>
|
|
51
|
+
<Button variant="ghost" size="sm">Toggle</Button>
|
|
52
|
+
</CollapsibleTrigger>
|
|
53
|
+
</div>
|
|
54
|
+
<CollapsibleContent className="space-y-2">
|
|
55
|
+
<div className="border-d-border rounded-md border px-4 py-3 text-sm">Item A</div>
|
|
56
|
+
<div className="border-d-border rounded-md border px-4 py-3 text-sm">Item B</div>
|
|
57
|
+
<div className="border-d-border rounded-md border px-4 py-3 text-sm">Item C</div>
|
|
58
|
+
</CollapsibleContent>
|
|
59
|
+
</Collapsible>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Open by Default
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { useState } from "react";
|
|
68
|
+
import { Button } from "laif-ds";
|
|
69
|
+
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "laif-ds";
|
|
70
|
+
|
|
71
|
+
export function OpenByDefault() {
|
|
72
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
73
|
+
return (
|
|
74
|
+
<Collapsible open={isOpen} onOpenChange={setIsOpen} className="w-[350px] space-y-2">
|
|
75
|
+
<div className="flex items-center justify-between gap-4 px-4">
|
|
76
|
+
<h4 className="text-sm font-semibold">Details</h4>
|
|
77
|
+
<CollapsibleTrigger asChild>
|
|
78
|
+
<Button variant="ghost" size="sm">Toggle</Button>
|
|
79
|
+
</CollapsibleTrigger>
|
|
80
|
+
</div>
|
|
81
|
+
<CollapsibleContent className="space-y-2">
|
|
82
|
+
<div className="rounded-md border px-4 py-3 text-sm">This is additional information.</div>
|
|
83
|
+
</CollapsibleContent>
|
|
84
|
+
</Collapsible>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Notes
|
|
92
|
+
|
|
93
|
+
- **asChild**: Wrap your own button/link as trigger while preserving styles.
|
|
94
|
+
- **Styling**: Use `className` on root/content to adjust spacing and borders.
|
|
95
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Command
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Command palette and command list built on `cmdk`. Provides an input for filtering, groups, items, separators, and a dialog wrapper for modal usage.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### Command (Root)
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| ----------- | ----------------- | ----------- | -------------------------------------------------- |
|
|
15
|
+
| `className` | `string` | `""` | Additional classes for layout/size. |
|
|
16
|
+
| `children` | `React.ReactNode` | **required**| Compose with input, list, groups, items, etc. |
|
|
17
|
+
|
|
18
|
+
### CommandDialog
|
|
19
|
+
|
|
20
|
+
Wraps a `Dialog` and renders a `Command` inside.
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Description |
|
|
23
|
+
| -------------- | ------------------------ | -------------------------------------- | -------------------------------- |
|
|
24
|
+
| `open` | `boolean` | `undefined` | Controlled open state. |
|
|
25
|
+
| `onOpenChange` | `(open: boolean) => any` | `undefined` | Called when dialog state changes.|
|
|
26
|
+
| `title` | `string` | `"Command Palette"` | Accessible dialog title. |
|
|
27
|
+
| `description` | `string` | `"Search for a command to run..."` | Accessible dialog description. |
|
|
28
|
+
|
|
29
|
+
### Subcomponents
|
|
30
|
+
|
|
31
|
+
- `CommandInput`: Search input with a leading search icon.
|
|
32
|
+
- `CommandList`: Scrollable list container.
|
|
33
|
+
- `CommandEmpty`: Empty state when no results match.
|
|
34
|
+
- `CommandGroup`: Group with optional `heading` prop.
|
|
35
|
+
- `CommandItem`: Selectable item (supports disabled state).
|
|
36
|
+
- `CommandSeparator`: Visual separator between groups.
|
|
37
|
+
- `CommandShortcut`: Right-aligned shortcut hint (e.g., `⌘K`).
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Behavior
|
|
42
|
+
|
|
43
|
+
- **Filtering**: Typing in `CommandInput` filters visible items.
|
|
44
|
+
- **Keyboard**: Arrow keys navigate, Enter selects, Esc can close the dialog.
|
|
45
|
+
- **Accessibility**: Proper roles/aria set by `cmdk` and dialog wrapper.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### Basic List
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import {
|
|
55
|
+
Command,
|
|
56
|
+
CommandEmpty,
|
|
57
|
+
CommandGroup,
|
|
58
|
+
CommandInput,
|
|
59
|
+
CommandItem,
|
|
60
|
+
CommandList,
|
|
61
|
+
CommandSeparator,
|
|
62
|
+
CommandShortcut,
|
|
63
|
+
} from "laif-ds";
|
|
64
|
+
|
|
65
|
+
export function BasicCommand() {
|
|
66
|
+
return (
|
|
67
|
+
<Command className="border-d-border w-[400px] rounded-lg border shadow-md">
|
|
68
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
69
|
+
<CommandList>
|
|
70
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
71
|
+
<CommandGroup heading="Suggestions">
|
|
72
|
+
<CommandItem>Calendar</CommandItem>
|
|
73
|
+
<CommandItem>Search</CommandItem>
|
|
74
|
+
<CommandItem>Settings</CommandItem>
|
|
75
|
+
</CommandGroup>
|
|
76
|
+
<CommandSeparator />
|
|
77
|
+
<CommandGroup heading="User">
|
|
78
|
+
<CommandItem>
|
|
79
|
+
Profile
|
|
80
|
+
<CommandShortcut>⌘P</CommandShortcut>
|
|
81
|
+
</CommandItem>
|
|
82
|
+
<CommandItem>Billing</CommandItem>
|
|
83
|
+
<CommandItem>Logout</CommandItem>
|
|
84
|
+
</CommandGroup>
|
|
85
|
+
</CommandList>
|
|
86
|
+
</Command>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Command Dialog
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { useState } from "react";
|
|
95
|
+
import { Button } from "laif-ds";
|
|
96
|
+
import {
|
|
97
|
+
CommandDialog,
|
|
98
|
+
CommandInput,
|
|
99
|
+
CommandList,
|
|
100
|
+
CommandEmpty,
|
|
101
|
+
CommandGroup,
|
|
102
|
+
CommandItem,
|
|
103
|
+
CommandSeparator,
|
|
104
|
+
} from "laif-ds";
|
|
105
|
+
|
|
106
|
+
export function CommandDialogExample() {
|
|
107
|
+
const [open, setOpen] = useState(false);
|
|
108
|
+
return (
|
|
109
|
+
<>
|
|
110
|
+
<Button onClick={() => setOpen(true)} variant="outline">
|
|
111
|
+
Open Command Dialog
|
|
112
|
+
</Button>
|
|
113
|
+
<CommandDialog open={open} onOpenChange={setOpen}>
|
|
114
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
115
|
+
<CommandList>
|
|
116
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
117
|
+
<CommandGroup heading="Suggestions">
|
|
118
|
+
<CommandItem>Calendar</CommandItem>
|
|
119
|
+
<CommandItem>Search</CommandItem>
|
|
120
|
+
<CommandItem>Settings</CommandItem>
|
|
121
|
+
</CommandGroup>
|
|
122
|
+
<CommandSeparator />
|
|
123
|
+
<CommandGroup heading="User">
|
|
124
|
+
<CommandItem>Profile</CommandItem>
|
|
125
|
+
<CommandItem>Billing</CommandItem>
|
|
126
|
+
<CommandItem>Logout</CommandItem>
|
|
127
|
+
</CommandGroup>
|
|
128
|
+
</CommandList>
|
|
129
|
+
</CommandDialog>
|
|
130
|
+
</>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Notes
|
|
138
|
+
|
|
139
|
+
- **Shortcuts**: Use `CommandShortcut` for right-aligned hints within `CommandItem`.
|
|
140
|
+
- **Layout**: Set explicit width on `Command` (e.g., `w-[400px]`) when used inline.
|
|
141
|
+
- **Dialog**: `CommandDialog` hides its title/description visually but preserves accessibility.
|
|
142
|
+
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Confirmer
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Promise-based confirmation dialog utility built on top of `AlertDialog`. Mount the `Confirmer` component once, then call `confirm()` to open a dialog and await the user decision.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## API
|
|
10
|
+
|
|
11
|
+
### `Confirmer` (Component)
|
|
12
|
+
|
|
13
|
+
Mount this once at app root (or Story scope) to enable dialogs.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { Confirmer } from "laif-ds";
|
|
17
|
+
|
|
18
|
+
export function AppRoot() {
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
{/* ...your app... */}
|
|
22
|
+
<Confirmer />
|
|
23
|
+
</>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `confirm(options)`
|
|
29
|
+
|
|
30
|
+
Returns a Promise that resolves when the user confirms and rejects when the user cancels.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
type ConfirmOptions = {
|
|
34
|
+
title?: React.ReactNode;
|
|
35
|
+
description?: React.ReactNode;
|
|
36
|
+
cancelText?: React.ReactNode;
|
|
37
|
+
actionText?: React.ReactNode;
|
|
38
|
+
CancelProps?: React.ComponentProps<typeof AlertDialogCancel>;
|
|
39
|
+
ActionProps?: React.ComponentProps<typeof Button>;
|
|
40
|
+
variant?: "default" | "destructive";
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
declare function confirm(options: ConfirmOptions): Promise<boolean>;
|
|
44
|
+
declare function safeConfirm(options: ConfirmOptions): Promise<boolean | undefined>;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- `variant`: when set to `"destructive"`, shows a destructive style and warning icon.
|
|
48
|
+
- `safeConfirm`: resolves `undefined` instead of throwing on cancel.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Behavior
|
|
53
|
+
|
|
54
|
+
- **Resolve/Reject**: `confirm()` resolves on action click, rejects on cancel or close.
|
|
55
|
+
- **Destructive mode**: Adds an alert icon and uses destructive button variant.
|
|
56
|
+
- **Custom buttons**: Pass `ActionProps` and `CancelProps` to customize.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
### Destructive
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { Button } from "laif-ds";
|
|
66
|
+
import { Confirmer, confirm } from "laif-ds";
|
|
67
|
+
|
|
68
|
+
export function DeleteFile() {
|
|
69
|
+
const onClick = async () => {
|
|
70
|
+
try {
|
|
71
|
+
await confirm({
|
|
72
|
+
variant: "destructive",
|
|
73
|
+
title: "Permanently delete file?",
|
|
74
|
+
description: "This action cannot be undone. The file will be removed permanently.",
|
|
75
|
+
cancelText: "Cancel",
|
|
76
|
+
actionText: "Delete",
|
|
77
|
+
});
|
|
78
|
+
console.log("File deleted");
|
|
79
|
+
} catch {
|
|
80
|
+
console.log("Deletion cancelled");
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
<Button variant="destructive" onClick={onClick}>Delete File</Button>
|
|
87
|
+
<Confirmer />
|
|
88
|
+
</>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Custom Text and Buttons
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { Button } from "laif-ds";
|
|
97
|
+
import { Confirmer, confirm } from "laif-ds";
|
|
98
|
+
|
|
99
|
+
export function PublishArticle() {
|
|
100
|
+
const onClick = async () => {
|
|
101
|
+
try {
|
|
102
|
+
await confirm({
|
|
103
|
+
title: "Publish article?",
|
|
104
|
+
description: "This will make your article visible to the public.",
|
|
105
|
+
cancelText: "Save as draft",
|
|
106
|
+
actionText: "Publish now",
|
|
107
|
+
ActionProps: {
|
|
108
|
+
variant: "default",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
console.log("Article published");
|
|
112
|
+
} catch {
|
|
113
|
+
console.log("Article saved as draft");
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
119
|
+
<Button onClick={onClick}>Publish Article</Button>
|
|
120
|
+
<Confirmer />
|
|
121
|
+
</>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Multiple Confirmers (independent flows)
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { Button } from "laif-ds";
|
|
130
|
+
import { Confirmer, confirm } from "laif-ds";
|
|
131
|
+
|
|
132
|
+
export function MultipleActions() {
|
|
133
|
+
const accept1 = async () => {
|
|
134
|
+
try {
|
|
135
|
+
await confirm({ title: "Confirm action 1", description: "This is the first confirmation dialog." });
|
|
136
|
+
console.log("Action 1 confirmed");
|
|
137
|
+
} catch {
|
|
138
|
+
console.log("Action 1 cancelled");
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const accept2 = async () => {
|
|
143
|
+
try {
|
|
144
|
+
await confirm({
|
|
145
|
+
title: "Confirm action 2",
|
|
146
|
+
description: "This is the second confirmation dialog.",
|
|
147
|
+
cancelText: "Reject",
|
|
148
|
+
actionText: "Accept",
|
|
149
|
+
});
|
|
150
|
+
console.log("Action 2 confirmed");
|
|
151
|
+
} catch {
|
|
152
|
+
console.log("Action 2 cancelled");
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<>
|
|
158
|
+
<div className="flex gap-4">
|
|
159
|
+
<Button onClick={accept1}>Action 1</Button>
|
|
160
|
+
<Button onClick={accept2}>Action 2</Button>
|
|
161
|
+
</div>
|
|
162
|
+
<Confirmer />
|
|
163
|
+
</>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Notes
|
|
171
|
+
|
|
172
|
+
- **Mount once**: Add a single `<Confirmer />` near app root.
|
|
173
|
+
- **Error handling**: Use `try/catch` with `confirm()`; or `safeConfirm()` to avoid throwing.
|
|
174
|
+
- **Theming**: `variant="destructive"` changes icon and button styling accordingly.
|
|
175
|
+
|