@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,91 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type TagSize = "sm" | "md" | "lg";
5
+
6
+ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
7
+ size?: TagSize;
8
+ children?: ReactNode;
9
+ /** Leading visual — dot / country flag / avatar (ReactNode slot). */
10
+ icon?: ReactNode;
11
+ /** Render a leading checkbox (bare bordered box, distinct from `Checkbox`). */
12
+ checkbox?: boolean;
13
+ checked?: boolean;
14
+ onCheckedChange?: (checked: boolean) => void;
15
+ /** Trailing count value (renders a divider + number). */
16
+ count?: ReactNode;
17
+ /** Trailing X-close button callback. */
18
+ onClose?: () => void;
19
+ }
20
+
21
+ /**
22
+ * Compact tag/chip. One component over the Figma matrix: `icon` (dot/country/
23
+ * avatar) slot, optional leading `checkbox`, trailing `count`, and an `onClose`
24
+ * X button. The checkbox/count/close sub-parts are inline (not separate exported
25
+ * components); `checkbox` is a bare bordered box, intentionally distinct from the
26
+ * full `Checkbox`/`Radio` controls.
27
+ */
28
+ export function Tag({
29
+ size = "md",
30
+ children,
31
+ icon,
32
+ checkbox = false,
33
+ checked = false,
34
+ onCheckedChange,
35
+ count,
36
+ onClose,
37
+ className,
38
+ ...rest
39
+ }: TagProps) {
40
+ const text = size === "sm" ? "text-xs" : "text-sm";
41
+ return (
42
+ <span
43
+ className={clsx(
44
+ "inline-flex items-center gap-[5px] rounded-sm border border-border-primary bg-bg-primary font-medium text-text-secondary",
45
+ size === "lg" ? "px-md py-xs" : "px-xs py-xxs",
46
+ text,
47
+ className,
48
+ )}
49
+ {...rest}
50
+ >
51
+ {checkbox && (
52
+ <button
53
+ type="button"
54
+ role="checkbox"
55
+ aria-checked={checked}
56
+ onClick={() => onCheckedChange?.(!checked)}
57
+ className={clsx(
58
+ "flex size-4 shrink-0 items-center justify-center rounded-xs border",
59
+ checked ? "border-transparent bg-bg-brand-solid" : "border-border-primary bg-bg-primary",
60
+ )}
61
+ >
62
+ {checked && (
63
+ <svg viewBox="0 0 16 16" fill="none" className="size-3 text-fg-white" aria-hidden>
64
+ <path d="M13.33 4 6 11.33 2.67 8" stroke="currentColor" strokeWidth="1.67" strokeLinecap="round" strokeLinejoin="round" />
65
+ </svg>
66
+ )}
67
+ </button>
68
+ )}
69
+ {icon && <span className="flex shrink-0 items-center">{icon}</span>}
70
+ <span className="whitespace-nowrap">{children}</span>
71
+ {count != null && (
72
+ <>
73
+ <span className="h-3 w-px bg-border-secondary" aria-hidden />
74
+ <span className="text-text-tertiary">{count}</span>
75
+ </>
76
+ )}
77
+ {onClose && (
78
+ <button
79
+ type="button"
80
+ onClick={onClose}
81
+ aria-label="Remove"
82
+ className="-mr-0.5 flex shrink-0 items-center justify-center rounded-[3px] p-xxs text-fg-quaternary hover:bg-bg-primary-hover hover:text-fg-secondary"
83
+ >
84
+ <svg viewBox="0 0 12 12" fill="none" className="size-3" aria-hidden>
85
+ <path d="M9 3 3 9M3 3l6 6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
86
+ </svg>
87
+ </button>
88
+ )}
89
+ </span>
90
+ );
91
+ }
@@ -0,0 +1,2 @@
1
+ export { Tag } from "./Tag";
2
+ export type { TagProps, TagSize } from "./Tag";
@@ -0,0 +1,90 @@
1
+ import type { InputHTMLAttributes, ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import { FieldWrapper, type InputFieldSize } from "../InputField/inputFieldShared";
4
+
5
+ export type TagsInputVariant = "inner" | "outer";
6
+
7
+ export interface TagsInputFieldProps
8
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
9
+ /** Current tags. */
10
+ tags?: string[];
11
+ /** Remove handler (receives the tag index). Renders a close button per chip. */
12
+ onRemoveTag?: (index: number) => void;
13
+ /** `inner` keeps chips inside the field; `outer` shows them below it. */
14
+ variant?: TagsInputVariant;
15
+ size?: InputFieldSize;
16
+ label?: ReactNode;
17
+ hint?: ReactNode;
18
+ required?: boolean;
19
+ destructive?: boolean;
20
+ }
21
+
22
+ function TagChip({ label, onRemove }: { label: string; onRemove?: () => void }) {
23
+ return (
24
+ <span className="flex shrink-0 items-center gap-[3px] rounded-sm border border-border-primary bg-bg-primary py-xxs pl-[9px] pr-xs text-sm font-medium text-text-secondary">
25
+ {label}
26
+ {onRemove ? (
27
+ <button type="button" onClick={onRemove} aria-label={`Remove ${label}`} className="rounded-[3px] p-xxs text-fg-quaternary hover:text-fg-quaternary-hover">
28
+ <svg viewBox="0 0 12 12" fill="none" className="size-3" aria-hidden>
29
+ <path d="M9 3 3 9M3 3l6 6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
30
+ </svg>
31
+ </button>
32
+ ) : null}
33
+ </span>
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Tag/chip input. `inner` renders the chips inside the field (wrapping with the
39
+ * text input); `outer` renders the field on top with the chips below it.
40
+ * Tag state is controlled by the consumer (`tags` + `onRemoveTag`).
41
+ */
42
+ export function TagsInputField({
43
+ tags = [],
44
+ onRemoveTag,
45
+ variant = "inner",
46
+ size = "md",
47
+ label,
48
+ hint,
49
+ required,
50
+ destructive,
51
+ className,
52
+ placeholder = "Add tag",
53
+ ...rest
54
+ }: TagsInputFieldProps) {
55
+ const chips = tags.map((t, i) => (
56
+ <TagChip key={i} label={t} onRemove={onRemoveTag ? () => onRemoveTag(i) : undefined} />
57
+ ));
58
+
59
+ const box = (inner: ReactNode) => (
60
+ <div
61
+ className={clsx(
62
+ "flex w-full flex-wrap items-center gap-md rounded-md border bg-bg-primary px-lg py-md shadow-xs",
63
+ "focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-bg-primary",
64
+ destructive
65
+ ? "border-border-error focus-within:ring-border-error"
66
+ : "border-border-primary focus-within:border-border-brand focus-within:ring-border-brand",
67
+ )}
68
+ >
69
+ {inner}
70
+ <input
71
+ placeholder={placeholder}
72
+ className="min-w-[80px] flex-1 bg-transparent text-md text-text-primary outline-none placeholder:text-text-placeholder"
73
+ {...rest}
74
+ />
75
+ </div>
76
+ );
77
+
78
+ return (
79
+ <FieldWrapper label={label} required={required} hint={hint} destructive={destructive} className={className}>
80
+ {variant === "inner" ? (
81
+ box(chips)
82
+ ) : (
83
+ <div className="flex w-full flex-col gap-md">
84
+ {box(null)}
85
+ {chips.length ? <div className="flex flex-wrap gap-sm">{chips}</div> : null}
86
+ </div>
87
+ )}
88
+ </FieldWrapper>
89
+ );
90
+ }
@@ -0,0 +1,2 @@
1
+ export { TagsInputField } from "./TagsInputField";
2
+ export type { TagsInputFieldProps, TagsInputVariant } from "./TagsInputField";
@@ -0,0 +1,33 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface TextEditorToolbarProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** Toolbar controls — typically `ButtonUtility` groups. */
6
+ children?: ReactNode;
7
+ }
8
+
9
+ /**
10
+ * Formatting-toolbar **chrome shell** for a rich-text editor (layout + tokens
11
+ * only, no editing logic). Horizontal bar; drop your formatting buttons in as
12
+ * `children` (use `TextEditorToolbarDivider` between groups). Pair with a real
13
+ * editor engine (TipTap/Quill) — the deferred `Text editor` row.
14
+ */
15
+ export function TextEditorToolbar({ children, className, ...rest }: TextEditorToolbarProps) {
16
+ return (
17
+ <div
18
+ className={clsx(
19
+ "flex flex-wrap items-center gap-xs rounded-lg border border-border-secondary bg-bg-primary p-xs shadow-xs",
20
+ className,
21
+ )}
22
+ role="toolbar"
23
+ {...rest}
24
+ >
25
+ {children}
26
+ </div>
27
+ );
28
+ }
29
+
30
+ /** Vertical divider between toolbar groups. */
31
+ export function TextEditorToolbarDivider({ className }: { className?: string }) {
32
+ return <span className={clsx("mx-xs h-5 w-px shrink-0 bg-border-secondary", className)} aria-hidden />;
33
+ }
@@ -0,0 +1,2 @@
1
+ export { TextEditorToolbar, TextEditorToolbarDivider } from "./TextEditorToolbar";
2
+ export type { TextEditorToolbarProps } from "./TextEditorToolbar";
@@ -0,0 +1,28 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface TextEditorTooltipProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** Inline formatting controls shown for the current selection. */
6
+ children?: ReactNode;
7
+ }
8
+
9
+ /**
10
+ * Floating selection-toolbar **chrome shell** for a rich-text editor (layout +
11
+ * tokens only, no editing logic). A small elevated card meant to be positioned
12
+ * over a text selection; drop inline-format buttons in as `children`. Pair with a
13
+ * real editor engine — the deferred `Text editor` row.
14
+ */
15
+ export function TextEditorTooltip({ children, className, ...rest }: TextEditorTooltipProps) {
16
+ return (
17
+ <div
18
+ className={clsx(
19
+ "inline-flex items-center gap-xxs rounded-lg border border-border-secondary-alt bg-bg-primary p-xxs shadow-lg",
20
+ className,
21
+ )}
22
+ role="toolbar"
23
+ {...rest}
24
+ >
25
+ {children}
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,2 @@
1
+ export { TextEditorTooltip } from "./TextEditorTooltip";
2
+ export type { TextEditorTooltipProps } from "./TextEditorTooltip";
@@ -0,0 +1,45 @@
1
+ import type { TextareaHTMLAttributes, ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import {
4
+ FieldWrapper,
5
+ boxClasses,
6
+ inputSizeClasses,
7
+ type InputFieldSize,
8
+ } from "../InputField/inputFieldShared";
9
+
10
+ export interface TextareaInputFieldProps
11
+ extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "size"> {
12
+ size?: InputFieldSize;
13
+ label?: ReactNode;
14
+ hint?: ReactNode;
15
+ required?: boolean;
16
+ destructive?: boolean;
17
+ }
18
+
19
+ /**
20
+ * Multiline text input. Reuses the Input field family's shared `FieldWrapper`
21
+ * (label/required/hint/destructive) and `boxClasses`/`inputSizeClasses` — the
22
+ * wrapper is NOT reimplemented. `rows` controls height (default 4).
23
+ */
24
+ export function TextareaInputField({
25
+ size = "md",
26
+ label,
27
+ hint,
28
+ required,
29
+ destructive,
30
+ rows = 4,
31
+ className,
32
+ ...rest
33
+ }: TextareaInputFieldProps) {
34
+ return (
35
+ <FieldWrapper label={label} required={required} hint={hint} destructive={destructive} className={className}>
36
+ <div className={clsx(boxClasses(destructive), "items-stretch", inputSizeClasses[size])}>
37
+ <textarea
38
+ rows={rows}
39
+ className="min-w-0 flex-1 resize-y bg-transparent text-text-primary outline-none placeholder:text-text-placeholder"
40
+ {...rest}
41
+ />
42
+ </div>
43
+ </FieldWrapper>
44
+ );
45
+ }
@@ -0,0 +1,2 @@
1
+ export { TextareaInputField } from "./TextareaInputField";
2
+ export type { TextareaInputFieldProps } from "./TextareaInputField";
@@ -0,0 +1,87 @@
1
+ import { type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type ToggleType = "default" | "slim";
5
+ export type ToggleSize = "sm" | "md";
6
+
7
+ export interface ToggleProps {
8
+ type?: ToggleType;
9
+ size?: ToggleSize;
10
+ checked?: boolean;
11
+ onCheckedChange?: (checked: boolean) => void;
12
+ disabled?: boolean;
13
+ label?: ReactNode;
14
+ supportingText?: ReactNode;
15
+ className?: string;
16
+ id?: string;
17
+ "aria-label"?: string;
18
+ }
19
+
20
+ const TRACK: Record<ToggleSize, string> = { sm: "h-5 w-9", md: "h-6 w-11" };
21
+ const KNOB: Record<ToggleSize, string> = { sm: "size-4", md: "size-5" };
22
+ const TRAVEL: Record<ToggleSize, string> = { sm: "translate-x-4", md: "translate-x-5" };
23
+
24
+ /**
25
+ * Switch toggle. `default` = filled track (`bg-brand-solid` when on); `slim` = a
26
+ * thinner track with a bordered knob (uses the `toggle-slim-border-pressed`
27
+ * tokens when on). The `_Toggle base` control is inline (not a separate export).
28
+ * Controlled via `checked`/`onCheckedChange`; optional `label`/`supportingText`.
29
+ */
30
+ export function Toggle({
31
+ type = "default",
32
+ size = "sm",
33
+ checked = false,
34
+ onCheckedChange,
35
+ disabled = false,
36
+ label,
37
+ supportingText,
38
+ className,
39
+ id,
40
+ "aria-label": ariaLabel,
41
+ }: ToggleProps) {
42
+ const slim = type === "slim";
43
+
44
+ const control = (
45
+ <button
46
+ type="button"
47
+ role="switch"
48
+ id={id}
49
+ aria-checked={checked}
50
+ aria-label={ariaLabel}
51
+ disabled={disabled}
52
+ onClick={() => onCheckedChange?.(!checked)}
53
+ className={clsx(
54
+ "relative inline-flex shrink-0 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-utility-brand-500 focus-visible:ring-offset-2",
55
+ slim ? "h-2 w-9 border" : TRACK[size],
56
+ slim
57
+ ? checked
58
+ ? "border-toggle-slim-border-pressed bg-bg-brand-solid hover:border-toggle-slim-border-pressed-hover"
59
+ : "border-transparent bg-bg-quaternary"
60
+ : checked
61
+ ? "bg-bg-brand-solid hover:bg-bg-brand-solid-hover"
62
+ : "bg-bg-quaternary",
63
+ disabled && "cursor-not-allowed opacity-60",
64
+ )}
65
+ >
66
+ <span
67
+ className={clsx(
68
+ "pointer-events-none inline-block rounded-full bg-fg-white shadow-sm transition-transform",
69
+ slim ? "size-4 border border-border-primary" : KNOB[size],
70
+ checked ? (slim ? "translate-x-5" : TRAVEL[size]) : slim ? "-translate-x-px" : "translate-x-0.5",
71
+ )}
72
+ />
73
+ </button>
74
+ );
75
+
76
+ if (!label && !supportingText) return <span className={className}>{control}</span>;
77
+
78
+ return (
79
+ <div className={clsx("flex items-start gap-md", className)}>
80
+ {control}
81
+ <label htmlFor={id} className="flex flex-col">
82
+ {label && <span className="text-sm font-medium text-text-secondary">{label}</span>}
83
+ {supportingText && <span className="text-sm text-text-tertiary">{supportingText}</span>}
84
+ </label>
85
+ </div>
86
+ );
87
+ }
@@ -0,0 +1,2 @@
1
+ export { Toggle } from "./Toggle";
2
+ export type { ToggleProps, ToggleType, ToggleSize } from "./Toggle";
@@ -0,0 +1,59 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type TooltipArrow =
5
+ | "none"
6
+ | "topCenter"
7
+ | "bottomCenter"
8
+ | "bottomLeft"
9
+ | "bottomRight"
10
+ | "left"
11
+ | "right";
12
+
13
+ export interface TooltipProps extends HTMLAttributes<HTMLDivElement> {
14
+ /** Tooltip heading text. */
15
+ text?: ReactNode;
16
+ children?: ReactNode;
17
+ /** Secondary line below the heading. */
18
+ supportingText?: ReactNode;
19
+ /** Arrow position relative to the bubble. */
20
+ arrow?: TooltipArrow;
21
+ }
22
+
23
+ const ARROW_POS: Record<Exclude<TooltipArrow, "none">, string> = {
24
+ topCenter: "left-1/2 top-0 -translate-x-1/2 -translate-y-1/2",
25
+ bottomCenter: "left-1/2 bottom-0 -translate-x-1/2 translate-y-1/2",
26
+ bottomLeft: "left-3 bottom-0 translate-y-1/2",
27
+ bottomRight: "right-3 bottom-0 translate-y-1/2",
28
+ left: "left-0 top-1/2 -translate-x-1/2 -translate-y-1/2",
29
+ right: "right-0 top-1/2 translate-x-1/2 -translate-y-1/2",
30
+ };
31
+
32
+ /**
33
+ * Presentational tooltip bubble (dark `bg-primary-solid`, white text). `text` is
34
+ * the heading; `supportingText` adds a second `utility-neutral-300` line (max
35
+ * 296px). `arrow` positions a small pointer on the bubble edge (rendered as a
36
+ * rotated square). Positioning relative to a trigger is the caller's job.
37
+ */
38
+ export function Tooltip({ text, children, supportingText, arrow = "none", className, ...rest }: TooltipProps) {
39
+ const hasSupporting = supportingText != null;
40
+ return (
41
+ <div
42
+ role="tooltip"
43
+ className={clsx(
44
+ "relative inline-flex flex-col rounded-md bg-bg-primary-solid shadow-lg",
45
+ hasSupporting ? "max-w-[320px] gap-xxs p-lg" : "px-lg py-md",
46
+ className,
47
+ )}
48
+ {...rest}
49
+ >
50
+ <span className="text-xs font-semibold text-text-white">{text ?? children}</span>
51
+ {hasSupporting && (
52
+ <span className="max-w-[296px] text-xs font-medium text-utility-neutral-300">{supportingText}</span>
53
+ )}
54
+ {arrow !== "none" && (
55
+ <span className={clsx("absolute size-2 rotate-45 bg-bg-primary-solid", ARROW_POS[arrow])} aria-hidden />
56
+ )}
57
+ </div>
58
+ );
59
+ }
@@ -0,0 +1,2 @@
1
+ export { Tooltip } from "./Tooltip";
2
+ export type { TooltipProps, TooltipArrow } from "./Tooltip";
@@ -0,0 +1,62 @@
1
+ import type { InputHTMLAttributes, ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import { FieldWrapper, type InputFieldSize } from "../InputField/inputFieldShared";
4
+
5
+ export interface TrailingInputFieldProps
6
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
7
+ /**
8
+ * Right add-on — a trailing button or dropdown. Covers the Trailing button /
9
+ * Trailing dropdown types.
10
+ */
11
+ suffix?: ReactNode;
12
+ size?: InputFieldSize;
13
+ label?: ReactNode;
14
+ hint?: ReactNode;
15
+ required?: boolean;
16
+ destructive?: boolean;
17
+ }
18
+
19
+ const pad: Record<InputFieldSize, string> = {
20
+ sm: "px-lg py-md text-sm",
21
+ md: "px-lg py-md text-md",
22
+ lg: "px-[14px] py-2.5 text-md",
23
+ };
24
+
25
+ /** Input with a right add-on (trailing button or dropdown). */
26
+ export function TrailingInputField({
27
+ suffix,
28
+ size = "md",
29
+ label,
30
+ hint,
31
+ required,
32
+ destructive,
33
+ className,
34
+ ...rest
35
+ }: TrailingInputFieldProps) {
36
+ return (
37
+ <FieldWrapper label={label} required={required} hint={hint} destructive={destructive} className={className}>
38
+ <div
39
+ className={clsx(
40
+ "flex w-full items-stretch overflow-hidden rounded-md border bg-bg-primary shadow-xs",
41
+ "focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-bg-primary",
42
+ destructive
43
+ ? "border-border-error focus-within:ring-border-error"
44
+ : "border-border-primary focus-within:border-border-brand focus-within:ring-border-brand",
45
+ )}
46
+ >
47
+ <input
48
+ className={clsx(
49
+ "min-w-0 flex-1 bg-transparent text-text-primary outline-none placeholder:text-text-placeholder",
50
+ pad[size],
51
+ )}
52
+ {...rest}
53
+ />
54
+ {suffix ? (
55
+ <span className="flex shrink-0 items-center border-l border-border-primary">
56
+ {suffix}
57
+ </span>
58
+ ) : null}
59
+ </div>
60
+ </FieldWrapper>
61
+ );
62
+ }
@@ -0,0 +1,2 @@
1
+ export { TrailingInputField } from "./TrailingInputField";
2
+ export type { TrailingInputFieldProps } from "./TrailingInputField";
@@ -0,0 +1,86 @@
1
+ import { useState, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import { TreeViewItem, type TreeViewItemSize } from "../TreeViewItem";
4
+
5
+ export interface TreeNode {
6
+ id: string;
7
+ label: ReactNode;
8
+ icon?: ReactNode;
9
+ children?: TreeNode[];
10
+ }
11
+
12
+ export interface TreeViewProps {
13
+ data: TreeNode[];
14
+ size?: TreeViewItemSize;
15
+ /** Currently selected node id (controlled). */
16
+ selectedId?: string;
17
+ onSelect?: (id: string) => void;
18
+ /** Node ids expanded by default (uncontrolled expand state). */
19
+ defaultExpandedIds?: string[];
20
+ /** Show a checkbox on every row. */
21
+ checkboxes?: boolean;
22
+ /** Max nesting depth rendered — guards against runaway/cyclic data. */
23
+ maxDepth?: number;
24
+ className?: string;
25
+ "aria-label"?: string;
26
+ }
27
+
28
+ /**
29
+ * Tree view composite — renders nested `TreeNode` data recursively as
30
+ * `TreeViewItem`s (which compose `TreeViewConnector` for indent guides). Expand
31
+ * state is internal (seeded by `defaultExpandedIds`); selection is controlled via
32
+ * `selectedId`/`onSelect`.
33
+ */
34
+ export function TreeView({
35
+ data,
36
+ size = "sm",
37
+ selectedId,
38
+ onSelect,
39
+ defaultExpandedIds = [],
40
+ checkboxes = false,
41
+ maxDepth = 10,
42
+ className,
43
+ "aria-label": ariaLabel,
44
+ }: TreeViewProps) {
45
+ const [expanded, setExpanded] = useState<Set<string>>(new Set(defaultExpandedIds));
46
+ const toggle = (id: string) =>
47
+ setExpanded((prev) => {
48
+ const next = new Set(prev);
49
+ next.has(id) ? next.delete(id) : next.add(id);
50
+ return next;
51
+ });
52
+
53
+ const renderNodes = (nodes: TreeNode[], level: number): ReactNode => {
54
+ if (level >= maxDepth) return null;
55
+ return nodes.map((node) => {
56
+ const hasChildren = !!node.children?.length;
57
+ const isOpen = expanded.has(node.id);
58
+ return (
59
+ <li key={node.id} role="treeitem" aria-expanded={hasChildren ? isOpen : undefined} aria-selected={node.id === selectedId}>
60
+ <TreeViewItem
61
+ size={size}
62
+ level={level}
63
+ icon={node.icon}
64
+ expandable={hasChildren}
65
+ open={isOpen}
66
+ selected={node.id === selectedId}
67
+ checkbox={checkboxes}
68
+ onToggle={() => toggle(node.id)}
69
+ onClick={() => onSelect?.(node.id)}
70
+ >
71
+ {node.label}
72
+ </TreeViewItem>
73
+ {hasChildren && isOpen && (
74
+ <ul role="group">{renderNodes(node.children!, level + 1)}</ul>
75
+ )}
76
+ </li>
77
+ );
78
+ });
79
+ };
80
+
81
+ return (
82
+ <ul role="tree" aria-label={ariaLabel} className={clsx("flex flex-col", className)}>
83
+ {renderNodes(data, 0)}
84
+ </ul>
85
+ );
86
+ }
@@ -0,0 +1,2 @@
1
+ export { TreeView } from "./TreeView";
2
+ export type { TreeViewProps, TreeNode } from "./TreeView";
@@ -0,0 +1,36 @@
1
+ import { type HTMLAttributes } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type TreeViewConnectorType = "default" | "endConnector" | "none";
5
+ export type TreeViewConnectorSize = "sm" | "md";
6
+
7
+ export interface TreeViewConnectorProps extends HTMLAttributes<HTMLSpanElement> {
8
+ type?: TreeViewConnectorType;
9
+ size?: TreeViewConnectorSize;
10
+ }
11
+
12
+ /**
13
+ * Indent guide for `TreeViewItem`/`TreeView`. `default` = a full-height vertical
14
+ * line (a passing-through branch); `endConnector` = an L-shape (vertical down to
15
+ * centre, then a stub to the right) for the last child; `none` = empty spacer.
16
+ * Drawn with borders rather than the Figma image asset.
17
+ */
18
+ export function TreeViewConnector({ type = "default", size = "sm", className, ...rest }: TreeViewConnectorProps) {
19
+ return (
20
+ <span
21
+ className={clsx("relative inline-block shrink-0", size === "md" ? "size-5" : "size-4", className)}
22
+ aria-hidden
23
+ {...rest}
24
+ >
25
+ {type === "default" && (
26
+ <span className="absolute left-1/2 top-0 bottom-0 w-px -translate-x-1/2 bg-border-secondary" />
27
+ )}
28
+ {type === "endConnector" && (
29
+ <>
30
+ <span className="absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-border-secondary" />
31
+ <span className="absolute left-1/2 top-1/2 right-0 h-px bg-border-secondary" />
32
+ </>
33
+ )}
34
+ </span>
35
+ );
36
+ }
@@ -0,0 +1,2 @@
1
+ export { TreeViewConnector } from "./TreeViewConnector";
2
+ export type { TreeViewConnectorProps, TreeViewConnectorType, TreeViewConnectorSize } from "./TreeViewConnector";