agent ui components

This commit is contained in:
AI Christianson 2025-03-13 18:25:21 -04:00
parent a9c7f92687
commit 1ced6ece4c
41 changed files with 3263 additions and 278 deletions

2
.gitignore vendored
View File

@ -17,3 +17,5 @@ appmap.log
/vsc/node_modules
/vsc/dist
node_modules/
/frontend/common/dist
/frontend/web/dist/

View File

@ -1,4 +1,7 @@
export * from './button';
export * from './card';
export * from './collapsible';
export * from './input';
export * from './sheet';
export * from './switch';
export * from './scroll-area';

View File

@ -1,4 +1,7 @@
export * from './button';
export * from './card';
export * from './collapsible';
export * from './input';
export * from './sheet';
export * from './switch';
export * from './scroll-area';

View File

@ -1,4 +1,9 @@
import './styles/global.css';
export * from './utils';
export * from './components/ui';
export * from './components/TimelineStep';
export * from './components/TimelineFeed';
export * from './components/SessionDrawer';
export * from './components/SessionSidebar';
export declare const hello: () => void;
export { getSampleAgentSteps, getSampleAgentSessions, type AgentStep, type AgentSession } from './utils/sample-data';

View File

@ -1,10 +1,18 @@
// Entry point for @ra-aid/common package
import './styles/global.css';
// Export utility functions
// Export utility functions (excluding sample data to avoid circular references)
export * from './utils';
// Export all UI components
export * from './components/ui';
// Export timeline components
export * from './components/TimelineStep';
export * from './components/TimelineFeed';
// Export session navigation components
export * from './components/SessionDrawer';
export * from './components/SessionSidebar';
// Export the hello function (temporary example)
export const hello = () => {
console.log("Hello from @ra-aid/common");
};
// Directly export sample data functions and types to avoid circular references
export { getSampleAgentSteps, getSampleAgentSessions } from './utils/sample-data';

View File

@ -539,9 +539,85 @@ video {
color: hsl(var(--foreground));
font-feature-settings: "rlig" 1, "calt" 1;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.pointer-events-none {
pointer-events: none;
}
.fixed {
position: fixed;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.inset-0 {
inset: 0px;
}
.inset-x-0 {
left: 0px;
right: 0px;
}
.inset-y-0 {
top: 0px;
bottom: 0px;
}
.bottom-0 {
bottom: 0px;
}
.left-0 {
left: 0px;
}
.right-0 {
right: 0px;
}
.right-4 {
right: 1rem;
}
.top-0 {
top: 0px;
}
.top-4 {
top: 1rem;
}
.z-50 {
z-index: 50;
}
.mb-2 {
margin-bottom: 0.5rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.mr-2 {
margin-right: 0.5rem;
}
.mr-3 {
margin-right: 0.75rem;
}
.mt-1 {
margin-top: 0.25rem;
}
.mt-1\.5 {
margin-top: 0.375rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.mt-6 {
margin-top: 1.5rem;
}
.block {
display: block;
}
@ -551,9 +627,18 @@ video {
.inline-flex {
display: inline-flex;
}
.hidden {
display: none;
}
.h-10 {
height: 2.5rem;
}
.h-2\.5 {
height: 0.625rem;
}
.h-3 {
height: 0.75rem;
}
.h-4 {
height: 1rem;
}
@ -566,44 +651,142 @@ video {
.h-9 {
height: 2.25rem;
}
.h-\[calc\(100vh-5rem\)\] {
height: calc(100vh - 5rem);
}
.h-full {
height: 100%;
}
.h-screen {
height: 100vh;
}
.w-2\.5 {
width: 0.625rem;
}
.w-3 {
width: 0.75rem;
}
.w-3\/4 {
width: 75%;
}
.w-4 {
width: 1rem;
}
.w-5 {
width: 1.25rem;
}
.w-9 {
width: 2.25rem;
}
.w-\[250px\] {
width: 250px;
}
.w-\[85\%\] {
width: 85%;
}
.w-full {
width: 100%;
}
.min-w-0 {
min-width: 0px;
}
.max-w-xs {
max-width: 20rem;
}
.flex-1 {
flex: 1 1 0%;
}
.flex-shrink-0 {
flex-shrink: 0;
}
.shrink-0 {
flex-shrink: 0;
}
.cursor-pointer {
cursor: pointer;
}
.touch-none {
touch-action: none;
}
.select-none {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.flex-col {
flex-direction: column;
}
.flex-col-reverse {
flex-direction: column-reverse;
}
.items-start {
align-items: flex-start;
}
.items-end {
align-items: flex-end;
}
.items-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.justify-between {
justify-content: space-between;
}
.gap-2 {
gap: 0.5rem;
}
.gap-4 {
gap: 1rem;
}
.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
}
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
}
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
}
.overflow-hidden {
overflow: hidden;
}
.overflow-x-auto {
overflow-x: auto;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.whitespace-nowrap {
white-space: nowrap;
}
.whitespace-pre-wrap {
white-space: pre-wrap;
}
.rounded {
border-radius: 0.25rem;
}
.rounded-\[inherit\] {
border-radius: inherit;
}
.rounded-full {
border-radius: 9999px;
}
.rounded-md {
border-radius: calc(var(--radius) - 2px);
}
.rounded-sm {
border-radius: calc(var(--radius) - 4px);
}
.rounded-xl {
border-radius: 0.75rem;
}
@ -613,30 +796,96 @@ video {
.border-2 {
border-width: 2px;
}
.border-b {
border-bottom-width: 1px;
}
.border-l {
border-left-width: 1px;
}
.border-r {
border-right-width: 1px;
}
.border-t {
border-top-width: 1px;
}
.border-border {
border-color: hsl(var(--border));
}
.border-input {
border-color: hsl(var(--input));
}
.border-transparent {
border-color: transparent;
}
.border-l-transparent {
border-left-color: transparent;
}
.border-t-transparent {
border-top-color: transparent;
}
.bg-accent {
background-color: hsl(var(--accent));
}
.bg-background {
background-color: hsl(var(--background));
}
.bg-background\/80 {
background-color: hsl(var(--background) / 0.8);
}
.bg-blue-500 {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
}
.bg-border {
background-color: hsl(var(--border));
}
.bg-card {
background-color: hsl(var(--card));
}
.bg-destructive {
background-color: hsl(var(--destructive));
}
.bg-gray-500 {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity, 1));
}
.bg-green-500 {
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
}
.bg-primary {
background-color: hsl(var(--primary));
}
.bg-red-500 {
--tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
}
.bg-secondary {
background-color: hsl(var(--secondary));
}
.bg-secondary\/50 {
background-color: hsl(var(--secondary) / 0.5);
}
.bg-yellow-500 {
--tw-bg-opacity: 1;
background-color: rgb(234 179 8 / var(--tw-bg-opacity, 1));
}
.p-3 {
padding: 0.75rem;
}
.p-4 {
padding: 1rem;
}
.p-6 {
padding: 1.5rem;
}
.p-\[1px\] {
padding: 1px;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-3 {
padding-left: 0.75rem;
padding-right: 0.75rem;
@ -657,9 +906,29 @@ video {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.py-8 {
padding-top: 2rem;
padding-bottom: 2rem;
}
.pb-2 {
padding-bottom: 0.5rem;
}
.pt-0 {
padding-top: 0px;
}
.pt-3 {
padding-top: 0.75rem;
}
.text-left {
text-align: left;
}
.text-center {
text-align: center;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
@ -674,6 +943,9 @@ video {
.font-semibold {
font-weight: 600;
}
.capitalize {
text-transform: capitalize;
}
.leading-none {
line-height: 1;
}
@ -686,6 +958,9 @@ video {
.text-destructive-foreground {
color: hsl(var(--destructive-foreground));
}
.text-foreground {
color: hsl(var(--foreground));
}
.text-muted-foreground {
color: hsl(var(--muted-foreground));
}
@ -701,6 +976,9 @@ video {
.underline-offset-4 {
text-underline-offset: 4px;
}
.opacity-70 {
opacity: 0.7;
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@ -724,16 +1002,50 @@ video {
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-offset-background {
--tw-ring-offset-color: hsl(var(--background));
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-blur-sm {
--tw-backdrop-blur: blur(4px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-all {
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-colors {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-opacity {
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.transition-transform {
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-200 {
transition-duration: 200ms;
}
.ease-in-out {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes enter {
from {
@ -748,6 +1060,12 @@ video {
transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0));
}
}
.duration-200 {
animation-duration: 200ms;
}
.ease-in-out {
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.file\:border-0::file-selector-button {
border-width: 0px;
}
@ -770,6 +1088,9 @@ video {
.hover\:bg-accent:hover {
background-color: hsl(var(--accent));
}
.hover\:bg-accent\/50:hover {
background-color: hsl(var(--accent) / 0.5);
}
.hover\:bg-destructive\/90:hover {
background-color: hsl(var(--destructive) / 0.9);
}
@ -785,6 +1106,24 @@ video {
.hover\:underline:hover {
text-decoration-line: underline;
}
.hover\:opacity-100:hover {
opacity: 1;
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
}
.focus\:ring-2:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus\:ring-ring:focus {
--tw-ring-color: hsl(var(--ring));
}
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
}
.focus-visible\:outline-none:focus-visible {
outline: 2px solid transparent;
outline-offset: 2px;
@ -825,9 +1164,142 @@ video {
--tw-translate-x: 0px;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
.data-\[state\=closed\]\:animate-accordion-up[data-state="closed"] {
animation: accordion-up 0.2s ease-out;
}
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
.data-\[state\=open\]\:animate-accordion-down[data-state="open"] {
animation: accordion-down 0.2s ease-out;
}
.data-\[state\=checked\]\:bg-primary[data-state="checked"] {
background-color: hsl(var(--primary));
}
.data-\[state\=open\]\:bg-secondary[data-state="open"] {
background-color: hsl(var(--secondary));
}
.data-\[state\=unchecked\]\:bg-input[data-state="unchecked"] {
background-color: hsl(var(--input));
}
.data-\[state\=closed\]\:duration-300[data-state="closed"] {
transition-duration: 300ms;
}
.data-\[state\=open\]\:duration-500[data-state="open"] {
transition-duration: 500ms;
}
.data-\[state\=open\]\:animate-in[data-state="open"] {
animation-name: enter;
animation-duration: 150ms;
--tw-enter-opacity: initial;
--tw-enter-scale: initial;
--tw-enter-rotate: initial;
--tw-enter-translate-x: initial;
--tw-enter-translate-y: initial;
}
.data-\[state\=closed\]\:animate-out[data-state="closed"] {
animation-name: exit;
animation-duration: 150ms;
--tw-exit-opacity: initial;
--tw-exit-scale: initial;
--tw-exit-rotate: initial;
--tw-exit-translate-x: initial;
--tw-exit-translate-y: initial;
}
.data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
--tw-exit-opacity: 0;
}
.data-\[state\=open\]\:fade-in-0[data-state="open"] {
--tw-enter-opacity: 0;
}
.data-\[state\=closed\]\:slide-out-to-bottom[data-state="closed"] {
--tw-exit-translate-y: 100%;
}
.data-\[state\=closed\]\:slide-out-to-left[data-state="closed"] {
--tw-exit-translate-x: -100%;
}
.data-\[state\=closed\]\:slide-out-to-right[data-state="closed"] {
--tw-exit-translate-x: 100%;
}
.data-\[state\=closed\]\:slide-out-to-top[data-state="closed"] {
--tw-exit-translate-y: -100%;
}
.data-\[state\=open\]\:slide-in-from-bottom[data-state="open"] {
--tw-enter-translate-y: 100%;
}
.data-\[state\=open\]\:slide-in-from-left[data-state="open"] {
--tw-enter-translate-x: -100%;
}
.data-\[state\=open\]\:slide-in-from-right[data-state="open"] {
--tw-enter-translate-x: 100%;
}
.data-\[state\=open\]\:slide-in-from-top[data-state="open"] {
--tw-enter-translate-y: -100%;
}
.data-\[state\=closed\]\:duration-300[data-state="closed"] {
animation-duration: 300ms;
}
.data-\[state\=open\]\:duration-500[data-state="open"] {
animation-duration: 500ms;
}
@media (min-width: 640px) {
.sm\:max-w-md {
max-width: 28rem;
}
.sm\:max-w-sm {
max-width: 24rem;
}
.sm\:flex-row {
flex-direction: row;
}
.sm\:justify-end {
justify-content: flex-end;
}
.sm\:space-x-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
}
.sm\:text-left {
text-align: left;
}
}
@media (min-width: 768px) {
.md\:block {
display: block;
}
.md\:hidden {
display: none;
}
}
@media (min-width: 1024px) {
.lg\:w-\[300px\] {
width: 300px;
}
}

View File

@ -4,3 +4,4 @@ import { type ClassValue } from "clsx";
* Combines clsx for conditional logic and tailwind-merge for handling conflicting tailwind classes
*/
export declare function cn(...inputs: ClassValue[]): string;
export * from './utils';

View File

@ -7,3 +7,5 @@ import { twMerge } from "tailwind-merge";
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
// Re-export everything from utils directory
export * from './utils';

View File

@ -9,9 +9,11 @@
"dev": "concurrently \"tsc --watch\" \"postcss src/styles/global.css -o dist/styles/global.css --watch\""
},
"dependencies": {
"@radix-ui/react-collapsible": "^1.1.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.1.3",

View File

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionDrawer = void 0;
var react_1 = require("react");
var lucide_react_1 = require("lucide-react");
var sheet_1 = require("./ui/sheet");
var button_1 = require("./ui/button");
var scroll_area_1 = require("./ui/scroll-area");
var sample_data_1 = require("../utils/sample-data");
var SessionDrawer = function (_a) {
var onSelectSession = _a.onSelectSession, currentSessionId = _a.currentSessionId, _b = _a.sessions, sessions = _b === void 0 ? (0, sample_data_1.getSampleAgentSessions)() : _b;
// Get status color
var getStatusColor = function (status) {
switch (status) {
case 'active':
return 'bg-blue-500';
case 'completed':
return 'bg-green-500';
case 'error':
return 'bg-red-500';
default:
return 'bg-gray-500';
}
};
// Format timestamp
var formatDate = function (date) {
return date.toLocaleDateString([], {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
return (<sheet_1.Sheet>
<sheet_1.SheetTrigger asChild>
<button_1.Button variant="ghost" size="icon" className="md:hidden">
<lucide_react_1.Menu className="h-5 w-5"/>
<span className="sr-only">Toggle navigation</span>
</button_1.Button>
</sheet_1.SheetTrigger>
<sheet_1.SheetContent side="left" className="w-[85%] sm:max-w-md">
<sheet_1.SheetHeader>
<sheet_1.SheetTitle>Sessions</sheet_1.SheetTitle>
</sheet_1.SheetHeader>
<scroll_area_1.ScrollArea className="h-[calc(100vh-5rem)] mt-6">
<div className="space-y-4">
{sessions.map(function (session) { return (<sheet_1.SheetClose key={session.id} asChild>
<button onClick={function () { return onSelectSession === null || onSelectSession === void 0 ? void 0 : onSelectSession(session.id); }} className={"w-full flex items-start p-3 text-left rounded-md transition-colors hover:bg-accent/50 ".concat(currentSessionId === session.id ? 'bg-accent' : '')}>
<div className={"w-3 h-3 rounded-full ".concat(getStatusColor(session.status), " mt-1.5 mr-3 flex-shrink-0")}/>
<div className="flex-1 min-w-0">
<div className="font-medium truncate">{session.name}</div>
<div className="text-xs text-muted-foreground mt-1">
{session.steps.length} steps {formatDate(session.updated)}
</div>
<div className="text-xs text-muted-foreground mt-1">
<span className="capitalize">{session.status}</span>
</div>
</div>
</button>
</sheet_1.SheetClose>); })}
</div>
</scroll_area_1.ScrollArea>
</sheet_1.SheetContent>
</sheet_1.Sheet>);
};
exports.SessionDrawer = SessionDrawer;

View File

@ -0,0 +1,90 @@
import React from 'react';
import { Menu } from 'lucide-react';
import {
Sheet,
SheetTrigger,
SheetContent,
SheetHeader,
SheetTitle,
SheetClose
} from './ui/sheet';
import { Button } from './ui/button';
import { ScrollArea } from './ui/scroll-area';
import { AgentSession, getSampleAgentSessions } from '../utils/sample-data';
interface SessionDrawerProps {
onSelectSession?: (sessionId: string) => void;
currentSessionId?: string;
sessions?: AgentSession[];
}
export const SessionDrawer: React.FC<SessionDrawerProps> = ({
onSelectSession,
currentSessionId,
sessions = getSampleAgentSessions()
}) => {
// Get status color
const getStatusColor = (status: string) => {
switch (status) {
case 'active':
return 'bg-blue-500';
case 'completed':
return 'bg-green-500';
case 'error':
return 'bg-red-500';
default:
return 'bg-gray-500';
}
};
// Format timestamp
const formatDate = (date: Date) => {
return date.toLocaleDateString([], {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle navigation</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="w-[85%] sm:max-w-md">
<SheetHeader>
<SheetTitle>Sessions</SheetTitle>
</SheetHeader>
<ScrollArea className="h-[calc(100vh-5rem)] mt-6">
<div className="space-y-4">
{sessions.map((session) => (
<SheetClose key={session.id} asChild>
<button
onClick={() => onSelectSession?.(session.id)}
className={`w-full flex items-start p-3 text-left rounded-md transition-colors hover:bg-accent/50 ${
currentSessionId === session.id ? 'bg-accent' : ''
}`}
>
<div className={`w-3 h-3 rounded-full ${getStatusColor(session.status)} mt-1.5 mr-3 flex-shrink-0`} />
<div className="flex-1 min-w-0">
<div className="font-medium truncate">{session.name}</div>
<div className="text-xs text-muted-foreground mt-1">
{session.steps.length} steps {formatDate(session.updated)}
</div>
<div className="text-xs text-muted-foreground mt-1">
<span className="capitalize">{session.status}</span>
</div>
</div>
</button>
</SheetClose>
))}
</div>
</ScrollArea>
</SheetContent>
</Sheet>
);
};

View File

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionSidebar = void 0;
var react_1 = require("react");
var scroll_area_1 = require("./ui/scroll-area");
var sample_data_1 = require("../utils/sample-data");
var SessionSidebar = function (_a) {
var onSelectSession = _a.onSelectSession, currentSessionId = _a.currentSessionId, _b = _a.sessions, sessions = _b === void 0 ? (0, sample_data_1.getSampleAgentSessions)() : _b, _c = _a.className, className = _c === void 0 ? '' : _c;
// Get status color
var getStatusColor = function (status) {
switch (status) {
case 'active':
return 'bg-blue-500';
case 'completed':
return 'bg-green-500';
case 'error':
return 'bg-red-500';
default:
return 'bg-gray-500';
}
};
// Format timestamp
var formatDate = function (date) {
return date.toLocaleDateString([], {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
return (<div className={"hidden md:block w-[250px] lg:w-[300px] h-screen border-r border-border ".concat(className)}>
<div className="p-4 border-b border-border">
<h3 className="font-medium text-lg">Sessions</h3>
</div>
<scroll_area_1.ScrollArea className="h-[calc(100vh-5rem)]">
<div className="p-4 space-y-4">
{sessions.map(function (session) { return (<button key={session.id} onClick={function () { return onSelectSession === null || onSelectSession === void 0 ? void 0 : onSelectSession(session.id); }} className={"w-full flex items-start p-3 text-left rounded-md transition-colors hover:bg-accent/50 ".concat(currentSessionId === session.id ? 'bg-accent' : '')}>
<div className={"w-3 h-3 rounded-full ".concat(getStatusColor(session.status), " mt-1.5 mr-3 flex-shrink-0")}/>
<div className="flex-1 min-w-0">
<div className="font-medium truncate">{session.name}</div>
<div className="text-xs text-muted-foreground mt-1">
{session.steps.length} steps {formatDate(session.updated)}
</div>
<div className="text-xs text-muted-foreground mt-1">
<span className="capitalize">{session.status}</span>
</div>
</div>
</button>); })}
</div>
</scroll_area_1.ScrollArea>
</div>);
};
exports.SessionSidebar = SessionSidebar;

View File

@ -0,0 +1,73 @@
import React from 'react';
import { ScrollArea } from './ui/scroll-area';
import { AgentSession, getSampleAgentSessions } from '../utils/sample-data';
interface SessionSidebarProps {
onSelectSession?: (sessionId: string) => void;
currentSessionId?: string;
sessions?: AgentSession[];
className?: string;
}
export const SessionSidebar: React.FC<SessionSidebarProps> = ({
onSelectSession,
currentSessionId,
sessions = getSampleAgentSessions(),
className = ''
}) => {
// Get status color
const getStatusColor = (status: string) => {
switch (status) {
case 'active':
return 'bg-blue-500';
case 'completed':
return 'bg-green-500';
case 'error':
return 'bg-red-500';
default:
return 'bg-gray-500';
}
};
// Format timestamp
const formatDate = (date: Date) => {
return date.toLocaleDateString([], {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
return (
<div className={`hidden md:block w-[250px] lg:w-[300px] h-screen border-r border-border ${className}`}>
<div className="p-4 border-b border-border">
<h3 className="font-medium text-lg">Sessions</h3>
</div>
<ScrollArea className="h-[calc(100vh-5rem)]">
<div className="p-4 space-y-4">
{sessions.map((session) => (
<button
key={session.id}
onClick={() => onSelectSession?.(session.id)}
className={`w-full flex items-start p-3 text-left rounded-md transition-colors hover:bg-accent/50 ${
currentSessionId === session.id ? 'bg-accent' : ''
}`}
>
<div className={`w-3 h-3 rounded-full ${getStatusColor(session.status)} mt-1.5 mr-3 flex-shrink-0`} />
<div className="flex-1 min-w-0">
<div className="font-medium truncate">{session.name}</div>
<div className="text-xs text-muted-foreground mt-1">
{session.steps.length} steps {formatDate(session.updated)}
</div>
<div className="text-xs text-muted-foreground mt-1">
<span className="capitalize">{session.status}</span>
</div>
</div>
</button>
))}
</div>
</ScrollArea>
</div>
);
};

View File

@ -0,0 +1,103 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimelineFeed = void 0;
var react_1 = require("react");
var scroll_area_1 = require("./ui/scroll-area");
var TimelineStep_1 = require("./TimelineStep");
var TimelineFeed = function (_a) {
var steps = _a.steps, _b = _a.maxHeight, maxHeight = _b === void 0 ? '500px' : _b, filter = _a.filter, _c = _a.sortOrder, sortOrder = _c === void 0 ? 'desc' : _c;
// State for filtered and sorted steps
var _d = (0, react_1.useState)(filter), activeFilter = _d[0], setActiveFilter = _d[1];
var _e = (0, react_1.useState)(sortOrder), activeSortOrder = _e[0], setActiveSortOrder = _e[1];
// Apply filters and sorting
var filteredSteps = steps.filter(function (step) {
if (!activeFilter)
return true;
var typeMatch = !activeFilter.types || activeFilter.types.length === 0 ||
activeFilter.types.includes(step.type);
var statusMatch = !activeFilter.status || activeFilter.status.length === 0 ||
activeFilter.status.includes(step.status);
return typeMatch && statusMatch;
});
// Sort steps
var sortedSteps = __spreadArray([], filteredSteps, true).sort(function (a, b) {
if (activeSortOrder === 'asc') {
return a.timestamp.getTime() - b.timestamp.getTime();
}
else {
return b.timestamp.getTime() - a.timestamp.getTime();
}
});
// Toggle sort order
var toggleSortOrder = function () {
setActiveSortOrder(function (prevOrder) { return prevOrder === 'asc' ? 'desc' : 'asc'; });
};
// Filter by type
var filterTypes = [
'all',
'tool-execution',
'thinking',
'planning',
'implementation',
'user-input'
];
var handleFilterChange = function (type) {
if (type === 'all') {
setActiveFilter(__assign(__assign({}, activeFilter), { types: [] }));
}
else {
setActiveFilter(__assign(__assign({}, activeFilter), { types: [type] }));
}
};
return (<div className="w-full border border-border rounded-md bg-background">
<div className="p-3 border-b border-border">
<div className="flex justify-between items-center mb-2">
<h3 className="font-medium">Timeline Feed</h3>
<button onClick={toggleSortOrder} className="text-xs bg-secondary hover:bg-secondary/80 text-secondary-foreground px-2 py-1 rounded">
{activeSortOrder === 'asc' ? '⬆️ Oldest first' : '⬇️ Newest first'}
</button>
</div>
<div className="flex gap-2 overflow-x-auto pb-2 text-xs">
{filterTypes.map(function (type) {
var _a;
return (<button key={type} onClick={function () { return handleFilterChange(type); }} className={"px-2 py-1 rounded whitespace-nowrap ".concat(type === 'all' && (!(activeFilter === null || activeFilter === void 0 ? void 0 : activeFilter.types) || activeFilter.types.length === 0) ||
((_a = activeFilter === null || activeFilter === void 0 ? void 0 : activeFilter.types) === null || _a === void 0 ? void 0 : _a.includes(type))
? 'bg-primary text-primary-foreground'
: 'bg-secondary/50 text-secondary-foreground hover:bg-secondary/80')}>
{type === 'all' ? 'All types' : type}
</button>);
})}
</div>
</div>
<scroll_area_1.ScrollArea className="h-full" style={{ maxHeight: maxHeight }}>
<div className="p-3">
{sortedSteps.length > 0 ? (sortedSteps.map(function (step) { return (<TimelineStep_1.TimelineStep key={step.id} step={step}/>); })) : (<div className="text-center text-muted-foreground py-8">
No steps to display
</div>)}
</div>
</scroll_area_1.ScrollArea>
</div>);
};
exports.TimelineFeed = TimelineFeed;

View File

@ -0,0 +1,123 @@
import React, { useState } from 'react';
import { ScrollArea } from './ui/scroll-area';
import { TimelineStep } from './TimelineStep';
import { AgentStep } from '../utils/sample-data';
interface TimelineFeedProps {
steps: AgentStep[];
maxHeight?: string;
filter?: {
types?: string[];
status?: string[];
};
sortOrder?: 'asc' | 'desc';
}
export const TimelineFeed: React.FC<TimelineFeedProps> = ({
steps,
maxHeight = '500px',
filter,
sortOrder = 'desc'
}) => {
// State for filtered and sorted steps
const [activeFilter, setActiveFilter] = useState(filter);
const [activeSortOrder, setActiveSortOrder] = useState<'asc' | 'desc'>(sortOrder);
// Apply filters and sorting
const filteredSteps = steps.filter(step => {
if (!activeFilter) return true;
const typeMatch = !activeFilter.types || activeFilter.types.length === 0 ||
activeFilter.types.includes(step.type);
const statusMatch = !activeFilter.status || activeFilter.status.length === 0 ||
activeFilter.status.includes(step.status);
return typeMatch && statusMatch;
});
// Sort steps
const sortedSteps = [...filteredSteps].sort((a, b) => {
if (activeSortOrder === 'asc') {
return a.timestamp.getTime() - b.timestamp.getTime();
} else {
return b.timestamp.getTime() - a.timestamp.getTime();
}
});
// Toggle sort order
const toggleSortOrder = () => {
setActiveSortOrder(prevOrder => prevOrder === 'asc' ? 'desc' : 'asc');
};
// Filter by type
const filterTypes = [
'all',
'tool-execution',
'thinking',
'planning',
'implementation',
'user-input'
];
const handleFilterChange = (type: string) => {
if (type === 'all') {
setActiveFilter({
...activeFilter,
types: []
});
} else {
setActiveFilter({
...activeFilter,
types: [type]
});
}
};
return (
<div className="w-full border border-border rounded-md bg-background">
<div className="p-3 border-b border-border">
<div className="flex justify-between items-center mb-2">
<h3 className="font-medium">Timeline Feed</h3>
<button
onClick={toggleSortOrder}
className="text-xs bg-secondary hover:bg-secondary/80 text-secondary-foreground px-2 py-1 rounded"
>
{activeSortOrder === 'asc' ? '⬆️ Oldest first' : '⬇️ Newest first'}
</button>
</div>
<div className="flex gap-2 overflow-x-auto pb-2 text-xs">
{filterTypes.map(type => (
<button
key={type}
onClick={() => handleFilterChange(type)}
className={`px-2 py-1 rounded whitespace-nowrap ${
type === 'all' && (!activeFilter?.types || activeFilter.types.length === 0) ||
activeFilter?.types?.includes(type)
? 'bg-primary text-primary-foreground'
: 'bg-secondary/50 text-secondary-foreground hover:bg-secondary/80'
}`}
>
{type === 'all' ? 'All types' : type}
</button>
))}
</div>
</div>
<ScrollArea className="h-full" style={{ maxHeight }}>
<div className="p-3">
{sortedSteps.length > 0 ? (
sortedSteps.map((step) => (
<TimelineStep key={step.id} step={step} />
))
) : (
<div className="text-center text-muted-foreground py-8">
No steps to display
</div>
)}
</div>
</ScrollArea>
</div>
);
};

View File

@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimelineStep = void 0;
var react_1 = require("react");
var collapsible_1 = require("./ui/collapsible");
var TimelineStep = function (_a) {
var step = _a.step;
// Get status color
var getStatusColor = function (status) {
switch (status) {
case 'completed':
return 'bg-green-500';
case 'in-progress':
return 'bg-blue-500';
case 'error':
return 'bg-red-500';
case 'pending':
return 'bg-yellow-500';
default:
return 'bg-gray-500';
}
};
// Get icon based on step type
var getTypeIcon = function (type) {
switch (type) {
case 'tool-execution':
return '🛠️';
case 'thinking':
return '💭';
case 'planning':
return '📝';
case 'implementation':
return '💻';
case 'user-input':
return '👤';
default:
return '▶️';
}
};
// Format timestamp
var formatTime = function (timestamp) {
return timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};
return (<collapsible_1.Collapsible className="w-full mb-4 border border-border rounded-md overflow-hidden transition-all duration-200">
<collapsible_1.CollapsibleTrigger className="w-full flex items-center justify-between p-3 text-left hover:bg-accent/50 cursor-pointer">
<div className="flex items-center">
<div className={"w-3 h-3 rounded-full ".concat(getStatusColor(step.status), " mr-3")}/>
<div className="mr-2">{getTypeIcon(step.type)}</div>
<div>
<div className="font-medium">{step.title}</div>
<div className="text-sm text-muted-foreground truncate max-w-xs">
{step.type === 'tool-execution' ? 'Run tool' : step.content.substring(0, 60)}
{step.content.length > 60 ? '...' : ''}
</div>
</div>
</div>
<div className="text-xs text-muted-foreground flex flex-col items-end">
<span>{formatTime(step.timestamp)}</span>
{step.duration && (<span className="mt-1">{(step.duration / 1000).toFixed(1)}s</span>)}
</div>
</collapsible_1.CollapsibleTrigger>
<collapsible_1.CollapsibleContent>
<div className="p-4 bg-card border-t border-border">
<div className="text-sm whitespace-pre-wrap">
{step.content}
</div>
{step.duration && (<div className="mt-3 pt-3 border-t border-border">
<div className="text-xs text-muted-foreground">
Duration: {(step.duration / 1000).toFixed(1)} seconds
</div>
</div>)}
</div>
</collapsible_1.CollapsibleContent>
</collapsible_1.Collapsible>);
};
exports.TimelineStep = TimelineStep;

View File

@ -0,0 +1,86 @@
import React from 'react';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible';
import { AgentStep } from '../utils/sample-data';
interface TimelineStepProps {
step: AgentStep;
}
export const TimelineStep: React.FC<TimelineStepProps> = ({ step }) => {
// Get status color
const getStatusColor = (status: string) => {
switch (status) {
case 'completed':
return 'bg-green-500';
case 'in-progress':
return 'bg-blue-500';
case 'error':
return 'bg-red-500';
case 'pending':
return 'bg-yellow-500';
default:
return 'bg-gray-500';
}
};
// Get icon based on step type
const getTypeIcon = (type: string) => {
switch (type) {
case 'tool-execution':
return '🛠️';
case 'thinking':
return '💭';
case 'planning':
return '📝';
case 'implementation':
return '💻';
case 'user-input':
return '👤';
default:
return '▶️';
}
};
// Format timestamp
const formatTime = (timestamp: Date) => {
return timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};
return (
<Collapsible className="w-full mb-4 border border-border rounded-md overflow-hidden transition-all duration-200">
<CollapsibleTrigger className="w-full flex items-center justify-between p-3 text-left hover:bg-accent/50 cursor-pointer">
<div className="flex items-center">
<div className={`w-3 h-3 rounded-full ${getStatusColor(step.status)} mr-3`} />
<div className="mr-2">{getTypeIcon(step.type)}</div>
<div>
<div className="font-medium">{step.title}</div>
<div className="text-sm text-muted-foreground truncate max-w-xs">
{step.type === 'tool-execution' ? 'Run tool' : step.content.substring(0, 60)}
{step.content.length > 60 ? '...' : ''}
</div>
</div>
</div>
<div className="text-xs text-muted-foreground flex flex-col items-end">
<span>{formatTime(step.timestamp)}</span>
{step.duration && (
<span className="mt-1">{(step.duration / 1000).toFixed(1)}s</span>
)}
</div>
</CollapsibleTrigger>
<CollapsibleContent>
<div className="p-4 bg-card border-t border-border">
<div className="text-sm whitespace-pre-wrap">
{step.content}
</div>
{step.duration && (
<div className="mt-3 pt-3 border-t border-border">
<div className="text-xs text-muted-foreground">
Duration: {(step.duration / 1000).toFixed(1)} seconds
</div>
</div>
)}
</div>
</CollapsibleContent>
</Collapsible>
);
};

View File

@ -0,0 +1,48 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buttonVariants = exports.Button = void 0;
var React = require("react");
var react_slot_1 = require("@radix-ui/react-slot");
var class_variance_authority_1 = require("class-variance-authority");
var utils_1 = require("../../utils");
var buttonVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", {
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
});
exports.buttonVariants = buttonVariants;
var Button = React.forwardRef(function (_a, ref) {
var className = _a.className, variant = _a.variant, size = _a.size, _b = _a.asChild, asChild = _b === void 0 ? false : _b, props = __rest(_a, ["className", "variant", "size", "asChild"]);
var Comp = asChild ? react_slot_1.Slot : "button";
return (<Comp className={(0, utils_1.cn)(buttonVariants({ variant: variant, size: size, className: className }))} ref={ref} {...props}/>);
});
exports.Button = Button;
Button.displayName = "Button";

View File

@ -0,0 +1,52 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CardContent = exports.CardDescription = exports.CardTitle = exports.CardFooter = exports.CardHeader = exports.Card = void 0;
var React = require("react");
var utils_1 = require("../../utils");
var Card = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div ref={ref} className={(0, utils_1.cn)("rounded-xl border bg-card text-card-foreground shadow", className)} {...props}/>);
});
exports.Card = Card;
Card.displayName = "Card";
var CardHeader = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div ref={ref} className={(0, utils_1.cn)("flex flex-col space-y-1.5 p-6", className)} {...props}/>);
});
exports.CardHeader = CardHeader;
CardHeader.displayName = "CardHeader";
var CardTitle = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<h3 ref={ref} className={(0, utils_1.cn)("font-semibold leading-none tracking-tight", className)} {...props}/>);
});
exports.CardTitle = CardTitle;
CardTitle.displayName = "CardTitle";
var CardDescription = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<p ref={ref} className={(0, utils_1.cn)("text-sm text-muted-foreground", className)} {...props}/>);
});
exports.CardDescription = CardDescription;
CardDescription.displayName = "CardDescription";
var CardContent = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div ref={ref} className={(0, utils_1.cn)("p-6 pt-0", className)} {...props}/>);
});
exports.CardContent = CardContent;
CardContent.displayName = "CardContent";
var CardFooter = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div ref={ref} className={(0, utils_1.cn)("flex items-center p-6 pt-0", className)} {...props}/>);
});
exports.CardFooter = CardFooter;
CardFooter.displayName = "CardFooter";

View File

@ -0,0 +1,29 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CollapsibleContent = exports.CollapsibleTrigger = exports.Collapsible = void 0;
var React = require("react");
var CollapsiblePrimitive = require("@radix-ui/react-collapsible");
var utils_1 = require("../../utils");
var Collapsible = CollapsiblePrimitive.Root;
exports.Collapsible = Collapsible;
var CollapsibleTrigger = CollapsiblePrimitive.Trigger;
exports.CollapsibleTrigger = CollapsibleTrigger;
var CollapsibleContent = React.forwardRef(function (_a, ref) {
var className = _a.className, children = _a.children, props = __rest(_a, ["className", "children"]);
return (<CollapsiblePrimitive.Content ref={ref} className={(0, utils_1.cn)("overflow-hidden data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", className)} {...props}>
{children}
</CollapsiblePrimitive.Content>);
});
exports.CollapsibleContent = CollapsibleContent;
CollapsibleContent.displayName = "CollapsibleContent";

View File

@ -0,0 +1,27 @@
import * as React from "react"
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
import { cn } from "../../utils"
const Collapsible = CollapsiblePrimitive.Root
const CollapsibleTrigger = CollapsiblePrimitive.Trigger
const CollapsibleContent = React.forwardRef<
React.ElementRef<typeof CollapsiblePrimitive.Content>,
React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>
>(({ className, children, ...props }, ref) => (
<CollapsiblePrimitive.Content
ref={ref}
className={cn(
"overflow-hidden data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
className
)}
{...props}
>
{children}
</CollapsiblePrimitive.Content>
))
CollapsibleContent.displayName = "CollapsibleContent"
export { Collapsible, CollapsibleTrigger, CollapsibleContent }

View File

@ -0,0 +1,23 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./button"), exports);
__exportStar(require("./card"), exports);
__exportStar(require("./collapsible"), exports);
__exportStar(require("./input"), exports);
__exportStar(require("./sheet"), exports);
__exportStar(require("./switch"), exports);
__exportStar(require("./scroll-area"), exports);

View File

@ -1,4 +1,7 @@
export * from './button';
export * from './card';
export * from './collapsible';
export * from './input';
export * from './switch';
export * from './sheet';
export * from './switch';
export * from './scroll-area';

View File

@ -0,0 +1,22 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Input = void 0;
var React = require("react");
var utils_1 = require("../../utils");
var Input = React.forwardRef(function (_a, ref) {
var className = _a.className, type = _a.type, props = __rest(_a, ["className", "type"]);
return (<input type={type} className={(0, utils_1.cn)("flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", className)} ref={ref} {...props}/>);
});
exports.Input = Input;
Input.displayName = "Input";

View File

@ -0,0 +1,40 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScrollBar = exports.ScrollArea = void 0;
var React = require("react");
var ScrollAreaPrimitive = require("@radix-ui/react-scroll-area");
var utils_1 = require("../../utils");
var ScrollArea = React.forwardRef(function (_a, ref) {
var className = _a.className, children = _a.children, props = __rest(_a, ["className", "children"]);
return (<ScrollAreaPrimitive.Root ref={ref} className={(0, utils_1.cn)("relative overflow-hidden", className)} {...props}>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollBar orientation="horizontal"/>
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>);
});
exports.ScrollArea = ScrollArea;
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
var ScrollBar = React.forwardRef(function (_a, ref) {
var className = _a.className, _b = _a.orientation, orientation = _b === void 0 ? "vertical" : _b, props = __rest(_a, ["className", "orientation"]);
return (<ScrollAreaPrimitive.ScrollAreaScrollbar ref={ref} orientation={orientation} className={(0, utils_1.cn)("flex touch-none select-none transition-colors", orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]", orientation === "horizontal" &&
"h-2.5 border-t border-t-transparent p-[1px]", className)} {...props}>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border"/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>);
});
exports.ScrollBar = ScrollBar;
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;

View File

@ -0,0 +1,47 @@
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import { cn } from "../../utils"
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollBar orientation="horizontal" />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 border-t border-t-transparent p-[1px]",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
export { ScrollArea, ScrollBar }

View File

@ -0,0 +1,83 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SheetDescription = exports.SheetTitle = exports.SheetFooter = exports.SheetHeader = exports.SheetContent = exports.SheetClose = exports.SheetTrigger = exports.Sheet = void 0;
var React = require("react");
var SheetPrimitive = require("@radix-ui/react-dialog");
var class_variance_authority_1 = require("class-variance-authority");
var lucide_react_1 = require("lucide-react");
var utils_1 = require("../../utils");
var Sheet = SheetPrimitive.Root;
exports.Sheet = Sheet;
var SheetTrigger = SheetPrimitive.Trigger;
exports.SheetTrigger = SheetTrigger;
var SheetClose = SheetPrimitive.Close;
exports.SheetClose = SheetClose;
var SheetPortal = SheetPrimitive.Portal;
var SheetOverlay = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<SheetPrimitive.Overlay className={(0, utils_1.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className)} {...props} ref={ref}/>);
});
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
var sheetVariants = (0, class_variance_authority_1.cva)("fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", {
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
});
var SheetContent = React.forwardRef(function (_a, ref) {
var _b = _a.side, side = _b === void 0 ? "right" : _b, className = _a.className, children = _a.children, props = __rest(_a, ["side", "className", "children"]);
return (<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content ref={ref} className={(0, utils_1.cn)(sheetVariants({ side: side }), className)} {...props}>
{children}
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<lucide_react_1.X className="h-4 w-4"/>
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>);
});
exports.SheetContent = SheetContent;
SheetContent.displayName = SheetPrimitive.Content.displayName;
var SheetHeader = function (_a) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div className={(0, utils_1.cn)("flex flex-col space-y-2 text-center sm:text-left", className)} {...props}/>);
};
exports.SheetHeader = SheetHeader;
SheetHeader.displayName = "SheetHeader";
var SheetFooter = function (_a) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<div className={(0, utils_1.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props}/>);
};
exports.SheetFooter = SheetFooter;
SheetFooter.displayName = "SheetFooter";
var SheetTitle = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<SheetPrimitive.Title ref={ref} className={(0, utils_1.cn)("text-lg font-semibold text-foreground", className)} {...props}/>);
});
exports.SheetTitle = SheetTitle;
SheetTitle.displayName = SheetPrimitive.Title.displayName;
var SheetDescription = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<SheetPrimitive.Description ref={ref} className={(0, utils_1.cn)("text-sm text-muted-foreground", className)} {...props}/>);
});
exports.SheetDescription = SheetDescription;
SheetDescription.displayName = SheetPrimitive.Description.displayName;

View File

@ -0,0 +1,134 @@
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import { cn } from "../../utils"
const Sheet = SheetPrimitive.Root
const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close
const SheetPortal = SheetPrimitive.Portal
const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
)}
{...props}
ref={ref}
/>
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
{
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
}
)
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children}
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
SheetHeader.displayName = "SheetHeader"
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
SheetFooter.displayName = "SheetFooter"
const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}

View File

@ -0,0 +1,25 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Switch = void 0;
var React = require("react");
var SwitchPrimitives = require("@radix-ui/react-switch");
var utils_1 = require("../../utils");
var Switch = React.forwardRef(function (_a, ref) {
var className = _a.className, props = __rest(_a, ["className"]);
return (<SwitchPrimitives.Root className={(0, utils_1.cn)("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", className)} {...props} ref={ref}>
<SwitchPrimitives.Thumb className={(0, utils_1.cn)("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0")}/>
</SwitchPrimitives.Root>);
});
exports.Switch = Switch;
Switch.displayName = SwitchPrimitives.Root.displayName;

View File

@ -0,0 +1,38 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.hello = exports.getSampleAgentSteps = exports.getSampleAgentSessions = void 0;
// Entry point for @ra-aid/common package
require("./styles/global.css");
// Direct imports from sample-data
var sample_data_1 = require("./utils/sample-data");
Object.defineProperty(exports, "getSampleAgentSessions", { enumerable: true, get: function () { return sample_data_1.getSampleAgentSessions; } });
Object.defineProperty(exports, "getSampleAgentSteps", { enumerable: true, get: function () { return sample_data_1.getSampleAgentSteps; } });
// Export utility functions
__exportStar(require("./utils"), exports);
// Export all UI components
__exportStar(require("./components/ui"), exports);
// Export timeline components
__exportStar(require("./components/TimelineStep"), exports);
__exportStar(require("./components/TimelineFeed"), exports);
// Export session navigation components
__exportStar(require("./components/SessionDrawer"), exports);
__exportStar(require("./components/SessionSidebar"), exports);
// Export the hello function (temporary example)
var hello = function () {
console.log("Hello from @ra-aid/common");
};
exports.hello = hello;

View File

@ -1,13 +1,29 @@
// Entry point for @ra-aid/common package
import './styles/global.css';
// Export utility functions
// Export utility functions (excluding sample data to avoid circular references)
export * from './utils';
// Export all UI components
export * from './components/ui';
// Export timeline components
export * from './components/TimelineStep';
export * from './components/TimelineFeed';
// Export session navigation components
export * from './components/SessionDrawer';
export * from './components/SessionSidebar';
// Export the hello function (temporary example)
export const hello = (): void => {
console.log("Hello from @ra-aid/common");
};
};
// Directly export sample data functions and types to avoid circular references
export {
getSampleAgentSteps,
getSampleAgentSessions,
type AgentStep,
type AgentSession
} from './utils/sample-data';

View File

@ -0,0 +1,32 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.cn = cn;
var clsx_1 = require("clsx");
var tailwind_merge_1 = require("tailwind-merge");
/**
* Merges class names with Tailwind CSS classes
* Combines clsx for conditional logic and tailwind-merge for handling conflicting tailwind classes
*/
function cn() {
var inputs = [];
for (var _i = 0; _i < arguments.length; _i++) {
inputs[_i] = arguments[_i];
}
return (0, tailwind_merge_1.twMerge)((0, clsx_1.clsx)(inputs));
}
// Re-export everything from utils directory
__exportStar(require("./utils"), exports);

View File

@ -7,4 +7,7 @@ import { twMerge } from "tailwind-merge";
*/
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
}
// Re-export everything from utils directory
export * from './utils';

View File

@ -0,0 +1,32 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.cn = cn;
var clsx_1 = require("clsx");
var tailwind_merge_1 = require("tailwind-merge");
/**
* Merges class names with Tailwind CSS classes
* Combines clsx for conditional logic and tailwind-merge for handling conflicting tailwind classes
*/
function cn() {
var inputs = [];
for (var _i = 0; _i < arguments.length; _i++) {
inputs[_i] = arguments[_i];
}
return (0, tailwind_merge_1.twMerge)((0, clsx_1.clsx)(inputs));
}
// Export sample data utilities
__exportStar(require("./sample-data"), exports);

View File

@ -0,0 +1,13 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
/**
* Merges class names with Tailwind CSS classes
* Combines clsx for conditional logic and tailwind-merge for handling conflicting tailwind classes
*/
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// Note: Sample data functions and types are now exported directly from the root index.ts
// to avoid circular references

View File

@ -0,0 +1,163 @@
"use strict";
/**
* Sample data utility for agent UI components demonstration
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSampleAgentSteps = getSampleAgentSteps;
exports.getSampleAgentSessions = getSampleAgentSessions;
/**
* Returns an array of sample agent steps
*/
function getSampleAgentSteps() {
return [
{
id: "step-1",
timestamp: new Date(Date.now() - 30 * 60000), // 30 minutes ago
status: 'completed',
type: 'planning',
title: 'Initial Planning',
content: 'I need to analyze the codebase structure to understand the existing components and their relationships.',
duration: 5200
},
{
id: "step-2",
timestamp: new Date(Date.now() - 25 * 60000), // 25 minutes ago
status: 'completed',
type: 'tool-execution',
title: 'List Directory Structure',
content: 'Executing: list_directory_tree(path="src/", max_depth=2)\n\n📁 /project/src/\n├── 📁 components/\n│ ├── 📁 ui/\n│ └── App.tsx\n├── 📁 utils/\n└── index.tsx',
duration: 1800
},
{
id: "step-3",
timestamp: new Date(Date.now() - 20 * 60000), // 20 minutes ago
status: 'completed',
type: 'thinking',
title: 'Component Analysis',
content: 'Based on the directory structure, I see that the UI components are organized in a dedicated folder. I should examine the existing component patterns before implementing new ones.',
duration: 3500
},
{
id: "step-4",
timestamp: new Date(Date.now() - 15 * 60000), // 15 minutes ago
status: 'completed',
type: 'tool-execution',
title: 'Read Component Code',
content: 'Executing: read_file_tool(filepath="src/components/ui/Button.tsx")\n\n```tsx\nimport { cn } from "../../utils";\n\nexport interface ButtonProps {\n // Component props...\n}\n\nexport function Button({ children, ...props }: ButtonProps) {\n // Component implementation...\n}\n```',
duration: 2100
},
{
id: "step-5",
timestamp: new Date(Date.now() - 10 * 60000), // 10 minutes ago
status: 'completed',
type: 'implementation',
title: 'Creating NavBar Component',
content: 'I\'m creating a NavBar component following the design system patterns:\n\n```tsx\nimport { cn } from "../../utils";\n\nexport interface NavBarProps {\n // New component props...\n}\n\nexport function NavBar({ ...props }: NavBarProps) {\n // New component implementation...\n}\n```',
duration: 6800
},
{
id: "step-6",
timestamp: new Date(Date.now() - 5 * 60000), // 5 minutes ago
status: 'in-progress',
type: 'implementation',
title: 'Styling Timeline Component',
content: 'Currently working on styling the Timeline component to match the design system:\n\n```tsx\n// Work in progress...\nexport function Timeline({ steps, ...props }: TimelineProps) {\n // Current implementation...\n}\n```',
},
{
id: "step-7",
timestamp: new Date(Date.now() - 2 * 60000), // 2 minutes ago
status: 'error',
type: 'tool-execution',
title: 'Running Tests',
content: 'Error executing: run_shell_command(command="npm test")\n\nTest failed: TypeError: Cannot read property \'steps\' of undefined',
duration: 3200
},
{
id: "step-8",
timestamp: new Date(), // Now
status: 'pending',
type: 'planning',
title: 'Next Steps',
content: 'Need to plan the implementation of the SessionDrawer component...',
}
];
}
/**
* Returns an array of sample agent sessions
*/
function getSampleAgentSessions() {
var steps = getSampleAgentSteps();
return [
{
id: "session-1",
name: "UI Component Implementation",
created: new Date(Date.now() - 35 * 60000), // 35 minutes ago
updated: new Date(), // Now
status: 'active',
steps: steps
},
{
id: "session-2",
name: "API Integration",
created: new Date(Date.now() - 2 * 3600000), // 2 hours ago
updated: new Date(Date.now() - 30 * 60000), // 30 minutes ago
status: 'completed',
steps: [
{
id: "other-step-1",
timestamp: new Date(Date.now() - 2 * 3600000), // 2 hours ago
status: 'completed',
type: 'planning',
title: 'API Integration Planning',
content: 'Planning the integration with the backend API...',
duration: 4500
},
{
id: "other-step-2",
timestamp: new Date(Date.now() - 1.5 * 3600000), // 1.5 hours ago
status: 'completed',
type: 'implementation',
title: 'Implementing API Client',
content: 'Creating API client with fetch utilities...',
duration: 7200
},
{
id: "other-step-3",
timestamp: new Date(Date.now() - 1 * 3600000), // 1 hour ago
status: 'completed',
type: 'tool-execution',
title: 'Testing API Endpoints',
content: 'Running tests against API endpoints...',
duration: 5000
}
]
},
{
id: "session-3",
name: "Bug Fixes",
created: new Date(Date.now() - 5 * 3600000), // 5 hours ago
updated: new Date(Date.now() - 4 * 3600000), // 4 hours ago
status: 'error',
steps: [
{
id: "bug-step-1",
timestamp: new Date(Date.now() - 5 * 3600000), // 5 hours ago
status: 'completed',
type: 'planning',
title: 'Bug Analysis',
content: 'Analyzing reported bugs from issue tracker...',
duration: 3600
},
{
id: "bug-step-2",
timestamp: new Date(Date.now() - 4.5 * 3600000), // 4.5 hours ago
status: 'error',
type: 'implementation',
title: 'Fixing Authentication Bug',
content: 'Error: Unable to resolve dependency conflict with auth package',
duration: 2500
}
]
}
];
}

View File

@ -0,0 +1,187 @@
/**
* Sample data utility for agent UI components demonstration
*/
/**
* Represents a single step in the agent process
*/
export interface AgentStep {
id: string;
timestamp: Date;
status: 'completed' | 'in-progress' | 'error' | 'pending';
type: 'tool-execution' | 'thinking' | 'planning' | 'implementation' | 'user-input';
title: string;
content: string;
duration?: number; // in milliseconds
}
/**
* Represents a session with multiple steps
*/
export interface AgentSession {
id: string;
name: string;
created: Date;
updated: Date;
status: 'active' | 'completed' | 'error';
steps: AgentStep[];
}
/**
* Returns an array of sample agent steps
*/
export function getSampleAgentSteps(): AgentStep[] {
return [
{
id: "step-1",
timestamp: new Date(Date.now() - 30 * 60000), // 30 minutes ago
status: 'completed',
type: 'planning',
title: 'Initial Planning',
content: 'I need to analyze the codebase structure to understand the existing components and their relationships.',
duration: 5200
},
{
id: "step-2",
timestamp: new Date(Date.now() - 25 * 60000), // 25 minutes ago
status: 'completed',
type: 'tool-execution',
title: 'List Directory Structure',
content: 'Executing: list_directory_tree(path="src/", max_depth=2)\n\n📁 /project/src/\n├── 📁 components/\n│ ├── 📁 ui/\n│ └── App.tsx\n├── 📁 utils/\n└── index.tsx',
duration: 1800
},
{
id: "step-3",
timestamp: new Date(Date.now() - 20 * 60000), // 20 minutes ago
status: 'completed',
type: 'thinking',
title: 'Component Analysis',
content: 'Based on the directory structure, I see that the UI components are organized in a dedicated folder. I should examine the existing component patterns before implementing new ones.',
duration: 3500
},
{
id: "step-4",
timestamp: new Date(Date.now() - 15 * 60000), // 15 minutes ago
status: 'completed',
type: 'tool-execution',
title: 'Read Component Code',
content: 'Executing: read_file_tool(filepath="src/components/ui/Button.tsx")\n\n```tsx\nimport { cn } from "../../utils";\n\nexport interface ButtonProps {\n // Component props...\n}\n\nexport function Button({ children, ...props }: ButtonProps) {\n // Component implementation...\n}\n```',
duration: 2100
},
{
id: "step-5",
timestamp: new Date(Date.now() - 10 * 60000), // 10 minutes ago
status: 'completed',
type: 'implementation',
title: 'Creating NavBar Component',
content: 'I\'m creating a NavBar component following the design system patterns:\n\n```tsx\nimport { cn } from "../../utils";\n\nexport interface NavBarProps {\n // New component props...\n}\n\nexport function NavBar({ ...props }: NavBarProps) {\n // New component implementation...\n}\n```',
duration: 6800
},
{
id: "step-6",
timestamp: new Date(Date.now() - 5 * 60000), // 5 minutes ago
status: 'in-progress',
type: 'implementation',
title: 'Styling Timeline Component',
content: 'Currently working on styling the Timeline component to match the design system:\n\n```tsx\n// Work in progress...\nexport function Timeline({ steps, ...props }: TimelineProps) {\n // Current implementation...\n}\n```',
},
{
id: "step-7",
timestamp: new Date(Date.now() - 2 * 60000), // 2 minutes ago
status: 'error',
type: 'tool-execution',
title: 'Running Tests',
content: 'Error executing: run_shell_command(command="npm test")\n\nTest failed: TypeError: Cannot read property \'steps\' of undefined',
duration: 3200
},
{
id: "step-8",
timestamp: new Date(), // Now
status: 'pending',
type: 'planning',
title: 'Next Steps',
content: 'Need to plan the implementation of the SessionDrawer component...',
}
];
}
/**
* Returns an array of sample agent sessions
*/
export function getSampleAgentSessions(): AgentSession[] {
const steps = getSampleAgentSteps();
return [
{
id: "session-1",
name: "UI Component Implementation",
created: new Date(Date.now() - 35 * 60000), // 35 minutes ago
updated: new Date(), // Now
status: 'active',
steps: steps
},
{
id: "session-2",
name: "API Integration",
created: new Date(Date.now() - 2 * 3600000), // 2 hours ago
updated: new Date(Date.now() - 30 * 60000), // 30 minutes ago
status: 'completed',
steps: [
{
id: "other-step-1",
timestamp: new Date(Date.now() - 2 * 3600000), // 2 hours ago
status: 'completed',
type: 'planning',
title: 'API Integration Planning',
content: 'Planning the integration with the backend API...',
duration: 4500
},
{
id: "other-step-2",
timestamp: new Date(Date.now() - 1.5 * 3600000), // 1.5 hours ago
status: 'completed',
type: 'implementation',
title: 'Implementing API Client',
content: 'Creating API client with fetch utilities...',
duration: 7200
},
{
id: "other-step-3",
timestamp: new Date(Date.now() - 1 * 3600000), // 1 hour ago
status: 'completed',
type: 'tool-execution',
title: 'Testing API Endpoints',
content: 'Running tests against API endpoints...',
duration: 5000
}
]
},
{
id: "session-3",
name: "Bug Fixes",
created: new Date(Date.now() - 5 * 3600000), // 5 hours ago
updated: new Date(Date.now() - 4 * 3600000), // 4 hours ago
status: 'error',
steps: [
{
id: "bug-step-1",
timestamp: new Date(Date.now() - 5 * 3600000), // 5 hours ago
status: 'completed',
type: 'planning',
title: 'Bug Analysis',
content: 'Analyzing reported bugs from issue tracker...',
duration: 3600
},
{
id: "bug-step-2",
timestamp: new Date(Date.now() - 4.5 * 3600000), // 4.5 hours ago
status: 'error',
type: 'implementation',
title: 'Fixing Authentication Bug',
content: 'Error: Unable to resolve dependency conflict with auth package',
duration: 2500
}
]
}
];
}

View File

@ -10,7 +10,8 @@
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "dist",
"rootDir": "src"
"rootDir": "src",
"lib": ["DOM", "DOM.Iterable", "ESNext", "ES2016"]
},
"include": ["src"]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,170 +1,114 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import {
hello,
Button,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
Input,
Switch
Button,
SessionDrawer,
SessionSidebar,
TimelineFeed,
getSampleAgentSessions,
getSampleAgentSteps
} from '@ra-aid/common';
// The CSS import happens through the common package's index.ts
hello();
const App = () => {
const [inputValue, setInputValue] = useState('');
const [switchState, setSwitchState] = useState(false);
const [loading, setLoading] = useState(false);
const handleLoadingClick = () => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
// State for drawer open/close
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
// State for selected session
const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null);
// Get sample data
const sessions = getSampleAgentSessions();
const allSteps = getSampleAgentSteps();
// Set initial selected session if none selected
useEffect(() => {
if (!selectedSessionId && sessions.length > 0) {
setSelectedSessionId(sessions[0].id);
}
}, [sessions, selectedSessionId]);
// Filter steps for selected session
const selectedSessionSteps = selectedSessionId
? allSteps.filter(step => sessions.find(s => s.id === selectedSessionId)?.steps.some(s => s.id === step.id))
: [];
// Handle session selection
const handleSessionSelect = (sessionId: string) => {
setSelectedSessionId(sessionId);
setIsDrawerOpen(false); // Close drawer on selection (mobile)
};
return (
<div className="min-h-screen bg-background text-foreground dark">
<div className="container mx-auto py-10 px-4">
<header className="mb-10">
<h1 className="text-4xl font-bold mb-2 bg-gradient-to-r from-blue-400 to-purple-500 inline-block text-transparent bg-clip-text">shadcn/ui Components Demo</h1>
<p className="text-muted-foreground">A showcase of UI components from the common package</p>
</header>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card className="border-border bg-card">
<CardHeader>
<CardTitle>Button Component</CardTitle>
<CardDescription>Various button variants from shadcn/ui</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-2">
<Button variant="default">Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
<div className="pt-2">
<h3 className="text-sm font-medium mb-2">Button Sizes</h3>
<div className="flex items-center gap-2">
<Button size="sm">Small</Button>
<Button>Default</Button>
<Button size="lg">Large</Button>
</div>
</div>
<div className="pt-2">
<h3 className="text-sm font-medium mb-2">Button States</h3>
<div className="flex items-center gap-2">
<Button disabled>Disabled</Button>
<Button onClick={handleLoadingClick} disabled={loading}>
{loading ? 'Loading...' : 'Click to Load'}
</Button>
</div>
</div>
</CardContent>
</Card>
<Card className="border-border bg-card">
<CardHeader>
<CardTitle>Input Component</CardTitle>
<CardDescription>Text input with various states</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div>
<label className="text-sm font-medium block mb-1">Standard Input</label>
<Input
placeholder="Type something..."
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
{inputValue && (
<p className="text-sm mt-1 text-muted-foreground">You typed: {inputValue}</p>
)}
</div>
<div>
<label className="text-sm font-medium block mb-1">Disabled Input</label>
<Input disabled placeholder="Disabled input" />
</div>
<div>
<label className="text-sm font-medium block mb-1">With Icon</label>
<div className="relative">
<Input placeholder="Search..." />
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-muted-foreground">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.3-4.3"></path>
</svg>
</div>
</div>
</div>
</CardContent>
</Card>
<Card className="border-border bg-card">
<CardHeader>
<CardTitle>Switch Component</CardTitle>
<CardDescription>Toggle switch with controlled state</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<label className="text-sm font-medium">Toggle theme</label>
<Switch
checked={switchState}
onCheckedChange={setSwitchState}
/>
</div>
<p className="text-sm text-muted-foreground">
Current theme: <span className="font-medium">{switchState ? 'Dark' : 'Light'}</span>
</p>
<div className="flex items-center justify-between">
<label className="text-sm font-medium">Disabled switch</label>
<Switch disabled />
</div>
</CardContent>
<CardFooter>
<p className="text-xs text-muted-foreground">Click the switch to toggle its state</p>
</CardFooter>
</Card>
<Card className="border-border bg-card">
<CardHeader>
<CardTitle>Card Component</CardTitle>
<CardDescription>Card with header, content, and footer sections</CardDescription>
</CardHeader>
<CardContent>
<p className="text-card-foreground">Cards are versatile containers that group related content and actions.</p>
<div className="mt-4 p-3 bg-muted rounded-md">
<code className="text-xs text-pink-400">
{'<Card>'}<br/>
{' <CardHeader>'}<br/>
{' <CardTitle>Title</CardTitle>'}<br/>
{' <CardDescription>Description</CardDescription>'}<br/>
{' </CardHeader>'}<br/>
{' <CardContent>Content</CardContent>'}<br/>
{' <CardFooter>Footer</CardFooter>'}<br/>
{'</Card>'}
</code>
</div>
</CardContent>
<CardFooter className="flex justify-between border-t border-border pt-4">
<Button variant="outline" size="sm">Cancel</Button>
<Button size="sm">Save</Button>
</CardFooter>
</Card>
<div className="min-h-screen bg-background text-foreground flex flex-col dark">
{/* Header */}
<header className="border-b border-border py-4 px-4 sticky top-0 z-10 bg-background">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-500 inline-block text-transparent bg-clip-text">
RA-Aid
</h1>
{/* Mobile drawer toggle - show only on small screens */}
<div className="md:hidden">
<Button
variant="ghost"
size="icon"
onClick={() => setIsDrawerOpen(true)}
aria-label="Open menu"
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-menu"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
</Button>
</div>
</div>
<footer className="mt-12 text-center text-muted-foreground text-sm">
<p>Built with shadcn/ui components from the RA-Aid common package</p>
</footer>
</header>
{/* Main content */}
<div className="flex flex-1 overflow-hidden">
{/* Desktop sidebar - hidden on mobile */}
<SessionSidebar
sessions={sessions}
currentSessionId={selectedSessionId || undefined}
onSelectSession={handleSessionSelect}
className="shrink-0"
/>
{/* Mobile drawer */}
<SessionDrawer
sessions={sessions}
currentSessionId={selectedSessionId || undefined}
onSelectSession={handleSessionSelect}
/>
{/* Main content area */}
<main className="flex-1 overflow-auto p-4">
{selectedSessionId ? (
<>
<h2 className="text-xl font-semibold mb-4">
Session: {sessions.find(s => s.id === selectedSessionId)?.name || 'Unknown'}
</h2>
<TimelineFeed
steps={selectedSessionSteps}
maxHeight="calc(100vh - 14rem)"
/>
</>
) : (
<div className="flex items-center justify-center h-full">
<p className="text-muted-foreground">Select a session to view details</p>
</div>
)}
</main>
</div>
<footer className="border-t border-border py-4 px-4 text-center text-muted-foreground text-sm">
<p>Built with shadcn/ui components from the RA-Aid common package</p>
</footer>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(<App />);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

View File

@ -7,14 +7,14 @@ export default defineConfig({
resolve: {
// Ensure that Vite treats symlinked packages as local, so HMR works correctly.
alias: {
'@ra-aid/common': path.resolve(__dirname, '../common/src')
'@ra-aid/common': path.resolve(__dirname, '../common/dist')
}
},
server: {
watch: {
// Watch for changes in the common package.
// This pattern forces Vite to notice file changes in the shared library.
paths: ['../common/src/**']
paths: ['../common/src/**', '../common/dist/**']
}
},
css: {