@ciridae/ui-agent 0.3.0 → 0.3.5
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/README.md +7 -1
- package/dist/components/agentic/agent-card.d.ts +28 -0
- package/dist/components/agentic/agent-card.js +27 -0
- package/dist/components/agentic/agent-composer.d.ts +42 -0
- package/dist/components/agentic/agent-composer.js +89 -0
- package/dist/components/agentic/agent-context.d.ts +28 -0
- package/dist/components/agentic/agent-context.js +102 -0
- package/dist/components/agentic/agent-queue.js +1 -1
- package/dist/components/agentic/artifact.js +4 -4
- package/dist/components/agentic/assistant-mark-icon.d.ts +9 -0
- package/dist/components/agentic/assistant-mark-icon.js +12 -0
- package/dist/components/agentic/attachments-actions.d.ts +10 -0
- package/dist/components/agentic/attachments-actions.js +142 -0
- package/dist/components/agentic/attachments-context.d.ts +25 -0
- package/dist/components/agentic/attachments-context.js +196 -0
- package/dist/components/agentic/attachments-model.d.ts +23 -0
- package/dist/components/agentic/attachments-model.js +226 -0
- package/dist/components/agentic/attachments-preview.d.ts +7 -0
- package/dist/components/agentic/attachments-preview.js +25 -0
- package/dist/components/agentic/attachments-types.d.ts +87 -0
- package/dist/components/agentic/attachments-types.js +1 -0
- package/dist/components/agentic/attachments-ui.d.ts +14 -0
- package/dist/components/agentic/attachments-ui.js +90 -0
- package/dist/components/agentic/attachments.d.ts +5 -124
- package/dist/components/agentic/attachments.js +5 -591
- package/dist/components/agentic/audio-player.d.ts +16 -0
- package/dist/components/agentic/audio-player.js +21 -0
- package/dist/components/agentic/breathing-grid-icon.css +45 -0
- package/dist/components/agentic/breathing-grid-icon.css.d.ts +2 -0
- package/dist/components/agentic/breathing-grid-icon.d.ts +6 -0
- package/dist/components/agentic/breathing-grid-icon.js +7 -0
- package/dist/components/agentic/canvas.d.ts +10 -0
- package/dist/components/agentic/canvas.js +22 -0
- package/dist/components/agentic/code-block.js +4 -4
- package/dist/components/agentic/commit.d.ts +57 -0
- package/dist/components/agentic/commit.js +85 -0
- package/dist/components/agentic/connection.d.ts +3 -0
- package/dist/components/agentic/connection.js +8 -0
- package/dist/components/agentic/controls.d.ts +6 -0
- package/dist/components/agentic/controls.js +7 -0
- package/dist/components/agentic/edge.d.ts +8 -0
- package/dist/components/agentic/edge.js +65 -0
- package/dist/components/agentic/effort-selector.d.ts +43 -0
- package/dist/components/agentic/effort-selector.js +47 -0
- package/dist/components/agentic/environment-variables.d.ts +32 -0
- package/dist/components/agentic/environment-variables.js +66 -0
- package/dist/components/agentic/jsx-preview.d.ts +19 -0
- package/dist/components/agentic/jsx-preview.js +34 -0
- package/dist/components/agentic/message.d.ts +1 -1
- package/dist/components/agentic/message.js +56 -16
- package/dist/components/agentic/mic-selector.d.ts +58 -0
- package/dist/components/agentic/mic-selector.js +173 -0
- package/dist/components/agentic/node.d.ts +26 -0
- package/dist/components/agentic/node.js +29 -0
- package/dist/components/agentic/open-in-chat.d.ts +9 -0
- package/dist/components/agentic/open-in-chat.js +8 -0
- package/dist/components/agentic/package-info.d.ts +30 -0
- package/dist/components/agentic/package-info.js +44 -0
- package/dist/components/agentic/panel.d.ts +6 -0
- package/dist/components/agentic/panel.js +7 -0
- package/dist/components/agentic/persona.d.ts +16 -0
- package/dist/components/agentic/persona.js +116 -0
- package/dist/components/agentic/prompt-input.js +7 -6
- package/dist/components/agentic/sources.js +9 -9
- package/dist/components/agentic/speech-input.d.ts +24 -0
- package/dist/components/agentic/speech-input.js +30 -0
- package/dist/components/agentic/stack-trace.d.ts +27 -0
- package/dist/components/agentic/stack-trace.js +76 -0
- package/dist/components/agentic/suggestion.d.ts +12 -0
- package/dist/components/agentic/suggestion.js +15 -0
- package/dist/components/agentic/test-results.d.ts +51 -0
- package/dist/components/agentic/test-results.js +83 -0
- package/dist/components/agentic/theme.d.ts +5 -0
- package/dist/components/agentic/theme.js +31 -0
- package/dist/components/agentic/toolbar.d.ts +6 -0
- package/dist/components/agentic/toolbar.js +7 -0
- package/dist/components/agentic/transcription.d.ts +20 -0
- package/dist/components/agentic/transcription.js +32 -0
- package/dist/components/agentic/use-controllable-state.d.ts +6 -0
- package/dist/components/agentic/use-controllable-state.js +13 -0
- package/dist/components/agentic/voice-selector.d.ts +69 -0
- package/dist/components/agentic/voice-selector.js +122 -0
- package/dist/components/blocks/artifact-workbench.d.ts +9 -0
- package/dist/components/blocks/artifact-workbench.js +28 -0
- package/dist/components/blocks/tool-approval-panel.d.ts +11 -0
- package/dist/components/blocks/tool-approval-panel.js +11 -0
- package/dist/components/blocks/voice-agent-panel.d.ts +14 -0
- package/dist/components/blocks/voice-agent-panel.js +60 -0
- package/dist/components/blocks/workflow-canvas-panel.d.ts +18 -0
- package/dist/components/blocks/workflow-canvas-panel.js +106 -0
- package/dist/styles.css +5 -0
- package/package.json +176 -10
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRive, useStateMachineInput, useViewModel, useViewModelInstance, useViewModelInstanceColor, } from "@rive-app/react-webgl2";
|
|
3
|
+
import { memo, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { useAgenticTheme } from "@ciridae/ui-agent/theme";
|
|
5
|
+
import { cn } from "@ciridae/ui/utils";
|
|
6
|
+
const HALO_SOURCE = "/assets/persona/halo-2.0.riv";
|
|
7
|
+
const STATE_MACHINE = "default";
|
|
8
|
+
const Persona = memo(function Persona({ className, onLoad, onLoadError, onPause, onPlay, onReady, onStop, state = "idle", ...props }) {
|
|
9
|
+
const ready = useStrictModeSafeInit();
|
|
10
|
+
const callbacks = useStableRiveCallbacks({
|
|
11
|
+
onLoad,
|
|
12
|
+
onLoadError,
|
|
13
|
+
onPause,
|
|
14
|
+
onPlay,
|
|
15
|
+
onReady,
|
|
16
|
+
onStop,
|
|
17
|
+
});
|
|
18
|
+
const [loadFailed, setLoadFailed] = useState(false);
|
|
19
|
+
const riveParams = useMemo(() => ready
|
|
20
|
+
? {
|
|
21
|
+
autoplay: true,
|
|
22
|
+
onLoad: callbacks.onLoad,
|
|
23
|
+
onLoadError: (error) => {
|
|
24
|
+
setLoadFailed(true);
|
|
25
|
+
callbacks.onLoadError?.(error);
|
|
26
|
+
},
|
|
27
|
+
onPause: callbacks.onPause,
|
|
28
|
+
onPlay: callbacks.onPlay,
|
|
29
|
+
onRiveReady: callbacks.onReady,
|
|
30
|
+
onStop: callbacks.onStop,
|
|
31
|
+
src: HALO_SOURCE,
|
|
32
|
+
stateMachines: STATE_MACHINE,
|
|
33
|
+
}
|
|
34
|
+
: null, [callbacks, ready]);
|
|
35
|
+
const { rive, RiveComponent } = useRive(riveParams);
|
|
36
|
+
usePersonaThemeColor(rive);
|
|
37
|
+
usePersonaStateMachine(rive, state);
|
|
38
|
+
return (_jsx("div", { "data-slot": "persona", "data-state": state, className: cn("relative flex aspect-square size-48 items-center justify-center overflow-hidden rounded-full", "bg-background text-foreground", className), ...props, children: loadFailed ? _jsx(PersonaFallback, { state: state }) : _jsx(RiveComponent, { className: "size-full" }) }));
|
|
39
|
+
});
|
|
40
|
+
function useStrictModeSafeInit() {
|
|
41
|
+
const [ready, setReady] = useState(false);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const id = requestAnimationFrame(() => setReady(true));
|
|
44
|
+
return () => {
|
|
45
|
+
cancelAnimationFrame(id);
|
|
46
|
+
setReady(false);
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
return ready;
|
|
50
|
+
}
|
|
51
|
+
function useStableRiveCallbacks({ onLoad, onLoadError, onPause, onPlay, onReady, onStop, }) {
|
|
52
|
+
const callbacksRef = useRef({
|
|
53
|
+
onLoad,
|
|
54
|
+
onLoadError,
|
|
55
|
+
onPause,
|
|
56
|
+
onPlay,
|
|
57
|
+
onReady,
|
|
58
|
+
onStop,
|
|
59
|
+
});
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
callbacksRef.current = {
|
|
62
|
+
onLoad,
|
|
63
|
+
onLoadError,
|
|
64
|
+
onPause,
|
|
65
|
+
onPlay,
|
|
66
|
+
onReady,
|
|
67
|
+
onStop,
|
|
68
|
+
};
|
|
69
|
+
}, [onLoad, onLoadError, onPause, onPlay, onReady, onStop]);
|
|
70
|
+
return useMemo(() => ({
|
|
71
|
+
onLoad: (loadedRive) => callbacksRef.current.onLoad?.(loadedRive),
|
|
72
|
+
onLoadError: (error) => callbacksRef.current.onLoadError?.(error),
|
|
73
|
+
onPause: (event) => callbacksRef.current.onPause?.(event),
|
|
74
|
+
onPlay: (event) => callbacksRef.current.onPlay?.(event),
|
|
75
|
+
onReady: () => callbacksRef.current.onReady?.(),
|
|
76
|
+
onStop: (event) => callbacksRef.current.onStop?.(event),
|
|
77
|
+
}), []);
|
|
78
|
+
}
|
|
79
|
+
function usePersonaThemeColor(rive) {
|
|
80
|
+
const theme = useAgenticTheme();
|
|
81
|
+
const viewModel = useViewModel(rive, { useDefault: true });
|
|
82
|
+
const viewModelInstance = useViewModelInstance(viewModel, {
|
|
83
|
+
rive,
|
|
84
|
+
useDefault: true,
|
|
85
|
+
});
|
|
86
|
+
const color = useViewModelInstanceColor("color", viewModelInstance);
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (!color)
|
|
89
|
+
return;
|
|
90
|
+
if (theme === "light")
|
|
91
|
+
color.setRgb(24, 24, 27);
|
|
92
|
+
else
|
|
93
|
+
color.setRgb(255, 255, 255);
|
|
94
|
+
}, [color, theme]);
|
|
95
|
+
}
|
|
96
|
+
function usePersonaStateMachine(rive, state) {
|
|
97
|
+
const listeningInput = useStateMachineInput(rive, STATE_MACHINE, "listening");
|
|
98
|
+
const thinkingInput = useStateMachineInput(rive, STATE_MACHINE, "thinking");
|
|
99
|
+
const speakingInput = useStateMachineInput(rive, STATE_MACHINE, "speaking");
|
|
100
|
+
const asleepInput = useStateMachineInput(rive, STATE_MACHINE, "asleep");
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
setInputValue(listeningInput, state === "listening");
|
|
103
|
+
setInputValue(thinkingInput, state === "thinking");
|
|
104
|
+
setInputValue(speakingInput, state === "speaking");
|
|
105
|
+
setInputValue(asleepInput, state === "asleep");
|
|
106
|
+
}, [asleepInput, listeningInput, speakingInput, state, thinkingInput]);
|
|
107
|
+
}
|
|
108
|
+
function setInputValue(input, value) {
|
|
109
|
+
if (!input)
|
|
110
|
+
return;
|
|
111
|
+
input.value = value;
|
|
112
|
+
}
|
|
113
|
+
function PersonaFallback({ state }) {
|
|
114
|
+
return (_jsx("div", { "data-slot": "persona-fallback", "data-state": state, className: cn("size-24 rounded-full border border-foreground bg-background", state !== "asleep" && "ring-1 ring-foreground/20") }));
|
|
115
|
+
}
|
|
116
|
+
export { Persona };
|
|
@@ -26,9 +26,9 @@ const promptInputClassName = css({
|
|
|
26
26
|
borderWidth: "default",
|
|
27
27
|
boxShadow: "xs",
|
|
28
28
|
display: "grid",
|
|
29
|
-
gap: "
|
|
29
|
+
gap: "2",
|
|
30
30
|
outline: "none",
|
|
31
|
-
padding: "
|
|
31
|
+
padding: "2",
|
|
32
32
|
transitionProperty: "color, box-shadow",
|
|
33
33
|
width: "full",
|
|
34
34
|
"&:focus-within": {
|
|
@@ -44,6 +44,7 @@ const promptInputBodyClassName = css({
|
|
|
44
44
|
backgroundColor: "transparent",
|
|
45
45
|
borderWidth: 0,
|
|
46
46
|
boxShadow: "none",
|
|
47
|
+
flexDirection: "column",
|
|
47
48
|
minHeight: "6rem",
|
|
48
49
|
_dark: {
|
|
49
50
|
backgroundColor: "transparent",
|
|
@@ -53,8 +54,8 @@ const promptInputTextareaClassName = css({
|
|
|
53
54
|
fontSize: "sm",
|
|
54
55
|
lineHeight: "relaxed",
|
|
55
56
|
minHeight: "6rem",
|
|
56
|
-
paddingBlock: "
|
|
57
|
-
paddingInline: "
|
|
57
|
+
paddingBlock: "2",
|
|
58
|
+
paddingInline: "2",
|
|
58
59
|
"&::placeholder": {
|
|
59
60
|
color: "muted.foreground/70",
|
|
60
61
|
},
|
|
@@ -130,7 +131,7 @@ function getPromptInputFormText(form, fallback = "") {
|
|
|
130
131
|
return typeof message === "string" ? message : fallback;
|
|
131
132
|
}
|
|
132
133
|
function PromptInputBody({ className, ...props }) {
|
|
133
|
-
return (_jsx(InputGroup, { "data-slot": "prompt-input-body", className: cn(promptInputBodyClassName, className), ...props }));
|
|
134
|
+
return (_jsx(InputGroup, { "data-slot": "prompt-input-body", className: cn(promptInputBodyClassName, "items-stretch!", className), ...props }));
|
|
134
135
|
}
|
|
135
136
|
function PromptInputTextarea({ className, disabled, onKeyDown, onPaste, onValueChange, value, ...props }) {
|
|
136
137
|
const context = React.useContext(PromptInputContext);
|
|
@@ -184,7 +185,7 @@ function PromptInputFooter({ className, ...props }) {
|
|
|
184
185
|
return (_jsx("div", { "data-slot": "prompt-input-footer", className: cn("flex min-w-0 items-center justify-between gap-2 px-1", className), ...props }));
|
|
185
186
|
}
|
|
186
187
|
function PromptInputTools({ align = "block-end", className, ...props }) {
|
|
187
|
-
return (_jsx(InputGroupAddon, { align: align, "data-slot": "prompt-input-tools", className: cn("min-w-0 justify-between gap-2 px-0 pb-0", className), ...props }));
|
|
188
|
+
return (_jsx(InputGroupAddon, { align: align, "data-slot": "prompt-input-tools", className: cn("min-w-0 justify-between! gap-2 px-0 pb-0", className), ...props }));
|
|
188
189
|
}
|
|
189
190
|
function PromptInputButton({ children, className, label, size = "icon-sm", tooltip, variant = "ghost", ...props }) {
|
|
190
191
|
const button = (_jsx(InputGroupButton, { "aria-label": label ?? tooltip, "data-slot": "prompt-input-button", size: size, variant: variant, className: cn("shrink-0 text-muted-foreground", className), ...props, children: children }));
|
|
@@ -13,10 +13,10 @@ const sourcesTriggerClassName = css({
|
|
|
13
13
|
color: "card.foreground",
|
|
14
14
|
display: "flex",
|
|
15
15
|
fontSize: "sm",
|
|
16
|
-
gap: "
|
|
16
|
+
gap: "3",
|
|
17
17
|
justifyContent: "space-between",
|
|
18
|
-
paddingBlock: "
|
|
19
|
-
paddingInline: "
|
|
18
|
+
paddingBlock: "2",
|
|
19
|
+
paddingInline: "3",
|
|
20
20
|
transitionProperty: "color, background-color",
|
|
21
21
|
width: "full",
|
|
22
22
|
"&:hover": {
|
|
@@ -31,7 +31,7 @@ const sourcesTriggerClassName = css({
|
|
|
31
31
|
const sourcesTriggerLabelClassName = css({
|
|
32
32
|
alignItems: "center",
|
|
33
33
|
display: "flex",
|
|
34
|
-
gap: "
|
|
34
|
+
gap: "2",
|
|
35
35
|
minWidth: 0,
|
|
36
36
|
});
|
|
37
37
|
const sourcesIconClassName = css({
|
|
@@ -57,8 +57,8 @@ const sourcesChevronClassName = css({
|
|
|
57
57
|
});
|
|
58
58
|
const sourcesContentClassName = css({
|
|
59
59
|
display: "grid",
|
|
60
|
-
gap: "
|
|
61
|
-
marginTop: "
|
|
60
|
+
gap: "2",
|
|
61
|
+
marginTop: "2",
|
|
62
62
|
overflow: "hidden",
|
|
63
63
|
"&[data-state='closed']": {
|
|
64
64
|
animationName: "fade-out",
|
|
@@ -74,10 +74,10 @@ const sourceClassName = css({
|
|
|
74
74
|
color: "foreground",
|
|
75
75
|
display: "flex",
|
|
76
76
|
fontSize: "sm",
|
|
77
|
-
gap: "
|
|
77
|
+
gap: "2",
|
|
78
78
|
minWidth: 0,
|
|
79
|
-
paddingBlock: "
|
|
80
|
-
paddingInline: "
|
|
79
|
+
paddingBlock: "2",
|
|
80
|
+
paddingInline: "3",
|
|
81
81
|
transitionProperty: "color, background-color",
|
|
82
82
|
"&:hover": {
|
|
83
83
|
backgroundColor: "accent",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { AgenticSpeechStatus } from "@ciridae/ui-agent/types";
|
|
3
|
+
import { Button } from "@ciridae/ui/button";
|
|
4
|
+
type SpeechInputProps = React.ComponentProps<"div"> & {
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
onStart?: () => void;
|
|
7
|
+
onStop?: () => void;
|
|
8
|
+
status?: AgenticSpeechStatus;
|
|
9
|
+
};
|
|
10
|
+
type SpeechInputButtonProps = React.ComponentProps<typeof Button> & {
|
|
11
|
+
status?: AgenticSpeechStatus;
|
|
12
|
+
};
|
|
13
|
+
type SpeechInputStatusProps = React.ComponentProps<"p"> & {
|
|
14
|
+
status?: AgenticSpeechStatus;
|
|
15
|
+
};
|
|
16
|
+
type SpeechInputWaveformProps = React.ComponentProps<"div"> & {
|
|
17
|
+
active?: boolean;
|
|
18
|
+
};
|
|
19
|
+
declare function SpeechInput({ children, className, disabled, onStart, onStop, status, ...props }: SpeechInputProps): React.JSX.Element;
|
|
20
|
+
declare function SpeechInputButton({ children, className, status, type, ...props }: SpeechInputButtonProps): React.JSX.Element;
|
|
21
|
+
declare function SpeechInputStatus({ className, status, ...props }: SpeechInputStatusProps): React.JSX.Element;
|
|
22
|
+
declare function SpeechInputWaveform({ active, className, ...props }: SpeechInputWaveformProps): React.JSX.Element;
|
|
23
|
+
export { SpeechInput, SpeechInputButton, SpeechInputStatus, SpeechInputWaveform };
|
|
24
|
+
export type { SpeechInputButtonProps, SpeechInputProps, SpeechInputStatusProps, SpeechInputWaveformProps, };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { AudioLinesIcon, MicIcon, SquareIcon } from "lucide-react";
|
|
3
|
+
import { Button } from "@ciridae/ui/button";
|
|
4
|
+
import { cn } from "@ciridae/ui/utils";
|
|
5
|
+
function SpeechInput({ children, className, disabled, onStart, onStop, status = "idle", ...props }) {
|
|
6
|
+
const active = status === "listening" || status === "processing" || status === "speaking";
|
|
7
|
+
return (_jsx("div", { "data-slot": "speech-input", "data-status": status, className: cn("flex min-w-0 items-center gap-3 rounded-lg border bg-card p-3", "data-[status=error]:border-destructive/40 data-[status=error]:bg-destructive/5", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(SpeechInputButton, { disabled: disabled, onClick: active ? onStop : onStart, status: status }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(SpeechInputStatus, { status: status }), _jsx(SpeechInputWaveform, { active: active })] })] })) }));
|
|
8
|
+
}
|
|
9
|
+
function SpeechInputButton({ children, className, status = "idle", type = "button", ...props }) {
|
|
10
|
+
const active = status === "listening" || status === "processing" || status === "speaking";
|
|
11
|
+
const Icon = active ? SquareIcon : MicIcon;
|
|
12
|
+
return (_jsx(Button, { "aria-label": active ? "Stop speech input" : "Start speech input", "data-slot": "speech-input-button", size: "icon", type: type, variant: active ? "default" : "outline", className: cn("size-10 shrink-0 rounded-full", className), ...props, children: children ?? _jsx(Icon, { "aria-hidden": "true", className: "size-4" }) }));
|
|
13
|
+
}
|
|
14
|
+
function SpeechInputStatus({ className, status = "idle", ...props }) {
|
|
15
|
+
return (_jsx("p", { "data-slot": "speech-input-status", className: cn("truncate text-sm font-medium", className), ...props, children: getSpeechInputLabel(status) }));
|
|
16
|
+
}
|
|
17
|
+
function SpeechInputWaveform({ active, className, ...props }) {
|
|
18
|
+
return (_jsxs("div", { "aria-hidden": "true", "data-active": active ? "true" : undefined, "data-slot": "speech-input-waveform", className: cn("mt-2 flex h-4 items-center gap-1", className), ...props, children: [[0.3, 0.55, 0.85, 0.45, 0.7, 0.4, 0.6].map((scale, index) => (_jsx("span", { className: "h-full w-1 rounded-full bg-muted-foreground/30 data-[active=true]:bg-primary/70", "data-active": active ? "true" : undefined, style: { transform: `scaleY(${active ? scale : 0.28})` } }, index))), _jsx(AudioLinesIcon, { className: "ml-1 size-3.5 text-muted-foreground" })] }));
|
|
19
|
+
}
|
|
20
|
+
function getSpeechInputLabel(status) {
|
|
21
|
+
const labels = {
|
|
22
|
+
error: "Voice input needs attention",
|
|
23
|
+
idle: "Ready for voice input",
|
|
24
|
+
listening: "Listening",
|
|
25
|
+
processing: "Processing speech",
|
|
26
|
+
speaking: "Speaking response",
|
|
27
|
+
};
|
|
28
|
+
return labels[status];
|
|
29
|
+
}
|
|
30
|
+
export { SpeechInput, SpeechInputButton, SpeechInputStatus, SpeechInputWaveform };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { Button } from "@ciridae/ui/button";
|
|
3
|
+
import { Collapsible, CollapsibleContent } from "@ciridae/ui/collapsible";
|
|
4
|
+
type StackTraceProps = React.ComponentProps<typeof Collapsible> & {
|
|
5
|
+
stack: string;
|
|
6
|
+
};
|
|
7
|
+
type StackTraceHeaderProps = React.ComponentProps<"div">;
|
|
8
|
+
type StackTraceErrorProps = React.ComponentProps<"div">;
|
|
9
|
+
type StackTraceErrorTypeProps = React.ComponentProps<"span">;
|
|
10
|
+
type StackTraceErrorMessageProps = React.ComponentProps<"span">;
|
|
11
|
+
type StackTraceActionsProps = React.ComponentProps<"div">;
|
|
12
|
+
type StackTraceCopyButtonProps = React.ComponentProps<typeof Button>;
|
|
13
|
+
type StackTraceExpandButtonProps = React.ComponentProps<typeof Button>;
|
|
14
|
+
type StackTraceContentProps = React.ComponentProps<typeof CollapsibleContent>;
|
|
15
|
+
type StackTraceFramesProps = React.ComponentProps<"div">;
|
|
16
|
+
declare function StackTrace({ children, className, defaultOpen, stack, ...props }: StackTraceProps): React.JSX.Element;
|
|
17
|
+
declare function StackTraceHeader({ children, className, ...props }: StackTraceHeaderProps): React.JSX.Element;
|
|
18
|
+
declare function StackTraceError({ className, ...props }: StackTraceErrorProps): React.JSX.Element;
|
|
19
|
+
declare function StackTraceErrorType({ className, ...props }: StackTraceErrorTypeProps): React.JSX.Element;
|
|
20
|
+
declare function StackTraceErrorMessage({ className, ...props }: StackTraceErrorMessageProps): React.JSX.Element;
|
|
21
|
+
declare function StackTraceActions({ className, ...props }: StackTraceActionsProps): React.JSX.Element;
|
|
22
|
+
declare function StackTraceCopyButton({ children, ...props }: StackTraceCopyButtonProps): React.JSX.Element;
|
|
23
|
+
declare function StackTraceExpandButton({ children, className, ...props }: StackTraceExpandButtonProps): React.JSX.Element;
|
|
24
|
+
declare function StackTraceContent({ className, ...props }: StackTraceContentProps): React.JSX.Element;
|
|
25
|
+
declare function StackTraceFrames({ className, ...props }: StackTraceFramesProps): React.JSX.Element;
|
|
26
|
+
export { StackTrace, StackTraceActions, StackTraceContent, StackTraceCopyButton, StackTraceError, StackTraceErrorMessage, StackTraceErrorType, StackTraceExpandButton, StackTraceFrames, StackTraceHeader, };
|
|
27
|
+
export type { StackTraceActionsProps, StackTraceContentProps, StackTraceCopyButtonProps, StackTraceErrorMessageProps, StackTraceErrorProps, StackTraceErrorTypeProps, StackTraceExpandButtonProps, StackTraceFramesProps, StackTraceHeaderProps, StackTraceProps, };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CheckIcon, ChevronDownIcon, CopyIcon } from "lucide-react";
|
|
3
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
4
|
+
import { Button } from "@ciridae/ui/button";
|
|
5
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@ciridae/ui/collapsible";
|
|
6
|
+
import { cn } from "@ciridae/ui/utils";
|
|
7
|
+
import { copyToClipboard } from "./clipboard";
|
|
8
|
+
const StackTraceContext = createContext(null);
|
|
9
|
+
function useStackTrace() {
|
|
10
|
+
const context = useContext(StackTraceContext);
|
|
11
|
+
if (!context)
|
|
12
|
+
throw new Error("StackTrace components must be used within StackTrace");
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function StackTrace({ children, className, defaultOpen = true, stack, ...props }) {
|
|
16
|
+
const frames = useMemo(() => parseStackFrames(stack), [stack]);
|
|
17
|
+
const contextValue = useMemo(() => ({ frames, stack }), [frames, stack]);
|
|
18
|
+
return (_jsx(StackTraceContext.Provider, { value: contextValue, children: _jsx(Collapsible, { "data-slot": "stack-trace", className: cn("w-full overflow-hidden rounded-lg border bg-card text-card-foreground", className), defaultOpen: defaultOpen, ...props, children: children }) }));
|
|
19
|
+
}
|
|
20
|
+
function StackTraceHeader({ children, className, ...props }) {
|
|
21
|
+
return (_jsx("div", { "data-slot": "stack-trace-header", className: cn("flex w-full items-center justify-between gap-3 border-b px-3 py-2 text-left", className), ...props, children: children }));
|
|
22
|
+
}
|
|
23
|
+
function StackTraceError({ className, ...props }) {
|
|
24
|
+
return (_jsx("div", { "data-slot": "stack-trace-error", className: cn("min-w-0 flex-1 truncate text-sm", className), ...props }));
|
|
25
|
+
}
|
|
26
|
+
function StackTraceErrorType({ className, ...props }) {
|
|
27
|
+
return (_jsx("span", { "data-slot": "stack-trace-error-type", className: cn("font-medium text-destructive", className), ...props }));
|
|
28
|
+
}
|
|
29
|
+
function StackTraceErrorMessage({ className, ...props }) {
|
|
30
|
+
return (_jsx("span", { "data-slot": "stack-trace-error-message", className: cn("text-muted-foreground", className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
function StackTraceActions({ className, ...props }) {
|
|
33
|
+
return (_jsx("div", { "data-slot": "stack-trace-actions", className: cn("flex shrink-0 items-center gap-1", className), ...props }));
|
|
34
|
+
}
|
|
35
|
+
function StackTraceCopyButton({ children, ...props }) {
|
|
36
|
+
const { stack } = useStackTrace();
|
|
37
|
+
const [copied, setCopied] = useState(false);
|
|
38
|
+
const Icon = copied ? CheckIcon : CopyIcon;
|
|
39
|
+
return (_jsx(Button, { "aria-label": copied ? "Copied" : "Copy stack trace", size: "icon", type: "button", variant: "ghost", ...props, onClick: (event) => {
|
|
40
|
+
props.onClick?.(event);
|
|
41
|
+
if (!event.defaultPrevented)
|
|
42
|
+
void copyToClipboard(stack, setCopied);
|
|
43
|
+
}, children: children ?? _jsx(Icon, { "aria-hidden": "true", className: "size-4" }) }));
|
|
44
|
+
}
|
|
45
|
+
function StackTraceExpandButton({ children, className, ...props }) {
|
|
46
|
+
return (_jsx(CollapsibleTrigger, { asChild: true, children: _jsx(Button, { "aria-label": "Toggle stack trace", "data-slot": "stack-trace-expand-button", size: "icon", type: "button", variant: "ghost", ...props, className: cn("group/stack-trace-toggle shrink-0", className), children: children ?? (_jsx(ChevronDownIcon, { "aria-hidden": "true", className: "size-4 transition-transform group-data-[state=open]/stack-trace-toggle:rotate-180" })) }) }));
|
|
47
|
+
}
|
|
48
|
+
function StackTraceContent({ className, ...props }) {
|
|
49
|
+
return (_jsx(CollapsibleContent, { "data-slot": "stack-trace-content", className: cn("p-3", className), ...props }));
|
|
50
|
+
}
|
|
51
|
+
function StackTraceFrames({ className, ...props }) {
|
|
52
|
+
const { frames } = useStackTrace();
|
|
53
|
+
return (_jsx("div", { "data-slot": "stack-trace-frames", className: cn("grid gap-1 font-mono text-xs", className), ...props, children: frames.map((frame) => (_jsx(StackTraceFrame, { frame: frame }, `${frame.file}:${frame.line}:${frame.column}:${frame.method}`))) }));
|
|
54
|
+
}
|
|
55
|
+
function StackTraceFrame({ frame }) {
|
|
56
|
+
return (_jsxs("div", { className: "grid min-w-0 grid-cols-[1fr_auto] gap-3 rounded-md px-2 py-1 text-muted-foreground hover:bg-muted/50", children: [_jsx("span", { className: "truncate", children: frame.method ?? frame.file }), _jsx("span", { className: "shrink-0 text-foreground", children: formatLocation(frame) })] }));
|
|
57
|
+
}
|
|
58
|
+
function parseStackFrames(stack) {
|
|
59
|
+
return stack
|
|
60
|
+
.split("\n")
|
|
61
|
+
.map(parseStackLine)
|
|
62
|
+
.filter((frame) => frame !== null);
|
|
63
|
+
}
|
|
64
|
+
function parseStackLine(line) {
|
|
65
|
+
const trimmed = line.trim().replace(/^at\s+/, "");
|
|
66
|
+
const match = /^(?:(.+?)\s+\()?(.+):(\d+):(\d+)\)?$/.exec(trimmed);
|
|
67
|
+
if (!match)
|
|
68
|
+
return null;
|
|
69
|
+
return { column: match[4], file: match[2], line: match[3], method: match[1] };
|
|
70
|
+
}
|
|
71
|
+
function formatLocation(frame) {
|
|
72
|
+
if (!frame.line)
|
|
73
|
+
return frame.file;
|
|
74
|
+
return `${frame.file}:${frame.line}${frame.column ? `:${frame.column}` : ""}`;
|
|
75
|
+
}
|
|
76
|
+
export { StackTrace, StackTraceActions, StackTraceContent, StackTraceCopyButton, StackTraceError, StackTraceErrorMessage, StackTraceErrorType, StackTraceExpandButton, StackTraceFrames, StackTraceHeader, };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { Button } from "@ciridae/ui/button";
|
|
3
|
+
import { ScrollArea } from "@ciridae/ui/scroll-area";
|
|
4
|
+
type SuggestionsProps = React.ComponentProps<typeof ScrollArea>;
|
|
5
|
+
type SuggestionProps = Omit<React.ComponentProps<typeof Button>, "onClick"> & {
|
|
6
|
+
onClick?: (suggestion: string) => void;
|
|
7
|
+
suggestion: string;
|
|
8
|
+
};
|
|
9
|
+
declare function Suggestions({ children, className, ...props }: SuggestionsProps): React.JSX.Element;
|
|
10
|
+
declare function Suggestion({ children, className, onClick, size, suggestion, type, variant, ...props }: SuggestionProps): React.JSX.Element;
|
|
11
|
+
export { Suggestion, Suggestions };
|
|
12
|
+
export type { SuggestionProps, SuggestionsProps };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { Button } from "@ciridae/ui/button";
|
|
4
|
+
import { ScrollArea } from "@ciridae/ui/scroll-area";
|
|
5
|
+
import { cn } from "@ciridae/ui/utils";
|
|
6
|
+
function Suggestions({ children, className, ...props }) {
|
|
7
|
+
return (_jsx(ScrollArea, { "data-slot": "suggestions", scrollbars: "horizontal", className: cn("w-full overflow-hidden whitespace-nowrap", className), ...props, children: _jsx("div", { className: "flex w-max min-w-full flex-nowrap items-center gap-2 px-1 py-1 pb-3", children: children }) }));
|
|
8
|
+
}
|
|
9
|
+
function Suggestion({ children, className, onClick, size = "sm", suggestion, type = "button", variant = "outline", ...props }) {
|
|
10
|
+
const handleClick = useCallback(() => {
|
|
11
|
+
onClick?.(suggestion);
|
|
12
|
+
}, [onClick, suggestion]);
|
|
13
|
+
return (_jsx(Button, { "data-slot": "suggestion", className: cn("max-w-80 shrink-0 justify-start truncate rounded-full", className), onClick: handleClick, size: size, type: type, variant: variant, ...props, children: _jsx("span", { className: "truncate", children: children ?? suggestion }) }));
|
|
14
|
+
}
|
|
15
|
+
export { Suggestion, Suggestions };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@ciridae/ui/collapsible";
|
|
3
|
+
import { Progress } from "@ciridae/ui/progress";
|
|
4
|
+
type TestStatusValue = "failed" | "passed" | "running" | "skipped";
|
|
5
|
+
type TestResultsContextValue = {
|
|
6
|
+
failed?: number;
|
|
7
|
+
passed?: number;
|
|
8
|
+
running?: number;
|
|
9
|
+
skipped?: number;
|
|
10
|
+
total?: number;
|
|
11
|
+
};
|
|
12
|
+
type TestResultsProps = React.ComponentProps<"div"> & TestResultsContextValue;
|
|
13
|
+
type TestResultsHeaderProps = React.ComponentProps<"div">;
|
|
14
|
+
type TestResultsDurationProps = React.ComponentProps<"span">;
|
|
15
|
+
type TestResultsSummaryProps = React.ComponentProps<"div">;
|
|
16
|
+
type TestResultsProgressProps = React.ComponentProps<typeof Progress>;
|
|
17
|
+
type TestResultsContentProps = React.ComponentProps<"div">;
|
|
18
|
+
type TestSuiteProps = React.ComponentProps<typeof Collapsible> & {
|
|
19
|
+
status?: TestStatusValue;
|
|
20
|
+
};
|
|
21
|
+
type TestSuiteNameProps = React.ComponentProps<typeof CollapsibleTrigger>;
|
|
22
|
+
type TestSuiteStatsProps = React.ComponentProps<"div">;
|
|
23
|
+
type TestSuiteContentProps = React.ComponentProps<typeof CollapsibleContent>;
|
|
24
|
+
type TestProps = React.ComponentProps<"div"> & {
|
|
25
|
+
status?: TestStatusValue;
|
|
26
|
+
};
|
|
27
|
+
type TestNameProps = React.ComponentProps<"span">;
|
|
28
|
+
type TestDurationProps = React.ComponentProps<"span">;
|
|
29
|
+
type TestStatusProps = React.ComponentProps<"span">;
|
|
30
|
+
type TestErrorProps = React.ComponentProps<"div">;
|
|
31
|
+
type TestErrorMessageProps = React.ComponentProps<"p">;
|
|
32
|
+
type TestErrorStackProps = React.ComponentProps<"pre">;
|
|
33
|
+
declare function TestResults({ children, className, failed, passed, running, skipped, total, ...props }: TestResultsProps): React.JSX.Element;
|
|
34
|
+
declare function TestResultsHeader({ className, ...props }: TestResultsHeaderProps): React.JSX.Element;
|
|
35
|
+
declare function TestResultsDuration({ className, ...props }: TestResultsDurationProps): React.JSX.Element;
|
|
36
|
+
declare function TestResultsSummary({ className, ...props }: TestResultsSummaryProps): React.JSX.Element;
|
|
37
|
+
declare function TestResultsProgress(props: TestResultsProgressProps): React.JSX.Element;
|
|
38
|
+
declare function TestResultsContent({ className, ...props }: TestResultsContentProps): React.JSX.Element;
|
|
39
|
+
declare function TestSuite({ children, className, defaultOpen, status, ...props }: TestSuiteProps): React.JSX.Element;
|
|
40
|
+
declare function TestSuiteName({ className, ...props }: TestSuiteNameProps): React.JSX.Element;
|
|
41
|
+
declare function TestSuiteStats({ className, ...props }: TestSuiteStatsProps): React.JSX.Element;
|
|
42
|
+
declare function TestSuiteContent({ className, ...props }: TestSuiteContentProps): React.JSX.Element;
|
|
43
|
+
declare function Test({ children, className, status, ...props }: TestProps): React.JSX.Element;
|
|
44
|
+
declare function TestName({ className, ...props }: TestNameProps): React.JSX.Element;
|
|
45
|
+
declare function TestDuration({ className, ...props }: TestDurationProps): React.JSX.Element;
|
|
46
|
+
declare function TestStatus({ className, ...props }: TestStatusProps): React.JSX.Element;
|
|
47
|
+
declare function TestError({ className, ...props }: TestErrorProps): React.JSX.Element;
|
|
48
|
+
declare function TestErrorMessage({ className, ...props }: TestErrorMessageProps): React.JSX.Element;
|
|
49
|
+
declare function TestErrorStack({ className, ...props }: TestErrorStackProps): React.JSX.Element;
|
|
50
|
+
export { Test, TestDuration, TestError, TestErrorMessage, TestErrorStack, TestName, TestResults, TestResultsContent, TestResultsDuration, TestResultsHeader, TestResultsProgress, TestResultsSummary, TestStatus, TestSuite, TestSuiteContent, TestSuiteName, TestSuiteStats, };
|
|
51
|
+
export type { TestDurationProps, TestErrorMessageProps, TestErrorProps, TestErrorStackProps, TestNameProps, TestProps, TestResultsContentProps, TestResultsDurationProps, TestResultsHeaderProps, TestResultsProgressProps, TestResultsProps, TestResultsSummaryProps, TestStatusProps, TestStatusValue, TestSuiteContentProps, TestSuiteNameProps, TestSuiteProps, TestSuiteStatsProps, };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CheckCircleIcon, CircleSlashIcon, LoaderCircleIcon, XCircleIcon } from "lucide-react";
|
|
3
|
+
import { createContext, useContext, useMemo } from "react";
|
|
4
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@ciridae/ui/collapsible";
|
|
5
|
+
import { Progress } from "@ciridae/ui/progress";
|
|
6
|
+
import { cn } from "@ciridae/ui/utils";
|
|
7
|
+
const TestResultsContext = createContext({});
|
|
8
|
+
const TestSuiteContext = createContext({ status: "passed" });
|
|
9
|
+
const TestContext = createContext({ status: "passed" });
|
|
10
|
+
function TestResults({ children, className, failed, passed, running, skipped, total, ...props }) {
|
|
11
|
+
const contextValue = useMemo(() => ({ failed, passed, running, skipped, total }), [failed, passed, running, skipped, total]);
|
|
12
|
+
return (_jsx(TestResultsContext.Provider, { value: contextValue, children: _jsx("div", { "data-slot": "test-results", className: cn("grid gap-3 rounded-lg border bg-card p-4", className), ...props, children: children }) }));
|
|
13
|
+
}
|
|
14
|
+
function TestResultsHeader({ className, ...props }) {
|
|
15
|
+
return (_jsx("div", { "data-slot": "test-results-header", className: cn("flex items-center justify-between gap-3", className), ...props }));
|
|
16
|
+
}
|
|
17
|
+
function TestResultsDuration({ className, ...props }) {
|
|
18
|
+
return (_jsx("span", { "data-slot": "test-results-duration", className: cn("font-mono text-xs text-muted-foreground", className), ...props }));
|
|
19
|
+
}
|
|
20
|
+
function TestResultsSummary({ className, ...props }) {
|
|
21
|
+
const summary = useContext(TestResultsContext);
|
|
22
|
+
return (_jsx("div", { "data-slot": "test-results-summary", className: cn("text-sm text-muted-foreground", className), ...props, children: props.children ?? formatSummary(summary) }));
|
|
23
|
+
}
|
|
24
|
+
function TestResultsProgress(props) {
|
|
25
|
+
const { passed = 0, total = 0 } = useContext(TestResultsContext);
|
|
26
|
+
const value = total > 0 ? Math.round((passed / total) * 100) : 0;
|
|
27
|
+
return _jsx(Progress, { "data-slot": "test-results-progress", value: value, ...props });
|
|
28
|
+
}
|
|
29
|
+
function TestResultsContent({ className, ...props }) {
|
|
30
|
+
return _jsx("div", { "data-slot": "test-results-content", className: cn("grid gap-2", className), ...props });
|
|
31
|
+
}
|
|
32
|
+
function TestSuite({ children, className, defaultOpen = true, status = "passed", ...props }) {
|
|
33
|
+
const contextValue = useMemo(() => ({ status }), [status]);
|
|
34
|
+
return (_jsx(TestSuiteContext.Provider, { value: contextValue, children: _jsx(Collapsible, { "data-slot": "test-suite", className: cn("rounded-md border", className), defaultOpen: defaultOpen, ...props, children: children }) }));
|
|
35
|
+
}
|
|
36
|
+
function TestSuiteName({ className, ...props }) {
|
|
37
|
+
const { status } = useContext(TestSuiteContext);
|
|
38
|
+
return (_jsxs(CollapsibleTrigger, { "data-slot": "test-suite-name", className: cn("flex w-full items-center gap-2 px-3 py-2 text-left text-sm font-medium", className), ...props, children: [_jsx(TestStatusIcon, { status: status }), props.children] }));
|
|
39
|
+
}
|
|
40
|
+
function TestSuiteStats({ className, ...props }) {
|
|
41
|
+
return (_jsx("div", { "data-slot": "test-suite-stats", className: cn("px-3 pb-2 text-xs text-muted-foreground", className), ...props }));
|
|
42
|
+
}
|
|
43
|
+
function TestSuiteContent({ className, ...props }) {
|
|
44
|
+
return (_jsx(CollapsibleContent, { "data-slot": "test-suite-content", className: cn("grid gap-1 border-t p-2", className), ...props }));
|
|
45
|
+
}
|
|
46
|
+
function Test({ children, className, status = "passed", ...props }) {
|
|
47
|
+
const contextValue = useMemo(() => ({ status }), [status]);
|
|
48
|
+
return (_jsx(TestContext.Provider, { value: contextValue, children: _jsx("div", { "data-slot": "test", className: cn("grid gap-1 rounded-md px-2 py-1 text-sm", className), ...props, children: children }) }));
|
|
49
|
+
}
|
|
50
|
+
function TestName({ className, ...props }) {
|
|
51
|
+
const { status } = useContext(TestContext);
|
|
52
|
+
return (_jsxs("span", { "data-slot": "test-name", className: cn("flex items-center gap-2", className), ...props, children: [_jsx(TestStatusIcon, { status: status }), props.children] }));
|
|
53
|
+
}
|
|
54
|
+
function TestDuration({ className, ...props }) {
|
|
55
|
+
return (_jsx("span", { "data-slot": "test-duration", className: cn("font-mono text-xs text-muted-foreground", className), ...props }));
|
|
56
|
+
}
|
|
57
|
+
function TestStatus({ className, ...props }) {
|
|
58
|
+
const { status } = useContext(TestContext);
|
|
59
|
+
return (_jsx("span", { "data-slot": "test-status", className: cn("text-meta text-muted-foreground", className), ...props, children: props.children ?? status }));
|
|
60
|
+
}
|
|
61
|
+
function TestError({ className, ...props }) {
|
|
62
|
+
return (_jsx("div", { "data-slot": "test-error", className: cn("rounded-md border p-2", className), ...props }));
|
|
63
|
+
}
|
|
64
|
+
function TestErrorMessage({ className, ...props }) {
|
|
65
|
+
return (_jsx("p", { "data-slot": "test-error-message", className: cn("text-sm text-destructive", className), ...props }));
|
|
66
|
+
}
|
|
67
|
+
function TestErrorStack({ className, ...props }) {
|
|
68
|
+
return (_jsx("pre", { "data-slot": "test-error-stack", className: cn("overflow-auto font-mono text-xs text-muted-foreground", className), ...props }));
|
|
69
|
+
}
|
|
70
|
+
function TestStatusIcon({ status }) {
|
|
71
|
+
const Icon = status === "passed"
|
|
72
|
+
? CheckCircleIcon
|
|
73
|
+
: status === "failed"
|
|
74
|
+
? XCircleIcon
|
|
75
|
+
: status === "running"
|
|
76
|
+
? LoaderCircleIcon
|
|
77
|
+
: CircleSlashIcon;
|
|
78
|
+
return _jsx(Icon, { "aria-hidden": "true", className: "size-4 shrink-0" });
|
|
79
|
+
}
|
|
80
|
+
function formatSummary({ failed = 0, passed = 0, skipped = 0, total = 0, }) {
|
|
81
|
+
return `${passed}/${total} passed, ${failed} failed, ${skipped} skipped`;
|
|
82
|
+
}
|
|
83
|
+
export { Test, TestDuration, TestError, TestErrorMessage, TestErrorStack, TestName, TestResults, TestResultsContent, TestResultsDuration, TestResultsHeader, TestResultsProgress, TestResultsSummary, TestStatus, TestSuite, TestSuiteContent, TestSuiteName, TestSuiteStats, };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
function useAgenticTheme() {
|
|
3
|
+
const [theme, setTheme] = useState(getAgenticTheme);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const updateTheme = () => setTheme(getAgenticTheme());
|
|
6
|
+
const observer = new MutationObserver(updateTheme);
|
|
7
|
+
observer.observe(document.documentElement, {
|
|
8
|
+
attributeFilter: ["class"],
|
|
9
|
+
attributes: true,
|
|
10
|
+
});
|
|
11
|
+
const media = window.matchMedia?.("(prefers-color-scheme: dark)");
|
|
12
|
+
media?.addEventListener("change", updateTheme);
|
|
13
|
+
return () => {
|
|
14
|
+
observer.disconnect();
|
|
15
|
+
media?.removeEventListener("change", updateTheme);
|
|
16
|
+
};
|
|
17
|
+
}, []);
|
|
18
|
+
return theme;
|
|
19
|
+
}
|
|
20
|
+
function getAgenticTheme() {
|
|
21
|
+
if (typeof window === "undefined")
|
|
22
|
+
return "light";
|
|
23
|
+
if (document.documentElement.classList.contains("light"))
|
|
24
|
+
return "light";
|
|
25
|
+
if (document.documentElement.classList.contains("dark"))
|
|
26
|
+
return "dark";
|
|
27
|
+
if (window.matchMedia?.("(prefers-color-scheme: dark)").matches)
|
|
28
|
+
return "dark";
|
|
29
|
+
return "light";
|
|
30
|
+
}
|
|
31
|
+
export { getAgenticTheme, useAgenticTheme };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { NodeToolbar } from "@xyflow/react";
|
|
3
|
+
type ToolbarProps = React.ComponentProps<typeof NodeToolbar>;
|
|
4
|
+
declare function Toolbar({ className, position, ...props }: ToolbarProps): React.JSX.Element;
|
|
5
|
+
export { Toolbar };
|
|
6
|
+
export type { ToolbarProps };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { NodeToolbar, Position } from "@xyflow/react";
|
|
3
|
+
import { cn } from "@ciridae/ui/utils";
|
|
4
|
+
function Toolbar({ className, position = Position.Top, ...props }) {
|
|
5
|
+
return (_jsx(NodeToolbar, { "data-slot": "toolbar", position: position, className: cn("flex items-center gap-1 rounded-md border bg-card p-1 shadow-xs", className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
export { Toolbar };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { AgenticTranscriptSegment } from "@ciridae/ui-agent/types";
|
|
3
|
+
type TranscriptionProps = React.ComponentProps<"div"> & {
|
|
4
|
+
segments?: AgenticTranscriptSegment[];
|
|
5
|
+
};
|
|
6
|
+
type TranscriptionSegmentProps = React.ComponentProps<"div"> & {
|
|
7
|
+
segment?: AgenticTranscriptSegment;
|
|
8
|
+
};
|
|
9
|
+
type TranscriptionSpeakerProps = React.ComponentProps<"span">;
|
|
10
|
+
type TranscriptionTextProps = React.ComponentProps<"p">;
|
|
11
|
+
type TranscriptionTimestampProps = React.ComponentProps<"span">;
|
|
12
|
+
type TranscriptionEmptyProps = React.ComponentProps<"div">;
|
|
13
|
+
declare function Transcription({ children, className, segments, ...props }: TranscriptionProps): React.JSX.Element;
|
|
14
|
+
declare function TranscriptionSegment({ children, className, segment, ...props }: TranscriptionSegmentProps): React.JSX.Element;
|
|
15
|
+
declare function TranscriptionSpeaker({ className, ...props }: TranscriptionSpeakerProps): React.JSX.Element;
|
|
16
|
+
declare function TranscriptionText({ className, ...props }: TranscriptionTextProps): React.JSX.Element;
|
|
17
|
+
declare function TranscriptionTimestamp({ className, ...props }: TranscriptionTimestampProps): React.JSX.Element;
|
|
18
|
+
declare function TranscriptionEmpty({ className, children, ...props }: TranscriptionEmptyProps): React.JSX.Element;
|
|
19
|
+
export { Transcription, TranscriptionEmpty, TranscriptionSegment, TranscriptionSpeaker, TranscriptionText, TranscriptionTimestamp, };
|
|
20
|
+
export type { TranscriptionEmptyProps, TranscriptionProps, TranscriptionSegmentProps, TranscriptionSpeakerProps, TranscriptionTextProps, TranscriptionTimestampProps, };
|