@autobe/ui 0.19.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/lib/AutoBeChatMain.d.ts +16 -0
  2. package/lib/AutoBeChatMain.js +51 -0
  3. package/lib/AutoBeChatMain.js.map +1 -0
  4. package/lib/banner/AutoBeAgentInformation.d.ts +15 -0
  5. package/lib/banner/AutoBeAgentInformation.js +41 -0
  6. package/lib/banner/AutoBeAgentInformation.js.map +1 -0
  7. package/lib/banner/AutoBeChatBanner.d.ts +15 -0
  8. package/lib/banner/AutoBeChatBanner.js +29 -0
  9. package/lib/banner/AutoBeChatBanner.js.map +1 -0
  10. package/lib/banner/AutoBeChatState.d.ts +6 -0
  11. package/lib/banner/AutoBeChatState.js +80 -0
  12. package/lib/banner/AutoBeChatState.js.map +1 -0
  13. package/lib/banner/AutoBeTokenUsage.d.ts +14 -0
  14. package/lib/banner/AutoBeTokenUsage.js +60 -0
  15. package/lib/banner/AutoBeTokenUsage.js.map +1 -0
  16. package/lib/banner/index.d.ts +4 -0
  17. package/lib/banner/index.js +21 -0
  18. package/lib/banner/index.js.map +1 -0
  19. package/lib/common/Collapsible.d.ts +15 -0
  20. package/lib/common/Collapsible.js +45 -0
  21. package/lib/common/Collapsible.js.map +1 -0
  22. package/lib/common/index.d.ts +2 -0
  23. package/lib/common/index.js +19 -0
  24. package/lib/common/index.js.map +1 -0
  25. package/lib/constant/color.d.ts +18 -0
  26. package/lib/constant/color.js +25 -0
  27. package/lib/constant/color.js.map +1 -0
  28. package/lib/events/AutoBeCompleteEventMovie.d.ts +7 -0
  29. package/lib/events/AutoBeCompleteEventMovie.js +210 -0
  30. package/lib/events/AutoBeCompleteEventMovie.js.map +1 -0
  31. package/lib/events/AutoBeEventMovie.d.ts +8 -0
  32. package/lib/events/AutoBeEventMovie.js +84 -0
  33. package/lib/events/AutoBeEventMovie.js.map +1 -0
  34. package/lib/events/AutoBeProgressEventMovie.js +2 -61
  35. package/lib/events/AutoBeProgressEventMovie.js.map +1 -1
  36. package/lib/events/AutoBeScenarioEventMovie.js +2 -44
  37. package/lib/events/AutoBeScenarioEventMovie.js.map +1 -1
  38. package/lib/events/AutoBeValidateEventMovie.d.ts +6 -0
  39. package/lib/events/AutoBeValidateEventMovie.js +115 -0
  40. package/lib/events/AutoBeValidateEventMovie.js.map +1 -0
  41. package/lib/events/common/CollapsibleEventGroup.d.ts +28 -0
  42. package/lib/events/common/CollapsibleEventGroup.js +89 -0
  43. package/lib/events/common/CollapsibleEventGroup.js.map +1 -0
  44. package/lib/events/common/EventCard.d.ts +13 -0
  45. package/lib/events/common/EventCard.js +43 -0
  46. package/lib/events/common/EventCard.js.map +1 -0
  47. package/lib/events/common/EventContent.d.ts +11 -0
  48. package/lib/events/common/EventContent.js +14 -0
  49. package/lib/events/common/EventContent.js.map +1 -0
  50. package/lib/events/common/EventHeader.d.ts +15 -0
  51. package/lib/events/common/EventHeader.js +41 -0
  52. package/lib/events/common/EventHeader.js.map +1 -0
  53. package/lib/events/common/EventIcon.d.ts +11 -0
  54. package/lib/events/common/EventIcon.js +50 -0
  55. package/lib/events/common/EventIcon.js.map +1 -0
  56. package/lib/events/common/ProgressBar.d.ts +14 -0
  57. package/lib/events/common/ProgressBar.js +33 -0
  58. package/lib/events/common/ProgressBar.js.map +1 -0
  59. package/lib/events/common/index.d.ts +6 -0
  60. package/lib/events/common/index.js +16 -0
  61. package/lib/events/common/index.js.map +1 -0
  62. package/lib/events/groups/ValidateEventGroup.d.ts +12 -0
  63. package/lib/events/groups/ValidateEventGroup.js +78 -0
  64. package/lib/events/groups/ValidateEventGroup.js.map +1 -0
  65. package/lib/events/groups/index.d.ts +1 -0
  66. package/lib/events/groups/index.js +6 -0
  67. package/lib/events/groups/index.js.map +1 -0
  68. package/lib/events/index.d.ts +6 -0
  69. package/lib/events/index.js +27 -1
  70. package/lib/events/index.js.map +1 -1
  71. package/lib/events/utils/eventGrouper.d.ts +20 -0
  72. package/lib/events/utils/eventGrouper.js +74 -0
  73. package/lib/events/utils/eventGrouper.js.map +1 -0
  74. package/lib/events/utils/index.d.ts +1 -0
  75. package/lib/events/utils/index.js +6 -0
  76. package/lib/events/utils/index.js.map +1 -0
  77. package/lib/hooks/index.d.ts +2 -0
  78. package/lib/hooks/index.js +19 -0
  79. package/lib/hooks/index.js.map +1 -0
  80. package/lib/hooks/useIsomorphicLayoutEffect.d.ts +6 -0
  81. package/lib/hooks/useIsomorphicLayoutEffect.js +10 -0
  82. package/lib/hooks/useIsomorphicLayoutEffect.js.map +1 -0
  83. package/lib/hooks/useMediaQuery.d.ts +11 -0
  84. package/lib/hooks/useMediaQuery.js +52 -0
  85. package/lib/hooks/useMediaQuery.js.map +1 -0
  86. package/lib/index.d.ts +5 -0
  87. package/lib/index.js +8 -1
  88. package/lib/index.js.map +1 -1
  89. package/lib/structure/AutoBeListener.d.ts +17 -0
  90. package/lib/structure/AutoBeListener.js +250 -0
  91. package/lib/structure/AutoBeListener.js.map +1 -0
  92. package/lib/structure/AutoBeListenerState.d.ts +14 -0
  93. package/lib/structure/AutoBeListenerState.js +39 -0
  94. package/lib/structure/AutoBeListenerState.js.map +1 -0
  95. package/lib/structure/IAutoBeEventGroup.d.ts +5 -0
  96. package/lib/structure/IAutoBeEventGroup.js +3 -0
  97. package/lib/structure/IAutoBeEventGroup.js.map +1 -0
  98. package/lib/structure/index.d.ts +3 -0
  99. package/lib/structure/index.js +20 -0
  100. package/lib/structure/index.js.map +1 -0
  101. package/lib/upload/AutoBeChatUploadBox.d.ts +31 -0
  102. package/lib/upload/AutoBeChatUploadBox.js +221 -0
  103. package/lib/upload/AutoBeChatUploadBox.js.map +1 -0
  104. package/lib/upload/AutoBeChatUploadSendButton.d.ts +15 -0
  105. package/lib/upload/AutoBeChatUploadSendButton.js +38 -0
  106. package/lib/upload/AutoBeChatUploadSendButton.js.map +1 -0
  107. package/lib/upload/AutoBeFileUploadBox.d.ts +8 -0
  108. package/lib/upload/AutoBeFileUploadBox.js +68 -0
  109. package/lib/upload/AutoBeFileUploadBox.js.map +1 -0
  110. package/lib/upload/AutoBeUploadConfig.d.ts +9 -0
  111. package/lib/upload/AutoBeUploadConfig.js +3 -0
  112. package/lib/upload/AutoBeUploadConfig.js.map +1 -0
  113. package/lib/upload/AutoBeVoiceRecoderButton.d.ts +11 -0
  114. package/lib/upload/AutoBeVoiceRecoderButton.js +58 -0
  115. package/lib/upload/AutoBeVoiceRecoderButton.js.map +1 -0
  116. package/lib/upload/index.d.ts +5 -0
  117. package/lib/upload/index.js +22 -0
  118. package/lib/upload/index.js.map +1 -0
  119. package/lib/utils/AutoBeFileUploader.d.ts +28 -0
  120. package/lib/utils/AutoBeFileUploader.js +237 -0
  121. package/lib/utils/AutoBeFileUploader.js.map +1 -0
  122. package/lib/utils/AutoBeVoiceRecorder.d.ts +7 -0
  123. package/lib/utils/AutoBeVoiceRecorder.js +94 -0
  124. package/lib/utils/AutoBeVoiceRecorder.js.map +1 -0
  125. package/lib/utils/index.d.ts +4 -0
  126. package/lib/utils/index.js +21 -0
  127. package/lib/utils/index.js.map +1 -0
  128. package/lib/utils/number.d.ts +1 -0
  129. package/lib/utils/number.js +20 -0
  130. package/lib/utils/number.js.map +1 -0
  131. package/package.json +13 -2
  132. package/src/AutoBeChatMain.tsx +123 -0
  133. package/src/banner/AutoBeAgentInformation.tsx +102 -0
  134. package/src/banner/AutoBeChatBanner.tsx +72 -0
  135. package/src/banner/AutoBeChatState.tsx +152 -0
  136. package/src/banner/AutoBeTokenUsage.tsx +152 -0
  137. package/src/banner/index.ts +4 -0
  138. package/src/common/Collapsible.tsx +95 -0
  139. package/src/common/index.ts +2 -0
  140. package/src/constant/color.ts +24 -0
  141. package/src/events/AutoBeCompleteEventMovie.tsx +402 -0
  142. package/src/events/AutoBeEventMovie.tsx +114 -0
  143. package/src/events/AutoBeProgressEventMovie.tsx +12 -125
  144. package/src/events/AutoBeScenarioEventMovie.tsx +5 -93
  145. package/src/events/AutoBeValidateEventMovie.tsx +326 -0
  146. package/src/events/README.md +300 -0
  147. package/src/events/common/CollapsibleEventGroup.tsx +220 -0
  148. package/src/events/common/EventCard.tsx +61 -0
  149. package/src/events/common/EventContent.tsx +31 -0
  150. package/src/events/common/EventHeader.tsx +85 -0
  151. package/src/events/common/EventIcon.tsx +82 -0
  152. package/src/events/common/ProgressBar.tsx +63 -0
  153. package/src/events/common/index.ts +13 -0
  154. package/src/events/groups/ValidateEventGroup.tsx +150 -0
  155. package/src/events/groups/index.ts +4 -0
  156. package/src/events/index.ts +12 -0
  157. package/src/events/utils/eventGrouper.tsx +118 -0
  158. package/src/events/utils/index.ts +1 -0
  159. package/src/hooks/index.ts +2 -0
  160. package/src/hooks/useIsomorphicLayoutEffect.ts +8 -0
  161. package/src/hooks/useMediaQuery.ts +68 -0
  162. package/src/index.ts +5 -0
  163. package/src/structure/AutoBeListener.ts +263 -0
  164. package/src/structure/AutoBeListenerState.ts +53 -0
  165. package/src/structure/IAutoBeEventGroup.ts +6 -0
  166. package/src/structure/index.ts +3 -0
  167. package/src/upload/AutoBeChatUploadBox.tsx +372 -0
  168. package/src/upload/AutoBeChatUploadSendButton.tsx +66 -0
  169. package/src/upload/AutoBeFileUploadBox.tsx +123 -0
  170. package/src/upload/AutoBeUploadConfig.ts +5 -0
  171. package/src/upload/AutoBeVoiceRecoderButton.tsx +100 -0
  172. package/src/upload/index.ts +5 -0
  173. package/src/utils/AutoBeFileUploader.ts +279 -0
  174. package/src/utils/AutoBeVoiceRecorder.ts +95 -0
  175. package/src/utils/index.ts +4 -0
  176. package/src/utils/number.ts +17 -0
  177. package/tsconfig.json +2 -1
@@ -0,0 +1,300 @@
1
+ # AutoBe Event Components
2
+
3
+ Event UI components for the AutoBe platform with comprehensive event handling, grouping, and collapsible functionality.
4
+
5
+ ## Overview
6
+
7
+ The AutoBe Event system provides a complete solution for displaying various types of events in the AutoBe workflow. The main entry point is `AutoBeEventMovie`, which intelligently routes different event types to their appropriate components.
8
+
9
+ ## Main Event Router
10
+
11
+ ### AutoBeEventMovie
12
+ The central component that handles all event types and routes them to appropriate sub-components.
13
+
14
+ ```tsx
15
+ import { AutoBeEventMovie } from "@autobe/ui/events";
16
+
17
+ <AutoBeEventMovie
18
+ service={rpcService}
19
+ events={eventArray}
20
+ last={isLastEvent}
21
+ />
22
+ ```
23
+
24
+ **Supported Event Types:**
25
+ - **Message Events**: `userMessage`, `assistantMessage`
26
+ - **Start Events**: `analyzeStart`, `prismaStart`, `interfaceStart`, `testStart`, `realizeStart`, `realizeTestStart`, `realizeAuthorizationStart`
27
+ - **Scenario Events**: `analyzeScenario`, `prismaComponents`, `interfaceGroups`, `realizeTestReset`
28
+ - **Progress Events**: `analyzeWrite`, `analyzeReview`, `interfaceEndpoints`, `prismaSchemas`, `prismaReview`, `interfaceOperations`, `interfaceOperationsReview`, `interfaceAuthorization`, `interfaceSchemas`, `interfaceSchemasReview`, `testWrite`, `testScenarios`, `realizeWrite`, `realizeAuthorizationWrite`, `realizeTestOperation`
29
+ - **Validate Events**: `prismaInsufficient`, `prismaValidate`, `interfaceComplement`, `testValidate`, `realizeValidate`, `realizeAuthorizationValidate`
30
+ - **Complete Events**: `analyzeComplete`, `prismaComplete`, `interfaceComplete`, `testComplete`, `realizeComplete`
31
+
32
+ ## Individual Event Components
33
+
34
+ ### AutoBeProgressEventMovie
35
+ Shows progress tracking events with animated progress bars and status indicators.
36
+
37
+ ```tsx
38
+ import { AutoBeProgressEventMovie } from "@autobe/ui/events";
39
+
40
+ <AutoBeProgressEventMovie event={progressEvent} />
41
+ ```
42
+
43
+ ### AutoBeValidateEventMovie
44
+ Displays validation events with detailed error/success states and validation results.
45
+
46
+ ```tsx
47
+ import { AutoBeValidateEventMovie } from "@autobe/ui/events";
48
+
49
+ <AutoBeValidateEventMovie event={validateEvent} />
50
+ ```
51
+
52
+ ### AutoBeScenarioEventMovie
53
+ Shows scenario analysis and component generation events with structured data display.
54
+
55
+ ```tsx
56
+ import { AutoBeScenarioEventMovie } from "@autobe/ui/events";
57
+
58
+ <AutoBeScenarioEventMovie event={scenarioEvent} />
59
+ ```
60
+
61
+ ### AutoBeStartEventMovie
62
+ Displays pipeline start events with clean status indicators and timing information.
63
+
64
+ ```tsx
65
+ import { AutoBeStartEventMovie } from "@autobe/ui/events";
66
+
67
+ <AutoBeStartEventMovie event={startEvent} />
68
+ ```
69
+
70
+ ### AutoBeCompleteEventMovie
71
+ Shows completion events with file download capabilities and summary statistics.
72
+
73
+ ```tsx
74
+ import { AutoBeCompleteEventMovie } from "@autobe/ui/events";
75
+
76
+ <AutoBeCompleteEventMovie
77
+ event={completeEvent}
78
+ getFiles={service.getFiles}
79
+ />
80
+ ```
81
+
82
+ ## Grouped Event Components
83
+
84
+ ### ValidateEventGroup
85
+ Intelligently groups validation events with success rate statistics and collapsible interface.
86
+
87
+ ```tsx
88
+ import { ValidateEventGroup } from "@autobe/ui/events";
89
+
90
+ <ValidateEventGroup
91
+ events={validateEvents}
92
+ defaultCollapsed={true}
93
+ />
94
+ ```
95
+
96
+ **Features:**
97
+ - Automatic success/failure rate calculation
98
+ - Collapsible interface for better UX
99
+ - Grouped display for multiple validation events
100
+ - Individual event access when expanded
101
+
102
+ ## Message Components
103
+
104
+ ### AutoBeUserMessageMovie
105
+ Displays user messages with support for various content types (text, files, images, audio).
106
+
107
+ ```tsx
108
+ import { AutoBeUserMessageMovie } from "@autobe/ui";
109
+
110
+ <AutoBeUserMessageMovie message={userMessageContents} />
111
+ ```
112
+
113
+ ### AutoBeAssistantMessageMovie
114
+ Shows assistant responses with timestamps and custom assistant names.
115
+
116
+ ```tsx
117
+ import { AutoBeAssistantMessageMovie } from "@autobe/ui";
118
+
119
+ <AutoBeAssistantMessageMovie
120
+ text={responseText}
121
+ isoTimestamp={timestamp}
122
+ assistantName="AutoBe"
123
+ />
124
+ ```
125
+
126
+ ## Automatic Event Grouping
127
+
128
+ Use the `groupEvents` utility to automatically group events by type:
129
+
130
+ ```tsx
131
+ import { groupEvents } from "@autobe/ui/events/utils/eventGrouper";
132
+
133
+ const EventList = ({ events }: { events: AutoBeEvent[] }) => {
134
+ const groupedComponents = groupEvents(events, {
135
+ minGroupSize: 3, // Minimum events to form a group
136
+ defaultCollapsed: true, // Start collapsed
137
+ enableGrouping: true, // Enable grouping
138
+ });
139
+
140
+ return (
141
+ <div>
142
+ {groupedComponents}
143
+ </div>
144
+ );
145
+ };
146
+ ```
147
+
148
+ ## Custom Collapsible Groups
149
+
150
+ Create custom event groups using the `CollapsibleEventGroup` component:
151
+
152
+ ```tsx
153
+ import { CollapsibleEventGroup } from "@autobe/ui/events";
154
+
155
+ <CollapsibleEventGroup
156
+ events={customEvents}
157
+ title="Custom Event Group"
158
+ iconType="info"
159
+ getTimestamp={(event) => event.created_at}
160
+ renderEvent={(event, index) => <CustomEventComponent event={event} />}
161
+ renderSummary={(events) => <CustomSummary events={events} />}
162
+ defaultCollapsed={true}
163
+ description="Custom grouped events"
164
+ />
165
+ ```
166
+
167
+ ## Common Components
168
+
169
+ ### EventCard
170
+ Basic card container for consistent styling across all event types.
171
+
172
+ ```tsx
173
+ import { EventCard } from "@autobe/ui/events";
174
+
175
+ <EventCard>
176
+ <div>Your content here</div>
177
+ </EventCard>
178
+ ```
179
+
180
+ ### EventHeader
181
+ Standardized header with icon, title, timestamp, and step numbering.
182
+
183
+ ```tsx
184
+ import { EventHeader } from "@autobe/ui/events";
185
+
186
+ <EventHeader
187
+ title="Event Title"
188
+ timestamp="2024-01-01T12:00:00Z"
189
+ iconType="success"
190
+ step={1}
191
+ />
192
+ ```
193
+
194
+ ### EventContent
195
+ Consistent content area styling with proper spacing and typography.
196
+
197
+ ```tsx
198
+ import { EventContent } from "@autobe/ui/events";
199
+
200
+ <EventContent>
201
+ <div>Your content here</div>
202
+ </EventContent>
203
+ ```
204
+
205
+ ### EventIcon
206
+ Consistent icons for different event states with customizable sizes.
207
+
208
+ ```tsx
209
+ import { EventIcon } from "@autobe/ui/events";
210
+
211
+ <EventIcon type="success" size={16} />
212
+ ```
213
+
214
+ **Available icon types:** `success`, `progress`, `warning`, `error`, `info`, `start`
215
+
216
+ ### ProgressBar
217
+ Reusable progress bar component with customizable styling.
218
+
219
+ ```tsx
220
+ import { ProgressBar } from "@autobe/ui/events";
221
+
222
+ <ProgressBar
223
+ current={7}
224
+ total={10}
225
+ color="#4caf50"
226
+ showLabel={true}
227
+ />
228
+ ```
229
+
230
+ ## Event Flow Architecture
231
+
232
+ The AutoBe event system follows a predictable flow:
233
+
234
+ 1. **Start Events** → Initialize pipeline stages
235
+ 2. **Scenario Events** → Analyze and plan components
236
+ 3. **Progress Events** → Track ongoing operations
237
+ 4. **Validate Events** → Verify outputs and handle errors
238
+ 5. **Complete Events** → Finalize and provide results
239
+
240
+ ## Advanced Usage
241
+
242
+ ### Custom Event Handlers
243
+
244
+ ```tsx
245
+ import { AutoBeEventMovie, IAutoBeEventMovieProps } from "@autobe/ui/events";
246
+
247
+ const CustomEventHandler = ({ events, service, last }: IAutoBeEventMovieProps<AutoBeEvent>) => {
248
+ // Pre-process events if needed
249
+ const processedEvents = preprocessEvents(events);
250
+
251
+ return (
252
+ <AutoBeEventMovie
253
+ events={processedEvents}
254
+ service={service}
255
+ last={last}
256
+ />
257
+ );
258
+ };
259
+ ```
260
+
261
+ ### Event Filtering
262
+
263
+ ```tsx
264
+ const filteredEvents = events.filter(event =>
265
+ !['vendorRequest', 'vendorResponse', 'jsonParseError'].includes(event.type)
266
+ );
267
+ ```
268
+
269
+ ## TypeScript Support
270
+
271
+ All components are fully typed with comprehensive interfaces:
272
+
273
+ ```tsx
274
+ interface IAutoBeEventMovieProps<Event extends AutoBeEvent> {
275
+ service: IAutoBeRpcService;
276
+ events: Event[];
277
+ last: boolean;
278
+ }
279
+ ```
280
+
281
+ ## Features
282
+
283
+ - 🎯 **Intelligent Routing**: Automatic event type detection and routing
284
+ - 📱 **Responsive Design**: Works seamlessly on all screen sizes
285
+ - 🔄 **Smart Grouping**: Automatic grouping of related events
286
+ - 📊 **Rich Statistics**: Built-in progress and error rate calculations
287
+ - 🎨 **Consistent Styling**: Unified design system across all components
288
+ - 💎 **Full TypeScript**: Complete type safety and IntelliSense support
289
+ - ⚡ **Optimized Performance**: Efficient rendering with minimal re-renders
290
+ - 🔧 **Highly Customizable**: Easy to extend and customize for specific needs
291
+ - 🎪 **Animation Support**: Smooth transitions and progress animations
292
+ - 📁 **File Management**: Built-in file download and management capabilities
293
+
294
+ ## Best Practices
295
+
296
+ 1. **Always use AutoBeEventMovie** as the main entry point for event rendering
297
+ 2. **Group related validation events** for better user experience
298
+ 3. **Provide meaningful timestamps** for all events
299
+ 4. **Use consistent naming** for custom event types
300
+ 5. **Handle edge cases** gracefully with null returns for unsupported events
@@ -0,0 +1,220 @@
1
+ import { ReactNode, useState } from "react";
2
+
3
+ import { EventCard } from "./EventCard";
4
+ import { EventContent } from "./EventContent";
5
+ import { EventIcon, EventIconType } from "./EventIcon";
6
+
7
+ export interface ICollapsibleEventGroupProps<T = any> {
8
+ /** Array of events of the same type */
9
+ events: T[];
10
+ /** Title for the group */
11
+ title: string;
12
+ /** Icon type for the group header */
13
+ iconType: EventIconType;
14
+ /** Function to render individual events */
15
+ renderEvent: (event: T, index: number) => ReactNode;
16
+ /** Function to get timestamp from event (for header) */
17
+ getTimestamp: (event: T) => string;
18
+ /** Optional custom summary content */
19
+ renderSummary?: (events: T[]) => ReactNode;
20
+ /** Initial collapsed state */
21
+ defaultCollapsed?: boolean;
22
+ /** Custom group description */
23
+ description?: string;
24
+ /** Card variant based on event status */
25
+ variant?: "default" | "success" | "error" | "warning";
26
+ }
27
+
28
+ /**
29
+ * Collapsible event group component Groups multiple events of the same type
30
+ * with expand/collapse functionality
31
+ */
32
+ export const CollapsibleEventGroup = <T,>(
33
+ props: ICollapsibleEventGroupProps<T>,
34
+ ) => {
35
+ const {
36
+ events,
37
+ title,
38
+ iconType,
39
+ renderEvent,
40
+ getTimestamp,
41
+ renderSummary,
42
+ defaultCollapsed = true,
43
+ description,
44
+ variant = "default",
45
+ } = props;
46
+
47
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
48
+
49
+ if (events.length === 0) {
50
+ return null;
51
+ }
52
+
53
+ // Use the latest event's timestamp for the group header
54
+ const latestTimestamp = getTimestamp(events[events.length - 1]);
55
+
56
+ const toggleCollapse = () => {
57
+ setIsCollapsed(!isCollapsed);
58
+ };
59
+
60
+ const defaultSummary = (
61
+ <>
62
+ {description && (
63
+ <>
64
+ {description}
65
+ <br />
66
+ <br />
67
+ </>
68
+ )}
69
+ <strong>Total Events:</strong> {events.length}
70
+ <br />
71
+ <strong>Status:</strong> {isCollapsed ? "Collapsed" : "Expanded"}
72
+ </>
73
+ );
74
+
75
+ return (
76
+ <EventCard variant={variant}>
77
+ {/* Header */}
78
+ <div
79
+ style={{
80
+ display: "flex",
81
+ alignItems: "center",
82
+ justifyContent: "space-between",
83
+ marginBottom: "1rem",
84
+ }}
85
+ >
86
+ <div
87
+ style={{
88
+ display: "flex",
89
+ alignItems: "center",
90
+ gap: "0.75rem",
91
+ }}
92
+ >
93
+ <EventIcon type={iconType} />
94
+
95
+ <div>
96
+ <h3
97
+ style={{
98
+ fontSize: "1.125rem",
99
+ fontWeight: "600",
100
+ color: "#1e293b",
101
+ margin: 0,
102
+ marginBottom: "0.25rem",
103
+ }}
104
+ >
105
+ {title}
106
+ </h3>
107
+ <div
108
+ style={{
109
+ fontSize: "0.75rem",
110
+ color: "#64748b",
111
+ }}
112
+ >
113
+ {events.length} event{events.length !== 1 ? "s" : ""}
114
+ </div>
115
+ </div>
116
+ </div>
117
+
118
+ <div
119
+ style={{
120
+ fontSize: "0.75rem",
121
+ color: "#64748b",
122
+ textAlign: "right",
123
+ }}
124
+ >
125
+ {latestTimestamp}
126
+ </div>
127
+ </div>
128
+
129
+ {/* Summary content when collapsed */}
130
+ {isCollapsed && (
131
+ <EventContent>
132
+ {renderSummary ? renderSummary(events) : defaultSummary}
133
+ </EventContent>
134
+ )}
135
+
136
+ {/* Individual events when expanded */}
137
+ {!isCollapsed && (
138
+ <div
139
+ style={{
140
+ display: "flex",
141
+ flexDirection: "column",
142
+ gap: "0.5rem",
143
+ }}
144
+ >
145
+ {events.map((event, index) => (
146
+ <div
147
+ key={index}
148
+ style={{
149
+ border: "1px solid #e2e8f0",
150
+ borderRadius: "0.5rem",
151
+ overflow: "hidden",
152
+ }}
153
+ >
154
+ {renderEvent(event, index)}
155
+ </div>
156
+ ))}
157
+ </div>
158
+ )}
159
+
160
+ {/* Expand/Collapse Button */}
161
+ <div
162
+ style={{
163
+ display: "flex",
164
+ justifyContent: "center",
165
+ marginTop: "1rem",
166
+ }}
167
+ >
168
+ <button
169
+ onClick={toggleCollapse}
170
+ style={{
171
+ display: "flex",
172
+ alignItems: "center",
173
+ gap: "0.5rem",
174
+ padding: "0.5rem 1rem",
175
+ backgroundColor: "#f8fafc",
176
+ border: "1px solid #e2e8f0",
177
+ borderRadius: "0.5rem",
178
+ cursor: "pointer",
179
+ fontSize: "0.875rem",
180
+ color: "#64748b",
181
+ transition: "all 0.2s ease",
182
+ }}
183
+ onMouseEnter={(e) => {
184
+ e.currentTarget.style.backgroundColor = "#f1f5f9";
185
+ e.currentTarget.style.borderColor = "#cbd5e1";
186
+ }}
187
+ onMouseLeave={(e) => {
188
+ e.currentTarget.style.backgroundColor = "#f8fafc";
189
+ e.currentTarget.style.borderColor = "#e2e8f0";
190
+ }}
191
+ >
192
+ <span>{isCollapsed ? "Expand" : "Collapse"}</span>
193
+ <div
194
+ style={{
195
+ width: "1rem",
196
+ height: "1rem",
197
+ display: "flex",
198
+ alignItems: "center",
199
+ justifyContent: "center",
200
+ transition: "transform 0.2s ease",
201
+ transform: isCollapsed ? "rotate(0deg)" : "rotate(180deg)",
202
+ }}
203
+ >
204
+ <svg
205
+ width="12"
206
+ height="12"
207
+ viewBox="0 0 24 24"
208
+ fill="currentColor"
209
+ style={{ color: "#64748b" }}
210
+ >
211
+ <path d="M7 10l5 5 5-5z" />
212
+ </svg>
213
+ </div>
214
+ </button>
215
+ </div>
216
+ </EventCard>
217
+ );
218
+ };
219
+
220
+ export default CollapsibleEventGroup;
@@ -0,0 +1,61 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface IEventCardProps {
4
+ children: ReactNode;
5
+ style?: React.CSSProperties;
6
+ className?: string;
7
+ variant?: "default" | "success" | "error" | "warning";
8
+ }
9
+
10
+ /**
11
+ * Common event card container component Provides consistent styling across all
12
+ * event components
13
+ */
14
+ export const EventCard = (props: IEventCardProps) => {
15
+ const { variant = "default" } = props;
16
+
17
+ const getVariantStyles = () => {
18
+ switch (variant) {
19
+ case "success":
20
+ return {
21
+ backgroundColor: "#f0fdf4",
22
+ border: "1px solid #bbf7d0",
23
+ boxShadow: "0 1px 3px 0 rgb(34 197 94 / 0.1)",
24
+ };
25
+ case "error":
26
+ return {
27
+ backgroundColor: "#fef2f2",
28
+ border: "1px solid #fecaca",
29
+ boxShadow: "0 1px 3px 0 rgb(239 68 68 / 0.1)",
30
+ };
31
+ case "warning":
32
+ return {
33
+ backgroundColor: "#fffbeb",
34
+ border: "1px solid #fed7aa",
35
+ boxShadow: "0 1px 3px 0 rgb(245 158 11 / 0.1)",
36
+ };
37
+ default:
38
+ return {
39
+ backgroundColor: "#f8fafc",
40
+ border: "1px solid #e2e8f0",
41
+ boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
42
+ };
43
+ }
44
+ };
45
+
46
+ return (
47
+ <div
48
+ className={props.className}
49
+ style={{
50
+ ...getVariantStyles(),
51
+ borderRadius: "0.75rem",
52
+ padding: "1.5rem",
53
+ ...props.style,
54
+ }}
55
+ >
56
+ {props.children}
57
+ </div>
58
+ );
59
+ };
60
+
61
+ export default EventCard;
@@ -0,0 +1,31 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface IEventContentProps {
4
+ children: ReactNode;
5
+ style?: React.CSSProperties;
6
+ }
7
+
8
+ /**
9
+ * Common event content component Provides consistent content area styling
10
+ * across all event components
11
+ */
12
+ export const EventContent = (props: IEventContentProps) => {
13
+ return (
14
+ <div
15
+ style={{
16
+ fontSize: "0.875rem",
17
+ lineHeight: "1.5",
18
+ color: "#475569",
19
+ backgroundColor: "#ffffff",
20
+ padding: "1rem",
21
+ borderRadius: "0.5rem",
22
+ border: "1px solid #e2e8f0",
23
+ ...props.style,
24
+ }}
25
+ >
26
+ {props.children}
27
+ </div>
28
+ );
29
+ };
30
+
31
+ export default EventContent;
@@ -0,0 +1,85 @@
1
+ import { ReactNode } from "react";
2
+
3
+ import { formatTime } from "../../utils/time";
4
+ import { EventIcon, EventIconType } from "./EventIcon";
5
+
6
+ export interface IEventHeaderProps {
7
+ title: string;
8
+ subtitle?: ReactNode;
9
+ timestamp: string;
10
+ iconType: EventIconType;
11
+ step?: number;
12
+ }
13
+
14
+ /**
15
+ * Common event header component Provides consistent header layout with icon,
16
+ * title, and timestamp
17
+ */
18
+ export const EventHeader = (props: IEventHeaderProps) => {
19
+ return (
20
+ <div
21
+ style={{
22
+ display: "flex",
23
+ alignItems: "center",
24
+ justifyContent: "space-between",
25
+ marginBottom: "1rem",
26
+ }}
27
+ >
28
+ <div
29
+ style={{
30
+ display: "flex",
31
+ alignItems: "center",
32
+ gap: "0.75rem",
33
+ }}
34
+ >
35
+ <EventIcon type={props.iconType} />
36
+
37
+ <div>
38
+ <h3
39
+ style={{
40
+ fontSize: "1.125rem",
41
+ fontWeight: "600",
42
+ color: "#1e293b",
43
+ margin: 0,
44
+ marginBottom: "0.25rem",
45
+ }}
46
+ >
47
+ {props.title}
48
+ </h3>
49
+ {props.subtitle && (
50
+ <div
51
+ style={{
52
+ fontSize: "0.75rem",
53
+ color: "#64748b",
54
+ }}
55
+ >
56
+ {props.subtitle}
57
+ </div>
58
+ )}
59
+ {props.step !== undefined && (
60
+ <div
61
+ style={{
62
+ fontSize: "0.75rem",
63
+ color: "#64748b",
64
+ }}
65
+ >
66
+ Step #{props.step}
67
+ </div>
68
+ )}
69
+ </div>
70
+ </div>
71
+
72
+ <div
73
+ style={{
74
+ fontSize: "0.75rem",
75
+ color: "#64748b",
76
+ textAlign: "right",
77
+ }}
78
+ >
79
+ {formatTime(props.timestamp)}
80
+ </div>
81
+ </div>
82
+ );
83
+ };
84
+
85
+ export default EventHeader;