@tanstack/cta-ui 0.15.3 → 0.15.4

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 (88) hide show
  1. package/dist/assets/index-BLGJkAxX.css +1 -0
  2. package/dist/assets/index-DPjMQkKx.js +208 -0
  3. package/dist/assets/index-DPjMQkKx.js.map +1 -0
  4. package/dist/index.html +3 -2
  5. package/index.html +1 -0
  6. package/lib/engine-handling/create-app-wrapper.ts +3 -4
  7. package/lib/engine-handling/generate-initial-payload.ts +12 -20
  8. package/lib/engine-handling/server-environment.ts +2 -2
  9. package/lib/index.ts +33 -15
  10. package/lib-dist/engine-handling/create-app-wrapper.js +3 -2
  11. package/lib-dist/engine-handling/generate-initial-payload.d.ts +8 -6
  12. package/lib-dist/engine-handling/generate-initial-payload.js +9 -14
  13. package/lib-dist/engine-handling/server-environment.d.ts +3 -3
  14. package/lib-dist/index.d.ts +1 -0
  15. package/lib-dist/index.js +29 -11
  16. package/package.json +3 -32
  17. package/src/index.tsx +2 -42
  18. package/src/main.tsx +0 -1
  19. package/src/styles.css +2 -0
  20. package/src/types.d.ts +13 -8
  21. package/dist/assets/index-BktnQA5a.js +0 -213
  22. package/dist/assets/index-BktnQA5a.js.map +0 -1
  23. package/dist/assets/index-CpoUtYXp.css +0 -1
  24. package/dist/logo-color-100w.png +0 -0
  25. package/dist/logo192.png +0 -0
  26. package/dist/logo512.png +0 -0
  27. package/dist/tailwind.svg +0 -1
  28. package/dist/tanstack.png +0 -0
  29. package/dist/typescript.svg +0 -1
  30. package/lib/engine-handling/framework-registration.ts +0 -11
  31. package/lib-dist/engine-handling/framework-registration.d.ts +0 -1
  32. package/lib-dist/engine-handling/framework-registration.js +0 -10
  33. package/public/logo-color-100w.png +0 -0
  34. package/public/logo192.png +0 -0
  35. package/public/logo512.png +0 -0
  36. package/public/tailwind.svg +0 -1
  37. package/public/tanstack.png +0 -0
  38. package/public/typescript.svg +0 -1
  39. package/src/components/StatusList.tsx +0 -22
  40. package/src/components/add-on-info-dialog.tsx +0 -39
  41. package/src/components/background-animation.tsx +0 -229
  42. package/src/components/cta-sidebar.tsx +0 -50
  43. package/src/components/custom-add-on-dialog.tsx +0 -79
  44. package/src/components/file-navigator.tsx +0 -203
  45. package/src/components/file-tree.tsx +0 -35
  46. package/src/components/file-viewer.tsx +0 -67
  47. package/src/components/header.tsx +0 -31
  48. package/src/components/sidebar-items/add-ons.tsx +0 -94
  49. package/src/components/sidebar-items/mode-selector.tsx +0 -57
  50. package/src/components/sidebar-items/project-name.tsx +0 -28
  51. package/src/components/sidebar-items/run-add-ons.tsx +0 -71
  52. package/src/components/sidebar-items/run-create-app.tsx +0 -82
  53. package/src/components/sidebar-items/starter.tsx +0 -123
  54. package/src/components/sidebar-items/typescript-switch.tsx +0 -52
  55. package/src/components/starters-carousel.tsx +0 -45
  56. package/src/components/startup-dialog.tsx +0 -71
  57. package/src/components/toaster.tsx +0 -29
  58. package/src/components/ui/button.tsx +0 -61
  59. package/src/components/ui/carousel.tsx +0 -239
  60. package/src/components/ui/checkbox.tsx +0 -30
  61. package/src/components/ui/dialog.tsx +0 -138
  62. package/src/components/ui/dropdown-menu.tsx +0 -255
  63. package/src/components/ui/input.tsx +0 -21
  64. package/src/components/ui/label.tsx +0 -22
  65. package/src/components/ui/popover.tsx +0 -46
  66. package/src/components/ui/separator.tsx +0 -28
  67. package/src/components/ui/sheet.tsx +0 -137
  68. package/src/components/ui/sidebar.tsx +0 -726
  69. package/src/components/ui/skeleton.tsx +0 -13
  70. package/src/components/ui/sonner.tsx +0 -23
  71. package/src/components/ui/switch.tsx +0 -29
  72. package/src/components/ui/table.tsx +0 -114
  73. package/src/components/ui/tabs.tsx +0 -64
  74. package/src/components/ui/toggle-group.tsx +0 -71
  75. package/src/components/ui/toggle.tsx +0 -49
  76. package/src/components/ui/tooltip.tsx +0 -61
  77. package/src/components/ui/tree-view.tsx +0 -497
  78. package/src/file-classes.ts +0 -54
  79. package/src/hooks/use-mobile.ts +0 -19
  80. package/src/hooks/use-mounted.ts +0 -9
  81. package/src/hooks/use-preferred-reduced-motion.ts +0 -27
  82. package/src/hooks/use-streaming-status.ts +0 -70
  83. package/src/lib/api.ts +0 -92
  84. package/src/lib/utils.ts +0 -6
  85. package/src/store/add-ons.ts +0 -81
  86. package/src/store/project.ts +0 -347
  87. package/tests/store/add-ons.test.ts +0 -222
  88. package/vitest.config.ts +0 -6
@@ -1,497 +0,0 @@
1
- import React from 'react'
2
- import * as AccordionPrimitive from '@radix-ui/react-accordion'
3
- import { ChevronRight } from 'lucide-react'
4
- import { cva } from 'class-variance-authority'
5
- import { cn } from '@/lib/utils'
6
-
7
- const treeVariants = cva(
8
- 'group hover:before:opacity-100 before:absolute before:rounded-lg before:left-0 px-2 before:w-full before:opacity-0 before:bg-accent/70 before:h-[2rem] before:-z-10',
9
- )
10
-
11
- const selectedTreeVariants = cva(
12
- 'before:opacity-100 before:bg-accent/70 text-accent-foreground',
13
- )
14
-
15
- const dragOverVariants = cva(
16
- 'before:opacity-100 before:bg-primary/20 text-primary-foreground',
17
- )
18
-
19
- interface TreeDataItem {
20
- id: string
21
- name: string
22
- icon?: any
23
- selectedIcon?: any
24
- openIcon?: any
25
- children?: Array<TreeDataItem>
26
- actions?: React.ReactNode
27
- onClick?: () => void
28
- draggable?: boolean
29
- droppable?: boolean
30
- className?: string
31
- }
32
-
33
- type TreeProps = React.HTMLAttributes<HTMLDivElement> & {
34
- data: Array<TreeDataItem> | TreeDataItem
35
- initialSelectedItemId?: string
36
- onSelectChange?: (item: TreeDataItem | undefined) => void
37
- expandAll?: boolean
38
- initialExpandedItemIds?: Array<string>
39
- defaultNodeIcon?: any
40
- defaultLeafIcon?: any
41
- onDocumentDrag?: (sourceItem: TreeDataItem, targetItem: TreeDataItem) => void
42
- }
43
-
44
- const TreeView = React.forwardRef<HTMLDivElement, TreeProps>(
45
- (
46
- {
47
- data,
48
- initialSelectedItemId,
49
- onSelectChange,
50
- expandAll,
51
- initialExpandedItemIds,
52
- defaultLeafIcon,
53
- defaultNodeIcon,
54
- className,
55
- onDocumentDrag,
56
- ...props
57
- },
58
- ref,
59
- ) => {
60
- const [selectedItemId, setSelectedItemId] = React.useState<
61
- string | undefined
62
- >(initialSelectedItemId)
63
-
64
- const [draggedItem, setDraggedItem] = React.useState<TreeDataItem | null>(
65
- null,
66
- )
67
-
68
- const handleSelectChange = React.useCallback(
69
- (item: TreeDataItem | undefined) => {
70
- setSelectedItemId(item?.id)
71
- if (onSelectChange) {
72
- onSelectChange(item)
73
- }
74
- },
75
- [onSelectChange],
76
- )
77
-
78
- const handleDragStart = React.useCallback((item: TreeDataItem) => {
79
- setDraggedItem(item)
80
- }, [])
81
-
82
- const handleDrop = React.useCallback(
83
- (targetItem: TreeDataItem) => {
84
- if (draggedItem && onDocumentDrag && draggedItem.id !== targetItem.id) {
85
- onDocumentDrag(draggedItem, targetItem)
86
- }
87
- setDraggedItem(null)
88
- },
89
- [draggedItem, onDocumentDrag],
90
- )
91
-
92
- const expandedItemIds = React.useMemo(() => {
93
- if (initialExpandedItemIds) {
94
- return initialExpandedItemIds
95
- }
96
- if (!initialSelectedItemId && !expandAll) {
97
- return [] as Array<string>
98
- }
99
-
100
- const ids: Array<string> = []
101
-
102
- function walkTreeItems(
103
- items: Array<TreeDataItem> | TreeDataItem,
104
- targetId: string,
105
- ) {
106
- if (items instanceof Array) {
107
- for (let i = 0; i < items.length; i++) {
108
- ids.push(items[i]!.id)
109
- if (walkTreeItems(items[i]!, targetId) && !expandAll) {
110
- return true
111
- }
112
- if (!expandAll) ids.pop()
113
- }
114
- } else if (!expandAll && items.id === targetId) {
115
- return true
116
- } else if (items.children) {
117
- return walkTreeItems(items.children, targetId)
118
- }
119
- }
120
-
121
- walkTreeItems(data, initialSelectedItemId)
122
- return ids
123
- }, [data, expandAll, initialSelectedItemId, initialExpandedItemIds])
124
-
125
- return (
126
- <div className={cn('overflow-hidden relative p-2', className)}>
127
- <TreeItem
128
- data={data}
129
- ref={ref}
130
- selectedItemId={selectedItemId}
131
- handleSelectChange={handleSelectChange}
132
- expandedItemIds={expandedItemIds}
133
- defaultLeafIcon={defaultLeafIcon}
134
- defaultNodeIcon={defaultNodeIcon}
135
- handleDragStart={handleDragStart}
136
- handleDrop={handleDrop}
137
- draggedItem={draggedItem}
138
- {...props}
139
- />
140
- <div
141
- className="w-full h-[48px]"
142
- onDrop={(e) => {
143
- handleDrop({ id: '', name: 'parent_div' })
144
- }}
145
- ></div>
146
- </div>
147
- )
148
- },
149
- )
150
- TreeView.displayName = 'TreeView'
151
-
152
- type TreeItemProps = TreeProps & {
153
- selectedItemId?: string
154
- handleSelectChange: (item: TreeDataItem | undefined) => void
155
- expandedItemIds: Array<string>
156
- defaultNodeIcon?: any
157
- defaultLeafIcon?: any
158
- handleDragStart?: (item: TreeDataItem) => void
159
- handleDrop?: (item: TreeDataItem) => void
160
- draggedItem: TreeDataItem | null
161
- }
162
-
163
- const TreeItem = React.forwardRef<HTMLDivElement, TreeItemProps>(
164
- (
165
- {
166
- className,
167
- data,
168
- selectedItemId,
169
- handleSelectChange,
170
- expandedItemIds,
171
- defaultNodeIcon,
172
- defaultLeafIcon,
173
- handleDragStart,
174
- handleDrop,
175
- draggedItem,
176
- ...props
177
- },
178
- ref,
179
- ) => {
180
- if (!(data instanceof Array)) {
181
- data = [data]
182
- }
183
- return (
184
- <div ref={ref} role="tree" className={className} {...props}>
185
- <ul>
186
- {data.map((item) => (
187
- <li key={item.id}>
188
- {item.children ? (
189
- <TreeNode
190
- item={item}
191
- selectedItemId={selectedItemId}
192
- expandedItemIds={expandedItemIds}
193
- handleSelectChange={handleSelectChange}
194
- defaultNodeIcon={defaultNodeIcon}
195
- defaultLeafIcon={defaultLeafIcon}
196
- handleDragStart={handleDragStart}
197
- handleDrop={handleDrop}
198
- draggedItem={draggedItem}
199
- />
200
- ) : (
201
- <TreeLeaf
202
- item={item}
203
- selectedItemId={selectedItemId}
204
- handleSelectChange={handleSelectChange}
205
- defaultLeafIcon={defaultLeafIcon}
206
- handleDragStart={handleDragStart}
207
- handleDrop={handleDrop}
208
- draggedItem={draggedItem}
209
- className={item.className}
210
- />
211
- )}
212
- </li>
213
- ))}
214
- </ul>
215
- </div>
216
- )
217
- },
218
- )
219
- TreeItem.displayName = 'TreeItem'
220
-
221
- const TreeNode = ({
222
- item,
223
- handleSelectChange,
224
- expandedItemIds,
225
- selectedItemId,
226
- defaultNodeIcon,
227
- defaultLeafIcon,
228
- handleDragStart,
229
- handleDrop,
230
- draggedItem,
231
- }: {
232
- item: TreeDataItem
233
- handleSelectChange: (item: TreeDataItem | undefined) => void
234
- expandedItemIds: Array<string>
235
- selectedItemId?: string
236
- defaultNodeIcon?: any
237
- defaultLeafIcon?: any
238
- handleDragStart?: (item: TreeDataItem) => void
239
- handleDrop?: (item: TreeDataItem) => void
240
- draggedItem: TreeDataItem | null
241
- }) => {
242
- const [value, setValue] = React.useState(
243
- expandedItemIds.includes(item.id) ? [item.id] : [],
244
- )
245
- const [isDragOver, setIsDragOver] = React.useState(false)
246
-
247
- const onDragStart = (e: React.DragEvent) => {
248
- if (!item.draggable) {
249
- e.preventDefault()
250
- return
251
- }
252
- e.dataTransfer.setData('text/plain', item.id)
253
- handleDragStart?.(item)
254
- }
255
-
256
- const onDragOver = (e: React.DragEvent) => {
257
- if (item.droppable !== false && draggedItem && draggedItem.id !== item.id) {
258
- e.preventDefault()
259
- setIsDragOver(true)
260
- }
261
- }
262
-
263
- const onDragLeave = () => {
264
- setIsDragOver(false)
265
- }
266
-
267
- const onDrop = (e: React.DragEvent) => {
268
- e.preventDefault()
269
- setIsDragOver(false)
270
- handleDrop?.(item)
271
- }
272
-
273
- return (
274
- <AccordionPrimitive.Root
275
- type="multiple"
276
- value={value}
277
- onValueChange={(s) => setValue(s)}
278
- >
279
- <AccordionPrimitive.Item value={item.id}>
280
- <AccordionTrigger
281
- className={cn(
282
- treeVariants(),
283
- selectedItemId === item.id && selectedTreeVariants(),
284
- isDragOver && dragOverVariants(),
285
- )}
286
- onClick={() => {
287
- handleSelectChange(item)
288
- item.onClick?.()
289
- }}
290
- draggable={!!item.draggable}
291
- onDragStart={onDragStart}
292
- onDragOver={onDragOver}
293
- onDragLeave={onDragLeave}
294
- onDrop={onDrop}
295
- >
296
- <TreeIcon
297
- item={item}
298
- isSelected={selectedItemId === item.id}
299
- isOpen={value.includes(item.id)}
300
- default={defaultNodeIcon}
301
- />
302
- <span className="text-md truncate">{item.name}</span>
303
- <TreeActions isSelected={selectedItemId === item.id}>
304
- {item.actions}
305
- </TreeActions>
306
- </AccordionTrigger>
307
- <AccordionContent className="ml-4 pl-1 border-l">
308
- <TreeItem
309
- data={item.children ? item.children : item}
310
- selectedItemId={selectedItemId}
311
- handleSelectChange={handleSelectChange}
312
- expandedItemIds={expandedItemIds}
313
- defaultLeafIcon={defaultLeafIcon}
314
- defaultNodeIcon={defaultNodeIcon}
315
- handleDragStart={handleDragStart}
316
- handleDrop={handleDrop}
317
- draggedItem={draggedItem}
318
- />
319
- </AccordionContent>
320
- </AccordionPrimitive.Item>
321
- </AccordionPrimitive.Root>
322
- )
323
- }
324
-
325
- const TreeLeaf = React.forwardRef<
326
- HTMLDivElement,
327
- React.HTMLAttributes<HTMLDivElement> & {
328
- item: TreeDataItem
329
- selectedItemId?: string
330
- handleSelectChange: (item: TreeDataItem | undefined) => void
331
- defaultLeafIcon?: any
332
- handleDragStart?: (item: TreeDataItem) => void
333
- handleDrop?: (item: TreeDataItem) => void
334
- draggedItem: TreeDataItem | null
335
- }
336
- >(
337
- (
338
- {
339
- className,
340
- item,
341
- selectedItemId,
342
- handleSelectChange,
343
- defaultLeafIcon,
344
- handleDragStart,
345
- handleDrop,
346
- draggedItem,
347
- ...props
348
- },
349
- ref,
350
- ) => {
351
- const [isDragOver, setIsDragOver] = React.useState(false)
352
-
353
- const onDragStart = (e: React.DragEvent) => {
354
- if (!item.draggable) {
355
- e.preventDefault()
356
- return
357
- }
358
- e.dataTransfer.setData('text/plain', item.id)
359
- handleDragStart?.(item)
360
- }
361
-
362
- const onDragOver = (e: React.DragEvent) => {
363
- if (
364
- item.droppable !== false &&
365
- draggedItem &&
366
- draggedItem.id !== item.id
367
- ) {
368
- e.preventDefault()
369
- setIsDragOver(true)
370
- }
371
- }
372
-
373
- const onDragLeave = () => {
374
- setIsDragOver(false)
375
- }
376
-
377
- const onDrop = (e: React.DragEvent) => {
378
- e.preventDefault()
379
- setIsDragOver(false)
380
- handleDrop?.(item)
381
- }
382
-
383
- return (
384
- <div
385
- ref={ref}
386
- className={cn(
387
- 'ml-5 flex text-left items-center py-2 cursor-pointer before:right-1',
388
- treeVariants(),
389
- className,
390
- selectedItemId === item.id && selectedTreeVariants(),
391
- isDragOver && dragOverVariants(),
392
- )}
393
- onClick={() => {
394
- handleSelectChange(item)
395
- item.onClick?.()
396
- }}
397
- draggable={!!item.draggable}
398
- onDragStart={onDragStart}
399
- onDragOver={onDragOver}
400
- onDragLeave={onDragLeave}
401
- onDrop={onDrop}
402
- {...props}
403
- >
404
- <TreeIcon
405
- item={item}
406
- isSelected={selectedItemId === item.id}
407
- default={defaultLeafIcon}
408
- />
409
- <span className="flex-grow text-md truncate">{item.name}</span>
410
- <TreeActions isSelected={selectedItemId === item.id}>
411
- {item.actions}
412
- </TreeActions>
413
- </div>
414
- )
415
- },
416
- )
417
- TreeLeaf.displayName = 'TreeLeaf'
418
-
419
- const AccordionTrigger = React.forwardRef<
420
- React.ElementRef<typeof AccordionPrimitive.Trigger>,
421
- React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
422
- >(({ className, children, ...props }, ref) => (
423
- <AccordionPrimitive.Header>
424
- <AccordionPrimitive.Trigger
425
- ref={ref}
426
- className={cn(
427
- 'flex flex-1 w-full items-center py-2 transition-all first:[&[data-state=open]>svg]:rotate-90',
428
- className,
429
- )}
430
- {...props}
431
- >
432
- <ChevronRight className="h-4 w-4 shrink-0 transition-transform duration-200 text-accent-foreground/50 mr-1" />
433
- {children}
434
- </AccordionPrimitive.Trigger>
435
- </AccordionPrimitive.Header>
436
- ))
437
- AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
438
-
439
- const AccordionContent = React.forwardRef<
440
- React.ElementRef<typeof AccordionPrimitive.Content>,
441
- React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
442
- >(({ className, children, ...props }, ref) => (
443
- <AccordionPrimitive.Content
444
- ref={ref}
445
- className={cn(
446
- 'overflow-hidden text-md transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
447
- className,
448
- )}
449
- {...props}
450
- >
451
- <div className="pb-1 pt-0">{children}</div>
452
- </AccordionPrimitive.Content>
453
- ))
454
- AccordionContent.displayName = AccordionPrimitive.Content.displayName
455
-
456
- const TreeIcon = ({
457
- item,
458
- isOpen,
459
- isSelected,
460
- default: defaultIcon,
461
- }: {
462
- item: TreeDataItem
463
- isOpen?: boolean
464
- isSelected?: boolean
465
- default?: any
466
- }) => {
467
- let Icon = defaultIcon
468
- if (isSelected && item.selectedIcon) {
469
- Icon = item.selectedIcon
470
- } else if (isOpen && item.openIcon) {
471
- Icon = item.openIcon
472
- } else if (item.icon) {
473
- Icon = item.icon
474
- }
475
- return Icon ? <Icon className="h-4 w-4 shrink-0 mr-2" /> : <></>
476
- }
477
-
478
- const TreeActions = ({
479
- children,
480
- isSelected,
481
- }: {
482
- children: React.ReactNode
483
- isSelected: boolean
484
- }) => {
485
- return (
486
- <div
487
- className={cn(
488
- isSelected ? 'block' : 'hidden',
489
- 'absolute right-3 group-hover:block',
490
- )}
491
- >
492
- {children}
493
- </div>
494
- )
495
- }
496
-
497
- export { TreeView, type TreeDataItem }
@@ -1,54 +0,0 @@
1
- import type { FileClass } from '@/types.js'
2
-
3
- export const twClasses: Record<FileClass, string> = {
4
- unchanged: 'text-gray-500',
5
- added: 'text-green-500 font-bold',
6
- modified: 'text-blue-500 italic',
7
- deleted: 'text-red-500 line-through',
8
- overwritten: 'text-red-700 underline',
9
- }
10
-
11
- export type FileClassAndInfo = {
12
- fileClass: FileClass
13
- originalFile?: string
14
- modifiedFile?: string
15
- }
16
-
17
- export const getFileClass = (
18
- file: string,
19
- tree: Record<string, string>,
20
- originalTree: Record<string, string>,
21
- localTree: Record<string, string>,
22
- deletedFiles: Array<string>,
23
- ): FileClassAndInfo => {
24
- if (localTree[file]) {
25
- if (deletedFiles.includes(file)) {
26
- return { fileClass: 'deleted', originalFile: localTree[file] }
27
- }
28
- // We have a local file and it's in the new tree
29
- if (tree[file]) {
30
- // Our new tree has changed this file
31
- if (localTree[file] !== tree[file]) {
32
- // Was the local tree different from the original?
33
- if (originalTree[file] && localTree[file] !== originalTree[file]) {
34
- // Yes, it was overwritten
35
- return {
36
- fileClass: 'overwritten',
37
- originalFile: localTree[file],
38
- modifiedFile: tree[file],
39
- }
40
- } else {
41
- // No, it just being modified
42
- return {
43
- fileClass: 'modified',
44
- originalFile: localTree[file],
45
- modifiedFile: tree[file],
46
- }
47
- }
48
- }
49
- }
50
- return { fileClass: 'unchanged', modifiedFile: localTree[file] }
51
- } else {
52
- return { fileClass: 'added', modifiedFile: tree[file] }
53
- }
54
- }
@@ -1,19 +0,0 @@
1
- import * as React from "react"
2
-
3
- const MOBILE_BREAKPOINT = 768
4
-
5
- export function useIsMobile() {
6
- const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
-
8
- React.useEffect(() => {
9
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
- const onChange = () => {
11
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
- }
13
- mql.addEventListener("change", onChange)
14
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
- return () => mql.removeEventListener("change", onChange)
16
- }, [])
17
-
18
- return !!isMobile
19
- }
@@ -1,9 +0,0 @@
1
- import * as React from 'react'
2
-
3
- export function useMounted() {
4
- const [mounted, setMounted] = React.useState(false)
5
- React.useEffect(() => {
6
- setMounted(true)
7
- }, [])
8
- return mounted
9
- }
@@ -1,27 +0,0 @@
1
- import * as React from 'react'
2
-
3
- /**
4
- * Hook that returns the user's preference for reduced motion.
5
- * @returns null if the value is not yet determined or the user's preference for reduced motion.
6
- */
7
- export const usePrefersReducedMotion = () => {
8
- const [prefersReducedMotion, setPrefersReducedMotion] = React.useState<
9
- boolean | null
10
- >(null)
11
-
12
- React.useEffect(() => {
13
- const mediaQueryList = window.matchMedia('(prefers-reduced-motion: reduce)')
14
- setPrefersReducedMotion(mediaQueryList.matches)
15
-
16
- const listener = (event: MediaQueryListEvent) => {
17
- setPrefersReducedMotion(event.matches)
18
- }
19
-
20
- mediaQueryList.addEventListener('change', listener)
21
- return () => {
22
- mediaQueryList.removeEventListener('change', listener)
23
- }
24
- }, [])
25
-
26
- return prefersReducedMotion
27
- }
@@ -1,70 +0,0 @@
1
- import { useCallback, useState } from 'react'
2
-
3
- import {
4
- InfoIcon,
5
- MessageCircleCodeIcon,
6
- PackageIcon,
7
- SquarePenIcon,
8
- TerminalIcon,
9
- } from 'lucide-react'
10
-
11
- import type { StatusStepType } from '@tanstack/cta-engine'
12
-
13
- import type { StreamEvent, StreamItem } from '@/types'
14
-
15
- const iconMap: Record<StatusStepType, typeof InfoIcon> = {
16
- file: SquarePenIcon,
17
- command: TerminalIcon,
18
- 'package-manager': PackageIcon,
19
- info: InfoIcon,
20
- other: MessageCircleCodeIcon,
21
- }
22
-
23
- export default function useStreamingStatus() {
24
- const [streamItems, setStreamItems] = useState<Array<StreamItem>>([])
25
- const [finished, setFinished] = useState(false)
26
-
27
- const monitorStream = useCallback(async (res: Response) => {
28
- setFinished(false)
29
- const reader = res.body?.getReader()
30
- const decoder = new TextDecoder()
31
-
32
- let rawStream = ''
33
- while (true) {
34
- const result = await reader?.read()
35
- if (result?.done) break
36
-
37
- rawStream += decoder.decode(result?.value)
38
-
39
- let currentId: string | undefined
40
- const newStreamItems: Array<StreamItem> = []
41
- for (const line of rawStream.split('\n')) {
42
- if (line.startsWith('{') && line.endsWith('}')) {
43
- const item = JSON.parse(line) as StreamEvent
44
- if (item.msgType === 'start') {
45
- if (currentId === item.id) {
46
- newStreamItems[newStreamItems.length - 1].message = item.message
47
- } else {
48
- currentId = item.id
49
- newStreamItems.push({
50
- id: currentId,
51
- icon: iconMap[item.type],
52
- message: item.message,
53
- })
54
- }
55
- } else {
56
- if (newStreamItems.length > 0) {
57
- newStreamItems[newStreamItems.length - 1].message = item.message
58
- }
59
- currentId = undefined
60
- }
61
- }
62
- }
63
- setStreamItems(newStreamItems)
64
- }
65
- setFinished(true)
66
- return rawStream
67
- }, [])
68
-
69
- return { finished, streamItems, monitorStream }
70
- }