@speakeasy-api/moonshine 1.33.4 → 2.0.0-alpha.2

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 (330) hide show
  1. package/README.md +26 -10
  2. package/package.json +12 -23
  3. package/scripts/generate-utility-docs.js +324 -0
  4. package/src/assets/icons/external/github.svg +3 -0
  5. package/src/assets/icons/external/maven.svg +152 -0
  6. package/src/assets/icons/external/npm.svg +4 -0
  7. package/src/assets/icons/external/nuget.svg +5 -0
  8. package/src/assets/icons/external/packagist.svg +1 -0
  9. package/src/assets/icons/external/pypi.svg +182 -0
  10. package/src/assets/icons/external/rubygems.svg +14 -0
  11. package/src/assets/icons/external/terraform.svg +1 -0
  12. package/src/assets/icons/languages/csharp.svg +1 -0
  13. package/src/assets/icons/languages/go.svg +1 -0
  14. package/src/assets/icons/languages/java.svg +1 -0
  15. package/src/assets/icons/languages/json.svg +2 -0
  16. package/src/assets/icons/languages/php.svg +1 -0
  17. package/src/assets/icons/languages/postman.svg +3 -0
  18. package/src/assets/icons/languages/python.svg +1 -0
  19. package/src/assets/icons/languages/ruby.svg +1 -0
  20. package/src/assets/icons/languages/swift.svg +1 -0
  21. package/src/assets/icons/languages/terraform.svg +1 -0
  22. package/src/assets/icons/languages/typescript.svg +1 -0
  23. package/src/assets/icons/languages/unity.svg +1 -0
  24. package/src/components/AIChat/AIChatContainer.tsx +71 -0
  25. package/src/components/AIChat/AIChatMessage.tsx +135 -0
  26. package/src/components/AIChat/AIChatMessageComposer.tsx +175 -0
  27. package/src/components/AIChat/AIChatMessageList.tsx +34 -0
  28. package/src/components/AIChat/AIChatModelSelector.tsx +159 -0
  29. package/src/components/AIChat/componentsTypes.ts +36 -0
  30. package/src/components/AIChat/context.ts +15 -0
  31. package/src/components/AIChat/index.ts +12 -0
  32. package/src/components/AIChat/parts/AIChatMessageFilePart.tsx +129 -0
  33. package/src/components/AIChat/parts/AIChatMessageReasoningPart.tsx +23 -0
  34. package/src/components/AIChat/parts/AIChatMessageSourcePart.tsx +58 -0
  35. package/src/components/AIChat/parts/AIChatMessageTextPart.tsx +33 -0
  36. package/src/components/AIChat/parts/AIChatMessageToolInvocationPart.tsx +53 -0
  37. package/src/components/AIChat/parts/AIChatMessageToolPart.tsx +395 -0
  38. package/src/components/AIChat/parts/AIChatMessageToolResultPart.tsx +46 -0
  39. package/src/components/AIChat/toolCallApproval.ts +61 -0
  40. package/src/components/AIChat/types.ts +97 -0
  41. package/src/components/ActionBar/index.tsx +184 -0
  42. package/src/components/Alert/index.tsx +118 -0
  43. package/src/components/Alert/types.ts +12 -0
  44. package/src/components/AppLayout/context.tsx +31 -0
  45. package/src/components/AppLayout/index.tsx +550 -0
  46. package/src/components/AppLayout/provider.tsx +40 -0
  47. package/src/components/AppLayout/useAppLayoutKeys.ts +26 -0
  48. package/src/components/Badge/index.tsx +227 -0
  49. package/src/components/Button/index.tsx +531 -0
  50. package/src/components/Card/index.tsx +193 -0
  51. package/src/components/CodeEditorLayout/index.tsx +394 -0
  52. package/src/components/CodeEditorLayout/styles.module.css +8 -0
  53. package/src/components/CodeHighlight/Pre.tsx +63 -0
  54. package/src/components/CodePlayground/index.tsx +411 -0
  55. package/src/components/CodeSnippet/codeSnippet.css +97 -0
  56. package/src/components/CodeSnippet/index.tsx +224 -0
  57. package/src/components/Combobox/index.tsx +193 -0
  58. package/src/components/Command/index.tsx +152 -0
  59. package/src/components/Container/index.tsx +31 -0
  60. package/src/components/ContextDropdown/index.tsx +150 -0
  61. package/src/components/Dialog/index.tsx +123 -0
  62. package/src/components/DragNDrop/DragNDropArea.tsx +30 -0
  63. package/src/components/DragNDrop/DragOverlay.tsx +4 -0
  64. package/src/components/DragNDrop/Draggable.tsx +97 -0
  65. package/src/components/DragNDrop/Droppable.tsx +51 -0
  66. package/src/components/Dropdown/index.tsx +201 -0
  67. package/src/components/ExternalPill/index.tsx +58 -0
  68. package/src/components/Facepile/index.tsx +309 -0
  69. package/src/components/GradientCircle/gradientCircle.css +34 -0
  70. package/src/components/GradientCircle/index.tsx +143 -0
  71. package/src/components/Grid/index.tsx +150 -0
  72. package/src/components/Heading/index.tsx +54 -0
  73. package/src/components/HighlightedText/index.tsx +152 -0
  74. package/src/components/Icon/customIcons/createCustomLucideIcon.ts +25 -0
  75. package/src/components/Icon/customIcons/gems.ts +26 -0
  76. package/{dist/go-DsW1bFpz.mjs → src/components/Icon/customIcons/go.ts} +21 -19
  77. package/src/components/Icon/customIcons/index.ts +11 -0
  78. package/{dist/maven-Dub5liK1.mjs → src/components/Icon/customIcons/maven.ts} +17 -15
  79. package/src/components/Icon/customIcons/npm.ts +19 -0
  80. package/{dist/nuget-D86y5HDl.mjs → src/components/Icon/customIcons/nuget.ts} +17 -15
  81. package/src/components/Icon/customIcons/packagist.ts +124 -0
  82. package/{dist/pypi-2SUX-2OR.mjs → src/components/Icon/customIcons/pypi.ts} +16 -14
  83. package/src/components/Icon/index.tsx +83 -0
  84. package/src/components/Icon/isIconName.ts +10 -0
  85. package/src/components/Icon/names.ts +14 -0
  86. package/src/components/IconButton/index.tsx +51 -0
  87. package/src/components/Input/index.tsx +98 -0
  88. package/src/components/KeyHint/index.tsx +118 -0
  89. package/src/components/LanguageIndicator/index.tsx +68 -0
  90. package/src/components/Link/index.tsx +153 -0
  91. package/src/components/LoggedInUserMenu/index.tsx +116 -0
  92. package/src/components/Logo/Animated.tsx +191 -0
  93. package/src/components/Logo/index.tsx +17 -0
  94. package/src/components/Logo/speakeasy-logo.riv +0 -0
  95. package/src/components/Logo/svgs/index.tsx +126 -0
  96. package/src/components/Modal/index.tsx +104 -0
  97. package/src/components/PageHeader/index.tsx +227 -0
  98. package/src/components/PageHeader/styles.module.css +27 -0
  99. package/src/components/Popover/index.tsx +35 -0
  100. package/src/components/PromptInput/index.tsx +372 -0
  101. package/src/components/PullRequestLink/index.tsx +64 -0
  102. package/src/components/ResizablePanel/index.tsx +119 -0
  103. package/src/components/Score/index.module.css +32 -0
  104. package/src/components/Score/index.tsx +268 -0
  105. package/src/components/ScrollArea/index.tsx +48 -0
  106. package/src/components/SegmentedButton/index.module.css +19 -0
  107. package/src/components/SegmentedButton/index.tsx +101 -0
  108. package/src/components/Select/index.tsx +159 -0
  109. package/src/components/Separator/index.tsx +23 -0
  110. package/src/components/Skeleton/index.tsx +61 -0
  111. package/src/components/Skeleton/skeleton.css +52 -0
  112. package/src/components/Stack/index.tsx +137 -0
  113. package/src/components/Subnav/index.tsx +315 -0
  114. package/src/components/Switch/index.tsx +29 -0
  115. package/src/components/Table/context/context.tsx +19 -0
  116. package/src/components/Table/context/tableProvider.tsx +39 -0
  117. package/src/components/Table/index.tsx +707 -0
  118. package/src/components/Table/styles.module.css +25 -0
  119. package/src/components/Tabs/index.tsx +87 -0
  120. package/src/components/TargetLanguageIcon/index.tsx +84 -0
  121. package/src/components/Text/index.tsx +59 -0
  122. package/src/components/ThemeSwitcher/index.tsx +118 -0
  123. package/src/components/Timeline/index.tsx +290 -0
  124. package/src/components/Tooltip/index.tsx +41 -0
  125. package/src/components/UserAvatar/index.tsx +87 -0
  126. package/src/components/UserAvatar/sizeMap.ts +12 -0
  127. package/src/components/Wizard/index.tsx +208 -0
  128. package/src/components/Wizard/types.ts +17 -0
  129. package/src/components/WorkspaceSelector/CreateOrg.tsx +95 -0
  130. package/src/components/WorkspaceSelector/CreateWorkspace.tsx +196 -0
  131. package/src/components/WorkspaceSelector/OrgList.tsx +115 -0
  132. package/src/components/WorkspaceSelector/OrgSelector.tsx +207 -0
  133. package/src/components/WorkspaceSelector/RecentWorkspaces.tsx +83 -0
  134. package/src/components/WorkspaceSelector/ScrollingList.tsx +84 -0
  135. package/src/components/WorkspaceSelector/SearchBox.tsx +40 -0
  136. package/src/components/WorkspaceSelector/WorkspaceItem.tsx +37 -0
  137. package/src/components/WorkspaceSelector/WorkspaceList.tsx +107 -0
  138. package/src/components/WorkspaceSelector/index.tsx +400 -0
  139. package/src/components/WorkspaceSelector/styles.css +74 -0
  140. package/src/components/__beta__/CLIWizard/index.tsx +357 -0
  141. package/src/components/__beta__/CLIWizard/terminal-command.tsx +108 -0
  142. package/src/components/__beta__/CLIWizard/terminal.tsx +83 -0
  143. package/src/components/__beta__/README.md +3 -0
  144. package/src/components/index.mdx +38 -0
  145. package/src/context/ConfigContext.tsx +43 -0
  146. package/src/context/ModalContext.tsx +118 -0
  147. package/src/context/theme.ts +1 -0
  148. package/src/hooks/useAppLayout.ts +10 -0
  149. package/src/hooks/useConfig.ts +10 -0
  150. package/src/hooks/useIsMounted.ts +13 -0
  151. package/src/hooks/useModal.tsx +10 -0
  152. package/src/hooks/useTailwindBreakpoint.ts +47 -0
  153. package/src/hooks/useTheme.ts +13 -0
  154. package/src/index.ts +234 -0
  155. package/src/lib/assert.ts +9 -0
  156. package/src/lib/codeUtils.ts +177 -0
  157. package/src/lib/debounce.ts +9 -0
  158. package/src/lib/responsiveMappers.ts +69 -0
  159. package/src/lib/responsiveUtils.ts +23 -0
  160. package/src/lib/storybookUtils.tsx +26 -0
  161. package/src/lib/typeUtils.ts +109 -0
  162. package/src/lib/utils.ts +85 -0
  163. package/src/styles/codeSyntax.css +59 -0
  164. package/src/styles/globals.css +51 -0
  165. package/src/types.ts +200 -0
  166. package/src/vite-env.d.ts +6 -0
  167. package/types/utilities.d.ts +1 -1
  168. package/dist/components/AIChat/AIChatContainer.d.ts +0 -26
  169. package/dist/components/AIChat/AIChatMessage.d.ts +0 -19
  170. package/dist/components/AIChat/AIChatMessageComposer.d.ts +0 -22
  171. package/dist/components/AIChat/AIChatMessageList.d.ts +0 -6
  172. package/dist/components/AIChat/AIChatModelSelector.d.ts +0 -14
  173. package/dist/components/AIChat/componentsTypes.d.ts +0 -11
  174. package/dist/components/AIChat/context.d.ts +0 -3
  175. package/dist/components/AIChat/index.d.ts +0 -12
  176. package/dist/components/AIChat/parts/AIChatMessageFilePart.d.ts +0 -7
  177. package/dist/components/AIChat/parts/AIChatMessageReasoningPart.d.ts +0 -5
  178. package/dist/components/AIChat/parts/AIChatMessageSourcePart.d.ts +0 -9
  179. package/dist/components/AIChat/parts/AIChatMessageTextPart.d.ts +0 -5
  180. package/dist/components/AIChat/parts/AIChatMessageToolInvocationPart.d.ts +0 -6
  181. package/dist/components/AIChat/parts/AIChatMessageToolPart.d.ts +0 -33
  182. package/dist/components/AIChat/parts/AIChatMessageToolResultPart.d.ts +0 -5
  183. package/dist/components/AIChat/toolCallApproval.d.ts +0 -15
  184. package/dist/components/AIChat/types.d.ts +0 -79
  185. package/dist/components/ActionBar/index.d.ts +0 -36
  186. package/dist/components/Alert/index.d.ts +0 -18
  187. package/dist/components/Alert/types.d.ts +0 -4
  188. package/dist/components/AppLayout/context.d.ts +0 -16
  189. package/dist/components/AppLayout/index.d.ts +0 -131
  190. package/dist/components/AppLayout/provider.d.ts +0 -8
  191. package/dist/components/AppLayout/useAppLayoutKeys.d.ts +0 -1
  192. package/dist/components/Badge/index.d.ts +0 -21
  193. package/dist/components/Button/index.d.ts +0 -22
  194. package/dist/components/Card/index.d.ts +0 -47
  195. package/dist/components/CodeEditorLayout/index.d.ts +0 -101
  196. package/dist/components/CodeHighlight/Pre.d.ts +0 -8
  197. package/dist/components/CodePlayground/index.d.ts +0 -102
  198. package/dist/components/CodeSnippet/index.d.ts +0 -49
  199. package/dist/components/Combobox/index.d.ts +0 -35
  200. package/dist/components/Command/index.d.ts +0 -80
  201. package/dist/components/Container/index.d.ts +0 -9
  202. package/dist/components/ContextDropdown/index.d.ts +0 -7
  203. package/dist/components/Dialog/index.d.ts +0 -21
  204. package/dist/components/DragNDrop/DragNDropArea.d.ts +0 -8
  205. package/dist/components/DragNDrop/DragOverlay.d.ts +0 -1
  206. package/dist/components/DragNDrop/Draggable.d.ts +0 -29
  207. package/dist/components/DragNDrop/Droppable.d.ts +0 -28
  208. package/dist/components/Dropdown/index.d.ts +0 -27
  209. package/dist/components/ExternalPill/index.d.ts +0 -12
  210. package/dist/components/Facepile/index.d.ts +0 -16
  211. package/dist/components/GradientCircle/index.d.ts +0 -10
  212. package/dist/components/Grid/index.d.ts +0 -80
  213. package/dist/components/Heading/index.d.ts +0 -12
  214. package/dist/components/HighlightedText/index.d.ts +0 -19
  215. package/dist/components/Icon/customIcons/createCustomLucideIcon.d.ts +0 -3
  216. package/dist/components/Icon/customIcons/gems.d.ts +0 -2
  217. package/dist/components/Icon/customIcons/go.d.ts +0 -2
  218. package/dist/components/Icon/customIcons/index.d.ts +0 -10
  219. package/dist/components/Icon/customIcons/maven.d.ts +0 -2
  220. package/dist/components/Icon/customIcons/npm.d.ts +0 -2
  221. package/dist/components/Icon/customIcons/nuget.d.ts +0 -2
  222. package/dist/components/Icon/customIcons/packagist.d.ts +0 -2
  223. package/dist/components/Icon/customIcons/pypi.d.ts +0 -2
  224. package/dist/components/Icon/index.d.ts +0 -10
  225. package/dist/components/Icon/isIconName.d.ts +0 -2
  226. package/dist/components/Icon/names.d.ts +0 -6
  227. package/dist/components/IconButton/index.d.ts +0 -14
  228. package/dist/components/Input/index.d.ts +0 -8
  229. package/dist/components/KeyHint/index.d.ts +0 -16
  230. package/dist/components/LanguageIndicator/index.d.ts +0 -7
  231. package/dist/components/Link/index.d.ts +0 -15
  232. package/dist/components/LoggedInUserMenu/index.d.ts +0 -17
  233. package/dist/components/Logo/Animated.d.ts +0 -7
  234. package/dist/components/Logo/index.d.ts +0 -7
  235. package/dist/components/Logo/svgs/index.d.ts +0 -6
  236. package/dist/components/Modal/index.d.ts +0 -8
  237. package/dist/components/PageHeader/index.d.ts +0 -45
  238. package/dist/components/Popover/index.d.ts +0 -8
  239. package/dist/components/PromptInput/index.d.ts +0 -55
  240. package/dist/components/PullRequestLink/index.d.ts +0 -10
  241. package/dist/components/ResizablePanel/index.d.ts +0 -26
  242. package/dist/components/Score/index.d.ts +0 -37
  243. package/dist/components/ScrollArea/index.d.ts +0 -5
  244. package/dist/components/SegmentedButton/index.d.ts +0 -23
  245. package/dist/components/Select/index.d.ts +0 -13
  246. package/dist/components/Separator/index.d.ts +0 -6
  247. package/dist/components/Skeleton/index.d.ts +0 -27
  248. package/dist/components/Stack/index.d.ts +0 -33
  249. package/dist/components/Subnav/index.d.ts +0 -12
  250. package/dist/components/Switch/index.d.ts +0 -4
  251. package/dist/components/Table/context/context.d.ts +0 -8
  252. package/dist/components/Table/context/tableProvider.d.ts +0 -6
  253. package/dist/components/Table/index.d.ts +0 -94
  254. package/dist/components/Tabs/index.d.ts +0 -21
  255. package/dist/components/TargetLanguageIcon/index.d.ts +0 -7
  256. package/dist/components/Text/index.d.ts +0 -19
  257. package/dist/components/ThemeSwitcher/index.d.ts +0 -6
  258. package/dist/components/Timeline/index.d.ts +0 -49
  259. package/dist/components/Tooltip/index.d.ts +0 -9
  260. package/dist/components/UserAvatar/index.d.ts +0 -9
  261. package/dist/components/UserAvatar/sizeMap.d.ts +0 -3
  262. package/dist/components/Wizard/index.d.ts +0 -19
  263. package/dist/components/Wizard/types.d.ts +0 -15
  264. package/dist/components/WorkspaceSelector/CreateOrg.d.ts +0 -6
  265. package/dist/components/WorkspaceSelector/CreateWorkspace.d.ts +0 -17
  266. package/dist/components/WorkspaceSelector/OrgList.d.ts +0 -12
  267. package/dist/components/WorkspaceSelector/OrgSelector.d.ts +0 -13
  268. package/dist/components/WorkspaceSelector/RecentWorkspaces.d.ts +0 -11
  269. package/dist/components/WorkspaceSelector/ScrollingList.d.ts +0 -21
  270. package/dist/components/WorkspaceSelector/SearchBox.d.ts +0 -9
  271. package/dist/components/WorkspaceSelector/WorkspaceItem.d.ts +0 -9
  272. package/dist/components/WorkspaceSelector/WorkspaceList.d.ts +0 -11
  273. package/dist/components/WorkspaceSelector/index.d.ts +0 -36
  274. package/dist/components/__beta__/CLIWizard/index.d.ts +0 -19
  275. package/dist/components/__beta__/CLIWizard/terminal-command.d.ts +0 -19
  276. package/dist/components/__beta__/CLIWizard/terminal.d.ts +0 -26
  277. package/dist/context/ConfigContext.d.ts +0 -18
  278. package/dist/context/ModalContext.d.ts +0 -22
  279. package/dist/context/theme.d.ts +0 -1
  280. package/dist/createCustomLucideIcon-CatlpFc0.mjs +0 -19
  281. package/dist/createCustomLucideIcon-CatlpFc0.mjs.map +0 -1
  282. package/dist/gems-DQ7pOLLr.mjs +0 -24
  283. package/dist/gems-DQ7pOLLr.mjs.map +0 -1
  284. package/dist/github-kgjMtfE7.mjs +0 -11
  285. package/dist/github-kgjMtfE7.mjs.map +0 -1
  286. package/dist/go-DsW1bFpz.mjs.map +0 -1
  287. package/dist/hooks/useAppLayout.d.ts +0 -1
  288. package/dist/hooks/useConfig.d.ts +0 -2
  289. package/dist/hooks/useIsMounted.d.ts +0 -1
  290. package/dist/hooks/useModal.d.ts +0 -11
  291. package/dist/hooks/useTailwindBreakpoint.d.ts +0 -3
  292. package/dist/hooks/useTheme.d.ts +0 -6
  293. package/dist/index-C9bJtuJ5.mjs +0 -16347
  294. package/dist/index-C9bJtuJ5.mjs.map +0 -1
  295. package/dist/index.d.ts +0 -80
  296. package/dist/lib/assert.d.ts +0 -2
  297. package/dist/lib/codeUtils.d.ts +0 -36
  298. package/dist/lib/debounce.d.ts +0 -1
  299. package/dist/lib/responsiveMappers.d.ts +0 -10
  300. package/dist/lib/responsiveUtils.d.ts +0 -3
  301. package/dist/lib/storybookUtils.d.ts +0 -5
  302. package/dist/lib/typeUtils.d.ts +0 -24
  303. package/dist/lib/utils.d.ts +0 -24
  304. package/dist/maven-Dub5liK1.mjs.map +0 -1
  305. package/dist/maven-W_nkSDNW.mjs +0 -107
  306. package/dist/maven-W_nkSDNW.mjs.map +0 -1
  307. package/dist/moonshine.es.js +0 -125
  308. package/dist/moonshine.es.js.map +0 -1
  309. package/dist/npm-BWTcVvFH.mjs +0 -11
  310. package/dist/npm-BWTcVvFH.mjs.map +0 -1
  311. package/dist/npm-BYcG5_q9.mjs +0 -17
  312. package/dist/npm-BYcG5_q9.mjs.map +0 -1
  313. package/dist/nuget-CV5HU1JR.mjs +0 -11
  314. package/dist/nuget-CV5HU1JR.mjs.map +0 -1
  315. package/dist/nuget-D86y5HDl.mjs.map +0 -1
  316. package/dist/packagist-BFSSrw4p.mjs +0 -118
  317. package/dist/packagist-BFSSrw4p.mjs.map +0 -1
  318. package/dist/packagist-D01fn9N_.mjs +0 -11
  319. package/dist/packagist-D01fn9N_.mjs.map +0 -1
  320. package/dist/pypi-2SUX-2OR.mjs.map +0 -1
  321. package/dist/pypi-DLh6kIJe.mjs +0 -11
  322. package/dist/pypi-DLh6kIJe.mjs.map +0 -1
  323. package/dist/rubygems-DeiNjcDV.mjs +0 -11
  324. package/dist/rubygems-DeiNjcDV.mjs.map +0 -1
  325. package/dist/speakeasy-logo-ByBTXLWb.mjs +0 -5
  326. package/dist/speakeasy-logo-ByBTXLWb.mjs.map +0 -1
  327. package/dist/style.css +0 -1
  328. package/dist/terraform-C4aktQ0o.mjs +0 -11
  329. package/dist/terraform-C4aktQ0o.mjs.map +0 -1
  330. package/dist/types.d.ts +0 -85
@@ -0,0 +1,224 @@
1
+ import { useCallback, useState, useEffect, useRef } from 'react'
2
+ import { cn } from '../../lib/utils'
3
+ import { ProgrammingLanguage, Size } from '../../types'
4
+ import { AnimatePresence, motion } from 'motion/react'
5
+ import '../../styles/codeSyntax.css'
6
+ import './codeSnippet.css'
7
+ import { Icon } from '../Icon'
8
+ import {
9
+ highlightCode,
10
+ HighlightedCode,
11
+ LIGHT_THEME,
12
+ DARK_THEME,
13
+ } from '../../lib/codeUtils'
14
+ import { useConfig } from '../../hooks/useConfig'
15
+ import { Pre } from '../CodeHighlight/Pre'
16
+
17
+ export interface CodeSnippetProps {
18
+ /**
19
+ * The code to display.
20
+ */
21
+ code: string
22
+ /**
23
+ * Whether to show a copy button.
24
+ */
25
+ copyable?: boolean
26
+ /**
27
+ * One of the known Speakeasy target languages, or a language that Shiki supports.
28
+ * The full list of supported languages is available at https://shiki.style/languages
29
+ */
30
+ language: ProgrammingLanguage | string
31
+ /**
32
+ * The symbol to display before the code.
33
+ */
34
+ promptSymbol?: React.ReactNode
35
+ /**
36
+ * Whether to display the code snippet inline.
37
+ */
38
+ inline?: boolean
39
+ /**
40
+ * The font size of the code snippet.
41
+ */
42
+ fontSize?: Size
43
+ /**
44
+ * Whether to show line numbers.
45
+ */
46
+ showLineNumbers?: boolean
47
+ /**
48
+ * The callback to call when the code is selected or copied.
49
+ */
50
+ onSelectOrCopy?: () => void
51
+ /**
52
+ * Whether to shimmer the code snippet.
53
+ */
54
+ shimmer?: boolean
55
+ /**
56
+ * Additional CSS classes to apply to the code snippet container
57
+ */
58
+ className?: string
59
+
60
+ /**
61
+ * Additional CSS classes to apply to the code snippet inner container (e.g the Pre component).
62
+ */
63
+ snippetClassName?: string
64
+ }
65
+
66
+ const fontSizeMap: Record<Size, string> = {
67
+ small: 'text-sm',
68
+ medium: 'text-sm',
69
+ large: 'text-base',
70
+ xl: 'text-lg',
71
+ '2xl': 'text-xl',
72
+ }
73
+
74
+ const copyIconVariants = {
75
+ hidden: { opacity: 0, scale: 0.5 },
76
+ visible: { opacity: 1, scale: 1 },
77
+ }
78
+
79
+ export function CodeSnippet({
80
+ code,
81
+ copyable = false,
82
+ language,
83
+ promptSymbol,
84
+ inline = false,
85
+ fontSize = 'medium',
86
+ onSelectOrCopy,
87
+ shimmer = false,
88
+ className,
89
+ snippetClassName,
90
+ showLineNumbers = false,
91
+ }: CodeSnippetProps) {
92
+ const [copying, setCopying] = useState(false)
93
+ const [containerWidth, setContainerWidth] = useState(0)
94
+ const containerRef = useRef<HTMLDivElement>(null)
95
+
96
+ useEffect(() => {
97
+ const updateWidth = () => {
98
+ if (containerRef.current) {
99
+ const width = containerRef.current.getBoundingClientRect().width
100
+ // Only update if we have a non-zero width
101
+ if (width > 0) {
102
+ setContainerWidth(width)
103
+ }
104
+ }
105
+ }
106
+
107
+ // Initial measurement
108
+ updateWidth()
109
+
110
+ // Create ResizeObserver for more reliable width tracking
111
+ const resizeObserver = new ResizeObserver(updateWidth)
112
+ if (containerRef.current) {
113
+ resizeObserver.observe(containerRef.current)
114
+ }
115
+
116
+ return () => resizeObserver.disconnect()
117
+ }, [])
118
+
119
+ const [highlightedCodeState, setHighlightedCodeState] = useState<
120
+ HighlightedCode | undefined
121
+ >(undefined)
122
+ const isMultiline = code.split('\n').length > 1
123
+ const { theme } = useConfig()
124
+
125
+ // Directly highlight the code when code or language changes
126
+ useEffect(() => {
127
+ if (!language) return
128
+
129
+ const shikiTheme = theme === 'dark' ? DARK_THEME : LIGHT_THEME
130
+ // Use the highlightCode utility directly
131
+ highlightCode(code, language, shikiTheme).then((highlighted) => {
132
+ setHighlightedCodeState(highlighted)
133
+ })
134
+ }, [code, language, theme])
135
+
136
+ const handleCopy = useCallback(() => {
137
+ setCopying(true)
138
+ navigator.clipboard.writeText(highlightedCodeState?.code ?? code)
139
+ setTimeout(() => {
140
+ setCopying(false)
141
+ onSelectOrCopy?.()
142
+ }, 1000)
143
+ }, [highlightedCodeState?.code, code])
144
+
145
+ const handleBeforeInput = (event: React.KeyboardEvent<HTMLPreElement>) =>
146
+ event.preventDefault()
147
+
148
+ return (
149
+ <div
150
+ data-theme={theme}
151
+ className={cn(
152
+ 'border-muted snippet bg-card relative box-border flex w-full overflow-hidden rounded-lg border',
153
+ inline && 'inline-flex',
154
+ shimmer && 'shimmer',
155
+ className
156
+ )}
157
+ style={{ '--width': `${containerWidth}px` } as React.CSSProperties}
158
+ ref={containerRef}
159
+ >
160
+ <div className="snippet-inner bg-card flex w-full flex-row gap-2 rounded-lg p-4">
161
+ {language === 'bash' && (
162
+ <div className="text-body self-center font-mono font-light select-none">
163
+ {promptSymbol ?? '$'}
164
+ </div>
165
+ )}
166
+ {highlightedCodeState && (
167
+ <Pre
168
+ code={highlightedCodeState}
169
+ onClick={onSelectOrCopy}
170
+ className={cn(
171
+ 'highlighted-code inline-flex w-fit self-center font-mono outline-none',
172
+ fontSizeMap[fontSize],
173
+ isMultiline && 'min-w-32',
174
+ snippetClassName
175
+ )}
176
+ onBeforeInput={handleBeforeInput}
177
+ showLineNumbers={showLineNumbers}
178
+ />
179
+ )}
180
+
181
+ {copyable && (
182
+ <div
183
+ className={cn(
184
+ 'mr-1 ml-auto flex self-center text-white',
185
+ isMultiline && 'mt-1 h-4 w-6 self-start'
186
+ )}
187
+ >
188
+ <button
189
+ role="button"
190
+ aria-label="copy"
191
+ className="relative ml-2 border-none bg-transparent outline-none"
192
+ onClick={handleCopy}
193
+ >
194
+ <AnimatePresence mode="wait" initial={false}>
195
+ {copying ? (
196
+ <motion.span
197
+ key="checkmark"
198
+ variants={copyIconVariants}
199
+ initial="hidden"
200
+ animate="visible"
201
+ className="text-green-500"
202
+ >
203
+ <Icon name="check" stroke="currentColor" />
204
+ </motion.span>
205
+ ) : (
206
+ <motion.span
207
+ key="copy"
208
+ variants={copyIconVariants}
209
+ initial="hidden"
210
+ animate="visible"
211
+ className="text-body-muted hover:text-body"
212
+ exit="hidden"
213
+ >
214
+ <Icon name="copy" stroke="currentColor" />
215
+ </motion.span>
216
+ )}
217
+ </AnimatePresence>
218
+ </button>
219
+ </div>
220
+ )}
221
+ </div>
222
+ </div>
223
+ )
224
+ }
@@ -0,0 +1,193 @@
1
+ import * as React from 'react'
2
+ import { Virtuoso } from 'react-virtuoso'
3
+ import { cn } from '../../lib/utils'
4
+ import { Button } from '../Button'
5
+ import {
6
+ Command,
7
+ CommandGroup,
8
+ CommandInput,
9
+ CommandItem,
10
+ CommandList,
11
+ } from '../Command'
12
+ import { Popover, PopoverContent, PopoverTrigger } from '../Popover'
13
+ import { ButtonProps } from '../Button'
14
+ import { Icon } from '../Icon'
15
+
16
+ // I don't like that these aren't based on REM but I'm not sure how to fix it right now
17
+ const COMBOBOX_CONFIG = {
18
+ heights: {
19
+ row: 32,
20
+ header: 28,
21
+ padding: 8,
22
+ max: 300,
23
+ },
24
+ } as const
25
+
26
+ export interface ComboboxOption<T extends string = string> {
27
+ value: T
28
+ label: string
29
+ disabled?: boolean
30
+ }
31
+
32
+ export interface ComboboxGroup<T extends string = string> {
33
+ label: string
34
+ options: ComboboxOption<T>[]
35
+ }
36
+
37
+ type ComboboxDataProps<T extends string = string> =
38
+ | { options: ComboboxOption<T>[]; groups?: never }
39
+ | { options?: never; groups: ComboboxGroup<T>[] }
40
+
41
+ interface ComboboxBaseProps<T extends string = string> {
42
+ value: T
43
+ onValueChange: (value: T | undefined) => void
44
+ variant?: ButtonProps['variant']
45
+ size?: ButtonProps['size']
46
+ disabled?: boolean
47
+ loading?: boolean
48
+ error?: boolean
49
+ errorText?: string
50
+ searchable?: boolean
51
+ placeholder?: string
52
+ emptyText?: string
53
+ searchPlaceholder?: string
54
+ iconOnly?: boolean
55
+ }
56
+
57
+ export type ComboboxProps<T extends string = string> = ComboboxBaseProps<T> &
58
+ ComboboxDataProps<T>
59
+
60
+ export function Combobox<T extends string = string>({
61
+ options,
62
+ groups,
63
+ value,
64
+ onValueChange,
65
+ variant = 'secondary',
66
+ size = 'md',
67
+ disabled,
68
+ loading,
69
+ error,
70
+ errorText = 'An error occurred',
71
+ searchable = true,
72
+ placeholder = 'Select option...',
73
+ emptyText = 'No option found.',
74
+ searchPlaceholder = 'Search...',
75
+ iconOnly = false,
76
+ }: ComboboxProps<T>) {
77
+ const [open, setOpen] = React.useState(false)
78
+ const [search, setSearch] = React.useState('')
79
+
80
+ const allOptions = React.useMemo(() => {
81
+ if (options) return options
82
+ if (groups) return groups.flatMap((group) => group.options)
83
+ return []
84
+ }, [options, groups])
85
+
86
+ // TODO: Make the search more efficient and fuzzier
87
+ const filteredItems = React.useMemo(() => {
88
+ const items = groups || (options ? [{ label: '', options }] : [])
89
+ if (!search) return items
90
+
91
+ return items
92
+ .map((group) => ({
93
+ label: group.label,
94
+ options: group.options.filter((option) =>
95
+ option.label.toLowerCase().includes(search.toLowerCase())
96
+ ),
97
+ }))
98
+ .filter((group) => group.options.length > 0)
99
+ }, [search, options, groups])
100
+
101
+ const virtuosoHeight = React.useMemo(() => {
102
+ const { row, header, padding, max } = COMBOBOX_CONFIG.heights
103
+ const shouldShowHeaders = filteredItems.some((group) => group.label)
104
+ const headerHeight = shouldShowHeaders ? filteredItems.length * header : 0
105
+ const contentHeight = filteredItems.reduce(
106
+ (sum, group) => sum + group.options.length * row,
107
+ headerHeight
108
+ )
109
+
110
+ return Math.min(contentHeight + padding, max)
111
+ }, [filteredItems])
112
+
113
+ const handleSelect = React.useCallback(
114
+ (currentValue: string) => {
115
+ const newValue = currentValue === value ? undefined : (currentValue as T)
116
+ onValueChange?.(newValue)
117
+ setOpen(false)
118
+ setSearch('')
119
+ },
120
+ [value, onValueChange]
121
+ )
122
+
123
+ const selectedOption = allOptions.find((option) => option.value === value)
124
+
125
+ return (
126
+ <Popover open={open} onOpenChange={disabled ? undefined : setOpen}>
127
+ <PopoverTrigger asChild>
128
+ <Button
129
+ variant={variant}
130
+ size={size}
131
+ disabled={disabled}
132
+ aria-expanded={open}
133
+ >
134
+ {loading ? (
135
+ <div className="h-4 w-4 animate-spin">
136
+ <Icon name="loader-circle" />
137
+ </div>
138
+ ) : (
139
+ <div className="h-4 w-4 shrink-0 opacity-50">
140
+ <Icon name="chevrons-up-down" />
141
+ </div>
142
+ )}
143
+ {!iconOnly && <span>{selectedOption?.label || placeholder}</span>}
144
+ </Button>
145
+ </PopoverTrigger>
146
+ <PopoverContent className="w-[200px] p-0">
147
+ <Command shouldFilter={false}>
148
+ {searchable && (
149
+ <CommandInput
150
+ value={search}
151
+ onValueChange={setSearch}
152
+ placeholder={searchPlaceholder}
153
+ />
154
+ )}
155
+ <CommandList>
156
+ {error ? (
157
+ <CommandItem disabled>{errorText}</CommandItem>
158
+ ) : filteredItems.length === 0 ? (
159
+ <CommandItem disabled>{emptyText}</CommandItem>
160
+ ) : (
161
+ <Virtuoso
162
+ style={{ height: virtuosoHeight }}
163
+ data={filteredItems}
164
+ itemContent={(_, group) => (
165
+ <CommandGroup heading={group.label}>
166
+ {group.options.map((option) => (
167
+ <CommandItem
168
+ key={option.value}
169
+ value={option.value}
170
+ onSelect={() => handleSelect(option.value)}
171
+ disabled={option.disabled}
172
+ >
173
+ <div
174
+ className={cn(
175
+ 'mr-2 h-4 w-4',
176
+ value === option.value ? 'opacity-100' : 'opacity-0'
177
+ )}
178
+ >
179
+ <Icon name="check" />
180
+ </div>
181
+ {option.label}
182
+ </CommandItem>
183
+ ))}
184
+ </CommandGroup>
185
+ )}
186
+ />
187
+ )}
188
+ </CommandList>
189
+ </Command>
190
+ </PopoverContent>
191
+ </Popover>
192
+ )
193
+ }
@@ -0,0 +1,152 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { Command as CommandPrimitive } from 'cmdk'
5
+ import { cn } from '../../lib/utils'
6
+ import { Icon } from '../Icon'
7
+ import { DialogContent } from '@radix-ui/react-dialog'
8
+ import { DialogProps } from '@radix-ui/react-dialog'
9
+ import { Dialog } from '../Dialog'
10
+
11
+ const Command = React.forwardRef<
12
+ React.ElementRef<typeof CommandPrimitive>,
13
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive>
14
+ >(({ className, ...props }, ref) => (
15
+ <CommandPrimitive
16
+ ref={ref}
17
+ className={cn(
18
+ 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
19
+ className
20
+ )}
21
+ {...props}
22
+ />
23
+ ))
24
+ Command.displayName = CommandPrimitive.displayName
25
+
26
+ const CommandInput = React.forwardRef<
27
+ React.ElementRef<typeof CommandPrimitive.Input>,
28
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
29
+ >(({ ...props }, ref) => (
30
+ <div className="flex items-center gap-2 border-b px-3" cmdk-input-wrapper="">
31
+ <Icon name="search" />
32
+ <CommandPrimitive.Input
33
+ ref={ref}
34
+ className={cn(
35
+ 'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50'
36
+ )}
37
+ {...props}
38
+ />
39
+ </div>
40
+ ))
41
+
42
+ CommandInput.displayName = CommandPrimitive.Input.displayName
43
+
44
+ const CommandList = React.forwardRef<
45
+ React.ElementRef<typeof CommandPrimitive.List>,
46
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
47
+ >(({ className, ...props }, ref) => (
48
+ <CommandPrimitive.List
49
+ ref={ref}
50
+ className={cn('max-h-[300px] overflow-x-hidden overflow-y-auto', className)}
51
+ {...props}
52
+ />
53
+ ))
54
+
55
+ CommandList.displayName = CommandPrimitive.List.displayName
56
+
57
+ const CommandEmpty = React.forwardRef<
58
+ React.ElementRef<typeof CommandPrimitive.Empty>,
59
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
60
+ >((props, ref) => (
61
+ <CommandPrimitive.Empty
62
+ ref={ref}
63
+ className="py-6 text-center text-sm"
64
+ {...props}
65
+ />
66
+ ))
67
+
68
+ CommandEmpty.displayName = CommandPrimitive.Empty.displayName
69
+
70
+ const CommandGroup = React.forwardRef<
71
+ React.ElementRef<typeof CommandPrimitive.Group>,
72
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
73
+ >(({ className, ...props }, ref) => (
74
+ <CommandPrimitive.Group
75
+ ref={ref}
76
+ className={cn(
77
+ 'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
78
+ className
79
+ )}
80
+ {...props}
81
+ />
82
+ ))
83
+
84
+ CommandGroup.displayName = CommandPrimitive.Group.displayName
85
+
86
+ const CommandDialog = ({ children, ...props }: DialogProps) => {
87
+ return (
88
+ <Dialog {...props}>
89
+ <DialogContent className="overflow-hidden p-0 shadow-lg">
90
+ <Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
91
+ {children}
92
+ </Command>
93
+ </DialogContent>
94
+ </Dialog>
95
+ )
96
+ }
97
+
98
+ const CommandSeparator = React.forwardRef<
99
+ React.ElementRef<typeof CommandPrimitive.Separator>,
100
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
101
+ >(({ className, ...props }, ref) => (
102
+ <CommandPrimitive.Separator
103
+ ref={ref}
104
+ className={cn('bg-border -mx-1 h-px', className)}
105
+ {...props}
106
+ />
107
+ ))
108
+ CommandSeparator.displayName = CommandPrimitive.Separator.displayName
109
+
110
+ const CommandItem = React.forwardRef<
111
+ React.ElementRef<typeof CommandPrimitive.Item>,
112
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
113
+ >(({ className, ...props }, ref) => (
114
+ <CommandPrimitive.Item
115
+ ref={ref}
116
+ className={cn(
117
+ 'data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
118
+ className
119
+ )}
120
+ {...props}
121
+ />
122
+ ))
123
+
124
+ CommandItem.displayName = CommandPrimitive.Item.displayName
125
+
126
+ const CommandShortcut = ({
127
+ className,
128
+ ...props
129
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
130
+ return (
131
+ <span
132
+ className={cn(
133
+ 'text-muted-foreground ml-auto text-xs tracking-widest',
134
+ className
135
+ )}
136
+ {...props}
137
+ />
138
+ )
139
+ }
140
+ CommandShortcut.displayName = 'CommandShortcut'
141
+
142
+ export {
143
+ Command,
144
+ CommandInput,
145
+ CommandList,
146
+ CommandEmpty,
147
+ CommandGroup,
148
+ CommandItem,
149
+ CommandShortcut,
150
+ CommandSeparator,
151
+ CommandDialog,
152
+ }
@@ -0,0 +1,31 @@
1
+ import { paddingMapper } from '../../lib/responsiveMappers'
2
+ import { cn, getResponsiveClasses } from '../../lib/utils'
3
+ import { Padding, ResponsiveValue } from '../../types'
4
+ import { ReactNode } from 'react'
5
+
6
+ export interface ContainerProps {
7
+ children: ReactNode
8
+ flex?: boolean
9
+ padding?: ResponsiveValue<Padding>
10
+ className?: string
11
+ }
12
+
13
+ export function Container({
14
+ children,
15
+ flex = false,
16
+ padding,
17
+ className,
18
+ }: ContainerProps) {
19
+ return (
20
+ <div
21
+ className={cn(
22
+ 'container h-full w-full md:mx-auto',
23
+ flex && 'flex',
24
+ padding && getResponsiveClasses(padding, paddingMapper),
25
+ className
26
+ )}
27
+ >
28
+ {children}
29
+ </div>
30
+ )
31
+ }