create-start-app 0.6.11 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/create-app.js +2 -2
  2. package/package.json +2 -11
  3. package/src/create-app.ts +2 -2
  4. package/templates/react/add-on/start/assets/src/router.tsx.ejs +2 -0
  5. package/templates/react/base/README.md.ejs +9 -3
  6. package/templates/react/code-router/src/main.tsx.ejs +1 -0
  7. package/templates/react/example/tanchat/assets/public/example-guitar-dune.jpg +0 -0
  8. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  9. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  10. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  11. package/templates/react/example/tanchat/assets/public/example-guitar-steampunk.jpg +0 -0
  12. package/templates/react/example/tanchat/assets/public/example-guitar-underwater.jpg +0 -0
  13. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +173 -0
  14. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +47 -0
  15. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +73 -0
  16. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +5 -0
  17. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +119 -397
  18. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +50 -0
  19. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +54 -0
  20. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +3 -0
  21. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +14 -70
  22. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +43 -0
  23. package/templates/react/example/tanchat/info.json +4 -0
  24. package/templates/react/example/tanchat/package.json +4 -1
  25. package/templates/react/file-router/src/main.tsx.ejs +2 -1
  26. package/templates/react/file-router/src/routes/__root.tsx.ejs +8 -5
  27. package/templates/solid/file-router/src/main.tsx.ejs +1 -0
  28. package/tests/snapshots/cra/cr-js-npm.json +2 -2
  29. package/tests/snapshots/cra/cr-ts-npm.json +2 -2
  30. package/tests/snapshots/cra/fr-ts-npm.json +2 -2
  31. package/tests/snapshots/cra/fr-ts-tw-npm.json +2 -2
  32. package/.github/workflows/auto.yml +0 -46
  33. package/templates/react/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -148
  34. package/templates/react/example/tanchat/assets/src/store/demo.hooks.ts +0 -21
  35. package/templates/react/example/tanchat/assets/src/store/demo.store.ts +0 -133
@@ -1,46 +0,0 @@
1
- name: auto
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- schedule:
8
- - cron: '0 * * * *'
9
-
10
- concurrency: ${{ github.workflow }}-${{ github.ref }}
11
-
12
- permissions:
13
- contents: write
14
-
15
- jobs:
16
- update-templates:
17
- runs-on: ubuntu-latest
18
- steps:
19
- - name: Checkout Repo
20
- uses: actions/checkout@v4
21
- with:
22
- fetch-depth: 0
23
-
24
- - name: Setup Bun
25
- uses: oven-sh/setup-bun@v2
26
- with:
27
- bun-version: latest
28
-
29
- - name: Setup Node
30
- uses: actions/setup-node@v4
31
- with:
32
- node-version: 22
33
-
34
- - name: Publish Packages
35
- run: |
36
- npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
37
- # ~ alias create-tsrouter-app
38
- bunx gitpick@latest https://github.com/TanStack/create-tsrouter-app . --overwrite
39
- bun i && bun run build && rm -rf bun.lock
40
- bunx json -I -f package.json -e 'this.name="create-router-app"'
41
- npm publish || true
42
- # ~ alias create-tsrouter-app
43
- bunx json -I -f package.json -e 'this.name="create-start-app"'
44
- npm publish || true
45
- env:
46
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,148 +0,0 @@
1
- import { useState } from 'react'
2
- import { PlusCircle, Trash2 } from 'lucide-react'
3
- import { useAppState } from '../store/demo.hooks'
4
-
5
- interface SettingsDialogProps {
6
- isOpen: boolean
7
- onClose: () => void
8
- }
9
-
10
- export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) {
11
- const [promptForm, setPromptForm] = useState({ name: '', content: '' })
12
- const [isAddingPrompt, setIsAddingPrompt] = useState(false)
13
- const { prompts, createPrompt, deletePrompt, setPromptActive } = useAppState()
14
-
15
- const handleAddPrompt = () => {
16
- if (!promptForm.name.trim() || !promptForm.content.trim()) return
17
- createPrompt(promptForm.name, promptForm.content)
18
- setPromptForm({ name: '', content: '' })
19
- setIsAddingPrompt(false)
20
- }
21
-
22
- const handleClose = () => {
23
- onClose()
24
- setIsAddingPrompt(false)
25
- setPromptForm({ name: '', content: '' })
26
- }
27
-
28
- if (!isOpen) return null
29
-
30
- return (
31
- <div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center" onClick={(e) => {
32
- if (e.target === e.currentTarget) handleClose()
33
- }}>
34
- <div className="bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
35
- <div className="p-6">
36
- <div className="flex items-center justify-between mb-4">
37
- <h2 className="text-2xl font-semibold text-white">Settings</h2>
38
- <button
39
- onClick={handleClose}
40
- className="text-gray-400 hover:text-white focus:outline-none"
41
- >
42
- <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
43
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
44
- </svg>
45
- </button>
46
- </div>
47
-
48
- <div className="space-y-6">
49
- {/* Prompts Management */}
50
- <div className="space-y-2">
51
- <div className="flex items-center justify-between mb-4">
52
- <label className="block text-sm font-medium text-white">
53
- System Prompts
54
- </label>
55
- <button
56
- onClick={() => setIsAddingPrompt(true)}
57
- className="flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-gradient-to-r from-orange-500 to-red-600 rounded-lg hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-orange-500"
58
- >
59
- <PlusCircle className="w-4 h-4" />
60
- Add Prompt
61
- </button>
62
- </div>
63
-
64
- {isAddingPrompt && (
65
- <div className="space-y-3 mb-4 p-3 bg-gray-700/50 rounded-lg">
66
- <input
67
- type="text"
68
- value={promptForm.name}
69
- onChange={(e) => setPromptForm(prev => ({ ...prev, name: e.target.value }))}
70
- placeholder="Prompt name..."
71
- className="w-full px-3 py-2 text-sm text-white bg-gray-700 rounded-lg border border-gray-600 focus:border-orange-500 focus:ring-1 focus:ring-orange-500"
72
- />
73
- <textarea
74
- value={promptForm.content}
75
- onChange={(e) => setPromptForm(prev => ({ ...prev, content: e.target.value }))}
76
- placeholder="Enter prompt content..."
77
- className="w-full h-32 px-3 py-2 text-sm text-white bg-gray-700 rounded-lg border border-gray-600 focus:border-orange-500 focus:ring-1 focus:ring-orange-500"
78
- />
79
- <div className="flex justify-end gap-2">
80
- <button
81
- onClick={() => setIsAddingPrompt(false)}
82
- className="px-3 py-1.5 text-sm font-medium text-gray-300 hover:text-white focus:outline-none"
83
- >
84
- Cancel
85
- </button>
86
- <button
87
- onClick={handleAddPrompt}
88
- className="px-3 py-1.5 text-sm font-medium text-white bg-gradient-to-r from-orange-500 to-red-600 rounded-lg hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-orange-500"
89
- >
90
- Save Prompt
91
- </button>
92
- </div>
93
- </div>
94
- )}
95
-
96
- <div className="space-y-2">
97
- {prompts.map((prompt) => (
98
- <div key={prompt.id} className="flex items-center justify-between p-3 bg-gray-700/50 rounded-lg">
99
- <div className="flex-1 min-w-0 mr-4">
100
- <h4 className="text-sm font-medium text-white truncate">{prompt.name}</h4>
101
- <p className="text-xs text-gray-400 truncate">{prompt.content}</p>
102
- </div>
103
- <div className="flex items-center gap-2">
104
- <label className="relative inline-flex items-center cursor-pointer">
105
- <input
106
- type="checkbox"
107
- className="sr-only peer"
108
- checked={prompt.is_active}
109
- onChange={() => setPromptActive(prompt.id, !prompt.is_active)}
110
- />
111
- <div className="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-orange-500"></div>
112
- </label>
113
- <button
114
- onClick={() => deletePrompt(prompt.id)}
115
- className="p-1 text-gray-400 hover:text-red-500"
116
- >
117
- <Trash2 className="w-4 h-4" />
118
- </button>
119
- </div>
120
- </div>
121
- ))}
122
- </div>
123
- <p className="text-xs text-gray-400">
124
- Create and manage custom system prompts. Only one prompt can be active at a time.
125
- </p>
126
- </div>
127
-
128
- </div>
129
-
130
- <div className="mt-6 flex justify-end gap-3">
131
- <button
132
- onClick={handleClose}
133
- className="px-4 py-2 text-sm font-medium text-gray-300 hover:text-white focus:outline-none"
134
- >
135
- Cancel
136
- </button>
137
- <button
138
- onClick={handleClose}
139
- className="px-4 py-2 text-sm font-medium text-white bg-gradient-to-r from-orange-500 to-red-600 rounded-lg hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-orange-500"
140
- >
141
- Close
142
- </button>
143
- </div>
144
- </div>
145
- </div>
146
- </div>
147
- )
148
- }
@@ -1,21 +0,0 @@
1
- import { useStore } from '@tanstack/react-store'
2
- import { store, actions, selectors } from './demo.store'
3
-
4
- export type { State, Prompt, Conversation } from './demo.store'
5
-
6
- export function useAppState() {
7
- const state = useStore(store)
8
- return {
9
- ...state,
10
- ...actions,
11
- ...selectors
12
- }
13
- }
14
-
15
- export function useAppActions() {
16
- return actions
17
- }
18
-
19
- export function useAppSelectors() {
20
- return selectors
21
- }
@@ -1,133 +0,0 @@
1
- import { Store } from '@tanstack/store'
2
- import type { Message } from '../utils/demo.ai'
3
-
4
- // Types
5
- export interface Prompt {
6
- id: string
7
- name: string
8
- content: string
9
- is_active: boolean
10
- created_at: number
11
- }
12
-
13
- export interface Conversation {
14
- id: string
15
- title: string
16
- messages: Message[]
17
- }
18
-
19
- export interface State {
20
- prompts: Prompt[]
21
- conversations: Conversation[]
22
- currentConversationId: string | null
23
- isLoading: boolean
24
- }
25
-
26
- const initialState: State = {
27
- prompts: [],
28
- conversations: [],
29
- currentConversationId: null,
30
- isLoading: false
31
- }
32
-
33
- export const store = new Store<State>(initialState)
34
-
35
- export const actions = {
36
- // Prompt actions
37
- createPrompt: (name: string, content: string) => {
38
- const id = Date.now().toString()
39
- store.setState(state => {
40
- const updatedPrompts = state.prompts.map(p => ({ ...p, is_active: false }))
41
- return {
42
- ...state,
43
- prompts: [
44
- ...updatedPrompts,
45
- {
46
- id,
47
- name,
48
- content,
49
- is_active: true,
50
- created_at: Date.now()
51
- }
52
- ]
53
- }
54
- })
55
- },
56
-
57
- deletePrompt: (id: string) => {
58
- store.setState(state => ({
59
- ...state,
60
- prompts: state.prompts.filter(p => p.id !== id)
61
- }))
62
- },
63
-
64
- setPromptActive: (id: string, shouldActivate: boolean) => {
65
- store.setState(state => ({
66
- ...state,
67
- prompts: state.prompts.map(p => ({
68
- ...p,
69
- is_active: p.id === id ? shouldActivate : false
70
- }))
71
- }))
72
- },
73
-
74
- // Chat actions
75
- setConversations: (conversations: Conversation[]) => {
76
- store.setState(state => ({ ...state, conversations }))
77
- },
78
-
79
- setCurrentConversationId: (id: string | null) => {
80
- store.setState(state => ({ ...state, currentConversationId: id }))
81
- },
82
-
83
- addConversation: (conversation: Conversation) => {
84
- store.setState(state => ({
85
- ...state,
86
- conversations: [...state.conversations, conversation],
87
- currentConversationId: conversation.id
88
- }))
89
- },
90
-
91
- updateConversationTitle: (id: string, title: string) => {
92
- store.setState(state => ({
93
- ...state,
94
- conversations: state.conversations.map(conv =>
95
- conv.id === id ? { ...conv, title } : conv
96
- )
97
- }))
98
- },
99
-
100
- deleteConversation: (id: string) => {
101
- store.setState(state => ({
102
- ...state,
103
- conversations: state.conversations.filter(conv => conv.id !== id),
104
- currentConversationId: state.currentConversationId === id ? null : state.currentConversationId
105
- }))
106
- },
107
-
108
- addMessage: (conversationId: string, message: Message) => {
109
- store.setState(state => ({
110
- ...state,
111
- conversations: state.conversations.map(conv =>
112
- conv.id === conversationId
113
- ? { ...conv, messages: [...conv.messages, message] }
114
- : conv
115
- )
116
- }))
117
- },
118
-
119
- setLoading: (isLoading: boolean) => {
120
- store.setState(state => ({ ...state, isLoading }))
121
- }
122
- }
123
-
124
- // Selectors
125
- export const selectors = {
126
- getActivePrompt: (state: State) => state.prompts.find(p => p.is_active),
127
- getCurrentConversation: (state: State) =>
128
- state.conversations.find(c => c.id === state.currentConversationId),
129
- getPrompts: (state: State) => state.prompts,
130
- getConversations: (state: State) => state.conversations,
131
- getCurrentConversationId: (state: State) => state.currentConversationId,
132
- getIsLoading: (state: State) => state.isLoading
133
- }