@mcp-b/react-components 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Button-QCM8ZKgR.d.ts +98 -0
- package/dist/CodeBlock-CttHhWcb.js +356 -0
- package/dist/CodeBlock-V6pgafSS.d.ts +174 -0
- package/dist/Select-CRsKCJ9x.d.ts +200 -0
- package/dist/class-names-9UtZwb0J.js +12 -0
- package/dist/components/Accordion.d.ts +81 -0
- package/dist/components/Accordion.js +97 -0
- package/dist/components/AgentConnection.d.ts +69 -0
- package/dist/components/AgentConnection.js +176 -0
- package/dist/components/AlertDialog.d.ts +148 -0
- package/dist/components/AlertDialog.js +141 -0
- package/dist/components/Artifact.d.ts +128 -0
- package/dist/components/Artifact.js +115 -0
- package/dist/components/Autocomplete.d.ts +186 -0
- package/dist/components/Autocomplete.js +186 -0
- package/dist/components/Avatar.d.ts +134 -0
- package/dist/components/Avatar.js +118 -0
- package/dist/components/Badge.d.ts +68 -0
- package/dist/components/Badge.js +108 -0
- package/dist/components/Button.d.ts +2 -0
- package/dist/components/Button.js +73 -0
- package/dist/components/Card.d.ts +87 -0
- package/dist/components/Card.js +81 -0
- package/dist/components/ChainOfThought.d.ts +153 -0
- package/dist/components/ChainOfThought.js +157 -0
- package/dist/components/Checkbox.d.ts +35 -0
- package/dist/components/Checkbox.js +47 -0
- package/dist/components/CheckboxGroup.d.ts +76 -0
- package/dist/components/CheckboxGroup.js +69 -0
- package/dist/components/CodeBlock.d.ts +2 -0
- package/dist/components/CodeBlock.js +2 -0
- package/dist/components/Collapsible.d.ts +127 -0
- package/dist/components/Collapsible.js +103 -0
- package/dist/components/Combobox.d.ts +177 -0
- package/dist/components/Combobox.js +179 -0
- package/dist/components/Commit.d.ts +265 -0
- package/dist/components/Commit.js +282 -0
- package/dist/components/Context.d.ts +129 -0
- package/dist/components/Context.js +309 -0
- package/dist/components/ContextMenu.d.ts +282 -0
- package/dist/components/ContextMenu.js +270 -0
- package/dist/components/Conversation.d.ts +166 -0
- package/dist/components/Conversation.js +202 -0
- package/dist/components/Dialog.d.ts +120 -0
- package/dist/components/Dialog.js +114 -0
- package/dist/components/EnvironmentVariables.d.ts +176 -0
- package/dist/components/EnvironmentVariables.js +221 -0
- package/dist/components/Field.d.ts +281 -0
- package/dist/components/Field.js +274 -0
- package/dist/components/Fieldset.d.ts +93 -0
- package/dist/components/Fieldset.js +81 -0
- package/dist/components/FileTree.d.ts +116 -0
- package/dist/components/FileTree.js +310 -0
- package/dist/components/Form.d.ts +94 -0
- package/dist/components/Form.js +88 -0
- package/dist/components/GithubMotionMark.d.ts +13 -0
- package/dist/components/GithubMotionMark.js +23 -0
- package/dist/components/Input.d.ts +33 -0
- package/dist/components/Input.js +27 -0
- package/dist/components/Label.d.ts +44 -0
- package/dist/components/Label.js +41 -0
- package/dist/components/Menu.d.ts +395 -0
- package/dist/components/Menu.js +338 -0
- package/dist/components/Menubar.d.ts +331 -0
- package/dist/components/Menubar.js +299 -0
- package/dist/components/Message.d.ts +216 -0
- package/dist/components/Message.js +245 -0
- package/dist/components/Meter.d.ts +151 -0
- package/dist/components/Meter.js +121 -0
- package/dist/components/ModelSelector.d.ts +198 -0
- package/dist/components/ModelSelector.js +306 -0
- package/dist/components/NaniteScene.d.ts +33 -0
- package/dist/components/NaniteScene.js +405 -0
- package/dist/components/NavigationMenu.d.ts +256 -0
- package/dist/components/NavigationMenu.js +228 -0
- package/dist/components/NumberField.d.ts +159 -0
- package/dist/components/NumberField.js +123 -0
- package/dist/components/Popover.d.ts +278 -0
- package/dist/components/Popover.js +245 -0
- package/dist/components/PreviewCard.d.ts +156 -0
- package/dist/components/PreviewCard.js +156 -0
- package/dist/components/PricingPage.d.ts +209 -0
- package/dist/components/PricingPage.js +506 -0
- package/dist/components/Progress.d.ts +58 -0
- package/dist/components/Progress.js +51 -0
- package/dist/components/PromptInput.d.ts +399 -0
- package/dist/components/PromptInput.js +737 -0
- package/dist/components/Queue.d.ts +241 -0
- package/dist/components/Queue.js +225 -0
- package/dist/components/RadioGroup.d.ts +78 -0
- package/dist/components/RadioGroup.js +72 -0
- package/dist/components/Reasoning.d.ts +88 -0
- package/dist/components/Reasoning.js +187 -0
- package/dist/components/ScrollArea.d.ts +160 -0
- package/dist/components/ScrollArea.js +145 -0
- package/dist/components/Select.d.ts +2 -0
- package/dist/components/Select.js +260 -0
- package/dist/components/Separator.d.ts +45 -0
- package/dist/components/Separator.js +40 -0
- package/dist/components/Shell.d.ts +163 -0
- package/dist/components/Shell.js +137 -0
- package/dist/components/Slider.d.ts +120 -0
- package/dist/components/Slider.js +115 -0
- package/dist/components/Sources.d.ts +91 -0
- package/dist/components/Sources.js +121 -0
- package/dist/components/Stepper.d.ts +190 -0
- package/dist/components/Stepper.js +315 -0
- package/dist/components/Switch.d.ts +57 -0
- package/dist/components/Switch.js +55 -0
- package/dist/components/Tabs.d.ts +84 -0
- package/dist/components/Tabs.js +78 -0
- package/dist/components/Task.d.ts +100 -0
- package/dist/components/Task.js +120 -0
- package/dist/components/Terminal.d.ts +118 -0
- package/dist/components/Terminal.js +234 -0
- package/dist/components/TestResults.d.ts +236 -0
- package/dist/components/TestResults.js +346 -0
- package/dist/components/Toast.d.ts +192 -0
- package/dist/components/Toast.js +163 -0
- package/dist/components/Toggle.d.ts +69 -0
- package/dist/components/Toggle.js +66 -0
- package/dist/components/ToggleGroup.d.ts +69 -0
- package/dist/components/ToggleGroup.js +99 -0
- package/dist/components/Tool.d.ts +119 -0
- package/dist/components/Tool.js +192 -0
- package/dist/components/Toolbar.d.ts +162 -0
- package/dist/components/Toolbar.js +126 -0
- package/dist/components/Tooltip.d.ts +81 -0
- package/dist/components/Tooltip.js +74 -0
- package/dist/components/WebPreview.d.ts +143 -0
- package/dist/components/WebPreview.js +280 -0
- package/dist/components/useStickToBottom.d.ts +30 -0
- package/dist/components/useStickToBottom.js +95 -0
- package/dist/copy-button-BIATcZWZ.d.ts +16 -0
- package/dist/copy-button-BNgclDrO.js +43 -0
- package/dist/icons-BsWc8g4E.js +221 -0
- package/dist/styles/accordion.css +10 -10
- package/dist/styles/agent-connection.css +18 -17
- package/dist/styles/alert-dialog.css +48 -29
- package/dist/styles/artifact.css +10 -10
- package/dist/styles/autocomplete.css +25 -24
- package/dist/styles/avatar.css +96 -6
- package/dist/styles/badge.css +78 -14
- package/dist/styles/base.css +9 -9
- package/dist/styles/button.css +57 -38
- package/dist/styles/card.css +57 -10
- package/dist/styles/chain-of-thought.css +47 -33
- package/dist/styles/checkbox.css +24 -10
- package/dist/styles/code-block.css +22 -15
- package/dist/styles/collapsible.css +14 -12
- package/dist/styles/combobox.css +26 -25
- package/dist/styles/commit.css +49 -24
- package/dist/styles/context-menu.css +70 -16
- package/dist/styles/context.css +15 -15
- package/dist/styles/conversation.css +12 -12
- package/dist/styles/dialog.css +52 -16
- package/dist/styles/environment-variables.css +19 -19
- package/dist/styles/field.css +184 -22
- package/dist/styles/fieldset.css +5 -4
- package/dist/styles/file-tree.css +17 -17
- package/dist/styles/index.css.d.ts +1 -0
- package/dist/styles/input.css +45 -11
- package/dist/styles/label.css +21 -4
- package/dist/styles/menu.css +55 -32
- package/dist/styles/menubar.css +80 -28
- package/dist/styles/message.css +22 -13
- package/dist/styles/meter.css +8 -8
- package/dist/styles/model-selector.css +33 -21
- package/dist/styles/navigation-menu.css +26 -24
- package/dist/styles/number-field.css +20 -18
- package/dist/styles/popover.css +38 -28
- package/dist/styles/preview-card.css +15 -13
- package/dist/styles/pricing-page.css +53 -53
- package/dist/styles/progress.css +7 -7
- package/dist/styles/prompt-input.css +73 -24
- package/dist/styles/queue.css +58 -32
- package/dist/styles/radio.css +26 -11
- package/dist/styles/reasoning.css +15 -11
- package/dist/styles/scroll-area.css +6 -6
- package/dist/styles/scrollbars.css +4 -4
- package/dist/styles/select.css +84 -25
- package/dist/styles/separator.css +1 -1
- package/dist/styles/shell.css +21 -20
- package/dist/styles/slider.css +35 -11
- package/dist/styles/sources.css +20 -20
- package/dist/styles/stepper.css +22 -22
- package/dist/styles/switch.css +29 -13
- package/dist/styles/tabs.css +23 -16
- package/dist/styles/task.css +27 -23
- package/dist/styles/terminal.css +16 -13
- package/dist/styles/test-results.css +79 -32
- package/dist/styles/toast.css +26 -25
- package/dist/styles/toggle-group.css +12 -12
- package/dist/styles/toggle.css +29 -11
- package/dist/styles/tool.css +54 -32
- package/dist/styles/toolbar.css +30 -28
- package/dist/styles/tooltip.css +10 -8
- package/dist/styles/web-preview.css +37 -21
- package/dist/utils/structured-code.d.ts +10 -0
- package/dist/utils/structured-code.js +81 -0
- package/package.json +16 -7
- package/dist/index.d.ts +0 -7236
- package/dist/index.js +0 -8945
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { c as ChevronRightIcon, o as CheckIcon, u as DotIcon } from "../icons-BsWc8g4E.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
|
|
5
|
+
//#region src/components/ContextMenu.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Root component that manages context menu state.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <ContextMenu.Root>
|
|
12
|
+
* <ContextMenu.Trigger>Right click here</ContextMenu.Trigger>
|
|
13
|
+
* <ContextMenu.Portal>
|
|
14
|
+
* <ContextMenu.Positioner>
|
|
15
|
+
* <ContextMenu.Popup>
|
|
16
|
+
* <ContextMenu.Item>Cut</ContextMenu.Item>
|
|
17
|
+
* <ContextMenu.Item>Copy</ContextMenu.Item>
|
|
18
|
+
* <ContextMenu.Item>Paste</ContextMenu.Item>
|
|
19
|
+
* </ContextMenu.Popup>
|
|
20
|
+
* </ContextMenu.Positioner>
|
|
21
|
+
* </ContextMenu.Portal>
|
|
22
|
+
* </ContextMenu.Root>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see {@link https://base-ui.com/react/components/context-menu | Base UI ContextMenu}
|
|
26
|
+
*/
|
|
27
|
+
const ContextMenuRoot = (props) => {
|
|
28
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Root, {
|
|
29
|
+
"data-slot": "context-menu",
|
|
30
|
+
...props
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Interactive area that activates the menu on right-click or long-press.
|
|
35
|
+
*/
|
|
36
|
+
function ContextMenuTrigger({ className = "", ref, ...props }) {
|
|
37
|
+
const classes = ["context-menu__trigger", className].filter(Boolean).join(" ");
|
|
38
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Trigger, {
|
|
39
|
+
ref,
|
|
40
|
+
"data-slot": "context-menu-trigger",
|
|
41
|
+
className: classes,
|
|
42
|
+
...props
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Renders menu content in a portal.
|
|
47
|
+
*/
|
|
48
|
+
const ContextMenuPortal = (props) => {
|
|
49
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Portal, {
|
|
50
|
+
"data-slot": "context-menu-portal",
|
|
51
|
+
...props
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Positions the menu at the pointer location.
|
|
56
|
+
*/
|
|
57
|
+
function ContextMenuPositioner({ className = "", ref, ...props }) {
|
|
58
|
+
const classes = ["context-menu__positioner", className].filter(Boolean).join(" ");
|
|
59
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Positioner, {
|
|
60
|
+
ref,
|
|
61
|
+
"data-slot": "context-menu-positioner",
|
|
62
|
+
className: classes,
|
|
63
|
+
...props
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Container for menu items.
|
|
68
|
+
*/
|
|
69
|
+
function ContextMenuPopup({ className = "", ref, ...props }) {
|
|
70
|
+
const classes = ["context-menu__popup", className].filter(Boolean).join(" ");
|
|
71
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Popup, {
|
|
72
|
+
ref,
|
|
73
|
+
"data-slot": "context-menu-content",
|
|
74
|
+
className: classes,
|
|
75
|
+
...props
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function ContextMenuContent({ anchor, positionMethod, side, sideOffset, align, alignOffset, collisionBoundary, collisionPadding, sticky, arrowPadding, disableAnchorTracking, collisionAvoidance, ...props }) {
|
|
79
|
+
return /* @__PURE__ */ jsx(ContextMenuPortal, { children: /* @__PURE__ */ jsx(ContextMenuPositioner, {
|
|
80
|
+
anchor,
|
|
81
|
+
positionMethod,
|
|
82
|
+
side,
|
|
83
|
+
sideOffset,
|
|
84
|
+
align,
|
|
85
|
+
alignOffset,
|
|
86
|
+
collisionBoundary,
|
|
87
|
+
collisionPadding,
|
|
88
|
+
sticky,
|
|
89
|
+
arrowPadding,
|
|
90
|
+
disableAnchorTracking,
|
|
91
|
+
collisionAvoidance,
|
|
92
|
+
children: /* @__PURE__ */ jsx(ContextMenuPopup, { ...props })
|
|
93
|
+
}) });
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Interactive menu item.
|
|
97
|
+
*/
|
|
98
|
+
function ContextMenuItem({ className = "", inset, variant = "default", ref, ...props }) {
|
|
99
|
+
const classes = [
|
|
100
|
+
"context-menu__item",
|
|
101
|
+
inset && "context-menu__item--inset",
|
|
102
|
+
className
|
|
103
|
+
].filter(Boolean).join(" ");
|
|
104
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Item, {
|
|
105
|
+
ref,
|
|
106
|
+
"data-slot": "context-menu-item",
|
|
107
|
+
"data-inset": inset || void 0,
|
|
108
|
+
"data-variant": variant,
|
|
109
|
+
className: classes,
|
|
110
|
+
...props
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Visual separator between menu sections.
|
|
115
|
+
*/
|
|
116
|
+
function ContextMenuSeparator({ className = "", ref, ...props }) {
|
|
117
|
+
const classes = ["context-menu__separator", className].filter(Boolean).join(" ");
|
|
118
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Separator, {
|
|
119
|
+
ref,
|
|
120
|
+
"data-slot": "context-menu-separator",
|
|
121
|
+
className: classes,
|
|
122
|
+
...props
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function ContextMenuGroup({ className = "", ref, ...props }) {
|
|
126
|
+
const classes = ["context-menu__group", className].filter(Boolean).join(" ");
|
|
127
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.Group, {
|
|
128
|
+
ref,
|
|
129
|
+
"data-slot": "context-menu-group",
|
|
130
|
+
className: classes,
|
|
131
|
+
...props
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function ContextMenuLabel({ className = "", inset, ref, ...props }) {
|
|
135
|
+
const classes = [
|
|
136
|
+
"context-menu__label",
|
|
137
|
+
inset && "context-menu__label--inset",
|
|
138
|
+
className
|
|
139
|
+
].filter(Boolean).join(" ");
|
|
140
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.GroupLabel, {
|
|
141
|
+
ref,
|
|
142
|
+
"data-slot": "context-menu-label",
|
|
143
|
+
"data-inset": inset || void 0,
|
|
144
|
+
className: classes,
|
|
145
|
+
...props
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function ContextMenuCheckboxItem({ className = "", children, ref, ...props }) {
|
|
149
|
+
const classes = ["context-menu__checkbox-item", className].filter(Boolean).join(" ");
|
|
150
|
+
return /* @__PURE__ */ jsxs(ContextMenu$1.CheckboxItem, {
|
|
151
|
+
ref,
|
|
152
|
+
"data-slot": "context-menu-checkbox-item",
|
|
153
|
+
className: classes,
|
|
154
|
+
...props,
|
|
155
|
+
children: [/* @__PURE__ */ jsx(ContextMenu$1.CheckboxItemIndicator, {
|
|
156
|
+
className: "context-menu__indicator",
|
|
157
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
158
|
+
}), children]
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function ContextMenuRadioGroup({ className = "", ref, ...props }) {
|
|
162
|
+
const classes = ["context-menu__radio-group", className].filter(Boolean).join(" ");
|
|
163
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.RadioGroup, {
|
|
164
|
+
ref,
|
|
165
|
+
"data-slot": "context-menu-radio-group",
|
|
166
|
+
className: classes,
|
|
167
|
+
...props
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function ContextMenuRadioItem({ className = "", children, ref, ...props }) {
|
|
171
|
+
const classes = ["context-menu__radio-item", className].filter(Boolean).join(" ");
|
|
172
|
+
return /* @__PURE__ */ jsxs(ContextMenu$1.RadioItem, {
|
|
173
|
+
ref,
|
|
174
|
+
"data-slot": "context-menu-radio-item",
|
|
175
|
+
className: classes,
|
|
176
|
+
...props,
|
|
177
|
+
children: [/* @__PURE__ */ jsx(ContextMenu$1.RadioItemIndicator, {
|
|
178
|
+
className: "context-menu__indicator",
|
|
179
|
+
children: /* @__PURE__ */ jsx(DotIcon, { size: 8 })
|
|
180
|
+
}), children]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function ContextMenuShortcut({ className = "", ref, ...props }) {
|
|
184
|
+
return /* @__PURE__ */ jsx("span", {
|
|
185
|
+
ref,
|
|
186
|
+
"data-slot": "context-menu-shortcut",
|
|
187
|
+
className: ["context-menu__shortcut", className].filter(Boolean).join(" "),
|
|
188
|
+
...props
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
function ContextMenuSub(props) {
|
|
192
|
+
return /* @__PURE__ */ jsx(ContextMenu$1.SubmenuRoot, {
|
|
193
|
+
"data-slot": "context-menu-sub",
|
|
194
|
+
...props
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function ContextMenuSubContent({ side = "right", align = "start", sideOffset = 4, ...props }) {
|
|
198
|
+
return /* @__PURE__ */ jsx(ContextMenuContent, {
|
|
199
|
+
"data-slot": "context-menu-sub-content",
|
|
200
|
+
side,
|
|
201
|
+
align,
|
|
202
|
+
sideOffset,
|
|
203
|
+
...props
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function ContextMenuSubTrigger({ className = "", inset, children, ref, ...props }) {
|
|
207
|
+
const classes = [
|
|
208
|
+
"context-menu__submenu-trigger",
|
|
209
|
+
inset && "context-menu__item--inset",
|
|
210
|
+
className
|
|
211
|
+
].filter(Boolean).join(" ");
|
|
212
|
+
return /* @__PURE__ */ jsxs(ContextMenu$1.SubmenuTrigger, {
|
|
213
|
+
ref,
|
|
214
|
+
"data-slot": "context-menu-sub-trigger",
|
|
215
|
+
"data-inset": inset || void 0,
|
|
216
|
+
className: classes,
|
|
217
|
+
...props,
|
|
218
|
+
children: [children, /* @__PURE__ */ jsx(ChevronRightIcon, { className: "context-menu__submenu-icon" })]
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* A context menu that appears at the pointer on right-click or long-press.
|
|
223
|
+
* Provides keyboard navigation and supports nested submenus.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```tsx
|
|
227
|
+
* // Basic context menu
|
|
228
|
+
* <ContextMenu.Root>
|
|
229
|
+
* <ContextMenu.Trigger>
|
|
230
|
+
* <div style={{ padding: '2rem', border: '1px dashed gray' }}>
|
|
231
|
+
* Right-click here
|
|
232
|
+
* </div>
|
|
233
|
+
* </ContextMenu.Trigger>
|
|
234
|
+
* <ContextMenu.Portal>
|
|
235
|
+
* <ContextMenu.Positioner>
|
|
236
|
+
* <ContextMenu.Popup>
|
|
237
|
+
* <ContextMenu.Item onClick={() => console.log('Cut')}>Cut</ContextMenu.Item>
|
|
238
|
+
* <ContextMenu.Item onClick={() => console.log('Copy')}>Copy</ContextMenu.Item>
|
|
239
|
+
* <ContextMenu.Item onClick={() => console.log('Paste')}>Paste</ContextMenu.Item>
|
|
240
|
+
* <ContextMenu.Separator />
|
|
241
|
+
* <ContextMenu.Item onClick={() => console.log('Delete')}>Delete</ContextMenu.Item>
|
|
242
|
+
* </ContextMenu.Popup>
|
|
243
|
+
* </ContextMenu.Positioner>
|
|
244
|
+
* </ContextMenu.Portal>
|
|
245
|
+
* </ContextMenu.Root>
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @see {@link https://base-ui.com/react/components/context-menu | Base UI ContextMenu}
|
|
249
|
+
*/
|
|
250
|
+
const ContextMenu = Object.assign(ContextMenuRoot, {
|
|
251
|
+
Root: ContextMenuRoot,
|
|
252
|
+
Trigger: ContextMenuTrigger,
|
|
253
|
+
Portal: ContextMenuPortal,
|
|
254
|
+
Positioner: ContextMenuPositioner,
|
|
255
|
+
Popup: ContextMenuPopup,
|
|
256
|
+
Content: ContextMenuContent,
|
|
257
|
+
Item: ContextMenuItem,
|
|
258
|
+
Separator: ContextMenuSeparator,
|
|
259
|
+
Group: ContextMenuGroup,
|
|
260
|
+
Label: ContextMenuLabel,
|
|
261
|
+
CheckboxItem: ContextMenuCheckboxItem,
|
|
262
|
+
RadioGroup: ContextMenuRadioGroup,
|
|
263
|
+
RadioItem: ContextMenuRadioItem,
|
|
264
|
+
Shortcut: ContextMenuShortcut,
|
|
265
|
+
Sub: ContextMenuSub,
|
|
266
|
+
SubContent: ContextMenuSubContent,
|
|
267
|
+
SubTrigger: ContextMenuSubTrigger
|
|
268
|
+
});
|
|
269
|
+
//#endregion
|
|
270
|
+
export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPopup, ContextMenuPortal, ContextMenuPositioner, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuRoot, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger };
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { t as Button } from "../Button-QCM8ZKgR.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/Conversation.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Minimum message shape accepted by {@link ConversationDownload} and
|
|
7
|
+
* {@link messagesToMarkdown}. Structurally compatible with the AI SDK
|
|
8
|
+
* `UIMessage` type so consumers can pass those directly.
|
|
9
|
+
*/
|
|
10
|
+
interface ConversationMessage {
|
|
11
|
+
id?: string;
|
|
12
|
+
role: string;
|
|
13
|
+
/** AI SDK-style parts array. The text types are concatenated for export. */
|
|
14
|
+
parts?: Array<{
|
|
15
|
+
type: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
}>;
|
|
18
|
+
/** Plain-text content; used as a fallback when `parts` is not provided. */
|
|
19
|
+
content?: string;
|
|
20
|
+
}
|
|
21
|
+
interface ConversationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
22
|
+
/** Additional class names for layout only; do not override scroll behavior from apps. */
|
|
23
|
+
className?: string;
|
|
24
|
+
/** ConversationContent, messages, empty state, scroll button, or download button. */
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Scrollable container for a chat conversation. Sticks the viewport to the
|
|
29
|
+
* bottom as new content arrives, unless the user has scrolled up. Adapted
|
|
30
|
+
* from Vercel AI Elements and restyled with Sigvelo CSS tokens.
|
|
31
|
+
*
|
|
32
|
+
* Use for assistant/user message streams. Do not use for static lists or
|
|
33
|
+
* logs that should not auto-stick to the latest item.
|
|
34
|
+
*
|
|
35
|
+
* Sigvelo changes: removed Tailwind classes, uses a native scroll region with
|
|
36
|
+
* the local stick-to-bottom hook, emits `role="log"` with polite updates, and
|
|
37
|
+
* keeps transcript export in a separate ConversationDownload action.
|
|
38
|
+
*
|
|
39
|
+
* Styling consumes Sigvelo canvas, surface, border, spacing, radius, shadow,
|
|
40
|
+
* and motion tokens. Add new behavior in this package when multiple apps need
|
|
41
|
+
* it; app code should compose children and avoid reaching into scroll internals.
|
|
42
|
+
*
|
|
43
|
+
* Pair with {@link ConversationContent} for layout, {@link ConversationScrollButton}
|
|
44
|
+
* for a "jump to latest" affordance, and {@link ConversationDownload} to export
|
|
45
|
+
* the transcript as Markdown.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <Conversation>
|
|
50
|
+
* <ConversationContent>
|
|
51
|
+
* {messages.map((m) => <Message key={m.id} {...m} />)}
|
|
52
|
+
* </ConversationContent>
|
|
53
|
+
* <ConversationScrollButton />
|
|
54
|
+
* </Conversation>
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @see {@link https://elements.ai-sdk.dev/components/conversation | AI Elements Conversation}
|
|
58
|
+
*/
|
|
59
|
+
declare function Conversation({
|
|
60
|
+
className,
|
|
61
|
+
children,
|
|
62
|
+
ref,
|
|
63
|
+
...props
|
|
64
|
+
}: ConversationProps & {
|
|
65
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
66
|
+
}): React.JSX.Element;
|
|
67
|
+
interface ConversationContentProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
68
|
+
/**
|
|
69
|
+
* Inner layout wrapper for conversation children. Applies vertical stacking
|
|
70
|
+
* and padding; does not scroll (the parent {@link Conversation} does).
|
|
71
|
+
*/
|
|
72
|
+
declare function ConversationContent({
|
|
73
|
+
className,
|
|
74
|
+
children,
|
|
75
|
+
ref,
|
|
76
|
+
...props
|
|
77
|
+
}: ConversationContentProps & {
|
|
78
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
79
|
+
}): React.JSX.Element;
|
|
80
|
+
interface ConversationEmptyStateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
81
|
+
title?: React.ReactNode;
|
|
82
|
+
description?: React.ReactNode;
|
|
83
|
+
icon?: React.ReactNode;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Placeholder shown when there are no messages yet. Renders an icon, title,
|
|
87
|
+
* and description stacked vertically; pass `children` to override the
|
|
88
|
+
* default layout entirely.
|
|
89
|
+
*/
|
|
90
|
+
declare function ConversationEmptyState({
|
|
91
|
+
className,
|
|
92
|
+
title,
|
|
93
|
+
description,
|
|
94
|
+
icon,
|
|
95
|
+
children,
|
|
96
|
+
ref,
|
|
97
|
+
...props
|
|
98
|
+
}: ConversationEmptyStateProps & {
|
|
99
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
100
|
+
}): React.JSX.Element;
|
|
101
|
+
interface ConversationScrollButtonProps extends Omit<React.ComponentProps<typeof Button>, "onClick" | "className"> {
|
|
102
|
+
className?: string;
|
|
103
|
+
/** Optional click handler; runs before the default scroll-to-bottom action. */
|
|
104
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
105
|
+
/** Accessible label for the button. */
|
|
106
|
+
label?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Floating button that scrolls the conversation to the latest message.
|
|
110
|
+
* Hidden while the viewport is already pinned to the bottom.
|
|
111
|
+
*/
|
|
112
|
+
declare function ConversationScrollButton({
|
|
113
|
+
className,
|
|
114
|
+
variant,
|
|
115
|
+
color,
|
|
116
|
+
size,
|
|
117
|
+
onClick,
|
|
118
|
+
label,
|
|
119
|
+
children,
|
|
120
|
+
ref,
|
|
121
|
+
...props
|
|
122
|
+
}: ConversationScrollButtonProps & {
|
|
123
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
124
|
+
}): React.JSX.Element | null;
|
|
125
|
+
/**
|
|
126
|
+
* Converts a conversation to a Markdown document with a heading per message.
|
|
127
|
+
*
|
|
128
|
+
* @param messages - Array of messages to serialize.
|
|
129
|
+
* @param formatMessage - Optional per-message formatter; defaults to
|
|
130
|
+
* `### Role\n\n<text>` blocks joined by blank lines.
|
|
131
|
+
*/
|
|
132
|
+
declare function messagesToMarkdown(messages: ConversationMessage[], formatMessage?: (message: ConversationMessage, index: number) => string): string;
|
|
133
|
+
interface ConversationDownloadProps extends Omit<React.ComponentProps<typeof Button>, "onClick" | "children" | "className"> {
|
|
134
|
+
className?: string;
|
|
135
|
+
messages: ConversationMessage[];
|
|
136
|
+
/** Filename for the downloaded Markdown file. */
|
|
137
|
+
filename?: string;
|
|
138
|
+
/** Customize the text for each message in the exported Markdown. */
|
|
139
|
+
formatMessage?: (message: ConversationMessage, index: number) => string;
|
|
140
|
+
/** Accessible label for the button. */
|
|
141
|
+
label?: string;
|
|
142
|
+
children?: React.ReactNode;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Button that exports the current conversation as a Markdown file.
|
|
146
|
+
*
|
|
147
|
+
* Skipped when `messages` is empty. For custom export flows, use
|
|
148
|
+
* {@link messagesToMarkdown} directly.
|
|
149
|
+
*/
|
|
150
|
+
declare function ConversationDownload({
|
|
151
|
+
className,
|
|
152
|
+
messages,
|
|
153
|
+
filename,
|
|
154
|
+
formatMessage,
|
|
155
|
+
label,
|
|
156
|
+
variant,
|
|
157
|
+
color,
|
|
158
|
+
size,
|
|
159
|
+
children,
|
|
160
|
+
ref,
|
|
161
|
+
...props
|
|
162
|
+
}: ConversationDownloadProps & {
|
|
163
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
164
|
+
}): React.JSX.Element | null;
|
|
165
|
+
//#endregion
|
|
166
|
+
export { Conversation, ConversationContent, ConversationContentProps, ConversationDownload, ConversationDownloadProps, ConversationEmptyState, ConversationEmptyStateProps, ConversationMessage, ConversationProps, ConversationScrollButton, ConversationScrollButtonProps, messagesToMarkdown };
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { d as DownloadIcon, t as ArrowDownIcon } from "../icons-BsWc8g4E.js";
|
|
2
|
+
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
3
|
+
import { Button } from "./Button.js";
|
|
4
|
+
import { useStickToBottom } from "./useStickToBottom.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Conversation.tsx
|
|
8
|
+
const ConversationContext = React.createContext(null);
|
|
9
|
+
function useConversationContext(component) {
|
|
10
|
+
const ctx = React.useContext(ConversationContext);
|
|
11
|
+
if (!ctx) throw new Error(`${component} must be used inside a <Conversation>.`);
|
|
12
|
+
return ctx;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Scrollable container for a chat conversation. Sticks the viewport to the
|
|
16
|
+
* bottom as new content arrives, unless the user has scrolled up. Adapted
|
|
17
|
+
* from Vercel AI Elements and restyled with Sigvelo CSS tokens.
|
|
18
|
+
*
|
|
19
|
+
* Use for assistant/user message streams. Do not use for static lists or
|
|
20
|
+
* logs that should not auto-stick to the latest item.
|
|
21
|
+
*
|
|
22
|
+
* Sigvelo changes: removed Tailwind classes, uses a native scroll region with
|
|
23
|
+
* the local stick-to-bottom hook, emits `role="log"` with polite updates, and
|
|
24
|
+
* keeps transcript export in a separate ConversationDownload action.
|
|
25
|
+
*
|
|
26
|
+
* Styling consumes Sigvelo canvas, surface, border, spacing, radius, shadow,
|
|
27
|
+
* and motion tokens. Add new behavior in this package when multiple apps need
|
|
28
|
+
* it; app code should compose children and avoid reaching into scroll internals.
|
|
29
|
+
*
|
|
30
|
+
* Pair with {@link ConversationContent} for layout, {@link ConversationScrollButton}
|
|
31
|
+
* for a "jump to latest" affordance, and {@link ConversationDownload} to export
|
|
32
|
+
* the transcript as Markdown.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <Conversation>
|
|
37
|
+
* <ConversationContent>
|
|
38
|
+
* {messages.map((m) => <Message key={m.id} {...m} />)}
|
|
39
|
+
* </ConversationContent>
|
|
40
|
+
* <ConversationScrollButton />
|
|
41
|
+
* </Conversation>
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @see {@link https://elements.ai-sdk.dev/components/conversation | AI Elements Conversation}
|
|
45
|
+
*/
|
|
46
|
+
function Conversation({ className, children, ref, ...props }) {
|
|
47
|
+
const { viewportRef, contentRef, isAtBottom, scrollToBottom } = useStickToBottom();
|
|
48
|
+
const handleViewportRef = React.useCallback((element) => {
|
|
49
|
+
viewportRef(element);
|
|
50
|
+
if (typeof ref === "function") {
|
|
51
|
+
ref(element);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (ref) ref.current = element;
|
|
55
|
+
}, [ref, viewportRef]);
|
|
56
|
+
const ctx = React.useMemo(() => ({
|
|
57
|
+
isAtBottom,
|
|
58
|
+
scrollToBottom,
|
|
59
|
+
registerContentElement: contentRef
|
|
60
|
+
}), [
|
|
61
|
+
contentRef,
|
|
62
|
+
isAtBottom,
|
|
63
|
+
scrollToBottom
|
|
64
|
+
]);
|
|
65
|
+
return /* @__PURE__ */ jsx(ConversationContext.Provider, {
|
|
66
|
+
value: ctx,
|
|
67
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
68
|
+
ref: handleViewportRef,
|
|
69
|
+
role: "log",
|
|
70
|
+
"aria-live": "polite",
|
|
71
|
+
"aria-relevant": "additions text",
|
|
72
|
+
tabIndex: 0,
|
|
73
|
+
className: cx("conversation", className),
|
|
74
|
+
...props,
|
|
75
|
+
children
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Inner layout wrapper for conversation children. Applies vertical stacking
|
|
81
|
+
* and padding; does not scroll (the parent {@link Conversation} does).
|
|
82
|
+
*/
|
|
83
|
+
function ConversationContent({ className, children, ref, ...props }) {
|
|
84
|
+
const { registerContentElement } = useConversationContext("ConversationContent");
|
|
85
|
+
return /* @__PURE__ */ jsx("div", {
|
|
86
|
+
ref: React.useCallback((element) => {
|
|
87
|
+
registerContentElement(element);
|
|
88
|
+
if (typeof ref === "function") {
|
|
89
|
+
ref(element);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (ref) ref.current = element;
|
|
93
|
+
}, [registerContentElement, ref]),
|
|
94
|
+
className: cx("conversation__content", className),
|
|
95
|
+
...props,
|
|
96
|
+
children
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Placeholder shown when there are no messages yet. Renders an icon, title,
|
|
101
|
+
* and description stacked vertically; pass `children` to override the
|
|
102
|
+
* default layout entirely.
|
|
103
|
+
*/
|
|
104
|
+
function ConversationEmptyState({ className, title = "No messages yet", description = "Start a conversation to see messages here", icon, children, ref, ...props }) {
|
|
105
|
+
return /* @__PURE__ */ jsx("div", {
|
|
106
|
+
ref,
|
|
107
|
+
className: cx("conversation__empty", className),
|
|
108
|
+
...props,
|
|
109
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
110
|
+
icon ? /* @__PURE__ */ jsx("span", {
|
|
111
|
+
className: "conversation__empty-icon",
|
|
112
|
+
"aria-hidden": "true",
|
|
113
|
+
children: icon
|
|
114
|
+
}) : null,
|
|
115
|
+
title ? /* @__PURE__ */ jsx("div", {
|
|
116
|
+
className: "conversation__empty-title",
|
|
117
|
+
children: title
|
|
118
|
+
}) : null,
|
|
119
|
+
description ? /* @__PURE__ */ jsx("div", {
|
|
120
|
+
className: "conversation__empty-description",
|
|
121
|
+
children: description
|
|
122
|
+
}) : null
|
|
123
|
+
] })
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Floating button that scrolls the conversation to the latest message.
|
|
128
|
+
* Hidden while the viewport is already pinned to the bottom.
|
|
129
|
+
*/
|
|
130
|
+
function ConversationScrollButton({ className, variant = "outline", color = "neutral", size = "icon", onClick, label = "Scroll to latest", children, ref, ...props }) {
|
|
131
|
+
const { isAtBottom, scrollToBottom } = useConversationContext("ConversationScrollButton");
|
|
132
|
+
if (isAtBottom) return null;
|
|
133
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
134
|
+
ref,
|
|
135
|
+
type: "button",
|
|
136
|
+
variant,
|
|
137
|
+
color,
|
|
138
|
+
size,
|
|
139
|
+
className: cx("conversation__scroll-button", className),
|
|
140
|
+
"aria-label": label,
|
|
141
|
+
onClick: (event) => {
|
|
142
|
+
onClick?.(event);
|
|
143
|
+
if (!event.defaultPrevented) scrollToBottom();
|
|
144
|
+
},
|
|
145
|
+
...props,
|
|
146
|
+
children: children ?? /* @__PURE__ */ jsx(ArrowDownIcon, {})
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const ROLE_HEADING = {
|
|
150
|
+
user: "### User",
|
|
151
|
+
assistant: "### Assistant",
|
|
152
|
+
system: "### System",
|
|
153
|
+
tool: "### Tool"
|
|
154
|
+
};
|
|
155
|
+
function defaultFormatMessage(message) {
|
|
156
|
+
return `${ROLE_HEADING[message.role] ?? `### ${message.role}`}\n\n${(message.parts ? message.parts.filter((part) => part.type === "text" || part.type === "reasoning").map((part) => part.text ?? "").join("") : message.content ?? "").trim()}`;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Converts a conversation to a Markdown document with a heading per message.
|
|
160
|
+
*
|
|
161
|
+
* @param messages - Array of messages to serialize.
|
|
162
|
+
* @param formatMessage - Optional per-message formatter; defaults to
|
|
163
|
+
* `### Role\n\n<text>` blocks joined by blank lines.
|
|
164
|
+
*/
|
|
165
|
+
function messagesToMarkdown(messages, formatMessage = defaultFormatMessage) {
|
|
166
|
+
return messages.map((message, index) => formatMessage(message, index)).join("\n\n");
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Button that exports the current conversation as a Markdown file.
|
|
170
|
+
*
|
|
171
|
+
* Skipped when `messages` is empty. For custom export flows, use
|
|
172
|
+
* {@link messagesToMarkdown} directly.
|
|
173
|
+
*/
|
|
174
|
+
function ConversationDownload({ className, messages, filename = "conversation.md", formatMessage, label = "Download conversation", variant = "outline", color = "neutral", size = "icon", children, ref, ...props }) {
|
|
175
|
+
if (messages.length === 0) return null;
|
|
176
|
+
const handleClick = () => {
|
|
177
|
+
const markdown = messagesToMarkdown(messages, formatMessage);
|
|
178
|
+
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8" });
|
|
179
|
+
const url = URL.createObjectURL(blob);
|
|
180
|
+
const anchor = document.createElement("a");
|
|
181
|
+
anchor.href = url;
|
|
182
|
+
anchor.download = filename;
|
|
183
|
+
document.body.appendChild(anchor);
|
|
184
|
+
anchor.click();
|
|
185
|
+
anchor.remove();
|
|
186
|
+
URL.revokeObjectURL(url);
|
|
187
|
+
};
|
|
188
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
189
|
+
ref,
|
|
190
|
+
type: "button",
|
|
191
|
+
variant,
|
|
192
|
+
color,
|
|
193
|
+
size,
|
|
194
|
+
className: cx("conversation__download-button", className),
|
|
195
|
+
"aria-label": label,
|
|
196
|
+
onClick: handleClick,
|
|
197
|
+
...props,
|
|
198
|
+
children: children ?? /* @__PURE__ */ jsx(DownloadIcon, {})
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { Conversation, ConversationContent, ConversationDownload, ConversationEmptyState, ConversationScrollButton, messagesToMarkdown };
|