create-inox-app 0.1.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 (510) hide show
  1. package/README.md +110 -0
  2. package/dist/cli.js +22196 -0
  3. package/dist/prompt-Bp8saGVV.js +852 -0
  4. package/dist/templates/base/.gitignore.hbs +9 -0
  5. package/dist/templates/base/package.json.hbs +29 -0
  6. package/dist/templates/base/packages/typescript-config/base.json +17 -0
  7. package/dist/templates/base/packages/typescript-config/nextjs.json +8 -0
  8. package/dist/templates/base/packages/typescript-config/package.json +10 -0
  9. package/dist/templates/base/packages/typescript-config/react-library.json +7 -0
  10. package/dist/templates/base/turbo.json.hbs +32 -0
  11. package/dist/templates/ci/.gitlab-ci.yml.hbs +70 -0
  12. package/dist/templates/ci/scripts/build.sh.hbs +94 -0
  13. package/dist/templates/ci/scripts/prebuild.sh.hbs +11 -0
  14. package/dist/templates/claude-config/app/.agents/skills/agent-browser/SKILL.md +325 -0
  15. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/authentication.md +202 -0
  16. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/commands.md +259 -0
  17. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/proxy-support.md +188 -0
  18. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/session-management.md +193 -0
  19. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/snapshot-refs.md +194 -0
  20. package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/video-recording.md +173 -0
  21. package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/authenticated-session.sh +100 -0
  22. package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/capture-workflow.sh +69 -0
  23. package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/form-automation.sh +62 -0
  24. package/dist/templates/claude-config/app/.agents/skills/ai-elements/SKILL.md +150 -0
  25. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/agent.md +131 -0
  26. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/artifact.md +84 -0
  27. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/attachments.md +190 -0
  28. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/audio-player.md +134 -0
  29. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/canvas.md +32 -0
  30. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/chain-of-thought.md +81 -0
  31. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/checkpoint.md +163 -0
  32. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/code-block.md +170 -0
  33. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/commit.md +177 -0
  34. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/confirmation.md +252 -0
  35. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/connection.md +32 -0
  36. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/context.md +126 -0
  37. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/controls.md +30 -0
  38. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/conversation.md +210 -0
  39. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/edge.md +50 -0
  40. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/environment-variables.md +102 -0
  41. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/file-tree.md +72 -0
  42. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/image.md +143 -0
  43. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/inline-citation.md +293 -0
  44. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/jsx-preview.md +101 -0
  45. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/message.md +256 -0
  46. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/mic-selector.md +186 -0
  47. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/model-selector.md +112 -0
  48. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/node.md +71 -0
  49. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/open-in-chat.md +67 -0
  50. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/package-info.md +95 -0
  51. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/panel.md +31 -0
  52. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/persona.md +158 -0
  53. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/plan.md +79 -0
  54. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/prompt-input.md +555 -0
  55. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/queue.md +172 -0
  56. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/reasoning.md +219 -0
  57. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/sandbox.md +126 -0
  58. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/schema-display.md +102 -0
  59. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/shimmer.md +48 -0
  60. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/snippet.md +64 -0
  61. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/sources.md +193 -0
  62. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/speech-input.md +160 -0
  63. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/stack-trace.md +218 -0
  64. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/suggestion.md +121 -0
  65. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/task.md +215 -0
  66. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/terminal.md +103 -0
  67. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/test-results.md +157 -0
  68. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/tool.md +275 -0
  69. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/toolbar.md +30 -0
  70. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/transcription.md +120 -0
  71. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/voice-selector.md +241 -0
  72. package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/web-preview.md +197 -0
  73. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/agent.tsx +61 -0
  74. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/artifact.tsx +111 -0
  75. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments-inline.tsx +117 -0
  76. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments-list.tsx +88 -0
  77. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments.tsx +78 -0
  78. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/audio-player-remote.tsx +35 -0
  79. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/audio-player.tsx +69 -0
  80. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/chain-of-thought.tsx +74 -0
  81. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/checkpoint.tsx +90 -0
  82. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/code-block-dark.tsx +46 -0
  83. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/code-block.tsx +115 -0
  84. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/commit.tsx +94 -0
  85. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-accepted.tsx +35 -0
  86. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-rejected.tsx +35 -0
  87. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-request.tsx +54 -0
  88. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation.tsx +53 -0
  89. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/context.tsx +45 -0
  90. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/conversation.tsx +176 -0
  91. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/environment-variables.tsx +55 -0
  92. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-basic.tsx +14 -0
  93. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-expanded.tsx +17 -0
  94. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-selection.tsx +20 -0
  95. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree.tsx +38 -0
  96. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/image.tsx +20 -0
  97. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/inline-citation.tsx +95 -0
  98. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/jsx-preview.tsx +99 -0
  99. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/message.tsx +324 -0
  100. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/mic-selector.tsx +46 -0
  101. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/model-selector.tsx +362 -0
  102. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/open-in-chat.tsx +33 -0
  103. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/package-info.tsx +46 -0
  104. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-command.tsx +96 -0
  105. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-glint.tsx +96 -0
  106. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-halo.tsx +96 -0
  107. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-mana.tsx +96 -0
  108. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-obsidian.tsx +96 -0
  109. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-opal.tsx +96 -0
  110. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/plan.tsx +63 -0
  111. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input-cursor.tsx +459 -0
  112. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input-tooltip.tsx +40 -0
  113. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input.tsx +247 -0
  114. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/queue-prompt-input.tsx +367 -0
  115. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/queue.tsx +276 -0
  116. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/reasoning.tsx +67 -0
  117. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sandbox.tsx +166 -0
  118. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-basic.tsx +7 -0
  119. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-body.tsx +20 -0
  120. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-nested.tsx +23 -0
  121. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-params.tsx +16 -0
  122. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display.tsx +110 -0
  123. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer-duration.tsx +29 -0
  124. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer-elements.tsx +39 -0
  125. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer.tsx +17 -0
  126. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/snippet-plain.tsx +19 -0
  127. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/snippet.tsx +25 -0
  128. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sources-custom.tsx +34 -0
  129. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sources.tsx +27 -0
  130. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/speech-input.tsx +79 -0
  131. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace-collapsed.tsx +39 -0
  132. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace-no-internal.tsx +41 -0
  133. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace.tsx +54 -0
  134. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/suggestion-input.tsx +137 -0
  135. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/suggestion.tsx +28 -0
  136. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/task.tsx +60 -0
  137. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-basic.tsx +7 -0
  138. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-clear.tsx +19 -0
  139. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-streaming.tsx +38 -0
  140. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal.tsx +77 -0
  141. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-basic.tsx +27 -0
  142. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-errors.tsx +51 -0
  143. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-suites.tsx +40 -0
  144. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results.tsx +78 -0
  145. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-input-available.tsx +31 -0
  146. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-input-streaming.tsx +30 -0
  147. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-output-available.tsx +76 -0
  148. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-output-error.tsx +45 -0
  149. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool.tsx +205 -0
  150. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/transcription.tsx +284 -0
  151. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/voice-selector.tsx +228 -0
  152. package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/web-preview.tsx +99 -0
  153. package/dist/templates/claude-config/app/.agents/skills/ai-sdk/SKILL.md +78 -0
  154. package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/ai-gateway.md +66 -0
  155. package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/common-errors.md +439 -0
  156. package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/devtools.md +52 -0
  157. package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/type-safe-agents.md +200 -0
  158. package/dist/templates/claude-config/app/.agents/skills/better-auth-best-practices/SKILL.md +166 -0
  159. package/dist/templates/claude-config/app/.agents/skills/building-components/SKILL.md +37 -0
  160. package/dist/templates/claude-config/app/.agents/skills/building-components/references/accessibility.mdx +819 -0
  161. package/dist/templates/claude-config/app/.agents/skills/building-components/references/as-child.mdx +324 -0
  162. package/dist/templates/claude-config/app/.agents/skills/building-components/references/composition.mdx +239 -0
  163. package/dist/templates/claude-config/app/.agents/skills/building-components/references/data-attributes.mdx +413 -0
  164. package/dist/templates/claude-config/app/.agents/skills/building-components/references/definitions.mdx +258 -0
  165. package/dist/templates/claude-config/app/.agents/skills/building-components/references/design-tokens.mdx +57 -0
  166. package/dist/templates/claude-config/app/.agents/skills/building-components/references/docs.mdx +155 -0
  167. package/dist/templates/claude-config/app/.agents/skills/building-components/references/marketplaces.mdx +144 -0
  168. package/dist/templates/claude-config/app/.agents/skills/building-components/references/npm.mdx +166 -0
  169. package/dist/templates/claude-config/app/.agents/skills/building-components/references/polymorphism.mdx +583 -0
  170. package/dist/templates/claude-config/app/.agents/skills/building-components/references/principles.mdx +61 -0
  171. package/dist/templates/claude-config/app/.agents/skills/building-components/references/registry.mdx +169 -0
  172. package/dist/templates/claude-config/app/.agents/skills/building-components/references/state.mdx +99 -0
  173. package/dist/templates/claude-config/app/.agents/skills/building-components/references/styling.mdx +286 -0
  174. package/dist/templates/claude-config/app/.agents/skills/building-components/references/types.mdx +191 -0
  175. package/dist/templates/claude-config/app/.agents/skills/docker-expert/SKILL.md +409 -0
  176. package/dist/templates/claude-config/app/.agents/skills/email-and-password-best-practices/SKILL.md +224 -0
  177. package/dist/templates/claude-config/app/.agents/skills/find-skills/SKILL.md +133 -0
  178. package/dist/templates/claude-config/app/.agents/skills/frontend-design/LICENSE.txt +177 -0
  179. package/dist/templates/claude-config/app/.agents/skills/frontend-design/SKILL.md +42 -0
  180. package/dist/templates/claude-config/app/.agents/skills/git-commit/SKILL.md +124 -0
  181. package/dist/templates/claude-config/app/.agents/skills/gitlab-ci-patterns/SKILL.md +271 -0
  182. package/dist/templates/claude-config/app/.agents/skills/hono/SKILL.md +90 -0
  183. package/dist/templates/claude-config/app/.agents/skills/langfuse-observability/SKILL.md +139 -0
  184. package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/SKILL.md +127 -0
  185. package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/context.md +157 -0
  186. package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/pitfalls.md +118 -0
  187. package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/structure.md +193 -0
  188. package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/wide-events.md +113 -0
  189. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/SKILL.md +153 -0
  190. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/async-patterns.md +87 -0
  191. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/bundling.md +180 -0
  192. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/data-patterns.md +297 -0
  193. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/debug-tricks.md +105 -0
  194. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/directives.md +73 -0
  195. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/error-handling.md +227 -0
  196. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/file-conventions.md +140 -0
  197. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/font.md +245 -0
  198. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/functions.md +108 -0
  199. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/hydration-error.md +91 -0
  200. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/image.md +173 -0
  201. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/metadata.md +301 -0
  202. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/parallel-routes.md +287 -0
  203. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/route-handlers.md +146 -0
  204. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/rsc-boundaries.md +159 -0
  205. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/runtime-selection.md +39 -0
  206. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/scripts.md +141 -0
  207. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/self-hosting.md +371 -0
  208. package/dist/templates/claude-config/app/.agents/skills/next-best-practices/suspense-boundaries.md +67 -0
  209. package/dist/templates/claude-config/app/.agents/skills/next-cache-components/SKILL.md +411 -0
  210. package/dist/templates/claude-config/app/.agents/skills/next-upgrade/SKILL.md +50 -0
  211. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/SKILL.md +179 -0
  212. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/CHEATSHEET.md +418 -0
  213. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/MIGRATIONS.md +536 -0
  214. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/PERFORMANCE.md +559 -0
  215. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/POSTGRES.md +588 -0
  216. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/QUERIES.md +764 -0
  217. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/RELATIONS.md +624 -0
  218. package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/SCHEMA.md +554 -0
  219. package/dist/templates/claude-config/app/.agents/skills/skill-creator/LICENSE.txt +202 -0
  220. package/dist/templates/claude-config/app/.agents/skills/skill-creator/SKILL.md +356 -0
  221. package/dist/templates/claude-config/app/.agents/skills/skill-creator/references/output-patterns.md +82 -0
  222. package/dist/templates/claude-config/app/.agents/skills/skill-creator/references/workflows.md +28 -0
  223. package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/init_skill.py +303 -0
  224. package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/package_skill.py +113 -0
  225. package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/quick_validate.py +95 -0
  226. package/dist/templates/claude-config/app/.agents/skills/streamdown/SKILL.md +164 -0
  227. package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/basic-streaming.tsx +34 -0
  228. package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/custom-security.tsx +38 -0
  229. package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/full-featured.tsx +60 -0
  230. package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/static-mode.tsx +17 -0
  231. package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/with-caret.tsx +39 -0
  232. package/dist/templates/claude-config/app/.agents/skills/streamdown/references/api.md +278 -0
  233. package/dist/templates/claude-config/app/.agents/skills/streamdown/references/features.md +201 -0
  234. package/dist/templates/claude-config/app/.agents/skills/streamdown/references/plugins.md +239 -0
  235. package/dist/templates/claude-config/app/.agents/skills/streamdown/references/security.md +192 -0
  236. package/dist/templates/claude-config/app/.agents/skills/streamdown/references/styling.md +166 -0
  237. package/dist/templates/claude-config/app/.agents/skills/tdd/SKILL.md +107 -0
  238. package/dist/templates/claude-config/app/.agents/skills/tdd/deep-modules.md +33 -0
  239. package/dist/templates/claude-config/app/.agents/skills/tdd/interface-design.md +31 -0
  240. package/dist/templates/claude-config/app/.agents/skills/tdd/mocking.md +60 -0
  241. package/dist/templates/claude-config/app/.agents/skills/tdd/refactoring.md +10 -0
  242. package/dist/templates/claude-config/app/.agents/skills/tdd/tests.md +61 -0
  243. package/dist/templates/claude-config/app/.agents/skills/turborepo/SKILL.md +914 -0
  244. package/dist/templates/claude-config/app/.agents/skills/turborepo/command/turborepo.md +70 -0
  245. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/RULE.md +241 -0
  246. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/dependencies.md +246 -0
  247. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/packages.md +335 -0
  248. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/structure.md +270 -0
  249. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/boundaries/RULE.md +126 -0
  250. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/RULE.md +107 -0
  251. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/gotchas.md +169 -0
  252. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/remote-cache.md +127 -0
  253. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/RULE.md +79 -0
  254. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/github-actions.md +162 -0
  255. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/patterns.md +145 -0
  256. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/vercel.md +103 -0
  257. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/cli/RULE.md +100 -0
  258. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/cli/commands.md +297 -0
  259. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/RULE.md +211 -0
  260. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/global-options.md +191 -0
  261. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/gotchas.md +348 -0
  262. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/tasks.md +281 -0
  263. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/RULE.md +96 -0
  264. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/gotchas.md +141 -0
  265. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/modes.md +101 -0
  266. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/filtering/RULE.md +148 -0
  267. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/filtering/patterns.md +152 -0
  268. package/dist/templates/claude-config/app/.agents/skills/turborepo/references/watch/RULE.md +99 -0
  269. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/AGENTS.md +917 -0
  270. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/SKILL.md +88 -0
  271. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +94 -0
  272. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md +108 -0
  273. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +84 -0
  274. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +94 -0
  275. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  276. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  277. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +103 -0
  278. package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  279. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/AGENTS.md +2883 -0
  280. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/SKILL.md +138 -0
  281. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  282. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  283. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  284. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +35 -0
  285. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  286. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +48 -0
  287. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +24 -0
  288. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  289. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  290. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +37 -0
  291. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +48 -0
  292. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +34 -0
  293. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +44 -0
  294. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +78 -0
  295. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +74 -0
  296. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  297. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  298. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +110 -0
  299. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  300. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  301. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +68 -0
  302. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  303. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  304. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  305. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  306. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +50 -0
  307. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  308. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  309. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  310. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  311. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  312. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +32 -0
  313. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  314. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  315. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
  316. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +26 -0
  317. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  318. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  319. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  320. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  321. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  322. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  323. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +77 -0
  324. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  325. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  326. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  327. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  328. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  329. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  330. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  331. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  332. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  333. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  334. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  335. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  336. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  337. package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  338. package/dist/templates/claude-config/app/.agents/skills/web-design-guidelines/SKILL.md +40 -0
  339. package/dist/templates/claude-config/app/.agents/skills/workflow/SKILL.md +181 -0
  340. package/dist/templates/claude-config/app/.claude/commands/council.md +7 -0
  341. package/dist/templates/claude-config/app/.claude/commands/deslop.md +25 -0
  342. package/dist/templates/claude-config/app/.claude/commands/diagram.md +101 -0
  343. package/dist/templates/claude-config/app/.claude/commands/fix-merge.md +47 -0
  344. package/dist/templates/claude-config/app/.claude/commands/you-might-not-need-an-effect.md +10 -0
  345. package/dist/templates/claude-config/app/.claude/hooks/post-tool-use-tracker.sh +187 -0
  346. package/dist/templates/claude-config/app/.claude/hooks/skill-activation-prompt.sh +5 -0
  347. package/dist/templates/claude-config/app/.claude/hooks/skill-activation-prompt.ts +134 -0
  348. package/dist/templates/claude-config/app/.claude/rules/comments.md +12 -0
  349. package/dist/templates/claude-config/app/.claude/rules/typescript.md +31 -0
  350. package/dist/templates/claude-config/app/.claude/settings.json.hbs +74 -0
  351. package/dist/templates/claude-config/app/.claude/skills/skill-rules.json.hbs +309 -0
  352. package/dist/templates/claude-config/app/AGENTS.md.hbs +185 -0
  353. package/dist/templates/claude-config/app/CLAUDE.md.hbs +5 -0
  354. package/dist/templates/claude-config/kustomize/.agents/skills/git-commit/SKILL.md +124 -0
  355. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/SKILL.md +534 -0
  356. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
  357. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
  358. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
  359. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/references/deployment-spec.md +780 -0
  360. package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/references/service-spec.md +748 -0
  361. package/dist/templates/claude-config/kustomize/.claude/settings.json +42 -0
  362. package/dist/templates/claude-config/kustomize/.claude/skills/git-commit/SKILL.md +124 -0
  363. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/SKILL.md +534 -0
  364. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
  365. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
  366. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
  367. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/references/deployment-spec.md +780 -0
  368. package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/references/service-spec.md +748 -0
  369. package/dist/templates/docker/.dockerignore.hbs +8 -0
  370. package/dist/templates/docker/Dockerfile.hbs +81 -0
  371. package/dist/templates/docker/docker-compose.yml.hbs +55 -0
  372. package/dist/templates/kustomize/base/deployments/app.yaml.hbs +44 -0
  373. package/dist/templates/kustomize/base/ingress/app.yaml.hbs +20 -0
  374. package/dist/templates/kustomize/base/jobs/app-jobs.yaml.hbs +43 -0
  375. package/dist/templates/kustomize/base/kustomization.yaml.hbs +13 -0
  376. package/dist/templates/kustomize/base/secrets/regcred.yaml.hbs +7 -0
  377. package/dist/templates/kustomize/base/services/app.yaml.hbs +12 -0
  378. package/dist/templates/kustomize/overlays/{{env}}/configs/app.config.env.hbs +21 -0
  379. package/dist/templates/kustomize/overlays/{{env}}/configs/paradedb.config.env.hbs +3 -0
  380. package/dist/templates/kustomize/overlays/{{env}}/deployments/paradedb.yaml.hbs +28 -0
  381. package/dist/templates/kustomize/overlays/{{env}}/deployments/redis.yaml.hbs +18 -0
  382. package/dist/templates/kustomize/overlays/{{env}}/kustomization.yaml.hbs +36 -0
  383. package/dist/templates/kustomize/overlays/{{env}}/patch-operation/ingress-host.yaml.hbs +15 -0
  384. package/dist/templates/kustomize/overlays/{{env}}/services/paradedb.yaml.hbs +11 -0
  385. package/dist/templates/kustomize/overlays/{{env}}/services/redis.yaml.hbs +11 -0
  386. package/dist/templates/kustomize/overlays/{{env}}/storage/paradedb-pvc.yaml.hbs +10 -0
  387. package/dist/templates/presets/ai-chat-app/apps/web/.env.example +11 -0
  388. package/dist/templates/presets/ai-chat-app/apps/web/app/api/auth/[...all]/route.ts +5 -0
  389. package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/input-guardrail.ts +47 -0
  390. package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/route.ts +266 -0
  391. package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/[id]/messages/route.ts +38 -0
  392. package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/[id]/route.ts +59 -0
  393. package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/route.ts +24 -0
  394. package/dist/templates/presets/ai-chat-app/apps/web/app/api/health/route.ts +21 -0
  395. package/dist/templates/presets/ai-chat-app/apps/web/app/chat/[id]/page.tsx +54 -0
  396. package/dist/templates/presets/ai-chat-app/apps/web/app/chat/layout.tsx +23 -0
  397. package/dist/templates/presets/ai-chat-app/apps/web/app/chat/page.tsx +9 -0
  398. package/dist/templates/presets/ai-chat-app/apps/web/app/error.tsx +20 -0
  399. package/dist/templates/presets/ai-chat-app/apps/web/app/global-error.tsx +42 -0
  400. package/dist/templates/presets/ai-chat-app/apps/web/app/globals.css +187 -0
  401. package/dist/templates/presets/ai-chat-app/apps/web/app/layout.tsx.hbs +30 -0
  402. package/dist/templates/presets/ai-chat-app/apps/web/app/login/login-form.tsx +96 -0
  403. package/dist/templates/presets/ai-chat-app/apps/web/app/login/page.tsx +14 -0
  404. package/dist/templates/presets/ai-chat-app/apps/web/app/not-found.tsx +15 -0
  405. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/code-block.tsx +518 -0
  406. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/context.tsx +356 -0
  407. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/conversation.tsx +150 -0
  408. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/environment-variables.tsx +303 -0
  409. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/message.tsx +295 -0
  410. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/prompt-input.tsx +1179 -0
  411. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/sources.tsx +54 -0
  412. package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/tool.tsx +157 -0
  413. package/dist/templates/presets/ai-chat-app/apps/web/components/app-sidebar.tsx +110 -0
  414. package/dist/templates/presets/ai-chat-app/apps/web/components/chat-sessions-provider.tsx +89 -0
  415. package/dist/templates/presets/ai-chat-app/apps/web/components/chat-sidebar-list.tsx +174 -0
  416. package/dist/templates/presets/ai-chat-app/apps/web/components/chat-view.tsx +156 -0
  417. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/accordion.tsx +72 -0
  418. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/alert-dialog.tsx +162 -0
  419. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/alert.tsx +73 -0
  420. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/aspect-ratio.tsx +22 -0
  421. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/avatar.tsx +93 -0
  422. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/badge.tsx +49 -0
  423. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/breadcrumb.tsx +103 -0
  424. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/button-group.tsx +78 -0
  425. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/button.tsx +60 -0
  426. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/calendar.tsx +185 -0
  427. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/card.tsx +92 -0
  428. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/carousel.tsx +231 -0
  429. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/chart.tsx +325 -0
  430. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/checkbox.tsx +28 -0
  431. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/collapsible.tsx +17 -0
  432. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/combobox.tsx +273 -0
  433. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/command.tsx +181 -0
  434. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/context-menu.tsx +245 -0
  435. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/dialog.tsx +135 -0
  436. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/direction.tsx +3 -0
  437. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/drawer.tsx +120 -0
  438. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/dropdown-menu.tsx +258 -0
  439. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/empty.tsx +94 -0
  440. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/field.tsx +224 -0
  441. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/hover-card.tsx +46 -0
  442. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input-group.tsx +146 -0
  443. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input-otp.tsx +86 -0
  444. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input.tsx +20 -0
  445. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/item.tsx +188 -0
  446. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/kbd.tsx +26 -0
  447. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/label.tsx +20 -0
  448. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/menubar.tsx +270 -0
  449. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/native-select.tsx +43 -0
  450. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/navigation-menu.tsx +161 -0
  451. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/pagination.tsx +118 -0
  452. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/popover.tsx +77 -0
  453. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/progress.tsx +66 -0
  454. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/radio-group.tsx +39 -0
  455. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/resizable.tsx +42 -0
  456. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/scroll-area.tsx +51 -0
  457. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/select.tsx +190 -0
  458. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/separator.tsx +21 -0
  459. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sheet.tsx +125 -0
  460. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sidebar.tsx +689 -0
  461. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/skeleton.tsx +13 -0
  462. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/slider.tsx +54 -0
  463. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sonner.tsx +45 -0
  464. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/spinner.tsx +15 -0
  465. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/switch.tsx +32 -0
  466. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/table.tsx +89 -0
  467. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/tabs.tsx +75 -0
  468. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/textarea.tsx +18 -0
  469. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/toggle-group.tsx +87 -0
  470. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/toggle.tsx +44 -0
  471. package/dist/templates/presets/ai-chat-app/apps/web/components/ui/tooltip.tsx +54 -0
  472. package/dist/templates/presets/ai-chat-app/apps/web/components.json +20 -0
  473. package/dist/templates/presets/ai-chat-app/apps/web/drizzle.config.ts +10 -0
  474. package/dist/templates/presets/ai-chat-app/apps/web/env.ts +30 -0
  475. package/dist/templates/presets/ai-chat-app/apps/web/hooks/use-mobile.ts +19 -0
  476. package/dist/templates/presets/ai-chat-app/apps/web/instrumentation.ts +21 -0
  477. package/dist/templates/presets/ai-chat-app/apps/web/lib/auth-client.ts +3 -0
  478. package/dist/templates/presets/ai-chat-app/apps/web/lib/auth-session.ts +9 -0
  479. package/dist/templates/presets/ai-chat-app/apps/web/lib/auth.ts +16 -0
  480. package/dist/templates/presets/ai-chat-app/apps/web/lib/db/index.ts +11 -0
  481. package/dist/templates/presets/ai-chat-app/apps/web/lib/db/migrate.ts +53 -0
  482. package/dist/templates/presets/ai-chat-app/apps/web/lib/db/schema.ts +94 -0
  483. package/dist/templates/presets/ai-chat-app/apps/web/lib/db/seed.ts +123 -0
  484. package/dist/templates/presets/ai-chat-app/apps/web/lib/group-by-date.ts +34 -0
  485. package/dist/templates/presets/ai-chat-app/apps/web/lib/logger.ts +21 -0
  486. package/dist/templates/presets/ai-chat-app/apps/web/lib/openrouter.ts +7 -0
  487. package/dist/templates/presets/ai-chat-app/apps/web/lib/schemas/auth.ts +8 -0
  488. package/dist/templates/presets/ai-chat-app/apps/web/lib/utils.ts +4 -0
  489. package/dist/templates/presets/ai-chat-app/apps/web/next-env.d.ts +6 -0
  490. package/dist/templates/presets/ai-chat-app/apps/web/next.config.ts +14 -0
  491. package/dist/templates/presets/ai-chat-app/apps/web/package.json +70 -0
  492. package/dist/templates/presets/ai-chat-app/apps/web/postcss.config.mjs +7 -0
  493. package/dist/templates/presets/ai-chat-app/apps/web/proxy.ts +13 -0
  494. package/dist/templates/presets/ai-chat-app/apps/web/tsconfig.json +14 -0
  495. package/dist/templates/presets/blank/apps/web/.env.example +1 -0
  496. package/dist/templates/presets/blank/apps/web/app/api/health/route.ts +11 -0
  497. package/dist/templates/presets/blank/apps/web/app/globals.css +49 -0
  498. package/dist/templates/presets/blank/apps/web/app/layout.tsx.hbs +30 -0
  499. package/dist/templates/presets/blank/apps/web/app/page.tsx.hbs +10 -0
  500. package/dist/templates/presets/blank/apps/web/env.ts +10 -0
  501. package/dist/templates/presets/blank/apps/web/next-env.d.ts +2 -0
  502. package/dist/templates/presets/blank/apps/web/next.config.ts +9 -0
  503. package/dist/templates/presets/blank/apps/web/package.json.hbs +27 -0
  504. package/dist/templates/presets/blank/apps/web/postcss.config.mjs +7 -0
  505. package/dist/templates/presets/blank/apps/web/tsconfig.json +14 -0
  506. package/dist/templates/tooling/.oxfmtrc.json +6 -0
  507. package/dist/templates/tooling/.oxlintrc.json +20 -0
  508. package/dist/templates/tooling/commitlint.config.ts.hbs +3 -0
  509. package/dist/templates/tooling/lefthook.yml.hbs +25 -0
  510. package/package.json +47 -0
@@ -0,0 +1,1179 @@
1
+ "use client";
2
+
3
+ import type { ChatStatus, FileUIPart, SourceDocumentUIPart } from "ai";
4
+ import type {
5
+ ChangeEvent,
6
+ ChangeEventHandler,
7
+ ClipboardEventHandler,
8
+ ComponentProps,
9
+ FormEvent,
10
+ FormEventHandler,
11
+ HTMLAttributes,
12
+ KeyboardEventHandler,
13
+ PropsWithChildren,
14
+ ReactNode,
15
+ RefObject,
16
+ } from "react";
17
+
18
+ import {
19
+ Command,
20
+ CommandEmpty,
21
+ CommandGroup,
22
+ CommandInput,
23
+ CommandItem,
24
+ CommandList,
25
+ CommandSeparator,
26
+ } from "@/components/ui/command";
27
+ import {
28
+ DropdownMenu,
29
+ DropdownMenuContent,
30
+ DropdownMenuItem,
31
+ DropdownMenuTrigger,
32
+ } from "@/components/ui/dropdown-menu";
33
+ import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
34
+ import {
35
+ InputGroup,
36
+ InputGroupAddon,
37
+ InputGroupButton,
38
+ InputGroupTextarea,
39
+ } from "@/components/ui/input-group";
40
+ import {
41
+ Select,
42
+ SelectContent,
43
+ SelectItem,
44
+ SelectTrigger,
45
+ SelectValue,
46
+ } from "@/components/ui/select";
47
+ import { Spinner } from "@/components/ui/spinner";
48
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
49
+ import { cn } from "@/lib/utils";
50
+ import { CornerDownLeftIcon, ImageIcon, PlusIcon, SquareIcon, XIcon } from "lucide-react";
51
+ import { nanoid } from "nanoid";
52
+ import {
53
+ Children,
54
+ createContext,
55
+ useCallback,
56
+ useContext,
57
+ useEffect,
58
+ useMemo,
59
+ useRef,
60
+ useState,
61
+ } from "react";
62
+
63
+ // ============================================================================
64
+ // Helpers
65
+ // ============================================================================
66
+
67
+ const convertBlobUrlToDataUrl = async (url: string): Promise<string | null> => {
68
+ try {
69
+ const response = await fetch(url);
70
+ const blob = await response.blob();
71
+ // FileReader uses callback-based API, wrapping in Promise is necessary
72
+ // oxlint-disable-next-line eslint-plugin-promise(avoid-new)
73
+ return new Promise((resolve) => {
74
+ const reader = new FileReader();
75
+ // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)
76
+ reader.onloadend = () => resolve(reader.result as string);
77
+ // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)
78
+ reader.onerror = () => resolve(null);
79
+ reader.readAsDataURL(blob);
80
+ });
81
+ } catch {
82
+ return null;
83
+ }
84
+ };
85
+
86
+ // ============================================================================
87
+ // Provider Context & Types
88
+ // ============================================================================
89
+
90
+ export interface AttachmentsContext {
91
+ files: (FileUIPart & { id: string })[];
92
+ add: (files: File[] | FileList) => void;
93
+ remove: (id: string) => void;
94
+ clear: () => void;
95
+ openFileDialog: () => void;
96
+ fileInputRef: RefObject<HTMLInputElement | null>;
97
+ }
98
+
99
+ export interface TextInputContext {
100
+ value: string;
101
+ setInput: (v: string) => void;
102
+ clear: () => void;
103
+ }
104
+
105
+ export interface PromptInputControllerProps {
106
+ textInput: TextInputContext;
107
+ attachments: AttachmentsContext;
108
+ /** INTERNAL: Allows PromptInput to register its file textInput + "open" callback */
109
+ __registerFileInput: (ref: RefObject<HTMLInputElement | null>, open: () => void) => void;
110
+ }
111
+
112
+ const PromptInputController = createContext<PromptInputControllerProps | null>(null);
113
+ const ProviderAttachmentsContext = createContext<AttachmentsContext | null>(null);
114
+
115
+ export const usePromptInputController = () => {
116
+ const ctx = useContext(PromptInputController);
117
+ if (!ctx) {
118
+ throw new Error(
119
+ "Wrap your component inside <PromptInputProvider> to use usePromptInputController().",
120
+ );
121
+ }
122
+ return ctx;
123
+ };
124
+
125
+ // Optional variants (do NOT throw). Useful for dual-mode components.
126
+ const useOptionalPromptInputController = () => useContext(PromptInputController);
127
+
128
+ export const useProviderAttachments = () => {
129
+ const ctx = useContext(ProviderAttachmentsContext);
130
+ if (!ctx) {
131
+ throw new Error(
132
+ "Wrap your component inside <PromptInputProvider> to use useProviderAttachments().",
133
+ );
134
+ }
135
+ return ctx;
136
+ };
137
+
138
+ const useOptionalProviderAttachments = () => useContext(ProviderAttachmentsContext);
139
+
140
+ export type PromptInputProviderProps = PropsWithChildren<{
141
+ initialInput?: string;
142
+ }>;
143
+
144
+ /**
145
+ * Optional global provider that lifts PromptInput state outside of PromptInput.
146
+ * If you don't use it, PromptInput stays fully self-managed.
147
+ */
148
+ export const PromptInputProvider = ({
149
+ initialInput: initialTextInput = "",
150
+ children,
151
+ }: PromptInputProviderProps) => {
152
+ // ----- textInput state
153
+ const [textInput, setTextInput] = useState(initialTextInput);
154
+ const clearInput = useCallback(() => setTextInput(""), []);
155
+
156
+ // ----- attachments state (global when wrapped)
157
+ const [attachmentFiles, setAttachmentFiles] = useState<(FileUIPart & { id: string })[]>([]);
158
+ const fileInputRef = useRef<HTMLInputElement | null>(null);
159
+ // oxlint-disable-next-line eslint(no-empty-function)
160
+ const openRef = useRef<() => void>(() => {});
161
+
162
+ const add = useCallback((files: File[] | FileList) => {
163
+ const incoming = [...files];
164
+ if (incoming.length === 0) {
165
+ return;
166
+ }
167
+
168
+ setAttachmentFiles((prev) => [
169
+ ...prev,
170
+ ...incoming.map((file) => ({
171
+ filename: file.name,
172
+ id: nanoid(),
173
+ mediaType: file.type,
174
+ type: "file" as const,
175
+ url: URL.createObjectURL(file),
176
+ })),
177
+ ]);
178
+ }, []);
179
+
180
+ const remove = useCallback((id: string) => {
181
+ setAttachmentFiles((prev) => {
182
+ const found = prev.find((f) => f.id === id);
183
+ if (found?.url) {
184
+ URL.revokeObjectURL(found.url);
185
+ }
186
+ return prev.filter((f) => f.id !== id);
187
+ });
188
+ }, []);
189
+
190
+ const clear = useCallback(() => {
191
+ setAttachmentFiles((prev) => {
192
+ for (const f of prev) {
193
+ if (f.url) {
194
+ URL.revokeObjectURL(f.url);
195
+ }
196
+ }
197
+ return [];
198
+ });
199
+ }, []);
200
+
201
+ // Keep a ref to attachments for cleanup on unmount (avoids stale closure)
202
+ const attachmentsRef = useRef(attachmentFiles);
203
+
204
+ useEffect(() => {
205
+ attachmentsRef.current = attachmentFiles;
206
+ }, [attachmentFiles]);
207
+
208
+ // Cleanup blob URLs on unmount to prevent memory leaks
209
+ useEffect(
210
+ () => () => {
211
+ for (const f of attachmentsRef.current) {
212
+ if (f.url) {
213
+ URL.revokeObjectURL(f.url);
214
+ }
215
+ }
216
+ },
217
+ [],
218
+ );
219
+
220
+ const openFileDialog = useCallback(() => {
221
+ openRef.current?.();
222
+ }, []);
223
+
224
+ const attachments = useMemo<AttachmentsContext>(
225
+ () => ({
226
+ add,
227
+ clear,
228
+ fileInputRef,
229
+ files: attachmentFiles,
230
+ openFileDialog,
231
+ remove,
232
+ }),
233
+ [attachmentFiles, add, remove, clear, openFileDialog],
234
+ );
235
+
236
+ const __registerFileInput = useCallback(
237
+ (ref: RefObject<HTMLInputElement | null>, open: () => void) => {
238
+ fileInputRef.current = ref.current;
239
+ openRef.current = open;
240
+ },
241
+ [],
242
+ );
243
+
244
+ const controller = useMemo<PromptInputControllerProps>(
245
+ () => ({
246
+ __registerFileInput,
247
+ attachments,
248
+ textInput: {
249
+ clear: clearInput,
250
+ setInput: setTextInput,
251
+ value: textInput,
252
+ },
253
+ }),
254
+ [textInput, clearInput, attachments, __registerFileInput],
255
+ );
256
+
257
+ return (
258
+ <PromptInputController.Provider value={controller}>
259
+ <ProviderAttachmentsContext.Provider value={attachments}>
260
+ {children}
261
+ </ProviderAttachmentsContext.Provider>
262
+ </PromptInputController.Provider>
263
+ );
264
+ };
265
+
266
+ // ============================================================================
267
+ // Component Context & Hooks
268
+ // ============================================================================
269
+
270
+ const LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);
271
+
272
+ export const usePromptInputAttachments = () => {
273
+ // Prefer local context (inside PromptInput) as it has validation, fall back to provider
274
+ const provider = useOptionalProviderAttachments();
275
+ const local = useContext(LocalAttachmentsContext);
276
+ const context = local ?? provider;
277
+ if (!context) {
278
+ throw new Error(
279
+ "usePromptInputAttachments must be used within a PromptInput or PromptInputProvider",
280
+ );
281
+ }
282
+ return context;
283
+ };
284
+
285
+ // ============================================================================
286
+ // Referenced Sources (Local to PromptInput)
287
+ // ============================================================================
288
+
289
+ export interface ReferencedSourcesContext {
290
+ sources: (SourceDocumentUIPart & { id: string })[];
291
+ add: (sources: SourceDocumentUIPart[] | SourceDocumentUIPart) => void;
292
+ remove: (id: string) => void;
293
+ clear: () => void;
294
+ }
295
+
296
+ export const LocalReferencedSourcesContext = createContext<ReferencedSourcesContext | null>(null);
297
+
298
+ export const usePromptInputReferencedSources = () => {
299
+ const ctx = useContext(LocalReferencedSourcesContext);
300
+ if (!ctx) {
301
+ throw new Error(
302
+ "usePromptInputReferencedSources must be used within a LocalReferencedSourcesContext.Provider",
303
+ );
304
+ }
305
+ return ctx;
306
+ };
307
+
308
+ export type PromptInputActionAddAttachmentsProps = ComponentProps<typeof DropdownMenuItem> & {
309
+ label?: string;
310
+ };
311
+
312
+ export const PromptInputActionAddAttachments = ({
313
+ label = "Add photos or files",
314
+ ...props
315
+ }: PromptInputActionAddAttachmentsProps) => {
316
+ const attachments = usePromptInputAttachments();
317
+
318
+ const handleSelect = useCallback(() => {
319
+ attachments.openFileDialog();
320
+ }, [attachments]);
321
+
322
+ return (
323
+ <DropdownMenuItem {...props} onClick={handleSelect}>
324
+ <ImageIcon className="mr-2 size-4" /> {label}
325
+ </DropdownMenuItem>
326
+ );
327
+ };
328
+
329
+ export interface PromptInputMessage {
330
+ text: string;
331
+ files: FileUIPart[];
332
+ }
333
+
334
+ export type PromptInputProps = Omit<HTMLAttributes<HTMLFormElement>, "onSubmit" | "onError"> & {
335
+ // e.g., "image/*" or leave undefined for any
336
+ accept?: string;
337
+ multiple?: boolean;
338
+ // When true, accepts drops anywhere on document. Default false (opt-in).
339
+ globalDrop?: boolean;
340
+ // Render a hidden input with given name and keep it in sync for native form posts. Default false.
341
+ syncHiddenInput?: boolean;
342
+ // Minimal constraints
343
+ maxFiles?: number;
344
+ // bytes
345
+ maxFileSize?: number;
346
+ onError?: (err: { code: "max_files" | "max_file_size" | "accept"; message: string }) => void;
347
+ onSubmit: (
348
+ message: PromptInputMessage,
349
+ event: FormEvent<HTMLFormElement>,
350
+ ) => void | Promise<void>;
351
+ };
352
+
353
+ export const PromptInput = ({
354
+ className,
355
+ accept,
356
+ multiple,
357
+ globalDrop,
358
+ syncHiddenInput,
359
+ maxFiles,
360
+ maxFileSize,
361
+ onError,
362
+ onSubmit,
363
+ children,
364
+ ...props
365
+ }: PromptInputProps) => {
366
+ // Try to use a provider controller if present
367
+ const controller = useOptionalPromptInputController();
368
+ const usingProvider = !!controller;
369
+
370
+ // Refs
371
+ const inputRef = useRef<HTMLInputElement | null>(null);
372
+ const formRef = useRef<HTMLFormElement | null>(null);
373
+
374
+ // ----- Local attachments (only used when no provider)
375
+ const [items, setItems] = useState<(FileUIPart & { id: string })[]>([]);
376
+ const files = usingProvider ? controller.attachments.files : items;
377
+
378
+ // ----- Local referenced sources (always local to PromptInput)
379
+ const [referencedSources, setReferencedSources] = useState<
380
+ (SourceDocumentUIPart & { id: string })[]
381
+ >([]);
382
+
383
+ // Keep a ref to files for cleanup on unmount (avoids stale closure)
384
+ const filesRef = useRef(files);
385
+
386
+ useEffect(() => {
387
+ filesRef.current = files;
388
+ }, [files]);
389
+
390
+ const openFileDialogLocal = useCallback(() => {
391
+ inputRef.current?.click();
392
+ }, []);
393
+
394
+ const matchesAccept = useCallback(
395
+ (f: File) => {
396
+ if (!accept || accept.trim() === "") {
397
+ return true;
398
+ }
399
+
400
+ const patterns = accept
401
+ .split(",")
402
+ .map((s) => s.trim())
403
+ .filter(Boolean);
404
+
405
+ return patterns.some((pattern) => {
406
+ if (pattern.endsWith("/*")) {
407
+ // e.g: image/* -> image/
408
+ const prefix = pattern.slice(0, -1);
409
+ return f.type.startsWith(prefix);
410
+ }
411
+ return f.type === pattern;
412
+ });
413
+ },
414
+ [accept],
415
+ );
416
+
417
+ const addLocal = useCallback(
418
+ (fileList: File[] | FileList) => {
419
+ const incoming = [...fileList];
420
+ const accepted = incoming.filter((f) => matchesAccept(f));
421
+ if (incoming.length && accepted.length === 0) {
422
+ onError?.({
423
+ code: "accept",
424
+ message: "No files match the accepted types.",
425
+ });
426
+ return;
427
+ }
428
+ const withinSize = (f: File) => (maxFileSize ? f.size <= maxFileSize : true);
429
+ const sized = accepted.filter(withinSize);
430
+ if (accepted.length > 0 && sized.length === 0) {
431
+ onError?.({
432
+ code: "max_file_size",
433
+ message: "All files exceed the maximum size.",
434
+ });
435
+ return;
436
+ }
437
+
438
+ setItems((prev) => {
439
+ const capacity =
440
+ typeof maxFiles === "number" ? Math.max(0, maxFiles - prev.length) : undefined;
441
+ const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
442
+ if (typeof capacity === "number" && sized.length > capacity) {
443
+ onError?.({
444
+ code: "max_files",
445
+ message: "Too many files. Some were not added.",
446
+ });
447
+ }
448
+ const next: (FileUIPart & { id: string })[] = [];
449
+ for (const file of capped) {
450
+ next.push({
451
+ filename: file.name,
452
+ id: nanoid(),
453
+ mediaType: file.type,
454
+ type: "file",
455
+ url: URL.createObjectURL(file),
456
+ });
457
+ }
458
+ return [...prev, ...next];
459
+ });
460
+ },
461
+ [matchesAccept, maxFiles, maxFileSize, onError],
462
+ );
463
+
464
+ const removeLocal = useCallback(
465
+ (id: string) =>
466
+ setItems((prev) => {
467
+ const found = prev.find((file) => file.id === id);
468
+ if (found?.url) {
469
+ URL.revokeObjectURL(found.url);
470
+ }
471
+ return prev.filter((file) => file.id !== id);
472
+ }),
473
+ [],
474
+ );
475
+
476
+ // Wrapper that validates files before calling provider's add
477
+ const addWithProviderValidation = useCallback(
478
+ (fileList: File[] | FileList) => {
479
+ const incoming = [...fileList];
480
+ const accepted = incoming.filter((f) => matchesAccept(f));
481
+ if (incoming.length && accepted.length === 0) {
482
+ onError?.({
483
+ code: "accept",
484
+ message: "No files match the accepted types.",
485
+ });
486
+ return;
487
+ }
488
+ const withinSize = (f: File) => (maxFileSize ? f.size <= maxFileSize : true);
489
+ const sized = accepted.filter(withinSize);
490
+ if (accepted.length > 0 && sized.length === 0) {
491
+ onError?.({
492
+ code: "max_file_size",
493
+ message: "All files exceed the maximum size.",
494
+ });
495
+ return;
496
+ }
497
+
498
+ const currentCount = files.length;
499
+ const capacity =
500
+ typeof maxFiles === "number" ? Math.max(0, maxFiles - currentCount) : undefined;
501
+ const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
502
+ if (typeof capacity === "number" && sized.length > capacity) {
503
+ onError?.({
504
+ code: "max_files",
505
+ message: "Too many files. Some were not added.",
506
+ });
507
+ }
508
+
509
+ if (capped.length > 0) {
510
+ controller?.attachments.add(capped);
511
+ }
512
+ },
513
+ [matchesAccept, maxFileSize, maxFiles, onError, files.length, controller],
514
+ );
515
+
516
+ const clearAttachments = useCallback(
517
+ () =>
518
+ usingProvider
519
+ ? controller?.attachments.clear()
520
+ : setItems((prev) => {
521
+ for (const file of prev) {
522
+ if (file.url) {
523
+ URL.revokeObjectURL(file.url);
524
+ }
525
+ }
526
+ return [];
527
+ }),
528
+ [usingProvider, controller],
529
+ );
530
+
531
+ const clearReferencedSources = useCallback(() => setReferencedSources([]), []);
532
+
533
+ const add = usingProvider ? addWithProviderValidation : addLocal;
534
+ const remove = usingProvider ? controller.attachments.remove : removeLocal;
535
+ const openFileDialog = usingProvider
536
+ ? controller.attachments.openFileDialog
537
+ : openFileDialogLocal;
538
+
539
+ const clear = useCallback(() => {
540
+ clearAttachments();
541
+ clearReferencedSources();
542
+ }, [clearAttachments, clearReferencedSources]);
543
+
544
+ // Let provider know about our hidden file input so external menus can call openFileDialog()
545
+ useEffect(() => {
546
+ if (!usingProvider) {
547
+ return;
548
+ }
549
+ controller.__registerFileInput(inputRef, () => inputRef.current?.click());
550
+ }, [usingProvider, controller]);
551
+
552
+ // Note: File input cannot be programmatically set for security reasons
553
+ // The syncHiddenInput prop is no longer functional
554
+ useEffect(() => {
555
+ if (syncHiddenInput && inputRef.current && files.length === 0) {
556
+ inputRef.current.value = "";
557
+ }
558
+ }, [files, syncHiddenInput]);
559
+
560
+ // Attach drop handlers on nearest form and document (opt-in)
561
+ useEffect(() => {
562
+ const form = formRef.current;
563
+ if (!form) {
564
+ return;
565
+ }
566
+ if (globalDrop) {
567
+ // when global drop is on, let the document-level handler own drops
568
+ return;
569
+ }
570
+
571
+ const onDragOver = (e: DragEvent) => {
572
+ if (e.dataTransfer?.types?.includes("Files")) {
573
+ e.preventDefault();
574
+ }
575
+ };
576
+ const onDrop = (e: DragEvent) => {
577
+ if (e.dataTransfer?.types?.includes("Files")) {
578
+ e.preventDefault();
579
+ }
580
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
581
+ add(e.dataTransfer.files);
582
+ }
583
+ };
584
+ form.addEventListener("dragover", onDragOver);
585
+ form.addEventListener("drop", onDrop);
586
+ return () => {
587
+ form.removeEventListener("dragover", onDragOver);
588
+ form.removeEventListener("drop", onDrop);
589
+ };
590
+ }, [add, globalDrop]);
591
+
592
+ useEffect(() => {
593
+ if (!globalDrop) {
594
+ return;
595
+ }
596
+
597
+ const onDragOver = (e: DragEvent) => {
598
+ if (e.dataTransfer?.types?.includes("Files")) {
599
+ e.preventDefault();
600
+ }
601
+ };
602
+ const onDrop = (e: DragEvent) => {
603
+ if (e.dataTransfer?.types?.includes("Files")) {
604
+ e.preventDefault();
605
+ }
606
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
607
+ add(e.dataTransfer.files);
608
+ }
609
+ };
610
+ document.addEventListener("dragover", onDragOver);
611
+ document.addEventListener("drop", onDrop);
612
+ return () => {
613
+ document.removeEventListener("dragover", onDragOver);
614
+ document.removeEventListener("drop", onDrop);
615
+ };
616
+ }, [add, globalDrop]);
617
+
618
+ useEffect(
619
+ () => () => {
620
+ if (!usingProvider) {
621
+ for (const f of filesRef.current) {
622
+ if (f.url) {
623
+ URL.revokeObjectURL(f.url);
624
+ }
625
+ }
626
+ }
627
+ },
628
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- cleanup only on unmount; filesRef always current
629
+ [usingProvider],
630
+ );
631
+
632
+ const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(
633
+ (event) => {
634
+ if (event.currentTarget.files) {
635
+ add(event.currentTarget.files);
636
+ }
637
+ // Reset input value to allow selecting files that were previously removed
638
+ event.currentTarget.value = "";
639
+ },
640
+ [add],
641
+ );
642
+
643
+ const attachmentsCtx = useMemo<AttachmentsContext>(
644
+ () => ({
645
+ add,
646
+ clear: clearAttachments,
647
+ fileInputRef: inputRef,
648
+ files: files.map((item) => ({ ...item, id: item.id })),
649
+ openFileDialog,
650
+ remove,
651
+ }),
652
+ [files, add, remove, clearAttachments, openFileDialog],
653
+ );
654
+
655
+ const refsCtx = useMemo<ReferencedSourcesContext>(
656
+ () => ({
657
+ add: (incoming: SourceDocumentUIPart[] | SourceDocumentUIPart) => {
658
+ const array = Array.isArray(incoming) ? incoming : [incoming];
659
+ setReferencedSources((prev) => [...prev, ...array.map((s) => ({ ...s, id: nanoid() }))]);
660
+ },
661
+ clear: clearReferencedSources,
662
+ remove: (id: string) => {
663
+ setReferencedSources((prev) => prev.filter((s) => s.id !== id));
664
+ },
665
+ sources: referencedSources,
666
+ }),
667
+ [referencedSources, clearReferencedSources],
668
+ );
669
+
670
+ const handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(
671
+ async (event) => {
672
+ event.preventDefault();
673
+
674
+ const form = event.currentTarget;
675
+ const text = usingProvider
676
+ ? controller.textInput.value
677
+ : (() => {
678
+ const formData = new FormData(form);
679
+ return (formData.get("message") as string) || "";
680
+ })();
681
+
682
+ // Reset form immediately after capturing text to avoid race condition
683
+ // where user input during async blob conversion would be lost
684
+ if (!usingProvider) {
685
+ form.reset();
686
+ }
687
+
688
+ try {
689
+ // Convert blob URLs to data URLs asynchronously
690
+ const convertedFiles: FileUIPart[] = await Promise.all(
691
+ files.map(async ({ id: _id, ...item }) => {
692
+ if (item.url?.startsWith("blob:")) {
693
+ const dataUrl = await convertBlobUrlToDataUrl(item.url);
694
+ // If conversion failed, keep the original blob URL
695
+ return {
696
+ ...item,
697
+ url: dataUrl ?? item.url,
698
+ };
699
+ }
700
+ return item;
701
+ }),
702
+ );
703
+
704
+ const result = onSubmit({ files: convertedFiles, text }, event);
705
+
706
+ // Handle both sync and async onSubmit
707
+ if (result instanceof Promise) {
708
+ try {
709
+ await result;
710
+ clear();
711
+ if (usingProvider) {
712
+ controller.textInput.clear();
713
+ }
714
+ } catch {
715
+ // Don't clear on error - user may want to retry
716
+ }
717
+ } else {
718
+ // Sync function completed without throwing, clear inputs
719
+ clear();
720
+ if (usingProvider) {
721
+ controller.textInput.clear();
722
+ }
723
+ }
724
+ } catch {
725
+ // Don't clear on error - user may want to retry
726
+ }
727
+ },
728
+ [usingProvider, controller, files, onSubmit, clear],
729
+ );
730
+
731
+ // Render with or without local provider
732
+ const inner = (
733
+ <>
734
+ <input
735
+ accept={accept}
736
+ aria-label="Upload files"
737
+ className="hidden"
738
+ multiple={multiple}
739
+ onChange={handleChange}
740
+ ref={inputRef}
741
+ title="Upload files"
742
+ type="file"
743
+ />
744
+ <form className={cn("w-full", className)} onSubmit={handleSubmit} ref={formRef} {...props}>
745
+ <InputGroup className="overflow-hidden">{children}</InputGroup>
746
+ </form>
747
+ </>
748
+ );
749
+
750
+ const withReferencedSources = (
751
+ <LocalReferencedSourcesContext.Provider value={refsCtx}>
752
+ {inner}
753
+ </LocalReferencedSourcesContext.Provider>
754
+ );
755
+
756
+ // Always provide LocalAttachmentsContext so children get validated add function
757
+ return (
758
+ <LocalAttachmentsContext.Provider value={attachmentsCtx}>
759
+ {withReferencedSources}
760
+ </LocalAttachmentsContext.Provider>
761
+ );
762
+ };
763
+
764
+ export type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;
765
+
766
+ export const PromptInputBody = ({ className, ...props }: PromptInputBodyProps) => (
767
+ <div className={cn("contents", className)} {...props} />
768
+ );
769
+
770
+ export type PromptInputTextareaProps = ComponentProps<typeof InputGroupTextarea>;
771
+
772
+ export const PromptInputTextarea = ({
773
+ onChange,
774
+ onKeyDown,
775
+ className,
776
+ placeholder = "What would you like to know?",
777
+ ...props
778
+ }: PromptInputTextareaProps) => {
779
+ const controller = useOptionalPromptInputController();
780
+ const attachments = usePromptInputAttachments();
781
+ const [isComposing, setIsComposing] = useState(false);
782
+
783
+ const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = useCallback(
784
+ (e) => {
785
+ // Call the external onKeyDown handler first
786
+ onKeyDown?.(e);
787
+
788
+ // If the external handler prevented default, don't run internal logic
789
+ if (e.defaultPrevented) {
790
+ return;
791
+ }
792
+
793
+ if (e.key === "Enter") {
794
+ if (isComposing || e.nativeEvent.isComposing) {
795
+ return;
796
+ }
797
+ if (e.shiftKey) {
798
+ return;
799
+ }
800
+ e.preventDefault();
801
+
802
+ // Check if the submit button is disabled before submitting
803
+ const { form } = e.currentTarget;
804
+ const submitButton = form?.querySelector(
805
+ 'button[type="submit"]',
806
+ ) as HTMLButtonElement | null;
807
+ if (submitButton?.disabled) {
808
+ return;
809
+ }
810
+
811
+ form?.requestSubmit();
812
+ }
813
+
814
+ // Remove last attachment when Backspace is pressed and textarea is empty
815
+ if (e.key === "Backspace" && e.currentTarget.value === "" && attachments.files.length > 0) {
816
+ e.preventDefault();
817
+ const lastAttachment = attachments.files.at(-1);
818
+ if (lastAttachment) {
819
+ attachments.remove(lastAttachment.id);
820
+ }
821
+ }
822
+ },
823
+ [onKeyDown, isComposing, attachments],
824
+ );
825
+
826
+ const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = useCallback(
827
+ (event) => {
828
+ const items = event.clipboardData?.items;
829
+
830
+ if (!items) {
831
+ return;
832
+ }
833
+
834
+ const files: File[] = [];
835
+
836
+ for (const item of items) {
837
+ if (item.kind === "file") {
838
+ const file = item.getAsFile();
839
+ if (file) {
840
+ files.push(file);
841
+ }
842
+ }
843
+ }
844
+
845
+ if (files.length > 0) {
846
+ event.preventDefault();
847
+ attachments.add(files);
848
+ }
849
+ },
850
+ [attachments],
851
+ );
852
+
853
+ const handleCompositionEnd = useCallback(() => setIsComposing(false), []);
854
+ const handleCompositionStart = useCallback(() => setIsComposing(true), []);
855
+
856
+ const controlledProps = controller
857
+ ? {
858
+ onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {
859
+ controller.textInput.setInput(e.currentTarget.value);
860
+ onChange?.(e);
861
+ },
862
+ value: controller.textInput.value,
863
+ }
864
+ : {
865
+ onChange,
866
+ };
867
+
868
+ return (
869
+ <InputGroupTextarea
870
+ className={cn("field-sizing-content max-h-48 min-h-16", className)}
871
+ name="message"
872
+ onCompositionEnd={handleCompositionEnd}
873
+ onCompositionStart={handleCompositionStart}
874
+ onKeyDown={handleKeyDown}
875
+ onPaste={handlePaste}
876
+ placeholder={placeholder}
877
+ {...props}
878
+ {...controlledProps}
879
+ />
880
+ );
881
+ };
882
+
883
+ export type PromptInputHeaderProps = Omit<ComponentProps<typeof InputGroupAddon>, "align">;
884
+
885
+ export const PromptInputHeader = ({ className, ...props }: PromptInputHeaderProps) => (
886
+ <InputGroupAddon
887
+ align="block-end"
888
+ className={cn("order-first flex-wrap gap-1", className)}
889
+ {...props}
890
+ />
891
+ );
892
+
893
+ export type PromptInputFooterProps = Omit<ComponentProps<typeof InputGroupAddon>, "align">;
894
+
895
+ export const PromptInputFooter = ({ className, ...props }: PromptInputFooterProps) => (
896
+ <InputGroupAddon
897
+ align="block-end"
898
+ className={cn("justify-between gap-1", className)}
899
+ {...props}
900
+ />
901
+ );
902
+
903
+ export type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;
904
+
905
+ export const PromptInputTools = ({ className, ...props }: PromptInputToolsProps) => (
906
+ <div className={cn("flex min-w-0 items-center gap-1", className)} {...props} />
907
+ );
908
+
909
+ export type PromptInputButtonTooltip =
910
+ | string
911
+ | {
912
+ content: ReactNode;
913
+ shortcut?: string;
914
+ side?: ComponentProps<typeof TooltipContent>["side"];
915
+ };
916
+
917
+ export type PromptInputButtonProps = ComponentProps<typeof InputGroupButton> & {
918
+ tooltip?: PromptInputButtonTooltip;
919
+ };
920
+
921
+ export const PromptInputButton = ({
922
+ variant = "ghost",
923
+ className,
924
+ size,
925
+ tooltip,
926
+ ...props
927
+ }: PromptInputButtonProps) => {
928
+ const newSize = size ?? (Children.count(props.children) > 1 ? "sm" : "icon-sm");
929
+
930
+ const button = (
931
+ <InputGroupButton
932
+ className={cn(className)}
933
+ size={newSize}
934
+ type="button"
935
+ variant={variant}
936
+ {...props}
937
+ />
938
+ );
939
+
940
+ if (!tooltip) {
941
+ return button;
942
+ }
943
+
944
+ const tooltipContent = typeof tooltip === "string" ? tooltip : tooltip.content;
945
+ const shortcut = typeof tooltip === "string" ? undefined : tooltip.shortcut;
946
+ const side = typeof tooltip === "string" ? "top" : (tooltip.side ?? "top");
947
+
948
+ return (
949
+ <Tooltip>
950
+ <TooltipTrigger>{button}</TooltipTrigger>
951
+ <TooltipContent side={side}>
952
+ {tooltipContent}
953
+ {shortcut && <span className="ml-2 text-muted-foreground">{shortcut}</span>}
954
+ </TooltipContent>
955
+ </Tooltip>
956
+ );
957
+ };
958
+
959
+ export type PromptInputActionMenuProps = ComponentProps<typeof DropdownMenu>;
960
+ export const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (
961
+ <DropdownMenu {...props} />
962
+ );
963
+
964
+ export type PromptInputActionMenuTriggerProps = PromptInputButtonProps;
965
+
966
+ export const PromptInputActionMenuTrigger = ({
967
+ className,
968
+ children,
969
+ ...props
970
+ }: PromptInputActionMenuTriggerProps) => (
971
+ <DropdownMenuTrigger render={<PromptInputButton className={className} {...props} />}>
972
+ {children ?? <PlusIcon className="size-4" />}
973
+ </DropdownMenuTrigger>
974
+ );
975
+
976
+ export type PromptInputActionMenuContentProps = ComponentProps<typeof DropdownMenuContent>;
977
+ export const PromptInputActionMenuContent = ({
978
+ className,
979
+ ...props
980
+ }: PromptInputActionMenuContentProps) => (
981
+ <DropdownMenuContent align="start" className={cn(className)} {...props} />
982
+ );
983
+
984
+ export type PromptInputActionMenuItemProps = ComponentProps<typeof DropdownMenuItem>;
985
+ export const PromptInputActionMenuItem = ({
986
+ className,
987
+ ...props
988
+ }: PromptInputActionMenuItemProps) => <DropdownMenuItem className={cn(className)} {...props} />;
989
+
990
+ // Note: Actions that perform side-effects (like opening a file dialog)
991
+ // are provided in opt-in modules (e.g., prompt-input-attachments).
992
+
993
+ export type PromptInputSubmitProps = ComponentProps<typeof InputGroupButton> & {
994
+ status?: ChatStatus;
995
+ onStop?: () => void;
996
+ };
997
+
998
+ export const PromptInputSubmit = ({
999
+ className,
1000
+ variant = "default",
1001
+ size = "icon-sm",
1002
+ status,
1003
+ onStop,
1004
+ onClick,
1005
+ children,
1006
+ ...props
1007
+ }: PromptInputSubmitProps) => {
1008
+ const isGenerating = status === "submitted" || status === "streaming";
1009
+
1010
+ let Icon = <CornerDownLeftIcon className="size-4" />;
1011
+
1012
+ if (status === "submitted") {
1013
+ Icon = <Spinner />;
1014
+ } else if (status === "streaming") {
1015
+ Icon = <SquareIcon className="size-4" />;
1016
+ } else if (status === "error") {
1017
+ Icon = <XIcon className="size-4" />;
1018
+ }
1019
+
1020
+ const handleClick: NonNullable<typeof onClick> = useCallback(
1021
+ (e) => {
1022
+ if (isGenerating && onStop) {
1023
+ e.preventDefault();
1024
+ onStop();
1025
+ return;
1026
+ }
1027
+ onClick?.(e);
1028
+ },
1029
+ [isGenerating, onStop, onClick],
1030
+ );
1031
+
1032
+ return (
1033
+ <InputGroupButton
1034
+ aria-label={isGenerating ? "Stop" : "Submit"}
1035
+ className={cn(className)}
1036
+ onClick={handleClick}
1037
+ size={size}
1038
+ type={isGenerating && onStop ? "button" : "submit"}
1039
+ variant={variant}
1040
+ {...props}
1041
+ >
1042
+ {children ?? Icon}
1043
+ </InputGroupButton>
1044
+ );
1045
+ };
1046
+
1047
+ export type PromptInputSelectProps = ComponentProps<typeof Select>;
1048
+
1049
+ export const PromptInputSelect = (props: PromptInputSelectProps) => <Select {...props} />;
1050
+
1051
+ export type PromptInputSelectTriggerProps = ComponentProps<typeof SelectTrigger>;
1052
+
1053
+ export const PromptInputSelectTrigger = ({
1054
+ className,
1055
+ ...props
1056
+ }: PromptInputSelectTriggerProps) => (
1057
+ <SelectTrigger
1058
+ className={cn(
1059
+ "border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors",
1060
+ "hover:bg-accent hover:text-foreground aria-expanded:bg-accent aria-expanded:text-foreground",
1061
+ className,
1062
+ )}
1063
+ {...props}
1064
+ />
1065
+ );
1066
+
1067
+ export type PromptInputSelectContentProps = ComponentProps<typeof SelectContent>;
1068
+
1069
+ export const PromptInputSelectContent = ({
1070
+ className,
1071
+ ...props
1072
+ }: PromptInputSelectContentProps) => <SelectContent className={cn(className)} {...props} />;
1073
+
1074
+ export type PromptInputSelectItemProps = ComponentProps<typeof SelectItem>;
1075
+
1076
+ export const PromptInputSelectItem = ({ className, ...props }: PromptInputSelectItemProps) => (
1077
+ <SelectItem className={cn(className)} {...props} />
1078
+ );
1079
+
1080
+ export type PromptInputSelectValueProps = ComponentProps<typeof SelectValue>;
1081
+
1082
+ export const PromptInputSelectValue = ({ className, ...props }: PromptInputSelectValueProps) => (
1083
+ <SelectValue className={cn(className)} {...props} />
1084
+ );
1085
+
1086
+ export type PromptInputHoverCardProps = ComponentProps<typeof HoverCard>;
1087
+
1088
+ export const PromptInputHoverCard = (props: PromptInputHoverCardProps) => <HoverCard {...props} />;
1089
+
1090
+ export type PromptInputHoverCardTriggerProps = ComponentProps<typeof HoverCardTrigger>;
1091
+
1092
+ export const PromptInputHoverCardTrigger = (props: PromptInputHoverCardTriggerProps) => (
1093
+ <HoverCardTrigger {...props} />
1094
+ );
1095
+
1096
+ export type PromptInputHoverCardContentProps = ComponentProps<typeof HoverCardContent>;
1097
+
1098
+ export const PromptInputHoverCardContent = ({
1099
+ align = "start",
1100
+ ...props
1101
+ }: PromptInputHoverCardContentProps) => <HoverCardContent align={align} {...props} />;
1102
+
1103
+ export type PromptInputTabsListProps = HTMLAttributes<HTMLDivElement>;
1104
+
1105
+ export const PromptInputTabsList = ({ className, ...props }: PromptInputTabsListProps) => (
1106
+ <div className={cn(className)} {...props} />
1107
+ );
1108
+
1109
+ export type PromptInputTabProps = HTMLAttributes<HTMLDivElement>;
1110
+
1111
+ export const PromptInputTab = ({ className, ...props }: PromptInputTabProps) => (
1112
+ <div className={cn(className)} {...props} />
1113
+ );
1114
+
1115
+ export type PromptInputTabLabelProps = HTMLAttributes<HTMLHeadingElement>;
1116
+
1117
+ export const PromptInputTabLabel = ({ className, ...props }: PromptInputTabLabelProps) => (
1118
+ // Content provided via children in props
1119
+ // oxlint-disable-next-line eslint-plugin-jsx-a11y(heading-has-content)
1120
+ <h3 className={cn("mb-2 px-3 text-xs font-medium text-muted-foreground", className)} {...props} />
1121
+ );
1122
+
1123
+ export type PromptInputTabBodyProps = HTMLAttributes<HTMLDivElement>;
1124
+
1125
+ export const PromptInputTabBody = ({ className, ...props }: PromptInputTabBodyProps) => (
1126
+ <div className={cn("space-y-1", className)} {...props} />
1127
+ );
1128
+
1129
+ export type PromptInputTabItemProps = HTMLAttributes<HTMLDivElement>;
1130
+
1131
+ export const PromptInputTabItem = ({ className, ...props }: PromptInputTabItemProps) => (
1132
+ <div
1133
+ className={cn("flex items-center gap-2 px-3 py-2 text-xs hover:bg-accent", className)}
1134
+ {...props}
1135
+ />
1136
+ );
1137
+
1138
+ export type PromptInputCommandProps = ComponentProps<typeof Command>;
1139
+
1140
+ export const PromptInputCommand = ({ className, ...props }: PromptInputCommandProps) => (
1141
+ <Command className={cn(className)} {...props} />
1142
+ );
1143
+
1144
+ export type PromptInputCommandInputProps = ComponentProps<typeof CommandInput>;
1145
+
1146
+ export const PromptInputCommandInput = ({ className, ...props }: PromptInputCommandInputProps) => (
1147
+ <CommandInput className={cn(className)} {...props} />
1148
+ );
1149
+
1150
+ export type PromptInputCommandListProps = ComponentProps<typeof CommandList>;
1151
+
1152
+ export const PromptInputCommandList = ({ className, ...props }: PromptInputCommandListProps) => (
1153
+ <CommandList className={cn(className)} {...props} />
1154
+ );
1155
+
1156
+ export type PromptInputCommandEmptyProps = ComponentProps<typeof CommandEmpty>;
1157
+
1158
+ export const PromptInputCommandEmpty = ({ className, ...props }: PromptInputCommandEmptyProps) => (
1159
+ <CommandEmpty className={cn(className)} {...props} />
1160
+ );
1161
+
1162
+ export type PromptInputCommandGroupProps = ComponentProps<typeof CommandGroup>;
1163
+
1164
+ export const PromptInputCommandGroup = ({ className, ...props }: PromptInputCommandGroupProps) => (
1165
+ <CommandGroup className={cn(className)} {...props} />
1166
+ );
1167
+
1168
+ export type PromptInputCommandItemProps = ComponentProps<typeof CommandItem>;
1169
+
1170
+ export const PromptInputCommandItem = ({ className, ...props }: PromptInputCommandItemProps) => (
1171
+ <CommandItem className={cn(className)} {...props} />
1172
+ );
1173
+
1174
+ export type PromptInputCommandSeparatorProps = ComponentProps<typeof CommandSeparator>;
1175
+
1176
+ export const PromptInputCommandSeparator = ({
1177
+ className,
1178
+ ...props
1179
+ }: PromptInputCommandSeparatorProps) => <CommandSeparator className={cn(className)} {...props} />;