@neo4j-ndl/react 4.16.7 → 4.16.9
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/lib/cjs/color-picker/ColorPicker.js +3 -1
- package/lib/cjs/color-picker/ColorPicker.js.map +1 -1
- package/lib/cjs/color-picker/stories/color-picker-dialog.story.js +40 -0
- package/lib/cjs/color-picker/stories/color-picker-dialog.story.js.map +1 -0
- package/lib/cjs/color-picker/stories/color-picker-popover.story.js +32 -0
- package/lib/cjs/color-picker/stories/color-picker-popover.story.js.map +1 -0
- package/lib/cjs/color-picker/stories/index.js +9 -1
- package/lib/cjs/color-picker/stories/index.js.map +1 -1
- package/lib/cjs/popover/use-popover.js +1 -1
- package/lib/cjs/popover/use-popover.js.map +1 -1
- package/lib/cjs/select/Select.js +2 -0
- package/lib/cjs/select/Select.js.map +1 -1
- package/lib/esm/color-picker/ColorPicker.js +3 -1
- package/lib/esm/color-picker/ColorPicker.js.map +1 -1
- package/lib/esm/color-picker/stories/color-picker-dialog.story.js +38 -0
- package/lib/esm/color-picker/stories/color-picker-dialog.story.js.map +1 -0
- package/lib/esm/color-picker/stories/color-picker-popover.story.js +30 -0
- package/lib/esm/color-picker/stories/color-picker-popover.story.js.map +1 -0
- package/lib/esm/color-picker/stories/index.js +6 -0
- package/lib/esm/color-picker/stories/index.js.map +1 -1
- package/lib/esm/popover/use-popover.js +1 -1
- package/lib/esm/popover/use-popover.js.map +1 -1
- package/lib/esm/select/Select.js +2 -0
- package/lib/esm/select/Select.js.map +1 -1
- package/lib/types/color-picker/ColorPicker.d.ts +4 -0
- package/lib/types/color-picker/ColorPicker.d.ts.map +1 -1
- package/lib/types/color-picker/stories/color-picker-dialog.story.d.ts +24 -0
- package/lib/types/color-picker/stories/color-picker-dialog.story.d.ts.map +1 -0
- package/lib/types/color-picker/stories/color-picker-popover.story.d.ts +24 -0
- package/lib/types/color-picker/stories/color-picker-popover.story.d.ts.map +1 -0
- package/lib/types/color-picker/stories/index.d.ts +4 -0
- package/lib/types/color-picker/stories/index.d.ts.map +1 -1
- package/lib/types/select/Select.d.ts.map +1 -1
- package/package.json +5 -2
- package/skills/ndl-react/SKILL.md +152 -0
- package/skills/ndl-react/components/accordion.md +386 -0
- package/skills/ndl-react/components/ai/code-preview.md +128 -0
- package/skills/ndl-react/components/ai/file-tag.md +90 -0
- package/skills/ndl-react/components/ai/image-tag.md +91 -0
- package/skills/ndl-react/components/ai/more-files.md +73 -0
- package/skills/ndl-react/components/ai/presence.md +54 -0
- package/skills/ndl-react/components/ai/preview.md +498 -0
- package/skills/ndl-react/components/ai/prompt.md +362 -0
- package/skills/ndl-react/components/ai/reasoning.md +95 -0
- package/skills/ndl-react/components/ai/response.md +1109 -0
- package/skills/ndl-react/components/ai/suggestion.md +84 -0
- package/skills/ndl-react/components/ai/thinking.md +43 -0
- package/skills/ndl-react/components/ai/tool-call.md +43 -0
- package/skills/ndl-react/components/ai/user-bubble.md +187 -0
- package/skills/ndl-react/components/avatar.md +169 -0
- package/skills/ndl-react/components/banner.md +225 -0
- package/skills/ndl-react/components/box.md +39 -0
- package/skills/ndl-react/components/breadcrumbs.md +245 -0
- package/skills/ndl-react/components/checkbox.md +269 -0
- package/skills/ndl-react/components/clean-icon-button.md +294 -0
- package/skills/ndl-react/components/clipboard-button.md +154 -0
- package/skills/ndl-react/components/code-block.md +276 -0
- package/skills/ndl-react/components/code.md +68 -0
- package/skills/ndl-react/components/color-picker.md +131 -0
- package/skills/ndl-react/components/conditional-wrap.md +46 -0
- package/skills/ndl-react/components/data-grid.md +3121 -0
- package/skills/ndl-react/components/date-picker.md +652 -0
- package/skills/ndl-react/components/dialog.md +485 -0
- package/skills/ndl-react/components/dismissible-tag.md +136 -0
- package/skills/ndl-react/components/divider.md +96 -0
- package/skills/ndl-react/components/drawer.md +543 -0
- package/skills/ndl-react/components/dropdown-button.md +161 -0
- package/skills/ndl-react/components/dropzone.md +371 -0
- package/skills/ndl-react/components/filled-button.md +26 -0
- package/skills/ndl-react/components/flex.md +82 -0
- package/skills/ndl-react/components/graph-label.md +167 -0
- package/skills/ndl-react/components/icon-button-array.md +187 -0
- package/skills/ndl-react/components/icon-button.md +193 -0
- package/skills/ndl-react/components/inline-edit.md +209 -0
- package/skills/ndl-react/components/kbd.md +63 -0
- package/skills/ndl-react/components/loading-bar.md +43 -0
- package/skills/ndl-react/components/loading-spinner.md +57 -0
- package/skills/ndl-react/components/logo.md +57 -0
- package/skills/ndl-react/components/menu.md +993 -0
- package/skills/ndl-react/components/modal.md +27 -0
- package/skills/ndl-react/components/next/tree-view.md +966 -0
- package/skills/ndl-react/components/outlined-button.md +26 -0
- package/skills/ndl-react/components/popover.md +283 -0
- package/skills/ndl-react/components/progress-bar.md +70 -0
- package/skills/ndl-react/components/radio.md +150 -0
- package/skills/ndl-react/components/read-only-tag.md +96 -0
- package/skills/ndl-react/components/segmented-control.md +200 -0
- package/skills/ndl-react/components/select-icon-button.md +183 -0
- package/skills/ndl-react/components/select.md +530 -0
- package/skills/ndl-react/components/selectable-tag.md +203 -0
- package/skills/ndl-react/components/side-navigation.md +652 -0
- package/skills/ndl-react/components/skeleton.md +274 -0
- package/skills/ndl-react/components/slider.md +308 -0
- package/skills/ndl-react/components/spotlight.md +796 -0
- package/skills/ndl-react/components/status-indicator.md +57 -0
- package/skills/ndl-react/components/status-label.md +132 -0
- package/skills/ndl-react/components/switch.md +167 -0
- package/skills/ndl-react/components/tabs.md +433 -0
- package/skills/ndl-react/components/tag.md +91 -0
- package/skills/ndl-react/components/text-area.md +178 -0
- package/skills/ndl-react/components/text-button.md +25 -0
- package/skills/ndl-react/components/text-input.md +475 -0
- package/skills/ndl-react/components/text-link.md +119 -0
- package/skills/ndl-react/components/time-picker.md +137 -0
- package/skills/ndl-react/components/timezone-picker.md +496 -0
- package/skills/ndl-react/components/tooltip.md +478 -0
- package/skills/ndl-react/components/tree-view.md +545 -0
- package/skills/ndl-react/components/typography.md +72 -0
- package/skills/ndl-react/components/wizard.md +152 -0
|
@@ -0,0 +1,1109 @@
|
|
|
1
|
+
# Response
|
|
2
|
+
|
|
3
|
+
Import: `import { Response } from '@neo4j-ndl/react/ai'`
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
### Response
|
|
8
|
+
|
|
9
|
+
| Prop | Type | Required | Default | Description |
|
|
10
|
+
|------|------|----------|---------|-------------|
|
|
11
|
+
| `children` | `string` | ✅ | | The response from the AI |
|
|
12
|
+
| `isAnimating` | `boolean` | | | Whether the response is animating |
|
|
13
|
+
| `ref` | `Ref<HTMLDivElement>` | | | A ref to apply to the root element. |
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### Default
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
21
|
+
|
|
22
|
+
const markdownContent = `
|
|
23
|
+
# Hello World
|
|
24
|
+
|
|
25
|
+
This is a **bold** text and this is an *italic* text.
|
|
26
|
+
|
|
27
|
+
Here is a list:
|
|
28
|
+
- Item 1
|
|
29
|
+
- Item 2
|
|
30
|
+
- Item 3
|
|
31
|
+
|
|
32
|
+
And a code block:
|
|
33
|
+
|
|
34
|
+
\`\`\`typescript
|
|
35
|
+
const greeting = "Hello World";
|
|
36
|
+
console.log(greeting);
|
|
37
|
+
\`\`\`
|
|
38
|
+
|
|
39
|
+
[Link to Neo4j](https://neo4j.com)
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
export const Component = () => {
|
|
43
|
+
return <Response>{markdownContent}</Response>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default Component;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### All Components
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
53
|
+
|
|
54
|
+
const comprehensiveMarkdown = `
|
|
55
|
+
# All Markdown Components Demo
|
|
56
|
+
|
|
57
|
+
This story demonstrates all the markdown components that the Response component can render.
|
|
58
|
+
|
|
59
|
+
## Headings
|
|
60
|
+
|
|
61
|
+
# Heading 1
|
|
62
|
+
## Heading 2
|
|
63
|
+
### Heading 3
|
|
64
|
+
#### Heading 4
|
|
65
|
+
##### Heading 5
|
|
66
|
+
###### Heading 6
|
|
67
|
+
|
|
68
|
+
## Text Formatting
|
|
69
|
+
|
|
70
|
+
This is **bold text** and this is *italic text*.
|
|
71
|
+
|
|
72
|
+
You can also use __bold__ and _italic_ with underscores.
|
|
73
|
+
|
|
74
|
+
Combine them: **bold and *italic* together**.
|
|
75
|
+
|
|
76
|
+
## Lists
|
|
77
|
+
|
|
78
|
+
### Unordered Lists
|
|
79
|
+
|
|
80
|
+
- Item 1
|
|
81
|
+
- Item 2
|
|
82
|
+
- Item 3
|
|
83
|
+
- Nested item 1
|
|
84
|
+
- Nested item 2
|
|
85
|
+
- Deeply nested item
|
|
86
|
+
- <h1>Nested nested heading</h1>
|
|
87
|
+
|
|
88
|
+
### Ordered Lists
|
|
89
|
+
|
|
90
|
+
1. First item
|
|
91
|
+
2. Second item
|
|
92
|
+
3. Third item
|
|
93
|
+
1. Nested numbered item
|
|
94
|
+
2. Another nested item
|
|
95
|
+
3. <h2>Nested nested heading</h2>
|
|
96
|
+
|
|
97
|
+
## Code
|
|
98
|
+
|
|
99
|
+
### Inline Code
|
|
100
|
+
|
|
101
|
+
Use \`const x = 5\` for inline code.
|
|
102
|
+
|
|
103
|
+
### Code Blocks
|
|
104
|
+
|
|
105
|
+
#### JavaScript
|
|
106
|
+
|
|
107
|
+
\`\`\`javascript
|
|
108
|
+
const greeting = "Hello World";
|
|
109
|
+
console.log(greeting);
|
|
110
|
+
|
|
111
|
+
function sayHello(name) {
|
|
112
|
+
return \`Hello, \${name}!\`;
|
|
113
|
+
}
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
#### Python
|
|
117
|
+
|
|
118
|
+
\`\`\`python
|
|
119
|
+
def greet(name):
|
|
120
|
+
return f"Hello, {name}!"
|
|
121
|
+
|
|
122
|
+
print(greet("World"))
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
#### Cypher
|
|
126
|
+
|
|
127
|
+
\`\`\`cypher
|
|
128
|
+
MATCH (n:Person)-[:KNOWS]->(m:Person)
|
|
129
|
+
WHERE n.name = "Alice"
|
|
130
|
+
RETURN m.name
|
|
131
|
+
\`\`\`
|
|
132
|
+
|
|
133
|
+
#### TypeScript
|
|
134
|
+
|
|
135
|
+
\`\`\`typescript
|
|
136
|
+
interface User {
|
|
137
|
+
name: string;
|
|
138
|
+
age: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const user: User = {
|
|
142
|
+
name: "John",
|
|
143
|
+
age: 30
|
|
144
|
+
};
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
#### Without Language Specification
|
|
148
|
+
|
|
149
|
+
\`\`\`
|
|
150
|
+
Plain code block
|
|
151
|
+
without syntax highlighting
|
|
152
|
+
\`\`\`
|
|
153
|
+
|
|
154
|
+
## Links
|
|
155
|
+
|
|
156
|
+
Visit [Neo4j](https://neo4j.com) for more information.
|
|
157
|
+
|
|
158
|
+
Multiple links: [Documentation](https://neo4j.com/docs) and [Community](https://community.neo4j.com)
|
|
159
|
+
|
|
160
|
+
## Blockquotes
|
|
161
|
+
|
|
162
|
+
> This is a blockquote.
|
|
163
|
+
> It can span multiple lines.
|
|
164
|
+
|
|
165
|
+
> ### Blockquote with heading
|
|
166
|
+
>
|
|
167
|
+
> You can also include other markdown inside blockquotes.
|
|
168
|
+
>
|
|
169
|
+
> - Like lists
|
|
170
|
+
> - And other elements
|
|
171
|
+
|
|
172
|
+
### Nested Blockquotes
|
|
173
|
+
|
|
174
|
+
> Outer quote
|
|
175
|
+
>> Nested quote
|
|
176
|
+
>>> Deeply nested quote
|
|
177
|
+
|
|
178
|
+
## Horizontal Rules
|
|
179
|
+
|
|
180
|
+
Content above the rule
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
Content below the rule
|
|
185
|
+
|
|
186
|
+
## Images
|
|
187
|
+
|
|
188
|
+

|
|
189
|
+
|
|
190
|
+
## Paragraphs
|
|
191
|
+
|
|
192
|
+
This is a paragraph with multiple sentences. It demonstrates how regular text is rendered. You can write long-form content that spans multiple lines.
|
|
193
|
+
|
|
194
|
+
Another paragraph here. Paragraphs are separated by blank lines in markdown.
|
|
195
|
+
|
|
196
|
+
## Mixed Content Example
|
|
197
|
+
|
|
198
|
+
Here's a practical example combining multiple elements:
|
|
199
|
+
|
|
200
|
+
### Database Query Tutorial
|
|
201
|
+
|
|
202
|
+
To query your Neo4j database, follow these steps:
|
|
203
|
+
|
|
204
|
+
1. **Connect to your database**
|
|
205
|
+
|
|
206
|
+
Use the following code:
|
|
207
|
+
|
|
208
|
+
\`\`\`javascript
|
|
209
|
+
const driver = neo4j.driver(
|
|
210
|
+
'bolt://localhost:7687',
|
|
211
|
+
neo4j.auth.basic('neo4j', 'password')
|
|
212
|
+
);
|
|
213
|
+
\`\`\`
|
|
214
|
+
|
|
215
|
+
2. **Write your Cypher query**
|
|
216
|
+
|
|
217
|
+
\`\`\`cypher
|
|
218
|
+
MATCH (n:Movie)
|
|
219
|
+
WHERE n.released > 2000
|
|
220
|
+
RETURN n.title, n.released
|
|
221
|
+
ORDER BY n.released DESC
|
|
222
|
+
LIMIT 10
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
3. **Execute and process results**
|
|
226
|
+
|
|
227
|
+
> **Note**: Always close your session after use!
|
|
228
|
+
|
|
229
|
+
For more information, visit the [Neo4j Documentation](https://neo4j.com/docs).
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Special Characters and Escaping
|
|
234
|
+
|
|
235
|
+
You can escape special characters: \\* \\_ \\[ \\]
|
|
236
|
+
|
|
237
|
+
## Preformatted Text
|
|
238
|
+
|
|
239
|
+
Use code blocks for preformatted text with preserved spacing:
|
|
240
|
+
|
|
241
|
+
\`\`\`
|
|
242
|
+
This text
|
|
243
|
+
has preserved
|
|
244
|
+
indentation
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
| Item | In Stock | Price |
|
|
248
|
+
| :---------------- | :------: | ----: |
|
|
249
|
+
| Python Hat | True | 222222223.99 |
|
|
250
|
+
| SQL Hat | True | 23.99 |
|
|
251
|
+
| Codecademy Tee | False | 19.99 |
|
|
252
|
+
| Codecademy Hoodie | False | 42.99 |
|
|
253
|
+
`;
|
|
254
|
+
|
|
255
|
+
export const Component = () => {
|
|
256
|
+
return (
|
|
257
|
+
<div className="max-w-4xl">
|
|
258
|
+
<Response>{comprehensiveMarkdown}</Response>
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
export default Component;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Code Examples
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
270
|
+
|
|
271
|
+
const codeExamplesMarkdown = `
|
|
272
|
+
# Code Examples
|
|
273
|
+
|
|
274
|
+
This story focuses on different code rendering capabilities.
|
|
275
|
+
|
|
276
|
+
## Multiple Programming Languages
|
|
277
|
+
|
|
278
|
+
### JavaScript
|
|
279
|
+
|
|
280
|
+
\`\`\`javascript
|
|
281
|
+
// Array methods
|
|
282
|
+
const numbers = [1, 2, 3, 4, 5];
|
|
283
|
+
const doubled = numbers.map(n => n * 2);
|
|
284
|
+
const sum = numbers.reduce((acc, n) => acc + n, 0);
|
|
285
|
+
|
|
286
|
+
console.log('Doubled:', doubled);
|
|
287
|
+
console.log('Sum:', sum);
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
### TypeScript
|
|
291
|
+
|
|
292
|
+
\`\`\`typescript
|
|
293
|
+
// Generics
|
|
294
|
+
function identity<T>(arg: T): T {
|
|
295
|
+
return arg;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const result = identity<string>("Hello");
|
|
299
|
+
const num = identity(42);
|
|
300
|
+
\`\`\`
|
|
301
|
+
|
|
302
|
+
### Python
|
|
303
|
+
|
|
304
|
+
\`\`\`python
|
|
305
|
+
# List comprehension
|
|
306
|
+
squares = [x**2 for x in range(10)]
|
|
307
|
+
evens = [x for x in range(20) if x % 2 == 0]
|
|
308
|
+
|
|
309
|
+
# Dictionary comprehension
|
|
310
|
+
square_dict = {x: x**2 for x in range(5)}
|
|
311
|
+
|
|
312
|
+
print(f"Squares: {squares}")
|
|
313
|
+
print(f"Evens: {evens}")
|
|
314
|
+
\`\`\`
|
|
315
|
+
|
|
316
|
+
### Cypher
|
|
317
|
+
|
|
318
|
+
\`\`\`cypher
|
|
319
|
+
// Create nodes and relationships
|
|
320
|
+
CREATE (alice:Person {name: 'Alice', age: 30})
|
|
321
|
+
CREATE (bob:Person {name: 'Bob', age: 25})
|
|
322
|
+
CREATE (alice)-[:KNOWS {since: 2020}]->(bob)
|
|
323
|
+
RETURN alice, bob
|
|
324
|
+
\`\`\`
|
|
325
|
+
|
|
326
|
+
### SQL
|
|
327
|
+
|
|
328
|
+
\`\`\`sql
|
|
329
|
+
-- Complex query
|
|
330
|
+
SELECT
|
|
331
|
+
u.name,
|
|
332
|
+
COUNT(o.id) as order_count,
|
|
333
|
+
SUM(o.total) as total_spent
|
|
334
|
+
FROM users u
|
|
335
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
336
|
+
WHERE u.active = true
|
|
337
|
+
GROUP BY u.id, u.name
|
|
338
|
+
HAVING COUNT(o.id) > 5
|
|
339
|
+
ORDER BY total_spent DESC
|
|
340
|
+
LIMIT 10;
|
|
341
|
+
\`\`\`
|
|
342
|
+
|
|
343
|
+
### Rust
|
|
344
|
+
|
|
345
|
+
\`\`\`rust
|
|
346
|
+
// Pattern matching
|
|
347
|
+
fn describe_number(n: i32) -> String {
|
|
348
|
+
match n {
|
|
349
|
+
0 => "zero".to_string(),
|
|
350
|
+
1..=10 => "small".to_string(),
|
|
351
|
+
11..=100 => "medium".to_string(),
|
|
352
|
+
_ => "large".to_string(),
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
\`\`\`
|
|
356
|
+
|
|
357
|
+
### Go
|
|
358
|
+
|
|
359
|
+
\`\`\`go
|
|
360
|
+
// Goroutines and channels
|
|
361
|
+
func worker(id int, jobs <-chan int, results chan<- int) {
|
|
362
|
+
for j := range jobs {
|
|
363
|
+
fmt.Printf("worker %d processing job %d\\n", id, j)
|
|
364
|
+
results <- j * 2
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
\`\`\`
|
|
368
|
+
|
|
369
|
+
### JSON
|
|
370
|
+
|
|
371
|
+
\`\`\`json
|
|
372
|
+
{
|
|
373
|
+
"name": "Response Component",
|
|
374
|
+
"version": "1.0.0",
|
|
375
|
+
"features": [
|
|
376
|
+
"markdown rendering",
|
|
377
|
+
"syntax highlighting",
|
|
378
|
+
"streaming support"
|
|
379
|
+
],
|
|
380
|
+
"config": {
|
|
381
|
+
"theme": "dark",
|
|
382
|
+
"lineNumbers": true
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
\`\`\`
|
|
386
|
+
|
|
387
|
+
### YAML
|
|
388
|
+
|
|
389
|
+
\`\`\`yaml
|
|
390
|
+
# Configuration file
|
|
391
|
+
app:
|
|
392
|
+
name: MyApp
|
|
393
|
+
version: 1.0.0
|
|
394
|
+
port: 3000
|
|
395
|
+
|
|
396
|
+
database:
|
|
397
|
+
host: localhost
|
|
398
|
+
port: 5432
|
|
399
|
+
credentials:
|
|
400
|
+
username: admin
|
|
401
|
+
password: secret
|
|
402
|
+
|
|
403
|
+
features:
|
|
404
|
+
- authentication
|
|
405
|
+
- logging
|
|
406
|
+
- caching
|
|
407
|
+
\`\`\`
|
|
408
|
+
|
|
409
|
+
### Shell/Bash
|
|
410
|
+
|
|
411
|
+
\`\`\`bash
|
|
412
|
+
#!/bin/bash
|
|
413
|
+
|
|
414
|
+
# Deploy script
|
|
415
|
+
echo "Starting deployment..."
|
|
416
|
+
|
|
417
|
+
npm install
|
|
418
|
+
npm run build
|
|
419
|
+
npm test
|
|
420
|
+
|
|
421
|
+
if [ $? -eq 0 ]; then
|
|
422
|
+
echo "Deployment successful!"
|
|
423
|
+
else
|
|
424
|
+
echo "Deployment failed!"
|
|
425
|
+
exit 1
|
|
426
|
+
fi
|
|
427
|
+
\`\`\`
|
|
428
|
+
|
|
429
|
+
## Inline Code
|
|
430
|
+
|
|
431
|
+
You can use inline code like \`const x = 5\`, \`npm install\`, or \`SELECT * FROM users\` within sentences.
|
|
432
|
+
|
|
433
|
+
Mixed with text: The \`Array.map()\` method creates a new array and the \`filter()\` method filters elements.
|
|
434
|
+
|
|
435
|
+
## Code Without Language
|
|
436
|
+
|
|
437
|
+
\`\`\`
|
|
438
|
+
Plain text code block
|
|
439
|
+
No syntax highlighting
|
|
440
|
+
Just monospace font
|
|
441
|
+
\`\`\`
|
|
442
|
+
|
|
443
|
+
## Long Code Blocks
|
|
444
|
+
|
|
445
|
+
\`\`\`javascript
|
|
446
|
+
// Complex React component
|
|
447
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
448
|
+
|
|
449
|
+
const UserDashboard = ({ userId }) => {
|
|
450
|
+
const [user, setUser] = useState(null);
|
|
451
|
+
const [loading, setLoading] = useState(true);
|
|
452
|
+
const [error, setError] = useState(null);
|
|
453
|
+
|
|
454
|
+
const fetchUser = useCallback(async () => {
|
|
455
|
+
try {
|
|
456
|
+
setLoading(true);
|
|
457
|
+
const response = await fetch(\`/api/users/\${userId}\`);
|
|
458
|
+
if (!response.ok) throw new Error('Failed to fetch user');
|
|
459
|
+
const data = await response.json();
|
|
460
|
+
setUser(data);
|
|
461
|
+
} catch (err) {
|
|
462
|
+
setError(err.message);
|
|
463
|
+
} finally {
|
|
464
|
+
setLoading(false);
|
|
465
|
+
}
|
|
466
|
+
}, [userId]);
|
|
467
|
+
|
|
468
|
+
useEffect(() => {
|
|
469
|
+
fetchUser();
|
|
470
|
+
}, [fetchUser]);
|
|
471
|
+
|
|
472
|
+
if (loading) return <div>Loading...</div>;
|
|
473
|
+
if (error) return <div>Error: {error}</div>;
|
|
474
|
+
if (!user) return <div>No user found</div>;
|
|
475
|
+
|
|
476
|
+
return (
|
|
477
|
+
<div className="dashboard">
|
|
478
|
+
<h1>{user.name}</h1>
|
|
479
|
+
<p>Email: {user.email}</p>
|
|
480
|
+
<button onClick={fetchUser}>Refresh</button>
|
|
481
|
+
</div>
|
|
482
|
+
);
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
export default UserDashboard;
|
|
486
|
+
\`\`\`
|
|
487
|
+
`;
|
|
488
|
+
|
|
489
|
+
export const Component = () => {
|
|
490
|
+
return (
|
|
491
|
+
<div className="max-w-4xl">
|
|
492
|
+
<Response>{codeExamplesMarkdown}</Response>
|
|
493
|
+
</div>
|
|
494
|
+
);
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
export default Component;
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Full Example
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
import { CleanIconButton, TextLink, Typography } from '@neo4j-ndl/react';
|
|
504
|
+
import {
|
|
505
|
+
Prompt,
|
|
506
|
+
Response,
|
|
507
|
+
Suggestion,
|
|
508
|
+
Thinking,
|
|
509
|
+
UserBubble,
|
|
510
|
+
} from '@neo4j-ndl/react/ai';
|
|
511
|
+
import {
|
|
512
|
+
ArrowPathIconOutline,
|
|
513
|
+
Cog6ToothIconOutline,
|
|
514
|
+
HandThumbDownIconOutline,
|
|
515
|
+
PlusIconOutline,
|
|
516
|
+
Square2StackIconOutline,
|
|
517
|
+
XMarkIconOutline,
|
|
518
|
+
} from '@neo4j-ndl/react/icons';
|
|
519
|
+
import { useEffect, useRef, useState } from 'react';
|
|
520
|
+
|
|
521
|
+
const FAKE_RESPONSES = [
|
|
522
|
+
`Here is a simple response with some **bold text** and *italics*.`,
|
|
523
|
+
`Here is a list of items:
|
|
524
|
+
- Item 1
|
|
525
|
+
- Item 2
|
|
526
|
+
- Item 3`,
|
|
527
|
+
`Here is a code block example:
|
|
528
|
+
|
|
529
|
+
\`\`\`typescript
|
|
530
|
+
const greeting = "Hello World";
|
|
531
|
+
console.log(greeting);
|
|
532
|
+
\`\`\`
|
|
533
|
+
`,
|
|
534
|
+
`# Heading 1
|
|
535
|
+
## Heading 2
|
|
536
|
+
### Heading 3
|
|
537
|
+
|
|
538
|
+
Some text under headings.`,
|
|
539
|
+
`You can also use tables:
|
|
540
|
+
|
|
541
|
+
| Header 1 | Header 2 |
|
|
542
|
+
|Data 1|Data 2|
|
|
543
|
+
|Data 3|Data 4|
|
|
544
|
+
`,
|
|
545
|
+
];
|
|
546
|
+
|
|
547
|
+
export const Component = () => {
|
|
548
|
+
const [messages, setMessages] = useState<
|
|
549
|
+
{
|
|
550
|
+
role: 'user' | 'assistant';
|
|
551
|
+
content: string;
|
|
552
|
+
thinkingTime?: number;
|
|
553
|
+
done?: boolean;
|
|
554
|
+
}[]
|
|
555
|
+
>([]);
|
|
556
|
+
const [prompt, setPrompt] = useState('');
|
|
557
|
+
const [isThinking, setIsThinking] = useState(false);
|
|
558
|
+
const [isStreaming, setIsStreaming] = useState(false);
|
|
559
|
+
const [responseIndex, setResponseIndex] = useState(0);
|
|
560
|
+
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
561
|
+
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
562
|
+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
563
|
+
|
|
564
|
+
const scrollToBottom = () => {
|
|
565
|
+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
useEffect(() => {
|
|
569
|
+
scrollToBottom();
|
|
570
|
+
}, [messages, isThinking]);
|
|
571
|
+
|
|
572
|
+
const handleCancel = () => {
|
|
573
|
+
if (timeoutRef.current) {
|
|
574
|
+
clearTimeout(timeoutRef.current);
|
|
575
|
+
}
|
|
576
|
+
if (intervalRef.current) {
|
|
577
|
+
clearInterval(intervalRef.current);
|
|
578
|
+
}
|
|
579
|
+
setIsThinking(false);
|
|
580
|
+
setIsStreaming(false);
|
|
581
|
+
|
|
582
|
+
// Mark the last message as done if stopped
|
|
583
|
+
setMessages((prev) => {
|
|
584
|
+
const newMessages = [...prev];
|
|
585
|
+
const lastMessage = newMessages[newMessages.length - 1];
|
|
586
|
+
if (lastMessage?.role === 'assistant') {
|
|
587
|
+
lastMessage.done = true;
|
|
588
|
+
}
|
|
589
|
+
return newMessages;
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
const handleSend = (overridePrompt?: string) => {
|
|
594
|
+
const textToSend = overridePrompt || prompt;
|
|
595
|
+
|
|
596
|
+
if (!textToSend.trim()) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
setMessages((prev) => [...prev, { content: textToSend, role: 'user' }]);
|
|
601
|
+
setPrompt('');
|
|
602
|
+
setIsThinking(true);
|
|
603
|
+
const startTime = Date.now();
|
|
604
|
+
|
|
605
|
+
// Simulate network delay (thinking time)
|
|
606
|
+
timeoutRef.current = setTimeout(() => {
|
|
607
|
+
const endTime = Date.now();
|
|
608
|
+
const thinkingTime = endTime - startTime;
|
|
609
|
+
setIsThinking(false);
|
|
610
|
+
setIsStreaming(true);
|
|
611
|
+
|
|
612
|
+
const responseText = FAKE_RESPONSES[responseIndex];
|
|
613
|
+
setResponseIndex((prev) => (prev + 1) % FAKE_RESPONSES.length);
|
|
614
|
+
|
|
615
|
+
let currentText = '';
|
|
616
|
+
setMessages((prev) => [
|
|
617
|
+
...prev,
|
|
618
|
+
{ content: '', done: false, role: 'assistant', thinkingTime },
|
|
619
|
+
]);
|
|
620
|
+
|
|
621
|
+
// Simulate streaming
|
|
622
|
+
intervalRef.current = setInterval(() => {
|
|
623
|
+
if (currentText.length < responseText.length) {
|
|
624
|
+
// Add a few characters at a time to simulate chunks
|
|
625
|
+
// Ensure we don't split newlines incorrectly if that's an issue,
|
|
626
|
+
// but simple slicing should be fine as long as the source has \n.
|
|
627
|
+
const chunk = responseText.slice(
|
|
628
|
+
currentText.length,
|
|
629
|
+
currentText.length + 2,
|
|
630
|
+
);
|
|
631
|
+
currentText += chunk;
|
|
632
|
+
|
|
633
|
+
setMessages((prev) => {
|
|
634
|
+
const newMessages = [...prev];
|
|
635
|
+
const lastMessage = newMessages[newMessages.length - 1];
|
|
636
|
+
if (lastMessage.role === 'assistant') {
|
|
637
|
+
lastMessage.content = currentText;
|
|
638
|
+
}
|
|
639
|
+
return newMessages;
|
|
640
|
+
});
|
|
641
|
+
} else {
|
|
642
|
+
if (intervalRef.current) {
|
|
643
|
+
clearInterval(intervalRef.current);
|
|
644
|
+
}
|
|
645
|
+
setIsStreaming(false);
|
|
646
|
+
setMessages((prev) => {
|
|
647
|
+
const newMessages = [...prev];
|
|
648
|
+
const lastMessage = newMessages[newMessages.length - 1];
|
|
649
|
+
if (lastMessage.role === 'assistant') {
|
|
650
|
+
lastMessage.done = true;
|
|
651
|
+
}
|
|
652
|
+
return newMessages;
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
}, 50);
|
|
656
|
+
}, 2000);
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
return (
|
|
660
|
+
<section className="n-h-screen">
|
|
661
|
+
<div className="n-w-[440px] n-h-full n-flex n-flex-col n-bg-neutral-bg-weak">
|
|
662
|
+
<div className="n-flex n-flex-row n-border-b n-border-neutral-border-weak n-p-3">
|
|
663
|
+
<div className="n-ml-auto">
|
|
664
|
+
<CleanIconButton description="settings" tooltipProps={{}}>
|
|
665
|
+
<Cog6ToothIconOutline />
|
|
666
|
+
</CleanIconButton>
|
|
667
|
+
<CleanIconButton description="close">
|
|
668
|
+
<XMarkIconOutline />
|
|
669
|
+
</CleanIconButton>
|
|
670
|
+
</div>
|
|
671
|
+
</div>
|
|
672
|
+
<div className="n-p-4 n-flex n-flex-col n-grow n-overflow-y-auto">
|
|
673
|
+
{messages.length === 0 ? (
|
|
674
|
+
<div className="n-flex n-flex-col ">
|
|
675
|
+
<div className="n-flex n-flex-col n-gap-12">
|
|
676
|
+
<Typography variant="display">
|
|
677
|
+
Hi [User], how can I help you today?
|
|
678
|
+
</Typography>
|
|
679
|
+
<div className="n-flex n-flex-col n-gap-4">
|
|
680
|
+
<Typography variant="body-medium">Suggestions</Typography>
|
|
681
|
+
<Suggestion
|
|
682
|
+
isPrimary
|
|
683
|
+
onClick={() => {
|
|
684
|
+
handleSend('I want to import data');
|
|
685
|
+
}}
|
|
686
|
+
>
|
|
687
|
+
I want to import data
|
|
688
|
+
</Suggestion>
|
|
689
|
+
<Suggestion
|
|
690
|
+
onClick={() => {
|
|
691
|
+
handleSend('Create an AI agent');
|
|
692
|
+
}}
|
|
693
|
+
>
|
|
694
|
+
Create an AI agent
|
|
695
|
+
</Suggestion>
|
|
696
|
+
<Suggestion
|
|
697
|
+
onClick={() => {
|
|
698
|
+
handleSend('Invite project members');
|
|
699
|
+
}}
|
|
700
|
+
>
|
|
701
|
+
Invite project members
|
|
702
|
+
</Suggestion>
|
|
703
|
+
<Suggestion
|
|
704
|
+
onClick={() => {
|
|
705
|
+
handleSend('Generate a report');
|
|
706
|
+
}}
|
|
707
|
+
>
|
|
708
|
+
Generate a report
|
|
709
|
+
</Suggestion>
|
|
710
|
+
</div>
|
|
711
|
+
<Typography variant="body-medium">
|
|
712
|
+
You can also drag and drop files here, or{' '}
|
|
713
|
+
<TextLink as="button" type="internal-underline">
|
|
714
|
+
browse
|
|
715
|
+
</TextLink>
|
|
716
|
+
. Supports CVG, MOV, PDF
|
|
717
|
+
</Typography>
|
|
718
|
+
</div>
|
|
719
|
+
</div>
|
|
720
|
+
) : (
|
|
721
|
+
<div className="n-flex n-flex-col n-gap-4 n-pb-4">
|
|
722
|
+
{messages.map((msg, idx) => (
|
|
723
|
+
<div
|
|
724
|
+
key={idx}
|
|
725
|
+
className={`n-flex ${
|
|
726
|
+
msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'
|
|
727
|
+
}`}
|
|
728
|
+
>
|
|
729
|
+
{msg.role === 'user' ? (
|
|
730
|
+
<div className="n-max-w-[85%]">
|
|
731
|
+
<UserBubble
|
|
732
|
+
avatarProps={{
|
|
733
|
+
name: 'NM',
|
|
734
|
+
type: 'letters',
|
|
735
|
+
}}
|
|
736
|
+
>
|
|
737
|
+
{msg.content}
|
|
738
|
+
</UserBubble>
|
|
739
|
+
</div>
|
|
740
|
+
) : (
|
|
741
|
+
<div className="n-w-full n-flex n-flex-col n-gap-2">
|
|
742
|
+
{msg.thinkingTime !== undefined && (
|
|
743
|
+
<Thinking
|
|
744
|
+
isThinking={false}
|
|
745
|
+
thinkingMs={msg.thinkingTime}
|
|
746
|
+
/>
|
|
747
|
+
)}
|
|
748
|
+
<div className="n-flex n-flex-col n-gap-2">
|
|
749
|
+
<Response>{msg.content}</Response>
|
|
750
|
+
|
|
751
|
+
{msg.done === true && (
|
|
752
|
+
<div className="n-flex n-flex-row n-gap-1.5">
|
|
753
|
+
<CleanIconButton size="small" description="Dislike">
|
|
754
|
+
<HandThumbDownIconOutline />
|
|
755
|
+
</CleanIconButton>
|
|
756
|
+
<CleanIconButton size="small" description="Re-run">
|
|
757
|
+
<ArrowPathIconOutline />
|
|
758
|
+
</CleanIconButton>
|
|
759
|
+
<CleanIconButton size="small" description="Copy">
|
|
760
|
+
<Square2StackIconOutline />
|
|
761
|
+
</CleanIconButton>
|
|
762
|
+
</div>
|
|
763
|
+
)}
|
|
764
|
+
</div>
|
|
765
|
+
</div>
|
|
766
|
+
)}
|
|
767
|
+
</div>
|
|
768
|
+
))}
|
|
769
|
+
{isThinking && <Thinking isThinking={true} />}
|
|
770
|
+
<div ref={messagesEndRef} />
|
|
771
|
+
</div>
|
|
772
|
+
)}
|
|
773
|
+
</div>
|
|
774
|
+
<div className="n-px-4 n-pt-4 n-pb-1 n-mt-auto">
|
|
775
|
+
<Prompt
|
|
776
|
+
value={prompt}
|
|
777
|
+
onChange={(e) => setPrompt(e.target.value)}
|
|
778
|
+
onSubmitPrompt={() => handleSend()}
|
|
779
|
+
onCancelPrompt={handleCancel}
|
|
780
|
+
isRunningPrompt={isThinking || isStreaming}
|
|
781
|
+
isSubmitDisabled={
|
|
782
|
+
prompt.length === 0 && !(isThinking || isStreaming)
|
|
783
|
+
}
|
|
784
|
+
bottomContent={
|
|
785
|
+
<CleanIconButton description="Add files" size="small">
|
|
786
|
+
<PlusIconOutline />
|
|
787
|
+
</CleanIconButton>
|
|
788
|
+
}
|
|
789
|
+
/>
|
|
790
|
+
</div>
|
|
791
|
+
</div>
|
|
792
|
+
</section>
|
|
793
|
+
);
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
export default Component;
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### Headings
|
|
800
|
+
|
|
801
|
+
```tsx
|
|
802
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
803
|
+
|
|
804
|
+
const headingsMarkdown = `
|
|
805
|
+
# Heading Level 1
|
|
806
|
+
This is content under heading 1.
|
|
807
|
+
|
|
808
|
+
## Heading Level 2
|
|
809
|
+
This is content under heading 2.
|
|
810
|
+
|
|
811
|
+
### Heading Level 3
|
|
812
|
+
This is content under heading 3.
|
|
813
|
+
|
|
814
|
+
#### Heading Level 4
|
|
815
|
+
This is content under heading 4.
|
|
816
|
+
|
|
817
|
+
##### Heading Level 5
|
|
818
|
+
This is content under heading 5.
|
|
819
|
+
|
|
820
|
+
###### Heading Level 6
|
|
821
|
+
This is content under heading 6.
|
|
822
|
+
|
|
823
|
+
---
|
|
824
|
+
|
|
825
|
+
## Document Structure Example
|
|
826
|
+
|
|
827
|
+
# Main Document Title
|
|
828
|
+
|
|
829
|
+
Brief introduction to the document.
|
|
830
|
+
|
|
831
|
+
## Introduction
|
|
832
|
+
|
|
833
|
+
This section provides an overview of what we'll cover.
|
|
834
|
+
|
|
835
|
+
### Background
|
|
836
|
+
|
|
837
|
+
Some background information about the topic.
|
|
838
|
+
|
|
839
|
+
#### Historical Context
|
|
840
|
+
|
|
841
|
+
Details about the history.
|
|
842
|
+
|
|
843
|
+
##### Key Events
|
|
844
|
+
|
|
845
|
+
- Event 1
|
|
846
|
+
- Event 2
|
|
847
|
+
- Event 3
|
|
848
|
+
|
|
849
|
+
###### Notes
|
|
850
|
+
|
|
851
|
+
Additional notes and references.
|
|
852
|
+
|
|
853
|
+
## Content Section
|
|
854
|
+
|
|
855
|
+
Main content goes here.
|
|
856
|
+
|
|
857
|
+
### Subsection A
|
|
858
|
+
|
|
859
|
+
Details for subsection A.
|
|
860
|
+
|
|
861
|
+
### Subsection B
|
|
862
|
+
|
|
863
|
+
Details for subsection B.
|
|
864
|
+
|
|
865
|
+
## Conclusion
|
|
866
|
+
|
|
867
|
+
Final thoughts and summary.
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
## Headings with Other Elements
|
|
872
|
+
|
|
873
|
+
### Code Example
|
|
874
|
+
|
|
875
|
+
\`\`\`javascript
|
|
876
|
+
console.log("Hello from heading section");
|
|
877
|
+
\`\`\`
|
|
878
|
+
|
|
879
|
+
### List Example
|
|
880
|
+
|
|
881
|
+
- Item 1
|
|
882
|
+
- Item 2
|
|
883
|
+
- Item 3
|
|
884
|
+
|
|
885
|
+
### Quote Example
|
|
886
|
+
|
|
887
|
+
> "This is a quote under a heading."
|
|
888
|
+
|
|
889
|
+
### Mixed Content
|
|
890
|
+
|
|
891
|
+
Regular paragraph with **bold** and *italic* text.
|
|
892
|
+
`;
|
|
893
|
+
|
|
894
|
+
export const Component = () => {
|
|
895
|
+
return (
|
|
896
|
+
<div className="max-w-4xl">
|
|
897
|
+
<Response>{headingsMarkdown}</Response>
|
|
898
|
+
</div>
|
|
899
|
+
);
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
export default Component;
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
### Lists
|
|
906
|
+
|
|
907
|
+
```tsx
|
|
908
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
909
|
+
|
|
910
|
+
const listsMarkdown = `
|
|
911
|
+
# Lists Examples
|
|
912
|
+
|
|
913
|
+
## Simple Unordered List
|
|
914
|
+
|
|
915
|
+
- Apple
|
|
916
|
+
- Banana
|
|
917
|
+
- Cherry
|
|
918
|
+
- Date
|
|
919
|
+
- Elderberry
|
|
920
|
+
|
|
921
|
+
## Simple Ordered List
|
|
922
|
+
|
|
923
|
+
1. First step
|
|
924
|
+
2. Second step
|
|
925
|
+
3. Third step
|
|
926
|
+
4. Fourth step
|
|
927
|
+
5. Fifth step
|
|
928
|
+
|
|
929
|
+
## Nested Unordered Lists
|
|
930
|
+
|
|
931
|
+
- Fruits
|
|
932
|
+
- Apples
|
|
933
|
+
- Granny Smith
|
|
934
|
+
- Honeycrisp
|
|
935
|
+
- Fuji
|
|
936
|
+
- Oranges
|
|
937
|
+
- Navel
|
|
938
|
+
- Blood Orange
|
|
939
|
+
- Berries
|
|
940
|
+
- Strawberry
|
|
941
|
+
- Blueberry
|
|
942
|
+
- Raspberry
|
|
943
|
+
- Vegetables
|
|
944
|
+
- Leafy Greens
|
|
945
|
+
- Spinach
|
|
946
|
+
- Kale
|
|
947
|
+
- Root Vegetables
|
|
948
|
+
- Carrot
|
|
949
|
+
- Potato
|
|
950
|
+
|
|
951
|
+
## Nested Ordered Lists
|
|
952
|
+
|
|
953
|
+
1. Introduction
|
|
954
|
+
1. Overview
|
|
955
|
+
2. Purpose
|
|
956
|
+
3. Scope
|
|
957
|
+
2. Main Content
|
|
958
|
+
1. Chapter 1
|
|
959
|
+
1. Section 1.1
|
|
960
|
+
2. Section 1.2
|
|
961
|
+
3. Section 1.3
|
|
962
|
+
2. Chapter 2
|
|
963
|
+
1. Section 2.1
|
|
964
|
+
2. Section 2.2
|
|
965
|
+
3. Conclusion
|
|
966
|
+
1. Summary
|
|
967
|
+
2. Recommendations
|
|
968
|
+
|
|
969
|
+
## Mixed Lists
|
|
970
|
+
|
|
971
|
+
1. Install dependencies
|
|
972
|
+
- Node.js
|
|
973
|
+
- npm or yarn
|
|
974
|
+
- Git
|
|
975
|
+
2. Clone repository
|
|
976
|
+
- \`git clone <url>\`
|
|
977
|
+
- \`cd project-name\`
|
|
978
|
+
3. Configure settings
|
|
979
|
+
1. Copy \`.env.example\` to \`.env\`
|
|
980
|
+
2. Update configuration values:
|
|
981
|
+
- Database URL
|
|
982
|
+
- API keys
|
|
983
|
+
- Port number
|
|
984
|
+
4. Start development server
|
|
985
|
+
- Run \`npm install\`
|
|
986
|
+
- Run \`npm start\`
|
|
987
|
+
|
|
988
|
+
## Lists with Paragraphs
|
|
989
|
+
|
|
990
|
+
- **First Item**
|
|
991
|
+
|
|
992
|
+
This is a detailed explanation of the first item. It can contain multiple sentences and provide context.
|
|
993
|
+
|
|
994
|
+
- **Second Item**
|
|
995
|
+
|
|
996
|
+
The second item also has a detailed explanation. This helps provide more information to the reader.
|
|
997
|
+
|
|
998
|
+
- **Third Item**
|
|
999
|
+
|
|
1000
|
+
Each item can have as much detail as needed.
|
|
1001
|
+
|
|
1002
|
+
## Lists with Code
|
|
1003
|
+
|
|
1004
|
+
- JavaScript example:
|
|
1005
|
+
|
|
1006
|
+
\`\`\`javascript
|
|
1007
|
+
const items = ['a', 'b', 'c'];
|
|
1008
|
+
items.forEach(item => console.log(item));
|
|
1009
|
+
\`\`\`
|
|
1010
|
+
|
|
1011
|
+
- Python example:
|
|
1012
|
+
|
|
1013
|
+
\`\`\`python
|
|
1014
|
+
items = ['a', 'b', 'c']
|
|
1015
|
+
for item in items:
|
|
1016
|
+
print(item)
|
|
1017
|
+
\`\`\`
|
|
1018
|
+
|
|
1019
|
+
## Task Lists Representation
|
|
1020
|
+
|
|
1021
|
+
- [x] Complete feature A
|
|
1022
|
+
- [x] Write tests
|
|
1023
|
+
- [ ] Review code
|
|
1024
|
+
- [ ] Deploy to production
|
|
1025
|
+
- [ ] Monitor metrics
|
|
1026
|
+
|
|
1027
|
+
## Lists with Links
|
|
1028
|
+
|
|
1029
|
+
1. Official Resources
|
|
1030
|
+
- [Neo4j Documentation](https://neo4j.com/docs)
|
|
1031
|
+
- [Neo4j Community](https://community.neo4j.com)
|
|
1032
|
+
- [Neo4j GitHub](https://github.com/neo4j)
|
|
1033
|
+
2. Tutorials
|
|
1034
|
+
- [Getting Started Guide](https://neo4j.com/start)
|
|
1035
|
+
- [Cypher Query Language](https://neo4j.com/cypher)
|
|
1036
|
+
3. Tools
|
|
1037
|
+
- Neo4j Desktop
|
|
1038
|
+
- Neo4j Browser
|
|
1039
|
+
- Neo4j Bloom
|
|
1040
|
+
|
|
1041
|
+
## Lists with Inline Formatting
|
|
1042
|
+
|
|
1043
|
+
- **Bold item** with regular text
|
|
1044
|
+
- *Italic item* with regular text
|
|
1045
|
+
- \`Code item\` with regular text
|
|
1046
|
+
- Regular text with **bold**, *italic*, and \`code\`
|
|
1047
|
+
- Combination: **bold and *italic* text** together
|
|
1048
|
+
`;
|
|
1049
|
+
|
|
1050
|
+
export const Component = () => {
|
|
1051
|
+
return (
|
|
1052
|
+
<div className="max-w-4xl">
|
|
1053
|
+
<Response>{listsMarkdown}</Response>
|
|
1054
|
+
</div>
|
|
1055
|
+
);
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
export default Component;
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
### Streaming
|
|
1062
|
+
|
|
1063
|
+
```tsx
|
|
1064
|
+
import { Response } from '@neo4j-ndl/react/ai';
|
|
1065
|
+
import { useEffect, useState } from 'react';
|
|
1066
|
+
|
|
1067
|
+
const StreamingComponent = () => {
|
|
1068
|
+
const [content, setContent] = useState('');
|
|
1069
|
+
|
|
1070
|
+
useEffect(() => {
|
|
1071
|
+
const fullContent = `
|
|
1072
|
+
# Streaming Response
|
|
1073
|
+
|
|
1074
|
+
This content is being **streamed (and here's a long long long long bold text)** to simulate an AI response.
|
|
1075
|
+
|
|
1076
|
+
It handles:
|
|
1077
|
+
1. Partial updates
|
|
1078
|
+
2. Incomplete markdown
|
|
1079
|
+
3. Code blocks
|
|
1080
|
+
|
|
1081
|
+
\`\`\`javascript
|
|
1082
|
+
function stream() {
|
|
1083
|
+
return "streaming...";
|
|
1084
|
+
}
|
|
1085
|
+
\`\`\`
|
|
1086
|
+
And here comes more text after the code block.`;
|
|
1087
|
+
|
|
1088
|
+
let currentIndex = 0;
|
|
1089
|
+
const interval = setInterval(() => {
|
|
1090
|
+
if (currentIndex < fullContent.length) {
|
|
1091
|
+
setContent(fullContent.slice(0, currentIndex + 1));
|
|
1092
|
+
currentIndex++;
|
|
1093
|
+
} else {
|
|
1094
|
+
clearInterval(interval);
|
|
1095
|
+
}
|
|
1096
|
+
}, 30);
|
|
1097
|
+
|
|
1098
|
+
return () => clearInterval(interval);
|
|
1099
|
+
}, []);
|
|
1100
|
+
|
|
1101
|
+
return <Response>{content}</Response>;
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
export const Component = () => {
|
|
1105
|
+
return <StreamingComponent />;
|
|
1106
|
+
};
|
|
1107
|
+
|
|
1108
|
+
export default Component;
|
|
1109
|
+
```
|