@uipath/apollo-wind 2.68.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.
- package/dist/components/custom/chat-first-experience.cjs +3 -3
- package/dist/components/custom/chat-first-experience.js +3 -3
- package/dist/components/custom/demo-composer.cjs +80 -0
- package/dist/components/custom/demo-composer.d.ts +11 -0
- package/dist/components/custom/demo-composer.js +46 -0
- package/dist/components/custom/panel-flow.cjs +2 -2
- package/dist/components/custom/panel-flow.js +2 -2
- package/dist/components/ui/chat-composer.cjs +429 -0
- package/dist/components/ui/chat-composer.d.ts +157 -0
- package/dist/components/ui/chat-composer.js +359 -0
- package/dist/components/ui/citation.cjs +188 -0
- package/dist/components/ui/citation.d.ts +42 -0
- package/dist/components/ui/citation.js +148 -0
- package/dist/components/ui/code-block.cjs +375 -0
- package/dist/components/ui/code-block.d.ts +38 -0
- package/dist/components/ui/code-block.js +307 -0
- package/dist/components/ui/dropzone-overlay.cjs +142 -0
- package/dist/components/ui/dropzone-overlay.d.ts +27 -0
- package/dist/components/ui/dropzone-overlay.js +105 -0
- package/dist/components/ui/file-upload.cjs +5 -29
- package/dist/components/ui/file-upload.js +2 -26
- package/dist/components/ui/file-validation.cjs +91 -0
- package/dist/components/ui/file-validation.d.ts +24 -0
- package/dist/components/ui/file-validation.js +51 -0
- package/dist/components/ui/hover-card.cjs +15 -8
- package/dist/components/ui/hover-card.d.ts +4 -1
- package/dist/components/ui/hover-card.js +16 -9
- package/dist/components/ui/index.cjs +330 -198
- package/dist/components/ui/index.d.ts +12 -0
- package/dist/components/ui/index.js +12 -0
- package/dist/components/ui/input-group.cjs +1 -1
- package/dist/components/ui/input-group.d.ts +2 -1
- package/dist/components/ui/input-group.js +1 -1
- package/dist/components/ui/json-tree-view/JsonTree.cjs +2 -2
- package/dist/components/ui/json-tree-view/JsonTree.js +1 -1
- package/dist/components/ui/json-tree-view/index.cjs +26 -23
- package/dist/components/ui/json-tree-view/index.d.ts +2 -2
- package/dist/components/ui/json-tree-view/index.js +2 -2
- package/dist/components/ui/live-region.cjs +106 -0
- package/dist/components/ui/live-region.d.ts +31 -0
- package/dist/components/ui/live-region.js +72 -0
- package/dist/components/ui/loading-dots.cjs +95 -0
- package/dist/components/ui/loading-dots.d.ts +21 -0
- package/dist/components/ui/loading-dots.js +55 -0
- package/dist/components/ui/markdown.cjs +428 -0
- package/dist/components/ui/markdown.d.ts +55 -0
- package/dist/components/ui/markdown.js +378 -0
- package/dist/components/ui/message-actions.cjs +302 -0
- package/dist/components/ui/message-actions.d.ts +102 -0
- package/dist/components/ui/message-actions.js +241 -0
- package/dist/components/ui/message.cjs +1 -1
- package/dist/components/ui/message.d.ts +2 -0
- package/dist/components/ui/message.js +1 -1
- package/dist/components/ui/sources.cjs +175 -0
- package/dist/components/ui/sources.d.ts +44 -0
- package/dist/components/ui/sources.js +132 -0
- package/dist/components/ui/thinking-indicator.cjs +146 -0
- package/dist/components/ui/thinking-indicator.d.ts +38 -0
- package/dist/components/ui/thinking-indicator.js +106 -0
- package/dist/components/ui/tool-call.cjs +359 -0
- package/dist/components/ui/tool-call.d.ts +75 -0
- package/dist/components/ui/tool-call.js +301 -0
- package/dist/index.cjs +433 -253
- package/dist/index.d.ts +24 -0
- package/dist/index.js +13 -1
- package/dist/lib/index.cjs +8 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +2 -1
- package/dist/lib/url.cjs +54 -0
- package/dist/lib/url.d.ts +8 -0
- package/dist/lib/url.js +17 -0
- package/dist/styles.css +363 -35
- package/dist/tailwind.utilities.css +21 -0
- package/package.json +7 -1
- package/dist/components/custom/chat-composer.cjs +0 -134
- package/dist/components/custom/chat-composer.d.ts +0 -14
- package/dist/components/custom/chat-composer.js +0 -100
- /package/dist/{components/ui/json-tree-view → lib}/clipboard.cjs +0 -0
- /package/dist/{components/ui/json-tree-view → lib}/clipboard.d.ts +0 -0
- /package/dist/{components/ui/json-tree-view → lib}/clipboard.js +0 -0
|
@@ -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 };
|
|
@@ -0,0 +1,146 @@
|
|
|
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
|
+
thinkingIndicatorVariants: ()=>thinkingIndicatorVariants,
|
|
29
|
+
DEFAULT_THINKING_INDICATOR_STRINGS: ()=>DEFAULT_THINKING_INDICATOR_STRINGS,
|
|
30
|
+
ThinkingIndicator: ()=>ThinkingIndicator
|
|
31
|
+
});
|
|
32
|
+
const jsx_runtime_namespaceObject = require("react/jsx-runtime");
|
|
33
|
+
const external_class_variance_authority_namespaceObject = require("class-variance-authority");
|
|
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 REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';
|
|
38
|
+
function getPrefersReducedMotion() {
|
|
39
|
+
if ("u" < typeof window || 'function' != typeof window.matchMedia) return false;
|
|
40
|
+
return window.matchMedia(REDUCED_MOTION_QUERY).matches;
|
|
41
|
+
}
|
|
42
|
+
function usePrefersReducedMotion() {
|
|
43
|
+
const [reduced, setReduced] = external_react_namespaceObject.useState(getPrefersReducedMotion);
|
|
44
|
+
external_react_namespaceObject.useEffect(()=>{
|
|
45
|
+
if ('function' != typeof window.matchMedia) return;
|
|
46
|
+
const mql = window.matchMedia(REDUCED_MOTION_QUERY);
|
|
47
|
+
const onChange = ()=>setReduced(mql.matches);
|
|
48
|
+
mql.addEventListener('change', onChange);
|
|
49
|
+
return ()=>mql.removeEventListener('change', onChange);
|
|
50
|
+
}, []);
|
|
51
|
+
return reduced;
|
|
52
|
+
}
|
|
53
|
+
const thinkingIndicatorVariants = (0, external_class_variance_authority_namespaceObject.cva)('inline-flex max-w-full min-w-0 items-center text-muted-foreground', {
|
|
54
|
+
variants: {
|
|
55
|
+
size: {
|
|
56
|
+
sm: 'gap-1.5 text-xs [&_[data-slot=thinking-indicator-icon]]:size-3.5',
|
|
57
|
+
md: 'gap-2 text-sm [&_[data-slot=thinking-indicator-icon]]:size-4'
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
defaultVariants: {
|
|
61
|
+
size: 'md'
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const DEFAULT_THINKING_INDICATOR_STRINGS = {
|
|
65
|
+
label: 'Thinking'
|
|
66
|
+
};
|
|
67
|
+
const ThinkingIndicator = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ className, size = 'md', label, messages, interval = 2500, strings, icon, 'aria-label': ariaLabel, ...props }, ref)=>{
|
|
68
|
+
const text = {
|
|
69
|
+
...DEFAULT_THINKING_INDICATOR_STRINGS,
|
|
70
|
+
...strings
|
|
71
|
+
};
|
|
72
|
+
const staticLabel = label ?? text.label;
|
|
73
|
+
const name = ariaLabel ?? staticLabel;
|
|
74
|
+
const labels = messages && messages.length > 0 ? messages : [
|
|
75
|
+
staticLabel
|
|
76
|
+
];
|
|
77
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
78
|
+
const rotates = labels.length > 1 && !reducedMotion && interval > 0;
|
|
79
|
+
const rotationKey = `${rotates}\u0000${labels.join('\u0000')}`;
|
|
80
|
+
const [index, setIndex] = external_react_namespaceObject.useState(0);
|
|
81
|
+
const [prevRotationKey, setPrevRotationKey] = external_react_namespaceObject.useState(rotationKey);
|
|
82
|
+
if (rotationKey !== prevRotationKey) {
|
|
83
|
+
setPrevRotationKey(rotationKey);
|
|
84
|
+
setIndex(0);
|
|
85
|
+
}
|
|
86
|
+
external_react_namespaceObject.useEffect(()=>{
|
|
87
|
+
if (!rotates) return;
|
|
88
|
+
const id = window.setInterval(()=>{
|
|
89
|
+
setIndex((current)=>(current + 1) % labels.length);
|
|
90
|
+
}, interval);
|
|
91
|
+
return ()=>window.clearInterval(id);
|
|
92
|
+
}, [
|
|
93
|
+
rotates,
|
|
94
|
+
labels.length,
|
|
95
|
+
interval,
|
|
96
|
+
rotationKey
|
|
97
|
+
]);
|
|
98
|
+
const activeIndex = index < labels.length ? index : 0;
|
|
99
|
+
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
|
|
100
|
+
ref: ref,
|
|
101
|
+
"data-slot": "thinking-indicator",
|
|
102
|
+
"data-size": size,
|
|
103
|
+
role: "status",
|
|
104
|
+
"aria-label": name,
|
|
105
|
+
className: (0, index_cjs_namespaceObject.cn)(thinkingIndicatorVariants({
|
|
106
|
+
size
|
|
107
|
+
}), className),
|
|
108
|
+
...props,
|
|
109
|
+
children: [
|
|
110
|
+
null !== icon && false !== icon && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
|
|
111
|
+
"data-slot": "thinking-indicator-icon",
|
|
112
|
+
"aria-hidden": "true",
|
|
113
|
+
className: "inline-flex shrink-0 items-center justify-center [&>svg]:size-full",
|
|
114
|
+
children: icon ?? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_lucide_react_namespaceObject.Sparkles, {
|
|
115
|
+
className: "text-primary animate-pulse motion-reduce:animate-none"
|
|
116
|
+
})
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
|
|
119
|
+
"data-slot": "thinking-indicator-label",
|
|
120
|
+
"aria-hidden": "true",
|
|
121
|
+
className: "grid min-w-0",
|
|
122
|
+
children: labels.map((item, i)=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
|
|
123
|
+
"data-active": i === activeIndex,
|
|
124
|
+
className: "shimmer col-start-1 row-start-1 truncate transition-opacity duration-300 data-[active=false]:opacity-0 motion-reduce:transition-none",
|
|
125
|
+
children: item
|
|
126
|
+
}, i))
|
|
127
|
+
}),
|
|
128
|
+
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
|
|
129
|
+
className: "sr-only",
|
|
130
|
+
children: name
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
ThinkingIndicator.displayName = 'ThinkingIndicator';
|
|
136
|
+
exports.DEFAULT_THINKING_INDICATOR_STRINGS = __webpack_exports__.DEFAULT_THINKING_INDICATOR_STRINGS;
|
|
137
|
+
exports.ThinkingIndicator = __webpack_exports__.ThinkingIndicator;
|
|
138
|
+
exports.thinkingIndicatorVariants = __webpack_exports__.thinkingIndicatorVariants;
|
|
139
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
140
|
+
"DEFAULT_THINKING_INDICATOR_STRINGS",
|
|
141
|
+
"ThinkingIndicator",
|
|
142
|
+
"thinkingIndicatorVariants"
|
|
143
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
144
|
+
Object.defineProperty(exports, '__esModule', {
|
|
145
|
+
value: true
|
|
146
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
declare const thinkingIndicatorVariants: (props?: ({
|
|
4
|
+
size?: "sm" | "md" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
export interface ThinkingIndicatorStrings {
|
|
7
|
+
/** Default visible label, and the accessible name unless `label` or `aria-label` is set. */
|
|
8
|
+
label: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_THINKING_INDICATOR_STRINGS: ThinkingIndicatorStrings;
|
|
11
|
+
export interface ThinkingIndicatorProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>, VariantProps<typeof thinkingIndicatorVariants> {
|
|
12
|
+
/** A single label. Also the accessible name when `messages` rotate. */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Labels to cycle through. The first shows immediately; reduced motion keeps it there. */
|
|
15
|
+
messages?: string[];
|
|
16
|
+
/** Milliseconds each of `messages` stays on screen. */
|
|
17
|
+
interval?: number;
|
|
18
|
+
/** Overrides for any subset of the English strings. An explicit `aria-label` wins over both. */
|
|
19
|
+
strings?: Partial<ThinkingIndicatorStrings>;
|
|
20
|
+
/**
|
|
21
|
+
* Replaces the pulsing sparkle; `null` or `false` shows the label alone. A custom icon brings
|
|
22
|
+
* its own colour and animation and is sized by the indicator's `size`.
|
|
23
|
+
*/
|
|
24
|
+
icon?: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A "the assistant is working" row for a conversation: a pulsing sparkle and a shimmering label.
|
|
28
|
+
* Pass `messages` to cycle through progress labels ("Searching", "Reading files") every
|
|
29
|
+
* `interval` ms with a crossfade.
|
|
30
|
+
*
|
|
31
|
+
* Screen readers get one stable name (`label`, else `strings.label`) on a `role="status"` root,
|
|
32
|
+
* and the visual label is `aria-hidden`. Rotating labels are decoration, so announcing each one
|
|
33
|
+
* would only add noise. Announce real progress with `LiveRegion` instead.
|
|
34
|
+
*
|
|
35
|
+
* Under `prefers-reduced-motion` the icon and shimmer are static and the labels do not rotate.
|
|
36
|
+
*/
|
|
37
|
+
declare const ThinkingIndicator: React.ForwardRefExoticComponent<ThinkingIndicatorProps & React.RefAttributes<HTMLDivElement>>;
|
|
38
|
+
export { ThinkingIndicator, thinkingIndicatorVariants };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { Sparkles } from "lucide-react";
|
|
5
|
+
import { forwardRef, useEffect, useState } from "react";
|
|
6
|
+
import { cn } from "../../lib/index.js";
|
|
7
|
+
const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';
|
|
8
|
+
function getPrefersReducedMotion() {
|
|
9
|
+
if ("u" < typeof window || 'function' != typeof window.matchMedia) return false;
|
|
10
|
+
return window.matchMedia(REDUCED_MOTION_QUERY).matches;
|
|
11
|
+
}
|
|
12
|
+
function usePrefersReducedMotion() {
|
|
13
|
+
const [reduced, setReduced] = useState(getPrefersReducedMotion);
|
|
14
|
+
useEffect(()=>{
|
|
15
|
+
if ('function' != typeof window.matchMedia) return;
|
|
16
|
+
const mql = window.matchMedia(REDUCED_MOTION_QUERY);
|
|
17
|
+
const onChange = ()=>setReduced(mql.matches);
|
|
18
|
+
mql.addEventListener('change', onChange);
|
|
19
|
+
return ()=>mql.removeEventListener('change', onChange);
|
|
20
|
+
}, []);
|
|
21
|
+
return reduced;
|
|
22
|
+
}
|
|
23
|
+
const thinkingIndicatorVariants = cva('inline-flex max-w-full min-w-0 items-center text-muted-foreground', {
|
|
24
|
+
variants: {
|
|
25
|
+
size: {
|
|
26
|
+
sm: 'gap-1.5 text-xs [&_[data-slot=thinking-indicator-icon]]:size-3.5',
|
|
27
|
+
md: 'gap-2 text-sm [&_[data-slot=thinking-indicator-icon]]:size-4'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: {
|
|
31
|
+
size: 'md'
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const DEFAULT_THINKING_INDICATOR_STRINGS = {
|
|
35
|
+
label: 'Thinking'
|
|
36
|
+
};
|
|
37
|
+
const ThinkingIndicator = /*#__PURE__*/ forwardRef(({ className, size = 'md', label, messages, interval = 2500, strings, icon, 'aria-label': ariaLabel, ...props }, ref)=>{
|
|
38
|
+
const text = {
|
|
39
|
+
...DEFAULT_THINKING_INDICATOR_STRINGS,
|
|
40
|
+
...strings
|
|
41
|
+
};
|
|
42
|
+
const staticLabel = label ?? text.label;
|
|
43
|
+
const name = ariaLabel ?? staticLabel;
|
|
44
|
+
const labels = messages && messages.length > 0 ? messages : [
|
|
45
|
+
staticLabel
|
|
46
|
+
];
|
|
47
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
48
|
+
const rotates = labels.length > 1 && !reducedMotion && interval > 0;
|
|
49
|
+
const rotationKey = `${rotates}\u0000${labels.join('\u0000')}`;
|
|
50
|
+
const [index, setIndex] = useState(0);
|
|
51
|
+
const [prevRotationKey, setPrevRotationKey] = useState(rotationKey);
|
|
52
|
+
if (rotationKey !== prevRotationKey) {
|
|
53
|
+
setPrevRotationKey(rotationKey);
|
|
54
|
+
setIndex(0);
|
|
55
|
+
}
|
|
56
|
+
useEffect(()=>{
|
|
57
|
+
if (!rotates) return;
|
|
58
|
+
const id = window.setInterval(()=>{
|
|
59
|
+
setIndex((current)=>(current + 1) % labels.length);
|
|
60
|
+
}, interval);
|
|
61
|
+
return ()=>window.clearInterval(id);
|
|
62
|
+
}, [
|
|
63
|
+
rotates,
|
|
64
|
+
labels.length,
|
|
65
|
+
interval,
|
|
66
|
+
rotationKey
|
|
67
|
+
]);
|
|
68
|
+
const activeIndex = index < labels.length ? index : 0;
|
|
69
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
70
|
+
ref: ref,
|
|
71
|
+
"data-slot": "thinking-indicator",
|
|
72
|
+
"data-size": size,
|
|
73
|
+
role: "status",
|
|
74
|
+
"aria-label": name,
|
|
75
|
+
className: cn(thinkingIndicatorVariants({
|
|
76
|
+
size
|
|
77
|
+
}), className),
|
|
78
|
+
...props,
|
|
79
|
+
children: [
|
|
80
|
+
null !== icon && false !== icon && /*#__PURE__*/ jsx("span", {
|
|
81
|
+
"data-slot": "thinking-indicator-icon",
|
|
82
|
+
"aria-hidden": "true",
|
|
83
|
+
className: "inline-flex shrink-0 items-center justify-center [&>svg]:size-full",
|
|
84
|
+
children: icon ?? /*#__PURE__*/ jsx(Sparkles, {
|
|
85
|
+
className: "text-primary animate-pulse motion-reduce:animate-none"
|
|
86
|
+
})
|
|
87
|
+
}),
|
|
88
|
+
/*#__PURE__*/ jsx("span", {
|
|
89
|
+
"data-slot": "thinking-indicator-label",
|
|
90
|
+
"aria-hidden": "true",
|
|
91
|
+
className: "grid min-w-0",
|
|
92
|
+
children: labels.map((item, i)=>/*#__PURE__*/ jsx("span", {
|
|
93
|
+
"data-active": i === activeIndex,
|
|
94
|
+
className: "shimmer col-start-1 row-start-1 truncate transition-opacity duration-300 data-[active=false]:opacity-0 motion-reduce:transition-none",
|
|
95
|
+
children: item
|
|
96
|
+
}, i))
|
|
97
|
+
}),
|
|
98
|
+
/*#__PURE__*/ jsx("span", {
|
|
99
|
+
className: "sr-only",
|
|
100
|
+
children: name
|
|
101
|
+
})
|
|
102
|
+
]
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
ThinkingIndicator.displayName = 'ThinkingIndicator';
|
|
106
|
+
export { DEFAULT_THINKING_INDICATOR_STRINGS, ThinkingIndicator, thinkingIndicatorVariants };
|