@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,227 @@
1
+ import React, { Children, Fragment, PropsWithChildren } from 'react'
2
+ import { Heading } from '../Heading'
3
+ import { Separator } from '../Separator'
4
+
5
+ import styles from './styles.module.css'
6
+ import { cn } from '../../lib/utils'
7
+ import useTailwindBreakpoint from '../../hooks/useTailwindBreakpoint'
8
+ import { Link, LinkProps } from '../Link'
9
+
10
+ export interface PageHeaderProps extends PropsWithChildren {
11
+ className?: string
12
+ }
13
+
14
+ const Root: React.FC<PageHeaderProps> = ({ children, className }) => {
15
+ return (
16
+ <div
17
+ className={cn(
18
+ 'page-header group/page-header',
19
+ styles.pageHeader,
20
+ className
21
+ )}
22
+ >
23
+ {children}
24
+ </div>
25
+ )
26
+ }
27
+
28
+ interface ContextBarProps extends PropsWithChildren {
29
+ className?: string
30
+ }
31
+
32
+ const ContextBar: React.FC<ContextBarProps> = ({ children, className }) => {
33
+ return (
34
+ <div
35
+ className={cn(
36
+ styles.contextBar,
37
+ 'context-bar flex flex-row items-center justify-start pt-6',
38
+ className
39
+ )}
40
+ >
41
+ {children}
42
+ </div>
43
+ )
44
+ }
45
+ ContextBar.displayName = 'PageHeader.ContextBar'
46
+
47
+ interface ParentLinkProps
48
+ extends PropsWithChildren<Pick<LinkProps, 'href' | 'onClick'>> {
49
+ className?: string
50
+ }
51
+
52
+ const ParentLink: React.FC<ParentLinkProps> = ({
53
+ children,
54
+ className,
55
+ onClick,
56
+ href,
57
+ }) => {
58
+ return (
59
+ <Link
60
+ href={href}
61
+ onClick={onClick}
62
+ className={className}
63
+ iconPrefixName="arrow-left"
64
+ variant="secondary"
65
+ target="_self"
66
+ >
67
+ {children}
68
+ </Link>
69
+ )
70
+ }
71
+ ParentLink.displayName = 'PageHeader.ParentLink'
72
+
73
+ interface TitleBarProps extends PropsWithChildren {
74
+ className?: string
75
+ }
76
+ const TitleBar: React.FC<TitleBarProps> = ({ children, className }) => {
77
+ return (
78
+ <div
79
+ className={cn(
80
+ styles.titleBar,
81
+ 'flex flex-row items-center justify-between gap-4 border-b py-10 group-has-[.context-bar]/page-header:pt-8',
82
+ className
83
+ )}
84
+ >
85
+ {children}
86
+ </div>
87
+ )
88
+ }
89
+ TitleBar.displayName = 'PageHeader.TitleBar'
90
+
91
+ interface TitleAreaProps extends PropsWithChildren {
92
+ className?: string
93
+ }
94
+ const TitleArea: React.FC<TitleAreaProps> = ({ children, className }) => {
95
+ return (
96
+ <div
97
+ className={cn(
98
+ styles.titleArea,
99
+ 'flex flex-row items-center gap-2',
100
+ className
101
+ )}
102
+ >
103
+ {children}
104
+ </div>
105
+ )
106
+ }
107
+ TitleArea.displayName = 'PageHeader.TitleArea'
108
+
109
+ interface LeadingVisualProps extends PropsWithChildren {
110
+ className?: string
111
+ }
112
+
113
+ const LeadingVisual: React.FC<LeadingVisualProps> = ({
114
+ children,
115
+ className,
116
+ }) => {
117
+ return <div className={cn('order-1', className)}>{children}</div>
118
+ }
119
+ LeadingVisual.displayName = 'PageHeader.LeadingVisual'
120
+
121
+ interface TitleProps extends PropsWithChildren {
122
+ className?: string
123
+ viewTransitionName?: string
124
+ }
125
+ const Title: React.FC<TitleProps> = ({
126
+ children,
127
+ className,
128
+ viewTransitionName,
129
+ }) => {
130
+ return (
131
+ <Heading
132
+ variant="xl"
133
+ className={cn('order-2 flex-1', className)}
134
+ viewTransitionName={viewTransitionName}
135
+ >
136
+ {children}
137
+ </Heading>
138
+ )
139
+ }
140
+ Title.displayName = 'PageHeader.Title'
141
+
142
+ interface ActionsProps extends PropsWithChildren {
143
+ className?: string
144
+ }
145
+ const Actions: React.FC<ActionsProps> = ({ children, className }) => {
146
+ return (
147
+ <div
148
+ className={cn(
149
+ styles.actions,
150
+ 'flex min-w-max flex-row items-start justify-end gap-2',
151
+ className
152
+ )}
153
+ >
154
+ {children}
155
+ </div>
156
+ )
157
+ }
158
+ Actions.displayName = 'PageHeader.Actions'
159
+
160
+ interface FooterProps extends PropsWithChildren {
161
+ className?: string
162
+ }
163
+ const Footer: React.FC<FooterProps> = ({ children, className }) => {
164
+ const breakpoint = useTailwindBreakpoint()
165
+ const validChildren = Children.toArray(children).filter(
166
+ (child) => React.isValidElement(child) && child.type === FooterItem
167
+ )
168
+ const childCount = Children.count(validChildren)
169
+
170
+ const isSmallScreen = breakpoint === 'xs' || breakpoint === 'sm'
171
+
172
+ return (
173
+ <div
174
+ className={cn(
175
+ styles.footer,
176
+ 'flex w-full flex-col flex-wrap items-stretch justify-start gap-y-2 border-b py-6 md:flex-row md:gap-y-4',
177
+ className
178
+ )}
179
+ >
180
+ {Children.map(validChildren, (child, index) => (
181
+ <Fragment key={index}>
182
+ {child}
183
+ {index < childCount - 1 && (
184
+ <PageHeader.FooterItem>
185
+ <Separator
186
+ orientation={isSmallScreen ? 'horizontal' : 'vertical'}
187
+ className="footer-item-separator md:mx-6"
188
+ />
189
+ </PageHeader.FooterItem>
190
+ )}
191
+ </Fragment>
192
+ ))}
193
+ </div>
194
+ )
195
+ }
196
+ Footer.displayName = 'PageHeader.Footer'
197
+
198
+ interface FooterItemProps extends PropsWithChildren {
199
+ className?: string
200
+ }
201
+ const FooterItem: React.FC<FooterItemProps> = ({ children, className }) => {
202
+ return (
203
+ <div
204
+ className={cn(
205
+ 'flex flex-row items-center [&:has(.footer-item-separator)]:hidden [&:has(.footer-item-separator)]:md:flex',
206
+ className
207
+ )}
208
+ >
209
+ {children}
210
+ </div>
211
+ )
212
+ }
213
+ FooterItem.displayName = 'PageHeader.FooterItem'
214
+
215
+ export const PageHeader = Object.assign(Root, {
216
+ ContextBar,
217
+ ParentLink,
218
+ TitleBar,
219
+ TitleArea,
220
+ LeadingVisual,
221
+ Title,
222
+ Actions,
223
+ Footer,
224
+ FooterItem,
225
+ })
226
+
227
+ PageHeader.displayName = 'PageHeader'
@@ -0,0 +1,27 @@
1
+ .pageHeader {
2
+ display: grid;
3
+ grid-template-areas: "context-bar" "title-bar" "footer";
4
+ }
5
+
6
+ .contextBar {
7
+ grid-area: context-bar;
8
+ }
9
+
10
+ .titleBar {
11
+ display: grid;
12
+ grid-area: title-bar;
13
+ grid-template-areas: "title-area actions";
14
+ grid-template-columns: auto 1fr;
15
+ }
16
+
17
+ .titleArea {
18
+ grid-area: title-area;
19
+ }
20
+
21
+ .actions {
22
+ grid-area: actions;
23
+ }
24
+
25
+ .footer {
26
+ grid-area: footer;
27
+ }
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as PopoverPrimitive from '@radix-ui/react-popover'
5
+
6
+ import { cn } from '../../lib/utils'
7
+
8
+ const Popover = PopoverPrimitive.Root
9
+
10
+ const PopoverTrigger = PopoverPrimitive.Trigger
11
+
12
+ const PopoverAnchor = PopoverPrimitive.Anchor
13
+
14
+ const PopoverPortal = PopoverPrimitive.Portal
15
+
16
+ const PopoverContent = React.forwardRef<
17
+ React.ElementRef<typeof PopoverPrimitive.Content>,
18
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
19
+ >(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
20
+ <PopoverPrimitive.Portal>
21
+ <PopoverPrimitive.Content
22
+ ref={ref}
23
+ align={align}
24
+ sideOffset={sideOffset}
25
+ className={cn(
26
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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 w-72 rounded-md border p-4 shadow-md outline-none',
27
+ className
28
+ )}
29
+ {...props}
30
+ />
31
+ </PopoverPrimitive.Portal>
32
+ ))
33
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName
34
+
35
+ export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverPortal }
@@ -0,0 +1,372 @@
1
+ import { cn } from '../../lib/utils'
2
+ import { Icon } from '../Icon'
3
+ import { AnimatePresence, motion } from 'motion/react'
4
+ import { IconName } from '../Icon/names'
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
6
+
7
+ export interface Suggestion {
8
+ id: string
9
+ label: string
10
+ onClick: (id: string) => void
11
+ icon?: IconName
12
+ className?: string
13
+ iconClassName?: string
14
+ }
15
+
16
+ export interface Attachment {
17
+ id: string
18
+ name: string
19
+ bytes: ArrayBuffer
20
+ type: string
21
+ size: number
22
+ onRemove?: (id: string) => void
23
+ }
24
+
25
+ export interface PromptInputProps {
26
+ prompt?: string
27
+ placeholder: string
28
+ onChange: (prompt: string) => void
29
+ onSubmit: (e: React.MouseEvent<HTMLButtonElement>) => void
30
+ onFileUpload?: (files: Attachment[]) => void
31
+ suggestions?: Suggestion[]
32
+ attachments?: Attachment[]
33
+
34
+ /**
35
+ * The icon to show when the prompt is being submitted.
36
+ */
37
+ submittingIcon?: IconName
38
+
39
+ /**
40
+ * Whether the prompt is being submitted.
41
+ */
42
+ isSubmitting?: boolean
43
+
44
+ /**
45
+ * The max height the prompt input can grow to in pixels.
46
+ */
47
+ maxHeight?: number
48
+
49
+ /**
50
+ * The ref to the file input.
51
+ */
52
+ fileInputRef?: React.RefObject<HTMLInputElement>
53
+
54
+ /**
55
+ * The file types that are accepted by the file input.
56
+ */
57
+ acceptedFileTypes?: string[]
58
+
59
+ /**
60
+ * Whether the prompt input is disabled.
61
+ */
62
+ isDisabled?: boolean
63
+
64
+ /**
65
+ * The maximum number of attachments that can be uploaded.
66
+ */
67
+ maxAttachments?: number
68
+ }
69
+
70
+ export function PromptInput({
71
+ placeholder,
72
+ onSubmit,
73
+ suggestions = [],
74
+ prompt,
75
+ onChange,
76
+ onFileUpload,
77
+ attachments = [],
78
+ maxHeight = 250,
79
+ isSubmitting = false,
80
+ submittingIcon = 'loader',
81
+ fileInputRef,
82
+ acceptedFileTypes,
83
+ isDisabled = false,
84
+ maxAttachments = 1,
85
+ }: PromptInputProps) {
86
+ const [isDraggingOver, setIsDraggingOver] = useState(false)
87
+
88
+ // Always create a ref, and then assign it to the consumer's ref if provided
89
+ const internalFileInputRef = useRef<HTMLInputElement>(null)
90
+ const fileInputRefInternal = useMemo(() => {
91
+ return fileInputRef || internalFileInputRef
92
+ }, [fileInputRef])
93
+
94
+ const textAreaRef = useRef<HTMLTextAreaElement>(null)
95
+
96
+ const minHeight = useMemo<React.CSSProperties['minHeight']>(() => {
97
+ const promptLines = prompt?.split('\n').length ?? 0
98
+
99
+ if (promptLines === 0) {
100
+ return 0
101
+ }
102
+
103
+ // 1 line in the textarea = height 20px (approx)
104
+ const totalHeight = promptLines * 20
105
+
106
+ // We need to clamp the height of the textarea to the max height
107
+ // as min-height will override max-height
108
+ if (totalHeight > maxHeight) {
109
+ return `${maxHeight}px`
110
+ }
111
+
112
+ return `${totalHeight}px`
113
+ }, [prompt, maxHeight])
114
+
115
+ const handleDragOver = useCallback(
116
+ (event: React.DragEvent<HTMLDivElement>) => {
117
+ event.preventDefault()
118
+ event.stopPropagation()
119
+ setIsDraggingOver(true)
120
+ },
121
+ []
122
+ )
123
+
124
+ const handleFiles = useCallback(
125
+ async (files: File[]) => {
126
+ const attachments: Attachment[] = await Promise.all(
127
+ files.map(async (file) => ({
128
+ id: crypto.randomUUID(),
129
+ name: file.name,
130
+ type: file.type,
131
+ size: file.size,
132
+ bytes: await file.arrayBuffer(),
133
+ }))
134
+ )
135
+ onFileUpload?.(attachments)
136
+ },
137
+ [onFileUpload]
138
+ )
139
+
140
+ const handleDrop = useCallback(
141
+ async (event: React.DragEvent<HTMLDivElement>) => {
142
+ event.preventDefault()
143
+ event.stopPropagation()
144
+
145
+ setIsDraggingOver(false)
146
+ handleFiles(Array.from(event.dataTransfer.files))
147
+ },
148
+ [handleFiles]
149
+ )
150
+
151
+ const handleDragLeave = useCallback(
152
+ (event: React.DragEvent<HTMLDivElement>) => {
153
+ event.preventDefault()
154
+ event.stopPropagation()
155
+ setIsDraggingOver(false)
156
+ },
157
+ []
158
+ )
159
+
160
+ return (
161
+ <div className="flex w-full flex-col">
162
+ <div
163
+ onDragOver={handleDragOver}
164
+ onDrop={handleDrop}
165
+ onDragLeave={handleDragLeave}
166
+ className={cn(
167
+ 'text-foreground/70 dark:text-body-muted bg-background flex flex-col rounded-md border pt-2 text-sm',
168
+ isDraggingOver && 'border-primary/60 border-dashed'
169
+ )}
170
+ >
171
+ <div
172
+ className={cn(
173
+ 'flex flex-row gap-2 px-2',
174
+ attachments.length > 0 && 'mb-2'
175
+ )}
176
+ >
177
+ <AnimatePresence>
178
+ {attachments.map((attachment) => (
179
+ <AttachmentPreview key={attachment.id} attachment={attachment} />
180
+ ))}
181
+ </AnimatePresence>
182
+ </div>
183
+
184
+ <div
185
+ className="overflow-x-hidden overflow-y-scroll"
186
+ style={{ minHeight, maxHeight }}
187
+ >
188
+ <textarea
189
+ className="text-foreground selection:bg-primary/20 selection:text-primary dark:selection:bg-primary/20 dark:selection:text-primary min-h-[inherit] w-full resize-none rounded-md border border-none bg-transparent px-3 py-1.5 focus:outline-none [&::-webkit-scrollbar]:!invisible"
190
+ placeholder={placeholder}
191
+ value={prompt}
192
+ onChange={(e) => onChange(e.target.value)}
193
+ autoComplete="off"
194
+ data-1p-ignore="true"
195
+ data-dashlane-disabled-on-field="true"
196
+ ref={textAreaRef}
197
+ spellCheck={false}
198
+ onInput={(e) => {
199
+ if (e.currentTarget.parentNode) {
200
+ ;(
201
+ e.currentTarget.parentNode as HTMLElement
202
+ ).dataset.replicatedValue = e.currentTarget.value
203
+ }
204
+ }}
205
+ />
206
+ </div>
207
+
208
+ <div id="actions-bar" className="flex items-center p-2">
209
+ <div
210
+ id="file-upload"
211
+ className={cn(
212
+ 'text-foreground hover:bg-accent/80 relative flex cursor-pointer items-center gap-1 rounded-md p-1.5',
213
+ attachments.length >= maxAttachments &&
214
+ 'cursor-not-allowed opacity-50'
215
+ )}
216
+ onClick={() => {
217
+ if (attachments.length >= maxAttachments) {
218
+ return
219
+ }
220
+
221
+ fileInputRefInternal.current?.click()
222
+ }}
223
+ >
224
+ <Icon name="paperclip" className="h-4 w-4" />
225
+ <input
226
+ type="file"
227
+ ref={fileInputRef}
228
+ className="absolute inset-0 hidden h-full w-full"
229
+ onChange={(e) => handleFiles(Array.from(e.target.files ?? []))}
230
+ accept={acceptedFileTypes?.join(',')}
231
+ />
232
+ </div>
233
+ <div className="ml-auto">
234
+ <motion.button
235
+ onClick={(e) => {
236
+ e.preventDefault()
237
+ e.stopPropagation()
238
+ onSubmit(e)
239
+ }}
240
+ className="bg-foreground/5 text-foreground/60 dark:bg-foreground dark:text-background disabled:!bg-background/70 disabled:!text-body-muted rounded-md border p-2"
241
+ disabled={isDisabled || isSubmitting}
242
+ title={
243
+ !prompt
244
+ ? 'Enter a prompt to submit'
245
+ : isSubmitting
246
+ ? 'Submitting...'
247
+ : ''
248
+ }
249
+ whileHover={
250
+ (prompt && !isSubmitting && { scale: 1.05 }) || undefined
251
+ }
252
+ whileTap={
253
+ (prompt && !isSubmitting && { scale: 0.95 }) || undefined
254
+ }
255
+ >
256
+ <Icon
257
+ name={isSubmitting ? submittingIcon : 'arrow-up'}
258
+ strokeWidth={2.5}
259
+ className={cn(isSubmitting && 'animate-spin')}
260
+ />
261
+ </motion.button>
262
+ </div>
263
+ </div>
264
+ </div>
265
+
266
+ {suggestions.length > 0 && (
267
+ <div className="mt-4 flex w-full flex-row flex-wrap gap-3">
268
+ {suggestions.map((suggestion) => (
269
+ <button
270
+ key={suggestion.label}
271
+ className={cn(
272
+ 'bg-foreground/5 hover:bg-foreground/10 text-foreground/80 relative flex cursor-pointer flex-row items-center gap-1.5 rounded-md border px-2.5 py-2 text-sm tracking-tight whitespace-nowrap select-none',
273
+ suggestion.className
274
+ )}
275
+ onClick={() => suggestion.onClick(suggestion.id)}
276
+ >
277
+ {suggestion.icon && (
278
+ <Icon
279
+ name={suggestion.icon}
280
+ className={cn(
281
+ 'stroke-primary relative size-4',
282
+ suggestion.iconClassName
283
+ )}
284
+ strokeWidth={1}
285
+ />
286
+ )}
287
+ {suggestion.label}
288
+ </button>
289
+ ))}
290
+ </div>
291
+ )}
292
+ </div>
293
+ )
294
+ }
295
+
296
+ function AttachmentPreview({ attachment }: { attachment: Attachment }) {
297
+ const [img, setImg] = useState<string | null>(null)
298
+
299
+ useEffect(() => {
300
+ async function readFile() {
301
+ if (!attachment.type.startsWith('image/')) {
302
+ return // Only process image files
303
+ }
304
+
305
+ const reader = new FileReader()
306
+ reader.onloadend = () => setImg(reader.result as string)
307
+
308
+ try {
309
+ reader.readAsDataURL(
310
+ new Blob([attachment.bytes], { type: attachment.type })
311
+ )
312
+ } catch (error) {
313
+ console.error('Error reading file:', error)
314
+ }
315
+ }
316
+
317
+ readFile()
318
+ }, [attachment])
319
+
320
+ const icon = useMemo<IconName>(() => {
321
+ switch (attachment.type) {
322
+ // TODO: add more as and when
323
+ case 'application/x-yaml':
324
+ case 'application/yaml':
325
+ case 'application/json':
326
+ return 'file-code'
327
+ case 'text/plain':
328
+ return 'file-text'
329
+ default:
330
+ return 'file'
331
+ }
332
+ }, [attachment.type])
333
+
334
+ return (
335
+ <motion.div
336
+ initial={{ opacity: 0, scale: 0 }}
337
+ animate={{ opacity: 1, scale: 1 }}
338
+ exit={{ opacity: 0, scale: 0 }}
339
+ className={cn(
340
+ 'bg-card flex flex-row items-center rounded-lg border px-1.5 py-1 text-xs',
341
+ img && 'gap-1.5'
342
+ )}
343
+ key={attachment.id}
344
+ >
345
+ <div className={cn('size-5', img && 'size-4')}>
346
+ {img ? (
347
+ <img
348
+ src={img}
349
+ className="size-full rounded-lg object-cover"
350
+ alt={attachment.name}
351
+ />
352
+ ) : (
353
+ <Icon name={icon} className="size-full py-1" />
354
+ )}
355
+ </div>
356
+ <div
357
+ title={attachment.name}
358
+ className="max-w-36 flex-1 truncate text-xs select-none"
359
+ >
360
+ {attachment.name}
361
+ </div>
362
+ {attachment.onRemove && (
363
+ <div
364
+ className="hover:text-foreground ml-1 cursor-pointer"
365
+ onClick={() => attachment.onRemove?.(attachment.id)}
366
+ >
367
+ <Icon name="x" className="size-3" />
368
+ </div>
369
+ )}
370
+ </motion.div>
371
+ )
372
+ }