@speakeasy-api/moonshine 2.0.0-alpha.1 → 2.0.0-alpha.3

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,25 @@
1
+ .table {
2
+ --table-cell-padding: var(--cell-padding-block, 0.75rem)
3
+ var(--cell-padding-inline, 1rem);
4
+
5
+ /* Density modes: condensed, normal, spacious */
6
+ &:where([data-cell-padding='condensed']) {
7
+ --cell-padding-block: 0.5rem;
8
+ --cell-padding-inline: 0.75rem;
9
+ }
10
+
11
+ &:where([data-cell-padding='normal']) {
12
+ --cell-padding-block: 0.75rem;
13
+ --cell-padding-inline: 1rem;
14
+ }
15
+
16
+ &:where([data-cell-padding='spacious']) {
17
+ --cell-padding-block: 1rem;
18
+ --cell-padding-inline: 1.25rem;
19
+ }
20
+ }
21
+
22
+ .tableHeader,
23
+ .tableCell {
24
+ padding: var(--table-cell-padding);
25
+ }
@@ -0,0 +1,87 @@
1
+ import { cn } from '../../lib/utils'
2
+ import React, { ReactElement, useEffect, useState } from 'react'
3
+
4
+ export interface TabProps<I extends string> {
5
+ children: React.ReactNode
6
+ active?: boolean
7
+ id: I
8
+ onClick?: () => void
9
+ className?: string
10
+ }
11
+
12
+ const Tab = function Tab<I extends string>({
13
+ children,
14
+ active,
15
+ onClick,
16
+ className,
17
+ }: TabProps<I>) {
18
+ return (
19
+ <div
20
+ className={cn(
21
+ 'text-body mb-[-1px] cursor-pointer px-4 py-2 text-sm',
22
+ active &&
23
+ 'bg-background text-foreground rounded-t-lg border-t border-r border-l',
24
+ className
25
+ )}
26
+ onClick={onClick}
27
+ >
28
+ {children}
29
+ </div>
30
+ )
31
+ }
32
+
33
+ export interface TabsProps<I extends string> {
34
+ children: Array<ReactElement<TabProps<I>>>
35
+ selectedTab: I
36
+ onTabChange: (identifier: I) => void
37
+ className?: string
38
+ }
39
+
40
+ type TypeWithDisplayName = {
41
+ displayName?: string
42
+ }
43
+
44
+ export function Tabs<I extends string>({
45
+ children,
46
+ selectedTab,
47
+ onTabChange,
48
+ className,
49
+ }: TabsProps<I>) {
50
+ const [activeTab, setActiveTab] = useState<I>(
51
+ selectedTab || children[0].props.id
52
+ )
53
+
54
+ useEffect(() => {
55
+ setActiveTab(selectedTab || children[0].props.id)
56
+ }, [selectedTab])
57
+
58
+ const validChildren = React.Children.toArray(children).filter(
59
+ (child) =>
60
+ React.isValidElement(child) &&
61
+ (child.type as TypeWithDisplayName).displayName === 'Tabs.Tab'
62
+ ) as Array<React.ReactElement<TabProps<I>>>
63
+
64
+ return (
65
+ <div
66
+ className={cn(
67
+ 'border-border flex flex-row justify-start gap-2 border-b select-none',
68
+ className
69
+ )}
70
+ >
71
+ {React.Children.map(validChildren, (child) => {
72
+ return React.cloneElement(child, {
73
+ ...child.props,
74
+ active: child.props.id === activeTab,
75
+ onClick: () => {
76
+ setActiveTab(child.props.id)
77
+ child.props.onClick?.()
78
+ onTabChange?.(child.props.id)
79
+ },
80
+ })
81
+ })}
82
+ </div>
83
+ )
84
+ }
85
+
86
+ Tab.displayName = 'Tabs.Tab'
87
+ Tabs.Tab = Tab
@@ -0,0 +1,84 @@
1
+ import { Size } from '../../types'
2
+ import { SupportedLanguage } from '../../types'
3
+
4
+ import TypeScriptIcon from '../../assets/icons/languages/typescript.svg?react'
5
+ import GoIcon from '../../assets/icons/languages/go.svg?react'
6
+ import JavaIcon from '../../assets/icons/languages/java.svg?react'
7
+ import PythonIcon from '../../assets/icons/languages/python.svg?react'
8
+ import CSharpIcon from '../../assets/icons/languages/csharp.svg?react'
9
+ import TerraformIcon from '../../assets/icons/languages/terraform.svg?react'
10
+ import UnityIcon from '../../assets/icons/languages/unity.svg?react'
11
+ import PhpIcon from '../../assets/icons/languages/php.svg?react'
12
+ import SwiftIcon from '../../assets/icons/languages/swift.svg?react'
13
+ import RubyIcon from '../../assets/icons/languages/ruby.svg?react'
14
+ import PostmanIcon from '../../assets/icons/languages/postman.svg?react'
15
+ import JSONIcon from '../../assets/icons/languages/json.svg?react'
16
+ import { cn } from '../../lib/utils'
17
+
18
+ const sizeMap: Record<Size, number> = {
19
+ small: 32,
20
+ medium: 40,
21
+ large: 48,
22
+ xl: 64,
23
+ '2xl': 80,
24
+ }
25
+
26
+ const iconSizeMap: Record<Size, number> = {
27
+ small: 16,
28
+ medium: 24,
29
+ large: 32,
30
+ xl: 48,
31
+ '2xl': 64,
32
+ }
33
+
34
+ const icons: Record<
35
+ SupportedLanguage,
36
+ React.FC<React.SVGProps<SVGSVGElement>>
37
+ > = {
38
+ typescript: TypeScriptIcon,
39
+ go: GoIcon,
40
+ java: JavaIcon,
41
+ python: PythonIcon,
42
+ csharp: CSharpIcon,
43
+ terraform: TerraformIcon,
44
+ unity: UnityIcon,
45
+ php: PhpIcon,
46
+ swift: SwiftIcon,
47
+ ruby: RubyIcon,
48
+ postman: PostmanIcon,
49
+ json: JSONIcon,
50
+ }
51
+
52
+ export interface TargetLanguageIconProps {
53
+ language: SupportedLanguage
54
+ size?: Size
55
+ className?: string
56
+ }
57
+
58
+ export function TargetLanguageIcon({
59
+ language,
60
+ size = 'medium',
61
+ className,
62
+ }: TargetLanguageIconProps) {
63
+ const IconComponent = icons[language]
64
+
65
+ return (
66
+ <div
67
+ className={cn(
68
+ 'bg-background/50 flex items-center justify-center rounded-lg border p-2',
69
+ className
70
+ )}
71
+ style={{
72
+ width: sizeMap[size],
73
+ height: sizeMap[size],
74
+ }}
75
+ >
76
+ <IconComponent
77
+ style={{
78
+ width: iconSizeMap[size],
79
+ height: iconSizeMap[size],
80
+ }}
81
+ />
82
+ </div>
83
+ )
84
+ }
@@ -0,0 +1,59 @@
1
+ import { cn } from '../../lib/utils'
2
+ import { ReactNode } from 'react'
3
+
4
+ export type TextVariant = 'lg' | 'md' | 'sm' | 'xs'
5
+ type TextElement = 'p' | 'span' | 'div' | 'label'
6
+ type TextWhitespace = 'normal' | 'nowrap'
7
+
8
+ export type TextProps = {
9
+ children: ReactNode
10
+ variant?: TextVariant
11
+ muted?: boolean
12
+ whiteSpace?: TextWhitespace
13
+ className?: string
14
+ } & (
15
+ | {
16
+ as?: Exclude<TextElement, 'label'>
17
+ htmlFor?: never
18
+ }
19
+ | {
20
+ as: 'label'
21
+ htmlFor?: string
22
+ }
23
+ )
24
+
25
+ const variantStyles: Record<TextVariant, string> = {
26
+ lg: 'text-body-lg',
27
+ md: 'text-body-md',
28
+ sm: 'text-body-sm',
29
+ xs: 'text-body-xs',
30
+ }
31
+
32
+ const whitespaceStyles: Record<TextWhitespace, string> = {
33
+ normal: 'whitespace-normal',
34
+ nowrap: 'whitespace-nowrap',
35
+ }
36
+
37
+ export function Text({
38
+ children,
39
+ variant = 'md',
40
+ as: Component = 'span',
41
+ muted = false,
42
+ whiteSpace = 'normal',
43
+ className,
44
+ htmlFor,
45
+ }: TextProps) {
46
+ return (
47
+ <Component
48
+ htmlFor={htmlFor}
49
+ className={cn(
50
+ variantStyles[variant],
51
+ whitespaceStyles[whiteSpace],
52
+ muted ? 'text-muted' : 'text-default',
53
+ className
54
+ )}
55
+ >
56
+ {children}
57
+ </Component>
58
+ )
59
+ }
@@ -0,0 +1,118 @@
1
+ 'use client'
2
+
3
+ import { ReactNode, useId, useMemo } from 'react'
4
+ import { cn } from '../../lib/utils'
5
+ import { Moon, Sun } from 'lucide-react'
6
+ import { useIsMounted } from '../../hooks/useIsMounted'
7
+ import { useConfig } from '../../hooks/useConfig'
8
+ import { Theme } from '../../context/theme'
9
+ import { motion } from 'motion/react'
10
+
11
+ const THEMES: { key: Theme; icon: ReactNode }[] = [
12
+ { key: 'light', icon: <Sun /> },
13
+ { key: 'dark', icon: <Moon /> },
14
+ ]
15
+
16
+ export interface ThemeSwitcherProps {
17
+ onThemeSwitch?: (theme: string) => void
18
+ className?: string
19
+ orientation?: 'horizontal' | 'vertical'
20
+ }
21
+
22
+ export function ThemeSwitcher({
23
+ className,
24
+ onThemeSwitch,
25
+ orientation = 'horizontal',
26
+ }: ThemeSwitcherProps) {
27
+ const isMounted = useIsMounted()
28
+ const { theme, setTheme } = useConfig()
29
+ const rId = useId()
30
+
31
+ const posX = useMemo(() => {
32
+ const themeIndex = THEMES.findIndex((opt) => opt.key === theme)
33
+ return 100 * themeIndex
34
+ }, [theme])
35
+
36
+ const isVertical = orientation === 'vertical'
37
+ const knobSizeRem = 2.125
38
+ const placeholderStyle = isVertical
39
+ ? {
40
+ width: `${knobSizeRem}rem`,
41
+ height: `calc(${knobSizeRem}rem * ${THEMES.length} + 2px)`,
42
+ }
43
+ : {
44
+ width: `calc(${knobSizeRem}rem * ${THEMES.length} + 2px)`,
45
+ height: `${knobSizeRem}rem`,
46
+ }
47
+
48
+ if (!isMounted) return <div style={placeholderStyle} />
49
+
50
+ return (
51
+ <div className="relative h-fit w-fit overflow-hidden rounded-full border border-neutral-300 bg-neutral-100 p-0 dark:border-neutral-800/30 dark:bg-neutral-900">
52
+ <fieldset
53
+ className={cn(
54
+ 'group m-0 flex',
55
+ isVertical ? 'flex-col items-stretch' : 'flex-row items-center',
56
+ className
57
+ )}
58
+ >
59
+ <legend className="sr-only">Select a display theme:</legend>
60
+ {THEMES.map(({ key, icon }) => {
61
+ const checked = key === theme
62
+ const id = `theme-toggle-${key}-${rId}`
63
+ return (
64
+ <span key={key} className="h-full">
65
+ <input
66
+ tabIndex={checked ? -1 : 0}
67
+ className="peer absolute appearance-none outline-0"
68
+ aria-label={key}
69
+ checked={checked}
70
+ id={id}
71
+ onChange={(): void => {
72
+ setTheme(key)
73
+ onThemeSwitch?.(key)
74
+ }}
75
+ type="radio"
76
+ value={key}
77
+ suppressHydrationWarning
78
+ />
79
+ <label
80
+ className={cn(
81
+ // Base
82
+ 'text-foreground relative flex size-[2.125rem] cursor-pointer items-center justify-center rounded-full opacity-50 transition-opacity duration-300 dark:text-neutral-300 dark:opacity-70',
83
+ // Checked
84
+ 'peer-checked:cursor-default peer-checked:!opacity-100',
85
+ // Hover
86
+ 'peer-interact:!opacity-100',
87
+ // Focus
88
+ 'peer-focus-visible:ring-foreground peer-checked:!inset-ring-0 peer-focus-visible:inset-ring-2',
89
+ // Icon
90
+ 'relative z-[1] [&_svg]:size-4 [&_svg]:text-current'
91
+ )}
92
+ htmlFor={id}
93
+ >
94
+ <span className="sr-only">{key}</span>
95
+ {icon}
96
+ </label>
97
+ </span>
98
+ )
99
+ })}
100
+ </fieldset>
101
+ <motion.div
102
+ initial={{
103
+ transform: isVertical
104
+ ? `translateY(${posX}%)`
105
+ : `translateX(${posX}%)`,
106
+ }}
107
+ animate={{
108
+ transform: isVertical
109
+ ? `translateY(${posX}%)`
110
+ : `translateX(${posX}%)`,
111
+ }}
112
+ transition={{ type: 'spring', duration: 0.7, bounce: 0.3 }}
113
+ className="absolute top-0 left-0 z-[10] size-[2.125rem] rounded-full shadow-[0px_0px_4px_0px_rgba(0,0,0,0.10),0px_2px_1px_0px_#FFF_inset,0px_-2px_1px_0px_rgba(0,0,0,0.05)_inset] dark:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.60),0px_2px_1px_0px_#282828_inset,0px_-2px_1px_0px_rgba(0,0,0,0.05)_inset]"
114
+ suppressHydrationWarning
115
+ />
116
+ </div>
117
+ )
118
+ }
@@ -0,0 +1,290 @@
1
+ 'use client'
2
+
3
+ import React, {
4
+ useLayoutEffect,
5
+ useRef,
6
+ useState,
7
+ isValidElement,
8
+ cloneElement,
9
+ Children,
10
+ } from 'react'
11
+ import type { ReactNode } from 'react'
12
+ import { cn } from '../../lib/utils'
13
+ import { Text } from '../Text'
14
+ import { Heading } from '../Heading'
15
+
16
+ const TIMELINE_STYLES = {
17
+ line: 'bg-surface-tertiary-default',
18
+ iconContainer:
19
+ 'relative z-10 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full',
20
+ iconBackground:
21
+ 'bg-surface-primary-default border-border-neutral-softest absolute inset-0 rounded-full border-2 transition-all duration-300',
22
+ iconContent: 'relative z-10 flex h-full w-full items-center justify-center',
23
+ iconIcon:
24
+ 'text-muted flex items-center justify-center transition-colors duration-300 [&>svg]:h-4 [&>svg]:w-4',
25
+ iconNumber: 'text-muted text-sm font-medium transition-colors duration-300',
26
+ transition: 'transition-opacity duration-300',
27
+ } as const
28
+
29
+ export interface TimelineItemProps {
30
+ icon?: ReactNode
31
+ children: ReactNode
32
+ className?: string
33
+ index?: number
34
+ isLast?: boolean
35
+ setsize?: number
36
+ }
37
+
38
+ function TimelineItem({
39
+ icon,
40
+ children,
41
+ className,
42
+ index = 0,
43
+ isLast = false,
44
+ setsize,
45
+ }: TimelineItemProps) {
46
+ const enhancedChildren = Children.map(children, (child) => {
47
+ if (isValidElement(child) && child.type === TimelineContent) {
48
+ return cloneElement(child, {
49
+ ...child.props,
50
+ isLast,
51
+ })
52
+ }
53
+ return child
54
+ })
55
+
56
+ return (
57
+ <li
58
+ className={cn('relative flex items-start gap-4', className)}
59
+ data-timeline-item
60
+ aria-posinset={index + 1}
61
+ aria-setsize={setsize}
62
+ >
63
+ <div className={TIMELINE_STYLES.iconContainer}>
64
+ <div className={TIMELINE_STYLES.iconBackground} />
65
+ <div className={TIMELINE_STYLES.iconContent}>
66
+ {icon ? (
67
+ <div className={TIMELINE_STYLES.iconIcon}>{icon}</div>
68
+ ) : (
69
+ <div className={TIMELINE_STYLES.iconNumber}>{index + 1}</div>
70
+ )}
71
+ </div>
72
+ </div>
73
+
74
+ {enhancedChildren}
75
+ </li>
76
+ )
77
+ }
78
+
79
+ export interface TimelineContentProps {
80
+ children: ReactNode
81
+ className?: string
82
+ isLast?: boolean
83
+ }
84
+
85
+ function TimelineContent({
86
+ children,
87
+ className,
88
+ isLast,
89
+ }: TimelineContentProps) {
90
+ const childrenArray = Children.toArray(children)
91
+ let titleElement: React.ReactNode = null
92
+ let timestampElement: React.ReactNode = null
93
+ const otherChildren: React.ReactNode[] = []
94
+
95
+ childrenArray.forEach((child) => {
96
+ if (isValidElement(child)) {
97
+ if (child.type === TimelineTitle) {
98
+ titleElement = child
99
+ } else if (child.type === TimelineTimestamp) {
100
+ timestampElement = child
101
+ } else {
102
+ otherChildren.push(child)
103
+ }
104
+ } else {
105
+ otherChildren.push(child)
106
+ }
107
+ })
108
+
109
+ return (
110
+ <div
111
+ className={cn('min-w-0 flex-1', !isLast && 'pb-6', className)}
112
+ data-testid={isLast ? 'timeline-content-last' : 'timeline-content'}
113
+ >
114
+ {(titleElement || timestampElement) && (
115
+ <div className="mb-1 flex items-start justify-between gap-4">
116
+ <div className="min-w-0 flex-1">{titleElement}</div>
117
+ {timestampElement && (
118
+ <div className="flex-shrink-0">{timestampElement}</div>
119
+ )}
120
+ </div>
121
+ )}
122
+ {otherChildren.length > 0 && (
123
+ <div className="space-y-1">{otherChildren}</div>
124
+ )}
125
+ </div>
126
+ )
127
+ }
128
+
129
+ export interface TimelineTitleProps {
130
+ children: ReactNode
131
+ className?: string
132
+ as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'
133
+ }
134
+
135
+ function TimelineTitle({
136
+ children,
137
+ className,
138
+ as = 'div',
139
+ }: TimelineTitleProps) {
140
+ if (as === 'div') {
141
+ return (
142
+ <div
143
+ className={cn('text-heading-xs', TIMELINE_STYLES.transition, className)}
144
+ >
145
+ {children}
146
+ </div>
147
+ )
148
+ }
149
+
150
+ return (
151
+ <Heading
152
+ variant="xs"
153
+ as={as}
154
+ className={cn(TIMELINE_STYLES.transition, className)}
155
+ >
156
+ {children}
157
+ </Heading>
158
+ )
159
+ }
160
+
161
+ export interface TimelineDescriptionProps {
162
+ children: ReactNode
163
+ className?: string
164
+ }
165
+
166
+ function TimelineDescription({
167
+ children,
168
+ className,
169
+ }: TimelineDescriptionProps) {
170
+ return (
171
+ <Text
172
+ variant="sm"
173
+ muted
174
+ className={cn('leading-relaxed', TIMELINE_STYLES.transition, className)}
175
+ >
176
+ {children}
177
+ </Text>
178
+ )
179
+ }
180
+
181
+ export interface TimelineTimestampProps {
182
+ children: ReactNode
183
+ className?: string
184
+ }
185
+
186
+ function TimelineTimestamp({ children, className }: TimelineTimestampProps) {
187
+ return (
188
+ <Text
189
+ variant="xs"
190
+ muted
191
+ className={cn(TIMELINE_STYLES.transition, className)}
192
+ >
193
+ {children}
194
+ </Text>
195
+ )
196
+ }
197
+
198
+ export interface TimelineSeparatorProps {
199
+ className?: string
200
+ }
201
+
202
+ export interface TimelineRootProps {
203
+ children: ReactNode
204
+ className?: string
205
+ hasMore?: boolean
206
+ }
207
+
208
+ function TimelineRoot({
209
+ children,
210
+ className,
211
+ hasMore = false,
212
+ }: TimelineRootProps) {
213
+ const childrenArray = Children.toArray(children)
214
+ const itemsOnly = childrenArray.filter(
215
+ (child) => isValidElement(child) && child.type === TimelineItem
216
+ )
217
+ const itemCount = itemsOnly.length
218
+ const timelineRef = useRef<HTMLDivElement>(null)
219
+ const [lineHeight, setLineHeight] = useState<number | null>(null)
220
+
221
+ let itemIndex = 0
222
+ const enhancedChildren = childrenArray.map((child) => {
223
+ if (isValidElement(child) && child.type === TimelineItem) {
224
+ const cloned = cloneElement(child, {
225
+ ...child.props,
226
+ index: itemIndex,
227
+ isLast: itemIndex === itemCount - 1,
228
+ setsize: itemCount,
229
+ })
230
+ itemIndex += 1
231
+ return cloned
232
+ }
233
+ return child
234
+ })
235
+
236
+ useLayoutEffect(() => {
237
+ if (timelineRef.current && itemCount > 1) {
238
+ const timelineItems = timelineRef.current.querySelectorAll(
239
+ '[data-timeline-item]'
240
+ )
241
+ if (timelineItems.length >= 2) {
242
+ const lastItem = timelineItems[timelineItems.length - 1] as HTMLElement
243
+
244
+ // Calculate distance from center of first icon to center of last icon
245
+ const firstIconCenter = 24 // 1.5rem (top-6) + 0.75rem (half of 3rem icon height)
246
+ const lastItemTop = lastItem.offsetTop
247
+ const baseHeight = lastItemTop + 24 - firstIconCenter // 24px = center of last icon
248
+
249
+ // If hasMore is true, extend the line by an additional 2rem (32px) past the last icon
250
+ const calculatedHeight = hasMore ? baseHeight + 32 : baseHeight
251
+
252
+ setLineHeight(calculatedHeight)
253
+ }
254
+ }
255
+ }, [itemCount, children, hasMore])
256
+
257
+ return (
258
+ <div className={cn('relative', className)}>
259
+ {itemCount > 0 && (
260
+ <div className="relative" ref={timelineRef}>
261
+ {itemCount > 1 && (
262
+ <div
263
+ className={cn(TIMELINE_STYLES.line, 'absolute top-6 left-6 w-px')}
264
+ style={{
265
+ height: lineHeight
266
+ ? `${lineHeight}px`
267
+ : hasMore
268
+ ? `calc(100% - 2.5rem)`
269
+ : `calc(100% - 4.5rem)`,
270
+ }}
271
+ aria-hidden="true"
272
+ data-testid="timeline-connector"
273
+ />
274
+ )}
275
+ <ol className="space-y-6">{enhancedChildren}</ol>
276
+ </div>
277
+ )}
278
+ </div>
279
+ )
280
+ }
281
+
282
+ const Timeline = Object.assign(TimelineRoot, {
283
+ Item: TimelineItem,
284
+ Content: TimelineContent,
285
+ Title: TimelineTitle,
286
+ Description: TimelineDescription,
287
+ Timestamp: TimelineTimestamp,
288
+ })
289
+
290
+ export { Timeline }
@@ -0,0 +1,41 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip'
5
+
6
+ import { cn } from '../../lib/utils'
7
+
8
+ const TooltipProvider = TooltipPrimitive.Provider
9
+
10
+ const Tooltip = TooltipPrimitive.Root
11
+
12
+ const TooltipTrigger = TooltipPrimitive.Trigger
13
+
14
+ const TooltipArrow = TooltipPrimitive.TooltipArrow
15
+
16
+ const TooltipPortal = TooltipPrimitive.Portal
17
+
18
+ const TooltipContent = React.forwardRef<
19
+ React.ElementRef<typeof TooltipPrimitive.Content>,
20
+ React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
21
+ >(({ className, sideOffset = 4, ...props }, ref) => (
22
+ <TooltipPrimitive.Content
23
+ ref={ref}
24
+ sideOffset={sideOffset}
25
+ className={cn(
26
+ 'bg-popover text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md border px-3 py-1.5 text-sm shadow-md',
27
+ className
28
+ )}
29
+ {...props}
30
+ />
31
+ ))
32
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName
33
+
34
+ export {
35
+ Tooltip,
36
+ TooltipPortal,
37
+ TooltipTrigger,
38
+ TooltipContent,
39
+ TooltipProvider,
40
+ TooltipArrow,
41
+ }