agent ui components
This commit is contained in:
parent
a9c7f92687
commit
1ced6ece4c
|
|
@ -17,3 +17,5 @@ appmap.log
|
|||
/vsc/node_modules
|
||||
/vsc/dist
|
||||
node_modules/
|
||||
/frontend/common/dist
|
||||
/frontend/web/dist/
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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";
|
||||
|
|
@ -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";
|
||||
|
|
@ -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";
|
||||
|
|
@ -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 }
|
||||
|
|
@ -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);
|
||||
|
|
@ -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';
|
||||
|
|
@ -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";
|
||||
|
|
@ -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;
|
||||
|
|
@ -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 }
|
||||
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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';
|
||||
|
|
@ -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);
|
||||
|
|
@ -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';
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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>
|
||||
);
|
||||
|
|
@ -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: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue