@tanstack/cta-ui 0.15.2 → 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,203 +0,0 @@
1
- import { useMemo, useState } from 'react'
2
- import { FileText, Folder } from 'lucide-react'
3
-
4
- import FileViewer from './file-viewer'
5
- import FileTree from './file-tree'
6
-
7
- import type { FileTreeItem } from '@/types'
8
-
9
- import { Label } from '@/components/ui/label'
10
- import { Switch } from '@/components/ui/switch'
11
-
12
- import {
13
- useApplicationMode,
14
- useDryRun,
15
- useFilters,
16
- useOriginalOutput,
17
- useProjectLocalFiles,
18
- useReady,
19
- } from '@/store/project'
20
-
21
- import { getFileClass, twClasses } from '@/file-classes'
22
-
23
- export function Filters() {
24
- const { includedFiles, toggleFilter } = useFilters()
25
-
26
- return (
27
- <div className="bg-white dark:bg-black/40 shadow-xl p-4 rounded-lg flex flex-row items-center gap-4 mb-2">
28
- <h3 className="font-medium whitespace-nowrap">File Filters</h3>
29
- <div className="flex flex-row items-center">
30
- <Switch
31
- id="unchanged"
32
- checked={includedFiles.includes('unchanged')}
33
- onCheckedChange={() => toggleFilter('unchanged')}
34
- className="mr-2"
35
- />
36
- <Label htmlFor="unchanged" className={twClasses.unchanged}>
37
- Unchanged
38
- </Label>
39
- </div>
40
- <div className="flex flex-row items-center">
41
- <Switch
42
- id="added"
43
- checked={includedFiles.includes('added')}
44
- onCheckedChange={() => toggleFilter('added')}
45
- className="mr-2"
46
- />
47
- <Label htmlFor="added" className={twClasses.added}>
48
- Added
49
- </Label>
50
- </div>
51
- <div className="flex flex-row items-center">
52
- <Switch
53
- id="modified"
54
- checked={includedFiles.includes('modified')}
55
- onCheckedChange={() => toggleFilter('modified')}
56
- className="mr-2"
57
- />
58
- <Label htmlFor="modified" className={twClasses.modified}>
59
- Modified
60
- </Label>
61
- </div>
62
- <div className="flex flex-row items-center">
63
- <Switch
64
- id="deleted"
65
- checked={includedFiles.includes('deleted')}
66
- onCheckedChange={() => toggleFilter('deleted')}
67
- className="mr-2"
68
- />
69
- <Label htmlFor="deleted" className={twClasses.deleted}>
70
- Deleted
71
- </Label>
72
- </div>
73
- <div className="flex flex-row items-center">
74
- <Switch
75
- id="overwritten"
76
- checked={includedFiles.includes('overwritten')}
77
- onCheckedChange={() => toggleFilter('overwritten')}
78
- className="mr-2"
79
- />
80
- <Label htmlFor="overwritten" className={twClasses.overwritten}>
81
- Overwritten
82
- </Label>
83
- </div>
84
- </div>
85
- )
86
- }
87
-
88
- export default function FileNavigator() {
89
- const [selectedFile, setSelectedFile] = useState<string | null>(
90
- './package.json',
91
- )
92
-
93
- const projectFiles = useOriginalOutput()
94
- const localTree = useProjectLocalFiles()
95
- const dryRunOutput = useDryRun()
96
-
97
- const mode = useApplicationMode()
98
-
99
- const tree = dryRunOutput.files
100
- const originalTree =
101
- mode === 'setup' ? dryRunOutput.files : projectFiles.files
102
- const deletedFiles = dryRunOutput.deletedFiles
103
-
104
- const [originalFileContents, setOriginalFileContents] = useState<string>()
105
- const [modifiedFileContents, setModifiedFileContents] = useState<string>()
106
-
107
- const { includedFiles } = useFilters()
108
-
109
- const fileTree = useMemo(() => {
110
- const treeData: Array<FileTreeItem> = []
111
-
112
- const allFileSet = Array.from(
113
- new Set([
114
- ...Object.keys(tree),
115
- ...Object.keys(localTree),
116
- ...Object.keys(originalTree),
117
- ]),
118
- )
119
-
120
- allFileSet.sort().forEach((file) => {
121
- const strippedFile = file.replace('./', '')
122
- const parts = strippedFile.split('/')
123
-
124
- let currentLevel = treeData
125
- parts.forEach((part, index) => {
126
- const existingNode = currentLevel.find((node) => node.name === part)
127
- if (existingNode) {
128
- currentLevel = existingNode.children || []
129
- } else {
130
- const fileInfo = getFileClass(
131
- file,
132
- tree,
133
- originalTree,
134
- localTree,
135
- deletedFiles,
136
- )
137
-
138
- if (
139
- index === parts.length - 1 &&
140
- !includedFiles.includes(fileInfo.fileClass)
141
- ) {
142
- return
143
- }
144
- if (index === parts.length - 1 && file === selectedFile) {
145
- setModifiedFileContents(fileInfo.modifiedFile)
146
- setOriginalFileContents(fileInfo.originalFile)
147
- }
148
-
149
- const newNode: FileTreeItem = {
150
- id: parts.slice(0, index + 1).join('/'),
151
- name: part,
152
- fullPath: strippedFile,
153
- children: index < parts.length - 1 ? [] : undefined,
154
- icon:
155
- index < parts.length - 1
156
- ? () => <Folder className="w-4 h-4 mr-2" />
157
- : () => <FileText className="w-4 h-4 mr-2" />,
158
- onClick:
159
- index === parts.length - 1
160
- ? () => {
161
- setSelectedFile(file)
162
- setModifiedFileContents(fileInfo.modifiedFile)
163
- setOriginalFileContents(fileInfo.originalFile)
164
- }
165
- : undefined,
166
- className: twClasses[fileInfo.fileClass],
167
- ...fileInfo,
168
- contents: tree[file] || localTree[file] || originalTree[file],
169
- }
170
- currentLevel.push(newNode)
171
- currentLevel = newNode.children!
172
- }
173
- })
174
- })
175
- return treeData
176
- }, [tree, originalTree, localTree, includedFiles])
177
-
178
- const ready = useReady()
179
-
180
- if (!ready) {
181
- return null
182
- }
183
-
184
- return (
185
- <div className="bg-white dark:bg-black/50 rounded-lg p-2 sm:p-4">
186
- {mode === 'add' && <Filters />}
187
- <div className="flex flex-row @container">
188
- <div className="w-1/3 @6xl:w-1/4 bg-gray-500/10 rounded-l-lg">
189
- <FileTree selectedFile={selectedFile} tree={fileTree} />
190
- </div>
191
- <div className="w-2/3 @6xl:w-3/4">
192
- {selectedFile && modifiedFileContents ? (
193
- <FileViewer
194
- filePath={selectedFile}
195
- originalFile={originalFileContents}
196
- modifiedFile={modifiedFileContents}
197
- />
198
- ) : null}
199
- </div>
200
- </div>
201
- </div>
202
- )
203
- }
@@ -1,35 +0,0 @@
1
- import { useMemo } from 'react'
2
- import { FileText, Folder } from 'lucide-react'
3
-
4
- import type { FileTreeItem } from '@/types.js'
5
-
6
- import { TreeView } from '@/components/ui/tree-view'
7
-
8
- export default function FileTree({
9
- selectedFile,
10
- tree,
11
- }: {
12
- selectedFile: string | null
13
- tree: Array<FileTreeItem>
14
- }) {
15
- const initialExpandedItemIds = useMemo(
16
- () => [
17
- 'src',
18
- 'src/routes',
19
- 'src/components',
20
- 'src/components/ui',
21
- 'src/lib',
22
- ],
23
- [],
24
- )
25
-
26
- return (
27
- <TreeView
28
- initialSelectedItemId={selectedFile?.replace('./', '') ?? undefined}
29
- initialExpandedItemIds={initialExpandedItemIds}
30
- data={tree}
31
- defaultNodeIcon={() => <Folder className="w-4 h-4 mr-2" />}
32
- defaultLeafIcon={() => <FileText className="w-4 h-4 mr-2" />}
33
- />
34
- )
35
- }
@@ -1,67 +0,0 @@
1
- import CodeMirror from '@uiw/react-codemirror'
2
- import CodeMirrorMerge from 'react-codemirror-merge'
3
-
4
- import { javascript } from '@codemirror/lang-javascript'
5
- import { json } from '@codemirror/lang-json'
6
- import { css } from '@codemirror/lang-css'
7
- import { html } from '@codemirror/lang-html'
8
-
9
- import { githubDarkInit } from '@uiw/codemirror-theme-github'
10
-
11
- const theme = githubDarkInit({
12
- settings: {
13
- background: 'oklch(0.07 0.005 285.823)',
14
- foreground: '#c9d1d9',
15
- gutterBackground: 'oklch(0.22 0.005 285.823)',
16
- },
17
- })
18
-
19
- export default function FileViewer({
20
- originalFile,
21
- modifiedFile,
22
- filePath,
23
- }: {
24
- originalFile?: string
25
- modifiedFile: string
26
- filePath: string
27
- }) {
28
- function getLanguage(file: string) {
29
- if (file.endsWith('.js') || file.endsWith('.jsx')) {
30
- return javascript({ jsx: true })
31
- }
32
- if (file.endsWith('.ts') || file.endsWith('.tsx')) {
33
- return javascript({ typescript: true, jsx: true })
34
- }
35
- if (file.endsWith('.json')) {
36
- return json()
37
- }
38
- if (file.endsWith('.css')) {
39
- return css()
40
- }
41
- if (file.endsWith('.html')) {
42
- return html()
43
- }
44
- return javascript()
45
- }
46
- const language = getLanguage(filePath)
47
-
48
- if (!originalFile || originalFile === modifiedFile) {
49
- return (
50
- <CodeMirror
51
- value={modifiedFile}
52
- theme={theme}
53
- height="100vh"
54
- width="100%"
55
- readOnly
56
- extensions={[language]}
57
- className="text-lg"
58
- />
59
- )
60
- }
61
- return (
62
- <CodeMirrorMerge orientation="a-b" theme={theme} className="text-lg">
63
- <CodeMirrorMerge.Original value={originalFile} extensions={[language]} />
64
- <CodeMirrorMerge.Modified value={modifiedFile} extensions={[language]} />
65
- </CodeMirrorMerge>
66
- )
67
- }
@@ -1,31 +0,0 @@
1
- export function AppHeader() {
2
- return (
3
- <div className="bg-white dark:bg-black/50 rounded-lg p-2 sm:p-4 flex items-center gap-2 text-lg sm:text-xl shadow-xl">
4
- <div className="flex items-center gap-1.5">
5
- <img
6
- src="/logo-color-100w.png"
7
- alt="TanStack Logo"
8
- className="w-[30px] rounded-full overflow-hidden border-2 border-black dark:border-none"
9
- />
10
- <div className="font-black text-xl uppercase">TanStack</div>
11
- </div>
12
- <svg
13
- stroke="currentColor"
14
- fill="currentColor"
15
- stroke-width="0"
16
- viewBox="0 0 256 512"
17
- height="1em"
18
- width="1em"
19
- xmlns="http://www.w3.org/2000/svg"
20
- >
21
- <path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path>
22
- </svg>
23
- <div className="hover:text-blue-500 flex items-center gap-2">
24
- Create TanStack App{' '}
25
- <span className="bg-gradient-to-r from-blue-500 to-cyan-500 text-white text-xs font-bold px-2 py-0.5 rounded">
26
- ALPHA
27
- </span>
28
- </div>
29
- </div>
30
- )
31
- }
@@ -1,94 +0,0 @@
1
- import { useMemo, useState, Fragment } from 'react'
2
- import { InfoIcon } from 'lucide-react'
3
-
4
- import type { AddOnInfo } from '@/types'
5
-
6
- import { Switch } from '@/components/ui/switch'
7
- import { Label } from '@/components/ui/label'
8
-
9
- import { useAddOns } from '@/store/project'
10
-
11
- import ImportCustomAddOn from '@/components/custom-add-on-dialog'
12
- import AddOnInfoDialog from '@/components/add-on-info-dialog'
13
-
14
- const addOnTypeLabels: Record<string, string> = {
15
- toolchain: 'Toolchain',
16
- 'add-on': 'Add-on',
17
- example: 'Example',
18
- }
19
-
20
- export default function SelectedAddOns() {
21
- const { availableAddOns, addOnState, toggleAddOn } = useAddOns()
22
-
23
- const sortedAddOns = useMemo(() => {
24
- return availableAddOns.sort((a, b) => {
25
- return a.name.localeCompare(b.name)
26
- })
27
- }, [availableAddOns])
28
-
29
- const [infoAddOn, setInfoAddOn] = useState<AddOnInfo>()
30
-
31
- return (
32
- <>
33
- <AddOnInfoDialog
34
- addOn={infoAddOn}
35
- onClose={() => setInfoAddOn(undefined)}
36
- />
37
- {Object.keys(addOnTypeLabels).map((type) => (
38
- <Fragment key={type}>
39
- {sortedAddOns.filter((addOn) => addOn.type === type).length > 0 && (
40
- <div
41
- key={`${type}-add-ons`}
42
- className="block p-4 bg-gray-500/10 hover:bg-gray-500/20 rounded-lg transition-colors space-y-4 active"
43
- >
44
- <h3 className="font-medium">{addOnTypeLabels[type]}</h3>
45
- <div className="flex flex-row flex-wrap">
46
- {sortedAddOns
47
- .filter((addOn) => addOn.type === type)
48
- .map((addOn) => (
49
- <div
50
- key={addOn.id}
51
- className="w-1/2 flex flex-row justify-between pr-4"
52
- >
53
- <div className="p-1 flex flex-row items-center">
54
- <Switch
55
- id={addOn.id}
56
- checked={addOnState[addOn.id].selected}
57
- disabled={!addOnState[addOn.id].enabled}
58
- onCheckedChange={() => {
59
- toggleAddOn(addOn.id)
60
- }}
61
- />
62
- <Label
63
- htmlFor={addOn.id}
64
- className="pl-2 font-semibold text-gray-300"
65
- >
66
- {addOn.smallLogo && (
67
- <img
68
- src={`data:image/svg+xml,${encodeURIComponent(
69
- addOn.smallLogo,
70
- )}`}
71
- alt={addOn.name}
72
- className="w-5"
73
- />
74
- )}
75
- {addOn.name}
76
- </Label>
77
- <InfoIcon
78
- className="ml-2 w-4 text-gray-600"
79
- onClick={() => setInfoAddOn(addOn)}
80
- />
81
- </div>
82
- </div>
83
- ))}
84
- </div>
85
- </div>
86
- )}
87
- </Fragment>
88
- ))}
89
- <div className="mt-4">
90
- <ImportCustomAddOn />
91
- </div>
92
- </>
93
- )
94
- }
@@ -1,57 +0,0 @@
1
- import { CodeIcon, FileIcon } from 'lucide-react'
2
-
3
- import type { Mode } from '@tanstack/cta-engine'
4
-
5
- import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
6
-
7
- import {
8
- setRouterMode,
9
- useApplicationMode,
10
- useModeEditable,
11
- useRouterMode,
12
- } from '@/store/project'
13
-
14
- export default function ModeSelector() {
15
- const mode = useApplicationMode()
16
- const enableMode = useModeEditable()
17
- const routerMode = useRouterMode()
18
-
19
- if (mode !== 'setup') {
20
- return null
21
- }
22
-
23
- return (
24
- <div className="flex flex-col @md:flex-row @md:items-center gap-2 items-start">
25
- <h3 className="font-medium whitespace-nowrap">Router Mode</h3>
26
- <div className="flex flex-row justify-center items-center">
27
- <ToggleGroup
28
- type="single"
29
- value={routerMode}
30
- onValueChange={(v: string) => {
31
- if (v) {
32
- setRouterMode(v as Mode)
33
- }
34
- }}
35
- className="rounded-md border-2 border-gray-500/10"
36
- >
37
- <ToggleGroupItem
38
- value="code-router"
39
- className="px-4"
40
- disabled={!enableMode}
41
- >
42
- <CodeIcon className="w-4 h-4" />
43
- Code Router
44
- </ToggleGroupItem>
45
- <ToggleGroupItem
46
- value="file-router"
47
- className="px-4"
48
- disabled={!enableMode}
49
- >
50
- <FileIcon className="w-4 h-4" />
51
- File Router
52
- </ToggleGroupItem>
53
- </ToggleGroup>
54
- </div>
55
- </div>
56
- )
57
- }
@@ -1,28 +0,0 @@
1
- import { Input } from '@/components/ui/input'
2
-
3
- import {
4
- setProjectName,
5
- useApplicationMode,
6
- useProjectName,
7
- } from '@/store/project'
8
-
9
- export default function ProjectName() {
10
- const name = useProjectName()
11
- const mode = useApplicationMode()
12
-
13
- if (mode !== 'setup') {
14
- return null
15
- }
16
-
17
- return (
18
- <div className="flex flex-row gap-2 items-center">
19
- <h3 className="font-medium whitespace-nowrap">Project Name</h3>
20
- <Input
21
- value={name}
22
- placeholder="my-app"
23
- onChange={(e) => setProjectName(e.target.value)}
24
- className="w-full bg-gray-500/10 rounded-md px-2 py-1 min-w-[200px] text-sm"
25
- />
26
- </div>
27
- )
28
- }
@@ -1,71 +0,0 @@
1
- import { useState } from 'react'
2
-
3
- import { Button } from '@/components/ui/button'
4
- import {
5
- Dialog,
6
- DialogContent,
7
- DialogFooter,
8
- DialogHeader,
9
- DialogTitle,
10
- } from '@/components/ui/dialog'
11
-
12
- import { useAddOns, useApplicationMode } from '@/store/project'
13
- import useStreamingStatus from '@/hooks/use-streaming-status'
14
- import StatusList from '@/components/StatusList'
15
- import { addToAppStreaming, shutdown } from '@/lib/api'
16
-
17
- export default function RunAddOns() {
18
- const { chosenAddOns } = useAddOns()
19
- const [isRunning, setIsRunning] = useState(false)
20
- const { streamItems, monitorStream, finished } = useStreamingStatus()
21
-
22
- const mode = useApplicationMode()
23
-
24
- if (mode !== 'add') {
25
- return null
26
- }
27
-
28
- async function onAddToApp() {
29
- setIsRunning(true)
30
- monitorStream(await addToAppStreaming(chosenAddOns))
31
- }
32
-
33
- return (
34
- <div>
35
- <Dialog open={isRunning}>
36
- <DialogContent
37
- className="sm:min-w-[425px] sm:max-w-fit"
38
- hideCloseButton
39
- >
40
- <DialogHeader>
41
- <DialogTitle>Adding Add-Ons</DialogTitle>
42
- </DialogHeader>
43
- <StatusList streamItems={streamItems} finished={finished} />
44
- <DialogFooter>
45
- <Button
46
- variant="default"
47
- onClick={async () => {
48
- await shutdown()
49
- window.close()
50
- }}
51
- disabled={!finished}
52
- >
53
- Exit This Application
54
- </Button>
55
- </DialogFooter>
56
- </DialogContent>
57
- </Dialog>
58
-
59
- <div className="flex flex-col gap-2">
60
- <Button
61
- variant="default"
62
- onClick={onAddToApp}
63
- disabled={chosenAddOns.length === 0 || isRunning}
64
- className="w-full"
65
- >
66
- Add These Add-Ons To Your App
67
- </Button>
68
- </div>
69
- </div>
70
- )
71
- }
@@ -1,82 +0,0 @@
1
- import { useState } from 'react'
2
- import { HammerIcon } from 'lucide-react'
3
-
4
- import { Button } from '@/components/ui/button'
5
- import {
6
- Dialog,
7
- DialogContent,
8
- DialogFooter,
9
- DialogHeader,
10
- DialogTitle,
11
- } from '@/components/ui/dialog'
12
-
13
- import useStreamingStatus from '@/hooks/use-streaming-status'
14
- import {
15
- useAddOns,
16
- useApplicationMode,
17
- useProjectOptions,
18
- useProjectStarter,
19
- } from '@/store/project'
20
- import StatusList from '@/components/StatusList'
21
- import { createAppStreaming, shutdown } from '@/lib/api'
22
-
23
- export default function RunCreateApp() {
24
- const [isRunning, setIsRunning] = useState(false)
25
- const { streamItems, monitorStream, finished } = useStreamingStatus()
26
-
27
- const mode = useApplicationMode()
28
- const options = useProjectOptions()
29
- const { chosenAddOns } = useAddOns()
30
- const { projectStarter } = useProjectStarter()
31
-
32
- if (mode !== 'setup') {
33
- return null
34
- }
35
-
36
- async function onAddToApp() {
37
- setIsRunning(true)
38
- monitorStream(
39
- await createAppStreaming(options, chosenAddOns, projectStarter),
40
- )
41
- }
42
-
43
- return (
44
- <div>
45
- <Dialog open={isRunning}>
46
- <DialogContent
47
- className="sm:min-w-[425px] sm:max-w-fit"
48
- hideCloseButton
49
- >
50
- <DialogHeader>
51
- <DialogTitle>Creating Your Application</DialogTitle>
52
- </DialogHeader>
53
- <StatusList streamItems={streamItems} finished={finished} />
54
- <DialogFooter>
55
- <Button
56
- variant="default"
57
- onClick={async () => {
58
- await shutdown()
59
- window.close()
60
- }}
61
- disabled={!finished}
62
- >
63
- Exit This Application
64
- </Button>
65
- </DialogFooter>
66
- </DialogContent>
67
- </Dialog>
68
-
69
- <div className="flex flex-col gap-2">
70
- <Button
71
- variant="default"
72
- onClick={onAddToApp}
73
- disabled={isRunning}
74
- className="w-full"
75
- >
76
- <HammerIcon className="w-4 h-4" />
77
- Build Your App
78
- </Button>
79
- </div>
80
- </div>
81
- )
82
- }