@speakeasy-api/moonshine 2.0.0-alpha.1 → 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/LICENSE +21 -0
  2. package/README.md +49 -23
  3. package/package.json +33 -50
  4. package/scripts/generate-utility-docs.js +324 -0
  5. package/src/assets/icons/external/github.svg +3 -0
  6. package/src/assets/icons/external/maven.svg +152 -0
  7. package/src/assets/icons/external/npm.svg +4 -0
  8. package/src/assets/icons/external/nuget.svg +5 -0
  9. package/src/assets/icons/external/packagist.svg +1 -0
  10. package/src/assets/icons/external/pypi.svg +182 -0
  11. package/src/assets/icons/external/rubygems.svg +14 -0
  12. package/src/assets/icons/external/terraform.svg +1 -0
  13. package/src/assets/icons/languages/csharp.svg +1 -0
  14. package/src/assets/icons/languages/go.svg +1 -0
  15. package/src/assets/icons/languages/java.svg +1 -0
  16. package/src/assets/icons/languages/json.svg +2 -0
  17. package/src/assets/icons/languages/php.svg +1 -0
  18. package/src/assets/icons/languages/postman.svg +3 -0
  19. package/src/assets/icons/languages/python.svg +1 -0
  20. package/src/assets/icons/languages/ruby.svg +1 -0
  21. package/src/assets/icons/languages/swift.svg +1 -0
  22. package/src/assets/icons/languages/terraform.svg +1 -0
  23. package/src/assets/icons/languages/typescript.svg +1 -0
  24. package/src/assets/icons/languages/unity.svg +1 -0
  25. package/src/base.css +12 -12
  26. package/src/components/AIChat/AIChatContainer.tsx +71 -0
  27. package/src/components/AIChat/AIChatMessage.tsx +135 -0
  28. package/src/components/AIChat/AIChatMessageComposer.tsx +175 -0
  29. package/src/components/AIChat/AIChatMessageList.tsx +34 -0
  30. package/src/components/AIChat/AIChatModelSelector.tsx +159 -0
  31. package/src/components/AIChat/componentsTypes.ts +36 -0
  32. package/src/components/AIChat/context.ts +15 -0
  33. package/src/components/AIChat/index.ts +12 -0
  34. package/src/components/AIChat/parts/AIChatMessageFilePart.tsx +129 -0
  35. package/src/components/AIChat/parts/AIChatMessageReasoningPart.tsx +23 -0
  36. package/src/components/AIChat/parts/AIChatMessageSourcePart.tsx +58 -0
  37. package/src/components/AIChat/parts/AIChatMessageTextPart.tsx +33 -0
  38. package/src/components/AIChat/parts/AIChatMessageToolInvocationPart.tsx +53 -0
  39. package/src/components/AIChat/parts/AIChatMessageToolPart.tsx +395 -0
  40. package/src/components/AIChat/parts/AIChatMessageToolResultPart.tsx +46 -0
  41. package/src/components/AIChat/toolCallApproval.ts +61 -0
  42. package/src/components/AIChat/types.ts +97 -0
  43. package/src/components/ActionBar/index.tsx +184 -0
  44. package/src/components/Alert/index.tsx +118 -0
  45. package/src/components/Alert/types.ts +12 -0
  46. package/src/components/AppLayout/context.tsx +31 -0
  47. package/src/components/AppLayout/index.tsx +550 -0
  48. package/src/components/AppLayout/provider.tsx +40 -0
  49. package/src/components/AppLayout/useAppLayoutKeys.ts +26 -0
  50. package/src/components/Badge/index.tsx +227 -0
  51. package/src/components/Button/index.tsx +531 -0
  52. package/src/components/Card/index.tsx +193 -0
  53. package/src/components/CodeEditorLayout/index.tsx +394 -0
  54. package/src/components/CodeEditorLayout/styles.module.css +8 -0
  55. package/src/components/CodeHighlight/Pre.tsx +63 -0
  56. package/src/components/CodePlayground/index.tsx +411 -0
  57. package/src/components/CodeSnippet/codeSnippet.css +97 -0
  58. package/src/components/CodeSnippet/index.tsx +224 -0
  59. package/src/components/Combobox/index.tsx +193 -0
  60. package/src/components/Command/index.tsx +152 -0
  61. package/src/components/Container/index.tsx +31 -0
  62. package/src/components/ContextDropdown/index.tsx +150 -0
  63. package/src/components/Dialog/index.tsx +123 -0
  64. package/src/components/DragNDrop/DragNDropArea.tsx +30 -0
  65. package/src/components/DragNDrop/DragOverlay.tsx +4 -0
  66. package/src/components/DragNDrop/Draggable.tsx +97 -0
  67. package/src/components/DragNDrop/Droppable.tsx +51 -0
  68. package/src/components/Dropdown/index.tsx +201 -0
  69. package/src/components/ExternalPill/index.tsx +58 -0
  70. package/src/components/Facepile/index.tsx +309 -0
  71. package/src/components/GradientCircle/gradientCircle.css +34 -0
  72. package/src/components/GradientCircle/index.tsx +143 -0
  73. package/src/components/Grid/index.tsx +150 -0
  74. package/src/components/Heading/index.tsx +54 -0
  75. package/src/components/HighlightedText/index.tsx +152 -0
  76. package/src/components/Icon/customIcons/createCustomLucideIcon.ts +25 -0
  77. package/src/components/Icon/customIcons/gems.ts +26 -0
  78. package/{dist/go-CiWl_aXI.mjs → src/components/Icon/customIcons/go.ts} +21 -19
  79. package/src/components/Icon/customIcons/index.ts +11 -0
  80. package/{dist/maven-DhmnGXoB.mjs → src/components/Icon/customIcons/maven.ts} +17 -15
  81. package/src/components/Icon/customIcons/npm.ts +19 -0
  82. package/{dist/nuget-5a2icRS2.mjs → src/components/Icon/customIcons/nuget.ts} +17 -15
  83. package/src/components/Icon/customIcons/packagist.ts +124 -0
  84. package/{dist/pypi-DsuRYjdK.mjs → src/components/Icon/customIcons/pypi.ts} +16 -14
  85. package/src/components/Icon/index.tsx +83 -0
  86. package/src/components/Icon/isIconName.ts +10 -0
  87. package/src/components/Icon/names.ts +14 -0
  88. package/src/components/IconButton/index.tsx +51 -0
  89. package/src/components/Input/index.tsx +98 -0
  90. package/src/components/KeyHint/index.tsx +118 -0
  91. package/src/components/LanguageIndicator/index.tsx +68 -0
  92. package/src/components/Link/index.tsx +153 -0
  93. package/src/components/LoggedInUserMenu/index.tsx +116 -0
  94. package/src/components/Logo/Animated.tsx +191 -0
  95. package/src/components/Logo/index.tsx +17 -0
  96. package/src/components/Logo/speakeasy-logo.riv +0 -0
  97. package/src/components/Logo/svgs/index.tsx +126 -0
  98. package/src/components/Modal/index.tsx +104 -0
  99. package/src/components/PageHeader/index.tsx +227 -0
  100. package/src/components/PageHeader/styles.module.css +27 -0
  101. package/src/components/Popover/index.tsx +35 -0
  102. package/src/components/PromptInput/index.tsx +372 -0
  103. package/src/components/PullRequestLink/index.tsx +64 -0
  104. package/src/components/ResizablePanel/index.tsx +119 -0
  105. package/src/components/Score/index.module.css +32 -0
  106. package/src/components/Score/index.tsx +268 -0
  107. package/src/components/ScrollArea/index.tsx +48 -0
  108. package/src/components/SegmentedButton/index.module.css +19 -0
  109. package/src/components/SegmentedButton/index.tsx +101 -0
  110. package/src/components/Select/index.tsx +159 -0
  111. package/src/components/Separator/index.tsx +23 -0
  112. package/src/components/Skeleton/index.tsx +61 -0
  113. package/src/components/Skeleton/skeleton.css +52 -0
  114. package/src/components/Stack/index.tsx +137 -0
  115. package/src/components/Subnav/index.tsx +315 -0
  116. package/src/components/Switch/index.tsx +29 -0
  117. package/src/components/Table/context/context.tsx +19 -0
  118. package/src/components/Table/context/tableProvider.tsx +39 -0
  119. package/src/components/Table/index.tsx +707 -0
  120. package/src/components/Table/styles.module.css +25 -0
  121. package/src/components/Tabs/index.tsx +87 -0
  122. package/src/components/TargetLanguageIcon/index.tsx +84 -0
  123. package/src/components/Text/index.tsx +59 -0
  124. package/src/components/ThemeSwitcher/index.tsx +118 -0
  125. package/src/components/Timeline/index.tsx +290 -0
  126. package/src/components/Tooltip/index.tsx +41 -0
  127. package/src/components/UserAvatar/index.tsx +87 -0
  128. package/src/components/UserAvatar/sizeMap.ts +12 -0
  129. package/src/components/Wizard/index.tsx +208 -0
  130. package/src/components/Wizard/types.ts +17 -0
  131. package/src/components/WorkspaceSelector/CreateOrg.tsx +95 -0
  132. package/src/components/WorkspaceSelector/CreateWorkspace.tsx +196 -0
  133. package/src/components/WorkspaceSelector/OrgList.tsx +115 -0
  134. package/src/components/WorkspaceSelector/OrgSelector.tsx +207 -0
  135. package/src/components/WorkspaceSelector/RecentWorkspaces.tsx +83 -0
  136. package/src/components/WorkspaceSelector/ScrollingList.tsx +84 -0
  137. package/src/components/WorkspaceSelector/SearchBox.tsx +40 -0
  138. package/src/components/WorkspaceSelector/WorkspaceItem.tsx +37 -0
  139. package/src/components/WorkspaceSelector/WorkspaceList.tsx +107 -0
  140. package/src/components/WorkspaceSelector/index.tsx +400 -0
  141. package/src/components/WorkspaceSelector/styles.css +74 -0
  142. package/src/components/__beta__/CLIWizard/index.tsx +357 -0
  143. package/src/components/__beta__/CLIWizard/terminal-command.tsx +108 -0
  144. package/src/components/__beta__/CLIWizard/terminal.tsx +83 -0
  145. package/src/components/__beta__/README.md +3 -0
  146. package/src/components/index.mdx +38 -0
  147. package/src/context/ConfigContext.tsx +43 -0
  148. package/src/context/ModalContext.tsx +118 -0
  149. package/src/context/theme.ts +1 -0
  150. package/src/hooks/useAppLayout.ts +10 -0
  151. package/src/hooks/useConfig.ts +10 -0
  152. package/src/hooks/useIsMounted.ts +13 -0
  153. package/src/hooks/useModal.tsx +10 -0
  154. package/src/hooks/useTailwindBreakpoint.ts +47 -0
  155. package/src/hooks/useTheme.ts +13 -0
  156. package/src/index.ts +234 -0
  157. package/src/lib/assert.ts +9 -0
  158. package/src/lib/codeUtils.ts +177 -0
  159. package/src/lib/debounce.ts +9 -0
  160. package/src/lib/responsiveMappers.ts +69 -0
  161. package/src/lib/responsiveUtils.ts +23 -0
  162. package/src/lib/storybookUtils.tsx +26 -0
  163. package/src/lib/typeUtils.ts +109 -0
  164. package/src/lib/utils.ts +85 -0
  165. package/src/styles/codeSyntax.css +59 -0
  166. package/src/styles/globals.css +51 -0
  167. package/src/types.ts +200 -0
  168. package/src/utilities.css +347 -6
  169. package/src/vite-env.d.ts +6 -0
  170. package/types/utilities.d.ts +43 -1
  171. package/dist/components/AIChat/AIChatContainer.d.ts +0 -25
  172. package/dist/components/AIChat/AIChatMessage.d.ts +0 -19
  173. package/dist/components/AIChat/AIChatMessageComposer.d.ts +0 -22
  174. package/dist/components/AIChat/AIChatMessageList.d.ts +0 -6
  175. package/dist/components/AIChat/AIChatModelSelector.d.ts +0 -14
  176. package/dist/components/AIChat/componentsTypes.d.ts +0 -11
  177. package/dist/components/AIChat/context.d.ts +0 -3
  178. package/dist/components/AIChat/index.d.ts +0 -12
  179. package/dist/components/AIChat/parts/AIChatMessageFilePart.d.ts +0 -7
  180. package/dist/components/AIChat/parts/AIChatMessageReasoningPart.d.ts +0 -5
  181. package/dist/components/AIChat/parts/AIChatMessageSourcePart.d.ts +0 -9
  182. package/dist/components/AIChat/parts/AIChatMessageTextPart.d.ts +0 -5
  183. package/dist/components/AIChat/parts/AIChatMessageToolInvocationPart.d.ts +0 -6
  184. package/dist/components/AIChat/parts/AIChatMessageToolPart.d.ts +0 -33
  185. package/dist/components/AIChat/parts/AIChatMessageToolResultPart.d.ts +0 -5
  186. package/dist/components/AIChat/toolCallApproval.d.ts +0 -15
  187. package/dist/components/AIChat/types.d.ts +0 -78
  188. package/dist/components/ActionBar/index.d.ts +0 -36
  189. package/dist/components/Alert/index.d.ts +0 -18
  190. package/dist/components/Alert/types.d.ts +0 -4
  191. package/dist/components/Badge/index.d.ts +0 -10
  192. package/dist/components/Button/index.d.ts +0 -11
  193. package/dist/components/Card/index.d.ts +0 -47
  194. package/dist/components/CodeEditorLayout/index.d.ts +0 -101
  195. package/dist/components/CodePlayground/index.d.ts +0 -108
  196. package/dist/components/CodePlayground/lineNumbers.d.ts +0 -2
  197. package/dist/components/CodePlayground/tokenTransitions.d.ts +0 -2
  198. package/dist/components/CodePlayground/wordWrap.d.ts +0 -2
  199. package/dist/components/CodeSnippet/index.d.ts +0 -50
  200. package/dist/components/Combobox/index.d.ts +0 -35
  201. package/dist/components/Command/index.d.ts +0 -80
  202. package/dist/components/Container/index.d.ts +0 -9
  203. package/dist/components/ContextDropdown/index.d.ts +0 -7
  204. package/dist/components/ContextDropdown/provider.d.ts +0 -22
  205. package/dist/components/ContextDropdown/useModal.d.ts +0 -11
  206. package/dist/components/Dialog/index.d.ts +0 -19
  207. package/dist/components/DragNDrop/DragNDropArea.d.ts +0 -8
  208. package/dist/components/DragNDrop/DragOverlay.d.ts +0 -1
  209. package/dist/components/DragNDrop/Draggable.d.ts +0 -29
  210. package/dist/components/DragNDrop/Droppable.d.ts +0 -28
  211. package/dist/components/Dropdown/index.d.ts +0 -27
  212. package/dist/components/ExternalPill/index.d.ts +0 -12
  213. package/dist/components/Facepile/index.d.ts +0 -16
  214. package/dist/components/GradientCircle/index.d.ts +0 -10
  215. package/dist/components/Grid/index.d.ts +0 -80
  216. package/dist/components/Heading/index.d.ts +0 -12
  217. package/dist/components/HighlightedText/index.d.ts +0 -19
  218. package/dist/components/Icon/customIcons/createCustomLucideIcon.d.ts +0 -3
  219. package/dist/components/Icon/customIcons/gems.d.ts +0 -2
  220. package/dist/components/Icon/customIcons/go.d.ts +0 -2
  221. package/dist/components/Icon/customIcons/index.d.ts +0 -10
  222. package/dist/components/Icon/customIcons/maven.d.ts +0 -2
  223. package/dist/components/Icon/customIcons/npm.d.ts +0 -2
  224. package/dist/components/Icon/customIcons/nuget.d.ts +0 -2
  225. package/dist/components/Icon/customIcons/packagist.d.ts +0 -2
  226. package/dist/components/Icon/customIcons/pypi.d.ts +0 -2
  227. package/dist/components/Icon/index.d.ts +0 -10
  228. package/dist/components/Icon/isIconName.d.ts +0 -2
  229. package/dist/components/Icon/names.d.ts +0 -6
  230. package/dist/components/Input/index.d.ts +0 -8
  231. package/dist/components/KeyHint/index.d.ts +0 -16
  232. package/dist/components/LanguageIndicator/index.d.ts +0 -7
  233. package/dist/components/Link/index.d.ts +0 -19
  234. package/dist/components/LoggedInUserMenu/index.d.ts +0 -17
  235. package/dist/components/Logo/Animated.d.ts +0 -7
  236. package/dist/components/Logo/index.d.ts +0 -7
  237. package/dist/components/Logo/svgs/index.d.ts +0 -6
  238. package/dist/components/Navbar/Slim.d.ts +0 -33
  239. package/dist/components/Navbar/index.d.ts +0 -15
  240. package/dist/components/PageHeader/index.d.ts +0 -45
  241. package/dist/components/Popover/index.d.ts +0 -8
  242. package/dist/components/PromptInput/index.d.ts +0 -55
  243. package/dist/components/PullRequestLink/index.d.ts +0 -10
  244. package/dist/components/ResizablePanel/index.d.ts +0 -26
  245. package/dist/components/Score/index.d.ts +0 -37
  246. package/dist/components/ScrollArea/index.d.ts +0 -5
  247. package/dist/components/Select/index.d.ts +0 -13
  248. package/dist/components/Separator/index.d.ts +0 -6
  249. package/dist/components/Skeleton/index.d.ts +0 -27
  250. package/dist/components/Stack/index.d.ts +0 -33
  251. package/dist/components/Subnav/index.d.ts +0 -12
  252. package/dist/components/Switch/index.d.ts +0 -4
  253. package/dist/components/Table/context/context.d.ts +0 -8
  254. package/dist/components/Table/context/tableProvider.d.ts +0 -6
  255. package/dist/components/Table/index.d.ts +0 -94
  256. package/dist/components/Tabs/index.d.ts +0 -21
  257. package/dist/components/TargetLanguageIcon/index.d.ts +0 -7
  258. package/dist/components/Text/index.d.ts +0 -19
  259. package/dist/components/ThemeSwitcher/index.d.ts +0 -5
  260. package/dist/components/Tooltip/index.d.ts +0 -8
  261. package/dist/components/UserAvatar/index.d.ts +0 -9
  262. package/dist/components/UserAvatar/sizeMap.d.ts +0 -3
  263. package/dist/components/Wizard/index.d.ts +0 -19
  264. package/dist/components/Wizard/types.d.ts +0 -15
  265. package/dist/components/WorkspaceSelector/CreateOrg.d.ts +0 -6
  266. package/dist/components/WorkspaceSelector/CreateWorkspace.d.ts +0 -17
  267. package/dist/components/WorkspaceSelector/OrgList.d.ts +0 -11
  268. package/dist/components/WorkspaceSelector/OrgSelector.d.ts +0 -13
  269. package/dist/components/WorkspaceSelector/RecentWorkspaces.d.ts +0 -11
  270. package/dist/components/WorkspaceSelector/ScrollingList.d.ts +0 -21
  271. package/dist/components/WorkspaceSelector/SearchBox.d.ts +0 -9
  272. package/dist/components/WorkspaceSelector/WorkspaceItem.d.ts +0 -9
  273. package/dist/components/WorkspaceSelector/WorkspaceList.d.ts +0 -10
  274. package/dist/components/WorkspaceSelector/index.d.ts +0 -34
  275. package/dist/components/__beta__/CLIWizard/index.d.ts +0 -21
  276. package/dist/components/__beta__/CLIWizard/terminal-command.d.ts +0 -19
  277. package/dist/components/__beta__/CLIWizard/terminal.d.ts +0 -26
  278. package/dist/context/ConfigContext.d.ts +0 -18
  279. package/dist/context/theme.d.ts +0 -1
  280. package/dist/createCustomLucideIcon-YlrRX5h9.mjs +0 -19
  281. package/dist/createCustomLucideIcon-YlrRX5h9.mjs.map +0 -1
  282. package/dist/gems-BcsO9cXq.mjs +0 -24
  283. package/dist/gems-BcsO9cXq.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-CiWl_aXI.mjs.map +0 -1
  287. package/dist/hooks/useConfig.d.ts +0 -2
  288. package/dist/hooks/useIsMounted.d.ts +0 -1
  289. package/dist/hooks/useTailwindBreakpoint.d.ts +0 -3
  290. package/dist/hooks/useTheme.d.ts +0 -6
  291. package/dist/index-COXZ9O-g.mjs +0 -50882
  292. package/dist/index-COXZ9O-g.mjs.map +0 -1
  293. package/dist/index.d.ts +0 -73
  294. package/dist/lib/assert.d.ts +0 -2
  295. package/dist/lib/codeUtils.d.ts +0 -35
  296. package/dist/lib/debounce.d.ts +0 -1
  297. package/dist/lib/responsiveMappers.d.ts +0 -10
  298. package/dist/lib/responsiveUtils.d.ts +0 -3
  299. package/dist/lib/storybookUtils.d.ts +0 -5
  300. package/dist/lib/typeUtils.d.ts +0 -24
  301. package/dist/lib/utils.d.ts +0 -23
  302. package/dist/lucide-icons-BDw0imyx.mjs +0 -28054
  303. package/dist/lucide-icons-BDw0imyx.mjs.map +0 -1
  304. package/dist/maven-DhmnGXoB.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 -114
  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-CvQ4GKW4.mjs +0 -17
  312. package/dist/npm-CvQ4GKW4.mjs.map +0 -1
  313. package/dist/nuget-5a2icRS2.mjs.map +0 -1
  314. package/dist/nuget-CV5HU1JR.mjs +0 -11
  315. package/dist/nuget-CV5HU1JR.mjs.map +0 -1
  316. package/dist/packagist-CET6q9hi.mjs +0 -118
  317. package/dist/packagist-CET6q9hi.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-DLh6kIJe.mjs +0 -11
  321. package/dist/pypi-DLh6kIJe.mjs.map +0 -1
  322. package/dist/pypi-DsuRYjdK.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 -80
@@ -0,0 +1,83 @@
1
+ 'use client'
2
+
3
+ import { lazy, Suspense } from 'react'
4
+ import { LucideProps } from 'lucide-react'
5
+ import dynamicIconImports from 'lucide-react/dynamicIconImports'
6
+ import { ResponsiveValue, Size } from '../../types'
7
+ import useTailwindBreakpoint from '../../hooks/useTailwindBreakpoint'
8
+ import { resolveSizeForBreakpoint } from '../../lib/responsiveUtils'
9
+
10
+ import customDynamicIconImports from './customIcons'
11
+ import { IconName } from './names'
12
+
13
+ // TODO: Use skeleton
14
+ function Skeleton() {
15
+ return <div />
16
+ }
17
+
18
+ // Skeleton fallback
19
+ const fallback = <Skeleton />
20
+
21
+ type SvgProps = Pick<
22
+ LucideProps,
23
+ | 'stroke'
24
+ | 'strokeWidth'
25
+ | 'strokeOpacity'
26
+ | 'size'
27
+ | 'viewBox'
28
+ | 'fill'
29
+ | 'fillOpacity'
30
+ | 'className'
31
+ >
32
+
33
+ const sizeMap: Record<Size, number> = {
34
+ small: 16,
35
+ medium: 24,
36
+ large: 32,
37
+ xl: 48,
38
+ '2xl': 64,
39
+ }
40
+
41
+ export interface IconProps extends Omit<SvgProps, 'size'> {
42
+ name: IconName
43
+ size?: ResponsiveValue<Size>
44
+ }
45
+
46
+ const iconCache = new Map<
47
+ string,
48
+ React.LazyExoticComponent<React.ComponentType<LucideProps>>
49
+ >()
50
+
51
+ function tryGetIcon(
52
+ name: string
53
+ ): React.LazyExoticComponent<React.ComponentType<LucideProps>> {
54
+ if (iconCache.has(name)) {
55
+ return iconCache.get(name) as React.LazyExoticComponent<
56
+ React.ComponentType<LucideProps>
57
+ >
58
+ }
59
+
60
+ const LucideIcon = customDynamicIconImports[
61
+ name as keyof typeof customDynamicIconImports
62
+ ]
63
+ ? lazy(
64
+ customDynamicIconImports[name as keyof typeof customDynamicIconImports]
65
+ )
66
+ : lazy(dynamicIconImports[name as keyof typeof dynamicIconImports])
67
+
68
+ iconCache.set(name, LucideIcon)
69
+ return LucideIcon
70
+ }
71
+
72
+ export function Icon({ name, size = 'small', ...props }: IconProps) {
73
+ const LucideIcon = tryGetIcon(name)
74
+ const breakpoint = useTailwindBreakpoint()
75
+ const resolvedSize = resolveSizeForBreakpoint(breakpoint, size, 'small')
76
+ const sizeNumber = sizeMap[resolvedSize]
77
+
78
+ return (
79
+ <Suspense fallback={fallback}>
80
+ <LucideIcon {...props} size={sizeNumber} />
81
+ </Suspense>
82
+ )
83
+ }
@@ -0,0 +1,10 @@
1
+ import { IconName, iconNames } from './names'
2
+
3
+ const iconNameSet = new Set(Object.values(iconNames))
4
+
5
+ export function isIconName(maybeIconName: unknown): maybeIconName is IconName {
6
+ return (
7
+ typeof maybeIconName === 'string' &&
8
+ iconNameSet.has(maybeIconName as IconName)
9
+ )
10
+ }
@@ -0,0 +1,14 @@
1
+ import dynamicIconImports from 'lucide-react/dynamicIconImports'
2
+ import customDynamicIconImports from './customIcons'
3
+
4
+ export const lucideIconNames = Object.keys(
5
+ dynamicIconImports
6
+ ) as (keyof typeof dynamicIconImports)[]
7
+
8
+ export const customIconNames = Object.keys(
9
+ customDynamicIconImports
10
+ ) as (keyof typeof customDynamicIconImports)[]
11
+
12
+ export const iconNames = [...lucideIconNames, ...customIconNames]
13
+
14
+ export type IconName = (typeof iconNames)[number]
@@ -0,0 +1,51 @@
1
+ import * as React from 'react'
2
+ import { Button, ButtonIcon } from '../Button'
3
+ import { ButtonVariant, ButtonSize, ButtonContext } from '../../types'
4
+ import { cn } from '../../lib/utils'
5
+
6
+ type Attributes = Pick<
7
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
8
+ | 'disabled'
9
+ | 'onClick'
10
+ | 'type'
11
+ | 'role'
12
+ | 'onMouseEnter'
13
+ | 'onMouseLeave'
14
+ | 'onMouseDown'
15
+ | 'onMouseUp'
16
+ >
17
+
18
+ export interface IconButtonProps extends Attributes {
19
+ icon: React.ReactNode
20
+ variant?: ButtonVariant
21
+ size?: ButtonSize
22
+ context?: ButtonContext
23
+ className?: string
24
+ asChild?: boolean
25
+ 'aria-label': string // Required for accessibility
26
+ }
27
+
28
+ const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
29
+ ({ icon, size = 'md', className, ...props }, ref) => {
30
+ // Map button sizes to square dimensions with proper icon sizing
31
+ const sizeClasses = {
32
+ xs: 'h-7 w-7 [&_svg]:size-3',
33
+ sm: 'h-8 w-8 [&_svg]:size-3.5',
34
+ md: 'h-9 w-9 [&_svg]:size-4',
35
+ lg: 'h-10 w-10 [&_svg]:size-5',
36
+ }
37
+
38
+ return (
39
+ <Button
40
+ ref={ref}
41
+ className={cn(sizeClasses[size], 'p-0', className)}
42
+ {...props}
43
+ >
44
+ <ButtonIcon>{icon}</ButtonIcon>
45
+ </Button>
46
+ )
47
+ }
48
+ )
49
+ IconButton.displayName = 'IconButton'
50
+
51
+ export { IconButton }
@@ -0,0 +1,98 @@
1
+ // TODO: https://linear.app/speakeasy/issue/SXF-171/input-component
2
+ import { cn } from '../../lib/utils'
3
+ import { Icon } from '../Icon'
4
+ import { IconName } from '../Icon/names'
5
+ import { useCallback, useState } from 'react'
6
+
7
+ export interface InputProps
8
+ extends React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement> {
9
+ icon?: IconName
10
+ multiline?: boolean
11
+ error?: boolean
12
+ className?: string
13
+ }
14
+
15
+ export function Input({
16
+ value,
17
+ onChange,
18
+ placeholder,
19
+ disabled,
20
+ icon,
21
+ multiline,
22
+ error,
23
+ className,
24
+ ...props
25
+ }: InputProps) {
26
+ const [isFocused, setIsFocused] = useState(false)
27
+
28
+ const handleFocus = useCallback(
29
+ (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
30
+ if (props.onFocus) {
31
+ props.onFocus(event)
32
+ }
33
+ setIsFocused(true)
34
+ },
35
+ [props.onFocus]
36
+ )
37
+ const handleBlur = useCallback(
38
+ (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
39
+ if (props.onBlur) {
40
+ props.onBlur(event)
41
+ }
42
+ setIsFocused(false)
43
+ },
44
+ [props.onBlur]
45
+ )
46
+
47
+ const commonProps = {
48
+ value,
49
+ onChange,
50
+ placeholder,
51
+ disabled,
52
+ } as const
53
+
54
+ let element: React.ReactNode = (
55
+ <input
56
+ {...commonProps}
57
+ {...props}
58
+ onFocus={handleFocus}
59
+ onBlur={handleBlur}
60
+ className={cn(
61
+ 'bg-surface-primary-default placeholder:text-placeholder text-default h-full w-full text-sm shadow-none outline-none disabled:cursor-not-allowed disabled:opacity-50',
62
+ isFocused && 'placeholder:text-default'
63
+ )}
64
+ />
65
+ )
66
+
67
+ if (multiline) {
68
+ element = (
69
+ <textarea
70
+ {...commonProps}
71
+ {...props}
72
+ onFocus={handleFocus}
73
+ onBlur={handleBlur}
74
+ cols={30}
75
+ rows={10}
76
+ className={cn(
77
+ 'bg-surface-primary-default placeholder:text-placeholder text-default my-2 h-full max-h-60 min-h-16 w-full px-3 py-3 text-sm shadow-none outline-none disabled:cursor-not-allowed disabled:opacity-50',
78
+ isFocused && 'placeholder:text-default'
79
+ )}
80
+ />
81
+ )
82
+ }
83
+
84
+ return (
85
+ <div
86
+ className={cn(
87
+ 'bg-surface-primary-default border-input text-muted-foreground flex items-center gap-3 rounded-md border px-4 py-3',
88
+ icon && 'px-3',
89
+ isFocused && 'text-default border-focus',
90
+ error && 'border-destructive-default',
91
+ className
92
+ )}
93
+ >
94
+ {icon && <Icon name={icon} size="small" />}
95
+ {element}
96
+ </div>
97
+ )
98
+ }
@@ -0,0 +1,118 @@
1
+ import { cn } from '../../lib/utils'
2
+ import { Icon } from '../Icon'
3
+
4
+ type Modifier = 'shift' | 'ctrlorcommand' | 'alt' | 'meta' | 'esc'
5
+
6
+ function checkIsMac(): boolean {
7
+ if (typeof window === 'undefined') {
8
+ return false
9
+ }
10
+ return /Mac|iPod|iPhone|iPad/.test(window.navigator.platform)
11
+ }
12
+
13
+ const modifierMap: Record<Modifier, string> = {
14
+ shift: '⇧',
15
+ ctrlorcommand: checkIsMac() ? '⌘' : 'Ctrl',
16
+ alt: checkIsMac() ? '⌥' : 'Alt',
17
+ meta: checkIsMac() ? '⌘' : 'Win',
18
+ esc: 'Esc',
19
+ }
20
+
21
+ export interface KeyProps {
22
+ value: string
23
+ className?: string
24
+ }
25
+
26
+ export function Key({ value, className }: KeyProps) {
27
+ return (
28
+ <span
29
+ className={cn(
30
+ 'from-background to-card text-foreground/70 dark:text-foreground rounded-lg border bg-gradient-to-br px-2 py-0.5 text-sm',
31
+ className
32
+ )}
33
+ >
34
+ {value}
35
+ </span>
36
+ )
37
+ }
38
+
39
+ interface KeyHintItemProps {
40
+ modifiers: Modifier[]
41
+ keys: string[]
42
+ actionText?: string
43
+ }
44
+
45
+ function KeyHintKeys({ modifiers, keys }: KeyHintItemProps) {
46
+ return (
47
+ <div className="flex flex-row items-center gap-1">
48
+ {modifiers.map((modifier, index) => (
49
+ <>
50
+ <Key value={modifierMap[modifier]} />
51
+ {index < modifiers.length - 1 && (
52
+ <span className="text-body-muted text-sm">+</span>
53
+ )}
54
+ </>
55
+ ))}
56
+ {keys.length > 0 && <span className="text-body-muted text-sm">+</span>}
57
+ {keys.map((key, index) => (
58
+ <>
59
+ <Key value={key.toUpperCase()} />
60
+ {index < keys.length - 1 && (
61
+ <span className="text-body-muted text-sm">+</span>
62
+ )}
63
+ </>
64
+ ))}
65
+ </div>
66
+ )
67
+ }
68
+
69
+ export interface KeyHintProps extends React.HTMLAttributes<HTMLDivElement> {
70
+ modifiers: Modifier[]
71
+ keys: string[]
72
+ actionText: string
73
+ titleText?: string
74
+ dismissable?: boolean
75
+ onDismiss?: () => void
76
+ }
77
+
78
+ export function KeyHint({
79
+ modifiers,
80
+ keys,
81
+ actionText,
82
+ className,
83
+ dismissable = true,
84
+ onDismiss,
85
+ titleText = 'Key hint',
86
+ ...props
87
+ }: KeyHintProps) {
88
+ return (
89
+ <div
90
+ className={cn(
91
+ 'inline-flex min-w-24 flex-col items-start gap-1 rounded-lg border text-base font-semibold tracking-tight text-black shadow-sm shadow-black/5 select-none dark:text-white dark:shadow-white/10',
92
+ className
93
+ )}
94
+ {...props}
95
+ >
96
+ <div className="text-body-muted dark:text-body-muted/80 flex w-full flex-row items-center self-start border-b px-2.5 py-0.5 text-[10px] font-semibold tracking-wide uppercase select-none">
97
+ <div>{titleText}</div>
98
+ {dismissable && (
99
+ <div
100
+ className="hover:text-foreground ml-auto cursor-pointer"
101
+ onClick={onDismiss}
102
+ title="Close"
103
+ >
104
+ <Icon name="x" className="h-3.5 w-3.5" />
105
+ </div>
106
+ )}
107
+ </div>
108
+ <div className="flex flex-row items-center gap-1 px-4 py-3.5">
109
+ <KeyHintKeys modifiers={modifiers} keys={keys} />
110
+ {actionText && (
111
+ <div className="text-body-muted text-sm font-normal">
112
+ {actionText}
113
+ </div>
114
+ )}
115
+ </div>
116
+ </div>
117
+ )
118
+ }
@@ -0,0 +1,68 @@
1
+ // TODO: https://linear.app/speakeasy/issue/SXF-172/language-indicator-component
2
+ import { cn } from '../../lib/utils'
3
+ import { SupportedLanguage } from '../../types'
4
+
5
+ export interface LanguageIndicatorProps {
6
+ language: SupportedLanguage
7
+ className?: string
8
+ indicatorOnly?: boolean
9
+ }
10
+
11
+ const languageLabelMap: Record<string, string> = {
12
+ typescript: 'TypeScript',
13
+ go: 'Go',
14
+ java: 'Java',
15
+ python: 'Python',
16
+ csharp: 'C#',
17
+ terraform: 'Terraform',
18
+ unity: 'Unity',
19
+ php: 'PHP',
20
+ swift: 'Swift',
21
+ ruby: 'Ruby',
22
+ postman: 'Postman',
23
+
24
+ // Unsupported languages but used elsewhere
25
+ bash: 'Bash',
26
+ json: 'JSON',
27
+ dotnet: 'C#',
28
+ javascript: 'JavaScript',
29
+ }
30
+
31
+ const languageColorMap: Record<string, string> = {
32
+ typescript: 'bg-yellow-500',
33
+ go: 'bg-green-600',
34
+ java: 'bg-orange-500',
35
+ python: 'bg-indigo-500',
36
+ csharp: 'bg-purple-500',
37
+ terraform: 'bg-blue-500',
38
+ unity: 'bg-emerald-300',
39
+ php: 'bg-orange-500',
40
+ swift: 'bg-sky-300',
41
+ ruby: 'bg-red-500',
42
+ postman: 'bg-pink-500',
43
+
44
+ // Unsupported languages but used elsewhere
45
+ bash: 'bg-gray-500',
46
+ json: 'bg-gray-500',
47
+ dotnet: 'bg-gray-500',
48
+ javascript: 'bg-yellow-500',
49
+ }
50
+
51
+ export function LanguageIndicator({
52
+ language,
53
+ className,
54
+ indicatorOnly = false,
55
+ }: LanguageIndicatorProps) {
56
+ return (
57
+ <div className={cn('gap flex items-center gap-2 select-none', className)}>
58
+ <div
59
+ className={`mx-1 h-2 w-2 rounded-full ${languageColorMap[language]}`}
60
+ />
61
+ {!indicatorOnly && (
62
+ <span className="text-body font-medium">
63
+ {languageLabelMap[language]}
64
+ </span>
65
+ )}
66
+ </div>
67
+ )
68
+ }
@@ -0,0 +1,153 @@
1
+ import React, { forwardRef, ReactNode } from 'react'
2
+ import { cn } from '../../lib/utils'
3
+ import { cva } from 'class-variance-authority'
4
+ import { Slot, Slottable } from '@radix-ui/react-slot'
5
+ import { IconName } from '../Icon/names'
6
+ import { Icon as IconComponent } from '../Icon'
7
+ import { TextVariant } from '../Text'
8
+
9
+ type LinkVariant = 'primary' | 'secondary'
10
+
11
+ const linkVariants = cva(
12
+ 'group/link items-center inline-flex flex-row cursor-pointer',
13
+ {
14
+ variants: {
15
+ variant: {
16
+ primary: 'text-link-primary visited:text-link-visited',
17
+ secondary: 'text-link-secondary visited:text-link-visited',
18
+ },
19
+ size: {
20
+ xs: 'text-body-xs gap-1',
21
+ sm: 'text-body-sm gap-1',
22
+ md: 'text-body-md gap-2',
23
+ lg: 'text-body-lg gap-2',
24
+ },
25
+ },
26
+ }
27
+ )
28
+
29
+ const linkTextVariants = cva(
30
+ 'underline-offset-4 decoration-1 inline-flex flex-row items-center',
31
+ {
32
+ variants: {
33
+ variant: {
34
+ primary: '',
35
+ secondary: '',
36
+ },
37
+ underline: {
38
+ false: 'no-underline group-hover/link:underline',
39
+ true: 'underline group-hover/link:no-underline',
40
+ },
41
+ },
42
+ }
43
+ )
44
+
45
+ const iconWrapperVariants = cva('inline-block', {
46
+ variants: {
47
+ size: {
48
+ xs: 'size-3 [&>svg]:size-3',
49
+ sm: 'size-3 [&>svg]:size-3',
50
+ md: 'size-4 [&>svg]:size-4',
51
+ lg: 'size-4 [&>svg]:size-4',
52
+ },
53
+ },
54
+ })
55
+
56
+ export interface LinkProps
57
+ extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
58
+ children: ReactNode
59
+ variant?: LinkVariant
60
+ size?: TextVariant
61
+ underline?: boolean
62
+ iconPrefixName?: IconName
63
+ iconSuffixName?: IconName
64
+ asChild?: boolean
65
+ }
66
+
67
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
68
+ (
69
+ {
70
+ children,
71
+ variant = 'primary',
72
+ size = 'md',
73
+ underline = true,
74
+ target = '_blank',
75
+ iconPrefixName,
76
+ iconSuffixName,
77
+ className,
78
+ asChild = false,
79
+ ...rest
80
+ },
81
+ ref
82
+ ) => {
83
+ const Comp = asChild ? Slot : 'a'
84
+
85
+ // When asChild is true, we need to apply underline styles to the main component
86
+ // since the Text wrapper won't be used
87
+ const underlineClasses = asChild
88
+ ? linkTextVariants({ underline, variant })
89
+ : ''
90
+
91
+ return (
92
+ <Comp
93
+ ref={ref}
94
+ target={target}
95
+ className={cn(
96
+ linkVariants({ size, variant }),
97
+ underlineClasses,
98
+ className
99
+ )}
100
+ {...rest}
101
+ >
102
+ {iconPrefixName && (
103
+ <IconWrapper size={size}>
104
+ <IconComponent name={iconPrefixName} size="small" />
105
+ </IconWrapper>
106
+ )}
107
+
108
+ {asChild ? (
109
+ <Slottable>{children}</Slottable>
110
+ ) : (
111
+ <Text underline={underline} variant={variant}>
112
+ {children}
113
+ </Text>
114
+ )}
115
+
116
+ {iconSuffixName && (
117
+ <IconWrapper size={size}>
118
+ <IconComponent name={iconSuffixName} size="small" />
119
+ </IconWrapper>
120
+ )}
121
+ </Comp>
122
+ )
123
+ }
124
+ )
125
+ Link.displayName = 'Link'
126
+
127
+ interface TextProps {
128
+ underline?: boolean
129
+ variant?: LinkVariant
130
+ }
131
+
132
+ const Text = ({
133
+ children,
134
+ underline,
135
+ variant,
136
+ }: React.PropsWithChildren<TextProps>) => {
137
+ return (
138
+ <span className={cn(linkTextVariants({ underline, variant }))}>
139
+ {children}
140
+ </span>
141
+ )
142
+ }
143
+
144
+ interface IconWrapperProps {
145
+ size?: TextVariant
146
+ }
147
+
148
+ const IconWrapper = ({
149
+ children,
150
+ size,
151
+ }: React.PropsWithChildren<IconWrapperProps>) => {
152
+ return <span className={cn(iconWrapperVariants({ size }))}>{children}</span>
153
+ }