@borisj74/bv-ds 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/index.cjs +33885 -0
  4. package/dist/index.d.cts +2715 -0
  5. package/dist/index.d.ts +2715 -0
  6. package/dist/index.js +33717 -0
  7. package/package.json +67 -0
  8. package/src/components/ActivityFeed/ActivityFeed.tsx +48 -0
  9. package/src/components/ActivityFeed/index.ts +2 -0
  10. package/src/components/ActivityGauge/ActivityGauge.tsx +155 -0
  11. package/src/components/ActivityGauge/index.ts +7 -0
  12. package/src/components/AdvancedFilterBar/AdvancedFilterBar.tsx +80 -0
  13. package/src/components/AdvancedFilterBar/index.ts +2 -0
  14. package/src/components/Alert/Alert.tsx +210 -0
  15. package/src/components/Alert/index.ts +2 -0
  16. package/src/components/Avatar/Avatar.tsx +111 -0
  17. package/src/components/Avatar/index.ts +2 -0
  18. package/src/components/AvatarAddButton/AvatarAddButton.tsx +65 -0
  19. package/src/components/AvatarAddButton/index.ts +5 -0
  20. package/src/components/AvatarGroup/AvatarGroup.tsx +79 -0
  21. package/src/components/AvatarGroup/index.ts +6 -0
  22. package/src/components/AvatarLabelGroup/AvatarLabelGroup.tsx +62 -0
  23. package/src/components/AvatarLabelGroup/index.ts +5 -0
  24. package/src/components/AvatarProfilePhoto/AvatarProfilePhoto.tsx +117 -0
  25. package/src/components/AvatarProfilePhoto/index.ts +5 -0
  26. package/src/components/Badge/ColorBadge.tsx +36 -0
  27. package/src/components/Badge/ModernBadge.tsx +38 -0
  28. package/src/components/Badge/PillBadge.tsx +36 -0
  29. package/src/components/Badge/badgeShared.tsx +139 -0
  30. package/src/components/Badge/index.ts +7 -0
  31. package/src/components/BadgeCloseX/BadgeCloseX.tsx +64 -0
  32. package/src/components/BadgeCloseX/index.ts +2 -0
  33. package/src/components/BadgeGroup/BadgeGroup.tsx +61 -0
  34. package/src/components/BadgeGroup/index.ts +7 -0
  35. package/src/components/BreadcrumbButtonBase/BreadcrumbButtonBase.tsx +75 -0
  36. package/src/components/BreadcrumbButtonBase/index.ts +5 -0
  37. package/src/components/Breadcrumbs/Breadcrumbs.tsx +62 -0
  38. package/src/components/Breadcrumbs/index.ts +2 -0
  39. package/src/components/Button/Button.tsx +71 -0
  40. package/src/components/Button/index.ts +2 -0
  41. package/src/components/ButtonCloseX/ButtonCloseX.tsx +54 -0
  42. package/src/components/ButtonCloseX/index.ts +2 -0
  43. package/src/components/ButtonDestructive/ButtonDestructive.tsx +67 -0
  44. package/src/components/ButtonDestructive/index.ts +6 -0
  45. package/src/components/ButtonGroup/ButtonGroup.tsx +28 -0
  46. package/src/components/ButtonGroup/index.ts +2 -0
  47. package/src/components/ButtonGroupSegment/ButtonGroupSegment.tsx +54 -0
  48. package/src/components/ButtonGroupSegment/index.ts +5 -0
  49. package/src/components/ButtonUtility/ButtonUtility.tsx +67 -0
  50. package/src/components/ButtonUtility/index.ts +6 -0
  51. package/src/components/CalendarCell/CalendarCell.tsx +82 -0
  52. package/src/components/CalendarCell/index.ts +2 -0
  53. package/src/components/CalendarCellDayWeekView/CalendarCellDayWeekView.tsx +56 -0
  54. package/src/components/CalendarCellDayWeekView/index.ts +2 -0
  55. package/src/components/CalendarColumnHeader/CalendarColumnHeader.tsx +45 -0
  56. package/src/components/CalendarColumnHeader/index.ts +5 -0
  57. package/src/components/CalendarDateIcon/CalendarDateIcon.tsx +25 -0
  58. package/src/components/CalendarDateIcon/index.ts +2 -0
  59. package/src/components/CalendarEvent/CalendarEvent.tsx +76 -0
  60. package/src/components/CalendarEvent/index.ts +2 -0
  61. package/src/components/CalendarEventDayWeekView/CalendarEventDayWeekView.tsx +76 -0
  62. package/src/components/CalendarEventDayWeekView/index.ts +2 -0
  63. package/src/components/CalendarHeader/CalendarHeader.tsx +47 -0
  64. package/src/components/CalendarHeader/index.ts +2 -0
  65. package/src/components/CalendarRowLabel/CalendarRowLabel.tsx +21 -0
  66. package/src/components/CalendarRowLabel/index.ts +2 -0
  67. package/src/components/CalendarTimemarker/CalendarTimemarker.tsx +46 -0
  68. package/src/components/CalendarTimemarker/index.ts +5 -0
  69. package/src/components/CalendarViewDropdown/CalendarViewDropdown.tsx +101 -0
  70. package/src/components/CalendarViewDropdown/index.ts +6 -0
  71. package/src/components/CardHeader/CardHeader.tsx +57 -0
  72. package/src/components/CardHeader/index.ts +2 -0
  73. package/src/components/CarouselArrow/CarouselArrow.tsx +47 -0
  74. package/src/components/CarouselArrow/index.ts +6 -0
  75. package/src/components/CarouselImage/CarouselImage.tsx +60 -0
  76. package/src/components/CarouselImage/index.ts +2 -0
  77. package/src/components/Change/Change.tsx +73 -0
  78. package/src/components/Change/index.ts +2 -0
  79. package/src/components/ChartLegend/ChartLegend.tsx +38 -0
  80. package/src/components/ChartLegend/index.ts +2 -0
  81. package/src/components/ChartMarker/ChartMarker.tsx +54 -0
  82. package/src/components/ChartMarker/index.ts +2 -0
  83. package/src/components/ChartMini/ChartMini.tsx +86 -0
  84. package/src/components/ChartMini/index.ts +2 -0
  85. package/src/components/ChartTooltip/ChartTooltip.tsx +44 -0
  86. package/src/components/ChartTooltip/index.ts +2 -0
  87. package/src/components/Checkbox/Checkbox.tsx +65 -0
  88. package/src/components/Checkbox/checkboxBase.tsx +81 -0
  89. package/src/components/Checkbox/index.ts +3 -0
  90. package/src/components/CodeSnippet/CodeSnippet.tsx +94 -0
  91. package/src/components/CodeSnippet/index.ts +2 -0
  92. package/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx +44 -0
  93. package/src/components/CodeSnippetTabs/index.ts +2 -0
  94. package/src/components/CommandBar/CommandBar.tsx +80 -0
  95. package/src/components/CommandBar/index.ts +2 -0
  96. package/src/components/CommandBarFooter/CommandBarFooter.tsx +125 -0
  97. package/src/components/CommandBarFooter/index.ts +5 -0
  98. package/src/components/CommandBarMenuSection/CommandBarMenuSection.tsx +28 -0
  99. package/src/components/CommandBarMenuSection/index.ts +2 -0
  100. package/src/components/CommandBarNavigationIcon/CommandBarNavigationIcon.tsx +47 -0
  101. package/src/components/CommandBarNavigationIcon/index.ts +2 -0
  102. package/src/components/CommandDropdownMenuItem/CommandDropdownMenuItem.tsx +51 -0
  103. package/src/components/CommandDropdownMenuItem/index.ts +2 -0
  104. package/src/components/CommandInput/CommandInput.tsx +74 -0
  105. package/src/components/CommandInput/index.ts +2 -0
  106. package/src/components/CommandShortcut/CommandShortcut.tsx +26 -0
  107. package/src/components/CommandShortcut/index.ts +2 -0
  108. package/src/components/ContentDivider/ContentDivider.tsx +80 -0
  109. package/src/components/ContentDivider/index.ts +6 -0
  110. package/src/components/ContentFeatureText/ContentFeatureText.tsx +60 -0
  111. package/src/components/ContentFeatureText/index.ts +5 -0
  112. package/src/components/ContentHeading/ContentHeading.tsx +43 -0
  113. package/src/components/ContentHeading/index.ts +5 -0
  114. package/src/components/ContentParagraph/ContentParagraph.tsx +39 -0
  115. package/src/components/ContentParagraph/index.ts +5 -0
  116. package/src/components/ContentQuote/ContentQuote.tsx +114 -0
  117. package/src/components/ContentQuote/index.ts +6 -0
  118. package/src/components/ContentRule/ContentRule.tsx +31 -0
  119. package/src/components/ContentRule/index.ts +2 -0
  120. package/src/components/ContextMenu/ContextMenu.tsx +67 -0
  121. package/src/components/ContextMenu/index.ts +7 -0
  122. package/src/components/ContextMenu/useContextMenu.ts +41 -0
  123. package/src/components/DatePickerCell/DatePickerCell.tsx +77 -0
  124. package/src/components/DatePickerCell/index.ts +2 -0
  125. package/src/components/DatePickerListItem/DatePickerListItem.tsx +39 -0
  126. package/src/components/DatePickerListItem/index.ts +2 -0
  127. package/src/components/DatePickerMenu/DatePickerMenu.tsx +131 -0
  128. package/src/components/DatePickerMenu/index.ts +2 -0
  129. package/src/components/DropdownAccountListItem/DropdownAccountListItem.tsx +69 -0
  130. package/src/components/DropdownAccountListItem/index.ts +2 -0
  131. package/src/components/DropdownMenuFooter/DropdownMenuFooter.tsx +50 -0
  132. package/src/components/DropdownMenuFooter/index.ts +5 -0
  133. package/src/components/DropdownMenuHeader/DropdownMenuHeader.tsx +93 -0
  134. package/src/components/DropdownMenuHeader/index.ts +5 -0
  135. package/src/components/DropdownMenuItemInsetIcon/DropdownMenuItemInsetIcon.tsx +89 -0
  136. package/src/components/DropdownMenuItemInsetIcon/index.ts +5 -0
  137. package/src/components/DropdownMenuListItem/DropdownMenuListItem.tsx +84 -0
  138. package/src/components/DropdownMenuListItem/index.ts +2 -0
  139. package/src/components/EmptyState/EmptyState.tsx +65 -0
  140. package/src/components/EmptyState/index.ts +2 -0
  141. package/src/components/FeedItemBase/FeedItemBase.tsx +135 -0
  142. package/src/components/FeedItemBase/index.ts +2 -0
  143. package/src/components/FileUpload/FileUpload.tsx +112 -0
  144. package/src/components/FileUpload/index.ts +2 -0
  145. package/src/components/FileUploadBase/FileUploadBase.tsx +69 -0
  146. package/src/components/FileUploadBase/index.ts +2 -0
  147. package/src/components/FileUploadItemBase/FileUploadItemBase.tsx +190 -0
  148. package/src/components/FileUploadItemBase/index.ts +7 -0
  149. package/src/components/FilterBar/FilterBar.tsx +62 -0
  150. package/src/components/FilterBar/index.ts +2 -0
  151. package/src/components/FilterTabs/FilterTabs.tsx +41 -0
  152. package/src/components/FilterTabs/index.ts +2 -0
  153. package/src/components/FiltersDropdownMenu/FiltersDropdownMenu.tsx +104 -0
  154. package/src/components/FiltersDropdownMenu/index.ts +2 -0
  155. package/src/components/FiltersSlideoutMenu/FiltersSlideoutMenu.tsx +71 -0
  156. package/src/components/FiltersSlideoutMenu/index.ts +2 -0
  157. package/src/components/HeaderNavigation/HeaderNavigation.tsx +178 -0
  158. package/src/components/HeaderNavigation/index.ts +6 -0
  159. package/src/components/HelpIcon/HelpIcon.tsx +49 -0
  160. package/src/components/HelpIcon/index.ts +2 -0
  161. package/src/components/InputField/InputField.tsx +108 -0
  162. package/src/components/InputField/index.ts +3 -0
  163. package/src/components/InputField/inputFieldShared.tsx +68 -0
  164. package/src/components/LeadingInputField/LeadingInputField.tsx +60 -0
  165. package/src/components/LeadingInputField/index.ts +2 -0
  166. package/src/components/LineAndBarChart/LineAndBarChart.tsx +96 -0
  167. package/src/components/LineAndBarChart/index.ts +2 -0
  168. package/src/components/LinkMessage/LinkMessage.tsx +52 -0
  169. package/src/components/LinkMessage/index.ts +2 -0
  170. package/src/components/LoadingIndicator/LoadingIndicator.tsx +108 -0
  171. package/src/components/LoadingIndicator/index.ts +6 -0
  172. package/src/components/MediaMessage/MediaMessage.tsx +109 -0
  173. package/src/components/MediaMessage/index.ts +2 -0
  174. package/src/components/MegaInputFieldBase/MegaInputFieldBase.tsx +49 -0
  175. package/src/components/MegaInputFieldBase/index.ts +5 -0
  176. package/src/components/Message/Message.tsx +85 -0
  177. package/src/components/Message/index.ts +3 -0
  178. package/src/components/Message/messageShared.tsx +73 -0
  179. package/src/components/MessageAction/MessageAction.tsx +221 -0
  180. package/src/components/MessageAction/index.ts +2 -0
  181. package/src/components/MessageActionButton/MessageActionButton.tsx +36 -0
  182. package/src/components/MessageActionButton/index.ts +2 -0
  183. package/src/components/MessageActionPanel/MessageActionPanel.tsx +36 -0
  184. package/src/components/MessageActionPanel/index.ts +2 -0
  185. package/src/components/MessageReaction/MessageReaction.tsx +37 -0
  186. package/src/components/MessageReaction/index.ts +2 -0
  187. package/src/components/MessageStatusIcon/MessageStatusIcon.tsx +54 -0
  188. package/src/components/MessageStatusIcon/index.ts +2 -0
  189. package/src/components/MetricItem/MetricItem.tsx +147 -0
  190. package/src/components/MetricItem/index.ts +2 -0
  191. package/src/components/ModalActions/ModalActions.tsx +57 -0
  192. package/src/components/ModalActions/index.ts +2 -0
  193. package/src/components/ModalHeader/ModalHeader.tsx +99 -0
  194. package/src/components/ModalHeader/index.ts +2 -0
  195. package/src/components/MultiSelect/MultiSelect.tsx +118 -0
  196. package/src/components/MultiSelect/index.ts +2 -0
  197. package/src/components/NavAccountCard/NavAccountCard.tsx +124 -0
  198. package/src/components/NavAccountCard/index.ts +2 -0
  199. package/src/components/NavAccountCardMenuItem/NavAccountCardMenuItem.tsx +101 -0
  200. package/src/components/NavAccountCardMenuItem/index.ts +5 -0
  201. package/src/components/NavButton/NavButton.tsx +50 -0
  202. package/src/components/NavButton/index.ts +2 -0
  203. package/src/components/NavFeaturedCard/NavFeaturedCard.tsx +82 -0
  204. package/src/components/NavFeaturedCard/index.ts +2 -0
  205. package/src/components/NavItemBase/NavItemBase.tsx +79 -0
  206. package/src/components/NavItemBase/index.ts +2 -0
  207. package/src/components/NavItemDropdownBase/NavItemDropdownBase.tsx +74 -0
  208. package/src/components/NavItemDropdownBase/index.ts +2 -0
  209. package/src/components/NavMenuButton/NavMenuButton.tsx +47 -0
  210. package/src/components/NavMenuButton/index.ts +2 -0
  211. package/src/components/Notification/Notification.tsx +102 -0
  212. package/src/components/Notification/index.ts +2 -0
  213. package/src/components/NumberInput/NumberInput.tsx +114 -0
  214. package/src/components/NumberInput/index.ts +2 -0
  215. package/src/components/PageHeader/PageHeader.tsx +88 -0
  216. package/src/components/PageHeader/index.ts +2 -0
  217. package/src/components/Pagination/Pagination.tsx +124 -0
  218. package/src/components/Pagination/index.ts +2 -0
  219. package/src/components/PaginationButtonGroupBase/PaginationButtonGroupBase.tsx +69 -0
  220. package/src/components/PaginationButtonGroupBase/index.ts +5 -0
  221. package/src/components/PaginationCards/PaginationCards.tsx +72 -0
  222. package/src/components/PaginationCards/index.ts +2 -0
  223. package/src/components/PaginationDotGroup/PaginationDotGroup.tsx +66 -0
  224. package/src/components/PaginationDotGroup/index.ts +2 -0
  225. package/src/components/PaginationDotIndicator/PaginationDotIndicator.tsx +39 -0
  226. package/src/components/PaginationDotIndicator/index.ts +6 -0
  227. package/src/components/PaginationNumberBase/PaginationNumberBase.tsx +42 -0
  228. package/src/components/PaginationNumberBase/index.ts +5 -0
  229. package/src/components/PieChart/PieChart.tsx +73 -0
  230. package/src/components/PieChart/index.ts +2 -0
  231. package/src/components/ProgressBar/ProgressBar.tsx +75 -0
  232. package/src/components/ProgressBar/index.ts +2 -0
  233. package/src/components/ProgressCircle/ProgressCircle.tsx +89 -0
  234. package/src/components/ProgressCircle/index.ts +6 -0
  235. package/src/components/RadarChart/RadarChart.tsx +62 -0
  236. package/src/components/RadarChart/index.ts +2 -0
  237. package/src/components/Radio/Radio.tsx +55 -0
  238. package/src/components/Radio/index.ts +2 -0
  239. package/src/components/RadioGroup/RadioGroup.tsx +54 -0
  240. package/src/components/RadioGroup/index.ts +2 -0
  241. package/src/components/RadioGroupItem/RadioGroupItem.tsx +118 -0
  242. package/src/components/RadioGroupItem/index.ts +6 -0
  243. package/src/components/SectionFooter/SectionFooter.tsx +40 -0
  244. package/src/components/SectionFooter/index.ts +2 -0
  245. package/src/components/SectionHeader/SectionHeader.tsx +44 -0
  246. package/src/components/SectionHeader/index.ts +2 -0
  247. package/src/components/SectionLabel/SectionLabel.tsx +51 -0
  248. package/src/components/SectionLabel/index.ts +2 -0
  249. package/src/components/Select/Select.tsx +121 -0
  250. package/src/components/Select/index.ts +2 -0
  251. package/src/components/SelectMenuItem/SelectMenuItem.tsx +85 -0
  252. package/src/components/SelectMenuItem/index.ts +2 -0
  253. package/src/components/SidebarNavigation/SidebarNavigation.tsx +100 -0
  254. package/src/components/SidebarNavigation/index.ts +2 -0
  255. package/src/components/SlideOutMenuHeader/SlideOutMenuHeader.tsx +56 -0
  256. package/src/components/SlideOutMenuHeader/index.ts +2 -0
  257. package/src/components/Slider/Slider.tsx +125 -0
  258. package/src/components/Slider/index.ts +2 -0
  259. package/src/components/SocialButton/SocialButton.tsx +88 -0
  260. package/src/components/SocialButton/index.ts +2 -0
  261. package/src/components/StatusIcon/StatusIcon.tsx +75 -0
  262. package/src/components/StatusIcon/index.ts +2 -0
  263. package/src/components/StepBase/StepBase.tsx +90 -0
  264. package/src/components/StepBase/index.ts +2 -0
  265. package/src/components/StepIconBase/StepIconBase.tsx +65 -0
  266. package/src/components/StepIconBase/index.ts +7 -0
  267. package/src/components/TabButtonBase/TabButtonBase.tsx +88 -0
  268. package/src/components/TabButtonBase/index.ts +2 -0
  269. package/src/components/TableCell/TableCell.tsx +44 -0
  270. package/src/components/TableCell/index.ts +2 -0
  271. package/src/components/TableHeaderCell/TableHeaderCell.tsx +34 -0
  272. package/src/components/TableHeaderCell/index.ts +2 -0
  273. package/src/components/TableHeaderLabel/TableHeaderLabel.tsx +37 -0
  274. package/src/components/TableHeaderLabel/index.ts +2 -0
  275. package/src/components/Tabs/Tabs.tsx +80 -0
  276. package/src/components/Tabs/index.ts +2 -0
  277. package/src/components/Tag/Tag.tsx +91 -0
  278. package/src/components/Tag/index.ts +2 -0
  279. package/src/components/TagsInputField/TagsInputField.tsx +90 -0
  280. package/src/components/TagsInputField/index.ts +2 -0
  281. package/src/components/TextEditorToolbar/TextEditorToolbar.tsx +33 -0
  282. package/src/components/TextEditorToolbar/index.ts +2 -0
  283. package/src/components/TextEditorTooltip/TextEditorTooltip.tsx +28 -0
  284. package/src/components/TextEditorTooltip/index.ts +2 -0
  285. package/src/components/TextareaInputField/TextareaInputField.tsx +45 -0
  286. package/src/components/TextareaInputField/index.ts +2 -0
  287. package/src/components/Toggle/Toggle.tsx +87 -0
  288. package/src/components/Toggle/index.ts +2 -0
  289. package/src/components/Tooltip/Tooltip.tsx +59 -0
  290. package/src/components/Tooltip/index.ts +2 -0
  291. package/src/components/TrailingInputField/TrailingInputField.tsx +62 -0
  292. package/src/components/TrailingInputField/index.ts +2 -0
  293. package/src/components/TreeView/TreeView.tsx +86 -0
  294. package/src/components/TreeView/index.ts +2 -0
  295. package/src/components/TreeViewConnector/TreeViewConnector.tsx +36 -0
  296. package/src/components/TreeViewConnector/index.ts +2 -0
  297. package/src/components/TreeViewItem/TreeViewItem.tsx +111 -0
  298. package/src/components/TreeViewItem/index.ts +2 -0
  299. package/src/components/VerificationCodeInput/VerificationCodeInput.tsx +114 -0
  300. package/src/components/VerificationCodeInput/index.ts +2 -0
  301. package/src/illustrations/BoxIllustration.tsx +13 -0
  302. package/src/illustrations/CloudIllustration.tsx +18 -0
  303. package/src/illustrations/CreditCardIllustration.tsx +13 -0
  304. package/src/illustrations/DocumentsIllustration.tsx +13 -0
  305. package/src/illustrations/index.ts +4 -0
  306. package/src/index.ts +147 -0
  307. package/src/internal/chartTheme.ts +30 -0
  308. package/src/internal/ringBase.tsx +82 -0
  309. package/src/styles.css +3 -0
  310. package/tailwind-preset.js +295 -0
@@ -0,0 +1,50 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type DropdownMenuFooterType = "text" | "button";
5
+
6
+ export interface DropdownMenuFooterProps {
7
+ /** `text` shows a left/right caption pair; `button` hosts an action. */
8
+ type?: DropdownMenuFooterType;
9
+ /** Left caption for `type="text"`. */
10
+ left?: ReactNode;
11
+ /** Right caption for `type="text"`. */
12
+ right?: ReactNode;
13
+ /** Action content for `type="button"` — compose a Button. */
14
+ children?: ReactNode;
15
+ className?: string;
16
+ }
17
+
18
+ /** The bottom section of a dropdown menu panel. */
19
+ export function DropdownMenuFooter({
20
+ type = "button",
21
+ left,
22
+ right,
23
+ children,
24
+ className,
25
+ }: DropdownMenuFooterProps) {
26
+ if (type === "text") {
27
+ return (
28
+ <div
29
+ className={clsx(
30
+ "flex items-center justify-between border-t border-border-secondary px-xl py-lg font-body text-sm font-normal text-text-quaternary",
31
+ className,
32
+ )}
33
+ >
34
+ <span>{left}</span>
35
+ <span>{right}</span>
36
+ </div>
37
+ );
38
+ }
39
+
40
+ return (
41
+ <div
42
+ className={clsx(
43
+ "flex items-center border-t border-border-secondary p-lg font-body [&>*]:flex-1",
44
+ className,
45
+ )}
46
+ >
47
+ {children}
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1,5 @@
1
+ export { DropdownMenuFooter } from "./DropdownMenuFooter";
2
+ export type {
3
+ DropdownMenuFooterProps,
4
+ DropdownMenuFooterType,
5
+ } from "./DropdownMenuFooter";
@@ -0,0 +1,93 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type DropdownMenuHeaderType =
5
+ | "avatar-group"
6
+ | "header"
7
+ | "subheading"
8
+ | "search";
9
+
10
+ export interface DropdownMenuHeaderProps {
11
+ /** Header layout. */
12
+ type?: DropdownMenuHeaderType;
13
+ /** Primary text (name / heading / subheading label). */
14
+ title?: ReactNode;
15
+ /** Secondary line (email / supporting text). */
16
+ supportingText?: ReactNode;
17
+ /** Avatar node for `avatar-group`. */
18
+ avatar?: ReactNode;
19
+ /** Search control for `search` (compose your own input). */
20
+ search?: ReactNode;
21
+ className?: string;
22
+ }
23
+
24
+ /** The top section of a dropdown menu panel. */
25
+ export function DropdownMenuHeader({
26
+ type = "header",
27
+ title,
28
+ supportingText,
29
+ avatar,
30
+ search,
31
+ className,
32
+ }: DropdownMenuHeaderProps) {
33
+ if (type === "subheading") {
34
+ return (
35
+ <div className={clsx("px-xl pb-xxs pt-sm font-body", className)}>
36
+ <p className="text-xs font-semibold text-text-brand-secondary">{title}</p>
37
+ </div>
38
+ );
39
+ }
40
+
41
+ if (type === "search") {
42
+ return (
43
+ <div
44
+ className={clsx(
45
+ "border-b border-border-secondary p-lg font-body",
46
+ className,
47
+ )}
48
+ >
49
+ {search}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ if (type === "avatar-group") {
55
+ return (
56
+ <div
57
+ className={clsx(
58
+ "flex items-center gap-md border-b border-border-secondary p-lg font-body",
59
+ className,
60
+ )}
61
+ >
62
+ {avatar ? <div className="shrink-0">{avatar}</div> : null}
63
+ <div className="flex min-w-0 flex-1 flex-col">
64
+ <p className="truncate text-sm font-semibold text-text-primary">
65
+ {title}
66
+ </p>
67
+ {supportingText ? (
68
+ <p className="truncate text-sm font-normal text-text-tertiary">
69
+ {supportingText}
70
+ </p>
71
+ ) : null}
72
+ </div>
73
+ </div>
74
+ );
75
+ }
76
+
77
+ // header
78
+ return (
79
+ <div
80
+ className={clsx(
81
+ "flex flex-col border-b border-border-secondary px-xl py-lg font-body",
82
+ className,
83
+ )}
84
+ >
85
+ <p className="truncate text-sm font-semibold text-text-primary">{title}</p>
86
+ {supportingText ? (
87
+ <p className="truncate text-sm font-normal text-text-tertiary">
88
+ {supportingText}
89
+ </p>
90
+ ) : null}
91
+ </div>
92
+ );
93
+ }
@@ -0,0 +1,5 @@
1
+ export { DropdownMenuHeader } from "./DropdownMenuHeader";
2
+ export type {
3
+ DropdownMenuHeaderProps,
4
+ DropdownMenuHeaderType,
5
+ } from "./DropdownMenuHeader";
@@ -0,0 +1,89 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type DropdownMenuItemInsetIconType =
5
+ | "spacer"
6
+ | "icon"
7
+ | "check"
8
+ | "checkbox"
9
+ | "dot"
10
+ | "avatar"
11
+ | "integration-icon";
12
+
13
+ export interface DropdownMenuItemInsetIconProps {
14
+ /** Which leading visual to render in the 16px slot. */
15
+ type?: DropdownMenuItemInsetIconType;
16
+ /** Glyph/avatar/integration content for `icon`/`avatar`/`integration-icon`. */
17
+ children?: ReactNode;
18
+ /** Checked state for `checkbox`. */
19
+ checked?: boolean;
20
+ className?: string;
21
+ }
22
+
23
+ /**
24
+ * The 16px leading-icon slot used inside a dropdown menu row. Renders one of
25
+ * several visuals (icon, check, checkbox, radio dot, avatar, integration icon)
26
+ * or an empty spacer to keep labels aligned.
27
+ */
28
+ export function DropdownMenuItemInsetIcon({
29
+ type = "spacer",
30
+ children,
31
+ checked = false,
32
+ className,
33
+ }: DropdownMenuItemInsetIconProps) {
34
+ return (
35
+ <span
36
+ className={clsx(
37
+ "relative flex size-4 shrink-0 items-center justify-center",
38
+ className,
39
+ )}
40
+ >
41
+ {type === "icon" ? (
42
+ <span className="flex size-4 items-center justify-center text-fg-quaternary">
43
+ {children}
44
+ </span>
45
+ ) : null}
46
+ {type === "check" ? (
47
+ <svg viewBox="0 0 16 16" fill="none" className="size-4 text-fg-brand-primary" aria-hidden>
48
+ <path
49
+ d="M13.333 4 6 11.333 2.667 8"
50
+ stroke="currentColor"
51
+ strokeWidth="1.5"
52
+ strokeLinecap="round"
53
+ strokeLinejoin="round"
54
+ />
55
+ </svg>
56
+ ) : null}
57
+ {type === "checkbox" ? (
58
+ <span
59
+ className={clsx(
60
+ "flex size-4 items-center justify-center rounded-xs border",
61
+ checked
62
+ ? "border-border-brand bg-bg-brand-solid text-text-white"
63
+ : "border-border-primary bg-bg-primary",
64
+ )}
65
+ >
66
+ {checked ? (
67
+ <svg viewBox="0 0 16 16" fill="none" className="size-3" aria-hidden>
68
+ <path
69
+ d="M13.333 4 6 11.333 2.667 8"
70
+ stroke="currentColor"
71
+ strokeWidth="1.667"
72
+ strokeLinecap="round"
73
+ strokeLinejoin="round"
74
+ />
75
+ </svg>
76
+ ) : null}
77
+ </span>
78
+ ) : null}
79
+ {type === "dot" ? (
80
+ <span className="size-[6px] rounded-full bg-fg-brand-primary" aria-hidden />
81
+ ) : null}
82
+ {type === "avatar" || type === "integration-icon" ? (
83
+ <span className="flex size-5 items-center justify-center overflow-hidden rounded-full">
84
+ {children}
85
+ </span>
86
+ ) : null}
87
+ </span>
88
+ );
89
+ }
@@ -0,0 +1,5 @@
1
+ export { DropdownMenuItemInsetIcon } from "./DropdownMenuItemInsetIcon";
2
+ export type {
3
+ DropdownMenuItemInsetIconProps,
4
+ DropdownMenuItemInsetIconType,
5
+ } from "./DropdownMenuItemInsetIcon";
@@ -0,0 +1,84 @@
1
+ import type { ButtonHTMLAttributes, ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface DropdownMenuListItemProps
5
+ extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
6
+ /** Leading visual — typically a DropdownMenuItemInsetIcon. */
7
+ leadingIcon?: ReactNode;
8
+ /** Trailing keyboard-shortcut hint. */
9
+ shortcut?: ReactNode;
10
+ /** Shows the trailing chevron (submenu affordance). */
11
+ chevron?: boolean;
12
+ /** Renders a divider rule instead of an interactive row. */
13
+ divider?: boolean;
14
+ /** Highlights the row as currently active/open. */
15
+ selected?: boolean;
16
+ children?: ReactNode;
17
+ }
18
+
19
+ function ChevronRight() {
20
+ return (
21
+ <svg viewBox="0 0 16 16" fill="none" className="size-4 shrink-0 text-fg-quaternary" aria-hidden>
22
+ <path
23
+ d="M6 12l4-4-4-4"
24
+ stroke="currentColor"
25
+ strokeWidth="1.333"
26
+ strokeLinecap="round"
27
+ strokeLinejoin="round"
28
+ />
29
+ </svg>
30
+ );
31
+ }
32
+
33
+ /**
34
+ * A single row in a dropdown menu — leading icon, label, optional shortcut and
35
+ * submenu chevron. Pass `divider` to render a separator rule instead.
36
+ */
37
+ export function DropdownMenuListItem({
38
+ leadingIcon,
39
+ shortcut,
40
+ chevron = false,
41
+ divider = false,
42
+ selected = false,
43
+ children,
44
+ className,
45
+ disabled,
46
+ ...rest
47
+ }: DropdownMenuListItemProps) {
48
+ if (divider) {
49
+ return (
50
+ <div className="flex w-full items-center py-xs" role="separator">
51
+ <span className="h-px flex-1 bg-border-secondary" />
52
+ </div>
53
+ );
54
+ }
55
+
56
+ return (
57
+ <div className="flex w-full items-center px-sm py-px">
58
+ <button
59
+ type="button"
60
+ disabled={disabled}
61
+ className={clsx(
62
+ "flex flex-1 items-center gap-md overflow-hidden rounded-sm py-md pl-[10px] pr-sm font-body text-sm font-semibold",
63
+ "outline-none transition-colors",
64
+ "focus-visible:ring-2 focus-visible:ring-border-brand",
65
+ selected
66
+ ? "bg-bg-primary-hover text-text-secondary-hover"
67
+ : "text-text-secondary hover:bg-bg-primary-hover hover:text-text-secondary-hover",
68
+ disabled && "pointer-events-none opacity-50",
69
+ className,
70
+ )}
71
+ {...rest}
72
+ >
73
+ {leadingIcon ? <span className="shrink-0">{leadingIcon}</span> : null}
74
+ <span className="min-w-0 flex-1 truncate text-left">{children}</span>
75
+ {shortcut ? (
76
+ <span className="shrink-0 pr-xs text-xs font-medium text-text-quaternary">
77
+ {shortcut}
78
+ </span>
79
+ ) : null}
80
+ {chevron ? <ChevronRight /> : null}
81
+ </button>
82
+ </div>
83
+ );
84
+ }
@@ -0,0 +1,2 @@
1
+ export { DropdownMenuListItem } from "./DropdownMenuListItem";
2
+ export type { DropdownMenuListItemProps } from "./DropdownMenuListItem";
@@ -0,0 +1,65 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type EmptyStateSize = "sm" | "md" | "lg";
5
+
6
+ export interface EmptyStateProps {
7
+ /**
8
+ * The icon/illustration area. Pass any of the 8 Figma options (featured
9
+ * icon, folder, file-type, illustration, users, integrations) as a node —
10
+ * EmptyState doesn't prescribe which.
11
+ */
12
+ icon?: ReactNode;
13
+ /** Headline. */
14
+ title: ReactNode;
15
+ /** Supporting copy under the title. */
16
+ description?: ReactNode;
17
+ /** Action buttons row — compose Button(s). */
18
+ actions?: ReactNode;
19
+ /** Size scale (affects title size + max text width). */
20
+ size?: EmptyStateSize;
21
+ className?: string;
22
+ }
23
+
24
+ // md verified: title text-lg. sm/lg inferred one step each.
25
+ const titleSize: Record<EmptyStateSize, string> = {
26
+ sm: "text-md",
27
+ md: "text-lg",
28
+ lg: "text-xl",
29
+ };
30
+
31
+ /**
32
+ * Centred empty/zero state — icon, title, supporting text, and actions.
33
+ * The icon area is a single slot (`icon`) per the resolved structural
34
+ * decision (one component, icon slot — not split per icon type).
35
+ */
36
+ export function EmptyState({
37
+ icon,
38
+ title,
39
+ description,
40
+ actions,
41
+ size = "md",
42
+ className,
43
+ }: EmptyStateProps) {
44
+ return (
45
+ <div
46
+ className={clsx(
47
+ "flex flex-col items-center gap-4xl font-body text-center",
48
+ className,
49
+ )}
50
+ >
51
+ <div className="flex flex-col items-center gap-2xl">
52
+ {icon ? <div className="shrink-0">{icon}</div> : null}
53
+ <div className="flex max-w-[352px] flex-col gap-md">
54
+ <p className={clsx("font-semibold text-text-primary", titleSize[size])}>
55
+ {title}
56
+ </p>
57
+ {description ? (
58
+ <p className="text-sm font-normal text-text-tertiary">{description}</p>
59
+ ) : null}
60
+ </div>
61
+ </div>
62
+ {actions ? <div className="flex items-start gap-lg">{actions}</div> : null}
63
+ </div>
64
+ );
65
+ }
@@ -0,0 +1,2 @@
1
+ export { EmptyState } from "./EmptyState";
2
+ export type { EmptyStateProps, EmptyStateSize } from "./EmptyState";
@@ -0,0 +1,135 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type FeedItemSize = "sm" | "md";
5
+
6
+ export interface FeedItemBaseProps {
7
+ /** Display name of the actor (e.g. "Olivia Rhye"). */
8
+ name: string;
9
+ /** Relative timestamp shown next to the name (e.g. "2 mins ago"). */
10
+ timestamp: string;
11
+ /**
12
+ * The activity line beneath the name — e.g. "Invited Lana Steiner to the
13
+ * team". Pass a ReactNode so embedded links can use
14
+ * `text-text-brand-secondary font-medium`.
15
+ */
16
+ action?: ReactNode;
17
+ /**
18
+ * Optional supporting content rendered below the action line. In Figma this
19
+ * is the `Supporting item` variant (File / Labels / Text). It's modelled as a
20
+ * slot rather than a `type` prop so consumers compose the actual content —
21
+ * which keeps the File sample's `Colors/Red/600` and the Labels sample's
22
+ * `utility-*` color families (both flagged in figma-map.md, neither in
23
+ * tailwind-preset.js) out of this base component.
24
+ */
25
+ supporting?: ReactNode;
26
+ /** Avatar image URL. Falls back to a neutral placeholder when omitted. */
27
+ avatarSrc?: string;
28
+ /** Alt text for the avatar image. */
29
+ avatarAlt?: string;
30
+ /** Show the online status dot on the avatar. */
31
+ hasStatus?: boolean;
32
+ /** Render the vertical connector line below the avatar (for stacked feeds). */
33
+ connector?: boolean;
34
+ /** Show the unread "new" dot in the top-right corner. */
35
+ isNew?: boolean;
36
+ size?: FeedItemSize;
37
+ className?: string;
38
+ }
39
+
40
+ const avatarSize: Record<FeedItemSize, string> = {
41
+ sm: "size-8", // 32px
42
+ md: "size-10", // 40px
43
+ };
44
+
45
+ const statusSize: Record<FeedItemSize, string> = {
46
+ sm: "size-3", // 12px
47
+ md: "size-3.5", // 14px
48
+ };
49
+
50
+ export function FeedItemBase({
51
+ name,
52
+ timestamp,
53
+ action,
54
+ supporting,
55
+ avatarSrc,
56
+ avatarAlt = "",
57
+ hasStatus = false,
58
+ connector = false,
59
+ isNew = false,
60
+ size = "sm",
61
+ className,
62
+ }: FeedItemBaseProps) {
63
+ return (
64
+ <div
65
+ className={clsx(
66
+ "relative flex w-full items-start gap-lg font-body",
67
+ className,
68
+ )}
69
+ >
70
+ {/* Avatar column (+ connector line) */}
71
+ <div
72
+ className={clsx(
73
+ "flex shrink-0 flex-col items-center gap-sm",
74
+ connector && "self-stretch pb-sm",
75
+ )}
76
+ >
77
+ <div className={clsx("relative shrink-0", avatarSize[size])}>
78
+ <div className="size-full overflow-hidden rounded-full border-[0.5px] border-black/[0.16] bg-bg-quaternary">
79
+ {avatarSrc ? (
80
+ <img
81
+ src={avatarSrc}
82
+ alt={avatarAlt}
83
+ className="size-full object-cover"
84
+ />
85
+ ) : null}
86
+ </div>
87
+ {hasStatus ? (
88
+ <span
89
+ className={clsx(
90
+ "absolute -bottom-0.5 -right-0.5 rounded-full border-[1.5px] border-bg-primary bg-fg-success-secondary",
91
+ statusSize[size],
92
+ )}
93
+ />
94
+ ) : null}
95
+ </div>
96
+ {connector ? (
97
+ <div className="w-px flex-1 bg-border-primary" aria-hidden />
98
+ ) : null}
99
+ </div>
100
+
101
+ {/* Content column */}
102
+ <div
103
+ className={clsx(
104
+ "flex min-w-0 flex-1 flex-col",
105
+ supporting ? "gap-lg" : "gap-none",
106
+ connector && "pb-4xl",
107
+ )}
108
+ >
109
+ <div className="flex flex-col items-start">
110
+ <div className="flex w-full items-center gap-md">
111
+ <span className="text-sm font-medium text-text-secondary">
112
+ {name}
113
+ </span>
114
+ <span className="text-xs font-normal text-text-tertiary">
115
+ {timestamp}
116
+ </span>
117
+ </div>
118
+ {action ? (
119
+ <div className="text-sm font-normal text-text-tertiary">
120
+ {action}
121
+ </div>
122
+ ) : null}
123
+ </div>
124
+ {supporting ? <div>{supporting}</div> : null}
125
+ </div>
126
+
127
+ {isNew ? (
128
+ <span
129
+ className="absolute right-0 top-0 size-2 rounded-full bg-fg-brand-primary"
130
+ aria-label="Unread"
131
+ />
132
+ ) : null}
133
+ </div>
134
+ );
135
+ }
@@ -0,0 +1,2 @@
1
+ export { FeedItemBase } from "./FeedItemBase";
2
+ export type { FeedItemBaseProps, FeedItemSize } from "./FeedItemBase";
@@ -0,0 +1,112 @@
1
+ import { useRef, useState, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import { FileUploadBase } from "../FileUploadBase";
4
+ import { FileUploadItemBase } from "../FileUploadItemBase";
5
+
6
+ export interface FileUploadProps {
7
+ /** Selected files (controlled). */
8
+ files?: File[];
9
+ onFilesChange?: (files: File[]) => void;
10
+ /** Max number of files kept; extra picks are dropped. */
11
+ maxFiles?: number;
12
+ /** Accepted MIME types / extensions for the native picker. */
13
+ accept?: string;
14
+ disabled?: boolean;
15
+ actionText?: ReactNode;
16
+ promptText?: ReactNode;
17
+ hint?: ReactNode;
18
+ className?: string;
19
+ }
20
+
21
+ const formatBytes = (n: number) => {
22
+ if (n < 1024) return `${n} B`;
23
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(0)} KB`;
24
+ return `${(n / 1024 / 1024).toFixed(1)} MB`;
25
+ };
26
+
27
+ /**
28
+ * File upload — composes the `FileUploadBase` dropzone (click + drag/drop, via a
29
+ * hidden native input) with a `FileUploadItemBase` list. Controlled through
30
+ * `files`/`onFilesChange`; respects `maxFiles` and `accept`. The item rows here
31
+ * are simple "complete" entries — wire `progress`/`status` per item if you need
32
+ * live upload state.
33
+ */
34
+ export function FileUpload({
35
+ files = [],
36
+ onFilesChange,
37
+ maxFiles = Infinity,
38
+ accept,
39
+ disabled = false,
40
+ actionText,
41
+ promptText,
42
+ hint,
43
+ className,
44
+ }: FileUploadProps) {
45
+ const inputRef = useRef<HTMLInputElement>(null);
46
+ const [dragActive, setDragActive] = useState(false);
47
+
48
+ const addFiles = (incoming: FileList | null) => {
49
+ if (!incoming?.length) return;
50
+ const merged = [...files, ...Array.from(incoming)].slice(0, maxFiles);
51
+ onFilesChange?.(merged);
52
+ };
53
+
54
+ const removeAt = (i: number) => onFilesChange?.(files.filter((_, idx) => idx !== i));
55
+
56
+ return (
57
+ <div className={clsx("flex flex-col gap-lg font-body", className)}>
58
+ <label
59
+ className={clsx("block", disabled ? "cursor-not-allowed" : "cursor-pointer")}
60
+ onDragOver={(e) => {
61
+ if (disabled) return;
62
+ e.preventDefault();
63
+ setDragActive(true);
64
+ }}
65
+ onDragLeave={() => setDragActive(false)}
66
+ onDrop={(e) => {
67
+ if (disabled) return;
68
+ e.preventDefault();
69
+ setDragActive(false);
70
+ addFiles(e.dataTransfer.files);
71
+ }}
72
+ >
73
+ <input
74
+ ref={inputRef}
75
+ type="file"
76
+ multiple={maxFiles !== 1}
77
+ accept={accept}
78
+ disabled={disabled}
79
+ className="sr-only"
80
+ onChange={(e) => {
81
+ addFiles(e.target.files);
82
+ e.target.value = "";
83
+ }}
84
+ />
85
+ <FileUploadBase
86
+ actionText={actionText}
87
+ promptText={promptText}
88
+ hint={hint}
89
+ dragActive={dragActive}
90
+ disabled={disabled}
91
+ />
92
+ </label>
93
+
94
+ {files.length > 0 && (
95
+ <ul className="flex flex-col gap-md">
96
+ {files.map((f, i) => (
97
+ <li key={`${f.name}-${i}`}>
98
+ <FileUploadItemBase
99
+ fileName={f.name}
100
+ meta={formatBytes(f.size)}
101
+ status="complete"
102
+ progress={100}
103
+ fileExt={f.name.split(".").pop()?.toUpperCase()}
104
+ onDelete={() => removeAt(i)}
105
+ />
106
+ </li>
107
+ ))}
108
+ </ul>
109
+ )}
110
+ </div>
111
+ );
112
+ }
@@ -0,0 +1,2 @@
1
+ export { FileUpload } from "./FileUpload";
2
+ export type { FileUploadProps } from "./FileUpload";