kaddidlehopper 0.5.0 → 0.6.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 (296) hide show
  1. package/dist/cli.js +104 -208
  2. package/dist/index.js +1 -31
  3. package/dist/types/cli.d.ts +1 -8
  4. package/dist/types/types.d.ts +7 -12
  5. package/package.json +1 -2
  6. package/src/cli.ts +129 -271
  7. package/src/index.ts +1 -47
  8. package/src/types.ts +7 -13
  9. package/CONTEXT.md +0 -139
  10. package/add-ons/ai/README.md +0 -34
  11. package/add-ons/ai/assets/AGENTS.md.append +0 -24
  12. package/add-ons/ai/assets/_dot_env.local.append +0 -13
  13. package/add-ons/ai/assets/src/components/AIAssistant.tsx +0 -149
  14. package/add-ons/ai/assets/src/lib/ai-hook.ts +0 -21
  15. package/add-ons/ai/assets/src/lib/weather-tools.ts +0 -30
  16. package/add-ons/ai/assets/src/routes/api.chat.ts +0 -94
  17. package/add-ons/ai/assets/src/routes/chat.css +0 -175
  18. package/add-ons/ai/assets/src/routes/chat.tsx +0 -141
  19. package/add-ons/ai/info.json +0 -22
  20. package/add-ons/ai/package.json +0 -17
  21. package/add-ons/ai/small-logo.svg +0 -8
  22. package/add-ons/db/assets/AGENTS.md.append +0 -22
  23. package/add-ons/db/assets/DB-SETUP.md +0 -65
  24. package/add-ons/db/assets/_dot_env.local.append +0 -2
  25. package/add-ons/db/assets/drizzle.config.ts +0 -10
  26. package/add-ons/db/assets/src/db/index.ts +0 -8
  27. package/add-ons/db/assets/src/db/schema.ts +0 -8
  28. package/add-ons/db/assets/src/routes/db-example.tsx +0 -118
  29. package/add-ons/db/assets/src/server/guestbook.functions.ts +0 -23
  30. package/add-ons/db/info.json +0 -22
  31. package/add-ons/db/package.json +0 -10
  32. package/add-ons/forms/assets/AGENTS.md.append +0 -13
  33. package/add-ons/forms/assets/public/form-example.html +0 -14
  34. package/add-ons/forms/assets/src/routes/form-example.tsx +0 -76
  35. package/add-ons/forms/info.json +0 -18
  36. package/add-ons/forms/package.json +0 -3
  37. package/examples/ai-chat/README.md +0 -36
  38. package/examples/ai-chat/assets/AGENTS.md.append +0 -24
  39. package/examples/ai-chat/assets/src/lib/ai-hook.ts +0 -21
  40. package/examples/ai-chat/assets/src/lib/weather-tools.ts +0 -30
  41. package/examples/ai-chat/assets/src/routes/__root.tsx +0 -57
  42. package/examples/ai-chat/assets/src/routes/api.chat.ts +0 -94
  43. package/examples/ai-chat/assets/src/routes/index.tsx +0 -141
  44. package/examples/ai-chat/assets/src/styles.css +0 -165
  45. package/examples/ai-chat/info.json +0 -25
  46. package/examples/ai-chat/package.json +0 -14
  47. package/examples/blog/README.md +0 -60
  48. package/examples/blog/assets/AGENTS.md.append +0 -18
  49. package/examples/blog/assets/content/posts/beach.md +0 -12
  50. package/examples/blog/assets/content/posts/jungle.md.ejs +0 -12
  51. package/examples/blog/assets/content/posts/mountains.md.ejs +0 -12
  52. package/examples/blog/assets/content/posts/snorkeling.md.ejs +0 -12
  53. package/examples/blog/assets/content/posts/waterfall.md.ejs +0 -12
  54. package/examples/blog/assets/content-collections.ts +0 -30
  55. package/examples/blog/assets/public/beach.jpg +0 -0
  56. package/examples/blog/assets/public/jungle.jpg +0 -0
  57. package/examples/blog/assets/public/mountains.jpg +0 -0
  58. package/examples/blog/assets/public/snorkeling.jpg +0 -0
  59. package/examples/blog/assets/public/waterfall.jpg +0 -0
  60. package/examples/blog/assets/src/components/Header.tsx +0 -52
  61. package/examples/blog/assets/src/components/VacayAssistant.tsx +0 -205
  62. package/examples/blog/assets/src/components/blog-posts.tsx +0 -78
  63. package/examples/blog/assets/src/components/ui/card.tsx +0 -92
  64. package/examples/blog/assets/src/lib/blog-ai-hook.ts +0 -25
  65. package/examples/blog/assets/src/lib/blog-tools.ts +0 -111
  66. package/examples/blog/assets/src/lib/utils.ts +0 -6
  67. package/examples/blog/assets/src/routes/__root.tsx +0 -57
  68. package/examples/blog/assets/src/routes/api.blog-chat.ts +0 -117
  69. package/examples/blog/assets/src/routes/category.$category.tsx +0 -19
  70. package/examples/blog/assets/src/routes/index.tsx +0 -19
  71. package/examples/blog/assets/src/routes/posts.$slug.tsx +0 -63
  72. package/examples/blog/assets/src/styles.css +0 -138
  73. package/examples/blog/info.json +0 -40
  74. package/examples/blog/package.json +0 -23
  75. package/examples/calculator/README.md +0 -16
  76. package/examples/calculator/assets/AGENTS.md.append +0 -9
  77. package/examples/calculator/assets/src/components/Calculator.tsx +0 -238
  78. package/examples/calculator/assets/src/components/Header.tsx +0 -17
  79. package/examples/calculator/assets/src/routes/__root.tsx +0 -57
  80. package/examples/calculator/assets/src/routes/index.tsx +0 -14
  81. package/examples/calculator/info.json +0 -20
  82. package/examples/calculator/package.json +0 -1
  83. package/examples/dashboard/README.md +0 -17
  84. package/examples/dashboard/assets/AGENTS.md.append +0 -12
  85. package/examples/dashboard/assets/src/components/Header.tsx +0 -17
  86. package/examples/dashboard/assets/src/routes/__root.tsx +0 -57
  87. package/examples/dashboard/assets/src/routes/index.tsx +0 -158
  88. package/examples/dashboard/info.json +0 -19
  89. package/examples/dashboard/package.json +0 -6
  90. package/examples/ecommerce/README.md +0 -48
  91. package/examples/ecommerce/assets/AGENTS.md.append +0 -22
  92. package/examples/ecommerce/assets/public/logo.png +0 -0
  93. package/examples/ecommerce/assets/public/motorcycle-scooter.jpg +0 -0
  94. package/examples/ecommerce/assets/src/components/BuyButton.tsx +0 -35
  95. package/examples/ecommerce/assets/src/components/Header.tsx +0 -36
  96. package/examples/ecommerce/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
  97. package/examples/ecommerce/assets/src/components/MotorcycleRecommendation.tsx +0 -53
  98. package/examples/ecommerce/assets/src/data/motorcycles.ts +0 -27
  99. package/examples/ecommerce/assets/src/lib/motorcycle-ai-hook.ts +0 -24
  100. package/examples/ecommerce/assets/src/lib/motorcycle-tools.ts +0 -42
  101. package/examples/ecommerce/assets/src/lib/stripe.server.ts +0 -39
  102. package/examples/ecommerce/assets/src/routes/__root.tsx +0 -57
  103. package/examples/ecommerce/assets/src/routes/api.motorcycle-chat.ts +0 -78
  104. package/examples/ecommerce/assets/src/routes/checkout/cancel.tsx +0 -25
  105. package/examples/ecommerce/assets/src/routes/checkout/success.tsx +0 -25
  106. package/examples/ecommerce/assets/src/routes/index.tsx +0 -76
  107. package/examples/ecommerce/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -55
  108. package/examples/ecommerce/assets/src/store/motorcycle-assistant.ts +0 -3
  109. package/examples/ecommerce/assets/src/styles.css +0 -212
  110. package/examples/ecommerce/info.json +0 -38
  111. package/examples/ecommerce/package.json +0 -13
  112. package/examples/events/README.md +0 -110
  113. package/examples/events/assets/AGENTS.md.append +0 -21
  114. package/examples/events/assets/content/speakers/andre-costa.md +0 -22
  115. package/examples/events/assets/content/speakers/hans-mueller.md.ejs +0 -22
  116. package/examples/events/assets/content/speakers/isabella-martinez.md.ejs +0 -22
  117. package/examples/events/assets/content/speakers/kenji-nakamura.md.ejs +0 -22
  118. package/examples/events/assets/content/speakers/marie-dubois.md.ejs +0 -20
  119. package/examples/events/assets/content/speakers/priya-sharma.md.ejs +0 -22
  120. package/examples/events/assets/content/talks/croissant-lamination-secrets.md +0 -39
  121. package/examples/events/assets/content/talks/french-macaron-mastery.md.ejs +0 -39
  122. package/examples/events/assets/content/talks/neapolitan-pizza-tradition-meets-innovation.md.ejs +0 -39
  123. package/examples/events/assets/content/talks/savory-breads-of-the-mediterranean.md.ejs +0 -39
  124. package/examples/events/assets/content/talks/sourdough-from-starter-to-masterpiece.md.ejs +0 -36
  125. package/examples/events/assets/content/talks/the-art-of-the-perfect-tart.md.ejs +0 -32
  126. package/examples/events/assets/content/talks/the-science-of-sugar.md.ejs +0 -39
  127. package/examples/events/assets/content/talks/umami-in-pastry-east-meets-west.md.ejs +0 -39
  128. package/examples/events/assets/content-collections.ts +0 -56
  129. package/examples/events/assets/public/background-1.jpg +0 -0
  130. package/examples/events/assets/public/background-2.jpg +0 -0
  131. package/examples/events/assets/public/background-3.jpg +0 -0
  132. package/examples/events/assets/public/background-4.jpg +0 -0
  133. package/examples/events/assets/public/conference-logo.png +0 -0
  134. package/examples/events/assets/public/favicon.ico +0 -0
  135. package/examples/events/assets/public/speakers/andre-costa.jpg +0 -0
  136. package/examples/events/assets/public/speakers/hans-mueller.jpg +0 -0
  137. package/examples/events/assets/public/speakers/isabella-martinez.jpg +0 -0
  138. package/examples/events/assets/public/speakers/kenji-nakamura.jpg +0 -0
  139. package/examples/events/assets/public/speakers/marie-dubois.jpg +0 -0
  140. package/examples/events/assets/public/speakers/priya-sharma.jpg +0 -0
  141. package/examples/events/assets/public/talks/croissant-lamination-secrets.jpg +0 -0
  142. package/examples/events/assets/public/talks/french-macaron-mastery.jpg +0 -0
  143. package/examples/events/assets/public/talks/neapolitan-pizza-tradition-meets-innovation.jpg +0 -0
  144. package/examples/events/assets/public/talks/savory-breads-of-the-mediterranean.jpg +0 -0
  145. package/examples/events/assets/public/talks/sourdough-from-starter-to-masterpiece.jpg +0 -0
  146. package/examples/events/assets/public/talks/the-art-of-the-perfect-tart.jpg +0 -0
  147. package/examples/events/assets/public/talks/the-science-of-sugar.jpg +0 -0
  148. package/examples/events/assets/public/talks/umami-in-pastry-east-meets-west.jpg +0 -0
  149. package/examples/events/assets/public/tanstack-circle-logo.png +0 -0
  150. package/examples/events/assets/public/tanstack-word-logo-white.svg +0 -1
  151. package/examples/events/assets/src/components/Header.tsx +0 -59
  152. package/examples/events/assets/src/components/HeaderNav.tsx +0 -67
  153. package/examples/events/assets/src/components/HeroCarousel.tsx +0 -61
  154. package/examples/events/assets/src/components/RemyAssistant.tsx +0 -207
  155. package/examples/events/assets/src/components/SpeakerCard.tsx +0 -67
  156. package/examples/events/assets/src/components/TalkCard.tsx +0 -77
  157. package/examples/events/assets/src/components/ui/card.tsx +0 -92
  158. package/examples/events/assets/src/lib/conference-ai-hook.ts +0 -26
  159. package/examples/events/assets/src/lib/conference-tools.ts +0 -210
  160. package/examples/events/assets/src/lib/model-selection.ts +0 -1
  161. package/examples/events/assets/src/lib/utils.ts +0 -6
  162. package/examples/events/assets/src/routes/__root.tsx +0 -70
  163. package/examples/events/assets/src/routes/api.remy-chat.ts +0 -119
  164. package/examples/events/assets/src/routes/index.tsx +0 -192
  165. package/examples/events/assets/src/routes/schedule.index.tsx +0 -274
  166. package/examples/events/assets/src/routes/speakers.$slug.tsx +0 -122
  167. package/examples/events/assets/src/routes/speakers.index.tsx +0 -40
  168. package/examples/events/assets/src/routes/talks.$slug.tsx +0 -116
  169. package/examples/events/assets/src/routes/talks.index.tsx +0 -40
  170. package/examples/events/assets/src/styles.css +0 -182
  171. package/examples/events/info.json +0 -61
  172. package/examples/events/package.json +0 -23
  173. package/examples/marketing/README.md +0 -60
  174. package/examples/marketing/assets/AGENTS.md.append +0 -15
  175. package/examples/marketing/assets/public/logo.png +0 -0
  176. package/examples/marketing/assets/public/motorcycle-adventure.jpg +0 -0
  177. package/examples/marketing/assets/public/motorcycle-cruiser.jpg +0 -0
  178. package/examples/marketing/assets/public/motorcycle-scooter.jpg +0 -0
  179. package/examples/marketing/assets/public/motorcycle-sport.jpg +0 -0
  180. package/examples/marketing/assets/public/motorcycle-supersport.jpg +0 -0
  181. package/examples/marketing/assets/src/components/Header.tsx +0 -36
  182. package/examples/marketing/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
  183. package/examples/marketing/assets/src/components/MotorcycleRecommendation.tsx +0 -53
  184. package/examples/marketing/assets/src/data/motorcycles.ts.ejs +0 -77
  185. package/examples/marketing/assets/src/lib/motorcycle-ai-hook.ts +0 -24
  186. package/examples/marketing/assets/src/lib/motorcycle-tools.ts +0 -42
  187. package/examples/marketing/assets/src/routes/__root.tsx +0 -57
  188. package/examples/marketing/assets/src/routes/api.motorcycle-chat.ts +0 -78
  189. package/examples/marketing/assets/src/routes/index.tsx +0 -72
  190. package/examples/marketing/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -56
  191. package/examples/marketing/assets/src/store/motorcycle-assistant.ts +0 -3
  192. package/examples/marketing/assets/src/styles.css +0 -212
  193. package/examples/marketing/info.json +0 -33
  194. package/examples/marketing/package.json +0 -14
  195. package/examples/portfolio/README.md +0 -49
  196. package/examples/portfolio/assets/AGENTS.md.append +0 -21
  197. package/examples/portfolio/assets/content/blog/getting-started-with-tanstack.md +0 -53
  198. package/examples/portfolio/assets/content/blog/react-19-features.md +0 -78
  199. package/examples/portfolio/assets/content/blog/tailwind-css-v4-guide.md +0 -60
  200. package/examples/portfolio/assets/content/education/code-school.md +0 -17
  201. package/examples/portfolio/assets/content/jobs/initech-junior.md +0 -20
  202. package/examples/portfolio/assets/content/projects/portfolio-site.md +0 -15
  203. package/examples/portfolio/assets/content/projects/task-manager.md +0 -15
  204. package/examples/portfolio/assets/content-collections.ts +0 -65
  205. package/examples/portfolio/assets/public/contact.html +0 -6
  206. package/examples/portfolio/assets/public/headshot-on-white.jpg +0 -0
  207. package/examples/portfolio/assets/src/components/Header.tsx +0 -33
  208. package/examples/portfolio/assets/src/components/ResumeAssistant.tsx +0 -193
  209. package/examples/portfolio/assets/src/components/ui/badge.tsx +0 -46
  210. package/examples/portfolio/assets/src/components/ui/card.tsx +0 -92
  211. package/examples/portfolio/assets/src/components/ui/checkbox.tsx +0 -30
  212. package/examples/portfolio/assets/src/components/ui/hover-card.tsx +0 -44
  213. package/examples/portfolio/assets/src/components/ui/separator.tsx +0 -26
  214. package/examples/portfolio/assets/src/lib/resume-ai-hook.ts +0 -21
  215. package/examples/portfolio/assets/src/lib/resume-tools.ts +0 -165
  216. package/examples/portfolio/assets/src/lib/utils.ts +0 -6
  217. package/examples/portfolio/assets/src/routes/__root.tsx +0 -57
  218. package/examples/portfolio/assets/src/routes/api.resume-chat.ts +0 -116
  219. package/examples/portfolio/assets/src/routes/blog/$slug.tsx +0 -73
  220. package/examples/portfolio/assets/src/routes/contact.tsx +0 -121
  221. package/examples/portfolio/assets/src/routes/index.tsx +0 -55
  222. package/examples/portfolio/assets/src/routes/projects.tsx +0 -62
  223. package/examples/portfolio/assets/src/routes/resume.tsx +0 -220
  224. package/examples/portfolio/assets/src/styles.css +0 -138
  225. package/examples/portfolio/info.json +0 -50
  226. package/examples/portfolio/package.json +0 -26
  227. package/examples/resume/README.md +0 -82
  228. package/examples/resume/assets/AGENTS.md.append +0 -19
  229. package/examples/resume/assets/content/education/code-school.md +0 -17
  230. package/examples/resume/assets/content/jobs/freelance.md.ejs +0 -13
  231. package/examples/resume/assets/content/jobs/initech-junior.md +0 -20
  232. package/examples/resume/assets/content/jobs/initech-lead.md.ejs +0 -29
  233. package/examples/resume/assets/content/jobs/initrode-senior.md.ejs +0 -28
  234. package/examples/resume/assets/content-collections.ts +0 -36
  235. package/examples/resume/assets/public/headshot-on-white.jpg +0 -0
  236. package/examples/resume/assets/src/components/Header.tsx +0 -33
  237. package/examples/resume/assets/src/components/ResumeAssistant.tsx +0 -193
  238. package/examples/resume/assets/src/components/ui/badge.tsx +0 -46
  239. package/examples/resume/assets/src/components/ui/card.tsx +0 -92
  240. package/examples/resume/assets/src/components/ui/checkbox.tsx +0 -30
  241. package/examples/resume/assets/src/components/ui/hover-card.tsx +0 -44
  242. package/examples/resume/assets/src/components/ui/separator.tsx +0 -26
  243. package/examples/resume/assets/src/lib/resume-ai-hook.ts +0 -21
  244. package/examples/resume/assets/src/lib/resume-tools.ts +0 -165
  245. package/examples/resume/assets/src/lib/utils.ts +0 -6
  246. package/examples/resume/assets/src/routes/api.resume-chat.ts +0 -110
  247. package/examples/resume/assets/src/routes/index.tsx +0 -220
  248. package/examples/resume/assets/src/styles.css +0 -138
  249. package/examples/resume/info.json +0 -35
  250. package/examples/resume/package.json +0 -26
  251. package/examples/saas/README.md +0 -16
  252. package/examples/saas/assets/AGENTS.md.append +0 -9
  253. package/examples/saas/assets/src/components/Header.tsx +0 -17
  254. package/examples/saas/assets/src/routes/__root.tsx +0 -57
  255. package/examples/saas/assets/src/routes/faq.tsx +0 -94
  256. package/examples/saas/assets/src/routes/index.tsx +0 -197
  257. package/examples/saas/info.json +0 -23
  258. package/examples/saas/package.json +0 -1
  259. package/examples/survey/README.md +0 -20
  260. package/examples/survey/assets/AGENTS.md.append +0 -9
  261. package/examples/survey/assets/public/form-survey.html +0 -15
  262. package/examples/survey/assets/src/components/SurveyForm.tsx +0 -128
  263. package/examples/survey/assets/src/routes/index.tsx +0 -14
  264. package/examples/survey/info.json +0 -19
  265. package/examples/survey/package.json +0 -1
  266. package/project/base/AGENTS.md +0 -86
  267. package/project/base/_dot_claude/skills/content-collections/SKILL.md +0 -505
  268. package/project/base/_dot_claude/skills/netlify-blobs/SKILL.md +0 -410
  269. package/project/base/_dot_claude/skills/netlify-db/SKILL.md +0 -424
  270. package/project/base/_dot_claude/skills/netlify-debugging/SKILL.md +0 -419
  271. package/project/base/_dot_claude/skills/netlify-forms/SKILL.md +0 -243
  272. package/project/base/_dot_claude/skills/netlify-functions/SKILL.md +0 -372
  273. package/project/base/_dot_claude/skills/tanstack-start-api-routes/SKILL.md +0 -421
  274. package/project/base/_dot_claude/skills/tanstack-start-loaders/SKILL.md +0 -426
  275. package/project/base/_dot_claude/skills/tanstack-start-project-setup/SKILL.md +0 -493
  276. package/project/base/_dot_claude/skills/tanstack-start-routes/SKILL.md +0 -430
  277. package/project/base/_dot_claude/skills/tanstack-start-server-functions/SKILL.md +0 -445
  278. package/project/base/_dot_claude/skills/tanstack-start-typesafe-routing/SKILL.md +0 -494
  279. package/project/base/_dot_gitignore +0 -8
  280. package/project/base/netlify.toml +0 -7
  281. package/project/base/package.json +0 -33
  282. package/project/base/public/favicon.ico +0 -0
  283. package/project/base/public/tanstack-circle-logo.png +0 -0
  284. package/project/base/public/tanstack-word-logo-white.svg +0 -1
  285. package/project/base/src/components/Header.tsx +0 -17
  286. package/project/base/src/components/HeaderNav.tsx.ejs +0 -179
  287. package/project/base/src/router.tsx +0 -15
  288. package/project/base/src/routes/__root.tsx +0 -57
  289. package/project/base/src/routes/index.tsx +0 -48
  290. package/project/base/src/styles.css +0 -15
  291. package/project/base/tsconfig.json +0 -28
  292. package/project/base/vite.config.ts.ejs +0 -25
  293. package/project/info.json +0 -17
  294. package/project/packages.json +0 -22
  295. package/scripts/check-outdated-packages.js +0 -421
  296. package/src/agents-md.ts +0 -139
@@ -1,238 +0,0 @@
1
- import { useReducer } from 'react'
2
-
3
- interface State {
4
- display: string
5
- previousValue: string | null
6
- operation: string | null
7
- overwrite: boolean
8
- }
9
-
10
- type Action =
11
- | { type: 'ADD_DIGIT'; digit: string }
12
- | { type: 'CHOOSE_OPERATION'; operation: string }
13
- | { type: 'EVALUATE' }
14
- | { type: 'CLEAR' }
15
- | { type: 'DELETE_DIGIT' }
16
- | { type: 'PERCENT' }
17
- | { type: 'TOGGLE_SIGN' }
18
-
19
- function evaluate(previousValue: string, currentValue: string, operation: string): string {
20
- const prev = parseFloat(previousValue)
21
- const current = parseFloat(currentValue)
22
- if (isNaN(prev) || isNaN(current)) return 'Error'
23
-
24
- let result: number
25
- switch (operation) {
26
- case '+':
27
- result = prev + current
28
- break
29
- case '-':
30
- result = prev - current
31
- break
32
- case '*':
33
- result = prev * current
34
- break
35
- case '/':
36
- if (current === 0) return 'Error'
37
- result = prev / current
38
- break
39
- default:
40
- return currentValue
41
- }
42
- return String(result)
43
- }
44
-
45
- function reducer(state: State, action: Action): State {
46
- switch (action.type) {
47
- case 'ADD_DIGIT': {
48
- if (state.display === 'Error') {
49
- return { ...state, display: action.digit, overwrite: false }
50
- }
51
- if (state.overwrite) {
52
- return { ...state, display: action.digit, overwrite: false }
53
- }
54
- if (action.digit === '.' && state.display.includes('.')) return state
55
- if (state.display === '0' && action.digit !== '.') {
56
- return { ...state, display: action.digit }
57
- }
58
- return { ...state, display: state.display + action.digit }
59
- }
60
- case 'CHOOSE_OPERATION': {
61
- if (state.display === 'Error') return state
62
- if (state.previousValue != null && !state.overwrite) {
63
- const result = evaluate(state.previousValue, state.display, state.operation!)
64
- return {
65
- display: result,
66
- previousValue: result,
67
- operation: action.operation,
68
- overwrite: true,
69
- }
70
- }
71
- return {
72
- ...state,
73
- previousValue: state.display,
74
- operation: action.operation,
75
- overwrite: true,
76
- }
77
- }
78
- case 'EVALUATE': {
79
- if (state.previousValue == null || state.operation == null || state.overwrite) return state
80
- const result = evaluate(state.previousValue, state.display, state.operation)
81
- return {
82
- display: result,
83
- previousValue: null,
84
- operation: null,
85
- overwrite: true,
86
- }
87
- }
88
- case 'CLEAR':
89
- return { display: '0', previousValue: null, operation: null, overwrite: false }
90
- case 'DELETE_DIGIT': {
91
- if (state.display === 'Error') {
92
- return { display: '0', previousValue: null, operation: null, overwrite: false }
93
- }
94
- if (state.overwrite) return { ...state, display: '0', overwrite: false }
95
- if (state.display.length === 1) return { ...state, display: '0' }
96
- return { ...state, display: state.display.slice(0, -1) }
97
- }
98
- case 'PERCENT': {
99
- if (state.display === 'Error') return state
100
- const val = parseFloat(state.display)
101
- if (isNaN(val)) return state
102
- return { ...state, display: String(val / 100), overwrite: true }
103
- }
104
- case 'TOGGLE_SIGN': {
105
- if (state.display === 'Error' || state.display === '0') return state
106
- return {
107
- ...state,
108
- display: state.display.startsWith('-') ? state.display.slice(1) : '-' + state.display,
109
- }
110
- }
111
- default:
112
- return state
113
- }
114
- }
115
-
116
- const initialState: State = {
117
- display: '0',
118
- previousValue: null,
119
- operation: null,
120
- overwrite: false,
121
- }
122
-
123
- export default function Calculator() {
124
- const [state, dispatch] = useReducer(reducer, initialState)
125
-
126
- const addDigit = (digit: string) => dispatch({ type: 'ADD_DIGIT', digit })
127
- const chooseOperation = (operation: string) => dispatch({ type: 'CHOOSE_OPERATION', operation })
128
-
129
- const formatDisplay = (value: string) => {
130
- if (value === 'Error') return value
131
- if (value.includes('.') && value.endsWith('.')) return value
132
- const num = parseFloat(value)
133
- if (isNaN(num)) return value
134
- if (value.includes('.')) {
135
- const [int, dec] = value.split('.')
136
- return parseFloat(int).toLocaleString('en-US') + '.' + dec
137
- }
138
- return num.toLocaleString('en-US', { maximumFractionDigits: 10 })
139
- }
140
-
141
- const isActive = (op: string) => state.operation === op && state.overwrite
142
-
143
- return (
144
- <div className="w-full max-w-sm mx-auto bg-gray-900 rounded-2xl shadow-2xl overflow-hidden">
145
- {/* Display */}
146
- <div className="p-6 pb-4">
147
- <div className="text-right min-h-[24px] text-gray-400 text-sm mb-1">
148
- {state.previousValue != null && state.operation
149
- ? `${formatDisplay(state.previousValue)} ${state.operation}`
150
- : '\u00A0'}
151
- </div>
152
- <div className="text-right text-white text-5xl font-light tracking-tight overflow-hidden">
153
- {formatDisplay(state.display)}
154
- </div>
155
- </div>
156
-
157
- {/* Buttons */}
158
- <div className="grid grid-cols-4 gap-[1px] p-2 pt-0">
159
- {/* Row 1: C, +/-, %, / */}
160
- <button
161
- onClick={() => dispatch({ type: 'CLEAR' })}
162
- className="h-16 rounded-xl text-lg font-medium bg-gray-500 hover:bg-gray-400 text-white transition-colors"
163
- >
164
- C
165
- </button>
166
- <button
167
- onClick={() => dispatch({ type: 'TOGGLE_SIGN' })}
168
- className="h-16 rounded-xl text-lg font-medium bg-gray-500 hover:bg-gray-400 text-white transition-colors"
169
- >
170
- +/-
171
- </button>
172
- <button
173
- onClick={() => dispatch({ type: 'PERCENT' })}
174
- className="h-16 rounded-xl text-lg font-medium bg-gray-500 hover:bg-gray-400 text-white transition-colors"
175
- >
176
- %
177
- </button>
178
- <button
179
- onClick={() => chooseOperation('/')}
180
- className={`h-16 rounded-xl text-lg font-medium transition-colors ${
181
- isActive('/') ? 'bg-white text-orange-500 ring-2 ring-orange-400' : 'bg-orange-500 hover:bg-orange-400 text-white'
182
- }`}
183
- >
184
- ÷
185
- </button>
186
-
187
- {/* Row 2: 7, 8, 9, * */}
188
- <button onClick={() => addDigit('7')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">7</button>
189
- <button onClick={() => addDigit('8')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">8</button>
190
- <button onClick={() => addDigit('9')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">9</button>
191
- <button
192
- onClick={() => chooseOperation('*')}
193
- className={`h-16 rounded-xl text-lg font-medium transition-colors ${
194
- isActive('*') ? 'bg-white text-orange-500 ring-2 ring-orange-400' : 'bg-orange-500 hover:bg-orange-400 text-white'
195
- }`}
196
- >
197
- ×
198
- </button>
199
-
200
- {/* Row 3: 4, 5, 6, - */}
201
- <button onClick={() => addDigit('4')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">4</button>
202
- <button onClick={() => addDigit('5')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">5</button>
203
- <button onClick={() => addDigit('6')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">6</button>
204
- <button
205
- onClick={() => chooseOperation('-')}
206
- className={`h-16 rounded-xl text-lg font-medium transition-colors ${
207
- isActive('-') ? 'bg-white text-orange-500 ring-2 ring-orange-400' : 'bg-orange-500 hover:bg-orange-400 text-white'
208
- }`}
209
- >
210
-
211
- </button>
212
-
213
- {/* Row 4: 1, 2, 3, + */}
214
- <button onClick={() => addDigit('1')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">1</button>
215
- <button onClick={() => addDigit('2')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">2</button>
216
- <button onClick={() => addDigit('3')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">3</button>
217
- <button
218
- onClick={() => chooseOperation('+')}
219
- className={`h-16 rounded-xl text-lg font-medium transition-colors ${
220
- isActive('+') ? 'bg-white text-orange-500 ring-2 ring-orange-400' : 'bg-orange-500 hover:bg-orange-400 text-white'
221
- }`}
222
- >
223
- +
224
- </button>
225
-
226
- {/* Row 5: 0 (span 2), ., = */}
227
- <button onClick={() => addDigit('0')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors col-span-2">0</button>
228
- <button onClick={() => addDigit('.')} className="h-16 rounded-xl text-lg font-medium bg-gray-700 hover:bg-gray-600 text-white transition-colors">.</button>
229
- <button
230
- onClick={() => dispatch({ type: 'EVALUATE' })}
231
- className="h-16 rounded-xl text-lg font-medium bg-orange-500 hover:bg-orange-400 text-white transition-colors"
232
- >
233
- =
234
- </button>
235
- </div>
236
- </div>
237
- )
238
- }
@@ -1,17 +0,0 @@
1
- import { Link } from '@tanstack/react-router'
2
- import HeaderNav from './HeaderNav'
3
-
4
- interface HeaderProps {
5
- children?: React.ReactNode
6
- }
7
-
8
- export default function Header({ children }: HeaderProps) {
9
- return (
10
- <header className="p-4 flex items-center justify-between bg-gray-800 text-white shadow-lg">
11
- <nav className="flex items-center gap-4">{children ?? <HeaderNav />}</nav>
12
- <Link to="/" className="text-xl font-semibold">
13
- Calculator
14
- </Link>
15
- </header>
16
- )
17
- }
@@ -1,57 +0,0 @@
1
- import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
2
- import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
3
- import { TanStackDevtools } from '@tanstack/react-devtools'
4
-
5
- import Header from '../components/Header'
6
-
7
- import appCss from '../styles.css?url'
8
-
9
- export const Route = createRootRoute({
10
- head: () => ({
11
- meta: [
12
- {
13
- charSet: 'utf-8',
14
- },
15
- {
16
- name: 'viewport',
17
- content: 'width=device-width, initial-scale=1',
18
- },
19
- {
20
- title: 'Calculator',
21
- },
22
- ],
23
- links: [
24
- {
25
- rel: 'stylesheet',
26
- href: appCss,
27
- },
28
- ],
29
- }),
30
- shellComponent: RootDocument,
31
- })
32
-
33
- function RootDocument({ children }: { children: React.ReactNode }) {
34
- return (
35
- <html lang="en">
36
- <head>
37
- <HeadContent />
38
- </head>
39
- <body>
40
- <Header />
41
- {children}
42
- <TanStackDevtools
43
- config={{
44
- position: 'bottom-right',
45
- }}
46
- plugins={[
47
- {
48
- name: 'Tanstack Router',
49
- render: <TanStackRouterDevtoolsPanel />,
50
- },
51
- ]}
52
- />
53
- <Scripts />
54
- </body>
55
- </html>
56
- )
57
- }
@@ -1,14 +0,0 @@
1
- import { createFileRoute } from '@tanstack/react-router'
2
- import Calculator from '../components/Calculator'
3
-
4
- export const Route = createFileRoute('/')({
5
- component: Home,
6
- })
7
-
8
- function Home() {
9
- return (
10
- <div className="min-h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 flex items-center justify-center p-4">
11
- <Calculator />
12
- </div>
13
- )
14
- }
@@ -1,20 +0,0 @@
1
- {
2
- "name": "Calculator",
3
- "description": "A sleek iOS-style calculator built with TanStack Start and Tailwind CSS for Netlify.",
4
- "phase": "example",
5
- "modes": ["file-router"],
6
- "type": "example",
7
- "priority": 10,
8
- "link": "",
9
- "routes": [{"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"}],
10
- "features": ["tanstack-start"],
11
- "integrations": [],
12
- "dependsOn": [],
13
- "variables": [],
14
- "packageFileDescriptions": {
15
- "src/routes/index.tsx": "Home route: renders Calculator component.",
16
- "src/routes/__root.tsx": "Root layout: HTML shell, styles.",
17
- "src/components/Calculator.tsx": "iOS-style calculator: digits, operations, evaluate, clear, percent.",
18
- "src/components/Header.tsx": "Header component."
19
- }
20
- }
@@ -1 +0,0 @@
1
- {}
@@ -1,17 +0,0 @@
1
- # Dashboard Example
2
-
3
- An analytics dashboard built with TanStack Start, Chart.js, and Tailwind CSS for Netlify deployment.
4
-
5
- ## Features
6
-
7
- - **Stat Cards**: Revenue, users, orders, and conversion rate with change indicators
8
- - **Bar Chart**: Monthly revenue visualization
9
- - **Line Chart**: User growth over time with area fill
10
- - **Doughnut Chart**: Sales breakdown by category
11
- - **Responsive Layout**: Adapts to all screen sizes
12
-
13
- ## Development
14
-
15
- ```bash
16
- npm run dev
17
- ```
@@ -1,12 +0,0 @@
1
- ### Chart.js Dashboard
2
-
3
- Analytics dashboard with Chart.js and react-chartjs-2.
4
-
5
- **Dependencies:** chart.js, react-chartjs-2
6
-
7
- **Chart types:**
8
- - Bar - Revenue by month
9
- - Line - User growth
10
- - Doughnut - Sales by category
11
-
12
- **Setup:** Register Chart.js components before use (CategoryScale, LinearScale, BarElement, LineElement, PointElement, ArcElement, Title, Tooltip, Legend, Filler).
@@ -1,17 +0,0 @@
1
- import { Link } from '@tanstack/react-router'
2
- import HeaderNav from './HeaderNav'
3
-
4
- interface HeaderProps {
5
- children?: React.ReactNode
6
- }
7
-
8
- export default function Header({ children }: HeaderProps) {
9
- return (
10
- <header className="p-4 flex items-center justify-between bg-gray-800 text-white shadow-lg">
11
- <nav className="flex items-center gap-4">{children ?? <HeaderNav />}</nav>
12
- <Link to="/" className="text-xl font-semibold">
13
- Dashboard
14
- </Link>
15
- </header>
16
- )
17
- }
@@ -1,57 +0,0 @@
1
- import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
2
- import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
3
- import { TanStackDevtools } from '@tanstack/react-devtools'
4
-
5
- import Header from '../components/Header'
6
-
7
- import appCss from '../styles.css?url'
8
-
9
- export const Route = createRootRoute({
10
- head: () => ({
11
- meta: [
12
- {
13
- charSet: 'utf-8',
14
- },
15
- {
16
- name: 'viewport',
17
- content: 'width=device-width, initial-scale=1',
18
- },
19
- {
20
- title: 'Dashboard',
21
- },
22
- ],
23
- links: [
24
- {
25
- rel: 'stylesheet',
26
- href: appCss,
27
- },
28
- ],
29
- }),
30
- shellComponent: RootDocument,
31
- })
32
-
33
- function RootDocument({ children }: { children: React.ReactNode }) {
34
- return (
35
- <html lang="en">
36
- <head>
37
- <HeadContent />
38
- </head>
39
- <body>
40
- <Header />
41
- {children}
42
- <TanStackDevtools
43
- config={{
44
- position: 'bottom-right',
45
- }}
46
- plugins={[
47
- {
48
- name: 'Tanstack Router',
49
- render: <TanStackRouterDevtoolsPanel />,
50
- },
51
- ]}
52
- />
53
- <Scripts />
54
- </body>
55
- </html>
56
- )
57
- }
@@ -1,158 +0,0 @@
1
- import { createFileRoute } from '@tanstack/react-router'
2
- import { useState, useEffect } from 'react'
3
- import {
4
- Chart as ChartJS,
5
- CategoryScale,
6
- LinearScale,
7
- BarElement,
8
- LineElement,
9
- PointElement,
10
- ArcElement,
11
- Title,
12
- Tooltip,
13
- Legend,
14
- Filler,
15
- } from 'chart.js'
16
- import { Bar, Line, Doughnut } from 'react-chartjs-2'
17
- import { DollarSign, Users, ShoppingCart, TrendingUp } from 'lucide-react'
18
-
19
- ChartJS.register(
20
- CategoryScale,
21
- LinearScale,
22
- BarElement,
23
- LineElement,
24
- PointElement,
25
- ArcElement,
26
- Title,
27
- Tooltip,
28
- Legend,
29
- Filler
30
- )
31
-
32
- export const Route = createFileRoute('/')({
33
- component: Home,
34
- })
35
-
36
- const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
37
-
38
- const revenueData = {
39
- labels: months,
40
- datasets: [
41
- {
42
- label: 'Revenue ($)',
43
- data: [12000, 19000, 15000, 22000, 18000, 24000, 20000, 27000, 23000, 29000, 25000, 32000],
44
- backgroundColor: 'rgba(59, 130, 246, 0.7)',
45
- borderRadius: 6,
46
- },
47
- ],
48
- }
49
-
50
- const userGrowthData = {
51
- labels: months,
52
- datasets: [
53
- {
54
- label: 'Users',
55
- data: [1200, 1900, 2400, 2800, 3200, 3900, 4100, 4800, 5200, 5900, 6400, 7200],
56
- borderColor: 'rgb(16, 185, 129)',
57
- backgroundColor: 'rgba(16, 185, 129, 0.1)',
58
- fill: true,
59
- tension: 0.4,
60
- pointBackgroundColor: 'rgb(16, 185, 129)',
61
- },
62
- ],
63
- }
64
-
65
- const salesCategoryData = {
66
- labels: ['Electronics', 'Clothing', 'Home & Garden', 'Books', 'Sports'],
67
- datasets: [
68
- {
69
- data: [35, 25, 20, 12, 8],
70
- backgroundColor: [
71
- 'rgba(59, 130, 246, 0.8)',
72
- 'rgba(16, 185, 129, 0.8)',
73
- 'rgba(245, 158, 11, 0.8)',
74
- 'rgba(239, 68, 68, 0.8)',
75
- 'rgba(139, 92, 246, 0.8)',
76
- ],
77
- borderWidth: 0,
78
- },
79
- ],
80
- }
81
-
82
- const stats = [
83
- { title: 'Total Revenue', value: '$266,000', change: '+12.5%', icon: DollarSign, color: 'bg-blue-500' },
84
- { title: 'Total Users', value: '7,200', change: '+8.2%', icon: Users, color: 'bg-emerald-500' },
85
- { title: 'Orders', value: '1,840', change: '+5.1%', icon: ShoppingCart, color: 'bg-amber-500' },
86
- { title: 'Conversion Rate', value: '3.24%', change: '+1.8%', icon: TrendingUp, color: 'bg-violet-500' },
87
- ]
88
-
89
- function Home() {
90
- const [mounted, setMounted] = useState(false)
91
- useEffect(() => setMounted(true), [])
92
-
93
- return (
94
- <div className="min-h-screen bg-gray-50">
95
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
96
- <h1 className="text-3xl font-bold text-gray-900 mb-8">Analytics Dashboard</h1>
97
-
98
- {/* Stat Cards */}
99
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
100
- {stats.map((stat) => (
101
- <div key={stat.title} className="bg-white rounded-xl shadow-sm p-6 flex items-center gap-4">
102
- <div className={`${stat.color} p-3 rounded-lg`}>
103
- <stat.icon className="w-6 h-6 text-white" />
104
- </div>
105
- <div>
106
- <p className="text-sm text-gray-500">{stat.title}</p>
107
- <p className="text-2xl font-bold text-gray-900">{stat.value}</p>
108
- <p className="text-sm text-emerald-600 font-medium">{stat.change}</p>
109
- </div>
110
- </div>
111
- ))}
112
- </div>
113
-
114
- {/* Charts */}
115
- {mounted && (
116
- <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
117
- <div className="bg-white rounded-xl shadow-sm p-6">
118
- <h2 className="text-lg font-semibold text-gray-900 mb-4">Monthly Revenue</h2>
119
- <Bar
120
- data={revenueData}
121
- options={{
122
- responsive: true,
123
- plugins: { legend: { display: false } },
124
- scales: { y: { beginAtZero: true } },
125
- }}
126
- />
127
- </div>
128
-
129
- <div className="bg-white rounded-xl shadow-sm p-6">
130
- <h2 className="text-lg font-semibold text-gray-900 mb-4">User Growth</h2>
131
- <Line
132
- data={userGrowthData}
133
- options={{
134
- responsive: true,
135
- plugins: { legend: { display: false } },
136
- scales: { y: { beginAtZero: true } },
137
- }}
138
- />
139
- </div>
140
-
141
- <div className="bg-white rounded-xl shadow-sm p-6">
142
- <h2 className="text-lg font-semibold text-gray-900 mb-4">Sales by Category</h2>
143
- <div className="max-w-sm mx-auto">
144
- <Doughnut
145
- data={salesCategoryData}
146
- options={{
147
- responsive: true,
148
- plugins: { legend: { position: 'bottom' } },
149
- }}
150
- />
151
- </div>
152
- </div>
153
- </div>
154
- )}
155
- </div>
156
- </div>
157
- )
158
- }
@@ -1,19 +0,0 @@
1
- {
2
- "name": "Dashboard",
3
- "description": "An analytics dashboard with charts built with Chart.js, TanStack Start, and Tailwind CSS for Netlify.",
4
- "phase": "example",
5
- "modes": ["file-router"],
6
- "type": "example",
7
- "priority": 10,
8
- "link": "",
9
- "routes": [{"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"}],
10
- "features": ["tanstack-start", "chart.js"],
11
- "integrations": [],
12
- "dependsOn": [],
13
- "variables": [],
14
- "packageFileDescriptions": {
15
- "src/routes/index.tsx": "Dashboard home: Bar, Line, Doughnut charts (revenue, users, sales).",
16
- "src/routes/__root.tsx": "Root layout: Header, styles.",
17
- "src/components/Header.tsx": "Header component."
18
- }
19
- }
@@ -1,6 +0,0 @@
1
- {
2
- "dependencies": {
3
- "chart.js": "^4.5.1",
4
- "react-chartjs-2": "^5.3.1"
5
- }
6
- }