@galangel/react-scroll-magic 1.0.2 β 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -112
- package/dist/Scroll/story/ai-chat/AIChatDemo.d.ts +3 -0
- package/dist/Scroll/story/ai-chat/components/AgentStepHeader.d.ts +13 -0
- package/dist/Scroll/story/ai-chat/components/ChatHeader.d.ts +7 -0
- package/dist/Scroll/story/ai-chat/components/ChatInput.d.ts +8 -0
- package/dist/Scroll/story/ai-chat/components/ChatStyles.d.ts +3 -0
- package/dist/Scroll/story/ai-chat/components/EmptyState.d.ts +3 -0
- package/dist/Scroll/story/ai-chat/components/OutputLineItem.d.ts +9 -0
- package/dist/Scroll/story/ai-chat/components/QuestionBubble.d.ts +8 -0
- package/dist/Scroll/story/ai-chat/components/ReasoningHeader.d.ts +13 -0
- package/dist/Scroll/story/ai-chat/components/SolutionHeader.d.ts +11 -0
- package/dist/Scroll/story/ai-chat/components/index.d.ts +9 -0
- package/dist/Scroll/story/ai-chat/hooks/index.d.ts +2 -0
- package/dist/Scroll/story/ai-chat/hooks/use-auto-scroll.d.ts +13 -0
- package/dist/Scroll/story/ai-chat/hooks/use-chat-messages.d.ts +9 -0
- package/dist/Scroll/story/ai-chat/index.d.ts +5 -0
- package/dist/Scroll/story/ai-chat/index.stories.d.ts +7 -0
- package/dist/Scroll/story/ai-chat/types/index.d.ts +22 -0
- package/dist/Scroll/story/ai-chat/utils/convert-to-items.d.ts +4 -0
- package/dist/Scroll/story/ai-chat/utils/generate-output-line.d.ts +3 -0
- package/dist/Scroll/story/ai-chat/utils/generate-question.d.ts +1 -0
- package/dist/Scroll/story/ai-chat/utils/index.d.ts +4 -0
- package/dist/Scroll/story/ai-chat/utils/step-config.d.ts +3 -0
- package/dist/cjs/index.js +1 -1
- package/dist/es/index.js +51 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,28 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.shields.io/badge/πͺ-React_Scroll_Magic-667eea?style=for-the-badge&labelColor=764ba2" alt="React Scroll Magic" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">πͺ React Scroll Magic</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Create magical scroll experiences with nested sticky headers, collapsible sections, and smooth animations.</strong>
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@galangel/react-scroll-magic"><img src="https://img.shields.io/npm/v/@galangel/react-scroll-magic.svg?style=flat-square&color=667eea" alt="npm version" /></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/@galangel/react-scroll-magic"><img src="https://img.shields.io/npm/dm/@galangel/react-scroll-magic.svg?style=flat-square&color=764ba2" alt="npm downloads" /></a>
|
|
14
|
+
<a href="https://github.com/galangel/react-scroll-magic/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat-square" alt="license" /></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/TypeScript-Ready-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
16
|
+
<img src="https://img.shields.io/badge/React-18+-61dafb?style=flat-square&logo=react&logoColor=white" alt="React 18+" />
|
|
17
|
+
</p>
|
|
8
18
|
|
|
9
|
-
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://galangel.github.io/react-scroll-magic/">π Live Demo & Documentation</a>
|
|
21
|
+
</p>
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
- **Click-to-Scroll**: Click any header to smoothly scroll to its content
|
|
13
|
-
- **Collapsible Sections**: Headers can expand/collapse their nested content
|
|
14
|
-
- **Infinite Scrolling**: Load more content when reaching the bottom
|
|
15
|
-
- **Nested Structure**: Support for deeply nested hierarchical content
|
|
16
|
-
- **Multiple Header Behaviors**: Choose between sticky, push, or normal header behavior
|
|
17
|
-
- **TypeScript Support**: Fully typed with comprehensive interfaces
|
|
18
|
-
- **Customizable Rendering**: Complete control over how items and loading states are rendered
|
|
23
|
+
---
|
|
19
24
|
|
|
20
|
-
##
|
|
25
|
+
## β¨ Key Features
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
| Feature | Description |
|
|
28
|
+
| ------------------------- | --------------------------------------------------------------------------- |
|
|
29
|
+
| π **Sticky Headers** | Headers stick to top as you scroll, with support for nested sticky behavior |
|
|
30
|
+
| π― **Nested Structure** | Create deeply nested hierarchies with items inside items |
|
|
31
|
+
| π¦ **Collapse/Expand** | Each section with nested content can be collapsed or expanded |
|
|
32
|
+
| βΎοΈ **Infinite Scrolling** | Built-in support for loading more items when reaching the bottom |
|
|
33
|
+
| π¨ **Fully Customizable** | Complete control over rendering via render props |
|
|
34
|
+
| π€ **TypeScript Ready** | Fully typed with comprehensive interfaces |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## π Quick Start
|
|
39
|
+
|
|
40
|
+
### Installation
|
|
23
41
|
|
|
24
42
|
```bash
|
|
25
|
-
npm
|
|
43
|
+
npm install @galangel/react-scroll-magic
|
|
26
44
|
```
|
|
27
45
|
|
|
28
46
|
or
|
|
@@ -31,53 +49,85 @@ or
|
|
|
31
49
|
yarn add @galangel/react-scroll-magic
|
|
32
50
|
```
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Here is a basic example of how to use the Scroll Component in your React application:
|
|
52
|
+
### Basic Usage
|
|
37
53
|
|
|
38
54
|
```jsx
|
|
39
|
-
import React from 'react';
|
|
40
55
|
import { Scroll } from '@galangel/react-scroll-magic';
|
|
41
56
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{collapse
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Simple item without nesting
|
|
66
|
-
render: () => <div style={{ padding: '10px' }}>Simple Item</div>,
|
|
67
|
-
},
|
|
68
|
-
];
|
|
69
|
-
|
|
57
|
+
const items = [
|
|
58
|
+
{
|
|
59
|
+
id: 'section-1',
|
|
60
|
+
render: ({ collapse }) => (
|
|
61
|
+
<div style={{ padding: '10px', backgroundColor: '#f0f0f0' }}>
|
|
62
|
+
Header 1
|
|
63
|
+
{collapse && (
|
|
64
|
+
<button onClick={collapse.isOpen ? collapse.close : collapse.open}>{collapse.isOpen ? 'βΌ' : 'βΆ'}</button>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
),
|
|
68
|
+
nestedItems: [
|
|
69
|
+
{ render: () => <div style={{ padding: '10px' }}>Item 1.1</div> },
|
|
70
|
+
{ render: () => <div style={{ padding: '10px' }}>Item 1.2</div> },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'section-2',
|
|
75
|
+
render: () => <div style={{ padding: '10px' }}>Simple Item</div>,
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
function App() {
|
|
70
80
|
return (
|
|
71
81
|
<div style={{ height: '400px', width: '100%' }}>
|
|
72
|
-
<Scroll items={items}
|
|
82
|
+
<Scroll items={items} headerBehavior="push" scrollBehavior="smooth" />
|
|
73
83
|
</div>
|
|
74
84
|
);
|
|
75
|
-
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## π API Reference
|
|
91
|
+
|
|
92
|
+
### Scroll Component Props
|
|
76
93
|
|
|
77
|
-
|
|
94
|
+
| Prop | Type | Default | Description |
|
|
95
|
+
| ---------------- | --------------------------------- | ---------- | -------------------------------------------------------------------------------------- |
|
|
96
|
+
| `items` | `Items` | Required | Array of items to render. Each item has a `render` function and optional `nestedItems` |
|
|
97
|
+
| `stickTo` | `'top' \| 'bottom' \| 'all'` | `'all'` | Where headers should stick when scrolling |
|
|
98
|
+
| `scrollBehavior` | `'auto' \| 'instant' \| 'smooth'` | `'smooth'` | CSS scroll-behavior when clicking headers |
|
|
99
|
+
| `headerBehavior` | `'stick' \| 'push' \| 'none'` | `'none'` | How headers behave when scrolling |
|
|
100
|
+
| `loading` | `Loading` | Optional | Configuration for infinite scrolling |
|
|
101
|
+
|
|
102
|
+
### Item Structure
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
interface Item {
|
|
106
|
+
id?: string; // Optional unique identifier
|
|
107
|
+
render: (props: {
|
|
108
|
+
// Render function for the item
|
|
109
|
+
collapse?: {
|
|
110
|
+
isOpen: boolean; // Current collapse state
|
|
111
|
+
open: () => void; // Function to expand
|
|
112
|
+
close: () => void; // Function to collapse
|
|
113
|
+
};
|
|
114
|
+
}) => JSX.Element;
|
|
115
|
+
nestedItems?: Item[]; // Optional nested items (makes this a header)
|
|
116
|
+
}
|
|
78
117
|
```
|
|
79
118
|
|
|
80
|
-
###
|
|
119
|
+
### Loading Type Definition
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
interface Loading {
|
|
123
|
+
onBottomReached?: () => Promise<void>; // Callback when user scrolls to bottom
|
|
124
|
+
render?: (isLoading: boolean) => JSX.Element; // Custom loading indicator renderer
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## βΎοΈ Infinite Scrolling Example
|
|
81
131
|
|
|
82
132
|
```jsx
|
|
83
133
|
import React, { useState } from 'react';
|
|
@@ -90,7 +140,6 @@ const InfiniteScrollExample = () => {
|
|
|
90
140
|
]);
|
|
91
141
|
|
|
92
142
|
const loadMoreItems = async () => {
|
|
93
|
-
// Simulate API call
|
|
94
143
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
95
144
|
|
|
96
145
|
const newItems = Array.from({ length: 10 }, (_, i) => ({
|
|
@@ -115,106 +164,194 @@ const InfiniteScrollExample = () => {
|
|
|
115
164
|
};
|
|
116
165
|
```
|
|
117
166
|
|
|
118
|
-
|
|
167
|
+
---
|
|
119
168
|
|
|
120
|
-
|
|
169
|
+
## π¨ Styling & CSS Classes
|
|
121
170
|
|
|
122
|
-
|
|
123
|
-
| ---------------- | --------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- |
|
|
124
|
-
| `items` | `Items` | Required | Array of items to render. Each item has a `render` function and optional `nestedItems` |
|
|
125
|
-
| `stickTo` | `'top' \| 'bottom' \| 'all'` | `'all'` | Where headers should stick when scrolling |
|
|
126
|
-
| `scrollBehavior` | `'auto' \| 'instant' \| 'smooth'` | `'smooth'` | CSS scroll-behavior when clicking headers to scroll to content |
|
|
127
|
-
| `headerBehavior` | `'stick' \| 'push' \| 'none'` | `'none'` | How headers behave: `stick` = sticky positioning, `push` = headers push down content, `none` = normal flow |
|
|
128
|
-
| `loading` | `Loading` | Optional | Configuration for infinite scrolling and loading states |
|
|
171
|
+
The component uses semantic CSS classes that you can target for custom styling. Here's a complete reference:
|
|
129
172
|
|
|
130
|
-
###
|
|
173
|
+
### CSS Class Reference
|
|
131
174
|
|
|
132
|
-
|
|
133
|
-
|
|
175
|
+
| Class Name | Element | Description |
|
|
176
|
+
| ------------------------- | ------- | ----------------------------------------------- |
|
|
177
|
+
| `.scroll-list` | `<ul>` | Main scroll container element |
|
|
178
|
+
| `.scroll-item` | `<li>` | Regular list item (items without `nestedItems`) |
|
|
179
|
+
| `.scroll-header` | `<li>` | Header item (items with `nestedItems`) |
|
|
180
|
+
| `.scroll-header.stick` | `<li>` | Header with `headerBehavior="stick"` |
|
|
181
|
+
| `.scroll-header.push` | `<li>` | Header with `headerBehavior="push"` |
|
|
182
|
+
| `.scroll-header.none` | `<li>` | Header with `headerBehavior="none"` |
|
|
183
|
+
| `.scroll-loading` | `<li>` | Loading indicator container |
|
|
184
|
+
| `.scroll-loading.loading` | `<li>` | Loading indicator when actively loading |
|
|
134
185
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
186
|
+
### Styling Examples
|
|
187
|
+
|
|
188
|
+
```css
|
|
189
|
+
/* Main scroll container */
|
|
190
|
+
.scroll-list {
|
|
191
|
+
list-style: none;
|
|
192
|
+
margin: 0;
|
|
193
|
+
padding: 0;
|
|
194
|
+
height: 100%;
|
|
195
|
+
overflow-y: auto;
|
|
139
196
|
}
|
|
140
197
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
};
|
|
198
|
+
/* All items (headers and regular items) */
|
|
199
|
+
.scroll-item,
|
|
200
|
+
.scroll-header {
|
|
201
|
+
width: 100%;
|
|
202
|
+
box-sizing: border-box;
|
|
147
203
|
}
|
|
148
|
-
```
|
|
149
204
|
|
|
150
|
-
|
|
205
|
+
/* Regular items */
|
|
206
|
+
.scroll-item {
|
|
207
|
+
padding: 12px 16px;
|
|
208
|
+
background-color: #fff;
|
|
209
|
+
border-bottom: 1px solid #eee;
|
|
210
|
+
}
|
|
151
211
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
212
|
+
/* Header items - base styles */
|
|
213
|
+
.scroll-header {
|
|
214
|
+
padding: 16px 20px;
|
|
215
|
+
background-color: #f5f5f5;
|
|
216
|
+
font-weight: 600;
|
|
217
|
+
cursor: pointer;
|
|
218
|
+
border-bottom: 1px solid #ddd;
|
|
156
219
|
}
|
|
157
|
-
```
|
|
158
220
|
|
|
159
|
-
|
|
221
|
+
/* Sticky header behavior */
|
|
222
|
+
.scroll-header.stick {
|
|
223
|
+
position: sticky;
|
|
224
|
+
/* top/bottom values are set dynamically by the component */
|
|
225
|
+
}
|
|
160
226
|
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
- **Nested Structure**: Items can be nested to any depth for complex hierarchical layouts
|
|
227
|
+
/* Push header behavior */
|
|
228
|
+
.scroll-header.push {
|
|
229
|
+
position: sticky;
|
|
230
|
+
/* top value is set dynamically by the component */
|
|
231
|
+
}
|
|
167
232
|
|
|
168
|
-
|
|
233
|
+
/* Header hover effect */
|
|
234
|
+
.scroll-header:hover {
|
|
235
|
+
background-color: #e8e8e8;
|
|
236
|
+
}
|
|
169
237
|
|
|
170
|
-
|
|
238
|
+
/* Loading indicator */
|
|
239
|
+
.scroll-loading {
|
|
240
|
+
display: none;
|
|
241
|
+
padding: 20px;
|
|
242
|
+
text-align: center;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.scroll-loading.loading {
|
|
246
|
+
display: block;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Loading spinner animation */
|
|
250
|
+
.scroll-loading.loading::after {
|
|
251
|
+
content: '';
|
|
252
|
+
display: inline-block;
|
|
253
|
+
width: 20px;
|
|
254
|
+
height: 20px;
|
|
255
|
+
border: 2px solid #ccc;
|
|
256
|
+
border-top-color: #667eea;
|
|
257
|
+
border-radius: 50%;
|
|
258
|
+
animation: spin 1s linear infinite;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@keyframes spin {
|
|
262
|
+
to {
|
|
263
|
+
transform: rotate(360deg);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Dark Theme Example
|
|
171
269
|
|
|
172
270
|
```css
|
|
173
|
-
/*
|
|
271
|
+
/* Dark theme styling */
|
|
174
272
|
.scroll-list {
|
|
175
|
-
|
|
273
|
+
background-color: #1a202c;
|
|
176
274
|
}
|
|
177
275
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
276
|
+
.scroll-item {
|
|
277
|
+
background-color: #2d3748;
|
|
278
|
+
color: #e2e8f0;
|
|
279
|
+
border-bottom: 1px solid #4a5568;
|
|
181
280
|
}
|
|
182
281
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
282
|
+
.scroll-header {
|
|
283
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
284
|
+
color: #fff;
|
|
285
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
187
286
|
}
|
|
188
287
|
|
|
189
|
-
|
|
190
|
-
.
|
|
191
|
-
/* Push behavior styles */
|
|
288
|
+
.scroll-header:hover {
|
|
289
|
+
filter: brightness(1.1);
|
|
192
290
|
}
|
|
193
291
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
292
|
+
.scroll-loading.loading::after {
|
|
293
|
+
border-color: #4a5568;
|
|
294
|
+
border-top-color: #667eea;
|
|
197
295
|
}
|
|
198
296
|
```
|
|
199
297
|
|
|
200
|
-
|
|
298
|
+
### Important Notes
|
|
299
|
+
|
|
300
|
+
> β οΈ **Container Height Required**: The scroll container must have a defined height for scrolling to work properly.
|
|
201
301
|
|
|
202
302
|
```jsx
|
|
203
303
|
<div style={{ height: '400px' }}>
|
|
204
304
|
{' '}
|
|
205
|
-
{/*
|
|
305
|
+
{/* or height: '100vh' */}
|
|
206
306
|
<Scroll items={items} />
|
|
207
307
|
</div>
|
|
208
308
|
```
|
|
209
309
|
|
|
210
|
-
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## π‘ Tips & Best Practices
|
|
313
|
+
|
|
314
|
+
| Tip | Description |
|
|
315
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
316
|
+
| π― **Use Unique IDs** | Assign unique `id` properties to items for better performance and scroll-to functionality |
|
|
317
|
+
| π **Stop Propagation** | When adding click handlers inside items (like collapse buttons), use `e.stopPropagation()` to prevent scroll-to behavior |
|
|
318
|
+
| π **Set Container Height** | The Scroll component needs a container with a defined height (`height: 100vh` or fixed pixels) |
|
|
319
|
+
| π¨ **headerBehavior: "push"** | The "push" mode creates a natural feel where headers push each other out of view |
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## π€ Real World Example: AI Chat
|
|
324
|
+
|
|
325
|
+
Check out the [AI Chat demo](https://galangel.github.io/react-scroll-magic/?path=/story/examples-ai-chat--ai-chat) showcasing a complex real-world use case with:
|
|
326
|
+
|
|
327
|
+
- π¬ **Question β Response Flow**: Messages with nested reasoning steps
|
|
328
|
+
- π§ **Collapsible Reasoning**: Auto-collapse when complete
|
|
329
|
+
- π **Deep Nesting**: Four levels of nesting working seamlessly
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## π License
|
|
211
334
|
|
|
212
335
|
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
|
|
213
336
|
|
|
214
|
-
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## π€ Contributing
|
|
215
340
|
|
|
216
341
|
Contributions are welcome! Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines before submitting a pull request.
|
|
217
342
|
|
|
218
|
-
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## π¬ Contact
|
|
346
|
+
|
|
347
|
+
For any questions or feedback, please [open an issue](https://github.com/galangel/react-scroll-magic/issues) on GitHub.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
<p align="center">
|
|
352
|
+
Made with πͺ by <a href="https://github.com/galangel">@galangel</a>
|
|
353
|
+
</p>
|
|
219
354
|
|
|
220
|
-
|
|
355
|
+
<p align="center">
|
|
356
|
+
<a href="https://www.buymeacoffee.com/galangel"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50" /></a>
|
|
357
|
+
</p>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { AgentStep } from '../types';
|
|
3
|
+
|
|
4
|
+
interface AgentStepHeaderProps {
|
|
5
|
+
step: AgentStep;
|
|
6
|
+
collapse?: {
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
open: () => void;
|
|
9
|
+
close: () => void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare const AgentStepHeader: React.FC<AgentStepHeaderProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ReasoningHeaderProps {
|
|
4
|
+
messageId: string;
|
|
5
|
+
messageIsComplete?: boolean;
|
|
6
|
+
collapse?: {
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
open: () => void;
|
|
9
|
+
close: () => void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare const ReasoningHeader: React.FC<ReasoningHeaderProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { QuestionBubble } from './QuestionBubble';
|
|
2
|
+
export { AgentStepHeader } from './AgentStepHeader';
|
|
3
|
+
export { ReasoningHeader } from './ReasoningHeader';
|
|
4
|
+
export { SolutionHeader } from './SolutionHeader';
|
|
5
|
+
export { OutputLineItem } from './OutputLineItem';
|
|
6
|
+
export { ChatHeader } from './ChatHeader';
|
|
7
|
+
export { ChatInput } from './ChatInput';
|
|
8
|
+
export { EmptyState } from './EmptyState';
|
|
9
|
+
export { ChatStyles } from './ChatStyles';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface UseAutoScrollOptions {
|
|
2
|
+
threshold?: number;
|
|
3
|
+
scrollIdleDelay?: number;
|
|
4
|
+
hasContent?: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface UseAutoScrollReturn {
|
|
7
|
+
scrollContainerRef: React.RefObject<HTMLDivElement>;
|
|
8
|
+
shouldAutoScroll: () => boolean;
|
|
9
|
+
scrollToBottom: () => void;
|
|
10
|
+
forceAutoScrollOn: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const useAutoScroll: ({ threshold, scrollIdleDelay, hasContent, }?: UseAutoScrollOptions) => UseAutoScrollReturn;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface OutputLine {
|
|
2
|
+
id: string;
|
|
3
|
+
text: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AgentStep {
|
|
6
|
+
id: string;
|
|
7
|
+
type: 'thinking' | 'searching' | 'analyzing' | 'solution';
|
|
8
|
+
title: string;
|
|
9
|
+
outputs: OutputLine[];
|
|
10
|
+
isComplete: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ChatMessage {
|
|
13
|
+
id: string;
|
|
14
|
+
question: string;
|
|
15
|
+
steps: AgentStep[];
|
|
16
|
+
isComplete: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface StepConfig {
|
|
19
|
+
icon: string;
|
|
20
|
+
title: string;
|
|
21
|
+
bgColor: string;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const generateQuestion: () => string;
|
package/dist/cjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("react/jsx-runtime"),l=require("react"),w=(e=[])=>e.slice(0,e.length-1).map((u,h)=>e.slice(0,h+1)),k=l.createContext({getTopHeadersTotalHeight:()=>0,getBottomHeadersTotalHeight:()=>0,scrollToView:()=>{},setListRef:()=>{},stickTo:"all",scrollBehavior:"smooth",headerBehavior:"none",addHeader:()=>{},headerCollaspeOpen:()=>{},headerCollaspeClose:()=>{},collapsedPaths:[]}),z=()=>l.useContext(k),F=({children:e,stickTo:t="all",scrollBehavior:g="smooth",headerBehavior:u="none"})=>{const[h,p]=l.useState(null),[i,r]=l.useState([]),a=l.useRef({}),b=s=>{const n=a.current[s.join("-")],c=n.nextElementSibling;if(h&&c){const C=window.getComputedStyle(c),d=n.getBoundingClientRect().height,o=f(s),S=parseFloat(C.marginTop)+parseFloat(C.marginBottom)+parseFloat(C.paddingTop)+parseFloat(C.paddingBottom)+parseFloat(C.borderTopWidth)+parseFloat(C.borderBottomWidth),j=Math.ceil(t==="bottom"?c.offsetTop-d:c.offsetTop-o-d+S);h.scrollTo({top:j,behavior:g})}},x=(s,n)=>{a.current[n.join("-")]=s},f=(s=[])=>{const n=w(s),c=n.map(o=>o.join("-"));if(u==="stick"){const o=n.reduce((H,y)=>{const P=y[y.length-1],O=Array.from({length:P},(I,L)=>[...y.slice(0,y.length-1),L]).map(I=>I.join("-"));return H.push(...O),H},[]);c.push(...o);const S=s[s.length-1],j=Array.from({length:S},(H,y)=>[...s.slice(0,s.length-1),y]).map(H=>H.join("-"));c.push(...j)}return c.map(o=>a.current[o]).reduce((o,S)=>{var H;return o+((H=S==null?void 0:S.getBoundingClientRect)==null?void 0:H.call(S).height)||0},0)},T=(s=[])=>{const n=s[s.length-1];return Object.entries(a.current).reduce((d,[o,S])=>{const j=o.split("-").map(Number);return j.length===1&&j[0]>n&&d.push(S),d},[]).reduce((d,o)=>{var j;return d+((j=o==null?void 0:o.getBoundingClientRect)==null?void 0:j.call(o).height)||0},0)},R=s=>{const n=s.join("-");i.includes(n)&&r(c=>c.filter(C=>C!==n))},B=s=>{const n=s.join("-");i.includes(n)||r(c=>[...c,n])};return m.jsx(k.Provider,{value:{addHeader:x,getTopHeadersTotalHeight:f,getBottomHeadersTotalHeight:T,stickTo:t,scrollToView:b,setListRef:p,scrollBehavior:g,headerBehavior:u,headerCollaspeOpen:R,headerCollaspeClose:B,collapsedPaths:i},children:e})},M=({path:e,itemId:t,itemRender:g})=>{const{getTopHeadersTotalHeight:u,getBottomHeadersTotalHeight:h,scrollToView:p,stickTo:i,headerBehavior:r,addHeader:a,headerCollaspeClose:b,headerCollaspeOpen:x,collapsedPaths:f}=z(),T=l.useRef(null),R=()=>{p(e)};l.useEffect(()=>{if(T.current){const d=T.current;a(d,e)}},[T]);const B=l.useMemo(()=>{if(r==="stick"){let d="auto",o="auto";return d=i==="top"||i==="all"?u(e):"auto",o=i==="bottom"||i==="all"?h(e):"auto",{top:d,bottom:o,zIndex:100-e.length}}else if(r==="push")return{top:u(e),zIndex:100-e.length}},[r,e,i]),s=l.useCallback(()=>x(e),[x,e]),n=l.useCallback(()=>b(e),[b,e]),c=l.useMemo(()=>f.includes(e.join("-")),[f]),C=l.useMemo(()=>g({collapse:{open:s,close:n,isOpen:!c}}),[g,c,s,n]);return m.jsx("li",{id:t,onClick:R,className:`scroll-header ${r} `,style:{...B},"aria-label":"Scroll Header",role:"heading","aria-level":e.length,ref:T,children:C})},N=({itemRender:e,itemId:t})=>m.jsx("li",{id:t,role:"listitem","aria-label":"Scroll Item",className:"scroll-item ",children:e({})}),E={display:"none"},v=({headerBehavior:e,items:t,path:g=[],collapsedPaths:u})=>{const h=e==="push"?"section":l.Fragment;return m.jsx("section",{children:t.map((p,i)=>{var a;const r=[...g,i];if((a=p.nestedItems)!=null&&a.length){const x=u.includes(r.join("-"))?E:void 0;return m.jsxs(h,{children:[m.jsx(M,{path:r,itemRender:p.render,itemId:p.id}),m.jsx("section",{style:x,children:v({items:p.nestedItems,headerBehavior:e,path:r,collapsedPaths:u})})]},r.join("-"))}else return m.jsx(N,{itemRender:p.render,itemId:p.id},r.join("-"))})})},V=({loading:e})=>e?m.jsx("li",{role:"listitem","aria-label":"Scroll Loading",className:`scroll-loading ${e?"loading":""}`}):null,W=({items:e,loading:t})=>{const{setListRef:g,headerBehavior:u,collapsedPaths:h,scrollBehavior:p}=z(),[i,r]=l.useState(!1),a=l.useRef(null);l.useEffect(()=>{a.current&&g(a.current)},[a]);const b=l.useCallback(x=>{if(e.length===0||!(t!=null&&t.onBottomReached))return;const f=x.target;Math.floor(f.scrollHeight-f.scrollTop)<f.clientHeight+10&&(f.dataset.loading||(f.dataset.loading="true",r(!0),t.onBottomReached().finally(()=>{f.dataset.loading="",r(!1)})))},[e.length===0,t==null?void 0:t.onBottomReached]);return m.jsxs("ul",{ref:a,className:"scroll-list",onScroll:t!=null&&t.onBottomReached?b:void 0,style:{scrollBehavior:p},children:[v({items:e,headerBehavior:u,collapsedPaths:h}),t!=null&&t.render?t.render(i):m.jsx(V,{loading:i})]})},_=({stickTo:e,scrollBehavior:t,headerBehavior:g,loading:u,items:h})=>m.jsx(F,{headerBehavior:g,stickTo:e,scrollBehavior:t,children:m.jsx(W,{loading:u,items:h})});exports.Scroll=_;
|
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as C, jsxs as
|
|
2
|
-
import B, { useState as P, useRef as k, useEffect as
|
|
3
|
-
const W = (e = []) => e.slice(0, e.length - 1).map((d,
|
|
1
|
+
import { jsx as C, jsxs as L } from "react/jsx-runtime";
|
|
2
|
+
import B, { useState as P, useRef as k, useEffect as O, useMemo as j, useCallback as z } from "react";
|
|
3
|
+
const W = (e = []) => e.slice(0, e.length - 1).map((d, m) => e.slice(0, m + 1)), w = B.createContext({
|
|
4
4
|
getTopHeadersTotalHeight: () => 0,
|
|
5
5
|
getBottomHeadersTotalHeight: () => 0,
|
|
6
6
|
scrollToView: () => {
|
|
@@ -17,40 +17,40 @@ const W = (e = []) => e.slice(0, e.length - 1).map((d, h) => e.slice(0, h + 1)),
|
|
|
17
17
|
headerCollaspeClose: () => {
|
|
18
18
|
},
|
|
19
19
|
collapsedPaths: []
|
|
20
|
-
}), F = () => B.useContext(
|
|
20
|
+
}), F = () => B.useContext(w), _ = ({
|
|
21
21
|
children: e,
|
|
22
22
|
stickTo: t = "all",
|
|
23
23
|
scrollBehavior: u = "smooth",
|
|
24
24
|
headerBehavior: d = "none"
|
|
25
25
|
}) => {
|
|
26
|
-
const [
|
|
26
|
+
const [m, g] = P(null), [c, l] = P([]), i = k({}), b = (o) => {
|
|
27
27
|
const n = i.current[o.join("-")], r = n.nextElementSibling;
|
|
28
|
-
if (
|
|
29
|
-
const p = window.getComputedStyle(r), a = n.getBoundingClientRect().height, s =
|
|
30
|
-
|
|
28
|
+
if (m && r) {
|
|
29
|
+
const p = window.getComputedStyle(r), a = n.getBoundingClientRect().height, s = h(o), f = parseFloat(p.marginTop) + parseFloat(p.marginBottom) + parseFloat(p.paddingTop) + parseFloat(p.paddingBottom) + parseFloat(p.borderTopWidth) + parseFloat(p.borderBottomWidth), H = Math.ceil(t === "bottom" ? r.offsetTop - a : r.offsetTop - s - a + f);
|
|
30
|
+
m.scrollTo({ top: H, behavior: u });
|
|
31
31
|
}
|
|
32
|
-
},
|
|
32
|
+
}, S = (o, n) => {
|
|
33
33
|
i.current[n.join("-")] = o;
|
|
34
|
-
},
|
|
34
|
+
}, h = (o = []) => {
|
|
35
35
|
const n = W(o), r = n.map((s) => s.join("-"));
|
|
36
36
|
if (d === "stick") {
|
|
37
|
-
const s = n.reduce((
|
|
37
|
+
const s = n.reduce((T, y) => {
|
|
38
38
|
const M = y[y.length - 1], E = Array.from({ length: M }, (v, V) => [
|
|
39
39
|
...y.slice(0, y.length - 1),
|
|
40
40
|
V
|
|
41
41
|
]).map((v) => v.join("-"));
|
|
42
|
-
return
|
|
42
|
+
return T.push(...E), T;
|
|
43
43
|
}, []);
|
|
44
44
|
r.push(...s);
|
|
45
|
-
const f = o[o.length - 1], H = Array.from({ length: f }, (
|
|
45
|
+
const f = o[o.length - 1], H = Array.from({ length: f }, (T, y) => [
|
|
46
46
|
...o.slice(0, o.length - 1),
|
|
47
47
|
y
|
|
48
|
-
]).map((
|
|
48
|
+
]).map((T) => T.join("-"));
|
|
49
49
|
r.push(...H);
|
|
50
50
|
}
|
|
51
51
|
return r.map((s) => i.current[s]).reduce((s, f) => {
|
|
52
|
-
var
|
|
53
|
-
return s + ((
|
|
52
|
+
var T;
|
|
53
|
+
return s + ((T = f == null ? void 0 : f.getBoundingClientRect) == null ? void 0 : T.call(f).height) || 0;
|
|
54
54
|
}, 0);
|
|
55
55
|
}, x = (o = []) => {
|
|
56
56
|
const n = o[o.length - 1];
|
|
@@ -69,15 +69,15 @@ const W = (e = []) => e.slice(0, e.length - 1).map((d, h) => e.slice(0, h + 1)),
|
|
|
69
69
|
c.includes(n) || l((r) => [...r, n]);
|
|
70
70
|
};
|
|
71
71
|
return /* @__PURE__ */ C(
|
|
72
|
-
|
|
72
|
+
w.Provider,
|
|
73
73
|
{
|
|
74
74
|
value: {
|
|
75
|
-
addHeader:
|
|
76
|
-
getTopHeadersTotalHeight:
|
|
75
|
+
addHeader: S,
|
|
76
|
+
getTopHeadersTotalHeight: h,
|
|
77
77
|
getBottomHeadersTotalHeight: x,
|
|
78
78
|
stickTo: t,
|
|
79
|
-
scrollToView:
|
|
80
|
-
setListRef:
|
|
79
|
+
scrollToView: b,
|
|
80
|
+
setListRef: g,
|
|
81
81
|
scrollBehavior: u,
|
|
82
82
|
headerBehavior: d,
|
|
83
83
|
headerCollaspeOpen: I,
|
|
@@ -90,18 +90,18 @@ const W = (e = []) => e.slice(0, e.length - 1).map((d, h) => e.slice(0, h + 1)),
|
|
|
90
90
|
}, A = ({ path: e, itemId: t, itemRender: u }) => {
|
|
91
91
|
const {
|
|
92
92
|
getTopHeadersTotalHeight: d,
|
|
93
|
-
getBottomHeadersTotalHeight:
|
|
94
|
-
scrollToView:
|
|
93
|
+
getBottomHeadersTotalHeight: m,
|
|
94
|
+
scrollToView: g,
|
|
95
95
|
stickTo: c,
|
|
96
96
|
headerBehavior: l,
|
|
97
97
|
addHeader: i,
|
|
98
|
-
headerCollaspeClose:
|
|
99
|
-
headerCollaspeOpen:
|
|
100
|
-
collapsedPaths:
|
|
98
|
+
headerCollaspeClose: b,
|
|
99
|
+
headerCollaspeOpen: S,
|
|
100
|
+
collapsedPaths: h
|
|
101
101
|
} = F(), x = k(null), I = () => {
|
|
102
|
-
|
|
102
|
+
g(e);
|
|
103
103
|
};
|
|
104
|
-
|
|
104
|
+
O(() => {
|
|
105
105
|
if (x.current) {
|
|
106
106
|
const a = x.current;
|
|
107
107
|
i(a, e);
|
|
@@ -110,10 +110,10 @@ const W = (e = []) => e.slice(0, e.length - 1).map((d, h) => e.slice(0, h + 1)),
|
|
|
110
110
|
const R = j(() => {
|
|
111
111
|
if (l === "stick") {
|
|
112
112
|
let a = "auto", s = "auto";
|
|
113
|
-
return a = c === "top" || c === "all" ? d(e) : "auto", s = c === "bottom" || c === "all" ?
|
|
113
|
+
return a = c === "top" || c === "all" ? d(e) : "auto", s = c === "bottom" || c === "all" ? m(e) : "auto", { top: a, bottom: s, zIndex: 100 - e.length };
|
|
114
114
|
} else if (l === "push")
|
|
115
115
|
return { top: d(e), zIndex: 100 - e.length };
|
|
116
|
-
}, [l, e, c]), o = z(() =>
|
|
116
|
+
}, [l, e, c]), o = z(() => S(e), [S, e]), n = z(() => b(e), [b, e]), r = j(() => h.includes(e.join("-")), [h]), p = j(
|
|
117
117
|
() => u({
|
|
118
118
|
collapse: {
|
|
119
119
|
open: o,
|
|
@@ -137,49 +137,49 @@ const W = (e = []) => e.slice(0, e.length - 1).map((d, h) => e.slice(0, h + 1)),
|
|
|
137
137
|
children: p
|
|
138
138
|
}
|
|
139
139
|
);
|
|
140
|
-
}, $ = ({ itemRender: e, itemId: t }) => /* @__PURE__ */ C("li", { id: t, role: "listitem", "aria-label": "Scroll Item", className: "scroll-item ", children: e({}) }), q = {
|
|
141
|
-
const
|
|
142
|
-
return /* @__PURE__ */ C("section", { children: t.map((
|
|
140
|
+
}, $ = ({ itemRender: e, itemId: t }) => /* @__PURE__ */ C("li", { id: t, role: "listitem", "aria-label": "Scroll Item", className: "scroll-item ", children: e({}) }), q = { display: "none" }, N = ({ headerBehavior: e, items: t, path: u = [], collapsedPaths: d }) => {
|
|
141
|
+
const m = e === "push" ? "section" : B.Fragment;
|
|
142
|
+
return /* @__PURE__ */ C("section", { children: t.map((g, c) => {
|
|
143
143
|
var i;
|
|
144
144
|
const l = [...u, c];
|
|
145
|
-
if ((i =
|
|
146
|
-
const S = d.includes(l.join("-")) ? q :
|
|
147
|
-
return /* @__PURE__ */
|
|
148
|
-
/* @__PURE__ */ C(A, { path: l, itemRender:
|
|
149
|
-
/* @__PURE__ */ C("section", { style: S, children: N({ items:
|
|
145
|
+
if ((i = g.nestedItems) != null && i.length) {
|
|
146
|
+
const S = d.includes(l.join("-")) ? q : void 0;
|
|
147
|
+
return /* @__PURE__ */ L(m, { children: [
|
|
148
|
+
/* @__PURE__ */ C(A, { path: l, itemRender: g.render, itemId: g.id }),
|
|
149
|
+
/* @__PURE__ */ C("section", { style: S, children: N({ items: g.nestedItems, headerBehavior: e, path: l, collapsedPaths: d }) })
|
|
150
150
|
] }, l.join("-"));
|
|
151
151
|
} else
|
|
152
|
-
return /* @__PURE__ */ C($, { itemRender:
|
|
152
|
+
return /* @__PURE__ */ C($, { itemRender: g.render, itemId: g.id }, l.join("-"));
|
|
153
153
|
}) });
|
|
154
154
|
}, D = ({ loading: e }) => e ? /* @__PURE__ */ C("li", { role: "listitem", "aria-label": "Scroll Loading", className: `scroll-loading ${e ? "loading" : ""}` }) : null, G = ({ items: e, loading: t }) => {
|
|
155
|
-
const { setListRef: u, headerBehavior: d, collapsedPaths:
|
|
156
|
-
|
|
155
|
+
const { setListRef: u, headerBehavior: d, collapsedPaths: m, scrollBehavior: g } = F(), [c, l] = B.useState(!1), i = k(null);
|
|
156
|
+
O(() => {
|
|
157
157
|
i.current && u(i.current);
|
|
158
158
|
}, [i]);
|
|
159
|
-
const
|
|
160
|
-
(
|
|
159
|
+
const b = z(
|
|
160
|
+
(S) => {
|
|
161
161
|
if (e.length === 0 || !(t != null && t.onBottomReached)) return;
|
|
162
|
-
const
|
|
163
|
-
Math.floor(
|
|
164
|
-
|
|
162
|
+
const h = S.target;
|
|
163
|
+
Math.floor(h.scrollHeight - h.scrollTop) < h.clientHeight + 10 && (h.dataset.loading || (h.dataset.loading = "true", l(!0), t.onBottomReached().finally(() => {
|
|
164
|
+
h.dataset.loading = "", l(!1);
|
|
165
165
|
})));
|
|
166
166
|
},
|
|
167
167
|
[e.length === 0, t == null ? void 0 : t.onBottomReached]
|
|
168
168
|
);
|
|
169
|
-
return /* @__PURE__ */
|
|
169
|
+
return /* @__PURE__ */ L(
|
|
170
170
|
"ul",
|
|
171
171
|
{
|
|
172
172
|
ref: i,
|
|
173
173
|
className: "scroll-list",
|
|
174
|
-
onScroll: t != null && t.onBottomReached ?
|
|
175
|
-
style: { scrollBehavior:
|
|
174
|
+
onScroll: t != null && t.onBottomReached ? b : void 0,
|
|
175
|
+
style: { scrollBehavior: g },
|
|
176
176
|
children: [
|
|
177
|
-
N({ items: e, headerBehavior: d, collapsedPaths:
|
|
177
|
+
N({ items: e, headerBehavior: d, collapsedPaths: m }),
|
|
178
178
|
t != null && t.render ? t.render(c) : /* @__PURE__ */ C(D, { loading: c })
|
|
179
179
|
]
|
|
180
180
|
}
|
|
181
181
|
);
|
|
182
|
-
}, Q = ({ stickTo: e, scrollBehavior: t, headerBehavior: u, loading: d, items:
|
|
182
|
+
}, Q = ({ stickTo: e, scrollBehavior: t, headerBehavior: u, loading: d, items: m }) => /* @__PURE__ */ C(_, { headerBehavior: u, stickTo: e, scrollBehavior: t, children: /* @__PURE__ */ C(G, { loading: d, items: m }) });
|
|
183
183
|
export {
|
|
184
184
|
Q as Scroll
|
|
185
185
|
};
|