@uipath/apollo-wind 2.69.0 → 2.70.0

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.
Files changed (53) hide show
  1. package/dist/components/custom/chat-first-experience.cjs +3 -3
  2. package/dist/components/custom/chat-first-experience.js +3 -3
  3. package/dist/components/custom/demo-composer.cjs +80 -0
  4. package/dist/components/custom/demo-composer.d.ts +11 -0
  5. package/dist/components/custom/demo-composer.js +46 -0
  6. package/dist/components/custom/panel-flow.cjs +2 -2
  7. package/dist/components/custom/panel-flow.js +2 -2
  8. package/dist/components/ui/chat-composer.cjs +429 -0
  9. package/dist/components/ui/chat-composer.d.ts +157 -0
  10. package/dist/components/ui/chat-composer.js +359 -0
  11. package/dist/components/ui/citation.cjs +188 -0
  12. package/dist/components/ui/citation.d.ts +42 -0
  13. package/dist/components/ui/citation.js +148 -0
  14. package/dist/components/ui/dropzone-overlay.cjs +142 -0
  15. package/dist/components/ui/dropzone-overlay.d.ts +27 -0
  16. package/dist/components/ui/dropzone-overlay.js +105 -0
  17. package/dist/components/ui/file-upload.cjs +5 -29
  18. package/dist/components/ui/file-upload.js +2 -26
  19. package/dist/components/ui/file-validation.cjs +91 -0
  20. package/dist/components/ui/file-validation.d.ts +24 -0
  21. package/dist/components/ui/file-validation.js +51 -0
  22. package/dist/components/ui/hover-card.cjs +15 -8
  23. package/dist/components/ui/hover-card.d.ts +4 -1
  24. package/dist/components/ui/hover-card.js +16 -9
  25. package/dist/components/ui/index.cjs +280 -214
  26. package/dist/components/ui/index.d.ts +6 -0
  27. package/dist/components/ui/index.js +6 -0
  28. package/dist/components/ui/input-group.cjs +1 -1
  29. package/dist/components/ui/input-group.d.ts +2 -1
  30. package/dist/components/ui/input-group.js +1 -1
  31. package/dist/components/ui/message-actions.cjs +302 -0
  32. package/dist/components/ui/message-actions.d.ts +102 -0
  33. package/dist/components/ui/message-actions.js +241 -0
  34. package/dist/components/ui/message.cjs +1 -1
  35. package/dist/components/ui/message.d.ts +2 -0
  36. package/dist/components/ui/message.js +1 -1
  37. package/dist/components/ui/sources.cjs +175 -0
  38. package/dist/components/ui/sources.d.ts +44 -0
  39. package/dist/components/ui/sources.js +132 -0
  40. package/dist/index.cjs +117 -6
  41. package/dist/index.d.ts +12 -0
  42. package/dist/index.js +7 -1
  43. package/dist/lib/index.cjs +8 -1
  44. package/dist/lib/index.d.ts +1 -0
  45. package/dist/lib/index.js +2 -1
  46. package/dist/lib/url.cjs +54 -0
  47. package/dist/lib/url.d.ts +8 -0
  48. package/dist/lib/url.js +17 -0
  49. package/dist/styles.css +157 -35
  50. package/package.json +1 -1
  51. package/dist/components/custom/chat-composer.cjs +0 -134
  52. package/dist/components/custom/chat-composer.d.ts +0 -14
  53. package/dist/components/custom/chat-composer.js +0 -100
@@ -0,0 +1,241 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { cva } from "class-variance-authority";
4
+ import { Check, Copy, Ellipsis, ThumbsDown, ThumbsUp } from "lucide-react";
5
+ import { forwardRef, useEffect, useRef, useState } from "react";
6
+ import { cn } from "../../lib/index.js";
7
+ import { copyTextToClipboard } from "../../lib/clipboard.js";
8
+ import { Button } from "./button.js";
9
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./dropdown-menu.js";
10
+ import { Toggle } from "./toggle.js";
11
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip.js";
12
+ const DEFAULT_MESSAGE_ACTIONS_OVERFLOW_STRINGS = {
13
+ more: 'More actions'
14
+ };
15
+ const DEFAULT_MESSAGE_ACTIONS_STRINGS = {
16
+ ...DEFAULT_MESSAGE_ACTIONS_OVERFLOW_STRINGS,
17
+ label: 'Message actions'
18
+ };
19
+ const messageActionsVariants = cva('flex w-fit max-w-full items-center gap-0.5 px-2', {
20
+ variants: {
21
+ visibility: {
22
+ always: '',
23
+ hover: 'opacity-0 transition-opacity group-hover/message:opacity-100 group-focus-within/message:opacity-100 focus-within:opacity-100 has-[[data-state=open]]:opacity-100 has-[[data-state=delayed-open]]:opacity-100 has-[[data-state=instant-open]]:opacity-100 [@media(hover:none)]:opacity-100'
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ visibility: 'always'
28
+ }
29
+ });
30
+ const MessageActions = /*#__PURE__*/ forwardRef(({ className, visibility = 'always', actions = [], maxVisible, strings, 'aria-label': ariaLabel, children, ...props }, ref)=>{
31
+ const text = {
32
+ ...DEFAULT_MESSAGE_ACTIONS_STRINGS,
33
+ ...strings
34
+ };
35
+ const limit = void 0 === maxVisible ? actions.length : Math.max(0, maxVisible);
36
+ const visible = actions.slice(0, limit);
37
+ const overflow = actions.slice(limit);
38
+ return /*#__PURE__*/ jsx(TooltipProvider, {
39
+ delayDuration: 300,
40
+ skipDelayDuration: 150,
41
+ children: /*#__PURE__*/ jsxs("div", {
42
+ ref: ref,
43
+ role: "group",
44
+ "aria-label": ariaLabel ?? text.label,
45
+ "data-slot": "message-actions",
46
+ "data-visibility": visibility,
47
+ className: cn(messageActionsVariants({
48
+ visibility
49
+ }), className),
50
+ ...props,
51
+ children: [
52
+ children,
53
+ visible.map((action)=>/*#__PURE__*/ jsx(MessageAction, {
54
+ label: action.label,
55
+ disabled: action.disabled,
56
+ onClick: action.onSelect,
57
+ children: action.icon
58
+ }, action.id)),
59
+ overflow.length > 0 && /*#__PURE__*/ jsx(MessageActionsOverflow, {
60
+ items: overflow,
61
+ strings: {
62
+ more: text.more
63
+ }
64
+ })
65
+ ]
66
+ })
67
+ });
68
+ });
69
+ MessageActions.displayName = 'MessageActions';
70
+ const MessageAction = /*#__PURE__*/ forwardRef(({ label, tooltipSide = 'bottom', variant = 'ghost', size = '3xs', icon = true, ...props }, ref)=>/*#__PURE__*/ jsxs(Tooltip, {
71
+ children: [
72
+ /*#__PURE__*/ jsx(TooltipTrigger, {
73
+ asChild: true,
74
+ children: /*#__PURE__*/ jsx(Button, {
75
+ ref: ref,
76
+ "data-slot": "message-action",
77
+ "aria-label": label,
78
+ variant: variant,
79
+ size: size,
80
+ icon: icon,
81
+ ...props
82
+ })
83
+ }),
84
+ /*#__PURE__*/ jsx(TooltipContent, {
85
+ side: tooltipSide,
86
+ children: label
87
+ })
88
+ ]
89
+ }));
90
+ MessageAction.displayName = 'MessageAction';
91
+ const DEFAULT_MESSAGE_ACTION_COPY_STRINGS = {
92
+ copy: 'Copy',
93
+ copied: 'Copied'
94
+ };
95
+ const COPIED_RESET_MS = 1500;
96
+ const MessageActionCopy = /*#__PURE__*/ forwardRef(({ text: copyText, onCopy, strings, onClick, ...props }, ref)=>{
97
+ const text = {
98
+ ...DEFAULT_MESSAGE_ACTION_COPY_STRINGS,
99
+ ...strings
100
+ };
101
+ const [copied, setCopied] = useState(false);
102
+ const timer = useRef(void 0);
103
+ useEffect(()=>()=>clearTimeout(timer.current), []);
104
+ const handleClick = async (event)=>{
105
+ onClick?.(event);
106
+ if (event.defaultPrevented) return;
107
+ if (!await copyTextToClipboard(copyText)) return;
108
+ onCopy?.(copyText);
109
+ setCopied(true);
110
+ clearTimeout(timer.current);
111
+ timer.current = setTimeout(()=>setCopied(false), COPIED_RESET_MS);
112
+ };
113
+ return /*#__PURE__*/ jsxs(Fragment, {
114
+ children: [
115
+ /*#__PURE__*/ jsx(MessageAction, {
116
+ ref: ref,
117
+ "data-copied": copied || void 0,
118
+ label: copied ? text.copied : text.copy,
119
+ onClick: handleClick,
120
+ ...props,
121
+ children: copied ? /*#__PURE__*/ jsx(Check, {}) : /*#__PURE__*/ jsx(Copy, {})
122
+ }),
123
+ /*#__PURE__*/ jsx("output", {
124
+ "aria-live": "polite",
125
+ className: "sr-only",
126
+ children: copied ? text.copied : ''
127
+ })
128
+ ]
129
+ });
130
+ });
131
+ MessageActionCopy.displayName = 'MessageActionCopy';
132
+ const DEFAULT_MESSAGE_ACTION_FEEDBACK_STRINGS = {
133
+ label: 'Rate this response',
134
+ helpful: 'Helpful',
135
+ notHelpful: 'Not helpful'
136
+ };
137
+ const feedbackToggleClass = 'size-6 min-w-6 px-0 aria-pressed:bg-accent aria-pressed:text-accent-foreground future:aria-pressed:text-foreground';
138
+ const MessageActionFeedback = /*#__PURE__*/ forwardRef(({ value: valueProp, defaultValue = null, onChange, disabled, strings, className, 'aria-label': ariaLabel, ...props }, ref)=>{
139
+ const text = {
140
+ ...DEFAULT_MESSAGE_ACTION_FEEDBACK_STRINGS,
141
+ ...strings
142
+ };
143
+ const [uncontrolled, setUncontrolled] = useState(defaultValue);
144
+ const value = void 0 === valueProp ? uncontrolled : valueProp;
145
+ const set = (next)=>{
146
+ if (next === value) return;
147
+ if (void 0 === valueProp) setUncontrolled(next);
148
+ onChange?.(next);
149
+ };
150
+ const thumbs = [
151
+ {
152
+ rating: 'up',
153
+ label: text.helpful,
154
+ icon: /*#__PURE__*/ jsx(ThumbsUp, {})
155
+ },
156
+ {
157
+ rating: 'down',
158
+ label: text.notHelpful,
159
+ icon: /*#__PURE__*/ jsx(ThumbsDown, {})
160
+ }
161
+ ];
162
+ return /*#__PURE__*/ jsx("div", {
163
+ ref: ref,
164
+ role: "group",
165
+ "aria-label": ariaLabel ?? text.label,
166
+ "data-slot": "message-action-feedback",
167
+ "data-value": value ?? void 0,
168
+ className: cn('flex items-center gap-0.5', className),
169
+ ...props,
170
+ children: thumbs.map(({ rating, label, icon })=>/*#__PURE__*/ jsxs(Tooltip, {
171
+ children: [
172
+ /*#__PURE__*/ jsx(TooltipTrigger, {
173
+ asChild: true,
174
+ children: /*#__PURE__*/ jsx(Toggle, {
175
+ "data-slot": "message-action",
176
+ size: "xs",
177
+ className: feedbackToggleClass,
178
+ "aria-label": label,
179
+ pressed: value === rating,
180
+ onPressedChange: ()=>set(rating),
181
+ disabled: disabled,
182
+ children: icon
183
+ })
184
+ }),
185
+ /*#__PURE__*/ jsx(TooltipContent, {
186
+ side: "bottom",
187
+ children: label
188
+ })
189
+ ]
190
+ }, rating))
191
+ });
192
+ });
193
+ MessageActionFeedback.displayName = 'MessageActionFeedback';
194
+ const MessageActionsOverflow = /*#__PURE__*/ forwardRef(({ items, strings, align = 'start', tooltipSide = 'bottom', ...props }, ref)=>{
195
+ const text = {
196
+ ...DEFAULT_MESSAGE_ACTIONS_OVERFLOW_STRINGS,
197
+ ...strings
198
+ };
199
+ return /*#__PURE__*/ jsxs(DropdownMenu, {
200
+ children: [
201
+ /*#__PURE__*/ jsxs(Tooltip, {
202
+ children: [
203
+ /*#__PURE__*/ jsx(DropdownMenuTrigger, {
204
+ asChild: true,
205
+ children: /*#__PURE__*/ jsx(TooltipTrigger, {
206
+ asChild: true,
207
+ children: /*#__PURE__*/ jsx(Button, {
208
+ ref: ref,
209
+ "data-slot": "message-actions-overflow",
210
+ "aria-label": text.more,
211
+ variant: "ghost",
212
+ size: "3xs",
213
+ icon: true,
214
+ ...props,
215
+ children: /*#__PURE__*/ jsx(Ellipsis, {})
216
+ })
217
+ })
218
+ }),
219
+ /*#__PURE__*/ jsx(TooltipContent, {
220
+ side: tooltipSide,
221
+ children: text.more
222
+ })
223
+ ]
224
+ }),
225
+ /*#__PURE__*/ jsx(DropdownMenuContent, {
226
+ align: align,
227
+ children: items.map((item)=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
228
+ disabled: item.disabled,
229
+ onSelect: item.onSelect,
230
+ className: cn(item.destructive && 'text-error focus:bg-error-background focus:text-error'),
231
+ children: [
232
+ item.icon,
233
+ item.label
234
+ ]
235
+ }, item.id))
236
+ })
237
+ ]
238
+ });
239
+ });
240
+ MessageActionsOverflow.displayName = 'MessageActionsOverflow';
241
+ export { DEFAULT_MESSAGE_ACTIONS_OVERFLOW_STRINGS, DEFAULT_MESSAGE_ACTIONS_STRINGS, DEFAULT_MESSAGE_ACTION_COPY_STRINGS, DEFAULT_MESSAGE_ACTION_FEEDBACK_STRINGS, MessageAction, MessageActionCopy, MessageActionFeedback, MessageActions, MessageActionsOverflow, messageActionsVariants };
@@ -52,7 +52,7 @@ Message.displayName = 'Message';
52
52
  const MessageAvatar = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ className, ...props }, ref)=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
53
53
  ref: ref,
54
54
  "data-slot": "message-avatar",
55
- className: (0, index_cjs_namespaceObject.cn)('flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-[[data-slot=message-footer]]/message:-translate-y-8', className),
55
+ className: (0, index_cjs_namespaceObject.cn)('flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-[[data-slot=message-footer]]/message:-translate-y-8 group-has-[[data-slot=message-actions]]/message:-translate-y-10 group-has-[[data-slot=message-footer]]/message:group-has-[[data-slot=message-actions]]/message:-translate-y-16', className),
56
56
  ...props
57
57
  }));
58
58
  MessageAvatar.displayName = 'MessageAvatar';
@@ -3,6 +3,8 @@ import * as React from 'react';
3
3
  * Chat conversation row primitives, ported from shadcn/ui's chat components. A `Message` lays out
4
4
  * one turn: an optional `MessageAvatar`, then `MessageContent` holding a `MessageHeader`, the body
5
5
  * (usually a `Bubble`) and a `MessageFooter`. `align="end"` mirrors the row for the current user.
6
+ * A `MessageActions` bar goes inside `MessageContent` after the body, so it takes the same
7
+ * alignment as the bubble.
6
8
  */
7
9
  declare const MessageGroup: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
8
10
  export interface MessageProps extends React.HTMLAttributes<HTMLDivElement> {
@@ -19,7 +19,7 @@ Message.displayName = 'Message';
19
19
  const MessageAvatar = /*#__PURE__*/ forwardRef(({ className, ...props }, ref)=>/*#__PURE__*/ jsx("div", {
20
20
  ref: ref,
21
21
  "data-slot": "message-avatar",
22
- className: cn('flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-[[data-slot=message-footer]]/message:-translate-y-8', className),
22
+ className: cn('flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-[[data-slot=message-footer]]/message:-translate-y-8 group-has-[[data-slot=message-actions]]/message:-translate-y-10 group-has-[[data-slot=message-footer]]/message:group-has-[[data-slot=message-actions]]/message:-translate-y-16', className),
23
23
  ...props
24
24
  }));
25
25
  MessageAvatar.displayName = 'MessageAvatar';
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ "use client";
3
+ var __webpack_require__ = {};
4
+ (()=>{
5
+ __webpack_require__.d = (exports1, definition)=>{
6
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ get: definition[key]
9
+ });
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.r = (exports1)=>{
17
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
18
+ value: 'Module'
19
+ });
20
+ Object.defineProperty(exports1, '__esModule', {
21
+ value: true
22
+ });
23
+ };
24
+ })();
25
+ var __webpack_exports__ = {};
26
+ __webpack_require__.r(__webpack_exports__);
27
+ __webpack_require__.d(__webpack_exports__, {
28
+ SourcesList: ()=>SourcesList,
29
+ DEFAULT_SOURCES_STRINGS: ()=>DEFAULT_SOURCES_STRINGS,
30
+ SourceItem: ()=>SourceItem,
31
+ Sources: ()=>Sources
32
+ });
33
+ const jsx_runtime_namespaceObject = require("react/jsx-runtime");
34
+ const external_lucide_react_namespaceObject = require("lucide-react");
35
+ const external_react_namespaceObject = require("react");
36
+ const index_cjs_namespaceObject = require("../../lib/index.cjs");
37
+ const external_collapsible_cjs_namespaceObject = require("./collapsible.cjs");
38
+ const DEFAULT_SOURCES_STRINGS = {
39
+ sourceCount: (count)=>1 === count ? '1 source' : `${count} sources`,
40
+ opensInNewTab: '(opens in a new tab)'
41
+ };
42
+ const SourcesStringsContext = /*#__PURE__*/ external_react_namespaceObject.createContext(DEFAULT_SOURCES_STRINGS);
43
+ const Sources = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ className, count, strings, children, ...props }, ref)=>{
44
+ const text = {
45
+ ...DEFAULT_SOURCES_STRINGS,
46
+ ...strings
47
+ };
48
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(SourcesStringsContext.Provider, {
49
+ value: text,
50
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_collapsible_cjs_namespaceObject.Collapsible, {
51
+ ref: ref,
52
+ "data-slot": "sources",
53
+ className: (0, index_cjs_namespaceObject.cn)('group/sources flex w-full min-w-0 flex-col gap-2', className),
54
+ ...props,
55
+ children: [
56
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_collapsible_cjs_namespaceObject.CollapsibleTrigger, {
57
+ "data-slot": "sources-trigger",
58
+ className: "inline-flex h-7 w-fit cursor-pointer items-center gap-1.5 rounded-lg border border-border-subtle px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-surface-overlay hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&_svg]:size-3.5 [&_svg]:shrink-0",
59
+ children: [
60
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_lucide_react_namespaceObject.Link2, {
61
+ "aria-hidden": "true"
62
+ }),
63
+ text.sourceCount(count),
64
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_lucide_react_namespaceObject.ChevronDown, {
65
+ "aria-hidden": "true",
66
+ className: "transition-transform group-data-[state=open]/sources:rotate-180"
67
+ })
68
+ ]
69
+ }),
70
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_collapsible_cjs_namespaceObject.CollapsibleContent, {
71
+ "data-slot": "sources-content",
72
+ className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
73
+ children: children
74
+ })
75
+ ]
76
+ })
77
+ });
78
+ });
79
+ Sources.displayName = 'Sources';
80
+ const SourcesList = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ className, ...props }, ref)=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("ol", {
81
+ ref: ref,
82
+ "data-slot": "sources-list",
83
+ className: (0, index_cjs_namespaceObject.cn)('flex flex-col gap-0.5 rounded-xl border border-border-subtle bg-card p-1', className),
84
+ ...props
85
+ }));
86
+ SourcesList.displayName = 'SourcesList';
87
+ const SourceItem = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ className, index, title, source, snippet, href, icon, onSelect, onClick, target = '_blank', rel, ...props }, ref)=>{
88
+ const text = external_react_namespaceObject.useContext(SourcesStringsContext);
89
+ const linkHref = (0, index_cjs_namespaceObject.safeHref)(href);
90
+ const handleClick = (event)=>{
91
+ onClick?.(event);
92
+ if (!event.defaultPrevented) onSelect?.({
93
+ index,
94
+ title,
95
+ source,
96
+ snippet,
97
+ href: linkHref
98
+ }, event);
99
+ };
100
+ const itemClassName = (0, index_cjs_namespaceObject.cn)('flex w-full min-w-0 cursor-pointer items-start gap-2.5 rounded-lg px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-overlay focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', className);
101
+ const newTab = '_blank' === target;
102
+ const body = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
103
+ children: [
104
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
105
+ "data-slot": "source-index",
106
+ className: "mt-0.5 flex h-4.5 min-w-4.5 shrink-0 items-center justify-center rounded-full bg-muted px-1 text-[11px] font-medium leading-none text-muted-foreground tabular-nums",
107
+ children: index
108
+ }),
109
+ icon && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
110
+ "data-slot": "source-icon",
111
+ className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_img]:size-4 [&_img]:rounded-sm [&_svg]:size-4",
112
+ children: icon
113
+ }),
114
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("span", {
115
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
116
+ children: [
117
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
118
+ "data-slot": "source-title",
119
+ className: "truncate font-medium text-foreground",
120
+ children: title
121
+ }),
122
+ source && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
123
+ "data-slot": "source-source",
124
+ className: "truncate text-xs text-muted-foreground",
125
+ children: source
126
+ }),
127
+ snippet && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
128
+ "data-slot": "source-snippet",
129
+ className: "line-clamp-2 text-xs leading-relaxed text-muted-foreground",
130
+ children: snippet
131
+ })
132
+ ]
133
+ }),
134
+ linkHref && newTab && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
135
+ className: "sr-only",
136
+ children: text.opensInNewTab
137
+ })
138
+ ]
139
+ });
140
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("li", {
141
+ "data-slot": "source-item",
142
+ className: "min-w-0",
143
+ children: linkHref ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("a", {
144
+ ref: ref,
145
+ href: linkHref,
146
+ target: target,
147
+ rel: rel ?? (newTab ? 'noopener noreferrer' : void 0),
148
+ className: itemClassName,
149
+ onClick: handleClick,
150
+ ...props,
151
+ children: body
152
+ }) : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("button", {
153
+ ref: ref,
154
+ type: "button",
155
+ className: itemClassName,
156
+ onClick: handleClick,
157
+ ...props,
158
+ children: body
159
+ })
160
+ });
161
+ });
162
+ SourceItem.displayName = 'SourceItem';
163
+ exports.DEFAULT_SOURCES_STRINGS = __webpack_exports__.DEFAULT_SOURCES_STRINGS;
164
+ exports.SourceItem = __webpack_exports__.SourceItem;
165
+ exports.Sources = __webpack_exports__.Sources;
166
+ exports.SourcesList = __webpack_exports__.SourcesList;
167
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
168
+ "DEFAULT_SOURCES_STRINGS",
169
+ "SourceItem",
170
+ "Sources",
171
+ "SourcesList"
172
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
173
+ Object.defineProperty(exports, '__esModule', {
174
+ value: true
175
+ });
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { Collapsible } from './collapsible';
3
+ /**
4
+ * The list of sources behind an assistant answer, collapsed behind a count. `Sources` owns the
5
+ * trigger; put a `SourcesList` of `SourceItem`s inside. Items do not navigate on their own unless
6
+ * given `href`; `onSelect` receives the item and the event, so a host can run its `citation-click`
7
+ * pre-hook and call `event.preventDefault()` to stop a link. The payload drops an `href` that is
8
+ * not http(s), mailto, tel or relative, so it is safe to open.
9
+ */
10
+ export interface SourcesStrings {
11
+ /** Trigger text. A function so a host can apply its own plural rules. */
12
+ sourceCount: (count: number) => string;
13
+ /** Screen reader hint on links that open a new tab. */
14
+ opensInNewTab: string;
15
+ }
16
+ export declare const DEFAULT_SOURCES_STRINGS: SourcesStrings;
17
+ export interface SourcesProps extends React.ComponentPropsWithoutRef<typeof Collapsible> {
18
+ /** Number of sources, shown in the trigger. */
19
+ count: number;
20
+ /** Overrides for any subset of the English strings. Also read by the `SourceItem`s inside. */
21
+ strings?: Partial<SourcesStrings>;
22
+ }
23
+ declare const Sources: React.ForwardRefExoticComponent<SourcesProps & React.RefAttributes<HTMLDivElement>>;
24
+ declare const SourcesList: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLOListElement> & React.RefAttributes<HTMLOListElement>>;
25
+ export interface SourceData {
26
+ index: number | string;
27
+ title: string;
28
+ source?: string;
29
+ snippet?: string;
30
+ href?: string;
31
+ }
32
+ type SourceItemElementProps = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement> & React.ButtonHTMLAttributes<HTMLButtonElement>, 'onSelect' | 'title' | 'type'>;
33
+ export interface SourceItemProps extends SourceItemElementProps, SourceData {
34
+ /** Leading icon, such as a favicon or file type. */
35
+ icon?: React.ReactNode;
36
+ onSelect?: (source: SourceData, event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void;
37
+ }
38
+ /**
39
+ * One source. A link when `href` is set and uses a safe protocol (new tab by default), otherwise a
40
+ * button for `onSelect`.
41
+ * The ref and extra props go to that link or button, not the wrapping `li`.
42
+ */
43
+ declare const SourceItem: React.ForwardRefExoticComponent<SourceItemProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
44
+ export { Sources, SourcesList, SourceItem };
@@ -0,0 +1,132 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { ChevronDown, Link2 } from "lucide-react";
4
+ import { createContext, forwardRef, useContext } from "react";
5
+ import { cn, safeHref } from "../../lib/index.js";
6
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./collapsible.js";
7
+ const DEFAULT_SOURCES_STRINGS = {
8
+ sourceCount: (count)=>1 === count ? '1 source' : `${count} sources`,
9
+ opensInNewTab: '(opens in a new tab)'
10
+ };
11
+ const SourcesStringsContext = /*#__PURE__*/ createContext(DEFAULT_SOURCES_STRINGS);
12
+ const Sources = /*#__PURE__*/ forwardRef(({ className, count, strings, children, ...props }, ref)=>{
13
+ const text = {
14
+ ...DEFAULT_SOURCES_STRINGS,
15
+ ...strings
16
+ };
17
+ return /*#__PURE__*/ jsx(SourcesStringsContext.Provider, {
18
+ value: text,
19
+ children: /*#__PURE__*/ jsxs(Collapsible, {
20
+ ref: ref,
21
+ "data-slot": "sources",
22
+ className: cn('group/sources flex w-full min-w-0 flex-col gap-2', className),
23
+ ...props,
24
+ children: [
25
+ /*#__PURE__*/ jsxs(CollapsibleTrigger, {
26
+ "data-slot": "sources-trigger",
27
+ className: "inline-flex h-7 w-fit cursor-pointer items-center gap-1.5 rounded-lg border border-border-subtle px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-surface-overlay hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&_svg]:size-3.5 [&_svg]:shrink-0",
28
+ children: [
29
+ /*#__PURE__*/ jsx(Link2, {
30
+ "aria-hidden": "true"
31
+ }),
32
+ text.sourceCount(count),
33
+ /*#__PURE__*/ jsx(ChevronDown, {
34
+ "aria-hidden": "true",
35
+ className: "transition-transform group-data-[state=open]/sources:rotate-180"
36
+ })
37
+ ]
38
+ }),
39
+ /*#__PURE__*/ jsx(CollapsibleContent, {
40
+ "data-slot": "sources-content",
41
+ className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
42
+ children: children
43
+ })
44
+ ]
45
+ })
46
+ });
47
+ });
48
+ Sources.displayName = 'Sources';
49
+ const SourcesList = /*#__PURE__*/ forwardRef(({ className, ...props }, ref)=>/*#__PURE__*/ jsx("ol", {
50
+ ref: ref,
51
+ "data-slot": "sources-list",
52
+ className: cn('flex flex-col gap-0.5 rounded-xl border border-border-subtle bg-card p-1', className),
53
+ ...props
54
+ }));
55
+ SourcesList.displayName = 'SourcesList';
56
+ const SourceItem = /*#__PURE__*/ forwardRef(({ className, index, title, source, snippet, href, icon, onSelect, onClick, target = '_blank', rel, ...props }, ref)=>{
57
+ const text = useContext(SourcesStringsContext);
58
+ const linkHref = safeHref(href);
59
+ const handleClick = (event)=>{
60
+ onClick?.(event);
61
+ if (!event.defaultPrevented) onSelect?.({
62
+ index,
63
+ title,
64
+ source,
65
+ snippet,
66
+ href: linkHref
67
+ }, event);
68
+ };
69
+ const itemClassName = cn('flex w-full min-w-0 cursor-pointer items-start gap-2.5 rounded-lg px-2 py-1.5 text-left text-sm transition-colors hover:bg-surface-overlay focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', className);
70
+ const newTab = '_blank' === target;
71
+ const body = /*#__PURE__*/ jsxs(Fragment, {
72
+ children: [
73
+ /*#__PURE__*/ jsx("span", {
74
+ "data-slot": "source-index",
75
+ className: "mt-0.5 flex h-4.5 min-w-4.5 shrink-0 items-center justify-center rounded-full bg-muted px-1 text-[11px] font-medium leading-none text-muted-foreground tabular-nums",
76
+ children: index
77
+ }),
78
+ icon && /*#__PURE__*/ jsx("span", {
79
+ "data-slot": "source-icon",
80
+ className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_img]:size-4 [&_img]:rounded-sm [&_svg]:size-4",
81
+ children: icon
82
+ }),
83
+ /*#__PURE__*/ jsxs("span", {
84
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
85
+ children: [
86
+ /*#__PURE__*/ jsx("span", {
87
+ "data-slot": "source-title",
88
+ className: "truncate font-medium text-foreground",
89
+ children: title
90
+ }),
91
+ source && /*#__PURE__*/ jsx("span", {
92
+ "data-slot": "source-source",
93
+ className: "truncate text-xs text-muted-foreground",
94
+ children: source
95
+ }),
96
+ snippet && /*#__PURE__*/ jsx("span", {
97
+ "data-slot": "source-snippet",
98
+ className: "line-clamp-2 text-xs leading-relaxed text-muted-foreground",
99
+ children: snippet
100
+ })
101
+ ]
102
+ }),
103
+ linkHref && newTab && /*#__PURE__*/ jsx("span", {
104
+ className: "sr-only",
105
+ children: text.opensInNewTab
106
+ })
107
+ ]
108
+ });
109
+ return /*#__PURE__*/ jsx("li", {
110
+ "data-slot": "source-item",
111
+ className: "min-w-0",
112
+ children: linkHref ? /*#__PURE__*/ jsx("a", {
113
+ ref: ref,
114
+ href: linkHref,
115
+ target: target,
116
+ rel: rel ?? (newTab ? 'noopener noreferrer' : void 0),
117
+ className: itemClassName,
118
+ onClick: handleClick,
119
+ ...props,
120
+ children: body
121
+ }) : /*#__PURE__*/ jsx("button", {
122
+ ref: ref,
123
+ type: "button",
124
+ className: itemClassName,
125
+ onClick: handleClick,
126
+ ...props,
127
+ children: body
128
+ })
129
+ });
130
+ });
131
+ SourceItem.displayName = 'SourceItem';
132
+ export { DEFAULT_SOURCES_STRINGS, SourceItem, Sources, SourcesList };